# Automatic HTTPS for your app in one flag — no nginx, no certbot

> Synsema's built-in server issues and renews Let's Encrypt certificates itself. One flag turns the file you run in dev into a production HTTPS site, with HTTP/2, HSTS and www → apex.

Published 2026-09-02 · https://synsema.org/blog/automatic-https-lets-encrypt-one-flag


The usual production checklist for a small service: install nginx, write a site config, install
certbot, run it once, add a cron to renew, reload nginx after each renewal, remember all of this on the
next server. Synsema's server does the whole list by itself, because TLS and ACME are part of the
runtime, not a reverse proxy you put in front.

## The same file, dev and prod

Nothing in the program says "production". You run it plain in dev:

```sh
synsema serve app.syn                      # http://127.0.0.1:8080
```

And you run the **same file** in production with flags:

```sh
synsema serve app.syn --port 443 --domain example.com --tls-auto you@example.com
```

`--tls-auto` is the switch. The server orders a certificate from Let's Encrypt, answers the
HTTP-01 challenge on `:80`, stores the certificate under `~/.synsema/certs/`, and a background
thread renews it when fewer than 30 days remain. `:80` also redirects everything else to HTTPS.
TLS 1.2+ is enforced, HSTS is on, and HTTP/2 is negotiated over ALPN.

## One certificate for apex and www

Pass a list to `--domain` (or to `domain` in the file) and you get a single SAN certificate. To
canonicalize `www` to the apex, give `www` its own virtual host whose only job is to redirect:

```synsema
require serve(443)

serve on 443
    tls auto "you@example.com"
    domain ["example.com", "www.example.com"]
    host "www.example.com"
        route "GET /"
            give redirect("https://example.com/")
        route "GET /*path"
            give redirect("https://example.com/" + params.path)
    static "/assets" from "./static"
    route "GET /"
        give render("pages/home.html", {"title": "Home"})
```

Every name in the list must resolve to the server and be reachable on `:80`, or the order fails
loudly at startup instead of half-working.

## What you did not have to write

No nginx config, no certbot timer, no reload hook, no proxy headers to forward. The certificate is
per host (SNI), so several sites can share one process. If you do want something in front, the
server also speaks reverse proxy (`proxy to`) and streams SSE and WebSockets through it.

**Try it in ten minutes:** [install Synsema](/install), point a domain at your server and run the
second command above. The full deployment page — systemd, Docker, Kubernetes — is in the
[docs](https://synsema.dev/en/0.6.x/71-deploy).

