Logotipo de Bitdoze

Cómo instalar Memos con Docker Compose: ¡PASOS FÁCILES!

Guía paso a paso para instalar Memos con Docker Compose usando SQLite o PostgreSQL. Autoaloja una app de notas centrada en la privacidad con el proxy inverso Traefik en minutos.

Dragos

Actualizado Publicado 16 min de lectura

Cómo instalar Memos con Docker Compose: ¡PASOS FÁCILES!

Memos es una app de notas autoalojada para la gestión del conocimiento personal. Es de código abierto (licencia MIT), funciona con Go + React y supera las 60.000 estrellas en GitHub en su v0.30.0 (julio de 2025). Usa SQLite por defecto, soporta Markdown de serie y funciona sin problemas con 1 CPU / 1 GB de RAM. Esta guía te lleva paso a paso por la instalación de Memos con Docker Compose usando SQLite o PostgreSQL, detrás de un proxy inverso Traefik con TLS automático.

¿Qué es Memos?

Memos es una aplicación de notas autoalojada centrada en la privacidad. Todos los datos permanecen en tu servidor. Sin dependencia de la nube, sin suscripción, sin rastreo. La interfaz es limpia: escribes Markdown, se renderiza en vivo y todo se sincroniza entre tus dispositivos a través de la interfaz web.

Funciones principales:

  • Soporte de Markdown con el nuevo editor CodeMirror 6 y barra de herramientas de formato (v0.30.0)
  • Arquitectura ligera: el backend en Go y el frontend en React mantienen bajo el uso de memoria
  • Interfaz personalizable: temas claro/oscuro, nombre del servidor, icono, descripción
  • Acceso multidispositivo desde cualquier navegador
  • Adjuntos guardados en el sistema de archivos por defecto desde la v0.27.0 (no dentro de la base de datos)
  • Código abierto bajo licencia MIT. Contribuye o haz un fork como quieras.

Si necesitas algo más completo para la documentación de equipo, consulta Cómo instalar Outline Wiki en Docker o Instalación de Docmost con Docker Compose.

Desde la publicación original, Memos ha añadido varias funciones que conviene conocer:

  • Web Clipper, extensión de navegador para Chrome y Firefox
  • Notas de voz con transcripción por IA mediante proveedores OpenAI o Gemini
  • Servidor MCP en /mcp para integración con clientes de IA (Model Context Protocol)
  • Editor CodeMirror 6 con barra de herramientas de formato estilo WYSIWYG
  • Diseños de feed en varias columnas: 1, 2 o 3 columnas más ajuste automático
  • Actualización en vivo por SSE: cambios en tiempo real sin polling
  • Webhooks estándar con firma HMAC-SHA256
  • Configuración gestionada por despliegue mediante archivos JSON en /etc/secrets para flujos de trabajo GitOps

Instala Memos con Docker Compose

Abajo tienes dos configuraciones completas: SQLite (la más simple, recomendada para uso personal) y PostgreSQL (para cuando ya usas Postgres o quieres copias de seguridad con pg_dump).

Monitoriza tu servidor

Después de desplegar Memos, configura la monitorización del servidor para vigilar CPU, memoria y disco. Consulta Cómo monitorizar los recursos del servidor y de Docker o instala Beszel y Uptime Kuma para tener un panel ligero.

Requisitos previos

Los precios de los VPS subieron en todos los proveedores en 2026 — si estás reconsiderando un servidor alquilado, mira qué cambió y cuándo gana un mini PC.

Puedes gestionar los stacks de Docker Compose con Dockge o cualquiera de los mejores paneles de servidores autoalojados.

Inicio rápido: Memos con SQLite

SQLite es el backend por defecto y la forma más sencilla de empezar. Un contenedor, un volumen y ningún servicio de base de datos que gestionar.

yaml
services:
  memos:
    image: neosmemo/memos:stable
    container_name: memos
    restart: unless-stopped
    networks:
      - traefik-net
    volumes:
      - ./memos:/var/opt/memos
    environment:
      MEMOS_DRIVER: sqlite
      MEMOS_PORT: 5230
      # Set this to your public URL to enable public mode.
      # Leave empty for private-only (no anonymous access, no RSS, no Explore).
      MEMOS_INSTANCE_URL: https://memos.yourdomain.com
      # MEMOS_LOG_LEVEL: debug  # Uncomment for troubleshooting
    labels:
      - traefik.enable=true
      - traefik.http.routers.memos.rule=Host(`memos.yourdomain.com`)
      - traefik.http.routers.memos.entrypoints=websecure
      - traefik.http.routers.memos.tls.certresolver=letsencrypt
      - traefik.http.services.memos.loadbalancer.server.port=5230

