미니PC 홈서버 nginx 장애 복구기
최규민, Claude
2026년 3월 26일2 분 소요
증상
2026년 3월 25일부터 gyuminlab.co.kr 서버의 웹 서비스가 전부 먹통이 됐다. HTTP(80), HTTPS(443) 모두 접속 불가. SSH도 안 됨. 단, Cockpit(9090)만 접속 가능한 상태.
진단 과정
1. 외부에서 접근 확인
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에서 서버 내부 확인
sudo ss -tlnp | grep -E ':80|:443'
# (결과 없음 - nginx가 리슨하고 있지 않음)
sudo systemctl status nginx
# inactive (dead) - 실행 중이 아님nginx가 아예 안 돌아가고 있었다.
3. nginx 시작 시도 → 실패
sudo systemctl start nginx
# Job for nginx.service failed because the control process exited with error code.4. 에러 로그 확인
sudo journalctl -xeu nginx.service --no-pager -n 30핵심 에러 메시지:
[emerg] could not build map_hash, you should increase map_hash_bucket_size: 64
nginx: configuration file /etc/nginx/nginx.conf test failedmap_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 구간을 확인한 결과:
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.conf의 http 블록에 한 줄 추가:
http {
map_hash_bucket_size 128;
...
}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:
APT::Periodic::Update-Package-Lists "1"; # 매일 패키지 목록 갱신
APT::Periodic::Unattended-Upgrade "1"; # 매일 자동 업그레이드 실행/etc/apt/apt.conf.d/50unattended-upgrades — 어떤 패키지를 업그레이드할지:
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: 자동 업그레이드 자체를 끄기
sudo dpkg-reconfigure unattended-upgrades
# "No" 선택단, 보안 업데이트를 수동으로 관리해야 하므로 권장하지 않는다.
방법 2: 자동 업그레이드는 유지하되, 자동 재시작 방지
/etc/apt/apt.conf.d/50unattended-upgrades에서:
// 재시작이 필요한 경우 자동 재시작하지 않음
Unattended-Upgrade::Automatic-Reboot "false";다만 이번 케이스는 서버 재부팅이 아니라 systemd 자체 재실행이므로, 이 옵션으로는 완전히 방지되지 않을 수 있다.
방법 3: 특정 패키지를 자동 업그레이드에서 제외
Unattended-Upgrade::Package-Blacklist {
"systemd";
};systemd처럼 재시작 시 영향 범위가 큰 패키지를 제외하는 방법이다.
방법 4 (권장): 서비스 상태 모니터링 추가
자동 업그레이드 자체는 유지하되, 업그레이드 후 핵심 서비스가 살아있는지 확인하는 스크립트를 추가한다:
# /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설정을 반드시 확인하자. 기본값을 그대로 쓰면 언제든 이런 일이 다시 일어날 수 있다.