Production
Run the edge under Docker or systemd, where it can and can't be hosted, binding :443, and what to monitor.
The Setup walkthrough gets you a working edge. This page covers running it for real.
Where it can run
Beamd terminates its own TLS and ALPN-demuxes public HTTPS from client control
on a single :443, so it needs a raw TCP :443 on a public IP. That's the
whole story of platform fit:
| Target | Fits? | Why |
|---|---|---|
| Any VM — DigitalOcean, Hetzner, Linode, Vultr, EC2, GCE | ✅ | You're the host; raw :443 + public IP. |
| Fly.io | ✅ | Raw-TCP passthrough + a dedicated IP. |
| Render, Railway, Heroku, Cloud Run, DO App Platform | ❌ | They terminate TLS in front of your container. |
| Cloudflare Workers / Pages | ❌ | Request-scoped; no raw :443 + custom TLS/ALPN. |
Cloudflare is a DNS provider here, not a host — you can't run the edge on Cloudflare compute.
Docker (recommended)
The bundled example/docker-compose.yml is the production-ready shape:
services:
beamd:
image: ghcr.io/dynamismlabs/beamd:latest
container_name: beamd
restart: unless-stopped
user: "0:0" # root: bind :443, read tokens.json, write cert cache
dns: ["1.1.1.1", "8.8.8.8"] # pin resolvers (see below)
ports: ["443:443"] # the only public port (ALPN-demuxed)
volumes:
- /etc/beamd:/etc/beamd # rw: add-developer updates tokens.json
- /var/lib/beamd:/var/lib/beamd # cert cache + ACME state survive restarts
environment:
- BEAMD_DNS_PROVIDER_CREDS=${BEAMD_DNS_PROVIDER_CREDS}cd /etc/beamd && sudo docker compose up -d
sudo docker compose logs -f beamdPin DNS resolvers. certmagic finds the DNS-01 zone via an SOA lookup, and some hosts' default resolvers intermittently
SERVFAIL, which breaks ACME issuance. The compose file pins1.1.1.1/8.8.8.8to avoid it.
systemd (binary install)
If you run the static binary instead of Docker, grant the :443 capability and
run it as a unit:
sudo cp bin/beamd /usr/local/bin/
sudo setcap cap_net_bind_service=+ep /usr/local/bin/beamd
sudo tee /etc/systemd/system/beamd.service >/dev/null <<'EOF'
[Unit]
Description=Beamd edge server
After=network.target
[Service]
Type=simple
User=root
Environment=BEAMD_DNS_PROVIDER_CREDS=YOUR_CF_TOKEN
ExecStart=/usr/local/bin/beamd serve --config /etc/beamd/beamd.yaml
Restart=on-failure
RestartSec=2s
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl enable --now beamd
journalctl -u beamd -f:443 needs root or CAP_NET_BIND_SERVICE — the setcap line covers the
non-root binary case.
Running the client agent as a service
On a machine that should keep tunnels up unattended (a build box, an embedded
host app), run the background agent as a service instead of relying on
beamd open -d to spawn it. See Agent local API and
Embed in your app.
Monitoring
- Health:
GET /healthz→{"status":"ok","version":"…"}. - Metrics: the edge exposes
/metrics(Prometheus format) with per-slug bandwidth and active-tunnel counts — scrape it for dashboards and alerts. - Certs: certmagic renews automatically before expiry; wire
/metricsinto alerting if you want to be paged on failure.
Known limits
A single edge is a single point of failure — no built-in HA or anycast; if the VM dies, tunnels drop until it's back (fine for personal/team use, run a second region if you need more). Body size is capped but there's no per-IP rate limit — put a fronting WAF in front if you're exposed to abuse. See Limits & quotas.