[{"data":1,"prerenderedAt":192},["ShallowReactive",2],{"seo-verification":3,"blog-autoalojar-centrifugo-vps-servidor-tiempo-real-es":6},{"google":4,"bing":5},"EycwPY2XMyTkVzas3n1ygeNJFGAH513qrMjfDljzsMQ","",{"key":7,"data":8},"blog-autoalojar-centrifugo-vps-servidor-tiempo-real-es",{"id":9,"slug":10,"slugs":11,"title":15,"excerpt":16,"readTime":17,"views":18,"isPinned":19,"noindex":20,"publishedAt":21,"updatedAt":22,"category":23,"categories":28,"featuredImage":30,"bgImage":31,"posterImage":32,"relatedSolution":33,"intro":36,"sections":37,"ctaTitle":120,"ctaBody":121,"ctaButton":122,"ctaUrl":123,"relatedPosts":124},569,"autoalojar-centrifugo-vps-servidor-tiempo-real",{"fr":12,"en":13,"ar":14,"es":10},"self-host-centrifugo-vps","self-host-centrifugo-vps-real-time-server","استضافة-centrifugo-على-vps-خادم-زمن-حقيقي","Centrifugo en un VPS: servidor de tiempo real autoalojado","Instala Centrifugo en un VPS: un servidor de tiempo real de código abierto para enviar mensajes WebSocket desde tu backend, con tokens JWT y API.",7,0,false,true,"2026-11-07T00:00:00+00:00","2026-11-08T01:13:02+00:00",{"id":17,"name":24,"slug":25,"color":26,"icon":27},"Autoalojamiento","self-hosting","bg-indigo-500\u002F10 text-indigo-400","cloud",[29],{"id":17,"name":24,"slug":25,"color":26,"icon":27},null,"\u002Fblog\u002Fcovers\u002Fbg.svg","\u002Fblog\u002Fcovers\u002Fself-host-centrifugo-vps-poster.svg",{"categorySlug":34,"appSlug":35},"desarrollo","centrifugo","Mostrar una notificación en el momento en que se paga un pedido, mantener un chat, actualizar un panel sin recargar la página: todo esto requiere una conexión abierta de forma permanente entre el servidor y el navegador. Servicios como Pusher o Ably lo hacen muy bien, pero facturan cada conexión y cada mensaje, y tus datos pasan por ellos. Centrifugo es un servidor de mensajería en tiempo real de código abierto (licencia Apache-2.0), escrito en Go, que hace el mismo trabajo en tu propio VPS. Esta guía lo instala con Docker Compose, lo coloca detrás de nginx con HTTPS y muestra cómo publicar desde tu backend y conectar un navegador con un JWT.",[38,42,52,79,82,95,99,102,105,108,111,114,117],{"type":39,"title":40,"body":41},"h2","Cómo funciona Centrifugo","Centrifugo se sitúa entre tu aplicación y sus usuarios. Tu backend — Laravel, Django, Express, Rails u otro — no mantiene ninguna conexión abierta: firma un token para cada usuario y publica mensajes con una simple llamada HTTP. Centrifugo mantiene las conexiones WebSocket de los navegadores y las apps móviles, y entrega cada mensaje a los suscriptores del canal correspondiente.\n\nEsta separación tiene una ventaja concreta: tu aplicación sigue sin estado y es fácil de desplegar, y la parte de tiempo real cabe en un único binario Go que consume unas decenas de MB de RAM en reposo.",{"type":43,"title":44,"items":45},"ul","Lo que aporta Centrifugo",[46,47,48,49,50,51],"**Conexiones WebSocket** — con SDK cliente oficiales para JavaScript, Dart\u002FFlutter, Swift, Java\u002FAndroid, Go y Python.","**API de publicación** — un POST HTTP con la cabecera `X-API-Key`, desde cualquier lenguaje.","**Tokens JWT** — tu backend decide quién se conecta y a qué canales, Centrifugo verifica la firma.","**Suscripciones del lado del servidor** — la lista de canales de un usuario viaja en su token.","**Consola de administración** — estado del nodo, clientes conectados y comandos de la API desde el navegador.","**Valores por defecto prudentes** — ninguna conexión anónima, ninguna publicación desde el navegador sin permiso explícito.",{"type":53,"title":54,"headers":55,"rows":58},"comparison","Centrifugo frente a un servicio alojado",[5,56,57],"Centrifugo en un VPS","Pusher, Ably",[59,63,67,71,75],[60,61,62],"Facturación","Precio del VPS, sin límite de mensajes","Por conexiones y mensajes",[64,65,66],"Por dónde pasan los datos","Por tu servidor","Por el proveedor",[68,69,70],"Protocolo cliente","WebSocket y SDK oficiales","WebSocket y SDK propietarios",[72,73,74],"Autenticación","JWT firmado por tu backend","Firma propia del servicio",[76,77,78],"Operación","A tu cargo","A cargo del proveedor",{"type":39,"title":80,"body":81},"Requisitos previos","Un VPS Ubuntu 24.04 con 1 GB de RAM y 10 GB de disco, Docker y el plugin Compose instalados, y un subdominio que apunte al VPS, por ejemplo `rt.example.com`. El HTTPS no es opcional: un sitio servido por HTTPS solo puede abrir conexiones `wss:\u002F\u002F`, y tu clave de API nunca debe circular en claro.",{"type":83,"title":84,"steps":85},"steps","Instalar Centrifugo con Docker Compose",[86,89,92],{"title":87,"body":88},"Generar los secretos","Crea el directorio de la aplicación y un archivo `.env` con cuatro secretos distintos: la contraseña de la consola, la clave que firma sus sesiones, la clave de la API de servidor y la clave HMAC de los tokens de cliente.\n```bash\nmkdir -p \u002Fopt\u002Fcentrifugo && cd \u002Fopt\u002Fcentrifugo\n{\n  echo \"ADMIN_PASSWORD=$(openssl rand -hex 12)\"\n  echo \"SECRET_KEY=$(openssl rand -hex 24)\"\n  echo \"ENCRYPTION_KEY=$(openssl rand -hex 16)\"\n  echo \"ENCRYPTION_KEY_HEX64=$(openssl rand -hex 32)\"\n} > .env\nchmod 600 .env\n```",{"title":90,"body":91},"Escribir el archivo docker-compose.yml","El puerto se publica solo en la interfaz local: únicamente nginx accede a él. Sustituye `https:\u002F\u002Fapp.example.com` por la dirección de tu sitio.\n```yaml\nservices:\n  centrifugo:\n    image: centrifugo\u002Fcentrifugo:v6.10.2\n    restart: unless-stopped\n    command: [\"centrifugo\"]\n    ports:\n      - \"127.0.0.1:8000:8000\"\n    environment:\n      CENTRIFUGO_ADMIN_ENABLED: \"true\"\n      CENTRIFUGO_ADMIN_PASSWORD: \"${ADMIN_PASSWORD}\"\n      CENTRIFUGO_ADMIN_SECRET: \"${SECRET_KEY}\"\n      CENTRIFUGO_HTTP_API_KEY: \"${ENCRYPTION_KEY}\"\n      CENTRIFUGO_CLIENT_TOKEN_HMAC_SECRET_KEY: \"${ENCRYPTION_KEY_HEX64}\"\n      CENTRIFUGO_CLIENT_ALLOWED_ORIGINS: \"https:\u002F\u002Fapp.example.com\"\n      CENTRIFUGO_HEALTH_ENABLED: \"true\"\n    ulimits:\n      nofile:\n        soft: 65535\n        hard: 65535\n```",{"title":93,"body":94},"Arrancar y comprobar","Inicia el contenedor y consulta el punto de salud; debe responder `{}`.\n```bash\ndocker compose up -d\ncurl -fsS http:\u002F\u002F127.0.0.1:8000\u002Fhealth\n```",{"type":96,"title":97,"body":98},"tip","Nunca publiques el puerto 8000 en la IP pública","El mismo puerto sirve las conexiones de clientes, la API de servidor y la consola de administración. Mantenlo en `127.0.0.1` y pasa siempre por el proxy inverso HTTPS. Y nunca pongas `ENCRYPTION_KEY` ni `ENCRYPTION_KEY_HEX64` en código enviado al navegador: la primera permite publicar en cualquier canal, la segunda fabricar tokens para cualquier usuario.",{"type":39,"title":100,"body":101},"Colocar Centrifugo detrás de nginx","Una conexión WebSocket empieza con una petición HTTP que pide cambiar de protocolo. nginx debe transmitir esa petición y no cortar una conexión que permanece en silencio unos minutos. En el bloque `server` de tu subdominio, con un certificado Let's Encrypt:\n```nginx\nlocation \u002F {\n    proxy_pass http:\u002F\u002F127.0.0.1:8000;\n    proxy_http_version 1.1;\n    proxy_set_header Upgrade $http_upgrade;\n    proxy_set_header Connection \"upgrade\";\n    proxy_set_header Host $host;\n    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n    proxy_read_timeout 3600s;\n}\n```\nTras `nginx -t` y una recarga, `https:\u002F\u002Frt.example.com` muestra la pantalla de inicio de sesión de la consola.",{"type":39,"title":103,"body":104},"Publicar desde tu backend","Publicar es enviar un objeto JSON a un canal. Sirve cualquier lenguaje capaz de hacer una petición HTTP:\n```bash\ncurl -X POST https:\u002F\u002Frt.example.com\u002Fapi\u002Fpublish \\\n  -H \"X-API-Key: $ENCRYPTION_KEY\" \\\n  -d '{\"channel\": \"commandes\", \"data\": {\"id\": 1042, \"statut\": \"payee\"}}'\n```\nLa respuesta `{\"result\":{}}` confirma que el mensaje se aceptó. Sin la cabecera `X-API-Key`, o con una clave incorrecta, Centrifugo responde `401`.",{"type":39,"title":106,"body":107},"Firmar los tokens de conexión","Un navegador solo se conecta con un JWT firmado por tu backend con `ENCRYPTION_KEY_HEX64`. El claim `sub` lleva el identificador del usuario, `exp` la fecha de caducidad y `channels` la lista de canales a los que queda suscrito de oficio. Ejemplo en Python:\n```python\nimport time, jwt  # pip install pyjwt\n\ndef centrifugo_token(user_id: str) -> str:\n    claims = {\"sub\": user_id, \"exp\": int(time.time()) + 3600, \"channels\": [\"commandes\"]}\n    return jwt.encode(claims, ENCRYPTION_KEY_HEX64, algorithm=\"HS256\")\n```\nExpón esta función detrás de una ruta autenticada de tu aplicación: solo un usuario con sesión iniciada en tu app debe poder obtener un token.",{"type":39,"title":109,"body":110},"Lo que un cliente puede hacer","Los ajustes de esta instalación están cerrados a propósito. Un navegador no puede suscribirse por su cuenta a un canal ni publicar en él: solo recibe los canales listados en el claim `channels` de su token. Tu backend decide, cada vez que emite un token, quién escucha qué — un cliente solo ve sus propios pedidos, un agente de soporte solo la cola de su equipo.\n\nPara un chat, la publicación pasa también por tu backend: el navegador envía el mensaje a tu aplicación, que lo valida, lo guarda en la base de datos y lo publica por la API. Este rodeo cuesta unos milisegundos y te deja el control de la moderación y del historial.\n\nPor último, da a los tokens una duración corta, una hora por ejemplo. En lugar de pasar un token fijo, deja que el SDK pida uno nuevo a tu aplicación cuando caduque:\n```javascript\nconst client = new Centrifuge('wss:\u002F\u002Frt.example.com\u002Fconnection\u002Fwebsocket', {\n  getToken: async () => {\n    const res = await fetch('\u002Frealtime\u002Ftoken', { credentials: 'include' });\n    return (await res.json()).token;\n  },\n});\n```\nLa ruta `\u002Frealtime\u002Ftoken` es de tu aplicación; comprueba la sesión del usuario antes de firmar nada.",{"type":39,"title":112,"body":113},"Conectar un navegador","En el lado cliente, el SDK oficial `centrifuge` (npm) abre la conexión y entrega los mensajes:\n```javascript\nimport { Centrifuge } from 'centrifuge';\n\nconst client = new Centrifuge('wss:\u002F\u002Frt.example.com\u002Fconnection\u002Fwebsocket', {\n  token: tokenFromYourBackend,\n});\nclient.on('publication', (ctx) => console.log(ctx.channel, ctx.data));\nclient.connect();\n```\nSi la conexión falla, mira primero los registros (`docker compose logs centrifugo`). El mensaje «request Origin is not authorized» indica que falta el origen de tu sitio en `CENTRIFUGO_CLIENT_ALLOWED_ORIGINS`; «invalid token» apunta a un token mal firmado o caducado.",{"type":39,"title":115,"body":116},"La consola de administración","Abre `https:\u002F\u002Frt.example.com` e introduce `ADMIN_PASSWORD`: la consola no pide usuario. Muestra la versión del nodo, el número de clientes y usuarios conectados, y permite enviar comandos de la API — publicar un mensaje de prueba, listar los canales activos — sin escribir código. Es la forma más rápida de comprobar que un mensaje sale antes de buscar el fallo en el navegador.",{"type":39,"title":118,"body":119},"Escalado y actualizaciones","Esta guía usa el motor en memoria: un solo nodo, sin dependencias. Sirve para la mayoría de las aplicaciones, y un VPS modesto ya sostiene un gran número de conexiones simultáneas, de ahí el límite de archivos abiertos ampliado en el `docker-compose.yml`. El día en que un nodo no baste, Centrifugo puede repartir la carga entre varios nodos unidos por Redis. Para actualizar, cambia la etiqueta de la imagen tras leer las notas de versión y ejecuta `docker compose pull && docker compose up -d`; las conexiones se restablecen solas, porque los SDK cliente se reconectan automáticamente.","Tu servidor de tiempo real en tu VPS","Un VPS ServOrbit Ubuntu 24.04 con 1 GB de RAM basta para arrancar Centrifugo. Instalación en un clic desde el Marketplace, HTTPS y WebSocket en tu dominio o en el subdominio gratuito del VPS, contraseña y claves generadas para ti.","Instalar Centrifugo","\u002Fapplications\u002Fdesarrollo\u002Fcentrifugo",[125,150,174],{"id":126,"slug":127,"slugs":128,"title":132,"excerpt":133,"readTime":134,"views":135,"isPinned":19,"noindex":19,"publishedAt":136,"updatedAt":137,"category":138,"categories":144,"featuredImage":30,"bgImage":31,"posterImage":146,"relatedSolution":147},194,"autoalojar-ntfy-en-un-vps",{"fr":129,"en":130,"ar":131,"es":127},"self-host-ntfy-vps","self-host-ntfy-on-a-vps-push-notifications-for-scripts-and-cicd","استضافة-ntfy-على-vps-إشعارات-فورية-من-سكريبتاتك-وcicd","Alojar ntfy en un VPS: notificaciones push para sus scripts","Despliegue ntfy en su VPS y envíe notificaciones push desde cualquier script, cron o pipeline CI\u002FCD con un simple curl — sin SaaS ni clave de API.",16,2,"2026-07-28T00:00:00+00:00","2026-11-04T16:30:26+00:00",{"id":139,"name":140,"slug":141,"color":142,"icon":143},8,"Seguridad y monitorización","securite-monitoring","bg-rose-500\u002F10 text-rose-400","security",[145],{"id":139,"name":140,"slug":141,"color":142,"icon":143},"\u002Fblog\u002Fcovers\u002Fself-host-ntfy-vps-poster.svg",{"categorySlug":148,"appSlug":149},"monitorizacion-observabilidad","ntfy",{"id":151,"slug":152,"slugs":153,"title":157,"excerpt":158,"readTime":159,"views":18,"isPinned":19,"noindex":19,"publishedAt":160,"updatedAt":161,"category":162,"categories":168,"featuredImage":30,"bgImage":31,"posterImage":170,"relatedSolution":171},58,"alojar-redis-en-un-vps",{"fr":154,"en":155,"ar":156,"es":152},"heberger-redis-vps","hosting-redis-on-a-vps","استضافة-redis-على-خادم-vps","Alojar Redis en un VPS: la guía completa","Despliegue Redis en su VPS Cloud: requisitos de RAM\u002FCPU, seguridad (ACL, TLS), persistencia RDB\u002FAOF, resolución de errores y alta disponibilidad.",10,"2026-04-23T00:00:00+00:00","2026-09-08T21:59:59+00:00",{"id":163,"name":164,"slug":165,"color":166,"icon":167},6,"Bases de datos","bases-de-donnees","bg-teal-500\u002F10 text-teal-400","database",[169],{"id":163,"name":164,"slug":165,"color":166,"icon":167},"\u002Fblog\u002Fcovers\u002Fheberger-redis-vps-poster.svg",{"categorySlug":172,"appSlug":173},"bases-de-datos","redis-stack",{"id":175,"slug":176,"slugs":177,"title":181,"excerpt":182,"readTime":183,"views":18,"isPinned":19,"noindex":19,"publishedAt":184,"updatedAt":185,"category":186,"categories":187,"featuredImage":30,"bgImage":31,"posterImage":189,"relatedSolution":190},60,"alojar-supabase-en-un-vps",{"fr":178,"en":179,"ar":180,"es":176},"heberger-supabase-vps","hosting-supabase-on-a-vps","استضافة-supabase-على-خادم-vps","Alojar Supabase en un VPS en 2026","Autoaloje Supabase en su VPS: Postgres, Auth, Storage y API REST detrás de Envoy. Migración PG 15→17, Kong→Envoy, CVE de GoTrue.",15,"2026-04-21T00:00:00+00:00","2026-11-08T01:13:14+00:00",{"id":163,"name":164,"slug":165,"color":166,"icon":167},[188],{"id":163,"name":164,"slug":165,"color":166,"icon":167},"\u002Fblog\u002Fcovers\u002Fheberger-supabase-vps-poster.svg",{"categorySlug":172,"appSlug":191},"supabase",1794101244761]