# Olimpia Docs > Documentación de Olimpia, el cloud de Buenos Aires: apps, Postgres, Redis y buckets compatibles con S3, operables desde la consola o desde tu agente por MCP. # Olimpia para agentes Source: https://docs.olimpia.dev/agentes ![Un mecanismo de engranajes de bronce junto a un busto de Hermes, frente al Río de la Plata, en acuarela](/art/home-agentes.webp) Olimpia está pensada para que la operen personas desde la consola **y** agentes desde tu editor o tu terminal. Conectá Claude Code, Codex, Cursor o cualquier cliente MCP y pedile cosas como: - "Desplegá esta carpeta en Olimpia." - "Creale una base Postgres a la app `api` y corré las migraciones." - "¿Por qué falló el último deploy de `web`? Arreglalo." - "Apuntá `app.miempresa.com` a la app `web`." El agente usa las mismas reglas y permisos que la consola: no puede hacer nada que vos no puedas hacer, y te pide confirmación antes de borrar. ## En tres pasos 1. **Conectá el servidor MCP** ```bash claude mcp add --transport http olimpia https://api.olimpia.dev/mcp ``` Otros clientes en [Conectar tu agente](/agentes/conectar). 2. **Autorizá** La primera vez se abre olimpia.dev para que apruebes la conexión con tu sesión. Nunca le pasás tu contraseña al agente. 3. **Instalá la skill (opcional)** ```bash bunx skills add olimpiacloud/olimpia-skills ``` Le enseña al agente el flujo de deploy, cómo preparar cada stack y qué hacer cuando un build falla. Ver [Skill y plugin](/agentes/skill). ## Qué puede hacer | Para | Herramientas | | --- | --- | | Conectarse | `login` | | Descubrir | `list_projects`, `get_project`, `get_app`, `get_usage` | | Desplegar | `create_app`, `get_upload_url`, `deploy`, `get_deployment`, `rollback`, `cancel_deployment` | | Configurar | `update_app`, `get_env`, `set_env`, `create_project` | | Datos | `create_resource`, `connect_resource`, `get_connection`, `set_public_access`, `list_tables`, `query_postgres` | | Dominios | `add_domain`, `check_domain`, `remove_domain` | | Observar | `get_logs`, `get_deployment` | | Borrar | `delete_app`, `delete_resource` | Referencia completa en [Herramientas](/agentes/herramientas). ## Datos del servidor | | | | --- | --- | | URL | `https://api.olimpia.dev/mcp` | | Transporte | Streamable HTTP, sin estado | | Autorización | OAuth 2.1 con PKCE, registro dinámico y CIMD; o `Authorization: Bearer` con un token personal | | Descubrimiento | `/.well-known/oauth-protected-resource` y `/.well-known/oauth-authorization-server` | --- # CI y tokens Source: https://docs.olimpia.dev/agentes/ci-y-tokens OAuth necesita a una persona que apruebe en el navegador. Para CI, scripts o agentes autónomos, usá un [token personal](/cuenta/tokens). ## Crear el token En **Cuenta → Agentes y tokens → Tokens personales**, creá un token. Empieza con `olimpia_pat_`, tiene los mismos permisos que tu cuenta y se muestra una sola vez. Guardalo como secreto (`OLIMPIA_TOKEN`). ## MCP con un token Cualquier cliente MCP que permita headers puede saltear OAuth: ```json mcp.json { "mcpServers": { "olimpia": { "type": "http", "url": "https://api.olimpia.dev/mcp", "headers": { "Authorization": "Bearer ${OLIMPIA_TOKEN}" } } } } ``` Con Claude Code: ```bash claude mcp add --transport http olimpia https://api.olimpia.dev/mcp \ --header "Authorization: Bearer $OLIMPIA_TOKEN" ``` ## Claude Code o Codex en CI Un agente en GitHub Actions puede desplegar y diagnosticar con el token: ```yaml .github/workflows/agente.yml - name: Revisar el deploy con Claude Code env: ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} OLIMPIA_TOKEN: ${{ secrets.OLIMPIA_TOKEN }} run: | claude mcp add --transport http olimpia https://api.olimpia.dev/mcp \ --header "Authorization: Bearer $OLIMPIA_TOKEN" claude -p "Revisá el último deploy de la app web en Olimpia y, si falló, explicá por qué." ``` ## API REST El mismo token sirve para la [API REST](/cuenta/api). Para desplegar desde un pipeline sin agente, seguí [Deploy desde tu propio CI](/apps/ci-propio). ## Qué no puede hacer un token Con un token no se pueden ver ni cerrar sesiones, crear otros tokens ni vincular GitHub. Esas acciones necesitan una sesión en el navegador. --- # Conectar tu agente Source: https://docs.olimpia.dev/agentes/conectar El servidor MCP de Olimpia está en: ```txt https://api.olimpia.dev/mcp ``` Cualquier cliente que soporte servidores MCP remotos por HTTP se puede conectar. La primera vez, el cliente abre olimpia.dev para que autorices la conexión con tu sesión. ## Por cliente **Claude Code** ```bash claude mcp add --transport http olimpia https://api.olimpia.dev/mcp ``` Después, dentro de Claude Code, corré `/mcp`, elegí `olimpia` y autorizá en el navegador. También podés instalar el [plugin de Olimpia](/agentes/skill#plugin-de-claude-code), que trae el servidor y la skill juntos. **Codex** ```bash codex mcp add olimpia --url https://api.olimpia.dev/mcp ``` Codex abre el navegador para autorizar. Si no lo hace, corré `codex mcp login olimpia`. **Cursor** Agregá esto en `~/.cursor/mcp.json` (o en `.cursor/mcp.json` del proyecto): ```json mcp.json { "mcpServers": { "olimpia": { "url": "https://api.olimpia.dev/mcp" } } } ``` Cursor muestra **Needs login** en Settings → MCP: tocalo para autorizar. **VS Code** Agregá esto en `.vscode/mcp.json`: ```json .vscode/mcp.json { "servers": { "olimpia": { "type": "http", "url": "https://api.olimpia.dev/mcp" } } } ``` Al iniciar el servidor, VS Code te pide autorizar en el navegador. **Windsurf** Agregá esto en `~/.codeium/windsurf/mcp_config.json`: ```json mcp_config.json { "mcpServers": { "olimpia": { "serverUrl": "https://api.olimpia.dev/mcp" } } } ``` **Claude** En Claude (web o escritorio), abrí **Settings → Connectors → Add custom connector**, poné `Olimpia` como nombre y `https://api.olimpia.dev/mcp` como URL, y autorizá. **Otros** Cualquier cliente MCP con soporte de servidores remotos: ```json { "mcpServers": { "olimpia": { "url": "https://api.olimpia.dev/mcp" } } } ``` Si tu cliente no soporta OAuth, usá un [token personal](/agentes/ci-y-tokens). ## Qué pasa al autorizar 1. El cliente descubre el servidor de autorización de Olimpia y se registra solo. 2. Se abre `olimpia.dev` con una pantalla de consentimiento que dice qué agente pide acceso. 3. Si aprobás, el cliente recibe un token de acceso que dura una hora y se renueva solo. Ves y revocás cada agente conectado en **Cuenta → Agentes y tokens**. ## En una máquina remota Si tu agente corre en un servidor por SSH, un contenedor o un devcontainer, no puede abrir tu navegador. Con Claude Code: ```bash claude mcp login olimpia --no-browser ``` Abrí la URL que imprime en tu computadora, aprobá, copiá el código de conexión que te muestra Olimpia y pegalo donde Claude Code pide la URL de retorno. Con el [plugin de Olimpia](/agentes/skill#plugin-de-claude-code), el agente te da un enlace y te pide un código de 8 caracteres: lo abrís en cualquier dispositivo, autorizás y le pasás el código. ## Probar la conexión Pedile al agente: "¿Qué proyectos tengo en Olimpia?". Debería llamar a `list_projects` y mostrarte tus proyectos. --- # Esta documentación, para agentes Source: https://docs.olimpia.dev/agentes/docs-para-agentes Todo lo que ves en docs.olimpia.dev también se puede leer sin HTML, para que tu agente encuentre la respuesta sin raspar páginas. ## Archivos | URL | Qué es | | --- | --- | | [`/llms.txt`](https://docs.olimpia.dev/llms.txt) | Índice de toda la documentación, ordenado como la barra lateral, con un resumen de cada página. | | [`/llms-full.txt`](https://docs.olimpia.dev/llms-full.txt) | Toda la documentación en un solo archivo de Markdown. | | `/.md` | El Markdown de cualquier página. Por ejemplo, [`/apps/github.md`](/apps/github.md). | | [`/skill.md`](https://docs.olimpia.dev/skill.md) | Una skill generada con el mapa de la documentación. | | [`/agent-readability.json`](https://docs.olimpia.dev/agent-readability.json) | Manifiesto con todo lo que esta documentación ofrece a los agentes. | | [`/sitemap.xml`](https://docs.olimpia.dev/sitemap.xml) | Todas las páginas. | Cada página tiene además **Copiar como Markdown** y **Abrir en** ChatGPT, Claude y otros, en las acciones de la página. ## Para darle contexto a tu agente Pegale el índice al empezar una tarea: ```txt Leé https://docs.olimpia.dev/llms.txt y usalo para responder sobre Olimpia. ``` O traé una página puntual: ```bash curl https://docs.olimpia.dev/postgres/backups.md ``` ## También en olimpia.dev [`olimpia.dev/llms.txt`](https://olimpia.dev/llms.txt) resume la plataforma para modelos: qué es, cómo conectar el servidor MCP y cómo funcionan los deploys. --- # Flujos comunes Source: https://docs.olimpia.dev/agentes/flujos ## Desplegar una carpeta local ```txt create_app(name: "web", source: "upload", port: 3000) → upload.command_git (o command_tar si no hay git) deploy(app: "web", source_key: "", message: "primer deploy") get_deployment(app: "web", wait_seconds: 50) # repetir mientras esté queued, building o deploying get_logs(app: "web", since: "5m") ``` Para subir código nuevo después: `get_upload_url` → subir → `deploy(source_key)`. :::tip `active` solo significa que el contenedor arrancó. Verificá con `curl -sS -o /dev/null -w '%{http_code}' ` y revisá `get_logs`. ::: ## Desplegar desde GitHub ```txt create_app(name: "api", source: "github", repo: "acme/api", branch: "main") get_deployment(app: "api", wait_seconds: 50) ``` Desde ahí, cada push a `main` despliega solo. Si `create_app` devuelve `invalid_repo`, la GitHub App de Olimpia no está instalada en ese repo: la persona tiene que agregarlo desde la consola (**Apps → Nueva app**), o se puede desplegar con `source=upload`. ## Imagen de Docker ```txt create_app(name: "uptime", source: "image", image: "louislam/uptime-kuma:2", port: 3001) ``` ## Base de datos para una app ```txt create_resource(kind: "postgres", name: "main", connect_to_app: "api") deploy(app: "api") ``` `connect_to_app` carga `DATABASE_URL` en la app. Lo mismo con `kind: "redis"` (`REDIS_URL`) y `kind: "bucket"` (variables `AWS_*` y `BUCKET_NAME`). Para una base que ya existe: `connect_resource(app, kind, name)`. ## Revisar y arreglar datos ```txt list_tables(database: "main") query_postgres(database: "main", sql: "select id, email from users order by created_at desc limit 20") query_postgres(database: "main", sql: "update users set plan = 'pro' where id = 42", write: true) ``` Antes de cualquier sentencia que borre o reescriba datos, el agente tiene que pedir confirmación. ## Dominio propio ```txt add_domain(app: "web", domain: "app.acme.com") # devuelve los registros DNS check_domain(app: "web", domain: "app.acme.com") # repetir hasta active ``` ## Variables de entorno ```txt get_env(app: "api") set_env(app: "api", set: { "LOG_LEVEL": "debug" }, remove: ["OLD_FLAG"], redeploy: true) ``` ## Arreglar un deploy que falló ```txt get_deployment(app: "web") # leer error y build_log_tail # corregir la causa en el código get_upload_url(app: "web") → subir → deploy(app: "web", source_key: "...") ``` | `error` | Qué hacer | | --- | --- | | `source_failed` | Upload: la subida venció o no terminó. GitHub: revisar acceso al repo y la rama. | | `build_failed` | Leer `build_log_tail` y corregir el código o la configuración. | | `release_failed` | El proceso termina al arrancar: `get_logs(since: "5m")`. | | `import_failed`, `internal_error` | Reintentar una vez con `deploy`. | No reintentes el mismo build sin cambios, salvo con `internal_error`. Más casos en [Si algo falla](/apps/problemas). ## Volver atrás ```txt get_app(app: "web") # lista los últimos deploys rollback(app: "web", deployment: "") ``` --- # Herramientas Source: https://docs.olimpia.dev/agentes/herramientas Todas las herramientas aceptan nombres o ids (`app: "web"` o el UUID), y `project` es opcional cuando la cuenta tiene un solo proyecto. Los errores vuelven con la acción a seguir, para que el agente se pueda corregir solo. :::note[Convenciones] - **Nombres**: entre 3 y 63 caracteres, minúsculas, números y guiones. - **`kind`**: `postgres`, `redis` o `bucket`. - Las herramientas de lectura están marcadas como `readOnly`; las de borrado, como `destructive`. ::: ## Conexión ### `login` Conecta el agente a la cuenta cuando se usa el plugin de Claude Code. Sin `code`, devuelve un enlace para que la persona autorice en olimpia.dev; con `code`, canjea el código de 8 caracteres que recibió. También informa qué cuenta está conectada. | Parámetro | Tipo | | | --- | --- | --- | | `code` | string | Opcional. El código de conexión. | ## Descubrir ### `list_projects` Lista los proyectos con la cantidad de recursos y la salud de sus apps. Sin parámetros. ### `get_project` Resumen de un proyecto: cada app (estado, URL, origen), Postgres, Redis y bucket, con enlaces a la consola. Es el mejor punto de partida para descubrir nombres. | Parámetro | Tipo | | | --- | --- | --- | | `project` | string | Opcional. | ### `get_app` Detalle de una app: URL, origen, configuración de build, bases conectadas, dominios y últimos deploys. | Parámetro | Tipo | | | --- | --- | --- | | `app` | string | Nombre o id. | ### `get_usage` Uso actual de un proyecto: apps online y construyendo, objetos y bytes en buckets. ## Desplegar ### `create_app` Crea una app. Con `source=upload` (por defecto) la respuesta trae el comando para subir la carpeta local; después hay que llamar a `deploy` con el `source_key`. | Parámetro | Tipo | | | --- | --- | --- | | `name` | string | Nombre de la app, también usado como subdominio. | | `source` | `upload` \| `github` \| `image` | Opcional. `upload` por defecto. | | `repo` | string | Para `github`: `owner/name`. | | `branch` | string | Para `github`: rama a desplegar. Cada push redespliega. | | `image` | string | Para `image`: por ejemplo `nginx:1.29`. | | `root_dir` | string | Subcarpeta a construir, para monorepos. | | `dockerfile` | string | Ruta al Dockerfile relativa a `root_dir`. | | `port` | number | Puerto en el que escucha la app (3000 por defecto). | | `env` | object | Variables a cargar antes del primer build. | ### `get_upload_url` Devuelve una URL de subida nueva (vale 15 minutos) y el comando para subir la carpeta de una app con `source=upload`. ### `deploy` Construye y despliega una app. Espera hasta `wait_seconds` y devuelve el estado, con el final del log si falló. | Parámetro | Tipo | | | --- | --- | --- | | `app` | string | Nombre o id. | | `source_key` | string | Para `upload`: la clave de la subida. Sin ella, reconstruye la última subida. | | `message` | string | Descripción corta del cambio, visible en el historial. | | `wait_seconds` | number | 0 a 50, 45 por defecto. | ### `get_deployment` Estado de un deploy (el último por defecto), opcionalmente esperando mientras corre. Incluye las últimas líneas del log cuando falló o está construyendo. | Parámetro | Tipo | | | --- | --- | --- | | `app` | string | Nombre o id. | | `deployment` | string | Opcional. Id del deploy. | | `wait_seconds` | number | 0 a 50, 0 por defecto. | ### `rollback` Vuelve a un deploy anterior que haya estado online, reusando su imagen sin build. | Parámetro | Tipo | | | --- | --- | --- | | `app` | string | Nombre o id. | | `deployment` | string | Id del deploy (ver `get_app`). | ### `cancel_deployment` Cancela un deploy en cola o construyendo (el último por defecto). ## Configurar ### `update_app` Cambia la configuración de una app. Los cambios de build se aplican en el próximo deploy. | Parámetro | Tipo | | | --- | --- | --- | | `subdomain` | string | Subdominio nuevo en `olimpia.cc`. | | `branch` | string | Rama de GitHub. | | `image` | string | Imagen de Docker. | | `root_dir`, `dockerfile`, `port` | | Como en `create_app`. | | `auto_deploy` | boolean | Redesplegar en cada push. | ### `get_env` Lista las variables de una app. Los valores que parecen secretos (nombres con `SECRET`, `TOKEN`, `KEY`, `PASSWORD`, `AUTH`, o URLs con credenciales) vuelven ocultos salvo con `reveal: true`. ### `set_env` Agrega, cambia o borra variables, combinándolas con las existentes. Se aplican en el próximo deploy. | Parámetro | Tipo | | | --- | --- | --- | | `set` | object | Variables a agregar o pisar. `PORT` cambia el puerto de la app. | | `remove` | string[] | Nombres a borrar. | | `redeploy` | boolean | Desplegar ahora. `false` por defecto. | ### `create_project` Crea un proyecto. Parámetro: `name`. ## Datos ### `create_resource` Crea una base Postgres, una instancia de Redis o un bucket. Devuelve los datos de conexión. | Parámetro | Tipo | | | --- | --- | --- | | `kind` | `postgres` \| `redis` \| `bucket` | | | `name` | string | | | `connect_to_app` | string | Opcional. Además, carga las variables en esa app. | ### `get_connection` Datos de conexión: la URL interna para apps en Olimpia, la URL pública si está habilitada y las credenciales S3 de los buckets. Son secretos. ### `connect_resource` Carga las variables de conexión en una app y la redespliega. | Parámetro | Tipo | | | --- | --- | --- | | `app` | string | La app que va a usar el recurso. | | `kind`, `name` | | El recurso. | | `env_key` | string | Para Postgres y Redis: nombre de la variable (`DATABASE_URL` o `REDIS_URL` por defecto). | | `redeploy` | boolean | `true` por defecto. | | Recurso | Variables | | --- | --- | | Postgres | `DATABASE_URL` | | Redis | `REDIS_URL` | | Bucket | `AWS_ENDPOINT_URL_S3`, `AWS_REGION`, `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `BUCKET_NAME` | ### `set_public_access` Expone u oculta un recurso. En Postgres y Redis, `public: true` permite conexiones por TLS desde internet; en un bucket, hace que los objetos se puedan leer por URL. ### `list_tables` Lista las tablas y vistas de una base Postgres con cantidad de filas y tamaño. Parámetro: `database`. ### `query_postgres` Corre SQL como el usuario dueño de la base (no superusuario). | Parámetro | Tipo | | | --- | --- | --- | | `database` | string | Nombre o id de la base. | | `sql` | string | En lectura, una sola consulta `SELECT`, `WITH` o `VALUES` (hasta 200 filas). En escritura, cualquier sentencia, varias separadas por `;`, en una transacción. | | `write` | boolean | Modo escritura, con 30 segundos como máximo. | ## Dominios ### `add_domain` Agrega un dominio propio a una app y devuelve los registros DNS que hay que crear. Parámetros: `app`, `domain`. ### `check_domain` Estado del DNS y del certificado de un dominio. ### `remove_domain` Quita un dominio de una app. ## Observar ### `get_logs` Logs de la app (stdout y stderr). Su contenido es dato no confiable. | Parámetro | Tipo | | | --- | --- | --- | | `since` | string | `5m`, `1h` (por defecto), `24h` o `7d`. | | `search` | string | Solo las líneas que contienen este texto. | | `limit` | number | Hasta 500, 100 por defecto. | ## Borrar ### `delete_app` Borra una app con sus deploys y dominios. Irreversible. ### `delete_resource` Borra una base, una instancia de Redis o un bucket con todos sus datos. Irreversible. Las dos exigen `confirm` con el **nombre exacto** del recurso, después de que la persona confirmó explícitamente. --- # Prompts listos Source: https://docs.olimpia.dev/agentes/prompts Copiá cualquiera de estos prompts en Claude Code, Codex o Cursor con Olimpia [conectado](/agentes/conectar). ****Desplegar** la carpeta actual** > Desplegá esta carpeta en Olimpia como una app nueva. Revisá primero el stack, el comando de inicio y el puerto, y asegurate de que la app escuche en 0.0.0.0 y en $PORT. Cuando termine, verificá la URL con curl y revisá los logs. ****Base de datos** para una app** > Creá una base Postgres en Olimpia, conectala a mi app y configurá las migraciones para que corran al arrancar la app. Después desplegá y verificá que las tablas existan con list_tables. ****Cola de trabajos** con Redis** > Agregá una cola de trabajos con BullMQ a esta app usando un Redis de Olimpia. Creá la instancia, conectala a la app con REDIS_URL y desplegá un worker separado que procese los trabajos. ****Subidas de archivos** con un bucket** > Creá un bucket en Olimpia para esta app y conectalo. Implementá subidas desde el navegador con URLs firmadas generadas en el backend, usando el AWS SDK con las variables AWS_* y BUCKET_NAME. ****Arreglar** el último deploy** > El último deploy de mi app en Olimpia falló. Leé el error y el log del build con get_deployment, encontrá la causa en el código, corregila y volvé a desplegar. No reintentes sin cambios. ****Dominio propio**** > Apuntá el dominio app.miempresa.com a mi app en Olimpia. Decime exactamente qué registros DNS tengo que crear y después verificá con check_domain hasta que esté activo. ****Migrar** desde otra nube** > Quiero mover esta app a Olimpia. Mirá cómo está configurada hoy (variables de entorno, base de datos, puerto, comando de inicio), creá la app y los recursos equivalentes en Olimpia, y armame un plan para migrar los datos de Postgres con pg_dump y psql usando el acceso externo temporal. No borres nada sin preguntarme. ****Auditoría** de un proyecto** > Revisá mi proyecto en Olimpia: listá apps, bases y buckets, decime cuáles tienen acceso público habilitado, qué apps tienen deploys fallidos y si hay recursos que no usa ninguna app. No cambies nada, solo reportá. --- # Autorización y límites Source: https://docs.olimpia.dev/agentes/seguridad ## OAuth 2.1 Olimpia es su propio servidor de autorización: - **Descubrimiento.** El servidor publica `/.well-known/oauth-protected-resource` (RFC 9728) y `/.well-known/oauth-authorization-server` (RFC 8414). Un pedido sin token a `/mcp` responde `401` con `WWW-Authenticate` apuntando a esos documentos. - **Registro de clientes.** Por Client ID Metadata Document (el `client_id` es una URL `https`) o por registro dinámico (`POST /oauth/register`, solo clientes públicos). - **PKCE S256 obligatorio**, `iss` en la respuesta (RFC 9207) y `resource` validado (RFC 8707). - **Consentimiento** en olimpia.dev, con tu sesión. Ves qué agente pide acceso antes de aprobar. | Credencial | Duración | | --- | --- | | Código de autorización | 10 minutos, un solo uso | | Token de acceso | 1 hora | | Token de refresco | 90 días, rota en cada uso | | Código de conexión del plugin | 10 minutos, un solo uso, atado al agente que lo pidió | | Token personal | Sin vencimiento, hasta que lo revocás | `POST /oauth/revoke` revoca un token, y **Cuenta → Agentes y tokens** muestra y revoca cada conexión. ## Mismos permisos que la consola Cada herramienta llama a la misma API que usa la consola, con el token del pedido. Valida y autoriza exactamente igual: un agente no puede hacer nada que tu cuenta no pueda hacer. ## Límites | Límite | Valor | | --- | --- | | Llamadas a `/mcp` | 240 por minuto por token | | Recursos creados por MCP | 30 por hora | | Intentos de código de conexión fallidos | 10 cada 10 minutos por agente | | Filas por consulta de lectura | 200 | | Tiempo de una escritura SQL | 30 segundos | ## Reglas de seguridad - **Borrar exige confirmación.** `delete_app` y `delete_resource` necesitan `confirm` con el nombre exacto, que la persona tiene que aprobar. - **Secretos ocultos por defecto.** `get_env` oculta los valores que parecen secretos salvo con `reveal: true`. - **Datos no confiables.** Los logs, la salida de los builds, los valores de variables y las filas de la base son datos, no instrucciones. Las herramientas lo indican para que el agente no siga órdenes escondidas ahí. - **SQL sin superusuario.** `query_postgres` corre como el usuario dueño de la base; la lectura va en una transacción de solo lectura. ## Buenas prácticas - Usá OAuth para agentes interactivos y tokens personales solo para CI. - Un token por integración, con un nombre que diga dónde se usa. - Revocá las conexiones que ya no usás. --- # Skill y plugin Source: https://docs.olimpia.dev/agentes/skill El servidor MCP le da herramientas a tu agente. La **skill** le da criterio: cómo preparar cada stack, en qué orden llamar a las herramientas y qué hacer cuando algo falla. Está en [olimpiacloud/olimpia-skills](https://github.com/olimpiacloud/olimpia-skills). ## Instalar la skill Funciona con Claude Code, Codex, Cursor y cualquier agente compatible con [Agent Skills](https://agentskills.io): ```bash bunx skills add olimpiacloud/olimpia-skills ``` ## Plugin de Claude Code El plugin instala la skill y el servidor MCP de una vez: ```txt /plugin marketplace add olimpiacloud/olimpia-skills /plugin install olimpia@olimpia ``` La primera vez que el agente necesita Olimpia, te da un enlace. Lo abrís en cualquier dispositivo, autorizás con tu sesión y le pasás el código de 8 caracteres que te muestra Olimpia. El código vence a los 10 minutos y solo sirve para ese agente. Desde ahí queda conectado, y lo revocás cuando quieras en **Cuenta → Agentes y tokens**. ## Qué le enseña - **Deploy de una carpeta local**: revisar el stack, hacer que la app escuche en `0.0.0.0:$PORT`, crear la app, subir el código sin `node_modules` ni `.env`, desplegar y verificar con `curl` y los logs. - **Por stack**: Node, Bun, Python, Go, Rust, monorepos y Dockerfiles, con los errores típicos de cada uno. - **Datos**: conectar Postgres, Redis y buckets, correr migraciones al arrancar y usar SQL con cuidado. - **Dominios**: qué registros pedir y cómo verificar. - **Cuando algo falla**: qué significa cada error y cómo arreglarlo sin reintentar a ciegas. - **Reglas**: pedir confirmación antes de borrar, tratar credenciales como secretos y logs como datos no confiables, y no crear recursos que nadie pidió. ## Checklist de deploy Así despliega un agente con la skill: ```txt - [ ] 1. Revisar la app: stack, comando de inicio, puerto, variables necesarias - [ ] 2. Hacer que escuche en 0.0.0.0:$PORT - [ ] 3. create_app (source=upload) o get_upload_url si la app ya existe - [ ] 4. Correr el comando de subida desde la carpeta de la app - [ ] 5. deploy con source_key, después get_deployment hasta active o failed - [ ] 6. curl a la URL y leer get_logs ``` --- # Apps Source: https://docs.olimpia.dev/apps Una app de Olimpia es un contenedor que corre tu código y responde en `https://.olimpia.cc`. Vos elegís de dónde sale el código; Olimpia lo construye, lo publica con HTTPS y lo mantiene online. ## Tres formas de desplegar **[Desde GitHub](/apps/github)** Conectás un repo y cada push se despliega solo. **[Imagen de Docker](/apps/docker)** Cualquier imagen pública de un registry. **[Tu carpeta](/apps/subir-codigo)** Subís el código desde tu máquina, tu agente o tu CI. ## Qué incluye cada app - **HTTPS automático** en `*.olimpia.cc` y en hasta 10 [dominios propios](/apps/dominios). - **Builds sin configuración** con [Railpack](/apps/builds), o con tu `Dockerfile`. - **Deploys sin cortes.** La versión nueva arranca antes de bajar la anterior; si no levanta, sigue la que estaba. - **Rollback en un clic** a cualquier deploy anterior, sin volver a construir. - **[Variables de entorno](/apps/variables) cifradas**, disponibles en el build y al correr. - **[Logs y métricas](/apps/logs-y-metricas)**: el log de cada build, los logs de la app en vivo y CPU, memoria y disco de los últimos 7 días. - **[Red interna](/plataforma/red-interna)** hacia tus bases Postgres y Redis. - **Sin topes de recursos.** Las apps no tienen límite fijo de CPU ni de memoria: usan lo que necesitan y pagás por uso. ## Lo que tu app necesita - Escuchar en `0.0.0.0` y en el puerto de `PORT` (3000 por defecto). - Quedarse corriendo en primer plano. - Escribir sus logs en stdout y stderr. - Guardar los datos en Postgres, Redis o un bucket: el disco del contenedor se borra en cada deploy. ## La app en la consola Cada app tiene estas pestañas: | Pestaña | Para qué | | --- | --- | | **Deploys** | Historial, estado, log del build y rollback. | | **Logs** | Salida de la app en vivo, con búsqueda. | | **Métricas** | CPU, memoria y lecturas y escrituras de disco. | | **Variables** | Variables de entorno y conexión a las bases del proyecto. | | **Dominios** | Tu subdominio de `olimpia.cc` y tus dominios propios. | | **Configuración** | Rama, carpeta raíz, Dockerfile, puerto, deploy automático y borrado. | --- # Builds Source: https://docs.olimpia.dev/apps/builds Cada build corre en su propia máquina aislada, separada de donde corren las apps. Si tu repositorio tiene un `Dockerfile` en la ruta configurada, Olimpia lo usa. Si no, [Railpack](https://railpack.com) detecta el lenguaje y arma una imagen optimizada. ## Lenguajes detectados | Lenguaje | Cómo se detecta | Cómo arranca | | --- | --- | --- | | Node | `package.json` y el lockfile (npm, pnpm, yarn) | Script `start` | | Bun | `bun.lock` | Script `start` | | Deno | `deno.json` | Tarea `start` o el archivo principal | | Python | `requirements.txt`, `pyproject.toml` (uv, poetry) o `Pipfile` | `Procfile` o `main.py` | | Go | `go.mod` | El binario compilado | | Rust | `Cargo.toml` | El binario en release | | PHP | `composer.json` o `index.php` | Servidor PHP | | Ruby | `Gemfile` | `Procfile` o Rails | | Java | `pom.xml` o `build.gradle` | El jar compilado | | Elixir | `mix.exs` | Release de Mix | | Sitio estático | Solo `index.html`, o el `dist` de un build | Servidor de archivos | ## Ejemplos por stack **Node** ```json package.json { "scripts": { "build": "tsc", "start": "node dist/server.js" }, "engines": { "node": "22" } } ``` Next.js: `"start": "next start"` lee `PORT` solo. **Python** ```txt Procfile web: uvicorn main:app --host 0.0.0.0 --port $PORT ``` Django: `gunicorn proyecto.wsgi --bind 0.0.0.0:$PORT`, con `collectstatic` en el build. **Go** ```go main.go port := os.Getenv("PORT") if port == "" { port = "3000" } http.ListenAndServe("0.0.0.0:"+port, mux) ``` **Rust** ```rust main.rs let port = std::env::var("PORT").unwrap_or_else(|_| "3000".into()); let listener = tokio::net::TcpListener::bind(format!("0.0.0.0:{port}")).await?; ``` ## Cuando la detección no alcanza Si Railpack elige un comando equivocado, el log del build muestra su plan. Corregilo con: - un script `start` en `package.json`, - un `Procfile` con la línea `web:`, - un `railpack.json`: ```json railpack.json { "deploy": { "startCommand": "node dist/server.js" } } ``` - o un `Dockerfile`. ## Dockerfile Configurá **Dockerfile** con la ruta relativa a la carpeta raíz (`Dockerfile` o `docker/Dockerfile.prod`). Los builds multi-stage funcionan. La imagen tiene que escuchar en `$PORT`. ## Variables en el build Todas las variables de la app llegan al build como build args y como secretos de BuildKit, y también al contenedor cuando corre. Dos cosas a tener en cuenta: - **El build no llega a tus bases.** Corre en otras máquinas, fuera de la red interna. Corré las migraciones al arrancar, no en el build: ```json package.json { "scripts": { "start": "prisma migrate deploy && node server.js" } } ``` - **Las variables públicas se hornean.** Frameworks como Next.js (`NEXT_PUBLIC_*`) o Vite (`VITE_*`) las copian al bundle durante el build. Si las cambiás, hace falta un build nuevo. ## Límites - Cada build tiene **30 minutos** como máximo. - Los builds de distintas apps corren en paralelo, cada uno en su máquina. - El disco del contenedor no persiste entre deploys: guardá los datos en Postgres, Redis o un bucket. --- # Deploy desde tu propio CI Source: https://docs.olimpia.dev/apps/ci-propio El [deploy automático con GitHub](/apps/github) despliega cada push sin pasos extra. Si preferís que tu pipeline decida cuándo desplegar (por ejemplo, después de correr los tests), usá una app con [código subido](/apps/subir-codigo) y llamá a la API desde tu CI. ## Qué necesitás 1. Una app creada con `source: "upload"`. Ver [Subir tu carpeta](/apps/subir-codigo#el-flujo). 2. Un [token personal](/cuenta/tokens), guardado como secreto del CI (`OLIMPIA_TOKEN`). 3. El `id` de la app, como variable del CI (`OLIMPIA_APP_ID`). ## GitHub Actions ```yaml .github/workflows/deploy.yml name: Deploy a Olimpia on: push: branches: [main] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - run: npm ci && npm test deploy: needs: test runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Subir y desplegar env: OLIMPIA_TOKEN: ${{ secrets.OLIMPIA_TOKEN }} APP_ID: ${{ vars.OLIMPIA_APP_ID }} run: | api=https://api.olimpia.dev auth="Authorization: Bearer $OLIMPIA_TOKEN" upload=$(curl -fsS -X POST -H "$auth" "$api/apps/$APP_ID/source") git archive --format=tar.gz --prefix=src/ -o /tmp/src.tar.gz HEAD curl -fsS -X PUT -T /tmp/src.tar.gz "$(echo "$upload" | jq -r .upload_url)" curl -fsS -X POST -H "$auth" -H 'content-type: application/json' \ -d "{\"source\": \"$(echo "$upload" | jq -r .key)\", \"message\": \"$GITHUB_SHA\"}" \ "$api/apps/$APP_ID/deployments" > /dev/null ``` ## GitLab CI ```yaml .gitlab-ci.yml deploy: stage: deploy image: alpine:3.22 only: [main] script: - apk add --no-cache curl jq git - api=https://api.olimpia.dev - auth="Authorization: Bearer $OLIMPIA_TOKEN" - upload=$(curl -fsS -X POST -H "$auth" "$api/apps/$OLIMPIA_APP_ID/source") - git archive --format=tar.gz --prefix=src/ -o /tmp/src.tar.gz HEAD - curl -fsS -X PUT -T /tmp/src.tar.gz "$(echo "$upload" | jq -r .upload_url)" - > curl -fsS -X POST -H "$auth" -H 'content-type: application/json' -d "{\"source\": \"$(echo "$upload" | jq -r .key)\", \"message\": \"$CI_COMMIT_SHA\"}" "$api/apps/$OLIMPIA_APP_ID/deployments" ``` ## Esperar el resultado El `POST` de deployments responde enseguida. Para que el pipeline falle si el deploy falla, consultá el último deploy hasta que termine: ```bash until status=$(curl -fsS -H "$auth" "$api/apps/$APP_ID/deployments" | jq -r '.[0].status'); \ [ "$status" = active ] || [ "$status" = failed ] || [ "$status" = canceled ]; do sleep 10; done [ "$status" = active ] ``` :::note Las apps conectadas a GitHub se despliegan solas en cada push y no necesitan esto. ::: --- # Deploys y rollbacks Source: https://docs.olimpia.dev/apps/deploys ## Estados | Estado | Qué pasa | | --- | --- | | **En cola** | El deploy espera su turno. | | **Construyendo** | Se está construyendo la imagen. Ves el log en vivo. | | **Deployando** | La imagen está lista y se está levantando el contenedor nuevo. | | **Online** | El contenedor arrancó y recibe tráfico. | | **Falló** | El build o el arranque fallaron. El log muestra el motivo. | | **Cancelado** | Lo cancelaste vos o lo reemplazó un deploy más nuevo antes de empezar. | | **Reemplazado** | Estuvo online y lo reemplazó un deploy posterior. | Cada deploy muestra su origen: **Primer deploy**, **Push**, **Manual** o **Rollback**. ## Sin cortes Olimpia arranca el contenedor nuevo antes de bajar el anterior. Si el nuevo no levanta, el anterior sigue atendiendo y el deploy queda como **Falló**. Tus usuarios no ven un error mientras desplegás. :::note **Online** significa que el contenedor arrancó. Si tu app arranca pero falla al atender pedidos, mirá los [logs](/apps/logs-y-metricas). ::: ## Rollback En **Deploys**, abrí un deploy anterior que haya estado online y tocá **Volver a esta versión**. Olimpia reusa la imagen ya construida, sin build, así que el rollback tarda segundos. Olimpia guarda la imagen activa y las 5 más recientes de cada app. Las más viejas se borran solas. ## Cancelar Un deploy **En cola** o **Construyendo** se puede cancelar. La versión online no se toca. ## Concurrencia - Un solo deploy en curso por app. - Si llega un deploy nuevo, los que seguían en cola para esa app se cancelan. - Los builds de distintas apps corren en paralelo. --- # Imagen de Docker Source: https://docs.olimpia.dev/apps/docker Si ya tenés una imagen publicada, Olimpia la corre tal cual, sin construir nada. 1. **Elegí Imagen de Docker** En **Apps → Nueva app**, elegí **Imagen de Docker**. 2. **Indicá la imagen** Usá el nombre completo con su tag, por ejemplo `nginx:1.29` o `ghcr.io/owner/app:latest`. 3. **Indicá el puerto** El puerto en el que escucha el contenedor. Olimpia también lo pasa en la variable `PORT`. ## Actualizar la imagen Olimpia descarga la imagen al desplegar. Para traer una versión nueva: - Si usás un tag fijo (`app:1.4.2`), cambiá la imagen en **Configuración** y desplegá. - Si usás un tag móvil (`app:latest`), tocá **Deployar**: Olimpia vuelve a descargar la imagen. ## Límites - La imagen tiene que ser **pública**. Los registries privados todavía no están soportados. - Las imágenes de Docker no tienen deploy automático: Olimpia no se entera cuando publicás un tag nuevo. Para eso, [conectá GitHub](/apps/github) o [desplegá desde tu CI](/apps/ci-propio). --- # Dominios Source: https://docs.olimpia.dev/apps/dominios ## Tu subdominio de Olimpia Cada app responde en `https://.olimpia.cc`, con HTTPS incluido. Por defecto el subdominio es el nombre de la app; lo cambiás en **Dominios** o en **Configuración**. :::warning Al cambiar el subdominio, la dirección anterior deja de responder en el momento. ::: ## Agregar un dominio propio 1. **Agregá el dominio** En **Dominios → Agregar dominio**, escribí el dominio o subdominio, por ejemplo `app.tuempresa.com`. 2. **Cargá los registros DNS** La consola te muestra los registros a crear en tu proveedor de DNS: | Tipo | Nombre | Valor | | --- | --- | --- | | `CNAME` | `app` | `domains.olimpia.cc` | | `TXT` | (el que indique la consola) | (el que indique la consola) | El `TXT` es opcional: sirve para validar el dominio antes de apuntar el `CNAME`, útil si estás migrando un dominio que ya tiene tráfico. 3. **Esperá la verificación** Olimpia revisa el DNS cada 30 segundos, aunque cierres la página. Cuando el DNS apunta bien, emite el certificado HTTPS; suele tardar unos minutos. El dominio pasa por **Esperando DNS → Emitiendo certificado → Activo**. ## Dominios raíz Para usar un dominio raíz (`tuempresa.com`), tu proveedor de DNS tiene que permitir un `CNAME` en la raíz, con **CNAME flattening** o un registro **ALIAS**. Cloudflare, DNSimple y otros lo soportan. Si tu proveedor no, usá `www.tuempresa.com` y redirigí la raíz hacia ahí. ## Reglas - Hasta **10 dominios** por app. - Un dominio no puede estar en dos apps a la vez. - Un dominio que no se verifica en **7 días** se quita solo, para que nadie reserve dominios ajenos. - Si la app todavía no tiene un deploy online, el dominio queda en **Espera el primer deploy**. ## Quitar un dominio **Quitar dominio** deja de servir la app en ese dominio al instante. Podés volver a agregarlo cuando quieras. Acordate de borrar también el registro DNS. --- # Deploy desde GitHub Source: https://docs.olimpia.dev/apps/github Conectá un repositorio de GitHub y Olimpia se encarga del resto: cada push a la rama que elegiste dispara un build y un deploy sin downtime. No hace falta escribir un workflow ni guardar tokens en GitHub. ```txt git push ──▶ GitHub avisa a Olimpia ──▶ build ──▶ deploy sin cortes ──▶ online ``` ## Conectar GitHub 1. **Instalá la GitHub App de Olimpia** En **Apps → Nueva app**, tocá **Conectar GitHub**. GitHub te pide elegir la cuenta u organización y a qué repositorios puede acceder Olimpia. Solo pide permiso de lectura sobre el código. 2. **Elegí repositorio y rama** La consola lista los repositorios a los que tenés acceso. Elegí uno y la rama que querés desplegar, por ejemplo `main`. 3. **Ajustá el build si hace falta** - **Carpeta raíz**: para monorepos, la carpeta de la app (`apps/web`). - **Dockerfile**: la ruta dentro de la carpeta raíz, si querés construir con Docker. - **Puerto**: el puerto en el que escucha tu app. 4. **Creá la app** Olimpia construye el último commit de la rama y lo publica. A partir de ahí, cada push despliega solo. ## Cómo funciona el deploy automático - **Un push, un deploy.** Cada push a la rama configurada encola un deploy de ese commit. En el historial figura con el origen **Push**. - **Sin colas largas.** Hay un solo deploy en curso por app. Si llegan varios pushes seguidos, los que seguían en cola se cancelan y se construye el último. - **Sin cortes.** La versión nueva arranca antes de bajar la anterior. Si el contenedor nuevo no levanta, sigue corriendo el que estaba. - **Repos privados.** Funcionan igual: la GitHub App tiene acceso a los repositorios que elegiste al instalarla. Podés apagar el deploy automático desde **Configuración**. Con el deploy automático apagado, desplegás cuando quieras con **Deployar**, y Olimpia construye el último commit de la rama. ## Monorepos Creá una app por cada servicio del repositorio, todas apuntando al mismo repo con distinta **Carpeta raíz**: | App | Carpeta raíz | | --- | --- | | `web` | `apps/web` | | `api` | `apps/api` | | `worker` | `apps/worker` | Si un servicio necesita archivos de fuera de su carpeta (paquetes compartidos del workspace), dejá la carpeta raíz vacía y usá un `Dockerfile` en la raíz del repositorio. ## Permisos y acceso - Olimpia solo ve los repositorios que habilitaste en la GitHub App, y de esos, solo los que tu usuario de GitHub puede leer. - Para sumar o quitar repositorios, cambiá la instalación desde GitHub (**Settings → Applications → Installed GitHub Apps → Olimpia → Configure**). Los cambios se reflejan solos. - Si entrás a Olimpia con email, conectá tu cuenta de GitHub una vez para que la lista de repositorios se mantenga al día. ## Rollback Si un deploy rompe algo, abrí **Deploys**, elegí una versión anterior y tocá **Volver a esta versión**. Olimpia reusa la imagen ya construida, así que el rollback tarda segundos. Ver [Deploys y rollbacks](/apps/deploys). :::tip[¿Necesitás tests antes de desplegar?] Si querés correr tus tests en GitHub Actions y desplegar solo cuando pasan, usá una app con código subido y disparala desde tu workflow. Ver [Deploy desde tu propio CI](/apps/ci-propio). ::: --- # Logs y métricas Source: https://docs.olimpia.dev/apps/logs-y-metricas ## Logs del build Cada deploy guarda su log de build. Mientras construye lo ves en vivo; cuando termina, queda en el historial durante 30 días. Si un build falla, el final del log suele decir por qué: un comando de inicio que falta, un error de TypeScript, un lockfile desactualizado. Ver [Si algo falla](/apps/problemas). ## Logs de la app La pestaña **Logs** muestra lo que tu app escribe en stdout y stderr, en vivo y con búsqueda. Para que aparezcan, tu app tiene que escribir sus logs ahí, no en archivos. ```js console.log(JSON.stringify({ level: "info", msg: "pedido creado", id })); ``` :::tip Logs en una línea de JSON son más fáciles de buscar y filtrar. ::: ## Métricas La pestaña **Métricas** mide tu app cada minuto y guarda 7 días: | Métrica | Qué mide | | --- | --- | | **CPU** | Uso de CPU. 100 % equivale a 1 vCPU. | | **Memoria** | RSS y caché activa e inactiva. | | **IOPS** | Lecturas y escrituras de disco. | Elegí el período: última hora, 24 horas o 7 días. ## Desde tu agente Tu agente puede leer los logs con `get_logs` y el estado de cada deploy, con el final del log de build, con `get_deployment`. Ver [Herramientas](/agentes/herramientas). --- # Si algo falla Source: https://docs.olimpia.dev/apps/problemas Empezá por el deploy que falló: abrilo en **Deploys** y leé el error y el final del log del build. ## Por tipo de error | Error | Qué significa | Qué hacer | | --- | --- | --- | | `source_failed` | No se pudo traer el código. | GitHub: revisá que la rama exista y que la GitHub App siga teniendo acceso al repo. Código subido: la URL venció o la subida no terminó; subilo otra vez. | | `build_failed` | Falló Railpack o tu `Dockerfile`. | Leé el log del build. Mirá [Fallas de build](#fallas-de-build). | | `import_failed` | La imagen construida no se pudo guardar. | Es un problema de la plataforma. Desplegá de nuevo; si se repite, escribinos. | | `release_failed` | El contenedor no arrancó. | Casi siempre el proceso termina apenas arranca. Mirá los **Logs** de la app. | | `internal_error` | Error de la plataforma. | Desplegá de nuevo una vez. | | `timeout` | El build pasó los 30 minutos. | Revisá pasos lentos o usá un `Dockerfile` multi-stage con caché. | ## Fallas de build **No encuentra cómo arrancar la app** Agregá un script `start`, un `Procfile` o un `railpack.json` con `startCommand`. En monorepos, revisá la **Carpeta raíz**. Ver [Builds](/apps/builds#cuando-la-detección-no-alcanza). **El lockfile no coincide** `npm ci`, `pnpm install --frozen-lockfile` y `bun install --frozen-lockfile` fallan si el lockfile no está al día con `package.json`. Regeneralo en tu máquina, commitealo y desplegá. **Errores de TypeScript o lint** El build corre en modo producción. Corregí los errores en el código. **Falta una variable en el build** Variables como `NEXT_PUBLIC_*`, o código que lee variables mientras construye, necesitan estar cargadas antes del build. Agregala en **Variables** y desplegá. **El build se queda sin memoria** Bajá el paralelismo del build o pasá a un `Dockerfile` multi-stage. **Módulos nativos (sharp, bcrypt, canvas)** Suelen andar con Railpack. Si no, usá un `Dockerfile` basado en una imagen Debian completa. ## La app está Online pero no responde **Online** solo significa que el contenedor arrancó. Probá la URL y mirá los **Logs**. **Bad gateway o sin respuesta** Tu app escucha en `localhost` o en un puerto fijo. Hacé que escuche en `0.0.0.0` y en `$PORT`, o configurá el **Puerto** real de la app y desplegá. **Se reinicia una y otra vez** Falta una variable o la base. Revisá **Variables** y que la base esté conectada. **No conecta con la base** Estás usando `localhost` o la URL pública en lugar de la interna. Usá `DATABASE_URL` tal como la carga Olimpia. Si la base es nueva, corré las migraciones al arrancar. **404 al recargar una ruta de una SPA** Tu servidor tiene que devolver `index.html` para las rutas que no son archivos. ## Veo una página de Olimpia en lugar de mi app Esa página aparece cuando el subdominio no tiene un deploy online: la app todavía no terminó su primer deploy, no existe o cambió de subdominio. Revisá la dirección actual en **Dominios**. ## Dominio propio que no se activa La consola muestra qué registros espera y qué encuentra. Los cambios de DNS pueden tardar unos minutos en propagarse. Un `CNAME` en la raíz del dominio necesita CNAME flattening o ALIAS. Ver [Dominios](/apps/dominios). ## ¿Seguís trabado? Escribinos a [hola@olimpia.dev](mailto:hola@olimpia.dev) con el nombre de la app y del deploy. --- # Subir tu carpeta Source: https://docs.olimpia.dev/apps/subir-codigo Una app con código subido no está atada a ningún repositorio: le mandás un `.tar.gz` de tu carpeta y Olimpia lo construye y lo publica. Es la forma que usan los agentes por defecto, y la que conviene cuando desplegás desde tu propio CI. :::tip La manera más simple es pedírselo a tu agente: "desplegá esta carpeta en Olimpia". Ver [Conectar tu agente](/agentes/conectar). ::: ## El flujo Los ejemplos usan un [token personal](/cuenta/tokens) en `$OLIMPIA_TOKEN`. 1. **Creá la app** Las apps con código subido se crean desde tu agente o desde la [API](/cuenta/api). Buscá el `id` de tu proyecto con `GET /projects`. ```bash curl -fsS -X POST -H "Authorization: Bearer $OLIMPIA_TOKEN" \ -H "content-type: application/json" \ -d '{"project_id": "", "name": "mi-api", "source": "upload", "port": 3000}' \ https://api.olimpia.dev/apps ``` Guardá el `id` de la respuesta en `$APP_ID`. 2. **Pedí una URL de subida** Cada subida usa una URL firmada que vence a los 15 minutos. ```bash curl -fsS -X POST -H "Authorization: Bearer $OLIMPIA_TOKEN" \ https://api.olimpia.dev/apps/$APP_ID/source ``` La respuesta trae `upload_url` y `key`. 3. **Empaquetá y subí la carpeta** Desde la raíz de tu proyecto, con git: ```bash git add -A && ref=$(git stash create) git archive --format=tar.gz --prefix=src/ -o /tmp/src.tar.gz "${ref:-HEAD}" curl -fsS -X PUT -T /tmp/src.tar.gz "$UPLOAD_URL" ``` Esto incluye los cambios sin commitear, respeta `.gitignore` y no crea commits ni stashes. 4. **Desplegá** ```bash curl -fsS -X POST -H "Authorization: Bearer $OLIMPIA_TOKEN" \ -H "content-type: application/json" \ -d "{\"source\": \"$KEY\", \"message\": \"primer deploy\"}" \ https://api.olimpia.dev/apps/$APP_ID/deployments ``` ## Requisitos del archivo - Un `.tar.gz` con todos los archivos dentro de **una sola carpeta** de primer nivel (por eso el `--prefix=src/`). - Hasta **300 MB**. - Sin `node_modules`, carpetas de build, entornos virtuales ni archivos `.env`. Si no usás git, excluilos a mano: ```bash tar --exclude=node_modules --exclude=.git --exclude='.env*' --exclude=dist \ --exclude=build --exclude=.next --exclude=target --exclude=.venv \ -czf /tmp/src.tar.gz --transform 's,^\.,src,' . ``` ## Volver a construir Un deploy sin `source` reconstruye la última subida. Sirve para aplicar variables de entorno nuevas sin subir el código otra vez. ## Monorepos Subí el repositorio entero y configurá la **Carpeta raíz** de la app (por ejemplo `apps/web`). ## Retención Olimpia guarda la última subida de cada app y borra las anteriores al día siguiente. Al borrar la app, se borran todas. --- # Variables de entorno Source: https://docs.olimpia.dev/apps/variables Las variables de entorno se cargan en la pestaña **Variables** de cada app. Se guardan cifradas y se inyectan en el build y al correr la app. ## Cargar variables Agregalas de a una, o pegá un `.env` entero en cualquier campo de nombre para importarlo de una vez: ```bash .env STRIPE_SECRET_KEY=sk_live_... SENTRY_DSN=https://... LOG_LEVEL=info ``` También podés pasar al modo de edición en texto y editar todo como un archivo `.env`. ## Conectar una base Desde **Variables** podés agregar cualquier Postgres o Redis del proyecto. Olimpia carga la URL interna: | Recurso | Variable | | --- | --- | | Postgres | `DATABASE_URL` | | Redis | `REDIS_URL` | | Bucket | `AWS_ENDPOINT_URL_S3`, `AWS_REGION`, `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `BUCKET_NAME` | Las variables de los buckets se cargan desde tu agente con `connect_resource`, o copiándolas desde las [credenciales del bucket](/buckets/credenciales). ## Cuándo se aplican Cambiar variables no reinicia tu app. La consola marca la app con **cambios sin aplicar** hasta que tocás **Deployar**. Así podés cambiar varias cosas y aplicarlas juntas. ## `PORT` Olimpia define `PORT` con el puerto configurado de la app. Si cargás `PORT` a mano, el puerto de la app pasa a ser ese. ## Buenas prácticas - Nunca subas tus `.env` al repositorio ni los incluyas en una subida de código. - Las variables que el framework copia al bundle (`NEXT_PUBLIC_*`, `VITE_*`) son públicas: no pongas secretos ahí. - Para mirar valores, usá **Mostrar valores**. Por defecto se ven ocultos. --- # Buckets Source: https://docs.olimpia.dev/buckets Un bucket de Olimpia es object storage compatible con la API de S3. Guardás archivos de cualquier tamaño y los leés con los SDKs y herramientas de S3 que ya usás: el AWS SDK, `boto3`, `rclone`, la AWS CLI. ## Crear un bucket En la consola, entrá a **Buckets → Crear bucket** y elegí un nombre. Las credenciales se generan al crearlo. ## Qué incluye - **Compatible con S3.** Subidas, descargas, multipart, URLs firmadas y listados, con cualquier SDK. - **Una key por bucket.** Cada bucket tiene su propia access key, con permisos solo sobre ese bucket. Ver [Credenciales](/buckets/credenciales). - **Sin límite de espacio.** Pagás por lo que guardás. - **Almacenamiento global.** Los objetos se sirven rápido desde cualquier parte del mundo. - **Explorador en la consola.** Navegá carpetas, buscá por nombre, previsualizá, subí, renombrá y borrá archivos sin escribir código. - **Privado por defecto**, con [acceso público](/buckets/acceso-publico) opcional para servir archivos por URL. ## Explorador Desde la consola podés: - navegar por carpetas y ordenar por nombre, tamaño o fecha, - buscar archivos por nombre, aunque no escribas el nombre exacto, - previsualizar imágenes, videos, PDFs y texto, - subir archivos, crear carpetas, renombrar y borrar, - compartir un archivo con un enlace que vence en una hora. Las subidas y descargas van directo de tu navegador al almacenamiento, firmadas con la key del bucket. ## Borrar un bucket Se borran el bucket, todos sus objetos y sus credenciales. No se puede deshacer: la consola te pide escribir el nombre para confirmar. --- # Acceso público Source: https://docs.olimpia.dev/buckets/acceso-publico Los buckets son privados por defecto: solo se accede con las credenciales o con URLs firmadas. Si querés servir archivos a cualquiera (las imágenes de tu sitio, archivos para descargar), hacé público el bucket. ## Hacer público un bucket En el bucket, tocá **Hacer público**. Desde ese momento, cualquiera puede leer sus objetos por URL: ```txt https://.t3.storage.dev/ ``` La URL base aparece en las credenciales del bucket como URL pública. Para escribir o borrar siguen haciendo falta las credenciales. :::warning Un bucket público expone **todos** sus objetos. Si solo algunos archivos tienen que ser públicos, usá dos buckets: uno público y otro privado. ::: ## Si no te deja Durante el acceso anticipado, hacer público un bucket puede requerir un medio de pago verificado. Si la consola te muestra ese error, escribinos a [hola@olimpia.dev](mailto:hola@olimpia.dev) y lo habilitamos. ## Volver a privado **Hacer privado** corta el acceso por URL al instante. Las URLs firmadas que hayas generado siguen valiendo hasta que vencen. --- # Credenciales y SDKs Source: https://docs.olimpia.dev/buckets/credenciales Cada bucket tiene sus credenciales en **Credenciales**. Son estas cinco variables: ```bash .env AWS_ENDPOINT_URL_S3=https://t3.storage.dev AWS_REGION=auto AWS_ACCESS_KEY_ID=tid_... AWS_SECRET_ACCESS_KEY=tsec_... BUCKET_NAME=olimpia-... ``` Los SDKs de AWS leen `AWS_ENDPOINT_URL_S3`, `AWS_REGION` y las keys solos, así que no hace falta configurar nada en el código. `BUCKET_NAME` es el nombre real del bucket en el almacenamiento, distinto del nombre que ves en la consola. :::note Para tus apps en Olimpia, tu agente puede cargar las cinco variables con `connect_resource`. También podés copiarlas a **Variables** desde la consola. ::: ## Ejemplos **JavaScript** ```js import { GetObjectCommand, PutObjectCommand, S3Client } from "@aws-sdk/client-s3"; import { getSignedUrl } from "@aws-sdk/s3-request-presigner"; const s3 = new S3Client({}); const Bucket = process.env.BUCKET_NAME; await s3.send(new PutObjectCommand({ Bucket, Key: "avatars/ana.png", Body: archivo })); const url = await getSignedUrl(s3, new GetObjectCommand({ Bucket, Key: "avatars/ana.png" }), { expiresIn: 3600, }); ``` **Python** ```python import os import boto3 s3 = boto3.client("s3") bucket = os.environ["BUCKET_NAME"] s3.upload_file("informe.pdf", bucket, "informes/2026-10.pdf") url = s3.generate_presigned_url("get_object", Params={"Bucket": bucket, "Key": "informes/2026-10.pdf"}, ExpiresIn=3600) ``` **Go** ```go cfg, _ := config.LoadDefaultConfig(ctx) client := s3.NewFromConfig(cfg) _, err := client.PutObject(ctx, &s3.PutObjectInput{ Bucket: aws.String(os.Getenv("BUCKET_NAME")), Key: aws.String("datos/export.csv"), Body: archivo, }) ``` **AWS CLI** ```bash aws s3 cp ./foto.jpg "s3://$BUCKET_NAME/fotos/foto.jpg" aws s3 ls "s3://$BUCKET_NAME/fotos/" ``` **rclone** ```ini rclone.conf [olimpia] type = s3 provider = Other endpoint = https://t3.storage.dev region = auto access_key_id = tid_... secret_access_key = tsec_... ``` ## Subidas desde el navegador No pongas las keys en el frontend. Generá una URL firmada en tu backend y que el navegador suba directo con ella: ```js import { PutObjectCommand } from "@aws-sdk/client-s3"; import { getSignedUrl } from "@aws-sdk/s3-request-presigner"; const url = await getSignedUrl( s3, new PutObjectCommand({ Bucket: process.env.BUCKET_NAME, Key: `uploads/${id}`, ContentType: tipo }), { expiresIn: 600 }, ); ``` ## Alcance de la key La key de cada bucket solo puede operar sobre ese bucket. Si se filtra, no sirve para leer ni escribir en tus otros buckets. Para cambiarla, abrí **Credenciales** y rotá la key: se genera una nueva y la anterior deja de valer. Actualizá las variables en tus apps y desplegá. --- # Conceptos Source: https://docs.olimpia.dev/conceptos ## Proyectos Un proyecto agrupa apps, bases y buckets que trabajan juntos. Usalo para separar producción de pruebas, un producto de otro o un cliente de otro. - Cada cuenta arranca con el proyecto `personal`. - Los nombres de los recursos son únicos dentro de cada proyecto: podés tener una base `main` en `produccion` y otra `main` en `staging`. - Podés mover un recurso de un proyecto a otro sin recrearlo. - Un proyecto solo se puede borrar cuando está vacío, y nunca el último que te queda. ## Recursos | Recurso | Qué es | Dónde se conecta | | --- | --- | --- | | **App** | Un contenedor construido desde GitHub, una carpeta subida o una imagen de Docker. | `https://.olimpia.cc` y tus dominios propios. | | **Postgres** | Una base Postgres 18 administrada. | `DATABASE_URL` por la red interna; opcionalmente por TLS desde afuera. | | **Redis** | Una instancia de Redis 8 persistente. | `REDIS_URL` por la red interna; opcionalmente por TLS desde afuera. | | **Bucket** | Object storage compatible con S3. | Las variables `AWS_*` y `BUCKET_NAME`, desde cualquier lado. | Una app puede usar varios recursos y un recurso puede estar conectado a varias apps. ## Deploys Un deploy es un build y una publicación de tu app. Pasa por estos estados: ```txt En cola → Construyendo → Deployando → Online ``` Puede terminar como **Falló** o **Cancelado**, y un deploy online pasa a **Reemplazado** cuando entra uno nuevo. Hay un solo deploy en curso por app: si llega otro push, el anterior que seguía en cola se cancela. Más detalle en [Deploys y rollbacks](/apps/deploys). ## Nombres Apps, bases, buckets y proyectos usan el mismo formato: entre 3 y 63 caracteres, con minúsculas, números y guiones, sin guion al principio ni al final. ```txt mi-api ✓ api-v2 ✓ Mi_API ✗ -api ✗ ``` ## Dominios - La consola y la API viven en `olimpia.dev` y `api.olimpia.dev`. - Tus apps se publican en subdominios de `olimpia.cc`, por ejemplo `https://mi-api.olimpia.cc`. - Las bases con acceso externo usan `*.db.olimpia.cc`. ## Cobro por uso Olimpia cobra por lo que usás: CPU, memoria y almacenamiento de cada recurso. No hay planes con topes ni límites artificiales de cantidad de apps o bases. Durante el acceso anticipado no se pide tarjeta, y los precios se publican antes de abrir la región. :::note La facturación en la consola está en camino. Mirá [Próximamente](/proximamente/facturacion). ::: --- # Cuenta y acceso Source: https://docs.olimpia.dev/cuenta ## Entrar Podés entrar a [olimpia.dev](https://olimpia.dev/login) de dos formas: - **Email y contraseña.** - **GitHub.** Si tu cuenta de GitHub tiene verificado el mismo email que tu cuenta de Olimpia, se vinculan solas. La pantalla de inicio recuerda qué método usaste la última vez. :::note Durante el acceso anticipado, Olimpia es por invitación. Si tu email o tu cuenta de GitHub todavía no tienen acceso, pedilo en [olimpia.dev](https://olimpia.dev). ::: ## Recuperar la contraseña En la pantalla de inicio, tocá **¿No podés entrar?**, escribí tu email y te mandamos un enlace. Vence en una hora. Al cambiar la contraseña se cierran todas tus otras sesiones. ## Dispositivos En **Dispositivos**, desde el menú de tu cuenta, ves dónde tenés la sesión abierta y cuándo se usó por última vez. Cerrá los que no reconozcas, o todos los demás de una vez. Cerrar una sesión la invalida al instante. ## Límites de seguridad Para frenar ataques de fuerza bruta, el inicio de sesión, el registro y la recuperación aceptan una cantidad limitada de intentos por minuto y por IP, y cada cuenta acepta una cantidad limitada de contraseñas incorrectas cada 15 minutos. Si llegás al límite, esperá unos minutos. ## Idioma y tema La consola está en español y en inglés, con tema claro y oscuro. --- # API REST Source: https://docs.olimpia.dev/cuenta/api La consola de Olimpia usa la misma API que podés usar vos. Base URL: ```txt https://api.olimpia.dev ``` :::note[Acceso anticipado] La API puede cambiar mientras Olimpia está en acceso anticipado. Para automatizar con estabilidad, preferí el [servidor MCP](/agentes), que mantiene sus herramientas compatibles. ::: ## Autenticación Mandá un [token personal](/cuenta/tokens) en cada pedido: ```bash curl -H "Authorization: Bearer $OLIMPIA_TOKEN" https://api.olimpia.dev/projects ``` Los cuerpos van en JSON (`content-type: application/json`). Los errores responden con un código HTTP y un cuerpo como `{"error": "invalid_name"}`. ## Proyectos | Método | Ruta | Qué hace | | --- | --- | --- | | `GET` | `/projects` | Lista tus proyectos. | | `POST` | `/projects` | Crea un proyecto: `{"name": "staging"}`. | | `POST` | `/projects/{id}/move` | Mueve un recurso a este proyecto: `{"kind": "apps", "id": "..."}` (`apps`, `postgres`, `redis` o `buckets`). | ## Apps | Método | Ruta | Qué hace | | --- | --- | --- | | `GET` | `/apps?project={id}` | Lista las apps de un proyecto. | | `POST` | `/apps` | Crea una app. Ver abajo. | | `GET` | `/apps/{id}` | Detalle de la app. | | `PATCH` | `/apps/{id}` | Cambia `slug`, `branch`, `root_dir`, `dockerfile`, `image`, `port` o `auto_deploy`. | | `DELETE` | `/apps/{id}` | Borra la app. | | `GET` | `/apps/{id}/env` | Lee las variables. | | `PUT` | `/apps/{id}/env` | Reemplaza todas las variables: `{"vars": [{"key": "K", "value": "V"}]}`. | | `POST` | `/apps/{id}/source` | Devuelve `{key, upload_url}` para subir código. | | `GET` | `/apps/{id}/deployments` | Últimos 50 deploys, del más nuevo al más viejo. | | `POST` | `/apps/{id}/deployments` | Despliega. Ver abajo. | | `POST` | `/apps/{id}/deployments/{deployment}/cancel` | Cancela un deploy en cola o construyendo. | | `GET` | `/apps/{id}/deployments/{deployment}/log` | Log del build. | | `GET` | `/apps/{id}/logs` | Logs de la app. | | `GET` | `/apps/{id}/metrics` | Métricas de CPU, memoria y disco. | | `GET` | `/apps/{id}/domains` | Dominios propios. | | `POST` | `/apps/{id}/domains/{domain}/check` | Verifica un dominio ahora. | ### Crear una app ```json { "project_id": "", "name": "mi-api", "source": "upload", "port": 3000, "root_dir": "", "env": [{ "key": "LOG_LEVEL", "value": "info" }] } ``` `source` es `upload` (código subido), `image` (con `"image": "nginx:1.29"`) o `github`. Las apps de GitHub conviene crearlas desde la consola, que resuelve la instalación y el repositorio. ### Desplegar | Cuerpo | Qué despliega | | --- | --- | | `{"source": "", "message": "..."}` | Una subida nueva. | | `{}` | Reconstruye: la última subida, el último commit de la rama o la imagen otra vez. | | `{"from": ""}` | Rollback a ese deploy, sin build. | ## Postgres | Método | Ruta | Qué hace | | --- | --- | --- | | `GET` | `/postgres?project={id}` | Lista las bases. | | `POST` | `/postgres` | Crea una base: `{"project_id": "...", "name": "main"}`. | | `GET` | `/postgres/{id}` | Detalle y credenciales. | | `PATCH` | `/postgres/{id}` | Acceso externo: `{"public": true}`. | | `DELETE` | `/postgres/{id}` | Borra la base y sus datos. | | `POST` | `/postgres/{id}/password` | Rota la contraseña. | | `GET` | `/postgres/{id}/tables` | Tablas y vistas. | | `POST` | `/postgres/{id}/query` | Corre SQL: `{"sql": "select 1"}`, o `{"sql": "...", "write": true}`. | | `POST` | `/postgres/{id}/backups/run` | Hace un backup ahora. | ## Redis | Método | Ruta | Qué hace | | --- | --- | --- | | `GET` | `/redis?project={id}` | Lista las instancias. | | `POST` | `/redis` | Crea una instancia: `{"project_id": "...", "name": "cache"}`. | | `GET` | `/redis/{id}` | Detalle y credenciales. | | `PATCH` | `/redis/{id}` | Acceso externo: `{"public": true}`. | | `DELETE` | `/redis/{id}` | Borra la instancia. | | `POST` | `/redis/{id}/password` | Rota la contraseña. | ## Buckets | Método | Ruta | Qué hace | | --- | --- | --- | | `GET` | `/buckets?project={id}` | Lista los buckets. | | `POST` | `/buckets` | Crea un bucket: `{"project_id": "...", "name": "uploads"}`. | | `GET` | `/buckets/{id}` | Detalle y credenciales. | | `PATCH` | `/buckets/{id}` | Acceso público: `{"public": true}`. | | `DELETE` | `/buckets/{id}` | Borra el bucket y sus objetos. | | `POST` | `/buckets/{id}/keys` | Rota la access key. | --- # Proyectos Source: https://docs.olimpia.dev/cuenta/proyectos Todo lo que creás en Olimpia vive dentro de un proyecto. La consola recuerda el último que abriste y todo cuelga de su URL: `olimpia.dev/dashboard//...`. ## Crear un proyecto Desde el selector de proyectos, en la parte de arriba de la barra lateral, tocá **Nuevo proyecto**. El nombre aparece en la URL de la consola y lo podés cambiar cuando quieras sin afectar tus apps ni tus bases. ## Ideas para organizarte | Proyecto | Para | | --- | --- | | `produccion` y `staging` | Separar entornos con las mismas apps. | | `tienda`, `backoffice` | Un proyecto por producto. | | `cliente-acme` | Un proyecto por cliente, si sos una agencia. | ## Mover recursos Podés mover una app, una base, una instancia de Redis o un bucket a otro proyecto desde sus acciones. No se recrea nada: las URLs, los datos y las credenciales siguen iguales. El nombre tiene que estar libre en el proyecto de destino. ## Vista del proyecto La página del proyecto muestra todos sus recursos y su estado: apps online, desplegando o con errores, y el uso de bases y buckets. ## Borrar un proyecto Solo se puede borrar un proyecto vacío, y nunca el último que tenés. Mové o borrá sus recursos primero. --- # Tokens personales Source: https://docs.olimpia.dev/cuenta/tokens Un token personal da acceso programático a tu cuenta, con los mismos permisos que vos. Sirve para la [API REST](/cuenta/api), para [desplegar desde tu CI](/apps/ci-propio) y para [agentes sin OAuth](/agentes/ci-y-tokens). ## Crear un token 1. **Abrí Agentes y tokens** En la consola, entrá a **Cuenta → Agentes y tokens**. 2. **Creá el token** En **Tokens personales**, poné un nombre que diga dónde lo vas a usar (`github-actions`, `script-backups`) y tocá **Crear token**. 3. **Copialo ahora** El token empieza con `olimpia_pat_` y se muestra una sola vez. Guardalo en el gestor de secretos de tu CI o de tu equipo. ## Usarlo Mandalo en el header `Authorization`: ```bash curl -H "Authorization: Bearer olimpia_pat_..." https://api.olimpia.dev/projects ``` ## Qué no puede hacer un token Por seguridad, algunas acciones necesitan una sesión en el navegador y no funcionan con un token: - ver o cerrar sesiones, - crear otros tokens, - vincular GitHub. ## Revocar En **Agentes y tokens** ves cuándo se usó cada token por última vez. **Revocar** lo invalida al instante. Podés tener hasta 50 tokens. :::warning Un token tiene los mismos permisos que tu cuenta. No lo pongas en el código, en un repositorio ni en el frontend. ::: --- # Preguntas frecuentes Source: https://docs.olimpia.dev/faq **¿Dónde corre Olimpia?** En Buenos Aires, en infraestructura de primer nivel. Tus apps, bases e instancias de Redis corren en la región BUE; el tráfico web entra por la red de Cloudflare. Ver [Región BUE](/plataforma/buenos-aires). **¿Tengo que cambiar mi código?** No. Postgres y Redis son los de siempre y los buckets hablan la API de S3: tus drivers, ORMs y SDKs funcionan igual. Lo único que necesita tu app es escuchar en `0.0.0.0:$PORT`. **¿Puedo usar un solo producto?** Sí. Cada producto funciona por separado. Podés empezar con una base de datos y sumar apps o buckets después. **¿Cómo funciona el CI/CD con GitHub?** Instalás la GitHub App de Olimpia, elegís repo y rama, y cada push se construye y se publica solo, sin cortes. Ver [Deploy desde GitHub](/apps/github). **¿Mis apps se conectan a la base por internet?** No. Usan la [red interna](/plataforma/red-interna). Las bases no aceptan conexiones de afuera hasta que habilitás el acceso externo. **¿Puedo tener backups en mi propia cuenta de AWS?** Sí. Configurás un bucket de AWS S3, Cloudflare R2, Backblaze B2, MinIO o cualquier S3 y elegís la frecuencia. Ver [Backups en tu S3](/postgres/backups). **¿Puedo usar mi dominio?** Sí, hasta 10 por app. Apuntás un CNAME a `domains.olimpia.cc` y el certificado se emite solo. Ver [Dominios](/apps/dominios). **¿Mi agente puede desplegar por mí?** Sí. Olimpia tiene un servidor MCP para Claude Code, Codex, Cursor y cualquier cliente MCP. Ver [Para agentes](/agentes). **¿Cuánto cuesta?** Olimpia cobra por uso. Durante el acceso anticipado no se pide tarjeta, y publicamos los precios antes de abrir la región. **¿Cuándo abre Olimpia?** Estamos sumando a los primeros equipos. Pedí acceso en [olimpia.dev](https://olimpia.dev) y te escribimos apenas haya lugar. **¿Puedo correr workers o tareas programadas?** Sí, un worker se despliega como cualquier app: el contenedor sigue corriendo aunque no atienda HTTP (su URL simplemente no va a responder). Las tareas programadas (cron) como recurso propio todavía no están disponibles; mientras tanto, programalas dentro de un worker. **¿Qué pasa con los archivos que mi app escribe en disco?** Se pierden en el próximo deploy. Guardá los datos en Postgres, Redis o un bucket. ¿Te quedó otra duda? Escribinos a [hola@olimpia.dev](mailto:hola@olimpia.dev). --- # Introducción Source: https://docs.olimpia.dev/introduccion ![Ruinas clásicas frente al Río de la Plata, en acuarela](/art/banner.webp) Olimpia es una plataforma cloud para correr tu producto en producción. Subís tu código, conectás una base de datos y en unos minutos tenés tu app online con HTTPS, en infraestructura de primer nivel en Buenos Aires. Todo vive dentro de **proyectos**: tus apps, tus bases Postgres, tus instancias de Redis y tus buckets. Los manejás desde la [consola](https://olimpia.dev/dashboard) o le pedís a tu agente que lo haga por vos, por MCP. ## Qué podés correr hoy **[Apps](/apps)** Servicios web y APIs desde GitHub, desde una imagen de Docker o desde tu carpeta local. Deploy automático en cada push, sin cortes. **[Postgres](/postgres)** Postgres 18 administrado, con explorador de datos, logs, métricas y backups programados en tu propio S3. **[Redis](/redis)** Redis 8 persistente para caché, sesiones y colas. Nunca borra claves por falta de memoria. **[Buckets](/buckets)** Object storage compatible con S3, con credenciales propias por bucket. Tus SDKs de S3 funcionan sin cambios. ## Por qué Olimpia - **Corre en Buenos Aires.** La región BUE está acá, sobre infraestructura de primer nivel. Tus datos y tus usuarios en Argentina quedan cerca. [Más sobre la región](/plataforma/buenos-aires). - **Red interna.** Tus apps llegan a sus bases por una red privada. Las bases no aceptan conexiones de afuera hasta que vos lo habilitás. [Cómo funciona](/plataforma/red-interna). - **CI/CD con GitHub.** Conectás un repositorio y cada push a la rama elegida se construye y se publica solo, sin downtime y con rollback en un clic. [Deploy desde GitHub](/apps/github). - **Backups en tu S3.** Programás copias de tus bases en AWS S3, Cloudflare R2, Backblaze B2, MinIO o cualquier servicio compatible. [Configurar backups](/postgres/backups). - **Hecha para agentes.** Olimpia tiene un servidor MCP con 27 herramientas. Claude Code, Codex, Cursor y cualquier cliente MCP pueden desplegar, consultar y depurar por vos. [Para agentes](/agentes). - **Sin cambiar tu código.** Postgres y Redis son los de siempre y los buckets hablan la API de S3. Tus drivers, ORMs y SDKs funcionan igual. ## Cómo seguir 1. **Seguí los primeros pasos** En [Primeros pasos](/primeros-pasos) creás tu cuenta, desplegás una app y le conectás una base. 2. **Entendé los conceptos** [Conceptos](/conceptos) explica proyectos, recursos, nombres y cómo se cobra. 3. **Conectá tu agente** Si trabajás con Claude Code, Codex o Cursor, [conectalo a Olimpia](/agentes/conectar) y pedile que despliegue por vos. :::note[Acceso anticipado] Olimpia está sumando a los primeros equipos. Si todavía no tenés cuenta, pedí acceso en [olimpia.dev](https://olimpia.dev) o escribinos a [hola@olimpia.dev](mailto:hola@olimpia.dev). ::: --- # Región Buenos Aires Source: https://docs.olimpia.dev/plataforma/buenos-aires ![Un templo dórico con racks de servidores entre sus columnas, en acuarela](/art/infra.webp) Olimpia nace en Buenos Aires. La primera región, **BUE**, corre en un datacenter de la ciudad, sobre infraestructura de primer nivel. Tus apps, tus bases y tus instancias de Redis están ahí, una al lado de la otra. ## Por qué importa - **Latencia local.** Si tus usuarios están en Argentina, tus respuestas no cruzan el continente para llegar a un servidor en Virginia o en San Pablo. Tu app y tu base están en la misma ciudad que la mayoría de tus usuarios. - **App y base, juntas.** Las consultas entre tu app y su base viajan por la [red interna](/plataforma/red-interna) de la región, sin salir a internet. - **Tus datos, en el país.** Las bases Postgres y las instancias de Redis guardan sus datos en Buenos Aires. ## Cómo llega el tráfico ```txt navegador ── HTTPS ──▶ borde de Cloudflare ──▶ región BUE ──▶ tu app cliente ── TLS ──▶ proxy TCP protegido ──▶ región BUE ──▶ tu base (si es pública) ``` - **Web y APIs.** Todo el tráfico HTTP entra por la red de Cloudflare, que termina TLS cerca del usuario y filtra ataques antes de que lleguen a la región. El origen solo acepta conexiones que vienen de Cloudflare. - **Bases con acceso externo.** Las conexiones a Postgres y Redis desde fuera de Olimpia entran por un proxy TCP con protección anti-DDoS, que reenvía por un túnel cifrado. La dirección de la región no aparece en ningún registro DNS. - **Builds.** El código se construye en máquinas aisladas, separadas de donde corren tus apps. Un build pesado no le quita CPU a tu producción. ## Qué incluye la región | Producto | Estado | | --- | --- | | Apps | Disponible | | Postgres 18 | Disponible | | Redis 8 | Disponible | | Buckets S3 | Disponible (almacenamiento global) | | Stream, CDN, Email | Próximamente | Los buckets usan almacenamiento de objetos distribuido globalmente, compatible con S3, así que tus archivos se sirven rápido también fuera de Argentina. ## Más regiones Olimpia está pensada para correr en varias regiones. Vamos a anunciar las próximas a medida que abran. Mirá [Próximamente](/proximamente/regiones). --- # Red interna Source: https://docs.olimpia.dev/plataforma/red-interna Cada app, base e instancia de Redis de Olimpia está conectada a una red privada de la región. Tus apps usan esa red para hablar con sus bases: el tráfico no sale a internet, no pasa por el proxy público y no necesita certificados. ## URL interna y URL pública Cada base tiene dos formas de conectarse: | | URL interna | URL pública | | --- | --- | --- | | Desde | Apps en Olimpia | Tu compu, otra nube, una herramienta de BI | | Por defecto | Siempre activa | Apagada | | TLS | No hace falta | Obligatorio, con SNI | | Postgres | `postgresql://app:…@:5432/app` | `postgresql://app:…@pg-.db.olimpia.cc:5432/app?sslmode=require` | | Redis | `redis://default:…@:6379` | `rediss://default:…@rd-.db.olimpia.cc:6379` | Cuando conectás una base a una app desde la consola o desde tu agente, Olimpia carga la URL interna en `DATABASE_URL` o `REDIS_URL`. Es la que tenés que usar desde tus apps. :::warning La URL interna no funciona desde tu máquina: solo resuelve dentro de Olimpia. Para conectarte desde afuera, [habilitá el acceso externo](/postgres/conexion#acceso-externo) y usá la URL pública. ::: ## Privado por defecto Una base nueva no acepta conexiones de internet. Solo tus apps en Olimpia pueden llegar a ella. El acceso externo se prende y se apaga por base, cuando lo necesitás: para una migración desde tu compu, una herramienta de análisis o una app que todavía corre en otra nube. ## Aislamiento entre apps Las apps corren en una red separada de los servicios internos de la plataforma. Una app puede llegar a las bases y a Redis, pero no ve los paneles de administración, las bases internas de Olimpia ni el resto de la infraestructura. ## Buckets Los buckets no usan la red interna: se acceden por HTTPS con la API de S3, desde tus apps o desde cualquier lado, con [credenciales que solo sirven para ese bucket](/buckets/credenciales). --- # Seguridad Source: https://docs.olimpia.dev/plataforma/seguridad ## En el borde - **Todo el tráfico web pasa por Cloudflare.** Tus apps reciben HTTPS automático en `*.olimpia.cc` y en tus dominios propios, con protección contra ataques en el borde. El origen solo acepta conexiones de Cloudflare. - **Bases detrás de un proxy.** El acceso externo a Postgres y Redis entra por un proxy TCP con protección anti-DDoS y límites por IP de conexiones abiertas y nuevas. TLS es obligatorio: una conexión sin cifrar se corta. - **La dirección de la región no es pública.** Ningún registro DNS apunta directo a los servidores donde corren tus recursos. ## Tus secretos - **Variables de entorno cifradas.** Los valores se guardan cifrados y se descifran solo para construir y correr tu app. - **Credenciales por bucket.** Cada bucket tiene su propia access key, con permisos solo sobre ese bucket. Una key filtrada no sirve para tocar otro. - **Credenciales rotables.** Rotás la contraseña de Postgres o Redis, o la key de un bucket, con un clic; la anterior deja de valer al instante. - **Tokens que no se guardan.** De tus sesiones y tokens solo guardamos un hash. Revocar uno lo invalida en el momento. ## Tus datos - **Postgres sin superusuario para vos ni para el explorador.** Tu usuario `app` es dueño de su base pero no superusuario. El explorador de la consola se conecta con ese mismo usuario, en transacciones de solo lectura. - **Redis sin comandos de administración.** El usuario `default` no puede usar `CONFIG`, `ACL`, `SHUTDOWN` ni otros comandos de administración. - **Backups.** Olimpia guarda sus propias copias diarias, y además podés [programar backups en tu propio S3](/postgres/backups). ## Tu cuenta - Entrás con email y contraseña o con GitHub. - Ves y cerrás tus sesiones abiertas desde la consola. - Los intentos de inicio de sesión tienen límites por IP y por cuenta. - Los agentes se conectan con [OAuth 2.1 y PKCE](/agentes/seguridad) o con tokens personales que podés revocar cuando quieras. ## Reportar un problema Si encontrás una vulnerabilidad, escribinos a [hola@olimpia.dev](mailto:hola@olimpia.dev). Respondemos rápido y te mantenemos al tanto del arreglo. --- # Postgres Source: https://docs.olimpia.dev/postgres Una base Postgres de Olimpia es un Postgres 18 completo, con su propio usuario y su propia contraseña. Se crea en segundos y tus apps se conectan por la [red interna](/plataforma/red-interna), sin configurar TLS. ## Crear una base 1. **Abrí Postgres** En la consola, entrá a **Postgres → Crear base**. 2. **Elegí un nombre** Entre 3 y 63 caracteres: minúsculas, números y guiones. El usuario y la contraseña se generan solos. 3. **Conectala a tu app** En la app, abrí **Variables** y agregá la base: Olimpia carga `DATABASE_URL`. Desplegá para aplicarlo. ## Qué incluye - **Postgres 18**, con la base `app` y el usuario `app`, dueño de la base. - **Conexión interna** para tus apps y [acceso externo opcional](/postgres/conexion#acceso-externo) por TLS. - **[Explorador de datos](/postgres/explorador)** para ver tablas y filas desde la consola. - **[Backups en tu S3](/postgres/backups)**, programados, además de las copias diarias que guarda Olimpia. - **[Logs y métricas](/postgres/logs-y-metricas)**: errores, consultas lentas, CPU, memoria, conexiones y transacciones por segundo. - **Sin límite de tamaño.** Olimpia mide el almacenamiento cada minuto y cobra por uso. ## Lo que podés y no podés hacer El usuario `app` es dueño de su base pero no es superusuario: | Podés | No podés | | --- | --- | | Crear tablas, índices, vistas, funciones y esquemas | `ALTER SYSTEM` ni cambiar la configuración del servidor | | Usar extensiones confiables: `pgcrypto`, `citext`, `pg_trgm` y otras | Instalar extensiones no confiables | | Correr migraciones con cualquier ORM | Crear otros superusuarios | ## Con tu ORM `DATABASE_URL` funciona tal cual con Prisma, Drizzle, Knex, TypeORM, SQLAlchemy, Django, Ecto, sqlx y cualquier driver de Postgres. :::warning[Migraciones al arrancar] El build corre en otras máquinas y no llega a tu base. Corré las migraciones cuando arranca la app: ```json package.json { "scripts": { "start": "prisma migrate deploy && node server.js" } } ``` ::: ## Borrar una base Desde el menú de acciones de la base. Se borran la base y todos sus datos, y no se puede deshacer: la consola te pide escribir el nombre para confirmar. Los backups que ya estaban en tu S3 no se tocan. --- # Backups en tu S3 Source: https://docs.olimpia.dev/postgres/backups Olimpia guarda sus propias copias diarias de cada base. Además, podés programar backups en **tu propio bucket**, para tener los datos bajo tu control, en tu proveedor y con tu retención. ## Configurar 1. **Prepará un bucket** Creá un bucket en tu proveedor y una access key con permisos solo sobre ese bucket. Necesita poder listar, leer y escribir objetos. 2. **Abrí Backups** En tu base, abrí **Backups → Configurar backups**. 3. **Cargá el destino** | Campo | Ejemplo | | --- | --- | | **Endpoint** | `https://s3.us-east-1.amazonaws.com` o `https://.r2.cloudflarestorage.com` | | **Región** | `us-east-1`, o `auto` si tu proveedor no usa regiones | | **Bucket** | `mi-empresa-backups` | | **Access key ID** y **Secret access key** | Las de la key que creaste | 4. **Elegí frecuencia y retención** | Frecuencia | Cuándo | | --- | --- | | Cada hora | Al minuto cero de cada hora | | Cada 6 horas | Cuatro veces por día | | Todos los días | 03:00 UTC | | Los domingos | 03:00 UTC | | Personalizada | Una expresión cron en UTC | En **Conservar** indicás cuántos backups guardar, entre 1 y 90. Los más viejos se borran solos. 5. **Guardá** Olimpia prueba el acceso a tu bucket antes de guardar. Si algo falla, te dice qué revisar. ## Frecuencia personalizada La expresión cron tiene cinco campos (minuto, hora, día, mes y día de la semana), en UTC, con el minuto fijo: como mucho un backup por hora. La consola te muestra los próximos horarios antes de guardar. ```txt 30 */4 * * * cada 4 horas, a los 30 minutos 0 6 * * 1-5 de lunes a viernes, 06:00 UTC (03:00 en Buenos Aires) ``` ## Qué se guarda Cada backup es un dump comprimido de la base (`.sql.gz`), con la fecha en el nombre. En **Backups recientes** ves los archivos de tu bucket y los podés descargar directo desde la consola. Para restaurar uno en otra base: ```bash gunzip -c backup.sql.gz | psql "postgresql://app:@pg-.db.olimpia.cc:5432/app?sslmode=require" ``` ## Hacer un backup ahora **Hacer backup ahora** corre uno en el momento, sin esperar al próximo horario. Útil antes de una migración grande. ## Desactivar **Desactivar** deja de hacer backups de esa base. Los archivos que ya están en tu bucket no se borran. ## Ejemplos por proveedor | Proveedor | Endpoint | Región | | --- | --- | --- | | AWS S3 | `https://s3..amazonaws.com` | La del bucket | | Cloudflare R2 | `https://.r2.cloudflarestorage.com` | `auto` | | Backblaze B2 | `https://s3..backblazeb2.com` | La del bucket | | MinIO | `https://minio.tuempresa.com` | La que configuraste | :::warning[Requisitos del endpoint] El endpoint tiene que ser `https://host` (con puerto opcional, sin ruta) y apuntar a una dirección pública. Olimpia rechaza direcciones privadas o locales. El bucket lleva minúsculas, números, puntos y guiones. ::: --- # Conexión Source: https://docs.olimpia.dev/postgres/conexion La pestaña **Conexión** de cada base tiene todo lo que necesitás: la URL de conexión, la URL interna, host, puerto, base, usuario y contraseña. **Copiar como .env** copia todo listo para pegar. ## Desde tus apps Usá la URL interna. Es la que Olimpia carga en `DATABASE_URL` cuando conectás la base a una app: ```txt postgresql://app:@:5432/app ``` No necesita TLS ni parámetros extra, y no sale a internet. ## Acceso externo Por defecto la base solo acepta conexiones de tus apps en Olimpia. Para conectarte desde tu compu, una herramienta de BI o una app en otra nube, tocá **Permitir conexiones externas**. La URL pública queda así: ```txt postgresql://app:@pg-.db.olimpia.cc:5432/app?sslmode=require ``` **psql** ```bash psql "postgresql://app:@pg-.db.olimpia.cc:5432/app?sslmode=require" ``` **Node** ```js import postgres from "postgres"; const sql = postgres(process.env.DATABASE_URL, { ssl: "require" }); ``` **Python** ```python import os import psycopg conn = psycopg.connect(os.environ["DATABASE_URL"]) ``` ### Requisitos - **TLS obligatorio**, con `sslmode=require`. Una conexión sin TLS se corta. - **SNI.** Olimpia enruta cada conexión por el nombre del host, así que tu cliente tiene que mandar SNI: libpq 14 o más nuevo (`psql`, `pg_dump`) y los drivers actuales de Node, Python, Go, Java y Rust lo hacen. - Una conexión que no se autentica en 10 segundos se corta. :::tip Cuando ya no lo necesites, tocá **Bloquear conexiones externas**. Tus apps siguen conectadas por la red interna. ::: ## Rotar la contraseña **Rotar contraseña** genera una nueva y la anterior deja de funcionar al instante. Actualizá `DATABASE_URL` en tus apps (desde **Variables**, volviendo a agregar la base) y desplegá. ## Desde tu agente `get_connection` devuelve la URL interna y la pública; `set_public_access` prende o apaga el acceso externo. Ver [Herramientas](/agentes/herramientas). --- # Explorador de datos Source: https://docs.olimpia.dev/postgres/explorador La pestaña **Datos** de cada base lista sus tablas y vistas con la cantidad de filas, y te deja recorrer, buscar y filtrar filas sin salir de la consola. ## Tablas Ves cada objeto con su tipo: **Tabla**, **Vista**, **Vista materializada** o **Externa**, y cuántas filas tiene. Las tablas nuevas aparecen solas: creá tu esquema con tu ORM o tu cliente y tocá **Actualizar**. ## Filas Al abrir una tabla ves sus filas, con la clave primaria destacada. Podés: - buscar en toda la tabla, - filtrar por columna, - abrir una fila para ver todos sus valores. Los valores largos se recortan a 2000 caracteres. ## Solo lectura El explorador se conecta con el mismo usuario `app` de tu base, en transacciones de solo lectura y con tiempo máximo por consulta. No puede modificar datos ni ver nada que tu usuario no vea. ## SQL desde tu agente Para correr SQL, usá tu cliente favorito con el [acceso externo](/postgres/conexion#acceso-externo), o pedíselo a tu agente: - `list_tables` lista tablas y vistas con filas y tamaño. - `query_postgres` corre una consulta de lectura y devuelve hasta 200 filas en JSON. Con `write: true` corre cualquier sentencia en una transacción, con 30 segundos como máximo. Ver [Herramientas](/agentes/herramientas). --- # Logs y métricas Source: https://docs.olimpia.dev/postgres/logs-y-metricas ## Logs La pestaña **Logs** muestra lo que Postgres registra de tu base: - **errores** (una consulta que falla, una restricción violada), - **advertencias**, - **consultas de más de un segundo**, con su texto. Filtrás por nivel, buscás por texto y podés dejarlo **En vivo**. Cada registro abre su detalle: la consulta, el detalle y la sugerencia de Postgres, el cliente y la aplicación que la mandó. :::tip Poné `application_name` en tu cadena de conexión (`?application_name=api`) para saber qué app mandó cada consulta. ::: ## Métricas La pestaña **Métricas** mide la base cada minuto: | Métrica | Qué muestra | | --- | --- | | **CPU** | Uso de CPU; 100 % equivale a 1 vCPU. | | **Memoria** | RSS y caché. | | **IOPS** | Lecturas y escrituras de disco. | | **Almacenamiento** | Tamaño de la base. | | **Transacciones por segundo** | Cuánto trabajo está haciendo la base. | | **Conexiones** | Activas, inactivas y en transacción. | Elegí el período: última hora, 24 horas o 7 días. --- # Primeros pasos Source: https://docs.olimpia.dev/primeros-pasos Vas a terminar con una app online en `https://.olimpia.cc`, con HTTPS, conectada a una base Postgres por la red interna y redeployándose sola en cada push. :::tip[¿Preferís que lo haga tu agente?] Conectá Claude Code, Codex o Cursor y pedile "desplegá esta carpeta en Olimpia". La guía está en [Conectar tu agente](/agentes/conectar). ::: 1. **Creá tu cuenta** Entrá a [olimpia.dev/signup](https://olimpia.dev/signup) y registrate con tu email o con GitHub. Durante el acceso anticipado Olimpia es por invitación y no pide tarjeta. Al entrar ya tenés un proyecto llamado `personal`. Podés usarlo o crear otro desde el selector de proyectos. 2. **Conectá GitHub** En **Apps → Nueva app**, elegí **Conectar GitHub**. Se abre GitHub para instalar la GitHub App de Olimpia: elegí la cuenta u organización y a qué repositorios puede acceder. Olimpia solo pide lectura del código. 3. **Elegí el repositorio** Seleccioná el repositorio y la rama. Si tu app vive en una subcarpeta de un monorepo, completá **Carpeta raíz** (por ejemplo `apps/web`). Olimpia detecta el lenguaje con [Railpack](/apps/builds): Node, Bun, Deno, Python, Go, Rust, PHP, Ruby, Java, Elixir o un sitio estático. Si hay un `Dockerfile`, usa ese. 4. **Revisá el puerto** Tu app tiene que escuchar en `0.0.0.0` y en el puerto de la variable `PORT` (3000 por defecto). Si escucha en otro puerto, indicalo en **Puerto**. ```js server.js app.listen(process.env.PORT || 3000, "0.0.0.0"); ``` 5. **Desplegá** Confirmá y mirá el build en vivo. El primero suele tardar entre uno y cuatro minutos. Cuando el estado pasa a **Online**, tu app responde en `https://.olimpia.cc`. 6. **Creá una base Postgres** En **Postgres → Crear base**, elegí un nombre. En unos segundos tenés un Postgres 18 listo, con usuario y contraseña generados. 7. **Conectala a tu app** En tu app, abrí **Variables** y agregá la base del proyecto: Olimpia carga `DATABASE_URL` con la URL interna. Guardá y tocá **Deployar** para aplicar el cambio. ```js db.js import postgres from "postgres"; export const sql = postgres(process.env.DATABASE_URL); ``` Listo. Desde ahora, cada push a la rama que elegiste dispara un build y un deploy sin cortes. ## Siguientes pasos **[Usá tu dominio](/apps/dominios)** Apuntá un CNAME y Olimpia emite el certificado HTTPS. **[Programá backups](/postgres/backups)** Copias automáticas de tu base en tu propio bucket S3. **[Variables de entorno](/apps/variables)** Secretos cifrados, disponibles en el build y al correr. **[Si algo falla](/apps/problemas)** Los errores más comunes y cómo resolverlos. --- # Hoja de ruta Source: https://docs.olimpia.dev/proximamente Estos módulos todavía no se pueden usar (en la consola, los que ya tienen lugar aparecen marcados como **Pronto**); los documentamos para que sepas qué viene y puedas planificar. **[Stream](/proximamente/stream)** Streaming de eventos entre servicios. **[CDN](/proximamente/cdn)** Caché en el edge para assets y respuestas. **[Email](/proximamente/email)** Emails transaccionales desde tu dominio. **[Réplicas de lectura](/proximamente/replicas)** Escalá las lecturas de Postgres. **[Equipos](/proximamente/equipos)** Miembros, roles y ajustes compartidos. **[Facturación](/proximamente/facturacion)** Consumo, facturas y medios de pago. **[Nuevas regiones](/proximamente/regiones)** Más allá de Buenos Aires. ## ¿Te falta algo? Contanos qué más necesitás correr en Olimpia y lo sumamos a la hoja de ruta: [hola@olimpia.dev](mailto:hola@olimpia.dev). --- # CDN Source: https://docs.olimpia.dev/proximamente/cdn :::note[Próximamente] Este módulo todavía no está habilitado. Lo vas a ver en la consola marcado como **Pronto**. Si lo necesitás, escribinos a [hola@olimpia.dev](mailto:hola@olimpia.dev) y contanos tu caso. ::: La CDN de Olimpia va a cachear en el edge los assets estáticos y las respuestas de tus apps, para servirlos desde el punto más cercano a cada usuario. ## Para qué - Servir imágenes, JS y CSS sin que cada pedido llegue a tu app. - Cachear respuestas de APIs públicas con las cabeceras `Cache-Control` de siempre. - Bajar la latencia para usuarios fuera de Argentina. ## Mientras tanto Todo el tráfico de tus apps ya entra por la red de Cloudflare, con HTTPS terminado en el borde. Para archivos estáticos, un [bucket público](/buckets/acceso-publico) sirve objetos desde almacenamiento global. --- # Email Source: https://docs.olimpia.dev/proximamente/email :::note[Próximamente] Este módulo todavía no está habilitado. Lo vas a ver en la consola marcado como **Pronto**. Si lo necesitás, escribinos a [hola@olimpia.dev](mailto:hola@olimpia.dev) y contanos tu caso. ::: Email va a permitir mandar emails transaccionales desde tu propio dominio, por API o por SMTP: confirmaciones, avisos y resets de contraseña. ## Cómo va a funcionar 1. Verificás tu dominio con un par de registros DNS (SPF y DKIM). 2. Enviás por API o SMTP desde tus apps, en la misma región. 3. Ves los envíos, rebotes y entregas desde la consola. --- # Equipos Source: https://docs.olimpia.dev/proximamente/equipos :::note[Próximamente] Este módulo todavía no está habilitado. Lo vas a ver en la consola marcado como **Pronto**. Si lo necesitás, escribinos a [hola@olimpia.dev](mailto:hola@olimpia.dev) y contanos tu caso. ::: Ajustes de equipo va a permitir trabajar con otras personas en la misma cuenta: nombre del equipo, miembros, roles y preferencias. ## Cómo va a funcionar - Invitás a personas por email. - Cada miembro tiene un rol con permisos distintos. - Los proyectos, apps y bases pasan a ser del equipo, no de una persona. ## Mientras tanto Cada cuenta es individual. Para automatizar sin compartir tu contraseña, usá [tokens personales](/cuenta/tokens), que se revocan por separado. --- # Facturación Source: https://docs.olimpia.dev/proximamente/facturacion :::note[Próximamente] Este módulo todavía no está habilitado. Lo vas a ver en la consola marcado como **Pronto**. Si lo necesitás, escribinos a [hola@olimpia.dev](mailto:hola@olimpia.dev) y contanos tu caso. ::: Facturación va a mostrar tu consumo del mes, tus facturas y tus medios de pago, en pesos o en dólares. ## Cómo se va a cobrar Olimpia cobra por uso: CPU, memoria y almacenamiento de cada recurso. No hay planes con topes ni límites artificiales de cantidad de apps o bases. Vamos a publicar los precios antes de abrir la región. ## Mientras tanto Durante el acceso anticipado no se pide tarjeta. --- # Nuevas regiones Source: https://docs.olimpia.dev/proximamente/regiones :::note[Próximamente] Todavía no está disponible. Si lo necesitás, escribinos a [hola@olimpia.dev](mailto:hola@olimpia.dev) y contanos tu caso. ::: Olimpia está pensada para correr en varias regiones. La primera es **BUE**, en [Buenos Aires](/plataforma/buenos-aires). Vamos a anunciar las próximas a medida que abran. Cuando haya más regiones, vas a elegir dónde corre cada proyecto, y tus apps y bases van a quedar juntas en la misma región. --- # Réplicas de lectura Source: https://docs.olimpia.dev/proximamente/replicas :::note[Próximamente] Todavía no está disponible. Si lo necesitás, escribinos a [hola@olimpia.dev](mailto:hola@olimpia.dev) y contanos tu caso. ::: Las réplicas de lectura van a copiar tu base Postgres en tiempo real para que puedas mandarles consultas de solo lectura: reportes, búsquedas y dashboards, sin cargar la base principal. ## Mientras tanto Tu base [no tiene topes fijos de CPU ni memoria](/postgres): usa lo que necesita. Si tenés consultas pesadas, mirá las [consultas lentas en los logs](/postgres/logs-y-metricas) y agregá índices. --- # Stream Source: https://docs.olimpia.dev/proximamente/stream :::note[Próximamente] Este módulo todavía no está habilitado. Lo vas a ver en la consola marcado como **Pronto**. Si lo necesitás, escribinos a [hola@olimpia.dev](mailto:hola@olimpia.dev) y contanos tu caso. ::: Stream va a permitir publicar y consumir eventos en tiempo real entre tus servicios, dentro de la misma región que tus apps. ## Para qué - **Pagos y pedidos.** Publicá un evento cuando entra un pago y que cada servicio reaccione a su ritmo. - **Notificaciones.** Desacoplá el envío de emails, push y webhooks del pedido original. - **Logs y auditoría.** Juntá eventos de varias apps en un solo flujo ordenado. - **Pipelines de datos.** Alimentá procesos de análisis sin cargar tu base principal. ## Mientras tanto Para colas de trabajos, usá [Redis](/redis) con BullMQ, Sidekiq o Celery: Olimpia nunca borra claves por falta de memoria, así que tus colas no pierden trabajos. --- # Redis Source: https://docs.olimpia.dev/redis Una instancia de Redis de Olimpia es un Redis 8 propio, persistido en disco y conectado a tus apps por la [red interna](/plataforma/red-interna). Usala para caché, sesiones, colas de trabajos, pub/sub o rate limiting. ## Crear una instancia 1. **Abrí Redis** En la consola, entrá a **Redis → Crear instancia** y elegí un nombre. 2. **Conectala a tu app** En la app, abrí **Variables** y agregá la instancia: Olimpia carga `REDIS_URL`. Desplegá para aplicarlo. ## Qué incluye - **Redis 8**, listo en segundos. - **Persistencia en disco** (AOF): si la instancia se reinicia, tus datos siguen ahí. - **Sin desalojo de claves.** No hay `maxmemory`: Redis nunca borra claves para hacer lugar. Es lo que necesitan las colas como BullMQ, Sidekiq o Celery. - **Sin límite fijo de memoria.** Usa lo que necesita y pagás por uso. - **Acceso externo opcional** por TLS. Ver [Conexión](/redis/conexion). - **Métricas**: memoria usada, operaciones por segundo, clientes conectados y bloqueados, cantidad de claves y aciertos de caché. ## Ejemplos **ioredis** ```js import Redis from "ioredis"; const redis = new Redis(process.env.REDIS_URL); await redis.set("saludo", "hola", "EX", 60); ``` **BullMQ** ```js import { Queue, Worker } from "bullmq"; import Redis from "ioredis"; const connection = new Redis(process.env.REDIS_URL, { maxRetriesPerRequest: null }); const emails = new Queue("emails", { connection }); new Worker("emails", async (job) => enviar(job.data), { connection }); ``` **redis-py** ```python import os import redis r = redis.from_url(os.environ["REDIS_URL"]) r.set("saludo", "hola", ex=60) ``` **go-redis** ```go opt, _ := redis.ParseURL(os.Getenv("REDIS_URL")) rdb := redis.NewClient(opt) rdb.Set(ctx, "saludo", "hola", time.Minute) ``` ## Comandos permitidos Te conectás con el usuario `default`, que puede usar todos los comandos de datos. Los de administración (`CONFIG`, `ACL`, `SHUTDOWN`, `DEBUG` y similares) están deshabilitados. --- # Conexión Source: https://docs.olimpia.dev/redis/conexion ## Desde tus apps Usá la URL interna, la que Olimpia carga en `REDIS_URL`: ```txt redis://default:@:6379 ``` Sin TLS y sin salir a internet. ## Acceso externo Para conectarte desde tu compu u otra nube, habilitá las conexiones externas en la pestaña **Conexión**. La URL pública usa TLS: ```txt rediss://default:@rd-.db.olimpia.cc:6379 ``` ```bash redis-cli -u "rediss://default:@rd-.db.olimpia.cc:6379" ping ``` Fijate en la doble `s` de `rediss://`: TLS es obligatorio y el cliente tiene que mandar SNI. ioredis, node-redis, redis-py y go-redis lo hacen con esa URL. ## Rotar la contraseña **Rotar contraseña** genera una nueva: la anterior deja de valer y se cortan las conexiones abiertas con ella. La instancia se reinicia unos segundos para aplicar el cambio. Después, actualizá `REDIS_URL` en tus apps y desplegá.