Dominios
Esta guía explica cómo se publica un servicio en internet: el host que genera la plataforma, un dominio tuyo y qué hace la pasarela con cada petición.
Público o privado
Todo servicio nace privado. Sus vecinos del proyecto lo alcanzan siempre por su nombre (postgres:5432, api:8080), pero nada de fuera de la máquina. Publicarlo es un interruptor: en la pestaña Dominios, Además, accesible desde internet, o desde la terminal:
fundaia expose tienda api # público: si no tenía host, se genera uno
fundaia expose tienda api --off # privado otra vez
Hacerlo privado apaga sus hosts y retira sus registros DNS, pero los recuerda: al volver a hacerlo público, un dominio tuyo vuelve tal cual, sin teclearlo otra vez. A un servicio privado no se le pueden añadir hosts.
Host generado
Al publicar un servicio se le genera <proyecto>-<servicio>.fundaia.com, que funciona al momento porque un registro comodín de la zona ya lo cubre. Se puede generar otro con fundaia domains add tienda api.
Algunas etiquetas las usa la propia plataforma (infrastructure, orchestrator, api, www…) y se rechazan como primera parte de un host, también en un dominio propio: api.midominio.com no se acepta, app.midominio.com sí.
Tu propio dominio
fundaia domains add tienda api app.midominio.com
En tu proveedor de DNS, un solo registro:
| Tipo | Nombre | Valor |
|---|---|---|
| CNAME | app | cname.fundaia.com |
El nombre es la etiqueta sola (app), no el host entero: app.midominio.com en ese campo produciría app.midominio.com.midominio.com.
En la raíz del dominio (midominio.com, sin subdominio) un CNAME no vale: usa el ALIAS, ANAME o «CNAME aplanado» que ofrezca tu proveedor, o publica en un subdominio.
Los pasos, y cuánto tardan
La pantalla dibuja el progreso y fundaia domains list lo imprime. Avanza solo, sin recargar:
| Estado | Qué pasa |
|---|---|
| Esperando DNS | La plataforma aún no ve tu registro. Lo busca por su cuenta cada poco |
| Emitiendo certificado | El registro ya está; el certificado se está emitiendo. Suele ser cuestión de minutos: no cambies el registro |
| Activo | Sirviendo con TLS |
| Ha fallado | El mensaje dice por qué |
Comprobar ahora en la pantalla, o fundaia domains verify <id>, fuerza la comprobación, para cuando acabas de arreglar una errata.
Cuántos
Cada plan incluye un número de dominios propios (ver Facturación), y la instancia puede tener además un tope global; el dominio que lo pasa se rechaza con el motivo. Los hosts generados no cuentan.
Quitar un dominio
fundaia domains remove <id>
Deja de responder en el acto; la plataforma borra también su registro DNS si lo creó ella.
Mantenimiento y contraseña
Dos cosas que la pasarela responde antes de llegar al servicio, sin reiniciar nada y desde la siguiente petición. Están en Ajustes → Acceso de un servicio público.
- Modo mantenimiento. Cada visitante ve una página de «volvemos enseguida» (un
503conRetry-After) con tu mensaje, en claro u oscuro según su sistema. El servicio sigue en marcha y no se despierta, así que puedes migrar datos o revisar algo con calma. Un aviso encima de las pestañas lo recuerda y lo apaga con un clic. - Contraseña. El navegador pide usuario y contraseña (HTTP Basic) antes de enseñar nada: útil para un staging, una demo o una herramienta interna. La contraseña se guarda con bcrypt, nunca en claro, y el servicio no la ve: la pasarela la quita antes de reenviar. Una API que lea su propia cabecera
Authorizationno funcionará detrás.
fundaia maintenance tienda web --message "Volvemos a las 18:00"
fundaia maintenance tienda web --off
fundaia protect tienda staging-web --user equipo # pide la contraseña sin mostrarla
fundaia unprotect tienda staging-web
Con MCP: set_maintenance, protect_service y unprotect_service. Ninguna de las dos se copia al crear otro entorno.
Direcciones IP permitidas y límite de peticiones
Otras dos decisiones de la pasarela, en el mismo Ajustes → Acceso y con el mismo efecto inmediato: se aplican desde la siguiente petición, sin reiniciar nada.
- Direcciones IP permitidas. Una lista de direcciones o redes, en IPv4 o IPv6 y en notación CIDR (
203.0.113.7,198.51.100.0/24,2001:db8::/32), de hasta 100 entradas. Solo ellas llegan al servicio; cualquier otra recibe un403, y también quien llega sin una dirección conocida. Es la primera comprobación de todas: alguien de fuera de la lista no ve ni la página de mantenimiento ni la petición de contraseña, y nunca despierta un servicio dormido. Útil para un panel interno, un staging que solo debe ver la oficina o un servicio detrás de una VPN. - Límite de peticiones por IP. Cada dirección puede hacer como mucho N peticiones por minuto; las demás reciben un
429conRetry-After, sin despertar el servicio ni servir nada de la caché. Se admite una ráfaga de N y el cupo se rellena a ritmo constante. Una dirección IPv6 cuenta por su red/64, que es lo que suele tener una sola casa u oficina. Sirve contra un bot o un script que se ha quedado en bucle; no sustituye a una protección contra ataques de denegación de servicio.
La dirección es la que escribe el borde de la plataforma (el túnel de Cloudflare o el ingress propio), nunca un X-Forwarded-For que el visitante pueda inventarse.
fundaia allow tienda panel 203.0.113.7 198.51.100.0/24 # la lista queda exactamente así
fundaia allow tienda panel 2001:db8::/32 --add # añade sin quitar las demás
fundaia allow tienda panel --list # qué hay ahora, y el límite
fundaia allow tienda panel --clear # vuelve a entrar cualquiera
fundaia ratelimit tienda api 600/min
fundaia ratelimit tienda api off
Con MCP: set_ip_allowlist (una lista vacía la quita) y set_rate_limit (perMinute: null lo quita). Cada cambio queda en el historial del proyecto, y las peticiones que la pasarela rechaza por una u otra razón aparecen en la pestaña Peticiones (ver Registros, métricas y avisos). Tampoco se copian al crear otro entorno.
Reglas de la pasarela
Lo que la pasarela contesta o añade sin llegar al servicio: redirecciones, cabeceras de respuesta, CORS, rutas a otros servicios y páginas de error. Están en Ajustes → Reglas de un servicio público, se comprueban mientras escribes y se aplican desde la siguiente petición, sin reiniciar nada. Cada cambio queda en el historial del proyecto.
El orden en la puerta es: la lista de direcciones IP, las redirecciones, el preflight de CORS, el mantenimiento, el límite de peticiones y la contraseña. Una redirección o un preflight no gastan cupo ni piden contraseña (un navegador nunca manda credenciales en un preflight), y nunca despiertan un servicio dormido.
Redirecciones
- De un host a otro: de uno de los hosts del servicio (
tienda.es, o el generado) a otro host, conservando la ruta y la consulta:https://tienda.es/carrito?id=7→https://tienda.com/carrito?id=7. El host de origen tiene que estar ya en Dominios. - De una ruta: exacta (
/viejo→/nuevo) o con prefijo (/blog/*→https://blog.tienda.com/:splat, donde:splates lo que cubrió el*). La consulta pasa al destino salvo que el destino traiga la suya. Una ruta exacta va antes que un prefijo, y gana el prefijo más largo. - Códigos
301(por defecto),302,307y308. Un301/308se puede guardar una hora en el navegador; un302/307no se guarda.
No se acepta una redirección que se llamaría a sí misma (/blog/* → /blog/:splat) ni una cadena de hosts (a → b y b → c: manda a directamente a c).
fundaia redirects add tienda web tienda.es tienda.com
fundaia redirects add tienda web '/blog/*' 'https://blog.tienda.com/:splat' --status 308
fundaia redirects list tienda web
fundaia redirects rm tienda web /viejo
Cabeceras de respuesta y CORS
- Cabeceras que se añaden a cada respuesta: solo si el servicio no la pone, o siempre, sustituyendo la suya. El botón Cabeceras de seguridad (o
fundaia headers security) añadeStrict-Transport-Security,X-Content-Type-Options: nosniff,Referrer-Policy,X-Frame-Options: SAMEORIGINyContent-Security-Policy: frame-ancestors 'self'donde falten. También van en las páginas de la propia pasarela (mantenimiento, contraseña, errores), aunque ahí nunca sustituyen sus cabeceras: un401sigue pidiendo la contraseña y un mantenimiento sigue sin guardarse en ninguna caché.Set-Cookie, las de CORS y las que describen la conexión no se configuran aquí, y quien no pasa la lista de IPs no recibe ninguna. - CORS: los orígenes que pueden llamar desde un navegador (
https://tienda.com,https://*.tienda.compara sus subdominios, o*), los métodos, las cabeceras que puede mandar y leer, las credenciales y cuánto recuerda el navegador la respuesta. La pasarela contesta el preflight (OPTIONS) con un204, o un403a un origen que no está, y pone las cabeceras en cada respuesta en lugar de las del servicio. Con credenciales hay que nombrar los orígenes.
fundaia headers security tienda web
fundaia headers set tienda web X-Frame-Options DENY --override
fundaia cors tienda api --origin https://tienda.com --origin 'https://*.tienda.com' --credentials
fundaia cors tienda api --off
Rutas a otros servicios
Un prefijo de los hosts de un servicio lo atiende otro servicio público del mismo entorno: tienda.com/api → api. Gana el prefijo más largo; el resto sigue yendo al propio servicio. La petición llega al otro servicio como si se le pidiera por su propio host: se despierta si dormía, cuenta para sus métricas y aparece en su pestaña Peticiones. Lleva X-Forwarded-Host con el host que escribió el visitante y, si se quita el prefijo (/api/pedidos → /pedidos), X-Forwarded-Prefix con lo que se quitó. Los WebSockets también pasan.
La puerta es primero la del host (su lista de IPs, su mantenimiento, su contraseña) y después la del servicio de destino; las redirecciones, las cabeceras y el CORS son las del host. Si los dos piden contraseña, tiene que ser la misma. Una ruta no encadena con las rutas del otro servicio.
Una ruta a un servicio que se ha borrado o que ya no es público se ve rota en la pantalla y en fundaia routes list, y la pasarela contesta 502 en ese prefijo: nunca la manda a otro sitio.
fundaia routes add tienda web /api api --strip
fundaia routes list tienda web
fundaia routes rm tienda web /api
Páginas de error y de espera
- Cuando la pasarela no consigue respuesta del servicio, un navegador ve una página con la marca de la plataforma:
502si no responde,503si no pudo arrancar,504si tarda más de dos minutos. Cada servicio puede poner su propio HTML, de hasta 64 KB, para cada una. Una petición que no pide HTML (una API,curl) sigue recibiendo el texto de siempre, y lo que conteste el propio servicio, aunque sea un502, nunca se cambia. - Página de espera: un navegador que llega con el servicio dormido la ve al momento, mientras despierta, y se recarga sola cada 3 segundos hasta que responde. Si despertar falla, la siguiente recarga enseña la página del
503en lugar de prometer otra vez.
fundaia error-page tienda web 502 caido.html
fundaia error-page tienda web 503 --default
fundaia error-page tienda web waiting # encendida, con la página de la plataforma
fundaia error-page tienda web waiting --off
Probar una dirección
Debajo de las reglas, Probar una dirección dice qué haría la pasarela con una dirección, un método y un origen, con lo que estás editando y antes de guardarlo: si redirige y adónde, si contesta un preflight, a qué servicio y con qué ruta llega, y con qué cabeceras. Lo mismo, con lo guardado:
fundaia rules tienda web --try https://tienda.es/blog/hola
fundaia rules tienda api --try /pedidos --method OPTIONS --origin https://tienda.com
Con MCP: read_gateway_rules, update_gateway_rules (cada parte que pasas sustituye esa parte entera) y preview_gateway_rules.
Al copiar un entorno las reglas viajan con cada servicio, menos las redirecciones de host y las que mandan a un host del entorno de origen: la copia no tiene esos dominios, y no debe mandar a sus visitantes a producción. Una ruta apunta al servicio del mismo nombre en el entorno nuevo.
Qué hace la pasarela
Toda petición pública pasa por la pasarela de la plataforma, que enruta por el Host y además:
- Despierta el servicio si estaba dormido y retiene la petición mientras arranca; ver Dormir y despertar.
- Sigue sirviendo con el contenedor anterior mientras se construye un despliegue nuevo.
- Quita sus propias cookies de sesión antes de reenviar, así que un servicio publicado bajo
fundaia.comnunca ve la credencial de la plataforma. Las cookies de tu aplicación pasan intactas. - Reenvía WebSockets.
- Guarda en caché, si lo activas en Ajustes → Caché, las respuestas de recursos estáticos (JavaScript, CSS, imágenes, fuentes, JSON). Nunca HTML, ni respuestas con
Set-Cookie, ni peticiones que llevan credenciales. UnCache-Controldel servicio manda sobre el tiempo configurado. - Responde la página de mantenimiento o pide la contraseña si lo has activado; ver Mantenimiento y contraseña.
- Deja fuera las direcciones que no están en la lista y frena a quien pasa del límite de peticiones por minuto; ver Direcciones IP permitidas y límite de peticiones.
- Redirige, contesta el preflight de CORS, añade cabeceras, manda un prefijo a otro servicio y enseña las páginas de error y de espera que hayas configurado; ver Reglas de la pasarela.
- Anota las últimas 500 peticiones de cada servicio para la pestaña Peticiones.
- Cuenta peticiones, respuestas y latencia para las métricas.
Los contenedores solo escuchan en 127.0.0.1: lo único que llega desde la red es lo que pasa por la pasarela.