Synsema docsENES

Deploy

Synsema ships as a single static binary — no runtime on the target. The serve block stays dev-clean in the repo; deployment knobs are CLI flags, so the same file runs locally and in prod without edits.

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

Serve flags

FlagEffect
--port NOverrides serve on N and grants serve(N).
--domain d1,d2ACME SAN domains.
--tls-auto <email>Automatic HTTPS (ACME) — this is the dev↔prod switch; needs a domain.
--tls-cert / --tls-keyManual TLS (mutually exclusive with --tls-auto).
--bind <addr>Bind address (default 0.0.0.0).

Precedence: CLI flag > file clause > default. No --tls-auto → plain HTTP (dev); --tls-auto → TLS (prod).

Per-environment config (keep the repo dev-clean)

The .syn file never changes between your laptop and the server, so git pull on prod never conflicts. Everything that differs lives outside the code.

Server knobs → CLI flags. --port, --domain, --tls-auto (table above). The flag wins over the file clause.

App values → the environment. Anything you read with env("NAME", default) — e.g. the canonical public URL that feeds your canonical/OG/sitemap tags:

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

Set it on prod in the environment (Environment=SITE_URL=https://example.com under systemd, -e SITE_URL=… in Docker). Resolution is process env > .env > code default, so no repo edit is needed.

Two apps on one host? Give each its own port — the code stays identical: synsema serve api.syn --port 8081 and synsema serve admin.syn --port 8082. Since --port overrides serve on N and grants serve(N), nothing in either file changes.

HTTPS, step by step (free, auto-renewing cert)

--tls-auto gets a free certificate from Let's Encrypt (ACME) and auto-renews it — no certbot, no cron. What you need:

1. A domain pointing to the server's IP (a DNS A/AAAA record).

2. Ports 80 and 443 reachable — port 80 answers the one-time ACME challenge, then redirects to 443.

3. Run with the domain + a contact email:

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

On first boot Synsema obtains the cert, serves HTTPS on 443, redirects HTTP→HTTPS, and auto-renews ~30 days before the 90-day expiry. Certs are stored (SYNSEMA_CERT_DIR~/.synsema/certs), so a restart reloads them (no re-issue → no rate-limit).

Already have a cert? Use --tls-cert cert.pem --tls-key key.pem instead (mutually exclusive with --tls-auto). Under systemd, give the service a writable HOME/StateDirectory (below) so it can store certs.

synsema daemon vs systemd — pick one

[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        # writable HOME for ~/.synsema/certs fallback

Multiple sites on one host (Synsema is its own edge proxy)

Two processes can't both bind :443, and you don't need nginx/Caddy. One Synsema process is the edge: it terminates TLS for every domain (one SAN cert) and routes by Host to each backend, which runs plain-HTTP on a private port.

-- edge.syn — TLS + Host routing for every site on the box
require serve(443)
require net("127.0.0.1")            -- deny-by-default: the edge only talks to localhost

serve on 443
    host "example.com"
        route "GET /"                              -- root: /*path does NOT match "/"
            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"

Run the edge with a SAN cert for all domains; each backend runs plain-HTTP, localhost-only, with its own repo/version/service:

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 & Kubernetes

docker run -d --restart unless-stopped -e ANTHROPIC_API_KEY=sk-... synsema serve app.syn

In K8s, command: ["synsema", "serve", "/app/agent.syn"] and inject keys via secretKeyRef. Secrets/config come from the environment in prod (overrides .env) — see Secrets.

Updating

A running server does not auto-update. synsema update swaps the binary on disk; systemctl restart applies it. TLS certs persist (stored + auto-renewed), so a restart reloads them — no Let's Encrypt rate-limit hit.