Go 기반 경량 서버 모니터링 & 보안 감시 에이전트.
시스템 리소스(CPU, 메모리, 디스크, 온도)를 실시간 모니터링하고, 보안 이상 징후(SSH 침입 시도, crontab 변조, 은닉 프로세스)를 탐지하여 이메일로 즉시 알림을 보냅니다.
2026년 1월, 홈서버에 암호화폐 채굴 악성코드가 침투하여 13일간 CPU 99%를 점유하는 보안 사고가 발생했습니다. 실시간 모니터링 부재로 장기간 미탐지된 이 사고의 재발을 방지하기 위해 개발되었습니다.
- CPU 사용률 (이동평균 기반, 지속 시간 판단)
- 메모리 / SWAP 사용률
- 디스크 / inode 사용률
- CPU 온도 (coretemp 센서)
- Load Average (코어 수 대비)
- SSH
authorized_keys변조 감지 (SHA256 해시 비교) - SSH 로그인 실패 모니터링 (auth.log 파싱)
- SSH 로그인 IP 지오로케이션 (국가/도시/ISP 표시, 허용 국가 제한)
- crontab 변경/삭제 감지
/tmp,/dev/shm실행파일 탐지- 은닉 프로세스 탐지 (
/procvsps비교) - Docker 컨테이너 상태 감시 (exited/unhealthy)
- 서비스 프로세스 모니터링 (nginx, redis 등 중단 시 알림)
- 네트워크 대역폭 모니터링 (100MB/s 초과 시 경고)
- 마이닝 풀 아웃바운드 연결 탐지
- SMTP 이메일 즉시 알림 (HTML 템플릿)
- Webhook 알림 (Slack, Discord, Telegram)
- 등급별 debounce (WARNING 30분, CRITICAL 10분, SECURITY 5분)
- 등급 상승 시 즉시 재알림, 정상 복구 시 RESOLVED 알림
- 매일 일일 리포트 이메일 (시스템 현황 + top 프로세스 + 알림 요약)
- 웹 대시보드 (
:9090) — AJAX 실시간 갱신, 스파크라인 차트
- Config 핫 리로드 (fsnotify) — 설정 변경 시 재시작 없이 반영
- 메트릭 히스토리 (24시간 링 버퍼) + 스파크라인 시각화
# 1. config.yaml 준비
curl -o config.yaml https://raw.githubusercontent.com/jiin/picky/main/config.example.yaml
# email.to, email.from 등 수정
vi config.yaml
# 2. 실행
docker run -d \
--name picky \
--pid host \
--restart always \
-p 9090:9090 \
-v /proc:/host/proc:ro \
-v /sys:/host/sys:ro \
-v /etc:/host/etc:ro \
-v /var/log:/host/var/log:ro \
-v /var/run/docker.sock:/var/run/docker.sock \
-v $(pwd)/config.yaml:/app/config.yaml \
-e TZ=Asia/Seoul \
-e HOST_PROC=/host/proc \
-e HOST_SYS=/host/sys \
-e SMTP_USER=your@gmail.com \
-e SMTP_PASS=your-app-password \
jiin724/picky:latest# 1. config.yaml 준비
cp config.example.yaml config.yaml
vi config.yaml
# 2. 실행
SMTP_USER=your@gmail.com SMTP_PASS=your-app-password docker compose up -d
# 로그 확인
docker logs -f pickygo build -o picky ./cmd/picky
./picky -config config.yamlconfig.yaml 예시:
server:
hostname: "myserver"
check_interval: 10s
dashboard_addr: ":9090"
thresholds:
cpu:
warning: 70 # %
critical: 90
warning_duration: 5m
critical_duration: 3m
memory:
warning: 80
critical: 90
disk:
warning: 80
critical: 90
path: "/"
temperature:
warning: 65 # °C
critical: 80
load:
warning_ratio: 0.7 # 코어 수 대비
critical_ratio: 1.0
swap:
warning: 30
critical: 50
security:
watch_files:
- /host/etc/passwd
- /host/etc/shadow
- /host/etc/crontab
watch_user_files:
- authorized_keys
- .bashrc
- .bash_profile
ssh_fail_threshold: 10
ssh_fail_window: 5m
scan_paths:
- /tmp
- /dev/shm
- /var/tmp
watch_services: # 프로세스 실행 감시
- nginx
- redis
- mariadb
allowed_countries: # SSH 허용 국가 (비워두면 제한 없음)
- KR
email:
smtp_host: "smtp.gmail.com"
smtp_port: 587
from: "picky@myserver.com"
to:
- "admin@example.com"
alerts:
debounce:
warning: 30m
critical: 10m
security: 5m
max_history: 100
report:
daily_schedule: "0 9 * * *" # 매일 오전 9시SMTP 자격증명은 환경변수로도 설정 가능:
export SMTP_USER=your@gmail.com
export SMTP_PASS=your-app-passwordhttp://서버IP:9090으로 접속하면 실시간 메트릭과 최근 알림을 확인할 수 있습니다. 10초마다 자동 새로고침됩니다.
| 경로 | 설명 |
|---|---|
GET / |
HTML 대시보드 |
GET /api/metrics |
최신 메트릭 (JSON) |
GET /api/alerts |
알림 히스토리 (JSON) |
GET /api/metrics/history |
메트릭 히스토리 (JSON, 스파크라인용) |
GET /health |
헬스체크 |
| 등급 | 조건 | 재알림 주기 |
|---|---|---|
| INFO | 일일 리포트 | 1일 1회 |
| WARNING | 경고 임계값 초과 | 30분 |
| CRITICAL | 위험 임계값 초과 | 10분 |
| SECURITY | 보안 이상 징후 | 5분 |
picky/
├── cmd/picky/main.go # 엔트리포인트
├── internal/
│ ├── collector/ # 시스템 메트릭 수집 (CPU, 메모리, 디스크, 온도)
│ ├── security/ # 보안 스캐너 (SSH, crontab, 프로세스, 파일, Docker, 네트워크, 지오로케이션)
│ ├── alert/ # 알림 엔진 (임계값 판단, debounce)
│ ├── notifier/ # 이메일 발송 (SMTP, HTML 템플릿)
│ ├── scheduler/ # 일일 리포트 스케줄러
│ ├── dashboard/ # 웹 대시보드
│ └── config/ # YAML 설정 파서 + 핫 리로드 (fsnotify)
├── config.example.yaml
├── Dockerfile
├── docker-compose.yml
└── go.mod
# 테스트
go test ./...
# 정적 분석
go vet ./...
# 빌드
go build ./cmd/picky
# Docker 빌드 (linux/amd64)
docker build --no-cache --platform linux/amd64 -t jiin724/picky:latest .| 항목 | 목표 |
|---|---|
| CPU | < 1% |
| 메모리 | < 50MB |
| Docker 제한 | 0.5 CPU, 128MB RAM |
MIT