Ir al contenido

Despliegue con Docker ​

Mindwtr ofrece compatibilidad oficial con Docker para ejecutar:

  • mindwtr-app: La compilación web/PWA de escritorio, servida por Nginx.
  • mindwtr-cloud: El servidor ligero de sincronización y la API REST de automatización de tareas.

Están disponibles como imágenes de Docker y se pueden orquestar fácilmente mediante Docker Compose.


Inicio rápido (Docker Compose) ​

No necesitas clonar el repositorio. Las imágenes oficiales se publican en GHCR, y el archivo compose.yaml las descarga por ti.

  1. Descarga el archivo compose:

    bash
    curl -LO https://raw.githubusercontent.com/dongdongbh/Mindwtr/main/docker/compose.yaml
  2. Crea un archivo .env junto a él (Docker Compose lo lee automáticamente):

    dotenv
    MINDWTR_CLOUD_AUTH_TOKENS=your_token_here
    MINDWTR_CLOUD_CORS_ORIGIN=http://localhost:5173

    MINDWTR_CLOUD_CORS_ORIGIN debe coincidir exactamente con la dirección en la que abres la PWA en tu navegador, incluidos el esquema y el puerto. http://localhost:5173 solo funciona si el navegador se ejecuta en el propio host de Docker. Desde otro equipo, usa la dirección del host, por ejemplo http://192.168.1.20:5173. Solo se puede definir un origen.

  3. Descarga e inicia los servicios:

    bash
    docker compose pull
    docker compose up -d
  4. Accede a los servicios:

    • PWA (aplicación web): Abre http://localhost:5173 en tu navegador.
    • Comprobación de disponibilidad de Cloud: Abre http://localhost:8787/health.
    • Comprobación de almacenamiento de Cloud: Abre http://localhost:8787/ready.
    • URL autoalojada para pruebas locales: http://localhost:8787
    • URL base de la API REST: http://localhost:8787/v1

/health solo indica que el servidor cloud responde a las solicitudes HTTP. /ready comprueba además que el directorio de datos configurado se pueda escribir, así que es el que debes consultar para saber si el servidor puede guardar tus datos. Compose usa la comprobación de estado incluida en la imagen: las imágenes actuales comprueban /ready y las antiguas, /health.

Si prefieres compilar las imágenes desde el código fuente, clona el repositorio y ejecuta docker compose -f docker/compose.yaml up --build -d desde su raíz. Consulta Compilación manual más abajo.

Este archivo Compose predeterminado usa únicamente HTTP y está pensado para pruebas locales o privadas. Los clientes de escritorio y móviles de Mindwtr solo aceptan HTTP para destinos locales o privados reconocidos, como localhost, 127.0.0.1, 10.x.x.x, desde 172.16.x.x hasta 172.31.x.x, 192.168.x.x, direcciones IPv6 de bucle local o privadas, *.local y *.home.arpa.

Para URL públicas, nombres DNS personalizados, nombres de host de VPN, Tailscale, ZeroTier o cualquier nombre que no se reconozca como local o privado, usa HTTPS, o activa Permitir conexiones inseguras (HTTP) en los ajustes de sincronización de la app para aceptar ese nombre de host por HTTP sin cifrar. Los datos viajan entonces sin cifrar, así que úsala solo en una red de confianza.


Configuración de HTTPS con Caddy ​

Para la sincronización pública desde equipos de escritorio o dispositivos móviles, usa el archivo Compose respaldado por Caddy:

bash
cp docker/.env.https.example docker/.env.https.local

Edita docker/.env.https.local:

dotenv
MINDWTR_CLOUD_DOMAIN=mindwtr.example.com
MINDWTR_CLOUD_AUTH_TOKENS=your_long_random_token
MINDWTR_CLOUD_CORS_ORIGIN=https://mindwtr.example.com
MINDWTR_CADDYFILE=Caddyfile.https

Inicia el conjunto de servicios:

