Desplegar en Linux
Esta guía utiliza un servidor Debian/Ubuntu con systemd, una aplicación en /srv/orionis-app, un usuario de servicio orionis y el dominio de ejemplo app.example.com. Sustituye el dominio y proporciona un certificado válido para él. La aplicación atiende exclusivamente en 127.0.0.1:8000; Nginx recibe las conexiones públicas.
flowchart TD
accTitle: Servicio Linux con Nginx y Orionis
A[Cliente HTTPS / WSS] --> B[Nginx: TLS y proxy inverso]
B -->|HTTP / WebSocket, 127.0.0.1:8000| C[Granian: un worker ASGI]
C --> D[bootstrap.app:app]
D --> E[Arranque HTTP y proveedores]
E --> F[Rutas, middleware y componentes]
G[systemd] -->|Inicio, supervisión y parada| C1. Preparar el servidor y la entrega
Sección titulada «1. Preparar el servidor y la entrega»Necesitas acceso administrativo, DNS dirigido al servidor, los puertos públicos 80 y 443 habilitados y una entrega de tu aplicación, no solamente del paquete orionis. Esa entrega debe contener reactor, bootstrap/app.py, los directorios de la aplicación, pyproject.toml y su uv.lock revisado. Excluye .venv, credenciales y cachés generadas en otra máquina.
La implementación requiere Python 3.14 o posterior. En este ejemplo se selecciona Python 3.14; conserva la versión de Python con la que hayas verificado tu aplicación. Granian y su integración RSGI/ASGI ya forman parte de las dependencias de Orionis.
En un servidor nuevo, instala las herramientas del sistema y Nginx:
sudo apt updatesudo apt install --yes ca-certificates curl nginxsudo useradd --system --user-group --create-home --home-dir /var/lib/orionis --shell /usr/sbin/nologin orionissudo install -d -o orionis -g orionis -m 0750 /srv/orionis-appLa distribución proporciona el servicio y la estructura de sitios de Nginx utilizados aquí; consulta su instalación en Ubuntu si el servidor tiene otra configuración previa.
Instala uv para el usuario del servicio. Su directorio personal también conservará el intérprete de Python que utiliza .venv:
sudo -u orionis -H sh -c 'curl -LsSf https://astral.sh/uv/install.sh | sh'sudo -u orionis -H /var/lib/orionis/.local/bin/uv python install 3.14Estos comandos corresponden al instalador oficial de uv y a su gestión de Python. El usuario no necesita una sesión interactiva ni permisos de administrador para ejecutar la aplicación.
2. Instalar las dependencias de la aplicación
Sección titulada «2. Instalar las dependencias de la aplicación»Coloca la entrega preparada en /tmp/orionis-release. Los siguientes comandos comprueban sus archivos de entrada antes de copiarla:
set -eutest -f /tmp/orionis-release/reactortest -f /tmp/orionis-release/bootstrap/app.pytest -f /tmp/orionis-release/pyproject.tomltest -f /tmp/orionis-release/uv.locksudo cp -a /tmp/orionis-release/. /srv/orionis-app/sudo chown -R orionis:orionis /srv/orionis-appcd /srv/orionis-appsudo -u orionis -H /var/lib/orionis/.local/bin/uv sync --locked --no-default-groups --python 3.14--locked exige que el lockfile entregado esté actualizado respecto a pyproject.toml; si necesita cambios, la instalación falla en lugar de modificarlo. --no-default-groups excluye los grupos de desarrollo y otros grupos predeterminados. Las dependencias de producción y extras que necesite tu aplicación deben estar declarados y seleccionados en esa entrega; si tu propio proyecto define extras necesarios, añade su --extra correspondiente al comando. Véanse sincronización del proyecto y opciones de uv sync.
3. Proporcionar la configuración y los permisos
Sección titulada «3. Proporcionar la configuración y los permisos»Entrega el .env de producción por tu mecanismo de secretos. Por ejemplo, si se ha montado temporalmente como /run/secrets/orionis-app.env:
sudo install -o root -g orionis -m 0640 /run/secrets/orionis-app.env /srv/orionis-app/.envsudoedit /srv/orionis-app/.envComprueba estas entradas dentro del archivo, conservando su APP_KEY privada y el resto de credenciales de la aplicación:
APP_ENV=productionAPP_DEBUG=bool:falseAPP_URL=https://app.example.comALLOWED_HOSTS=list:['app.example.com']TRUSTED_PROXIES=list:['127.0.0.1']SESSION_DRIVER=fileSESSION_SECURE=bool:trueEl ejemplo utiliza sesiones de archivo para esta instancia y cookies seguras a través de HTTPS; conserva tu driver si ya utilizas otro almacén de producción. Esto no incorpora sesiones a las rutas API. TRUSTED_PROXIES corresponde al salto Nginx → aplicación de este escenario. Nginx sustituirá los encabezados de reenvío del cliente; Orionis solamente los utiliza cuando la conexión procede de un proxy confiable. Revisa la configuración de proxies si existe otro balanceador delante.
El framework lee .env desde el directorio de trabajo y convierte los prefijos tipados al cargar los archivos de configuración. Por eso el servicio tendrá WorkingDirectory=/srv/orionis-app. En esta guía lo carga Orionis; no se usa EnvironmentFile= de systemd ni --env-files de Granian para evitar una segunda lectura del mismo archivo. Un .env presente también puede sobrescribir variables coincidentes del proceso durante su carga. Consulta Entorno para definir una única fuente coherente de configuración.
Prepara los directorios que usarán el disco público y los componentes que escriben en storage. Después limita la escritura de código al administrador:
sudo install -d -o orionis -g orionis -m 0750 /srv/orionis-app/storage/app/public /srv/orionis-app/storage/app/private /srv/orionis-app/storage/framework /srv/orionis-app/storage/logssudo chown -R root:orionis /srv/orionis-appsudo chmod -R u=rwX,g=rX,o= /srv/orionis-appsudo chown -R orionis:orionis /srv/orionis-app/storagesudo chmod 0640 /srv/orionis-app/.envSi utilizas SQLite, su archivo y el directorio que contiene los archivos auxiliares de SQLite deben permitir escritura al usuario orionis. Puedes configurar DB_DATABASE=storage/app/private/database.sqlite en .env; en una aplicación existente, traslada y conserva la base de datos de forma controlada, con el servicio detenido. La ruta predeterminada database/database.sqlite queda fuera del directorio escribible de este servicio. Para un motor externo, configura su conexión y los drivers correspondientes; consulta Database.
Comprueba el arranque y las rutas desde la raíz:
cd /srv/orionis-appsudo -u orionis -H .venv/bin/python -B reactor aboutsudo -u orionis -H .venv/bin/python -B reactor route:listsudo -u orionis -H .venv/bin/python -B reactor serve --exportserve --export muestra el comando generado sin iniciar el servidor. En Linux, serve selecciona tantos workers como CPU lógicas y, en producción, escucha en 0.0.0.0. El servicio de esta guía usa explícitamente loopback y un worker; no copies esos valores del comando exportado sin revisar la topología. Aplica las migraciones que tu entrega requiera como una operación controlada, antes de atender tráfico.
4. Registrar el servicio systemd
Sección titulada «4. Registrar el servicio systemd»Crea /etc/systemd/system/orionis-app.service:
[Unit]Description=Orionis HTTP applicationWants=network-online.targetAfter=network-online.target
[Service]Type=simpleUser=orionisGroup=orionisWorkingDirectory=/srv/orionis-appEnvironment=PYTHONUTF8=1Environment=PYTHONDONTWRITEBYTECODE=1ExecStart=/srv/orionis-app/.venv/bin/python -B -m granian --interface asgi --host 127.0.0.1 --port 8000 --workers 1 --loop uvloop --no-reload --log-level info --workers-kill-timeout 60 --static-path-mount /srv/orionis-app/storage/app/public --static-path-route /static --static-path-dir-to-file index.html bootstrap.app:appRestart=on-failureRestartSec=3KillMode=mixedTimeoutStopSec=75UMask=0077NoNewPrivileges=truePrivateTmp=trueProtectSystem=strictReadWritePaths=/srv/orionis-app/storageStandardOutput=journalStandardError=journal
[Install]WantedBy=multi-user.targetbootstrap.app:app importa la instancia creada en bootstrap/app.py; no requiere un wrapper ni --factory. La ruta estática reproduce el disco público predeterminado. Si cambias config/filesystems.py, ajusta tanto el directorio como la URL del montaje; los archivos de ese montaje son públicos y no pasan por los middleware de tus rutas.
La alternativa RSGI sustituye únicamente --interface asgi por --interface rsgi. RSGI ejecuta los hooks de inicio/finalización de Granian; ASGI utiliza el protocolo lifespan. En ambos casos el arranque HTTP prepara el kernel y los proveedores de Orionis. Consulta puntos de entrada.
systemd supervisa el proceso padre y registra stdout/stderr. Al detenerlo, KillMode=mixed envía primero la señal de terminación al proceso principal; el límite de 75 segundos permite al supervisor de Granian agotar su espera de 60 segundos antes de una parada forzada. No garantiza finalizar indefinidamente una conexión WebSocket/SSE. Los detalles de supervisión y terminación están en systemd.service y systemd.kill.
ProtectSystem=strict hace de solo lectura el sistema de archivos del servicio salvo sus directorios privados y la excepción declarada en ReadWritePaths. Si tu aplicación escribe en otras rutas configuradas, decláralas expresamente; revisa systemd.exec.
Activa el servicio y comprueba el backend conservando el Host público:
sudo systemd-analyze verify /etc/systemd/system/orionis-app.servicesudo systemctl daemon-reloadsudo systemctl enable --now orionis-appsudo systemctl status orionis-app --no-pagercurl --fail --header 'Host: app.example.com' http://127.0.0.1:8000/up/up es la ruta de salud predeterminada de withRouting(health="/up"). Si tu bootstrap la modifica, utiliza la ruta configurada. Una respuesta satisfactoria comprueba el flujo HTTP, no la disponibilidad de todos los servicios externos.
5. Configurar Nginx con HTTPS
Sección titulada «5. Configurar Nginx con HTTPS»Proporciona la cadena completa de un certificado emitido para app.example.com y su clave privada mediante tu proceso de certificados. En este ejemplo se reciben como archivos temporales de secretos y se instalan en rutas explícitas:
sudo install -d -m 0755 /etc/nginx/tlssudo install -m 0644 /run/secrets/fullchain.pem /etc/nginx/tls/orionis-fullchain.pemsudo install -m 0600 /run/secrets/privkey.pem /etc/nginx/tls/orionis-privkey.pemNginx utiliza la cadena del certificado y la clave por separado; consulta su configuración de HTTPS. Programa la renovación mediante el emisor de tus certificados y recarga Nginx tras instalar los archivos renovados.
Crea /etc/nginx/sites-available/orionis-app. En Debian/Ubuntu este archivo se incluye dentro de http { ... }; por eso map y upstream se declaran fuera de los bloques server:
map $http_upgrade $orionis_connection { default upgrade; '' close;}
upstream orionis_app { server 127.0.0.1:8000;}
server { listen 80; server_name app.example.com; return 308 https://app.example.com$request_uri;}
server { listen 443 ssl; server_name app.example.com; ssl_certificate /etc/nginx/tls/orionis-fullchain.pem; ssl_certificate_key /etc/nginx/tls/orionis-privkey.pem; ssl_protocols TLSv1.2 TLSv1.3; client_max_body_size 16m;
location / { proxy_pass http://orionis_app; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $orionis_connection; proxy_buffering off; proxy_read_timeout 3600s; proxy_send_timeout 3600s; }}Los encabezados Upgrade/Connection permiten WebSocket; véase la guía oficial de Nginx. proxy_pass conserva la ruta completa, incluidos los endpoints API, Realtime, MCP y SSE. proxy_buffering off evita retener las respuestas SSE en el proxy. Los timeouts son intervalos sin actividad entre operaciones, no una duración garantizada de conexión; adapta sus valores a los heartbeats de tu aplicación. Consulta buffering y timeouts.
El máximo de 16 MiB coincide con el límite total HTTP predeterminado de Orionis. Ajusta ambos si necesitas otro tamaño; los límites de partes/archivos del framework siguen aplicándose. El proxy no sustituye la validación de orígenes WebSocket ni las políticas CORS/CSRF de la aplicación.
Activa el sitio en este servidor nuevo:
sudo ln -s /etc/nginx/sites-available/orionis-app /etc/nginx/sites-enabled/orionis-appsudo nginx -tsudo systemctl enable --now nginxsudo systemctl reload nginxcurl --fail https://app.example.com/upEl firewall debe publicar 80/443 y permitir tu acceso administrativo. El backend 8000 permanece ligado a loopback; no necesita una regla de entrada pública. Valida también una ruta real de tu aplicación y, si los utilizas, una conexión WebSocket y un stream SSE a través de HTTPS.
6. Operar, actualizar y diagnosticar
Sección titulada «6. Operar, actualizar y diagnosticar»Consulta el proceso y los registros por separado:
sudo journalctl -u orionis-app --since '10 minutes ago' --no-pagersudo tail -n 100 /var/log/nginx/error.logsudo systemctl restart orionis-appsudo systemctl stop orionis-appsudo systemctl start orionis-appjournalctl muestra la salida de Granian y del proceso; los archivos de la fachada Log dependen de tus canales y normalmente se ubican en storage/logs. Revisa Logs para rotación y retención.
Para una actualización en este único servidor:
- Prepara y verifica otra entrega y realiza las copias de seguridad de datos necesarias.
- Retira temporalmente el tráfico o acepta una interrupción controlada y detén
orionis-app. - Instala el código y sincroniza
.venvcomo en la preparación, restaurando después los permisos descritos. Conserva.env, archivos persistentes y bases de datos. - Limpia las cachés de la entrega anterior conforme a caché de bootstrap, aplica las migraciones previstas y arranca el servicio.
- Comprueba
/up, los endpoints reales y los registros antes de restablecer el tráfico.
restart vuelve a importar el bootstrap y ejecuta el ciclo de vida; no equivale a un despliegue sin interrupciones. Modificar .env o un archivo de código no actualiza los procesos existentes. Este servicio no utiliza --reload en producción.
El ejemplo empieza con un worker porque las sesiones en memoria, los grupos/conexiones Realtime, ciertos eventos MCP y otros estados locales no se comparten automáticamente entre procesos. Consulta las guías de sesiones, Realtime y MCP antes de aumentar --workers o distribuir instancias. Los workers de colas y el scheduler requieren procesos supervisados independientes; arrancar este servicio HTTP no los inicia.
| Síntoma | Comprobación concreta |
|---|---|
Nginx devuelve 502 | Revisa systemctl status, el journal, el puerto 8000 y que la instancia importe bootstrap.app:app desde la raíz correcta. |
Orionis devuelve 400 al comprobar por IP | Envía Host: app.example.com; comprueba ALLOWED_HOSTS y que Nginx preserve el host esperado. |
| No se escriben logs, caché o SQLite | Comprueba propietario, permisos y que la ruta esté incluida en el directorio escribible de ReadWritePaths. |
| Se interrumpe SSE o no conecta WebSocket | Comprueba buffering, encabezados de upgrade, timeouts y orígenes permitidos antes de modificar el controlador. |
| La configuración sigue mostrando valores anteriores | Revisa el .env realmente cargado, la caché compilada y reinicia todos los procesos de esa entrega. |