YunoHost and Let's Encrypt: When to Rely on Automatic Certificates for Your Apps
YunoHost can issue and renew Let's Encrypt certificates per app automatically — if DNS, port 80, and domain declarations line up. A decision guide with concrete validation steps.
05 May 2026, 18:21 UTC

If you self-host apps on YunoHost, the TLS question usually resolves itself: the platform can request and renew Let's Encrypt certificates for every installed web app with almost no intervention. But the automation only works under specific conditions — your domain must resolve publicly, port 80 must be reachable, and the app must declare its domain correctly. This guide helps you decide when the built-in integration is the right choice, when you need a different approach, and how to verify that certificates are actually being issued and renewed.
The decision and its constraints
The core decision is whether to let YunoHost manage certificates per app, or to handle TLS yourself (for example with a wildcard certificate, an internal CA, or a reverse proxy in front of the server). The built-in path is the default and is appropriate for most single-server setups exposed to the internet.
The constraints that matter:
- Public DNS: Let's Encrypt's HTTP-01 challenge requires your domain (or subdomain) to resolve to your server's public IP. Split-horizon DNS or LAN-only names will fail validation.
- Port 80 reachability: The challenge is served over plain HTTP. If your ISP blocks port 80, or a firewall drops it, issuance fails even if HTTPS works.
- Domain declared in the app: YunoHost only manages certificates for domains the app actually uses. An app installed without a proper domain falls back to a self-signed certificate, which browsers flag as untrusted.
Comparing the supported options
| Option | How it works | Best for | Main limitation |
|---|---|---|---|
| Automatic Let's Encrypt (default) | YunoHost's certbot hook runs HTTP-01 validation per domain; auto-renews | Public servers with normal DNS and open port 80 | Fails silently if DNS or port 80 breaks |
| Self-signed fallback | Generated when no valid certificate exists | Temporary testing only | Browser warnings; breaks some mobile apps and federation |
| Manually installed certificate | You provide cert/key obtained elsewhere (e.g., DNS-01 wildcard) | Wildcard needs, port 80 blocked, non-public domains | You own renewal; YunoHost won't auto-renew it |
For a typical home or small VPS setup with a domain you control, the automatic option wins on effort: zero recurring maintenance, per-app coverage, and renewal handled by the system's certbot integration. The manual option only makes sense when one of the constraints above genuinely blocks HTTP-01 — most commonly an ISP that filters inbound port 80.
How the automation actually works
When you install an app and assign it a domain, YunoHost records the domain in its configuration and triggers certificate issuance through its certbot hook. Let's Encrypt validates control of the domain by fetching a token over HTTP from a well-known path on your server. On success, the certificate is installed into the nginx vhost for that domain, and a renewal hook reloads the web server after each successful renewal. Renewals run automatically well before expiry, so under normal conditions you never touch the certificate again.
The declarative part is important: the domain-to-app mapping lives in YunoHost's configuration, not in ad-hoc certbot commands. If you later move an app to a different domain through YunoHost's tools, the certificate follows the configuration rather than requiring you to re-run anything by hand.
Concrete validation: checking one app end to end
After installing an app (say, a Nextcloud instance on cloud.example.com), verify three things from a shell on the YunoHost server. These commands require root or sudo.
First, confirm the domain assignment:
sudo yunohost domain listCheck that cloud.example.com appears and is associated with the app you expect. If the domain is missing here, no certificate automation will happen for it — fix the app or domain configuration first.
Second, confirm the certificate exists and is valid:
sudo certbot certificatesLook for an entry whose domains include cloud.example.com, with an expiry date roughly 90 days out from issuance. The web admin UI shows the same status per domain and flags anything self-signed or expiring soon.
Third, test renewal without changing anything:
sudo certbot renew --dry-runA dry run exercises the full HTTP-01 path — including port 80 reachability — without consuming rate limits or replacing live certificates. If the dry run succeeds for your domain, real renewals will almost certainly succeed too. If it fails, the error message usually points directly at the cause: DNS not resolving, connection refused on port 80, or an nginx misconfiguration.
As an external check, visit https://cloud.example.com from a machine outside your network (or use openssl s_client -connect cloud.example.com:443 -servername cloud.example.com) and confirm the issuer is Let's Encrypt and the chain verifies. Testing from inside your LAN can be misleading if you have hairpin NAT or local DNS overrides.
Limitations and failure modes to watch
- Silent renewal failure: If DNS or port 80 breaks after issuance, the certificate keeps working until it nears expiry. Check the admin UI's diagnosis section periodically; it reports certificate and reachability problems.
- Rate limits: Let's Encrypt caps issuance per registered domain. Repeatedly reinstalling apps in a short window can hit the limit; prefer fixing configuration over reinstalling.
- Self-signed fallback is sticky: If an app was installed without a proper domain, adding the domain later requires explicitly requesting the certificate — it does not always happen retroactively. Check the domain's certificate status in the admin UI after any domain change.
- Non-public services: Anything meant to stay LAN-only should not use the automatic flow; a self-signed cert or an internal CA is the honest choice there.
The practical rule: if your server is public, your DNS is standard, and port 80 is open, accept the default automation and spend your verification effort on the certbot renew --dry-run check. Only reach for manual certificates when one of those three conditions fails.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.