bash
docker compose --env-file docker/.env.https.local -f docker/compose.https.yaml up -d

Comprueba el servidor:

bash
curl https://mindwtr.example.com/health
curl https://mindwtr.example.com/ready

En Ajustes de Mindwtr -> Sincronización -> Autoalojado, establece la URL autoalojada en:

text
https://mindwtr.example.com

Mindwtr añadirá /v1/data automáticamente.

HTTPS público ​

Usa Caddyfile.https cuando MINDWTR_CLOUD_DOMAIN sea un nombre DNS público que apunte a este host de Docker. Los puertos 80 y 443 deben ser accesibles para la emisión automática de certificados. Caddy obtiene y renueva el certificado, y actúa como proxy inverso de las solicitudes hacia mindwtr-cloud.

HTTPS solo para LAN ​

Usa Caddyfile.local-https cuando el nombre de host solo se resuelva en tu red doméstica:

dotenv
MINDWTR_CLOUD_DOMAIN=mindwtr.home.arpa
MINDWTR_CLOUD_CORS_ORIGIN=https://mindwtr.home.arpa
MINDWTR_CADDYFILE=Caddyfile.local-https

Esto usa la autoridad de certificación interna de Caddy. Cada dispositivo cliente debe confiar en el certificado raíz local de Caddy antes de que Mindwtr acepte la conexión HTTPS. Mindwtr 1.2.0 y posteriores confían en las autoridades instaladas por el usuario en Android; en iPhone y iPad también hay que instalar el certificado raíz y activar explícitamente la confianza total. Los certificados públicos de Let's Encrypt siguen siendo la opción más sencilla cuando el nombre de host es accesible públicamente.

Después de iniciar el conjunto de servicios solo para LAN, exporta el certificado raíz local de Caddy:

bash
docker compose --env-file docker/.env.https.local -f docker/compose.https.yaml cp caddy:/data/caddy/pki/authorities/local/root.crt ./mindwtr-caddy-root.crt

Instala ese certificado como raíz de confianza en cada dispositivo que vaya a sincronizarse con este nombre de host.


Configuración ​

Token de sincronización ​

El servidor en la nube requiere un token para la autenticación. Debes establecerlo en las variables de entorno.

En docker/compose.yaml (o mediante una variable de entorno), establece:

yaml
MINDWTR_CLOUD_AUTH_TOKENS=your_token_here

MINDWTR_CLOUD_TOKEN sigue siendo compatible por retrocompatibilidad, pero está obsoleto.

Para usar un secreto de Docker basado en archivo, quita MINDWTR_CLOUD_AUTH_TOKENS de tu archivo .env, guarda el token en un archivo del host que solo pueda leer su propietario e inicia Compose con la superposición docker/compose.secrets.yaml. MINDWTR_CLOUD_AUTH_TOKENS_FILE_HOST debe ser una ruta absoluta del host:

bash
printf '%s\n' 'replace_with_a_token_at_least_20_characters_long' > /absolute/path/mindwtr-cloud-tokens
chmod 600 /absolute/path/mindwtr-cloud-tokens
MINDWTR_CLOUD_AUTH_TOKENS_FILE_HOST=/absolute/path/mindwtr-cloud-tokens \
  docker compose -f docker/compose.yaml -f docker/compose.secrets.yaml up -d

La superposición monta ese archivo en modo de solo lectura en /run/secrets/mindwtr_cloud_tokens y define MINDWTR_CLOUD_AUTH_TOKENS_FILE por ti, de modo que el token nunca llega al entorno de Compose generado. Mantén el archivo del host con permisos 0600. El servidor sigue negándose a arrancar si ni la opción escrita directamente ni un archivo de token legible aportan un token válido.

La misma superposición funciona con el conjunto HTTPS de Caddy. Quita el token escrito directamente en docker/.env.https.local y ejecuta:

