🔑 핵심 요약
✦ AI·GEN리눅스 서버에 UPS와 NUT을 도입하는 과정을 그대로 따라 할 수 있는 형태로 정리한 글. UPS 선정의 세 조건(PFC 정현파, AVR, NUT 지원), NUT의 driver / upsd / upsmon 세 층 구조와 다섯 개 설정 파일의 역할, upsmon.conf의 줄별 설명, POWERDOWNFLAG를 빼먹으면 안 되는 이유, 그리고 틀리면 전부가 헛수고가 되는 BIOS 항목 —— Restore after AC Power Loss는 Last State가 아니라 On이어야 한다, NUT의 깨끗한 종료 이후 머신의 상태는 "꺼짐"이기 때문이다. UPS 상태를 cron 로그, Discord 알림, 자체 대시보드로 빼는 방법도 함께 실었다. 모든 발단은 이사 후 서버가 매일 밤 강제로 꺼지기 시작한 것. 케이블 헐거움, 공용 회로, 과열, PSU를 전부 의심했지만 그것들은 전부 그냥 추측이었다. 저자가 UPS를 산 것은 절반은 보호를 위해, 나머지 절반은 계측기로 쓰기 위해서였고, 결국 그 로그가 문제는 UPS의 하류에 있다는 것을 증명했다. 범인은 고양이가 갉아 먹은 전원 케이블이었다.
이사한 다음 주부터, 서버가 매일 밤 혼자 꺼지기 시작했습니다.
크래시도 재부팅도 아니고 전원이 끊기는 형태의 죽음입니다. 켜면 반드시 ext4 recovery가 돌고, uptime은 0으로 돌아가고, 직전까지 돌던 것들은 아무 유언도 남기지 않았습니다. 게다가 시간대를 고릅니다. 거의 새벽이었습니다.
처음 의심한 건 케이블 헐거움이라 전부 다시 꽂았습니다. 다음 날 또 죽었습니다. 이사 후 에어컨과 온수기가 같은 회로에 물려 있을 가능성을 생각해 꺼 봤습니다. 또 죽었습니다. 온도를 재니 50에서 60°C, 완전히 정상. 마지막에는 이사의 진동으로 PSU가 상한 게 아닐까 의심하기 시작했습니다. 산 지 일 년도 안 된 Super Flower 플래티넘이라 별로 믿고 싶지 않은 얘기였습니다.
문제는 이게 전부 추측이라는 점입니다. 게다가 하나 검증하는 데 꼬박 하루가 걸립니다. 며칠을 쫓고 나서야 부족한 건 가설이 아니라 증거라는 걸 깨달았습니다. 죽은 그 순간 머신에 들어가던 전기가 어떤 상태였는지를 저는 아무것도 모르고 있었습니다.
그래서 UPS를 샀습니다. 절반은 보호를 위해, 나머지 절반은 계측기로 쓰기 위해서였습니다.
이 글은 그 이후의 전 과정입니다. UPS 고르는 법, NUT을 처음부터 자동 안전 종료까지 설정하는 순서, 절대 틀리면 안 되는 BIOS 항목, 그리고 마지막에 UPS 로그가 사건을 해결하기까지. 범인은 고양이가 갉아 먹은 전원 케이블이었습니다.
왜 UPS로 결판이 나는가#
왜 그게 계측기가 되는지를 먼저 분명히 해 둡니다. 아래 모든 논리가 거기에 얹혀 있기 때문입니다.
UPS가 재는 것은 자기 자신의 출력 쪽 상태이고, 지금 무엇을 하고 있는지를 짧은 코드로 보고합니다. 이 글에 계속 나오니 먼저 정리해 둡니다.
| 상태 | 의미 |
|---|---|
OL | On Line. 상용 전원 정상, UPS는 옆에서 대기 중일 뿐 |
OB | On Battery. 상용 전원이 끊겨 배터리 방전 중 |
LB | Low Battery. 잔량이 얼마 없어 종료해야 하는 상태 |
이 셋이 있으면, 계속 기록을 남기는 UPS는 다음번 죽음을 두 가지로 깔끔하게 갈라 줍니다.
- 죽은 순간에
OB또는 전압 강하를 기록했다 → 문제는 UPS의 상류, 상용 전원 쪽입니다. - 죽은 순간까지
OL그대로, 전압도 안정, 배터리도 만충 → UPS가 내보낸 전기는 깨끗하니 문제는 하류. 즉 전원 케이블, PSU, 메인보드 구간입니다.
이 경계선 하나로 탐색 범위가 절반이 되고, 게다가 추측에 기대지 않아도 됩니다.
선정: 1500VA / 정현파 / AVR 탑재#
짜리 CyberPower CP1500PFCLCD에는 이번 진단에 의미 있는 지점이 셋 있었습니다.
요즘 PC용 파워는 거의 전부 액티브 PFC입니다. 이런 파워는 저가 UPS가 내보내는 와 궁합이 나빠서, 배터리로 전환되는 순간 그대로 꺼지는 일이 있습니다. 그건 지금 쫓고 있는 증상과 똑같은 새 문제를 스스로 만드는 것이고, 진단 중에 가장 필요 없는 일입니다.
은 가설 하나를 통째로 지워 줍니다. 새벽에 정말로 전압 변동이 일어나고 있다면 그 자리에서 평탄하게 만들어 줍니다. 평탄하게 만든 뒤에도 여전히 죽는다면 상용 전원이라는 선은 지울 수 있습니다.
리눅스 쪽은 이 usbhid-ups 드라이버로 읽을 수 있으니 제조사 전용 소프트웨어가 필요 없습니다. USB를 꽂으면 lsusb에 이렇게 나옵니다.
Bus 001 Device 005: ID 0764:0601 Cyber Power System, Inc.NOTE
랜 케이블은 꽂지 않아도 됩니다 이 UPS는 USB와 시리얼을 둘 다 갖고 있지만 NUT은 USB만으로 충분합니다. 네트워크 쪽은 관리 카드가 달린 기종이나 여러 대가 공유하는 구성을 위한 것으로, 단일 머신 모니터링에서는 쓸 일이 없습니다.
NUT: 처음부터 자동 안전 종료까지#
NUT의 설정 파일은 여러 곳에 흩어져 있고, 권한이 맞지 않으면 서비스가 아예 뜨지 않습니다. 전부를 스크립트 하나로 묶어 두어서 재설치나 머신 교체 때는 그걸 돌리기만 하면 되게 해 뒀습니다.
먼저 NUT의 세 층을 이해하기#
설정 파일이 뒤죽박죽처럼 보이는 건 NUT이 프로그램 하나가 아니라 역할이 다른 셋이기 때문입니다. 누가 무엇인지 파악하면 설정 파일은 알아서 제자리를 찾습니다.
- driver(제 것은
usbhid-ups) —— 실제로 UPS와 대화하는 쪽으로, 제조사 프로토콜을 NUT의 데이터 모델로 번역합니다. - upsd —— driver가 가져온 데이터를 서비스로 공개해 다른 곳에서 물어볼 수 있게 합니다.
- upsmon —— 클라이언트 쪽. 계속
upsd에 데이터를 요구하다가 잔량이 낮아지면 종료를 실행합니다.
그렇게 보면 다섯 개의 설정 파일은 이렇게 나뉩니다.
/etc/nut/nut.conf # 이 머신의 역할(단독인가, 클라이언트/서버인가)
/etc/nut/ups.conf # driver: 어떤 드라이버로 어떤 UPS에 붙는가
/etc/nut/upsd.conf # upsd: 데이터 서비스가 어느 주소에서 대기하는가
/etc/nut/upsd.users # upsd: 누가 읽고, 누가 명령을 내릴 수 있는가
/etc/nut/upsmon.conf # upsmon: 어떤 조건에서 끄고, 어떻게 알리는가단일 머신 모니터링이면 standalone을 씁니다.
# /etc/nut/nut.conf
MODE=standalone# /etc/nut/ups.conf
maxretry = 3
pollinterval = 5
[cyberpower]
driver = usbhid-ups
port = auto
desc = "CyberPower CP1500PFCLCD"# /etc/nut/upsd.conf —— localhost만, 외부로 열지 않음
LISTEN 127.0.0.1 3493WARNING
LISTEN 기본값은 바꿔야 합니다
NUT의 upsd가 0.0.0.0에서 대기하면 같은 LAN의 누구나 UPS 상태를 조회할 수 있고, 권한 설정이 허술하면 명령까지 내릴 수 있습니다. 단일 머신 모니터링에서 외부로 열 이유는 전혀 없으니 127.0.0.1에 묶습니다. 비밀번호는 openssl rand -hex 16으로 만들어 그대로 파일에 씁니다. 사람이 외울 필요가 없으니까요.
권한도 맞춰야 합니다. 아니면 driver가 자기 설정을 읽지 못합니다.
chown root:nut /etc/nut/*.conf /etc/nut/upsd.users
chmod 640 /etc/nut/*.conf /etc/nut/upsd.users안전한 종료는 어떻게 일어나는가#
핵심은 upsmon.conf의 이 몇 줄입니다.
MONITOR cyberpower@localhost 1 upsmon <password> primary
MINSUPPLIES 1
SHUTDOWNCMD "/sbin/shutdown -h +0"
POWERDOWNFLAG /etc/killpower
POLLFREQ 5
POLLFREQALERT 5
FINALDELAY 5한 줄씩 보면:
| 디렉티브 | 무엇을 하는가 |
|---|---|
MONITOR | 어느 UPS를 어떤 자격 증명으로 감시할지. 끝의 primary는 이 머신이 종료 시 UPS에 전원 차단을 지시할 권한을 갖는다는 뜻 |
MINSUPPLIES | 계속 돌기 위해 최소 몇 개의 전원이 살아 있어야 하는지. 단일 파워 머신이면 1 |
SHUTDOWNCMD | 종료할 때 무엇을 실행할지 |
POWERDOWNFLAG | 종료 절차가 남기는 플래그 파일. 아래에서 따로 설명 |
POLLFREQ / POLLFREQALERT | 평상시와 이상 시에 각각 몇 초마다 upsd에 물을지 |
FINALDELAY | 종료 명령을 내리기 전 마지막 유예 초 |
실제 흐름은 이렇고, 마지막 단이 가장 자주 빠지는 부분입니다.
POWERDOWNFLAG가 가리키는 것은 플래그 파일입니다. upsmon은 종료를 결정한 시점에 먼저 그것을 만들고, 시스템 종료 절차는 마지막에 그것을 확인합니다. 파일이 있으면 UPS에도 자기 출력을 끊으라고 지시하는 것입니다.
이걸 하지 않으면 머신은 꺼졌는데 UPS는 계속 방전해서 배터리가 0까지 쥐어짜입니다. 그리고 납축 배터리는 심방전 한 번마다 수명이 깎입니다.
그리고 BIOS 자동 부팅 단을 설정하지 않으면 그 앞의 전부가 헛수고가 됩니다. 머신은 깨끗하게 종료한 뒤 누군가 전원 버튼을 누르러 오기를 계속 기다리게 되니까요.
종료 임계값의 절충#
트리거가 되는 것은 UPS 자신이 저잔량이라고 판단하는 지점입니다. 제 기종의 공장 출하값은 이랬습니다.
battery.charge.low: 10 # 잔량 10%
battery.runtime.low: 300 # 또는 추정 잔여 300초일단 출하값 그대로 쓰는 건 의도적입니다. 오작동이 가장 적게 나는 값이기 때문입니다. 한동안 돌려서 실제 숫자가 나온 뒤에 더 일찍 넘길지 결정합니다. 지금의 실측은 이렇습니다.
부하 12%에 가동 시간 한 시간이면, 5분 남았을 때 종료를 시작하는 여유로 충분하고도 남습니다. 다만 UPS를 60%까지 쓰고 가동 시간이 십몇 분밖에 없다면 5분은 좀 아슬아슬하니, upssched로 더 이른 트리거(예를 들어 "배터리 운전이 90초 지속되면 끈다")를 더하게 됩니다.
BIOS: 틀리면 안 되는 한 항목#
자동 복구 흐름 전체에서 가장 쉽게 망칠 수 있는 자리입니다.
CAUTION
Restore after AC Power Loss는 On, Last State가 아닙니다
Last State는 "전원이 끊기기 전 상태로 돌아간다"는 뜻입니다. 그런데 NUT의 저잔량 종료 이후 그 상태는 전원 꺼짐입니다. 그래서 상용 전원이 돌아왔을 때 BIOS는 "원래 꺼져 있었으니까"라고 판단하고 꺼진 채로 둡니다. 자동 복구를 한 벌 다 만들어 놓고 마지막 한 단에서 멈추는 셈입니다.
On 쪽이 "전기가 들어오면 켠다"는 뜻이고, 직전 상태는 묻지 않습니다.
제 보드는 MSI MAG X870E TOMAHAWK이라 경로는 이렇습니다.
부팅 시 Del → F7로 Advanced Mode
→ SETTINGS → Advanced → Power Management Setup
→ Restore after AC Power Loss = OnBIOS는 OS보다 먼저이므로 SSH도 원격 데스크톱도 닿지 않습니다. 물리 모니터와 키보드가 필요합니다. Del을 연타하는 수고를 덜고 싶다면 먼저 이걸 쳐 두면 됩니다.
sudo systemctl reboot --firmware-setup바로 BIOS 설정 화면으로 재부팅합니다. 다만 사람은 화면 앞에 있어야 합니다.
UPS 상태를 밖으로 빼기#
설정이 끝나면 upsc로 언제든 볼 수 있지만, 매번 SSH로 들어가 명령을 치는 건 번거로웠습니다.
매분 로그 한 줄 남기기#
이 스크립트를 cron으로 매분 돌립니다. 사람이 읽는 로그 한 줄과 프로그램이 읽는 JSON을 동시에 씁니다.
DATA=$(upsc cyberpower 2>/dev/null) || exit 0
g() { grep -m1 "^$1:" <<<"$DATA" | cut -d' ' -f2-; }
echo "$(date '+%F %T') status=$(g ups.status) in=$(g input.voltage)V \
out=$(g output.voltage)V load=$(g ups.load)% batt=$(g battery.charge)% \
runtime=$(g battery.runtime)s" >> "$OUT"그 로그 줄은 이렇게 생겼고, 이것이 나중에 사건을 해결한 물건입니다.
2026-07-05 00:12:01 status=OL in=113.0V out=113.0V load=12% batt=100% runtime=3675s
2026-07-05 00:13:01 status=OL in=113.0V out=113.0V load=12% batt=100% runtime=3675s
2026-07-05 00:14:01 status=OL in=113.0V out=113.0V load=12% batt=100% runtime=3675s
↑ 이 직후에 머신이 강제로 끊김이벤트를 Discord로#
upsmon.conf는 이벤트 종류마다 외부 명령을 걸 수 있습니다. NOTIFYCMD를 한 줄 더하고, 알리고 싶은 이벤트의 플래그에 +EXEC를 붙이면 됩니다.
NOTIFYCMD /path/to/ups-discord-notify.sh
NOTIFYFLAG ONBATT SYSLOG+WALL+EXEC
NOTIFYFLAG LOWBATT SYSLOG+WALL+EXEC
NOTIFYFLAG ONLINE SYSLOG+WALL+EXEC알리고 있는 이벤트는 여섯 가지입니다. 배터리로 전환, 잔량 저하로 곧 종료, 종료 실행, 상용 전원 복귀, 배터리 노화로 교체 시기, UPS와의 통신 두절. 각각에 현재 잔량, 남은 분수, 부하, 상용 전원 전압을 붙였습니다.
Webhook 파일은 upsmon이 읽을 수 있는 곳에, 소유자 root:nut, 권한 640으로 둬야 합니다. 처음 할 때 막힌 지점이 여기였는데, 홈 디렉터리 아래에 뒀더니 upsmon이 읽지 못했습니다.
서브도메인을 하나 더 늘리고 싶지 않다#
Home Assistant의 NUT 통합이나 peaNUT 같은 패널을 세우는 것도 생각했습니다. 다만 제 서브도메인은 이미 꽤 많고, UPS 한 대를 보자고 사이트를 하나 더 세우는 건 과합니다.
그래서 직접 만든 NAS 대시보드에 넣기로 했습니다. 여기에 제약이 하나 있습니다. 백엔드는 docker의 bridge 네트워크에서 도는데, 호스트 쪽 upsd:3493에 닿지 않습니다. upsd를 외부에 노출할 바에는 호스트가 파일을 쓰고 컨테이너가 읽는 형태로 갑니다.
JSON은 앞의 그 스크립트가 겸사겸사 뱉는 것입니다.
{
"status": "OL",
"online": true,
"battery_charge": 100,
"battery_runtime": 3675,
"ups_load": 12,
"input_voltage": 113.0,
"model": "CP1500PFCLCDa TW",
"updated_at": "2026-08-04T13:55:01+0800"
}이 방식은 백엔드가 원래 다른 마운트된 파일을 읽던 구성과 맞아떨어지고, 읽기 전용 값 하나 때문에 네트워크 권한을 열지 않아도 됩니다.
NOTE
덤으로 발견한 것 중간에 휴대폰에서 모니터링 화면이 보이지 않는 걸 알아채고 PWA 문제라고 넘겨짚었습니다. 아니었습니다. 애초에 PWA가 존재하지 않습니다. manifest도 service worker도 없습니다. 휴대폰에 표시되는 건 완전히 별개의 모바일 레이아웃이고, 모니터링 페이지는 데스크톱 버전의 Dock에만 넣어 뒀던 것입니다. 즉 "PWA에 안 넣었다"가 아니라 "모바일에 처음부터 없었다"였습니다. 이 "A 문제인 줄 알았는데 B였다"는 패턴은 이 건에서 한 번뿐이 아니었습니다.
해결: 고양이가 갉아 먹은 케이블#
UPS를 들이고 며칠 뒤, 또 한 번 죽었습니다.
로그를 다시 보니 죽기 전후로 전 구간 OL, 상용 전원은 113에서 115V로 안정, 배터리 100%, OB 이벤트는 단 한 건도 없음. nut-monitor에도 아무것도 남아 있지 않습니다. 그런데도 부팅할 때는 또 ext4 recovery였습니다.
들어오는 전기는 깨끗한데 머신은 강제로 꺼졌다. 문제는 UPS의 하류로 확정입니다.
범위가 전원 케이블·PSU·메인보드까지 좁혀졌으니 케이스를 열어 모든 커넥터를 다시 꽂고, 겸사겸사 전원 케이블도 교체했습니다. 원래 것은 12A 125V 정격이었고, 거기에 고양이가 갉아 낸 구멍이 나 있었습니다.
그 케이블의 위치가 정확히 UPS 출력에서 PSU 입구까지로, UPS의 시야에서는 완전히 벗어나 있습니다. 구리선이 절반 끊긴 케이블은 간헐적으로 접촉합니다. 약간의 진동이나 열팽창·수축으로 통했다가 끊겼다가 다시 통합니다. 그게 바로 "무작위이고, 순간적이고, 전조가 없는" 전원 차단의 정체였습니다.
게다가 이걸로 그때까지 앞뒤가 맞지 않던 지점이 전부 설명됩니다.
| 현상 | 갉아 먹힌 케이블로 설명하면 |
|---|---|
| UPS 로그가 전 구간 깨끗 | 단선 지점이 UPS 측정점보다 하류라 애초에 보이지 않음 |
| 아이들에서도 죽음 | 부하와 무관한 기계적 접촉 불량이라서 |
| 이사 후부터 시작 | 운반 진동으로 절반 끊긴 구리선이 더 쉽게 분리됨 |
| 새벽을 고름 | 기온이 가장 낮아 열수축으로 접점이 줄어듦 |
새로 단 케이블은 10A 125V입니다. 정격이 내려간 것처럼 보이지만 10A × 125V는 1250W. 머신 풀로드가 대략 350에서 400W이니 환산하면 3A에도 못 미칩니다. 여유는 매우 큰 계산입니다.
"거의 매일 밤 죽음"에서 "열흘에 한 번 죽음"으로. 빈도가 십분의 일이 됐습니다.
하마터면 잘못 이끌릴 뻔한 재발#
케이블 교체로부터 열하루째, 또 죽었습니다. 게다가 제 게임용 PC도 재부팅되어 있었습니다.
두 대가 동시에 나갔다면 결론은 명백해 보입니다. 진짜로 정전이 된 것이라고. 거기서부터 추론이 단숨에 뻗어 나갑니다. 진짜 정전이라면 UPS가 서버를 받쳐 줬어야 하고, 받쳐 주지 못했다면 전원 케이블이 "Battery Backup"이 아니라 "Surge Only" 열에 꽂혀 있었던 게 틀림없다. CyberPower 뒷면은 그 두 열이 거의 똑같이 생겨서 잘못 꽂는 일이 매우 흔합니다.
그 일련의 추론은 그럴듯하게 조립되어 있었습니다. 게임용 PC가 왜 재부팅됐는지 확인하기 전까지는요.
Windows Update였습니다.
전제가 무너지고 추론도 통째로 무효가 됩니다. 로그를 다시 보니 그 죽음은 앞의 네 번과 완전히 똑같았습니다. OL 그대로, 상용 전원 안정, 배터리 만충, OB 없음. 정전도 아니고 잘못 꽂은 것도 아니고, 같은 "UPS 하류의 순간 단선"이 십분의 일 빈도로 일어났을 뿐입니다.
TIP
독립된 두 사건이 동시에 일어나는 건 추론을 헛디디는 가장 빠른 길입니다 "두 대가 동시에 나갔다"는 이보다 더 강할 수 없는 공통 원인의 증거처럼 보입니다. 그냥 우연이었습니다. 새 증거가 나와서 가설이 갑자기 아주 설득력을 갖게 됐을 때, 바로 그때가 그 증거 자체를 다시 검증해야 하는 순간입니다. Windows Update 기록을 보러 가지 않았다면 하룻밤을 통째로 UPS 콘센트 분류를 조사하는 데 썼을 겁니다.
그러면 그 회차는 결국 무엇이었는가. 솔직히 말해 알아내지 못했습니다.
그 시점에 확정할 수 있었던 건 소거법의 결과뿐입니다. 상용 전원이 아니고(UPS 로그는 전 구간 깨끗), 과열도 아닙니다(죽은 순간 CPU는 85% idle, load 1에서 3, 온도 경고는 0, 온도도 정상). 남는 가능성에서 가장 높은 건 새 케이블의 한쪽 끝이 끝까지 들어가지 않았거나, 내부 커넥터가 또 조금 헐거워졌거나입니다. C13/C14의 "꽂힌 것 같은데 사실 끝까지 안 간" 경우는 매우 흔합니다. 양쪽 끝을 다시 꽂았고, 거기서 이야기가 끊겼습니다.
끊긴 건 포기해서가 아니라 나흘 뒤에 완전히 다른 방식으로 한 번 더 죽었기 때문입니다. 그때부터 주의가 완전히 그쪽으로 옮겨 갔고, 이 잔여 결함은 검증할 수 있을 만한 빈도로 재발하지 않았습니다. 그래서 정직한 결론은 이렇습니다. 갉아 먹힌 케이블이 빈도를 십분의 일로 만들었고, 남은 한 번은 지금도 미해결입니다.
다만 그날 한 가지를 더 했습니다. "과열"이 다소 일찍 배제된 게 걸려서 온도 로거를 겸사겸사 심어 뒀습니다. CPU 온도와 load를 매분 기록하는, 다음을 위한 보험이었습니다.
나흘 뒤 그게 곧바로 일했습니다.
15:12 cpu=90.1C load=8.65
15:22 cpu=90.0C load=32.53
15:31 cpu=90.0C load=84.42
15:43 cpu=90.0C load=156.54
15:50 cpu=90.0C load=196.01 ← cron이 더 이상 스케줄되지 않음그 회차는 전원 차단이 아니라 시스템이 타 버린 것이었습니다. 온도는 90°C에 박힌 채 사십 분, load는 8에서 196까지 올랐고, 그동안 UPS는 계속 정상이었습니다. 전기와는 전혀 무관한 다른 이야기입니다.
NOTE
추적할 때마다 계측기가 하나씩 남고, 다음 사건은 앞 사건이 남긴 계기로 풀린다 UPS는 전원 차단을 조사하려고 산 것이고, 그 로그가 갉아 먹힌 케이블을 밝혔습니다. 온도 로거는 과열을 배제하려고 더한 것이고, 나흘 뒤 열폭주의 현행범을 잡았습니다. 이건 운이 좋았던 게 아닙니다. "확신이 서지 않을" 때마다 더한 것이 추측이 아니라 기록 장치였다는 것뿐입니다. 그런 기록 장치는 자기가 필요해진다는 걸 깨닫기도 전부터 증거를 모으기 시작해 줍니다.
쓰는 시점의 현황#
journalctl --list-boots를 보면 각 재부팅이 "깨끗한 종료"였는지 "강제 차단"이었는지 알 수 있습니다. 끝에 systemd-shutdown이 있는 게 전자, 아무것도 남아 있지 않은 게 후자입니다.
07-14 → 07-15 20:21 종료 기록 없음 ← 잔여 전원 결함
07-16 → 07-19 15:56 종료 기록 없음 ← 열폭주
07-19 → 07-20 17:15 systemd-shutdown
07-20 → 이후 여덟 번 systemd-shutdown ← 전부 제가 직접 재부팅한 것마지막 비계획적 죽음은 07-19이고, 그 뒤 열엿새 동안 강제 차단은 한 번도 없습니다.
다만 이 잔여 전원 결함을 해결됐다고 부를 수는 없습니다. 이 기간에 이런저런 이유로 여덟 번 재부팅했으므로 단일 연속 가동은 최장 이레뿐이고, 반면 지난번 전원 결함이 나오기까지의 간격은 10.8일이었습니다. 즉 지금까지 지난번 발생 간격을 넘긴 연속 가동은 한 번도 없습니다. 고쳐졌다고 증명된 게 아니라 아직 나올 기회가 없었을 뿐입니다.
정말로 해결을 선언하려면 먼저 열하루를 넘겨 조용히 돌아 줘야 합니다. 이 기준은 제가 정한 것이고, 굳이 적는 이유는 "그 뒤로 일어나지 않았습니다"라는 한 문장은 시간 척도를 붙이지 않으면 증거로 성립하지 않기 때문입니다.
한 페이지 체크리스트#
UPS + NUT 셀프호스팅 체크리스트
- UPS 선정은 세 가지: PFC 정현파(액티브 PFC 파워는 파형을 가린다), AVR 탑재(전압 변동에 배터리를 쓰지 않는다), NUT 지원(제조사 소프트웨어가 필요 없다).
- UPS는 계측기이기도 하다:
ups.status/input.voltage/battery.charge를 매분 기록해 두면 다음 장애를 "상용 전원 문제"와 "UPS 하류 문제"로 깔끔히 가를 수 있다. upsd는127.0.0.1에 묶는다. 단일 머신 모니터링에서 외부로 열 이유가 없다.- 설정 파일 권한은
root:nut 640. 맞지 않으면 driver가 뜨지 않는다. POWERDOWNFLAG를 빼먹지 않는다. 빼면 OS 정지 후 배터리가 0까지 쥐어짜인다.- BIOS는
On,Last State가 아니다. 틀리면 NUT의 깨끗한 종료 후 상용 전원이 돌아와도 머신이 켜지지 않는다. - 종료 임계값은 일단 출하값. 실제 가동 시간 숫자가 나온 뒤에
upssched를 검토한다. - Webhook 파일은
/etc/nut아래에.upsmon은 홈 디렉터리를 읽지 못한다. - 컨테이너에 상태를 넘길 땐 파일 경유. 호스트가 JSON을 쓰고 bind-mount 하는 편이
upsd를 외부에 노출하는 것보다 깨끗하다. - 케이블은 배선 몰드나 갉아먹기 방지 슬리브로. 이건 서버와 무관하고, 고양이를 위한 것이다.
- 가설을 하나 지울 때마다 기록 장치를 하나 남긴다. 다음에 무슨 일이 생기면 이미 손에 있다.
- NUT —— Network UPS Tools 공식 문서networkupstools.org
- NUT —— 지원 하드웨어 목록(구입 전 기종 확인)HCL
- NUT —— usbhid-ups 드라이버 설명man usbhid-ups
- NUT —— upsmon.conf 레퍼런스man upsmon.conf
- CyberPower —— CP1500PFCLCD 제품 페이지cyberpowersystems.com
아직 댓글이 없어요
✨ 첫 댓글을 남겨보세요