Herkos

나만의 메일함 릴레이

최종 수정: 2026년 10월 3일

Herkos 메일은 봉인된 봉투(NIP-59 기프트 랩)로 이동하며, 앱이 가져갈 때까지 DM 릴레이 목록에 있는 릴레이에서 기다립니다. 대부분의 공개 릴레이는 요청하는 누구에게나 그 봉투를 건네줍니다. 아무도 열 수는 없지만, 누구나 누가 언제 메일을 받는지 셀 수 있고, 릴레이는 원할 때 언제든 봉투를 지울 수 있습니다.

누가 읽는지 확인하는(NIP-42) 나만의 릴레이는 여러분의 봉투를 여러분에게만 건네주고, 여러분이 정하는 기간 동안 보관합니다. 이 페이지는 세 단계로 릴레이를 설정하는 방법과 매일 밤 백업하는 방법을 설명합니다. 이미 서버가 있다면 15분 정도 걸립니다.

어떤 릴레이를 쓸까

2026년 9월 24일에 두 후보를 직접 돌려 보고, 광고하는 내용이 아니라 실제로 메일을 어떻게 다루는지 확인했습니다.

nogringo/nostr-relay HAVEN 1.2.2
봉투를 읽을 수 있는 사람 신원을 확인한 뒤 여러분만 /chat: 신원을 확인한 뒤 여러분의 신뢰망(web of trust)에 있는 누구나. /inbox: 신원 확인 없이 누구나
여러분에게 메일을 배달할 수 있는 사람 신원을 확인한 모든 발신자 여러분의 신뢰망만
받은 메일 삭제 가능 불가
빠른 재동기화(NIP-77) 가능 불가
라이선스 MIT MIT

메일함으로는 nogringo/nostr-relay를 쓰세요. 메일에 필요한 일을 하는 것은 이쪽입니다. 누구나 여러분에게 쓸 수 있고, 여러분만 읽을 수 있습니다. HAVEN은 다른 용도(개인 아웃박스, 미디어, 비공개 메모)로는 좋은 도구이지만, 메일함으로 쓰면 여러분이 팔로우하지 않는 모든 사람의 메일을 거절합니다. 일반 이메일을 전달하는 브리지도 포함해서요.

필요한 것

1단계: 릴레이 실행

git clone https://github.com/nogringo/nostr-relay
cd nostr-relay
cp .env.example .env

.env를 편집하세요. 릴레이에 이름(RELAY_NAME)을 붙이고 RELAY_URLS를 공개 주소인 wss://relay.example.com으로 설정합니다.

그다음 docker-compose.yml을 열어 포트 줄을 "127.0.0.1:3334:3334"로 바꾸세요. 릴레이는 누가 신원을 확인하는지 검사할 때 프록시가 전달하는 주소를 믿으므로, 반드시 프록시를 통해서만 접속할 수 있어야 합니다. 실행합니다:

docker compose up -d

2단계: 앞에 HTTPS 두기

Caddy를 쓰면 전체 설정(/etc/caddy/Caddyfile)은 이것뿐입니다:

relay.example.com {
    reverse_proxy 127.0.0.1:3334
}

Caddy를 다시 불러오세요(sudo systemctl reload caddy). 이제 브라우저에서 https://relay.example.com을 열면 응답이 와야 합니다.

3단계: Herkos에 알려 주기

  1. Herkos에서 설정 → 네트워크 및 서버 → 나만의 릴레이를 열고 릴레이 확인을 누릅니다. wss://relay.example.com을 입력하세요.
  2. Herkos가 연결해 시험해 봅니다. 다른 사람의 메일을 요청해 보고, 낯선 사람이 보낸 시험용 봉투를 남겼다가 지웁니다. 여기서는 나만 메일을 읽을 수 있습니다와 모든 발신자의 메일을 받습니다가 보여야 합니다.
  3. 첫 번째 DM 릴레이로 지정을 누르고, 위쪽의 저장을 누릅니다.

목록에 공개 릴레이도 두 번째로 남겨 두세요. 서버가 내려가도 메일이 기다릴 곳이 있게 됩니다. relay.damus.io는 역시 누가 읽는지 확인하므로 두 번째로 좋은 선택입니다.

4단계: 매일 밤 백업하기

Herkos는 가져온 메일의 사본을 따로 보관하지만, 앱이 닫혀 있는 동안 도착한 봉투는 Herkos를 열기 전까지 여러분의 서버에만 있습니다. 매일 밤 사본을 만들면 그 공백을 메울 수 있고, 디스크가 고장 나거나 업체가 계정을 닫아도 서버를 다시 만들 수 있습니다.