networks:
  traefik-net:
    external: true

Cambio importante en v0.30.0: modo privado por defecto

Desde Memos v0.30.0, dejar MEMOS_INSTANCE_URL vacío pone la instancia en modo solo privado. Los visitantes anónimos son redirigidos al inicio de sesión, RSS queda desactivado y Explorar se oculta. Define MEMOS_INSTANCE_URL con tu URL pública (por ejemplo, https://memos.yourdomain.com) si quieres memos públicos y feeds RSS.

Qué hace esto:

  • neosmemo/memos:stable descarga la última versión estable (actualmente v0.30.0)
  • El volumen ./memos:/var/opt/memos persiste todos los datos (base de datos + adjuntos) en el host
  • Las etiquetas de Traefik enrutan memos.yourdomain.com al puerto 5230 con TLS automático mediante tu cert resolver
  • El contenedor se ejecuta como non-root por defecto (UID 10001); no hace falta user: root

Si no usas Traefik (por ejemplo, Cloudflare Tunnel o acceso directo), sustituye el bloque labels por un mapeo de puertos:

yaml
ports:
  - 5230:5230

Elimina la sección networks si no usas una red externa de Traefik.

Memos con PostgreSQL

Usa PostgreSQL si ya lo ejecutas para otros servicios, si quieres soporte de copias de seguridad con pg_dump o si prefieres un backend de base de datos gestionado. MySQL también está soportado. Consulta la documentación de bases de datos de Memos para ver las cadenas de conexión.

Cuándo usar SQLite

  • Cero configuración, solo un archivo en disco
  • Ideal para uso personal en un solo nodo
  • Copia de seguridad = copiar el directorio de datos
  • Funciona en cualquier parte, sin servicio de base de datos que mantener
  • Opción por defecto y recomendada para la mayoría de usuarios

Cuándo usar PostgreSQL

  • Ya usas PostgreSQL para otros servicios
  • Quieres pg_dump para copias de seguridad estructuradas
  • Prefieres control operativo (replicación, monitorización)
  • Necesitas mejor gestión de la concurrencia con muchos adjuntos
  • Consulta Varias bases de datos PostgreSQL en UN servicio para compartir un solo contenedor de Postgres
yaml
services:
  memos:
    image: neosmemo/memos:stable
    container_name: memos
    restart: unless-stopped
    networks:
      - traefik-net
    depends_on:
      memos-db:
        condition: service_healthy
    volumes:
      - ./memos:/var/opt/memos
    environment:
      MEMOS_DRIVER: postgres
      MEMOS_DSN: postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@memos-db:5432/${POSTGRES_DB}?sslmode=disable
      MEMOS_PORT: 5230
      MEMOS_INSTANCE_URL: https://memos.yourdomain.com
    labels:
      - traefik.enable=true
      - traefik.http.routers.memos.rule=Host(`memos.yourdomain.com`)
      - traefik.http.routers.memos.entrypoints=websecure
      - traefik.http.routers.memos.tls.certresolver=letsencrypt
      - traefik.http.services.memos.loadbalancer.server.port=5230

  memos-db:
    image: postgres:16-alpine
    restart: unless-stopped
    networks:
      - traefik-net
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
      interval: 5s
      timeout: 5s
      retries: 5
    volumes:
      - ./memos-db:/var/lib/postgresql/data
    environment:
      POSTGRES_DB: ${POSTGRES_DB}
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}

networks:
  traefik-net:
    external: true

El depends_on con condition: service_healthy garantiza que Memos no arranque hasta que PostgreSQL acepte conexiones. El contenedor de PostgreSQL usa postgres:16-alpine para mantener una imagen de tamaño reducido.

Crea el archivo .env

La configuración con SQLite no necesita un archivo .env. Para PostgreSQL, crea un archivo .env en el mismo directorio que tu docker-compose.yml:

bash
POSTGRES_DB=memos
POSTGRES_USER=memos
POSTGRES_PASSWORD=change-me-to-a-strong-random-password

Cambia la contraseña por defecto

Genera una contraseña aleatoria antes de desplegar. Puedes usar openssl rand -base64 32 para crear una. No ejecutes PostgreSQL con una contraseña adivinable, ni siquiera en una red privada.

Inicia Memos

bash
docker compose up -d

Esto descarga las imágenes, crea los contenedores y arranca todo en segundo plano (detached).

Verifica que funciona

Después de docker compose up -d, confirma que todo está en buen estado:

bash
# Check container status — both should be "Up" and (for postgres) "healthy"
docker compose ps

# Check Memos logs for startup confirmation
docker compose logs memos
# Look for: "Server started at http://localhost:5230"

