Notas que se autodestruyen: cómo terminé desplegando Enclosed
Notas que se autodestruyen: cómo terminé desplegando Enclosed
Estaba buscando una forma segura de compartir datos sensibles sin dejarlos disponibles para siempre. Quería algo parecido a esos mensajes de Misión Imposible que se destruían solos después de unos minutos. No necesitaba una plataforma corporativa. Necesitaba algo simple: enviar un dato delicado, permitir que la otra persona lo leyera y hacer que luego desapareciera.
En medio de esa búsqueda, un compañero me comentó que había leído sobre un software pensado exactamente para eso. Esa conversación me llevó a revisar Enclosed, y de ahí a implementarlo para este proyecto.
Enclosed no intenta ser una suite de colaboración ni un gestor documental. Sirve para enviar notas privadas con cifrado de extremo a extremo, contraseña opcional, tiempo de expiración y destrucción tras lectura. El servidor almacena el contenedor cifrado, no el contenido en texto plano. Con eso ya resolvía buena parte del problema.
El tipo de herramienta que estaba buscando
Cuando uno comparte información sensible suele terminar usando herramientas que no fueron diseñadas para eso. Un chat, un correo, un documento compartido, una nota en la nube. Funcionan, sí, pero dejan demasiados rastros. El dato queda en un historial, en una bandeja, en una carpeta, o en un enlace que alguien puede reenviar meses después.
Por eso el enfoque de Enclosed me pareció claro. En lugar de preguntarse cómo compartir más cosas, se pregunta cómo compartirlas por menos tiempo. En muchos casos, la seguridad no depende solo del cifrado, sino también de reducir cuánto permanece disponible el dato.
Enclosed trabaja justamente ahí:
- cifra el contenido en el lado del cliente;
- permite definir un TTL para la nota;
- puede destruir la nota después de la primera lectura;
- admite contraseña adicional;
- y se puede alojar de forma propia.
Para un proyecto donde la privacidad importa, esa combinación tiene bastante sentido.
La primera decisión: alojarlo yo mismo
Después de revisar el proyecto, la pregunta ya no fue si usarlo, sino dónde desplegarlo. La documentación plantea dos caminos razonables: levantarlo en un VPS con Docker o usar Cloudflare Workers como alternativa serverless.
Mi primera opción fue un VPS con Docker. No porque fuera la alternativa más moderna, sino porque me daba más control. Si el objetivo era compartir información sensible, también tenía sentido cuidar dónde quedaban los datos, cómo se hacían los respaldos y qué piezas de infraestructura dependían de mí.
La arquitectura que terminé considerando era bastante limpia:
Internet -> Nginx con HTTPS -> Enclosed -> volumen persistente para datos
No había demasiada magia: un contenedor para la aplicación, un proxy inverso delante y almacenamiento persistente para que las notas no se perdieran al reiniciar el servicio. Esa sencillez fue parte de su atractivo.
El despliegue en VPS: simple, pero bien hecho
El recorrido empezó como casi todos los despliegues pequeños: preparando el servidor. En este caso, la base era una distro Linux con Docker Engine y el plugin de Docker Compose. Lo importante no era instalar Docker, sino dejar el entorno listo para que Enclosed no quedara expuesto de forma improvisada.
La primera prueba se podía hacer con un docker run muy corto, suficiente para confirmar que la aplicación levantaba y escuchaba en el puerto 8787:
docker run -d \
--name enclosed \
--restart unless-stopped \
-p 8787:8787 \
corentinth/enclosed
Eso servía para validar que todo funcionaba, pero era solo una prueba. Para un uso real, el siguiente paso natural era montar persistencia y pasar a docker compose, porque ahí el despliegue se vuelve más legible y más fácil de mantener.
La configuración base quedaba así:
services:
enclosed:
image: corentinth/enclosed:latest
container_name: enclosed
restart: unless-stopped
ports:
- "127.0.0.1:8787:8787"
volumes:
- enclosed-data:/app/.data
environment:
- PORT=8787
- AUTHENTICATION_JWT_SECRET=CAMBIA_ESTE_VALOR
- PUBLIC_IS_AUTHENTICATION_REQUIRED=false
- PUBLIC_DEFAULT_NOTE_TTL_SECONDS=86400
- TASK_DELETE_EXPIRED_NOTES_ENABLED=true
volumes:
enclosed-data:
driver: local
De esta etapa me gustó que el despliegue no pedía una pila enorme. También que varias decisiones importantes quedaban explícitas en variables de entorno: el secreto JWT, el tiempo por defecto de expiración, si se exigiría autenticación y si la limpieza de notas expiradas quedaría activada.
Ahí Enclosed deja de ser una aplicación curiosa y empieza a sentirse como una herramienta usable.
Cuando la seguridad deja de ser discurso y se vuelve configuración
Una vez que el contenedor estaba en pie, el punto delicado ya no era la aplicación, sino la exposición del servicio. Si iba a usarse para compartir información sensible, no tenía sentido dejarlo colgando directamente por HTTP.
Por eso el siguiente movimiento fue colocar Nginx por delante y emitir certificados con Let’s Encrypt. Ese paso, aunque estándar, era clave porque convertía un experimento funcional en un servicio listo para usarse.
La idea era mantener Enclosed escuchando solo en localhost y dejar que Nginx se encargara del acceso externo, del redireccionamiento a HTTPS y del encabezado correcto hacia el backend.
Un bloque como este resolvía la parte central:
server {
listen 443 ssl http2;
server_name notas.tudominio.com;
ssl_certificate /etc/letsencrypt/live/notas.tudominio.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/notas.tudominio.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:8787;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
En este punto el proyecto ya tenía forma: una URL propia, tráfico cifrado y un backend limitado a lo necesario.
Lo que más termina importando: expiración, acceso y tamaño
Cuando una herramienta está pensada para privacidad, los detalles pesan. Enclosed tiene varios, pero tres me parecieron especialmente importantes.
El primero es el TTL por defecto. Si el servicio iba a usarse para compartir datos temporales, tenía sentido que la caducidad viniera activada desde el inicio, no como una opción que alguien podría olvidar. En mi caso, 86400 segundos, es decir un día, era una base razonable para notas operativas.
El segundo es la posibilidad de exigir autenticación para crear notas. Dependiendo del proyecto, eso puede marcar una gran diferencia. Si se activa PUBLIC_IS_AUTHENTICATION_REQUIRED=true, la aplicación deja de ser un buzón público y pasa a ser un servicio controlado por usuarios autorizados.
El tercero es el tamaño máximo del payload cifrado. No solo porque define si la herramienta servirá para texto o para adjuntos, sino porque obliga a pensar el alcance real del servicio. Eso también me gustó: Enclosed invita a acotar el caso de uso. No intenta ser Dropbox. Intenta ser un mecanismo seguro para compartir algo puntual.
La alternativa que también tiene sentido: Cloudflare Workers
Mientras avanzaba con la opción del VPS, me pareció útil revisar la otra posibilidad: Cloudflare Workers con KV como almacenamiento. La ventaja es obvia. No hay que administrar servidor, actualizaciones del sistema, Nginx ni certificados. El servicio se despliega sobre la infraestructura de Cloudflare y queda disponible con un costo muy bajo o incluso nulo en escenarios pequeños.
Conceptualmente, la arquitectura se reduce mucho:
Usuario -> Cloudflare Workers -> KV Namespace
El despliegue también es bastante directo. Se crea el namespace KV, se configura wrangler.toml, se compila el proyecto y se publica.
name = "enclosed"
main = "packages/app-server/dist/cloudflare/worker.js"
compatibility_date = "2024-01-01"
[[kv_namespaces]]
binding = "notes"
id = "<ID_DEL_NAMESPACE>"
[vars]
STORAGE_DRIVER_CLOUDFLARE_KV_BINDING = "notes"
PUBLIC_IS_AUTHENTICATION_REQUIRED = "false"
Lo veo como una buena opción para pruebas, uso personal o equipos pequeños que quieran desplegar rápido y mantener poco.
Ahora bien, si la prioridad del proyecto está en la soberanía de datos, el VPS sigue teniendo ventaja. En Cloudflare hay una limitación además importante: la limpieza periódica automática de notas expiradas no está disponible de la misma manera que en Node/VPS. No es un detalle menor si uno está construyendo precisamente alrededor de la idea de caducidad.
Con cuál me quedaría
Si alguien me preguntara hoy por cuál camino empezar, respondería así.
Si el proyecto necesita salir rápido, tiene poco tráfico y no exige demasiadas garantías de control sobre la infraestructura, Cloudflare es una alternativa elegante.
Si el proyecto toca información sensible, si importa el control del entorno o si se quiere una operación más predecible, un VPS con Docker y Nginx sigue siendo el mejor camino.
En mi caso, la historia empezó con una necesidad concreta: compartir datos sensibles sin dejarlos flotando indefinidamente. Terminó en una implementación que me convenció porque no intentaba resolver más de lo necesario.
Enclosed hace una cosa, y la hace bien: tomar una nota privada, cifrarla, compartirla y dejar que desaparezca cuando ya cumplió su propósito.
Eso era lo que estaba buscando desde el principio: un pequeño mensaje de Misión Imposible, pero corriendo en mi propia infraestructura.
Recursos
- Repositorio oficial: CorentinTh/enclosed
- Documentación: docs.enclosed.cc