Documentation

Last updated: 2026-07-28

Public hosting: DNS vhosts and ACME

This page covers reaching one or more image instances from the public internet: how a DNS hostname routes to an instance, and how Everlock issues and renews a TLS certificate for it automatically. It builds on running multiple instances — the same vhost mechanism, now pointed at real domains.

The model in one paragraph

You map a public hostname to an image instance as a vhost. You point that hostname at your server in DNS. When the HTTP frontend has an HTTPS listener configured, it notices the vhost is a public name and requests a Let's Encrypt certificate for it over the http-01 challenge — no certbot, no nginx, no per-host setup. The same machinery already documented for publishing a site over HTTPS applies unchanged to image instances.

Prerequisites

  • an Everlock instance reachable from the internet on ports 80 and 443;
  • a domain name with a DNS A (and optionally AAAA) record pointing at the server's public IP;
  • the image instance already created, with the public hostname as one of its vhosts.

The hostname must resolve to your server before the first request, because ACME validation hits http://<host>/.well-known/acme-challenge/... on port 80.

Step 1 — Configure the HTTP frontend for HTTPS

The HTTP frontend reads config/frontend-http.toml. Enabling an HTTPS listener and an ACME contact email is what turns on certificate issuance:

listen_http  = "0.0.0.0:80"
listen_https = "0.0.0.0:443"
acme_email   = "ops@example.net"
redirect_http_to_https = true

The contact email is optional — without it the ACME account is created without a contact (/server settings set acme.email sets it at runtime). This config is shared across every HTTP backend — sites, OCI, and image instances all issue certificates through it.

Step 2 — Point the vhost at a real domain

Give the instance a public vhost, either in config/image-http.toml:

[instances.work]
store = "work-images"
vhosts = ["portfolio.example.com"]

or from the admin console (hot, no restart):

/image set work vhost=portfolio.example.com

Then create the matching DNS record so the name resolves to your server's public IP. If Everlock is also your authoritative DNS server, the vhost is published as a synthesised A/AAAA record automatically; otherwise add the record at your DNS provider.

Step 3 — Restart if you changed the frontend file

Editing frontend-http.toml requires a process restart to bind the new listeners. Adding the vhost itself does not. On startup Everlock will:

  1. bind the HTTP listener on port 80;
  2. bind the HTTPS listener on port 443;
  3. detect which vhosts are public hostnames (not localhost, *.local, or raw IPs);
  4. request a certificate for each public hostname;
  5. serve HTTPS for the instance as soon as the certificate is issued.
frontend-http: issuing or renewing certificate for portfolio.example.com
frontend-http: certificate persisted for portfolio.example.com
HTTPS server listening on https://0.0.0.0:443

How ACME works here

Everlock uses the http-01 challenge: Let's Encrypt requests http://<host>/.well-known/acme-challenge/<token> and Everlock answers it on the HTTP listener. Certificates and keys are written into the system store under:

config/<host>/fullchain.pem
config/<host>/privkey.pem

Renewal is automatic — Everlock checks expiry at startup and renews within acme_renew_before_days (default 30). For staging/testing against Let's Encrypt's rate-limited CA, point acme_directory at the staging endpoint; see the HTTPS guide.

public_url and the advertised base

The embedded engine advertises an absolute base URL to clients (used in API responses and share links). By default it is derived as https://<first-vhost>, which is correct for the common public case. Override public_url only when the scheme or port differs — for example if Everlock sits behind a separate load balancer that terminates TLS.

[instances.work]
store = "work-images"
vhosts = ["portfolio.example.com"]
public_url = "https://portfolio.example.com"

Multiple public domains, one or many instances

Each public vhost gets its own certificate, issued and renewed independently. That gives you two composable patterns:

  • Several names for one instance — give a single instance multiple public vhosts (e.g. photos.example.net and gallery.example.net); both resolve to the same library, each with its own certificate.
  • Several instances on different domains — run distinct instances, each on its own domain, from one process. Routing by Host keeps them isolated; see multiple instances.

Hosting from a home / NAT line

A residential line can serve a public image instance, but the server only sees a private RFC 1918 address on its interface, so the naive "publish the interface IP" approach publishes a useless address. Everlock's DNS backend solves this with address_mode = discover, which probes public resolvers hourly and publishes your real public IPv4. See DNS address modes and the NAT root-domain walkthrough.

Two operational caveats for this topology:

  • ports 80 and 443 must be forwarded from the router to Everlock, and the ISP must not block them;
  • the parent zone's glue (ns1/ns2) at your registrar still has to learn the IP — Everlock detects the change but does not push it to the registrar yet. If you want to avoid touching the registrar on every IP change, the primary-at-home + VPS-secondary setup hides the home IP entirely.

If a public certificate is more trouble than it's worth for a home-only gallery, skip DNS and ACME altogether and use mDNS on the LAN instead.

images dns acme tls https vhost