Cómo instalar y configurar Link Shortener: Acortador de URLs Autohospedado en Docker
Link Shortener: Acortador de URLs autohospedado con analíticas y panel administrativo
Solución open source en TypeScript, Fastify y PostgreSQL para crear enlaces cortos con dominio propio, panel de administración y estadísticas de clics, desplegable con Docker Compose y Caddy con HTTPS automático.
Vídeo tutorial en YouTube
Mira el vídeo completo sobre cómo instalar y usar Link Shortener: Acortador de URLs autohospedado con analíticas y panel administrativo en el canal GENBYTE:
¿Qué es Link Shortener: Acortador de URLs autohospedado con analíticas y panel administrativo?
Link Shortener es un acortador de enlaces autohospedado que permite usar un dominio propio, ofrece un panel administrativo con autenticación segura y proporciona analíticas detalladas de clics. Está construido con Node.js 22, Fastify 5, PostgreSQL 16 y Drizzle ORM, y se despliega mediante Docker Compose con Caddy como proxy inverso que gestiona certificados TLS de Let's Encrypt de forma automática. El proyecto está licenciado bajo MIT y su código está disponible en GitHub.
Características principales
Enlaces cortos con dominio propio
Permite crear URLs cortas utilizando un hostname personalizado configurado mediante la variable SHORTENER_DOMAIN.
Redirecciones configurables
Soporte para códigos de estado HTTP 301, 302, 307 y 308, configurable globalmente o por enlace mediante REDIRECT_STATUS_CODE.
Panel administrativo seguro
Interfaz de administración con autenticación basada en sesiones, hash de contraseñas Argon2id y protección CSRF integrada.
Gestión completa de enlaces
Crear, editar, desactivar y archivar enlaces; cada uno puede tener vencimiento, título, descripción y metadatos personalizados.
Analíticas globales y por enlace
Series temporales de clics, distribución por países, referrers y listado de clics recientes, tanto a nivel global como por enlace individual.
API JSON para automatización
Endpoints REST para listar, crear, obtener, actualizar, desactivar enlaces y consultar estadísticas, protegidos por autenticación de sesión o token heredado.
Captura de IP respetuosa con la privacidad
Las direcciones IP de los visitantes no se almacenan en claro; solo se guarda un hash para análisis geográfico sin identificar usuarios.
Despliegue listo para producción
Stack Docker Compose que incluye la aplicación, PostgreSQL en red interna, Caddy como reverse proxy y emisión/renovación automática de certificados TLS.
Desarrollo local simplificado
Entorno de desarrollo con docker-compose.yml que expone puertos y permite crear usuario administrador con contraseña definida por variable de entorno.
Validación estricta de configuración
La aplicación valida todas las variables de entorno requeridas al arranque y falla inmediatamente si falta algún valor obligatorio.
Requisitos del sistema
- VPS con Ubuntu 22.04, 24.04 o 26.04 y acceso SSH como root
- Registro DNS tipo A apuntando el subdominio deseado a la IPv4 pública del VPS
- Puertos TCP 80 y 443 abiertos en el firewall del proveedor y del servidor
- Docker Engine y Docker Compose (plugin docker-compose-plugin) instalados desde el repositorio oficial de Docker para Ubuntu
- Clonar el repositorio y configurar archivo .env.production con valores seguros generados mediante openssl
Instalación con Docker Compose
1. Preparar el VPS y el DNS
Crear un VPS con Ubuntu, anotar su IPv4 pública y crear un registro A en el proveedor DNS para el subdominio elegido (ej. go.example.com -> 203.0.113.10). Verificar que los puertos 80 y 443 estén permitidos.
2. Instalar Docker Engine y Docker Compose
Utilizar el repositorio oficial de Docker para Ubuntu para instalar docker-ce, docker-ce-cli, containerd.io, docker-buildx-plugin y docker-compose-plugin. Verificar la instalación con hello-world y docker compose version.
3. Descargar y configurar Link Shortener
Clonar el repositorio, copiar el archivo de ejemplo de producción a .env.production, restringir permisos y editar las variables requeridas: SHORTENER_DOMAIN (solo hostname), POSTGRES_PASSWORD (hexadecimal de 32 bytes) y SESSION_SECRET (Base64 de al menos 32 caracteres).
4. Levantar la aplicación con HTTPS automático
Ejecutar docker compose con el archivo compose.production.yml y el archivo de entorno .env.production. El stack incluye la app, PostgreSQL (solo red interna), Caddy y certificados Let's Encrypt automáticos. Verificar el estado con curl al endpoint /healthz.
5. Crear el primer usuario administrador
Ejecutar el script create-admin dentro del contenedor de la app, proporcionando el email. La contraseña se solicita de forma interactiva y oculta. Luego acceder al panel en https://<dominio>/admin/login.
Acceder al proyecto
Panel administrativo
Acceder mediante navegador a https://<SHORTENER_DOMAIN>/admin/login tras crear el usuario administrador.
Health check del servicio
Endpoint público GET /healthz para verificar que la aplicación responde correctamente (ej. curl https://go.example.com/healthz).
Casos de uso
- Acortador de URLs personal para marca o proyecto propio con dominio propio
- Campañas de marketing con seguimiento de clics, países y referrers
- Automatización de creación y gestión de enlaces mediante API JSON
- Reemplazo autohospedado de servicios acortadores de terceros manteniendo control total de datos
- Entornos donde se requiere privacidad: solo se almacena hash de IP, no la IP real
- Desarrollo y pruebas de integraciones que requieren un servicio de redirección configurable
Configuración avanzada
Variables de entorno principales
Configuración validada al arranque: SHORTENER_DOMAIN (obligatorio), SHORTENER_SCHEME (default https), DATABASE_URL (obligatorio, armado por Compose en producción), SESSION_SECRET (obligatorio, mínimo 32 chars), SESSION_MAX_AGE_SECONDS (default 604800), SESSION_COOKIE_NAME, CSRF_COOKIE_NAME, REDIRECT_STATUS_CODE (default 302), ADMIN_TOKEN (opcional, heredado), NODE_ENV (production).
Uso de la API JSON
Endpoints principales: GET /api/links (lista), POST /api/links (crear), GET /api/links/:id (detalle), PATCH /api/links/:id (actualizar), DELETE /api/links/:id (desactivar), GET /api/links/:id/stats (estadísticas). Autenticación mediante cookie de sesión o header Authorization: Bearer <ADMIN_TOKEN> (heredado).
Workflow de despliegue continuo (GitHub Actions)
El repositorio incluye un workflow que valida PRs y, en push a main, construye y publica la imagen en ghcr.io/<owner>/<repo>. El deploy remoto está deshabilitado por defecto; para habilitarlo configurar variables DEPLOY_ENABLED=true, DEPLOY_COMMAND y secrets DEPLOY_HOST, DEPLOY_USER, DEPLOY_SSH_KEY en GitHub Actions.
Códigos de redirección personalizados
Cada enlace puede definir su propio código de redirección (301, 302, 307, 308) sobrescribiendo el valor global REDIRECT_STATUS_CODE. Útil para SEO (301) o redirecciones temporales (302/307).
Rotación de credenciales
Script npm run rotate-credentials para regenerar secretos de sesión y CSRF sin perder datos, útil en respuesta a incidentes de seguridad.
Gestión y mantenimiento
Ver logs en tiempo real
Seguir la salida combinada de todos los servicios del stack de producción.
Actualizar a la última versión
Obtener cambios del repositorio y reconstruir y reiniciar los contenedores manteniendo los volúmenes de datos.
Detener el stack sin borrar datos
Para y elimina contenedores pero conserva volúmenes (base de datos, certificados TLS). No usar down -v a menos que se quiera borrar todo.
Backup de datos persistentes
Los datos viven en volúmenes Docker (shortener_pgdata para PostgreSQL, shortener_caddy_data y shortener_caddy_config para Caddy). Realizar backup de los volúmenes con herramientas como docker run --rm -v shortener_pgdata:/data -v $(pwd):/backup alpine tar czf /backup/pgdata.tar.gz /data.
Rotación de secretos de sesión
Ejecutar el script de rotación para invalidar sesiones activas y generar nuevos secretos de cookies y CSRF.
Stack técnico
- Node.js 22
- TypeScript 5
- Fastify 5
- PostgreSQL 16
- Drizzle ORM
- HTMX
- Chart.js
- Docker Compose
- Caddy
- Let's Encrypt
- Argon2id (hash de contraseñas)
- Zod (validación)
- Pino (logging)
Referencias oficiales
- Repositorio GitHub: https://github.com/pablokbs/link-shortener
- README en español: https://github.com/pablokbs/link-shortener/blob/main/README.md
- README en inglés: https://github.com/pablokbs/link-shortener/blob/main/README.en.md
- Documentación de arquitectura: https://github.com/pablokbs/link-shortener/blob/main/docs/architecture.md
- Roadmap del proyecto: https://github.com/pablokbs/link-shortener/blob/main/docs/roadmap.md
- Decisiones técnicas: Stack: https://github.com/pablokbs/link-shortener/blob/main/docs/decisions/0001-stack.md
- Decisiones técnicas: Autenticación: https://github.com/pablokbs/link-shortener/blob/main/docs/decisions/auth.md
- Guía de contribución: https://github.com/pablokbs/link-shortener/blob/main/CONTRIBUTING.md
- Política de seguridad: https://github.com/pablokbs/link-shortener/blob/main/SECURITY.md
- Licencia MIT: https://github.com/pablokbs/link-shortener/blob/main/LICENSE
Comentarios
Publicar un comentario