Qué hace
Es self-hosted: no hay una web donde te registras y ya. Te montas tu propia copia, y esta guía es para eso. Lo uso yo desde el 12-09-2026: en la semana del 7 al 14 de octubre mandó 712 DMs.
Cómo está hecho, en una línea
Son cuatro piezas: una web (recibe el aviso de Instagram y es donde creas las campañas), una base de datos Postgres (tus campañas), una cola Redis y un worker, que es el que manda los DMs. Es como un restaurante: la web toma nota y el worker es el cocinero, que no se puede ir nunca a casa.
La web la puedes tener gratis en Vercel. El worker no: tiene que estar encendido las 24 horas, y Vercel no deja procesos encendidos. Todo el coste está en dónde pones el worker.
Elige dónde vive el worker
Si ya pagas un servidor (por ejemplo, para n8n), metes ahí Postgres, Redis y el worker. No pagas nada más. Más abajo tienes el prompt para que una IA te lo monte, y el repo trae una guía para servidor propio con Dokploy.
Es el camino de la guía oficial y por donde empecé yo. La prueba es de 30 días con 5 $ de crédito; luego el plan Hobby cuesta 5 $ al mes con 5 $ de uso incluidos. Mi uso fue de 3,65 $ en un mes.
Es el montaje que usa el autor: Postgres en Neon, Redis en Redis Cloud y el worker en una máquina "Always Free" de Oracle. Todo gratis, pero son tres cuentas más. Esta ruta no la he probado yo.
Lo que necesitas
- Una cuenta profesional de Instagram (Empresa o Creador). Una personal no se puede conectar. Se cambia en Instagram: en Configuración, escribe "tipo de cuenta" en el buscador.
- Una cuenta de Facebook, para registrarte en Meta for Developers y crear tu app. Es gratis.
- GitHub y Vercel, las dos gratis. Vercel te da una dirección
tu-app.vercel.app: no necesitas comprar un dominio. - Algo que mande el email de inicio de sesión. OpenReply entra con un enlace al correo. La guía oficial usa Resend, que pide un dominio tuyo verificado; si no tienes, puedes poner tu propio servidor de correo en
EMAIL_SERVER. - Una tarde. A mí me llevó una, con la IA al lado. El código funciona a la primera; lo lento es la app de Meta.
Los pasos
Te pongo la ruta de Railway, que es la de la guía oficial. Si vas a tu servidor o a las capas gratuitas, cambian el paso 2 y las direcciones del paso 4; el resto es igual.
- Haz un fork del repo.
Entra en github.com/diwenne/openreply y pulsa Fork. Trabajas sobre tu copia.
- Base de datos, cola y worker en Railway.
Crea un proyecto y añade, con New: Database, PostgreSQL; Database, Redis; y GitHub Repo, tu fork. En el servicio de tu fork, en Settings, pon:
Build Command:
npm run db:generate
Start Command:
npm run worker
En sus Variables pon las del paso 4. Aquí, para la base y la cola, usa las direcciones internas (
postgres.railway.internalyredis.railway.internal). - Crea las tablas.
Una vez, desde tu ordenador y dentro de tu fork, con la dirección pública de Postgres (
DATABASE_PUBLIC_URLen Railway):npm install DATABASE_URL="pega-aquí-la-DATABASE_PUBLIC_URL" npm run db:migrate
- La web en Vercel, con sus variables.
En Vercel, Add New Project, importa tu fork. Antes de desplegar, en Settings, Environment Variables, añade estas. Las tres claves secretas se generan en la terminal:
Para
NEXTAUTH_SECRETy paraCRON_SECRET(una vez cada una):openssl rand -base64 32
Para
ENCRYPTION_KEY:openssl rand -hex 32
Variable Qué poner NEXTAUTH_URLTu dirección de Vercel, por ejemplo https://tu-app.vercel.appNEXTAUTH_SECRET,CRON_SECRETLas dos primeras claves ENCRYPTION_KEYLa tercera. La misma en Vercel y en el worker, o ningún DM se podrá enviar DATABASE_URL,REDIS_URLLas direcciones públicas de Railway ( DATABASE_PUBLIC_URLyREDIS_PUBLIC_URL). Copia el valor que se ve con el ojo, no el que lleva${{...}}RESEND_API_KEY,EMAIL_FROMTu clave de Resend y un remitente de tu dominio verificado ALLOWED_EMAILSTu email. Si no lo pones, cualquiera que llegue a tu dirección puede crearse una cuenta META_GRAPH_API_VERSIONv25.0INSTAGRAM_APP_ID,INSTAGRAM_APP_SECRET,FACEBOOK_APP_SECRETSalen de tu app de Meta (paso 6). Puedes desplegar ya y añadirlas luego WEBHOOK_VERIFY_TOKENUna palabra cualquiera inventada. La pegarás también en Meta El worker necesita las mismas, salvo que su
DATABASE_URLy suREDIS_URLson las internas (paso 2). Despliega y comprueba quehttps://tu-app.vercel.app/api/healthdice"status":"ok". - Crea la app de Meta.
En developers.facebook.com/apps, crea una app de tipo Business. Cuando te pida el caso de uso, filtra por All y elige Manage messaging and content on Instagram. No elijas el de anuncios ni "Authenticate with Facebook Login": OpenReply entra con Instagram, y con el de Facebook la conexión falla más tarde.
- Copia los tres secretos.
Variable Dónde está en Meta INSTAGRAM_APP_IDInstagram, API setup with Instagram login. No es el App ID de la página de ajustes básicos INSTAGRAM_APP_SECRETLa misma página, Show FACEBOOK_APP_SECRETApp settings, Basic, App secret, Show Añádelos en Vercel y vuelve a desplegar.
- Hazte tester, por los dos lados.
En la app de Meta: App roles, Roles, Instagram testers, añade tu usuario de Instagram exacto. Y luego en Instagram, con esa cuenta: abre Configuración, escribe "aplicaciones" en el buscador de arriba, entra en Aplicaciones y sitios web y acepta la invitación de tu app (en la app la llaman invitación de evaluador; en inglés, "Tester invites"). Sin esta segunda mitad, la conexión falla.
- Las dos direcciones de Meta.
En el producto Instagram, en Business login settings, añade como OAuth redirect URI:
https://tu-app.vercel.app/api/instagram/callback
Y en Configure webhooks, como Callback URL, y con tu
WEBHOOK_VERIFY_TOKENcomo Verify token:https://tu-app.vercel.app/api/webhook
Pulsa Verify and save y suscríbete a comments y a messages. Sin
messages, lo de contestar DMs e historias no funciona. - Publica la app.
Mientras la app esté en desarrollo, Instagram no manda los comentarios de verdad. En Publish, rellena las tres páginas, que OpenReply ya trae hechas:
https://tu-app.vercel.app/privacy https://tu-app.vercel.app/terms https://tu-app.vercel.app/data-deletion
Y publica.
- Conecta Instagram y prueba.
Entra en tu OpenReply con tu email, en Settings pulsa Connect Instagram, y crea una campaña en un post tuyo con la palabra
TEST. ComentaTESTdesde otra cuenta: tus propios comentarios los ignora a propósito. Si llega el DM, ya está.
Si prefieres que te lo monte una IA
Abre tu fork en Claude Code o Codex (o pégalo en ChatGPT y ve haciendo lo que te diga) y dale esto. Sirve para las tres rutas.
Quiero montar OpenReply (comment-to-DM de Instagram) para MI cuenta, con mi propia app de Meta, no con Zernio. Lee README.md y docs/setup.md antes de tocar nada. Dónde va el worker (elige conmigo antes de empezar): - A) Mi servidor, que ya tengo encendido. Ahí van Postgres, Redis y el worker. - B) Railway, como la guía oficial. - C) Capas gratuitas: Neon (Postgres), Redis Cloud (Redis con TCP, no uno solo HTTP) y una máquina siempre encendida para el worker. La web va en Vercel. Reglas: - No me pidas que pegue claves aquí. Dime dónde ponerlas (Vercel, Railway o el .env del servidor) y que las pegue yo. - ENCRYPTION_KEY idéntica en la web y en el worker. - La web usa direcciones de base de datos y Redis que se alcancen desde fuera; el worker, las internas si existen. - Si la web está en Vercel y la base de datos en Europa, pon "regions": ["fra1"] en vercel.json para que no vaya lenta. - Si el worker está en Railway y luego lo mueves a otro sitio, borra el servicio de Railway: si no, se vuelve a desplegar con cada push y los DMs salen dobles. - Para la app de Meta, sigue docs/setup.md paso a paso y avísame de las dos mitades del tester (Meta e Instagram) y de publicar la app. - No inventes pantallas: si lo que veo no coincide, pregúntame. Acaba cuando /api/health diga "status":"ok" con el worker sano y un comentario de prueba desde otra cuenta llegue como DM.
Si alguna clave acaba pegada en un chat, cámbiala después. Lo dice la propia guía de OpenReply, y vale para cualquier IA.
Los errores que me encontré
Insufficient developer roleAl conectar Instagram. Te falta aceptar la invitación de tester dentro de Instagram (paso 7). Añadirte en Meta no basta.
The callback URL or verify token couldn't be validatedAl guardar el webhook. Comprueba que la web está desplegada, que la dirección acaba en /api/webhook y que el token es exactamente el de WEBHOOK_VERIFY_TOKEN. Si el botón no se activa, vuelve a pegar el token.
Error: P1013: The provided database string is invalidAl desplegar en Vercel. La DATABASE_URL no es una dirección completa: tiene que empezar por postgresql:// y ser la pública.
getaddrinfo ENOTFOUND $La web se queda colgada y no entra nadie. En Vercel pegaste la plantilla de Railway (${{...}}) en vez del valor real. Vercel no la entiende: copia el valor con el ojo.
Todo bien, y no llega ningún DMLa app de Meta sigue en desarrollo. Publícala (paso 9). Y prueba siempre desde otra cuenta.
El mismo DM llega dos vecesHay dos workers a la vez. A mí me pasó al mover el worker de Railway a mi servidor: Railway seguía conectado al repo y lo volvió a encender con un cambio. Deja uno solo, y borra el otro servicio, no solo su despliegue.
El panel tarda en cargarLa web de Vercel está lejos de la base de datos. Vercel la pone en Washington por defecto; con mi base en Alemania, ponerla en Frankfurt ("regions": ["fra1"] en vercel.json) la hizo unas tres veces más rápida.