¿Por qué HedgeDoc en lugar de Notion o Google Docs?
Notion y Google Docs tienen cada uno sus ventajas, pero ambos alojan sus datos en sus servidores, imponen sus formatos propietarios y pueden modificar sus tarifas o condiciones sin previo aviso. Para un equipo técnico que documenta arquitecturas, redacta documentación de API, prepara RFC o gestiona actas de reunión, HedgeDoc ofrece una alternativa radicalmente distinta:
- Markdown nativo con renderizado en tiempo real en el editor y vista previa a pantalla dividida.
- Edición colaborativa con varios cursores visibles de forma simultánea.
- Bloques de código con resaltado de sintaxis para más de 200 lenguajes.
- Diagramas integrados: Mermaid, PlantUML, Vega-lite y flowcharts directamente en la nota.
- Fórmulas matemáticas: LaTeX mediante MathJax.
- Exportación: PDF, Markdown y HTML con un clic desde la interfaz.
- Alojamiento en su VPS: sus datos no salen de su infraestructura.
Requisitos previos antes de empezar
- Un VPS con Ubuntu 22.04 o Debian 12 y 1 GB de RAM como mínimo (512 MB pueden bastar para pruebas, pero se recomienda 1 GB para la colaboración simultánea).
- Docker Engine ≥ 24 y Docker Compose V2 instalados.
- Un nombre de dominio apuntando a su VPS para configurar TLS (obligatorio en producción: HedgeDoc utiliza WebSockets, que requieren una conexión segura).
- El puerto 3000 disponible (HedgeDoc escucha en ese puerto de forma predeterminada).
- Nginx instalado para el reverse proxy (con soporte WebSocket: imprescindible).
Instalación de HedgeDoc con Docker Compose
Paso 1 — Crear la estructura del proyecto
mkdir -p /opt/hedgedoc && cd /opt/hedgedocCree el archivo
docker-compose.yml:version: '3.8' services: database: image: postgres:15-alpine environment: POSTGRES_USER: hedgedoc POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_DB: hedgedoc volumes: - db-data:/var/lib/postgresql/data restart: unless-stopped healthcheck: test: ['CMD-SHELL', 'pg_isready -U hedgedoc'] interval: 10s timeout: 5s retries: 5 app: image: quay.io/hedgedoc/hedgedoc:1.11.1 environment: CMD_DB_URL: postgres://hedgedoc:${POSTGRES_PASSWORD}@database/hedgedoc CMD_DOMAIN: ${CMD_DOMAIN} CMD_PROTOCOL_USESSL: 'true' CMD_SESSION_SECRET: ${CMD_SESSION_SECRET} CMD_ALLOW_ANONYMOUS: 'false' CMD_ALLOW_REGISTRATION: 'true' CMD_ALLOW_FREEURL: 'true' volumes: - uploads:/hedgedoc/public/uploads ports: - '127.0.0.1:3000:3000' depends_on: database: condition: service_healthy restart: unless-stopped volumes: db-data: uploads:Paso 2 — Crear el archivo de entorno
cat > /opt/hedgedoc/.env << 'EOF' POSTGRES_PASSWORD=CONTRASENA_SEGURA_AQUI CMD_DOMAIN=hedgedoc.sudominio.com CMD_SESSION_SECRET=UNA_CADENA_ALEATORIA_LARGA_Y_FIJA EOF⚠️
CMD_SESSION_SECRETdebe ser un valor fijo, generado una sola vez y que nunca cambie. Si lo modifica después del primer arranque, todas las sesiones existentes quedarán invalidadas. Genérelo con:openssl rand -base64 32Paso 3 — Levantar los contenedores
docker compose up -dCompruebe que ambos contenedores están operativos:
docker compose ps docker compose logs appHedgeDoc migrará automáticamente la base de datos PostgreSQL en el primer arranque. En cuanto los registros muestren
listening on port 3000, la aplicación está lista.Paso 4 — Configurar Nginx con soporte WebSocket
⚠️ La configuración de Nginx para HedgeDoc debe incluir un bloque
/socket.io/con las cabeceras WebSocket adecuadas. Omitir ese bloque provoca fallos silenciosos de la colaboración en tiempo real: las notas se abren, pero los cambios de los demás usuarios no aparecen.apt install -y nginx certbot python3-certbot-nginx cat > /etc/nginx/sites-available/hedgedoc << 'EOF' server { server_name hedgedoc.sudominio.com; location / { proxy_pass http://127.0.0.1:3000; 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; } location /socket.io/ { proxy_pass http://127.0.0.1:3000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } } EOF ln -s /etc/nginx/sites-available/hedgedoc /etc/nginx/sites-enabled/ certbot --nginx -d hedgedoc.sudominio.com nginx -t && systemctl reload nginxPaso 5 — Crear la primera cuenta de usuario
Abra su navegador en
https://hedgedoc.sudominio.com. En la página de inicio, haga clic en Sign In → Register para crear su primera cuenta de administrador.Si ha definido
CMD_ALLOW_REGISTRATION: 'false', puede crear la primera cuenta desde la CLI:docker compose exec app npm run manage_users -- --add [email protected] --password SuContrasenaUna vez conectado, haga clic en New note para crear su primera nota colaborativa.
Funcionalidades que conviene descubrir
Compartir una nota: cada nota de HedgeDoc tiene una URL única. Haga clic en el botón de compartir para obtener la URL y elija el modo de acceso (solo lectura, comentarios, edición). Envíe la URL a sus colaboradores: pueden editar sin cuenta si usted lo autoriza.
Insertar un diagrama Mermaid:
graph LR
A[Cliente] --> B[API]
B --> C[Base de datos]
C --> D[Cache Redis]HedgeDoc renderiza el diagrama en tiempo real en la vista previa.
Exportar la nota: en el menú (icono ≡), elija Export para descargarla en Markdown, HTML o PDF. La exportación a PDF utiliza un navegador headless en el servidor: requiere que Chromium esté disponible, algo que la imagen Docker oficial ya incluye.
Modo presentación: añada --- entre las secciones para convertirlas en diapositivas. En el menú, elija Slide Mode para pasar a presentación a pantalla completa.
Bloque Socket.io ausente = colaboración rota en silencio
Es la trampa más frecuente con HedgeDoc detrás de Nginx. Síntoma: la interfaz se muestra con normalidad, usted puede escribir en la nota, pero las modificaciones de los demás usuarios no aparecen en tiempo real, sin ningún mensaje de error visible.
Causa: la ruta /socket.io/ necesita una conexión WebSocket (protocolo ws:// o wss://). Sin el bloque de Nginx dedicado que envía las cabeceras Upgrade: websocket y Connection: upgrade, Nginx trata la petición como HTTP clásico y la conexión en tiempo real falla en silencio.
Comprobación rápida:
# Desde su equipo, compruebe que el WebSocket es accesible
curl -v -N -H "Connection: Upgrade" -H "Upgrade: websocket" \
https://hedgedoc.sudominio.com/socket.io/?transport=websocketDebe ver 101 Switching Protocols en la respuesta. Un 200 o un 400 indica que el bloque /socket.io/ falta o está mal configurado.
Proxy sin barra final = página en blanco o error 404
En la directiva proxy_pass de Nginx, la presencia o la ausencia de la barra final cambia el comportamiento:
# CORRECTO — sin barra final (HedgeDoc gestiona sus propias rutas)
proxy_pass http://127.0.0.1:3000;
# INCORRECTO — la barra final hace que Nginx reescriba la ruta
proxy_pass http://127.0.0.1:3000/;Con una barra final, una petición a /s/mi-nota se convierte en una petición a /s/mi-nota en un contexto distinto, lo que rompe las redirecciones y el enrutamiento interno de HedgeDoc. Resultado: página en blanco o error 404 en las notas. Omita siempre la barra final en proxy_pass cuando configure HedgeDoc.
HedgeDoc vs Notion vs Confluence
Desplace la tabla
| Criterio | HedgeDoc (self-hosted) | Notion | Confluence (Cloud) |
|---|---|---|---|
| Precio | Gratis (coste del VPS) | Gratis hasta 10 miembros, ~10 $/miembro/mes | ~5.75 $/usuario/mes (mín. 10) |
| Formato | Markdown nativo | Bloques propietarios | Editor enriquecido (WYSIWYG) |
| Colaboración en tiempo real | Sí (WebSocket) | Sí | Sí |
| Diagramas nativos | Mermaid, PlantUML, Vega-lite | Limitado (mediante integraciones) | Mediante macros (Confluence) |
| Bloques de código | Más de 200 lenguajes con resaltado | Sí (limitado) | Sí (mediante plugin) |
| Alojamiento de los datos | Su VPS | Servidores de Notion (EE. UU.) | Servidores de Atlassian |
| Exportación a Markdown | Sí (nativa) | Parcial (importación/exportación) | No nativa |
| Fórmulas LaTeX | Sí (MathJax) | Sí | Mediante plugin |
| Modo presentación | Sí (integrado) | No | Mediante plugin |
Gestionar los usuarios y los permisos
HedgeDoc gestiona tres niveles de acceso por nota, definidos en el menú de cada nota:
- Freely: cualquiera puede editar, sin cuenta.
- Editable: solo los usuarios conectados pueden editar.
- Limited: solo el propietario puede editar; los demás pueden comentar.
- Locked: solo lectura para todos salvo el propietario.
- Private: accesible únicamente para el propietario.
Desactivar el registro público:
Si su instancia es pública, un desconocido podría crear una cuenta. Para reservar el acceso a su equipo, defina CMD_ALLOW_REGISTRATION: 'false' en .env y vuelva a crear el contenedor (docker compose up -d --force-recreate app). Después, cree las cuentas desde la CLI.
Activar la autenticación OAuth (GitHub, GitLab…):
HedgeDoc admite OAuth2 para GitHub, GitLab, Google, Twitter y varios proveedores más. Configure las variables CMD_GITHUB_CLIENTID / CMD_GITHUB_CLIENTSECRET en .env después de crear una OAuth App en GitHub.
Copias de seguridad y actualizaciones
Guardar los datos:
# Copia de seguridad de PostgreSQL
docker compose exec -T database \
pg_dump -U hedgedoc hedgedoc | gzip > /opt/hedgedoc/backups/hedgedoc-$(date +%Y%m%d).sql.gz
# Copia de seguridad de los archivos subidos (imágenes, adjuntos)
tar czf /opt/hedgedoc/backups/uploads-$(date +%Y%m%d).tar.gz \
-C /opt/hedgedoc uploads-volumeAutomatícelo con un cron diario y sincronícelo hacia un almacenamiento remoto (rclone hacia S3 o SFTP).
Actualizar HedgeDoc:
cd /opt/hedgedoc
docker compose pull app
docker compose up -d app
docker compose logs -f appLas migraciones de base de datos se aplican automáticamente al arrancar la nueva versión. Revise los registros para confirmar que las migraciones se han realizado correctamente antes de retomar el uso normal. La imagen actual es quay.io/hedgedoc/hedgedoc:1.11.1.
Resolver los problemas más habituales
La interfaz se muestra pero la colaboración no funciona
Compruebe en primer lugar el bloque /socket.io/ en Nginx (véase el recuadro dedicado más arriba).
Error 502 Bad Gateway después del arranque
HedgeDoc espera a que PostgreSQL esté listo gracias a depends_on: condition: service_healthy. Si el 502 persiste después de 60 segundos, compruebe que el contenedor database está realmente en estado healthy: docker compose ps. Si no lo está, inspeccione sus registros: docker compose logs database.
Las imágenes subidas desaparecen tras un reinicio
Asegúrese de que el volumen uploads está correctamente montado. Compruebe con docker inspect hedgedoc-app-1 | grep Mounts que el volumen es persistente (tipo volume, no bind).
Error al exportar a PDF
La exportación a PDF necesita Chromium en modo headless. Si la imagen Docker oficial no lo incluye en la versión que utiliza, puede desactivar la exportación a PDF con CMD_ALLOW_PDF_EXPORT: 'false' en .env.