Files
deadman-switch/README.md
zenn 5f9f10f305 설정 보강 및 메시지 동작 정리
RESET_TOKEN을 .env에서 읽도록 바꾸고 한국 시간 표시와 시간대별 클릭 메시지 동작을 정리합니다.
2026-06-10 12:42:14 +09:00

8.6 KiB

Collection Keeper

개인 NAS 사용자를 위한 초경량 생존 확인 웹앱입니다.

  • 현재 버전: v1.0.0
  • Git 저장소: https://git.sori.studio/zenn/collection.sori.studio.git
  • 상세 설치 문서: docs/DEPLOY.md

가끔 방문해서 중앙 버튼을 누르면 확인 시간이 갱신되고, 일정 기간 동안 아무도 누르지 않으면 사용자가 지정한 스크립트가 실행됩니다.

Collection Keeper는 Collection 폴더를 직접 삭제하지 않습니다.

주요 기능

  • 중앙 버튼 한 개로 생존 확인
  • SQLite 기반 통계 및 방문 흔적 저장
  • 1초 쿨다운 스팸 방지
  • 랜덤 이모지 클릭 효과
  • 배경 이미지 교체 및 랜덤 선택
  • threshold 초과 시 사용자 스크립트 실행

로컬 실행 가이드

개발하거나 먼저 동작을 확인할 때는 로컬에서 실행합니다.

필요한 것:

  • Node.js 20 이상
  • npm

설치:

npm install

실행:

npm start

브라우저에서 접속:

http://localhost:40100

개발 중 파일 변경을 감지해서 다시 실행하려면:

npm run dev

로컬 실행 시 SQLite 파일은 기본적으로 data/keeper.sqlite에 생성됩니다.

Docker 실행 가이드

Docker로 한 번에 빌드하고 실행합니다.

필요한 것:

  • Docker
  • Docker Compose

실행:

docker compose up -d --build

브라우저에서 접속:

http://localhost:40100

상태 확인:

docker compose ps

로그 확인:

docker compose logs -f

중지:

docker compose down

다시 시작:

docker compose restart

컨테이너와 네트워크를 중지해도 keeper-data 볼륨에 SQLite 데이터가 남습니다.

상용/NAS 설치 가이드

NAS에서 오래 켜둘 때는 Docker Compose 실행을 권장합니다.

  1. 프로젝트 폴더를 NAS에 둡니다.
cd /volume1/docker/collection-keeper
  1. 설정을 확인합니다.
vi config/default.json

자주 바꾸는 항목:

  • threshold_days: 며칠 동안 버튼을 누르지 않으면 스크립트를 실행할지
  • cooldown_seconds: 생존 확인으로 인정되는 최소 클릭 간격
  • trigger_script: 실행할 사용자 스크립트 경로
  • background: none, 배경 파일명, 또는 random
  1. 사용자 스크립트를 수정합니다.
