Herkos

Tu propio relay de correo

Última actualización: 3 de octubre de 2026

El correo de Herkos viaja en sobres cerrados (los gift wraps de NIP-59) y espera en los relays de tu lista de relays DM hasta que tu app lo recoge. La mayoría de los relays públicos entregan esos sobres a cualquiera que los pida. Nadie puede abrirlos, pero cualquiera puede contar quién recibe correo y cuándo, y el relay puede borrarlos cuando quiera.

Un relay tuyo que pregunta quién lee (NIP-42) te entrega tus sobres a ti y a nadie más, y los guarda el tiempo que tú decidas. Esta página explica cómo montarlo en tres pasos, más una copia de seguridad cada noche. Si ya tienes un servidor, son unos quince minutos.

Qué relay usar

El 24 de septiembre de 2026 pusimos en marcha los dos candidatos y comprobamos lo que hacen de verdad con el correo, no lo que anuncian.

nogringo/nostr-relay HAVEN 1.2.2
Quién puede leer tus sobres Solo tú, tras identificarte /chat: cualquiera de tu red de confianza, tras identificarse. /inbox: cualquiera, sin identificarse
Quién puede enviarte correo Cualquier remitente que se identifique Solo tu red de confianza
Borrar el correo recibido Sí No
Resincronización rápida (NIP-77) Sí No
Licencia MIT MIT

Usa nogringo/nostr-relay como buzón. Es el que hace lo que necesita el correo: cualquiera puede escribirte y solo tú puedes leer. HAVEN es buena herramienta para otras cosas (un outbox personal, archivos, notas privadas), pero como buzón rechazaría el correo de cualquiera a quien no sigas, incluido el puente que trae el correo normal.

Qué necesitas

Paso 1: arrancar el relay

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

Edita .env: pon un nombre al relay (RELAY_NAME) y en RELAY_URLS su dirección pública, wss://relay.ejemplo.com.

Después abre docker-compose.yml y cambia la línea del puerto por "127.0.0.1:3334:3334". El relay se fía de la dirección que le pasa el proxy cuando comprueba quién se identifica, así que solo debe poder alcanzarse a través del proxy. Arráncalo:

docker compose up -d

Paso 2: ponerle HTTPS delante

Con Caddy, la configuración entera (/etc/caddy/Caddyfile) es:

relay.ejemplo.com {
    reverse_proxy 127.0.0.1:3334
}

Recarga Caddy (sudo systemctl reload caddy). Al abrir https://relay.ejemplo.com en el navegador ya debería responder.

Paso 3: decírselo a Herkos

  1. En Herkos, abre Ajustes → Red y servidores → Tu relay personal y pulsa Comprobar un relay. Escribe wss://relay.ejemplo.com.
  2. Herkos se conecta y lo prueba: pide el correo de otra persona y deja un sobre de prueba de un desconocido (que luego borra). Debe salir Solo tú puedes leer aquí tu correo y Acepta correo de cualquier remitente.
  3. Pulsa Ponerlo como primer relay DM y, arriba, Guardar.

Deja también un relay público en la lista, en segundo lugar: si tu servidor se cae, el correo sigue teniendo dónde esperar. relay.damus.io es buena segunda opción, porque también pregunta quién lee.

Paso 4: copia de seguridad cada noche

Herkos guarda su propia copia del correo que ya ha recogido, pero un sobre que llegó con la app cerrada solo existe en tu servidor hasta que abres Herkos. Una copia cada noche cubre ese hueco, y te deja rehacer el servidor si se estropea el disco o el proveedor te cierra la cuenta.

El relay lo guarda todo en una base de datos LMDB dentro del volumen de Docker nostr-relay_relay-db (el nombre empieza por la carpeta donde lo clonaste; compruébalo con docker volume ls). Un fichero LMDB copiado mientras el relay escribe puede no abrirse, así que el script para el relay los pocos segundos que tarda una copia local, lo vuelve a arrancar y solo entonces sube la copia. Mientras está parado, el correo espera en el relay público que dejaste segundo en la lista.

La copia sale del servidor con restic, que la cifra antes de enviarla. Llévala a un sitio de otro proveedor, no el del servidor: una cuenta SFTP (un storage box, un ordenador en casa) o un bucket compatible con S3.

  1. Instala las herramientas y crea el repositorio. Guarda también la contraseña en tu gestor de contraseñas: sin ella las copias no se pueden leer, y si solo vive en el servidor, se pierde con él. Con SFTP, root necesita además una clave SSH que acepte la máquina de copias (sudo ssh-keygen -t ed25519, y añadir allí /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. Guarda esto como /usr/local/bin/backup-relay y hazlo ejecutable (sudo chmod 700 /usr/local/bin/backup-relay). Cambia RELAY_DIR si no lo clonaste en /root/nostr-relay. Conserva los últimos 14 días, 8 semanas y 12 meses: un año hacia atrás, en un tamaño parecido al de la base de datos.

    #!/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. Ejecútalo una vez a mano (sudo /usr/local/bin/backup-relay) y prográmalo con sudo crontab -e. La segunda línea vuelve a leer cada mes una décima parte de lo guardado, cada vez una distinta, para comprobar que las copias se siguen pudiendo abrir. Mira de vez en cuando /var/log/backup-relay.log: una línea con Fatal quiere decir que la copia de esa noche falló.

    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
    

Para restaurar (un servidor nuevo, o tras perder el disco): vuelve a montar el relay (pasos 1 a 3) y repite los puntos 1 y 2 de este paso con el mismo repositorio, pero escribe en /root/.restic-password la contraseña que guardaste en vez de crear una nueva, y sáltate restic init. Después copia la última copia en el volumen del relay:

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

Una vez al año, haz esta restauración en una máquina de repuesto y comprueba que el relay arranca con tu correo dentro: es la única prueba que demuestra toda la cadena, contraseña incluida.

Conviene saber