bash
MINDWTR_CLOUD_AUTH_TOKENS_FILE_HOST=/absolute/path/mindwtr-cloud-tokens \
  docker compose --env-file docker/.env.https.local \
    -f docker/compose.https.yaml -f docker/compose.secrets.yaml up -d

Generar un token: Puedes generar un token aleatorio seguro con:

bash
cat /dev/urandom | LC_ALL=C tr -dc 'a-zA-Z0-9' | fold -w 50 | head -n 1

Configuración del cliente ​

Para conectar tus clientes de Mindwtr (de escritorio o móviles) a esta nube autoalojada:

  1. Ve a Ajustes → Sincronización.
  2. Selecciona Autoalojado (o Cloud).
  3. Establece la URL autoalojada en el endpoint base de tu servidor:
    http://localhost:8787
    Mindwtr añadirá /v1/data automáticamente a esta URL.
  4. Introduce el mismo token que configuraste en MINDWTR_CLOUD_AUTH_TOKENS.

Para HTTP en una LAN privada, usa una dirección local o privada como http://192.168.1.20:8787. Para URL públicas, usa la configuración HTTPS con Caddy descrita arriba.

Preconfigurar los ajustes de sincronización de la aplicación web ​

Un navegador nuevo que abra la PWA puede llegar con la URL de la nube ya rellenada, de modo que solo haya que introducir el token:

  • Mismo dominio (recomendado): cuando la aplicación y la API de la nube comparten un dominio (como en la configuración HTTPS con Caddy), la aplicación web detecta la nube en su propio origen automáticamente. Nada que configurar.
  • Dominios separados: define MINDWTR_DEFAULT_CLOUD_URL en el contenedor mindwtr-app con la URL pública de la nube, por ejemplo en Kubernetes o en cualquier despliegue donde la aplicación y la API vivan en hosts distintos.

El valor solo rellena el formulario de configuración. Nunca sobrescribe una URL ya configurada, y la sincronización sigue desactivada hasta que la persona guarde con su token.

Restringir quién puede abrir la aplicación web alojada ​