vi scripts/cleanup.sh
chmod +x scripts/*.sh
  1. docker-compose.yml의 NAS 경로를 확인합니다.

기본값은 Synology 스타일 경로입니다.

- /home/zenn/Collection:/home/zenn/Collection

다른 경로를 쓴다면 왼쪽 경로를 실제 Collection 폴더로 바꿉니다.

  1. 실행합니다.
docker compose up -d --build
  1. 로그를 확인합니다.
docker compose logs -f collection-keeper
  1. NAS 주소로 접속합니다.
http://NAS_IP:40100

예시:

http://192.168.0.10:40100

업데이트 가이드

코드를 새 버전으로 바꾼 뒤 다시 빌드합니다.

docker compose down
docker compose up -d --build

데이터를 유지하려면 docker compose down -v는 사용하지 마세요. -v 옵션은 SQLite 데이터가 들어 있는 Docker 볼륨까지 삭제합니다.

백업 가이드

Docker Compose 기본 설정에서는 SQLite DB가 keeper-data 볼륨에 저장됩니다.

볼륨 이름 확인:

docker volume ls | grep keeper

로컬 실행에서는 data/keeper.sqlite 파일을 백업하면 됩니다.

cp data/keeper.sqlite keeper.backup.sqlite

멀티 아키텍처 이미지 빌드

ARM64와 x86_64 이미지를 함께 빌드하려면 Docker Buildx를 사용합니다.

docker buildx build --platform linux/amd64,linux/arm64 -t collection-keeper:latest .

문제 해결

EADDRINUSE: address already in use :::40100

이미 40100 포트를 쓰는 서버가 떠 있을 때 발생합니다.

포트를 쓰는 프로세스 확인:

lsof -nP -iTCP:40100 -sTCP:LISTEN

예시 출력에서 PID가 30383이라면 종료:

kill 30383

다시 실행:

npm start

기존 서버를 끄고 싶지 않다면 다른 포트로 실행할 수도 있습니다.

PORT=40101 npm start

이 경우 브라우저에서는 다음 주소로 접속합니다.

http://localhost:40101

설정

기본 설정은 config/default.json 에 있습니다.

항목 기본값 설명
threshold_days 90 생존 확인 허용 기간
threshold_seconds null 테스트용 초 단위 생존 확인 기간. 값이 있으면 threshold_days보다 우선합니다.
cooldown_seconds 1 생존 확인 인정 쿨다운
check_interval_seconds 60 스크립트 검사 주기
database_path ./data/keeper.sqlite SQLite 경로
trigger_script ./scripts/cleanup.sh 조건 충족 시 실행할 스크립트
background random none, 배경 파일명, 또는 random
collection_path /home/zenn/Collection Collection 폴더 경로
recent_traces_limit 5 최근 흔적 저장 조회 개수
reset_token "" 초기화 API 보호용 토큰. 비어 있으면 토큰 없이 초기화 가능합니다.

환경 변수로도 덮어쓸 수 있습니다.

  • THRESHOLD_DAYS
  • COOLDOWN_SECONDS
  • CHECK_INTERVAL_SECONDS
  • DATABASE_PATH
  • TRIGGER_SCRIPT
  • COLLECTION_PATH
  • BACKGROUND
  • PORT
  • THRESHOLD_SECONDS
  • RESET_TOKEN

화면 문구 커스터마이징

화면에 보이는 글, 클릭 이모지, 클릭 메시지는 public/custom.js 한 파일에서 바꿉니다.

코드를 몰라도 이 파일의 따옴표 안 문장과 이모지만 수정하면 됩니다.

window.COLLECTION_KEEPER_CUSTOM = {
  keeperTextLines: [
    '가끔은 생각해.',
    '',
    '누군가 버튼을 누른다는 건',
    '이곳을 기억하고 있다는 뜻일까,',
  ],

  farewellTextLines: [
    '안녕.',
    '',
    '고마웠어.',
  ],

  emojis: ['🐱', '🐰', '🌸', '✨'],

  clickMessages: [
    '기록은 남겨둘게.',
    '아직 이곳을 기억하고 있어.',
  ],
};
  • keeperTextLines: 오른쪽 아래에 표시되는 글입니다. 빈 줄은 ''로 넣습니다.
  • farewellTextLines: 남은 기간이 0이 되었을 때 표시되는 작별 인사입니다.
  • emojis: 클릭할 때 기록되고 표시되는 이모지입니다.
  • clickMessages: 클릭할 때 이모지 뒤에 붙는 랜덤 문장입니다.

만료 테스트와 초기화

만료 화면을 빠르게 확인하려면 초 단위 타이머를 사용합니다.

THRESHOLD_SECONDS=10 npm start

10초가 지나면 화면이 작별 인사로 전환되고, 더 이상 클릭해도 확인 시간이 갱신되지 않습니다.

다시 처음 상태로 초기화:

curl -X POST http://localhost:40100/api/reset

초기화 API에 토큰을 걸고 싶으면 RESET_TOKEN을 설정합니다. Docker 운영 환경에서는 Git에 올리지 않는 .env 파일을 사용하세요.

RESET_TOKEN=my-secret THRESHOLD_SECONDS=10 npm start

Docker Compose:

cat > .env <<'EOF'
RESET_TOKEN=my-secret
EOF

docker compose up -d --build

토큰이 있을 때 초기화:

curl -X POST http://localhost:40100/api/reset \
  -H 'Content-Type: application/json' \
  -d '{"token":"my-secret"}'

배경 이미지

assets/backgrounds/ 폴더에 이미지를 넣고 설정에서 지정합니다. 기본값은 random입니다.

예시:

{
  "background": "bg01.jpg"
}

랜덤 사용:

{
  "background": "random"
}

배경 없이 사용:

{
  "background": "none"
}

사용자 스크립트

scripts/ 폴더에 실행할 스크립트를 둡니다.

예시:

  • scripts/warning.sh
  • scripts/encrypt.sh
  • scripts/cleanup.sh

스크립트에는 다음 환경 변수가 전달됩니다.

  • COLLECTION_PATH
  • KEEPER_SCRIPT

안전 원칙

Collection Keeper는 다음 역할만 수행합니다.

  1. 마지막 확인 시간 관리
  2. 통계 관리
  3. 버튼 이벤트 처리
  4. 조건 충족 여부 판단
  5. 사용자 지정 스크립트 실행

파일 삭제, 암호화, 정리 같은 실제 작업은 반드시 사용자 스크립트에서 구현해야 합니다.

API

  • GET /api/status
  • POST /api/check

버튼 클릭은 반드시 POST /api/check 로 처리됩니다. 단순 방문만으로는 생존 확인이 갱신되지 않습니다.

NAS 볼륨 예시

volumes:
  - keeper-data:/data
  - ./scripts:/scripts:ro
  - /home/zenn/Collection:/home/zenn/Collection