TLS deployment for Studio

OpenADS Studio listens on plaintext HTTP today (openads_serverd --http-port N). The wire protocol has its own tls:// URI for client-side TLS (M12.12, vendored mbedtls 3.6 LTS), but the embedded HTTP console is wired through cpp-httplib, which only ships TLS via OpenSSL — not bundled in the daemon to keep the binary lean.

To run Studio on HTTPS in production, terminate TLS in front of the daemon. Three battle-tested options follow; all of them keep openads_serverd listening on 127.0.0.1 so only the proxy is reachable from the network.

Caddy auto-provisions a Let’s Encrypt certificate, redirects HTTP → HTTPS, sets sane TLS defaults, and reloads on config change. Caddyfile:

studio.example.com {
    reverse_proxy 127.0.0.1:6263
}
# install (Linux)
sudo apt-get install caddy
sudo nano /etc/caddy/Caddyfile        # paste the snippet above
sudo systemctl reload caddy

The studio is now reachable at https://studio.example.com/. The cert is renewed automatically; Caddy serves OCSP-stapled responses by default.

Option 2 — nginx

server {
    listen 443 ssl http2;
    server_name studio.example.com;

    ssl_certificate     /etc/letsencrypt/live/studio.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/studio.example.com/privkey.pem;

    # Proxy everything to the local Studio port.
    location / {
        proxy_pass         http://127.0.0.1:6263;
        proxy_http_version 1.1;
        proxy_set_header   Host              $host;
        proxy_set_header   X-Real-IP         $remote_addr;
        proxy_set_header   X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header   X-Forwarded-Proto https;
    }
}

server {
    listen 80;
    server_name studio.example.com;
    return 301 https://$server_name$request_uri;
}

Pair with certbot --nginx -d studio.example.com for a Let’s Encrypt cert.

Option 3 — stunnel (TLS-only termination)

Smaller surface than full HTTP proxies — stunnel just wraps the plaintext socket in TLS. Useful when an existing infra runs no web server.

# /etc/stunnel/openads.conf
[studio]
accept  = 0.0.0.0:443
connect = 127.0.0.1:6263
cert    = /etc/stunnel/openads-fullchain.pem
key     = /etc/stunnel/openads-key.pem
sudo apt-get install stunnel4
sudo systemctl enable --now stunnel4

Option 4 — SSH tunnel (zero-config, single user)

When only one admin needs to reach Studio and there’s already an SSH login, no proxy is needed:

ssh -L 6263:localhost:6263 user@server.example.com
# now open http://localhost:6263 in any browser

The SSH session encrypts the entire HTTP traffic; the daemon keeps listening on 127.0.0.1:6263 inside the remote box.

+--------+      HTTPS        +-------+   plaintext HTTP   +-----------------+
| Browser| ---------------→ | Caddy | -----------------→ | openads_serverd |
+--------+   public TLS      +-------+    127.0.0.1:6263  +-----------------+
                              ↑                                ↓
                            Let's Encrypt                  data dir

Daemon flags for this shape:

openads_serverd \
    --port 6262 \
    --http-port 6263 \
    --data /srv/openads/data \
    --http-user admin:strong-password
# bind --http-port to 127.0.0.1 by passing --host 127.0.0.1 if you don't
# want any path other than the proxy reaching the console.

Pair the proxy’s TLS with --http-user so even on a hijacked TLS terminator the credentials are required for any API call.

Native HTTPS in serverd

A dedicated OPENADS_WITH_OPENSSL=ON CMake option is on the roadmap. It would link cpp-httplib’s OpenSSL backend, accept --tls-cert <pem> --tls-key <pem> flags, and let serverd serve HTTPS without a proxy. Status: planned for a future studio.web.x milestone; until then, terminate TLS at a proxy.