WIUNIX ACADEMY
Set up Traefik with Let’s Encrypt and HTTP/3 on Ubuntu and Debian
Page 4 of 6. Review the earlier steps and prerequisites before continuing.
YOUR SYSTEM. YOUR STEPS.
Where are you working?
Choose your OS and version. The prerequisites, commands and troubleshooting follow your environment.
USE YOUR OWN VALUES
Configure this tutorial
Set the example values for your environment; related explanations and copy panels update together. Never enter passwords, private keys or tokens. Values stay in this tab and are not sent to the server or share links. Check actual DNS, certificates and network policy before running commands.
Different IP addresses, domains or ports? Open the settings below, change the values and select “Apply to tutorial”, then copy the updated commands.
Set values for my environment11 editable values
LET’S BUILD
Move to the production CA once staging works
Stop here until DNS, firewall and staging issuance are correct. Back up the staging YAML, then open it with the protected editor. Change exactly caServer to the production URL and storage to the separate production file shown below; keep every other setting, including any approved contact email. Never rename/copy staging account JSON into production or erase an existing production file. Public issuance has rate limits and subscriber terms; this guide does not automate acceptance on your behalf.
Dedicated Linux host
sudo cp -a --no-clobber '/etc/traefik-academy/traefik.yml' '/etc/traefik-academy/traefik-staging.yml.saved'
sudoedit '/etc/traefik-academy/traefik.yml'
Protected editor open; original staging configuration retained.
Production resolver replacement only
FILE FRAGMENT: replace the complete certificatesResolvers block with this block, not the whole file. Keep the static entrypoints/provider/API/log sections. If you added an approved contact email, retain its email key under acme in this replacement too. Staging and production use separate state files. The standard 90-day duration matches production defaults at this review date; do not assume it remains the CA lifetime forever. Recheck provider/Traefik renewal guidance when certificate profiles or lifetimes change.
certificatesResolvers:
le:
acme:
caServer: "https://acme-v02.api.letsencrypt.org/directory"
storage: "/var/lib/traefik-academy/acme-production.json"
httpChallenge:
entryPoint: web
LET’S BUILD
Require trusted TLS and the exact receiver
Restart only this proxy after the static edit. From the external client run the TLS and HTTP checks after issuance finishes; do not interpret a transient default certificate as success. The TLS verification must pass with normal system roots and hostname validation. Record the real issuer/expiry privately for monitoring. No --insecure is used from this point onward.
Dedicated Linux host
sudo systemctl restart traefik-academy.service
sudo journalctl -u traefik-academy.service --since '5 minutes ago' --no-pager
Proxy active, production issuance has no error; continue with the independent client checks.
LET’S BUILD
Independent trusted-certificate checks
Run on a Linux client with current CA roots. Require exact marker text and Verify return code: 0 (ok), correct hostname/SAN and production issuer. A 200 response with a bypassed trust check is insufficient. If your client has no HTTP/2 support, use the basic trusted request first and a capable client for protocol verification.
Independent external Linux client
curl --fail --silent --show-error --noproxy '*' 'https://app.example.com/health.txt'
openssl s_client -connect 'app.example.com:443' -servername 'app.example.com' -verify_hostname 'app.example.com' -verify_return_error </dev/null
curl --version
curl --http2 --fail --silent --show-error --noproxy '*' --output /dev/null --write-out 'HTTP version: %{http_version}\n' 'https://app.example.com/health.txt'
Trusted marker response, zero certificate verification error, HTTP/2 negotiated on a capable client.
LET’S BUILD
Prove HTTP/3 rather than only Alt-Svc
HTTP/3 requires a client with HTTP3 in curl’s Features output and an end-to-end UDP/443 path. The stock curl of a selected OS may lack that feature; no unsupported package replacement is required here. Use an existing approved HTTP/3-capable client or browser network inspector reporting h3. Alt-Svc only advertises availability and is not proof a QUIC request succeeded. --http3-only forbids an unnoticed fallback; the final request separately verifies the TCP path. Do not disable certificate validation to make it work.
Independent HTTP/3-capable client
curl --version
curl --silent --show-error --head --noproxy '*' 'https://app.example.com/health.txt'
curl --http3-only --fail --silent --show-error --noproxy '*' --write-out '
HTTP version: %{http_version}
' 'https://app.example.com/health.txt'
curl --http1.1 --fail --silent --show-error --noproxy '*' 'https://app.example.com/health.txt'
Capable client receives the exact marker with HTTP version 3; trusted TCP request still succeeds.
LET’S BUILD
Use the dashboard through an SSH tunnel
Run the tunnel on your own workstation using your existing verified SSH identity and host key. It binds only local 127.0.0.1:8080; choose a free local port, or update the admin-port setting consistently. Keep the terminal open, then visit the local dashboard URL including its trailing slash in your browser. The API is available only to this host and authorized tunnel users; other local users/processes on the server can also reach loopback, so the host itself must be trusted. Do not publish this endpoint or enable api.insecure.
Your workstation terminal and browser
ssh -p 22 -N -o ExitOnForwardFailure=yes -L 127.0.0.1:8080:127.0.0.1:8080 admin@203.0.113.10
Tunnel listens only on local loopback; dashboard route and app@file show enabled.