Skip to content
Brandon Johnson edited this page Sep 7, 2026 · 4 revisions

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.


HTTPS is an addition, never a replacement

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.


acme — Obelo gets a certificate for you

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 expiry

The 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:

Before you start: check you are not behind CGNAT

curl -4 ifconfig.me     # your address as the internet sees it

Compare 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.

Only one port has to be forwarded

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.

Set it up against staging first

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/directory

Staging 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.

Nothing is fetched at boot

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.)

OBELO_TLS_DOMAINS is required, and exact

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.

A certificate that cannot be obtained does not stop the server

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.

Keep the data directory

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.

Verifying it took

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 -dates

Do not put a reverse proxy in front of the TLS port in acme mode

The 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.


files — you supply the certificate

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.pem

Both 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.

Obelo

Home

Getting started

Reference

Going further

Plugins

Sharing with another household

Reaching it from away

When it breaks

Clone this wiki locally