릴레이는 모든 것을 Docker 볼륨 nostr-relay_relay-db 안의 LMDB 데이터베이스 하나에 보관합니다(이름은 클론한 폴더 이름으로 시작합니다. docker volume ls로 확인하세요). 릴레이가 쓰는 중에 복사한 LMDB 파일은 열리지 않을 수 있으므로, 스크립트는 로컬 사본을 만드는 몇 초 동안 릴레이를 멈췄다가 다시 시작하고, 그다음에야 사본을 업로드합니다. 멈춰 있는 동안 메일은 목록에 두 번째로 남겨 둔 공개 릴레이에서 기다립니다.

사본은 restic으로 서버 밖으로 보내며, restic은 내보내기 전에 암호화합니다. 서버와 다른 업체의 장소를 쓰세요. SFTP 계정(스토리지 박스, 집에 있는 컴퓨터)이나 S3 호환 버킷이면 됩니다.

  1. 도구를 설치하고 저장소를 만듭니다. 비밀번호는 비밀번호 관리자에도 보관하세요. 비밀번호가 없으면 사본을 읽을 수 없고, 서버에만 있으면 서버와 함께 사라집니다. SFTP를 쓴다면 root에게 백업 기계가 받아들이는 SSH 키도 필요합니다 (sudo ssh-keygen -t ed25519 후 그곳에 /root/.ssh/id_ed25519.pub 추가).

    sudo apt install restic rsync
    sudo sh -c 'openssl rand -base64 32 > /root/.restic-password'
    sudo sh -c 'cat > /root/.restic-env' <<'END'
    export RESTIC_REPOSITORY=sftp:backup@backup.example.com:/relay
    export RESTIC_PASSWORD_FILE=/root/.restic-password
    END
    sudo chmod 600 /root/.restic-password /root/.restic-env
    sudo sh -c '. /root/.restic-env && restic init'
    
  2. 다음을 /usr/local/bin/backup-relay로 저장하고 실행 권한을 주세요 (sudo chmod 700 /usr/local/bin/backup-relay). /root/nostr-relay에 클론하지 않았다면 RELAY_DIR를 바꾸세요. 최근 14일, 8주, 12개월분을 보관합니다. 1년 치를 데이터베이스와 비슷한 크기로 보관하는 셈입니다.

    #!/bin/sh
    set -eu
    . /root/.restic-env
    RELAY_DIR=/root/nostr-relay
    COPY=/var/backups/relay-db
    VOLUME=$(docker volume inspect --format '{{ .Mountpoint }}' nostr-relay_relay-db)
    mkdir -p "$COPY"
    cd "$RELAY_DIR"
    docker compose stop relay
    trap 'docker compose start relay' EXIT
    rsync -a --delete "$VOLUME/" "$COPY/"
    docker compose start relay
    trap - EXIT
    restic backup "$COPY" --tag relay
    restic forget --tag relay --keep-daily 14 --keep-weekly 8 --keep-monthly 12 --prune
    
  3. 한 번 직접 실행한 뒤(sudo /usr/local/bin/backup-relay) sudo crontab -e로 예약하세요. 두 번째 줄은 매달 저장된 데이터의 10분의 1을, 매번 다른 부분을 다시 읽어 사본을 아직 열 수 있는지 확인합니다. 가끔 /var/log/backup-relay.log를 살펴보세요. Fatal이 들어간 줄은 그날 밤 사본이 실패했다는 뜻입니다.

    15 4 * * * /usr/local/bin/backup-relay >> /var/log/backup-relay.log 2>&1
    45 5 1 * * . /root/.restic-env && restic check --read-data-subset=10% >> /var/log/backup-relay.log 2>&1
    

복원하려면(새 서버, 또는 디스크 고장 후): 릴레이를 다시 설정하고(1~3단계) 같은 저장소로 이 단계의 1번과 2번을 반복하되, 새 비밀번호를 만드는 대신 저장해 둔 비밀번호를 /root/.restic-password에 쓰고 restic init은 건너뛰세요. 그런 다음 가장 최근 백업을 릴레이의 볼륨에 복사합니다:

sudo sh -c '. /root/.restic-env && restic restore latest --tag relay --target /'
cd /root/nostr-relay && sudo docker compose stop relay
sudo rsync -a --delete /var/backups/relay-db/ "$(sudo docker volume inspect --format '{{ .Mountpoint }}' nostr-relay_relay-db)/"
sudo docker compose start relay

1년에 한 번은 여분의 기계에서 이 복원을 해 보고, 릴레이가 메일이 든 채로 시작되는지 확인하세요. 비밀번호를 포함한 전체 과정을 증명하는 유일한 시험입니다.

알아 두면 좋은 점