La versión para navegador es un paquete estático, y los datos que muestra viven solo en el almacenamiento de cada navegador; los datos de tareas y la API están protegidos por el token bearer en /v1/*. Por eso Mindwtr no tiene pantalla de inicio de sesión propia. Si la aplicación web es accesible desde internet y no quieres que desconocidos la abran, pon HTTP Basic Auth en el proxy que la precede, en todas las rutas excepto /v1/*, de modo que los navegadores inicien sesión una vez mientras las aplicaciones de escritorio y móvil siguen usando su token bearer. Con el Caddy incluido, genera un hash con caddy hash-password y usa:

example.com {
	@ui not path /v1/*
	basic_auth @ui {
		alice <bcrypt hash>
	}
	handle /v1/* {
		reverse_proxy mindwtr-cloud:8787
	}
	handle {
		reverse_proxy mindwtr-app:5173
	}
}

Con nginx, pon auth_basic en el bloque location / y deja location /v1/ sin él. Mantén MINDWTR_CLOUD_AUTH_TOKENS y MINDWTR_CLOUD_CORS_ORIGIN configurados como se describe arriba; son lo que protege los datos, el inicio de sesión del proxy solo decide quién puede cargar la página.

Sincronización con Dropbox y la PWA de Docker ​

La imagen de Docker mindwtr-app sirve la compilación para navegador/PWA. La sincronización OAuth nativa con Dropbox no está disponible en este entorno de ejecución porque la conexión con Dropbox está implementada por las aplicaciones nativas de escritorio y móviles. Añadir VITE_DROPBOX_APP_KEY o DROPBOX_APP_KEY mediante .env, env_file, el entorno de ejecución de Compose o un argumento de compilación de Docker no habilitará Dropbox en Docker.

Para la sincronización alojada en Docker, usa el servidor en la nube autoalojado incluido o WebDAV. Si el endpoint autoalojado está detrás de Authelia u otro proxy SSO interactivo, configura el proxy para permitir que la ruta de sincronización/API de Mindwtr use directamente el token de portador de Mindwtr; la aplicación móvil no puede completar un inicio de sesión de Authelia en el navegador delante de /v1/data.

Recordatorios en la PWA de Docker ​

Los recordatorios de tareas y de fechas de inicio, vencimiento y revisión también se muestran en la versión del navegador, como notificaciones web. Concede permiso de notificaciones al sitio (Ajustes → Notificaciones) y deja abierta una pestaña de Mindwtr: la versión del navegador no tiene servicio en segundo plano, así que los recordatorios solo se entregan mientras haya una pestaña en ejecución. Una pestaña en segundo plano ve limitados sus temporizadores, por lo que un recordatorio puede llegar hasta un minuto tarde, y el que venza con todas las pestañas cerradas se omite en lugar de entregarse después. Para recordatorios que sobrevivan a un navegador cerrado, usa la aplicación de escritorio o móvil.

API de automatización de tareas ​

El mismo contenedor mindwtr-cloud también expone la API REST para automatizar tareas. Usa la misma URL base y el mismo token de portador que la sincronización.

Endpoints habituales:

  • GET /v1/data y PUT /v1/data para la sincronización
  • GET /v1/tasks y POST /v1/tasks para enumerar y crear tareas
  • GET /v1/projects para los proyectos
  • GET /v1/search?query=... para buscar tareas y proyectos

Ejemplo:

bash
curl -X POST http://localhost:8787/v1/tasks \
  -H "Authorization: Bearer your_token_here" \
  -H "Content-Type: application/json" \
  -d '{"input":"Review PR @work /due:tomorrow"}'

Origen CORS (producción) ​

El servidor en la nube usa http://localhost:5173 como valor predeterminado para CORS. Para producción, establece:

yaml
MINDWTR_CLOUD_CORS_ORIGIN=https://your-app-domain.example

Persistencia de datos ​

Para mantener a salvo tus datos en la nube entre reinicios de los contenedores, debes montar un volumen para el directorio de datos.

En tu compose.yaml:

yaml
volumes:
  - ./data:/app/cloud_data

Compilación manual ​

Si prefieres compilar las imágenes tú mismo sin Compose:

Compilar la PWA:

bash
docker build -f docker/app/Dockerfile -t mindwtr-app .

Compilar el servidor en la nube:

bash
docker build -f docker/cloud/Dockerfile -t mindwtr-cloud .

GitHub Actions y GHCR ​

El proyecto incluye un flujo de trabajo de GitHub Actions que compila y publica imágenes automáticamente en GitHub Container Registry (GHCR).

Imágenes oficiales:

  • ghcr.io/dongdongbh/mindwtr-app:latest
  • ghcr.io/dongdongbh/mindwtr-cloud:latest

Las compilaciones preliminares están disponibles con la etiqueta flotante beta, que siempre apunta a la versión más reciente (candidata o estable), o se pueden fijar por versión, por ejemplo, ghcr.io/dongdongbh/mindwtr-app:1.2.0-rc.1. latest siempre permanece en la versión estable. Consulta Únete a los canales beta para conocer las demás plataformas.

El archivo docker/compose.yaml está configurado para usar estas imágenes de forma predeterminada, lo que facilita obtener la versión más reciente sin compilarla localmente.


Notas técnicas ​

  • Servicio de la PWA: La aplicación web usa renderizado del lado del cliente. El contenedor Nginx está configurado con try_files para redirigir todas las solicitudes a index.html, lo que evita errores 404 al actualizar la página.
  • Imagen base: La compilación usa Bun (fijado en v1.3) e incluye las opciones de C++20 que requiere better-sqlite3.

Mindwtr es gratuito, de código abierto y local-first.
Getting Things Done y GTD son marcas registradas de David Allen Company. Mindwtr no está afiliado, respaldado ni patrocinado por David Allen Company.