Repository navigation
HTTPS
Obelo can terminate TLS itself — useful when you reach your server from outside the house by forwarding a port, with no reverse proxy in front.
Do you actually want a port forward? If everyone who watches is willing to install a VPN client, Remote Access with Tailscale gets you a stable HTTPS address with no domain, no DNS, no port forward, and nothing exposed to the internet. This page is for the case where you need to hand a URL to someone who will not install anything.
A public origin set up here is also one of the ways a friend's Obelo can reach yours to receive libraries you lend it — see Linked Servers, which has a no-port-forward path too.
Turning TLS on does not stop the plain-HTTP listener. OBELO_LISTEN_ADDR
keeps serving exactly as before, because no public CA will issue a certificate
for a LAN address or a .local name — so the LAN, and the mDNS discovery that
depends on it, goes on working unchanged while TLS covers the hop that leaves
the house.
Both listeners serve the same API, and a session created on one works on the other.
The two ports must differ; the server refuses to start if
OBELO_TLS_LISTEN_ADDR equals OBELO_LISTEN_ADDR.
This is what most households want. You need a domain name whose public DNS points at your house, and one forwarded port.
OBELO_TLS_MODE=acme
OBELO_TLS_DOMAINS=media.example.com
OBELO_ACME_EMAIL=you@example.com # optional; the CA warns you before expiryThe settings are the easy half. The DNS record, the port forward, and the staging-first order of operations are the part that actually goes wrong — follow the full runbook for a first-time setup end to end. The essentials:
curl -4 ifconfig.me # your address as the internet sees itCompare with the WAN address on the router's status page. Different values, or a
WAN address in 100.64.0.0/10, means carrier-grade NAT — no port forward can
work, and you want the Tailscale path instead.
External TCP 443 → 192.168.1.50:8443.
- The external port must be exactly
443. Let's Encrypt validates TLS-ALPN-01 there and nowhere else; it is not configurable. - The internal port is
OBELO_TLS_LISTEN_ADDR(default:8443) — arbitrary, and above 1024 so Obelo needs no privileges. - Nothing needs port 80. The TLS-ALPN-01 challenge completes on the HTTPS port itself; there is no second listener to set up.
- Pin the server's LAN address with a DHCP reservation first. A port forward aimed at an address that moves is the standard way this breaks a month later.
Let's Encrypt production allows only five failed authorizations per hostname per hour, so one wrong port forward costs you the rest of the afternoon.
OBELO_ACME_DIRECTORY=https://acme-staging-v02.api.letsencrypt.org/directoryStaging certificates chain to an untrusted root, so your browser will warn — and that warning is the success signal. Remove the variable to switch to production, which issues a fresh, real certificate.
Issuance is driven by the first HTTPS handshake for a listed name. So go make that handshake happen, from cellular rather than house wifi — plenty of routers will not hairpin a connection from inside back to your own public address.
(This is deliberate: a boot-time attempt races the listener the CA has to dial back into, and would burn one of your five failed authorizations on every restart of a box whose DNS is not pointed yet.)
Every name you want a certificate for goes in it, www. included. Wildcards are
not possible with this challenge type, and there is deliberately no "any name"
setting: without the list, the server would ask the CA for a certificate for
whatever name any stranger's connection asked about, spending your rate limit on
other people's domains while looking perfectly healthy.
CA unreachable, DNS not propagated, port forward not set up yet, rate-limited — Obelo boots anyway, keeps serving plain HTTP on the LAN, logs the reason, and keeps trying. A CA outage is not your mistake, and it should not cost you your media server.
OBELO_DATA_DIR/acme (mode 0700) holds the ACME account key and every issued
private key. If it is wiped on each restart — a container without a volume, or a
tmpfs — Obelo re-issues every time and hits the CA's duplicate-certificate limit
within days.
It is also the most sensitive directory the server owns: anyone who can read
it can impersonate this server to every client in the house. Obelo warns at boot
if the mode is looser than 0700.
Renewal is automatic and needs nothing from you.
A padlock with no warning, and a log line naming the production directory:
obelo: HTTPS certificate ready for "media.example.com" from https://acme-v02.api.letsencrypt.org/directory (…)
That line is logged once per name, on the first successful handshake — grep the boot logs rather than expecting it to repeat. To read the served chain directly:
openssl s_client -connect media.example.com:443 -servername media.example.com </dev/null 2>/dev/null \
| openssl x509 -noout -issuer -subject -datesThe TLS-ALPN-01 challenge has to reach Obelo's own TLS handshake. If something else terminates TLS first, validation fails. Either forward TCP straight through, or let the proxy get the certificate and use Reverse Proxy instead.
Any CA, including your own:
OBELO_TLS_MODE=files
OBELO_TLS_CERT=/etc/letsencrypt/live/example.com/fullchain.pem
OBELO_TLS_KEY=/etc/letsencrypt/live/example.com/privkey.pemBoth paths are absolute. In Docker, mount the certificate directory into the container and use the container's paths.
- Renewals are picked up without a restart. The files are re-read when they change, so a certbot renewal takes effect on the next connection. If a renewal leaves a file half-written, the previous certificate keeps serving and the problem is logged rather than taking the listener down.
- A broken certificate stops the boot. Missing, unreadable, or not matching the key — the server refuses to start and says which path is wrong.
That last point is the opposite of acme's behaviour, on purpose: a wrong
path is a typo you can fix in ten seconds, and starting anyway would leave you
on plain HTTP believing you had TLS. A CA being down is nobody's typo.
For generating your own certificate and making clients trust it, see the self-signed runbook.
Getting started
Reference
Going further
Plugins
Sharing with another household
Reaching it from away
When it breaks