미니PC 홈서버 nginx 장애 복구기

최규민
Claude

최규민, Claude

2026년 3월 26일2 분 소요

미니PC 홈서버 nginx 장애 복구기

증상


2026년 3월 25일부터 gyuminlab.co.kr 서버의 웹 서비스가 전부 먹통이 됐다. HTTP(80), HTTPS(443) 모두 접속 불가. SSH도 안 됨. 단, Cockpit(9090)만 접속 가능한 상태.

진단 과정


1. 외부에서 접근 확인

bash
ping gyuminlab.co.kr        # 100% 패킷 손실
curl -sI http://gyuminlab.co.kr   # 연결 실패
nc -z gyuminlab.co.kr 80    # 실패
nc -z gyuminlab.co.kr 443   # 실패
nc -z gyuminlab.co.kr 9090  # 성공

DNS는 정상, 9090만 살아있었다. 서버 자체는 살아있는데 특정 포트만 안 되는 상황.

2. Cockpit Terminal에서 서버 내부 확인

bash
sudo ss -tlnp | grep -E ':80|:443'
# (결과 없음 - nginx가 리슨하고 있지 않음)

sudo systemctl status nginx
# inactive (dead) - 실행 중이 아님

nginx가 아예 안 돌아가고 있었다.

3. nginx 시작 시도 → 실패

bash
sudo systemctl start nginx
# Job for nginx.service failed because the control process exited with error code.

4. 에러 로그 확인

bash
sudo journalctl -xeu nginx.service --no-pager -n 30

핵심 에러 메시지:

plain text
[emerg] could not build map_hash, you should increase map_hash_bucket_size: 64
nginx: configuration file /etc/nginx/nginx.conf test failed

map_hash_bucket_size 기본값(64)이 설정에 있는 map 블록을 처리하기에 부족해서 시작 실패한 것이었다.

원인 분석


3월 18일까지는 정상 동작했는데, 왜 갑자기?

확인한 것들:

가설결과
nginx 패키지 업데이트?dpkg.log에 기록 없음
서버 재부팅?last reboot — 마지막 재부팅 2월 25일
certbot 갱신?06:30 시점 실행 기록 없음
설정 파일 변경?직접 수정한 적 없음

진짜 원인: apt-daily-upgrade → systemd 재실행


journalctl로 3월 25일 06:29~06:31 구간을 확인한 결과:

plain text
06:29:46  unattended-upgrade 실행 시작
06:29:51  apt-daily-upgrade가 systemd Reexecuting 요청
06:30:01  systemd가 주요 서비스 전부 stop → start
          nginx, ssh, fail2ban, multipathd, rsyslog, thermald ...
06:30:01  nginx start 실패 (map_hash_bucket_size 에러)

Ubuntu 자동 패키지 업그레이드(unattended-upgrades)가 systemd 패키지를 업데이트하면서, systemd가 자기 자신을 재실행했다. 이 과정에서 모든 서비스가 재시작되었고, nginx만 설정 문제로 올라오지 못한 것이다.

map_hash_bucket_size가 원래부터 빠듯했지만, 이전에는 기존 프로세스가 계속 떠있어서 문제가 없었다. 깨끗한 재시작에서 비로소 터진 케이스.

해결


/etc/nginx/nginx.confhttp 블록에 한 줄 추가:

plain text
http {
    map_hash_bucket_size 128;
    ...
}
bash
sudo nginx -t && sudo systemctl start nginx
# nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
# nginx: configuration file /etc/nginx/nginx.conf test is successful

정상 복구 완료.

💡

배경 지식: Ubuntu unattended-upgrades란?

Ubuntu는 설치 시 unattended-upgrades가 기본으로 활성화되어 있다. 사용자가 별도로 설정하지 않아도 매일 자동으로 보안 패치를 설치한다.

관련 설정 파일

/etc/apt/apt.conf.d/20auto-upgrades — 자동 업그레이드 on/off:

plain text
APT::Periodic::Update-Package-Lists "1";      # 매일 패키지 목록 갱신
APT::Periodic::Unattended-Upgrade "1";         # 매일 자동 업그레이드 실행

/etc/apt/apt.conf.d/50unattended-upgrades — 어떤 패키지를 업그레이드할지:

plain text
Unattended-Upgrade::Allowed-Origins {
    "${distro_id}:${distro_codename}";
    "${distro_id}:${distro_codename}-security";   // 보안 업데이트 (기본 대상)
    "${distro_id}ESMApps:${distro_codename}-apps-security";
    "${distro_id}ESM:${distro_codename}-infra-security";
};

기본적으로 보안 업데이트(security)만 자동 적용된다. 이번 사고의 경우 systemd 보안 패치s가 배포되어 자동 적용되었고, systemd가 자기 자신을 재실행하면서 모든 서비스가 재시작된 것이다.

이런 사고를 방지하려면

방법 1: 자동 업그레이드 자체를 끄기

bash
sudo dpkg-reconfigure unattended-upgrades
# "No" 선택

단, 보안 업데이트를 수동으로 관리해야 하므로 권장하지 않는다.

방법 2: 자동 업그레이드는 유지하되, 자동 재시작 방지

/etc/apt/apt.conf.d/50unattended-upgrades에서:

plain text
// 재시작이 필요한 경우 자동 재시작하지 않음
Unattended-Upgrade::Automatic-Reboot "false";

다만 이번 케이스는 서버 재부팅이 아니라 systemd 자체 재실행이므로, 이 옵션으로는 완전히 방지되지 않을 수 있다.

방법 3: 특정 패키지를 자동 업그레이드에서 제외

plain text
Unattended-Upgrade::Package-Blacklist {
    "systemd";
};

systemd처럼 재시작 시 영향 범위가 큰 패키지를 제외하는 방법이다.

방법 4 (권장): 서비스 상태 모니터링 추가

자동 업그레이드 자체는 유지하되, 업그레이드 후 핵심 서비스가 살아있는지 확인하는 스크립트를 추가한다:

bash
# /etc/apt/apt.conf.d/99post-upgrade-check
Dpkg::Post-Invoke {
    "systemctl is-active nginx || systemctl start nginx || true";
};

또는 systemd의 OnFailure= 디렉티브를 활용해 nginx가 죽으면 알림을 보내는 방법도 있다.

교훈


  • Cockpit 같은 별도 관리 포트가 있으면 서버 접근 불가 시에도 원격 진단이 가능하다. 물리 접근 없이 해결할 수 있었던 핵심.
  • unattended-upgrades는 편리하지만, systemd 업데이트 시 모든 서비스를 재시작시킬 수 있다. 프로덕션 서버라면 자동 업그레이드 대상에서 핵심 패키지를 제외하거나, 재시작 후 서비스 상태를 모니터링하는 것이 좋다.
  • nginx 설정은 nginx -t가 통과하더라도, map_hash_bucket_size 같은 런타임 제약은 데이터 양에 따라 나중에 터질 수 있다. 여유 있는 값을 미리 설정해두자.
  • Ubuntu 서버를 운영한다면 unattended-upgrades 설정을 반드시 확인하자. 기본값을 그대로 쓰면 언제든 이런 일이 다시 일어날 수 있다.

최규민

최규민

AI Engineer

사파(邪派)식 AI-Native LLM SWE

Claude

Claude

AI Agent

Claude for blog post automation