← Start of tutorial

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.

Ubuntu 26.10Reviewed against official documentation ·

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
13

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.

Bash

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'
How do I know it worked?

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.

yaml · /etc/traefik-academy/traefik.yml · certificatesResolvers
certificatesResolvers:
  le:
    acme:
      caServer: "https://acme-v02.api.letsencrypt.org/directory"
      storage: "/var/lib/traefik-academy/acme-production.json"
      httpChallenge:
        entryPoint: web
14

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.

Bash

Dedicated Linux host

sudo systemctl restart traefik-academy.service
sudo journalctl -u traefik-academy.service --since '5 minutes ago' --no-pager
How do I know it worked?

Proxy active, production issuance has no error; continue with the independent client checks.

15

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.

Bash

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'
How do I know it worked?

Trusted marker response, zero certificate verification error, HTTP/2 negotiated on a capable client.

16

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.

Bash

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'
How do I know it worked?

Capable client receives the exact marker with HTTP version 3; trusted TCP request still succeeds.

17

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.

Bash

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
How do I know it worked?

Tunnel listens only on local loopback; dashboard route and app@file show enabled.

Explore all tutorials ↗