서버백업운영
cron 실행 로그 확인으로 자동화 작업이 제대로 돌고 있는지 검증합니다
cron 작업 실행 여부 확인과 디버깅이 중요하다는 걸 깨달은 건 6개월 전에 등록한 DB 백업 cron이 실제로는 한 번도 실행 안 됐다는 걸 우연히 발견했을 때입니다. 로그 파일도 없었고, crontab에는 분명히 등록돼 있었습니다. 알고 보니 스크립트 경로에 공백이 있어서
서버백업운영
cron 잡 설정 실수, 이렇게 하면 백업 점검 시간을 아낀다
자동 백업을 등록했다고 해서 실제로 백업이 되고 있다고 볼 수는 없습니다. 병원 서버 운영에서 cron 잡 설정 실수는 조용히 누적되다가 복구가 필요한 순간에 드러납니다.
서버백업운영
디스크 사용량 자동 모니터링으로 다운 전에 미리 대응합니다
서버 디스크 사용량 자동 모니터링의 필요성을 실감한 건 새벽 2시에 병원 직원에게 "예약 시스템이 안 된다"는 연락을 받고 나서였습니다. 서버에 접속해보니 디스크가 100%였고, MySQL이 binlog 파일을 쓰지 못해서 DB 트랜잭션이 실패하고 있었습니다. 미리 알람만
서버백업운영
fail2ban 설치 10분으로 SSH 브루트포스 공격을 자동 차단합니다
fail2ban으로 SSH 무차별 대입 차단을 설정하기 전, 서버 로그를 열면 심장이 쫄깃했습니다. `/var/log/auth.log` 를 보면 중국, 러시아, 동유럽 IP에서 root, admin, ubuntu, test 같은 계정명으로 1초에 수 번씩 로그인을 시도하는 기록
서버백업운영
리눅스 스왑 파일 설정으로 메모리 부족 시 서버 다운을 방지합니다
리눅스 스왑 파일 설정으로 메모리 부족 방지가 필요하다는 걸 느낀 건 새벽에 MySQL이 갑자기 죽어서 사이트가 다운됐을 때입니다. 서버 로그에 `Out of memory: Killed process ... (mysqld)` 메시지가 있었고, 그 순간 메모리 사용률이 98%였습
서버백업운영
logrotate 설정으로 Nginx 로그를 자동으로 정리하고 디스크를 지킵니다
Nginx 로그 자동 정리 logrotate 설정이 필요했던 건 서버 디스크 사용량 점검 중 `/var/log/nginx/` 폴더가 30GB를 넘어있는 것을 발견했을 때였습니다. 수년 치 access.log가 그대로 쌓여 있었습니다. logrotate는 리눅스 표준 로그 관리
서버백업운영
MySQL binlog 자동 만료 설정으로 디스크를 낭비 없이 관리합니다
MySQL binlog 자동 정리로 디스크 절약이 필요했던 건 `df -h`를 보니 `/var/lib/mysql/`이 15GB를 차지하고 있었고, 그 안에 `mysql-bin.000001`부터 수백 개의 binlog 파일이 쌓여 있었을 때입니다. binlog는 MySQL 복제(
서버백업운영
MySQL 보안 설정으로 DB 무단 접근 위험을 차단합니다
MySQL 루트 계정 보안 설정은 서버 설치 후 반드시 해야 하는 초기 작업 중 하나입니다. MySQL을 패키지로 설치하면 기본적으로 루트 계정이 비밀번호 없이 접근 가능하거나, 약한 비밀번호가 설정된 상태입니다. 또한 테스트 DB와 익명 사용자 계정도 기본 생성됩니다. 이런
서버백업운영
MySQL 슬로우 쿼리 로그로 페이지 속도를 잡아먹는 쿼리를 찾아냅니다
MySQL 슬로우 쿼리 로그 설정과 분석으로 페이지 속도 문제의 원인을 찾은 건 병원 예약 목록 페이지가 유독 느린데도 GTmetrix에서는 파일 크기나 캐시 문제가 없었을 때입니다. 슬로우 쿼리 로그를 켜보니 `wp_postmeta` 테이블에 인덱스가 없는 `meta_key`
서버백업운영
mysqldump cron 자동화로 DB 백업을 매일 빠짐없이 보관합니다
mysqldump 자동 백업 cron 설정은 운영 서버의 가장 기본적인 안전망입니다. 플러그인 백업(UpdraftPlus 등)도 좋지만, 서버에서 직접 mysqldump로 DB를 덤프하는 방식은 호스팅·플러그인에 의존하지 않는 독립적인 백업입니다. 플러그인 오류로 자동 백업이
서버백업운영
Nginx 로그 분석으로 해킹 시도를 조기에 탐지합니다
Nginx 액세스 로그 해킹 흔적 분석은 서버 관리자의 핵심 루틴입니다. 제가 주기적으로 로그를 보지 않았다면, 한 병원 사이트의 특정 API 엔드포인트를 향한 수상한 요청 패턴을 놓쳤을 것입니다. 로그는 서버에서 일어나는 모든 일의 기록입니다. 공격이 성공하기 전에 시도 단계
서버백업운영
Nginx gzip 압축 설정으로 페이지 로딩 속도와 트래픽 비용을 동시에 줄입니다
Nginx gzip 압축 설정으로 페이지 속도 개선을 처음 시도한 건 GTmetrix 점수를 올리다가 "Enable text compression" 경고가 빨간불로 떠 있는 걸 발견했을 때입니다. Nginx 기본 설치에서는 gzip이 꺼져 있어서, 10KB짜리 HTML이 압
서버백업운영
NTP 시간 동기화 설정으로 SSL 오류와 로그 불일치를 방지합니다
서버 시간 동기화 NTP 설정의 필요성을 체감한 건 특정 사용자 브라우저에서만 SSL 인증서 오류가 발생하고, 에러 로그 시간이 실제 발생 시각과 5분 이상 차이가 났을 때입니다. 서버 시간이 실제보다 앞서 있어서 아직 유효하지 않은 인증서로 인식하는 문제였습니다. system
서버백업운영
오프사이트 백업으로 서버 장애에도 데이터를 안전하게 지킵니다
오프사이트 백업 원격 전송 설정의 필요성을 깨달은 건 서버 스토리지가 물리적으로 고장나서 `/var/backups/`에 있던 백업 파일도 함께 손실됐을 때입니다. 백업을 열심히 만들었는데, 같은 서버에만 보관했던 것이 문제였습니다. 백업의 기본 원칙은 `3-2-1 룰`: 3개
서버백업운영
PHP-FPM pm 설정 튜닝으로 트래픽 급증 시 502 에러를 방지합니다
PHP-FPM 설정 튜닝으로 워드프레스 속도 개선이 필요했던 건 병원 예약 페이지에 홍보 이메일이 나간 후 갑자기 접속이 몰리면서 502 Bad Gateway 에러가 쏟아졌을 때입니다. Nginx 로그를 보니 `connect() to unix:/run/php/php8.1-fpm
서버백업운영
rsync 자동화로 서버 파일 동기화 실수와 누락을 없앱니다
rsync로 서버 파일 자동 동기화는 두 서버 사이에 파일을 일관되게 유지해야 할 때 가장 신뢰할 수 있는 방법입니다. 병원 사이트를 운영 서버와 스테이징 서버 두 곳에서 관리했는데, 수동으로 FTP를 이용해 동기화하다가 업로드 이미지 일부를 빠뜨린 적이 있었습니다. rsync
서버백업운영
설정 변경 전 백업과 테스트로 서버 다운타임을 최소화합니다
서버 다운타임 최소화 운영 전략이 필요하다는 걸 뼈저리게 느낀 건 Nginx 설정을 수정하다가 세미콜론 하나를 빠뜨려서 `nginx -t` 테스트를 건너뛰고 reload 했더니 Nginx가 완전히 다운됐을 때입니다. 그날은 오전 진료 시간에 예약 시스템이 30분 동안 멈췄습니다
서버백업운영
서버 헤더 정보 숨기기로 자동화 공격 타겟이 되는 것을 줄입니다
서버 헤더 정보 노출 차단은 공격자에게 불필요한 정보를 주지 않는 기본 보안 조치입니다. HTTP 응답 헤더에는 기본적으로 서버 소프트웨어와 버전 정보가 포함됩니다. `Server: nginx/1.18.0` 이나 `X-Powered-By: PHP/8.1.12` 같은 정보는 공격
서버백업운영
top과 iotop으로 서버 부하 급증 원인을 5분 안에 찾아냅니다
서버 부하 급증 원인 분석 방법을 체계적으로 익히게 된 건 병원 사이트가 갑자기 느려졌는데 원인을 몰라서 그냥 서버를 재시작하고 넘어간 적이 몇 번 있었기 때문입니다. 재시작으로 해결됐지만 왜 느려졌는지 몰랐습니다. 이후 부하가 생기면 체계적으로 원인을 찾는 루틴을 만들었습니다
서버백업운영
월간 서버 점검 체크리스트로 장애를 미리 막고 운영 안정성을 높입니다
월간 서버 점검 체크리스트를 만든 건 인증서 만료 3일 전에야 알림이 와서 급하게 갱신했던 일이 있고 나서입니다. 그 전까지는 문제가 생기면 대응하는 방식이었는데, 체계적인 월간 점검 루틴을 만든 후로는 디스크 80% 경고, 백업 파일 0바이트 이슈, cron 미실행 등을 미리
서버백업운영
PHP-FPM 설정만 다듬어도 서버 터지는 횟수를 90% 줄입니다
월요일 아침 출근길, 병원 한 곳에서 웹사이트가 열리지 않는다는 긴급 전화를 받았습니다. 화면에는 'Error Establishing a Database Connection'이라는 문구만 떠 있었습니다. 원인은 물리 메모리 고갈로 리눅스 커널이 MySQL을 강제로 죽인 OOM(
서버백업운영
Nginx access.log 분석으로 서버 트래픽 이상 징후를 빠르게 탐지합니다
서버 트래픽 이상 징후 탐지 방법을 익히게 된 건 새벽 3시에 서버 CPU가 80%를 넘는다는 알림이 울렸고, access.log를 보니 동일 IP에서 1분에 500건 이상 요청이 들어오고 있었을 때입니다. 패턴을 보니 `/wp-login.php`와 `/wp-admin/`에 집
서버백업운영
systemctl enable로 서버 재부팅 후 서비스 자동 시작을 보장합니다
서버 재시작 후 서비스 자동 복구 설정이 얼마나 중요한지 알게 된 건 우분투 자동 보안 업데이트가 서버를 재부팅시킨 후, Nginx가 자동으로 올라오지 않아서 새벽 3시에 사이트가 다운된 것을 아침에 발견했을 때였습니다. 서버는 정상이었지만 Nginx가 enable 상태가 아니
서버백업운영
SSH 키 인증으로 전환하면 비밀번호 브루트포스가 원천 차단됩니다
SSH 키 기반 인증으로 패스워드 인증 비활성화는 서버 보안에서 가장 효과적인 단일 조치 중 하나입니다. fail2ban과 포트 변경을 하더라도 비밀번호 인증이 열려 있으면 결국 언젠가 뚫릴 수 있습니다. SSH 키 인증으로 전환하고 비밀번호 인증을 완전히 비활성화하면, 키 파
서버백업운영
SSH 포트 변경으로 자동화 봇 공격의 99%를 걸러냅니다
서버 SSH 포트 변경은 보안 전문가들 사이에서 "security through obscurity"라고 약간 비판을 받기도 하지만, 실제로 효과가 있습니다. 기본 22번 포트를 변경하면 자동화된 봇 스캐너 대부분이 그냥 지나갑니다. 이 봇들은 인터넷 전체를 스캔하면서 22번
서버백업운영
SSH 터널로 MySQL 외부 포트 없이 원격에서 안전하게 DB를 관리합니다
SSH 터널로 원격에서 내부 DB 안전하게 접속하는 방식으로 전환한 건 서버 접속 로그에서 3306 포트를 향한 자동화 스캔 시도가 하루에도 수백 번 기록되는 걸 발견한 후입니다. MySQL 외부 접속을 허용하면 비밀번호 brute force 공격에 항상 노출됩니다. SSH 터
서버백업운영
Supervisor로 백그라운드 프로세스를 자동 재시작하고 안정적으로 운영합니다
Supervisor로 백그라운드 프로세스 자동 재시작 관리를 도입한 건 병원 예약 알림을 보내는 Python 스크립트가 가끔 예외로 죽어도 아무도 몰랐던 문제를 해결하기 위해서입니다. `nohup python3 notify.py &`로 실행해두면 죽으면 그냥 죽어버렸습니다. S
서버백업운영
우분투 자동 보안 업데이트로 패치 누락 없이 서버를 안전하게 유지합니다
우분투 자동 보안 업데이트 설정의 중요성을 알게 된 건 CVE가 발표된 후 몇 주가 지나서야 패치가 안 됐다는 걸 감사 리포트에서 발견했을 때였습니다. 수동으로 업데이트하는 루틴이 있었지만 바쁜 주에는 밀리기 일쑤였습니다. 이후 `unattended-upgrades`로 보안 패
서버백업운영
UFW 방화벽 기본 설정으로 불필요한 포트를 모두 닫습니다
우분투 UFW 방화벽 기본 설정은 새 서버를 받으면 가장 먼저 해야 하는 작업 중 하나입니다. 신규 우분투 서버는 방화벽이 비활성화 상태로 납품됩니다. 저도 한 번은 서버 세팅에 집중하느라 방화벽 설정을 미루고 있었는데, Nginx 로그에 온갖 포트로 스캔 시도 기록이 쌓이는
서버백업운영
서버 디스크 용량 부족, 이렇게 하면 긴급 복구 시간을 아낀다
서버 디스크 용량 부족은 갑자기 보이지만, 대부분은 오래 쌓인 로그에서 시작됩니다. 병원 홈페이지가 느려지거나 접속이 불안정할 때 CPU보다 디스크부터 봐야 하는 경우가 많습니다.
서버백업운영
백업은 매일 돌고 있었는데, 정작 복구해 보니 안 됐습니다
병원 홈페이지 mysqldump·rsync 백업 설정 후 실제 복구 테스트에서 발견한 문제와 분기 1회 복구 테스트 루틴으로 백업 신뢰성을 검증하는 실운영 가이드.