Synsema docsENES

Deploy

Synsema viene como un único binario estático — sin runtime en el destino. El bloque serve queda dev-clean en el repo; los knobs de deploy son flags del CLI, así el mismo archivo corre local y en prod sin ediciones.

synsema serve app.syn        # dev: :8080, HTTP plano, sin setup
synsema serve app.syn --port 443 --domain example.com,www.example.com --tls-auto admin@example.com   # prod: HTTPS

Flags de serve

FlagEfecto
--port NOverride de serve on N y concede serve(N).
--domain d1,d2Dominios ACME (SAN).
--tls-auto <email>HTTPS automático (ACME) — es el switch dev↔prod; necesita un dominio.
--tls-cert / --tls-keyTLS manual (mutuamente excluyente con --tls-auto).
--bind <addr>Dirección de bind (default 0.0.0.0).

Precedencia: flag del CLI > cláusula del archivo > default. Sin --tls-auto → HTTP plano (dev); con --tls-auto → TLS (prod).

Config por entorno (mantené el repo dev-clean)

El archivo .syn no cambia entre tu laptop y el server, así que git pull en prod nunca genera conflictos. Todo lo que difiere vive fuera del código.

Knobs del server → flags del CLI. --port, --domain, --tls-auto (tabla de arriba). El flag gana sobre la cláusula del archivo.

Valores de la app → el entorno. Todo lo que leas con env("NAME", default) — p. ej. la URL pública canónica que alimenta tus tags canonical/OG/sitemap:

require env("SITE_URL")
let SITE be env("SITE_URL", "http://127.0.0.1:8080")   -- default dev; prod lo pisa

Seteala en prod desde el entorno (Environment=SITE_URL=https://example.com en systemd, -e SITE_URL=… en Docker). La resolución es process env > .env > default del código, así que no hace falta editar el repo.

Knobs del runtime → el entorno del proceso (no .env). SYNSEMA_SERVE_WORKERS=N dimensiona el pool de workers del intérprete que atienden requests (default: uno por core, mín. 2). Subilo para handlers I/O-bound — más requests en vuelo, a costa de más RAM. A diferencia de los valores de la app, este knob configura el runtime mismo, así que se lee una sola vez, del entorno del proceso, antes de que arranque el primer serverEnvironment= en systemd, -e en Docker, export en una shell. Ponerlo en .env no hace nada: el .env sólo alimenta a env()/secret() dentro de tu programa.

¿Dos apps en un mismo host? Dale a cada una su puerto — el código queda idéntico: synsema serve api.syn --port 8081 y synsema serve admin.syn --port 8082. Como --port pisa serve on N y concede serve(N), no cambia nada en ninguno de los dos archivos.

HTTPS, paso a paso (certificado gratis y auto-renovable)

--tls-auto obtiene un certificado gratis de Let's Encrypt (ACME) y lo auto-renueva — sin certbot, sin cron. Qué necesitás:

1. Un dominio apuntando a la IP del server (un registro DNS A/AAAA).

2. Puertos 80 y 443 alcanzables — el 80 responde el desafío ACME una vez, después redirige al 443.

3. Correr con el dominio + un email de contacto:

synsema serve app.syn --port 443 --domain example.com,www.example.com --tls-auto you@example.com

Al primer arranque Synsema obtiene el certificado, sirve HTTPS en 443, redirige HTTP→HTTPS, y auto-renueva ~30 días antes del vencimiento (90 días). Los certificados se guardan (SYNSEMA_CERT_DIR~/.synsema/certs), así que un restart los recarga (sin re-emisión → sin rate-limit).

El challenge de ACME escucha en el puerto 80 (HTTP-01), y la CA tiene que poder

alcanzarlo desde internet. Si ese puerto ya está tomado —otro servidor, un mapeo de

contenedor, un sidecar— movelo con SYNSEMA_ACME_HTTP_PORT=8080 y redirigí el :80

externo hacia ahí. Como el resto de los knobs de runtime se lee del **entorno del

proceso**, no del .env.

¿Ya tenés un certificado? Usá --tls-cert cert.pem --tls-key key.pem (mutuamente excluyente con --tls-auto). Bajo systemd, dale al servicio un HOME/StateDirectory escribible (abajo) para que pueda guardar los certificados.

synsema daemon vs systemd — elegí uno

[Service]
ExecStart=/usr/local/bin/synsema serve /opt/app/app.syn --port 443 --domain example.com --tls-auto admin@example.com
Restart=always
StateDirectory=synsema        # HOME escribible para el fallback ~/.synsema/certs

Varios sitios en un mismo host (Synsema es su propio edge proxy)

Dos procesos no pueden bindear ambos :443, y no necesitás nginx/Caddy. Un proceso Synsema es el edge: termina TLS para cada dominio (un cert SAN) y enruta por Host a cada backend, que corre en HTTP plano en un puerto privado.

-- edge.syn — TLS + routing por Host para cada sitio del server
require serve(443)
require net("127.0.0.1")            -- deny-by-default: el edge sólo habla con localhost

serve on 443
    host "example.com"
        route "GET /"                              -- raíz: /*path NO matchea "/"
            proxy to "http://127.0.0.1:8080"
        route "GET /*path"
            proxy to "http://127.0.0.1:8080"
        route "POST /*path"
            proxy to "http://127.0.0.1:8080"
    host "docs.example.com"
        route "GET /"
            proxy to "http://127.0.0.1:8791"
        route "GET /*path"
            proxy to "http://127.0.0.1:8791"
        route "POST /*path"
            proxy to "http://127.0.0.1:8791"

Corré el edge con un cert SAN para todos los dominios; cada backend en HTTP plano, sólo localhost, con su propio repo/versión/servicio:

synsema serve edge.syn --port 443 --domain example.com,docs.example.com --tls-auto admin@example.com
synsema serve app.syn  --port 8080 --bind 127.0.0.1
synsema serve docs.syn --port 8791 --bind 127.0.0.1

Docker y Kubernetes

La imagen es solo el binario de Synsema — el mismo binario estático prebuilt que instala el sitio. El Dockerfile del repo lo baja de la release de GitHub y verifica su checksum (no compila); vos montás tu programa .syn en /app:

docker build -t synsema .                                   # o --build-arg SYNSEMA_VERSION=v0.4.9
docker run -d --restart unless-stopped -e ANTHROPIC_API_KEY=sk-... \
    -v "$PWD":/app -w /app -p 8080:8080 synsema serve app.syn

En K8s, command: ["synsema", "serve", "/app/app.syn"] e inyectá claves vía secretKeyRef. Los secretos/config vienen del environment en prod (override de .env) — ver Secretos.

Actualizar

Un server corriendo no se auto-actualiza. synsema update reemplaza el binario en disco; systemctl restart lo aplica. Los certs TLS persisten (guardados + auto-renovados), así que un restart los recarga — sin pegarle al rate-limit de Let's Encrypt.