# Quick HTTP check
curl -I http://localhost:5230
# Expect: HTTP/1.1 200 OK

Si el contenedor se reinicia, revisa los logs con docker compose logs memos --tail 50 para ver los mensajes de error.

Accede a la interfaz de Memos

Abre https://memos.yourdomain.com en tu navegador. El primer usuario que crees será el administrador. Verás el feed principal de memos:

Panel de la app de notas autoalojada Memos

Desde la página de Ajustes puedes cambiar entre los temas claro y oscuro, gestionar usuarios, configurar SSO/OAuth2 (URL de callback: https://<instance>/auth/callback) y definir los backends de almacenamiento:

Página de ajustes de Memos con Docker Compose

Referencia de variables de entorno

Variable Propósito Valor por defecto
MEMOS_PORT Puerto HTTP de escucha 5230
MEMOS_DRIVER Backend de base de datos: sqlite, postgres, mysql sqlite
MEMOS_DSN Cadena de conexión a la base de datos Automática para SQLite
MEMOS_INSTANCE_URL URL pública; vacío = modo privado (vacío)
MEMOS_UID / MEMOS_GID Sobrescribir el UID/GID del contenedor 10001 / 10001
MEMOS_LOG_LEVEL debug, info, warn, error info

Consulta la documentación completa de variables de entorno para todas las opciones.

Copias de seguridad y actualización de Memos

Copias de seguridad

Las copias de seguridad dependen del backend de base de datos que uses. No te las saltes, sobre todo antes de actualizar.

SQLite:

bash
# Stop Memos for a consistent snapshot
docker compose stop memos
tar -czf memos-backup-$(date +%Y%m%d).tar.gz ./memos/
docker compose start memos

PostgreSQL:

bash
# No downtime needed — pg_dump is consistent
docker compose exec memos-db pg_dump -U memos memos > memos-dump-$(date +%Y%m%d).sql

Automatiza las copias de seguridad

Configura una tarea cron para ejecutar estos comandos a diario. Para mayor seguridad externa, sube los archivos de copia a un almacenamiento compatible con S3 (MinIO, Backblaze B2, Bunny Storage). Una copia olvidada es peor que una actualización fallida. Al menos con una copia puedes volver atrás.

Actualización

Memos publica versiones con frecuencia. Haz siempre una copia de seguridad primero y revisa el changelog por si hay cambios que rompen la compatibilidad.

bash
# 1. Backup (see above)
# 2. Pull the new image
docker compose pull
# 3. Recreate containers
docker compose up -d
# 4. Verify
docker compose logs memos
# Look for: "Server started at http://localhost:5230"

¿Actualizas desde una versión anterior a v0.30.0?

Memos v0.30.0 introdujo el modo privado por defecto. Si tu instancia era accesible públicamente, define MEMOS_INSTANCE_URL con tu URL pública en el archivo compose antes de actualizar. Si no, perderás el acceso anónimo, RSS y Explorar tras el reinicio. Revisa también en el changelog los requisitos de re-enlace de identidades SSO de la v0.28.0.

Después de actualizar, limpia las imágenes Docker antiguas para liberar espacio en disco. Consulta Cómo limpiar todas las imágenes Docker.

Solución de problemas

Permiso denegado en el volumen (discrepancia de UID/GID)

Memos v0.30.0 se ejecuta como UID 10001 por defecto. Si ves errores de permisos en los logs, puede que el directorio del volumen en el host pertenezca a un usuario distinto.

Opciones para arreglarlo:

  1. Define variables de entorno para sobrescribirlo: MEMOS_UID=1000 y MEMOS_GID=1000 (según tu usuario del host)
  2. O corrige la propiedad: chown -R 10001:10001 ./memos/

Consulta Cómo añadir usuarios a un contenedor Docker para más información sobre la gestión de usuarios en contenedores.

El contenedor no arranca tras una actualización

Revisa los logs en busca de errores de migración:

bash
docker compose logs memos --tail 100

Causas habituales:

  • La migración de la base de datos falló. Restaura la copia previa a la actualización y revisa el changelog para ver los cambios que rompen la compatibilidad.
  • MEMOS_INSTANCE_URL sin definir tras actualizar a v0.30.0 (no debería impedir el arranque, pero compruébalo)
  • PostgreSQL no está listo. Asegúrate de que el healthcheck pasa (docker compose ps debería mostrar “healthy” para memos-db).

Si necesitas volver atrás: docker compose down, restaura la copia de seguridad, fija la imagen a una etiqueta de versión concreta (por ejemplo, neosmemo/memos:0.29.0) y ejecuta docker compose up -d.

No se ven los memos públicos / RSS no funciona

Desde la v0.30.0, un MEMOS_INSTANCE_URL vacío pone la instancia en modo privado. Los visitantes anónimos son redirigidos al inicio de sesión, los feeds RSS dejan de estar disponibles y Explorar se oculta.

Solución: define MEMOS_INSTANCE_URL con tu URL pública completa en el entorno del compose:

yaml
environment:
  MEMOS_INSTANCE_URL: https://memos.yourdomain.com

Luego reinicia: docker compose up -d

Conexión rechazada a la base de datos (PostgreSQL)

Asegúrate de que el contenedor memos-db está saludable antes de que arranque Memos. La directiva depends_on: condition: service_healthy se encarga de esto, pero verifica:

bash
docker compose ps
# memos-db should show "healthy" in the STATUS column
docker compose logs memos-db
# Look for: "database system is ready to accept connections"

Comprueba también que las credenciales de tu .env coinciden entre el MEMOS_DSN de Memos y las variables POSTGRES_* de PostgreSQL.

Memos va lento o no responde

Memos es ligero. Funciona en una Raspberry Pi con 1 GB de RAM. Si va lento, casi seguro que el problema no es Memos.

Comprueba:

  • Recursos del servidor: docker stats memos para ver el uso de CPU/memoria
  • Espacio en disco: df -h. Un disco lleno provoca fallos de escritura.
  • Límites de recursos del contenedor: si definiste mem_limit o cpus en el compose, puede que sean demasiado bajos
  • Almacenamiento de adjuntos: si tienes muchos adjuntos grandes en un disco lento, las subidas se resienten

Consulta Cómo monitorizar los recursos del servidor y de Docker para una configuración de monitorización detallada.

Seguridad y endurecimiento para producción

Memos v0.30.0 se ejecuta como UID 10001 por defecto. No lo sobrescribas con user: root; no hay motivo para hacerlo. Pon Memos siempre detrás de un proxy inverso con TLS. Traefik + Let’s Encrypt es el camino recomendado. Nunca expongas el puerto 5230 directamente a internet.

Expón solo los puertos 80 y 443. Bloquea el acceso directo al 5230 desde fuera. Para instancias públicas, considera añadir el middleware de rate-limit de Traefik para evitar abusos.

Memos publica versiones con frecuencia. Suscríbete a las releases de GitHub y actualiza cada mes. Configura copias de seguridad diarias automáticas en un almacenamiento compatible con S3. Una copia local en el mismo disco es mejor que nada, pero no te salvará de un fallo de disco.

Endurece también tu servidor

Memos solo es tan seguro como el servidor donde se ejecuta. Protege tu VPS con CrowdSec y añade autenticación básica de Traefik como capa extra para las instancias privadas. Configura Beszel y Uptime Kuma para recibir alertas si Memos se cae.

Novedades de Memos v0.27 a v0.30

Si instalaste Memos antes de agosto de 2024, esto es lo que ha cambiado:

Versión Funciones clave
v0.27.0 Notas de voz, transcripción con IA (OpenAI/Gemini), servidor MCP en /mcp, actualización en vivo por SSE, menciones @username, almacenamiento de adjuntos en el sistema de archivos (nuevo valor por defecto)
v0.28.0 Re-enlace de identidades SSO (cambio que rompe la compatibilidad: los usuarios SSO existentes deben re-enlazar tras actualizar)
v0.29.0 Tarjetas de vista previa de enlaces, ajustes de correo de notificación por SMTP, página de atajos dedicada, nivel de log configurable, APIs de estadísticas de la instancia
v0.30.0 Web Clipper (Chrome + Firefox), editor CodeMirror 6 con barra de herramientas, diseños multicolumna, Webhooks estándar con firma HMAC, configuración gestionada por despliegue vía JSON en /etc/secrets, modo privado por defecto

El Web Clipper y el servidor MCP son las incorporaciones destacadas. El clipper te permite guardar páginas web directamente en Memos desde el navegador. El endpoint MCP hace que Memos sea accesible para clientes de IA compatibles con el Model Context Protocol.

Conclusiones

Configurar Memos con Docker Compose lleva menos de 10 minutos. SQLite es la opción por defecto por una razón: cero configuración, un volumen y listo. PostgreSQL añade controles operativos si los necesitas. En cualquier caso, haz copias de seguridad de tus datos y revisa el changelog antes de actualizar.

Si te interesa descubrir apps autoalojadas de código abierto, gratuitas e interesantes, puedes consultar la sección self hosted de toolhunt.net.

Para más herramientas autoalojadas y configuraciones de Docker, echa un vistazo a los mejores paneles de servidores autoalojados o explora la lista completa a continuación.

Explora más contenedores Docker