October DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsClean PCRecommendedOne scan can reveal what keeps slowing WindowsLook for cleanup and repair opportunities.Run ScanOctober DealsAmazon USDeal season is back - check today's better picksAmazon US: current deals, useful picks and tech finds.See Picks×
Skip to content
VGSources
Blog

WordPress with Traefik and Docker Compose: Complete HTTPS Setup

A complete, production-minded guide to running WordPress behind Traefik with Docker Compose: DNS and ports, ACME challenge selection, persistent certificates, router labels, HTTP redirects, and fixes for 404s or default certificates.
Length16 min Posted Quest giverVGSources Team

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Put Traefik in front of WordPress, keep WordPress on a private Docker network, and let Traefik obtain and renew the certificate from Let’s Encrypt. The reliable pattern is: point your hostname’s DNS record at the Docker host, publish Traefik on port 443 (and port 80 when you use HTTP-01 or an HTTP-to-HTTPS redirect), enable the Docker provider with automatic exposure disabled, and add an explicit HTTPS router to the WordPress container.

This guide builds that arrangement with Docker Compose, explains when to choose TLS-ALPN-01 or HTTP-01, shows a complete Compose file, and gives a test-and-troubleshoot procedure for 404 responses, default certificates, and failed ACME validation.

As an Amazon Associate I earn from qualifying purchases.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

How the finished setup works

A browser requests https://example.com. Public DNS sends that name to your server’s public IP address. Traefik is the only service listening on the public web ports, terminates TLS, selects the router whose Host rule matches example.com, and forwards the request over Docker’s private network to WordPress on its HTTP port.

WordPress does not need a public port mapping. Its container is reachable by Traefik through a shared Docker network, while the database is placed on a separate internal network. Traefik stores the ACME account and certificate data in /letsencrypt/acme.json, so a container recreation does not discard the certificate.

The request path has several independent parts, and each must be correct: DNS must identify the right machine; the firewall and any upstream router must forward the challenge and HTTPS ports; Traefik must discover the container through Docker; the router must match the hostname and entrypoint; and the selected ACME challenge must be able to complete. Checking these layers in that order is faster than changing labels at random.

Prerequisites and DNS checks

Before starting Compose, confirm every item below:

  • A public server with Docker Engine and Docker Compose installed.
  • A DNS A (and, if you use IPv6, AAAA) record for the exact WordPress hostname, such as example.com, pointing to that server.
  • Firewall, cloud security-group, and upstream-router rules that allow the ACME challenge port and HTTPS traffic.
  • Port 443 reaching Traefik directly for TLS-ALPN-01, or port 80 reaching Traefik for HTTP-01. Publish port 80 as well if you plan to redirect ordinary HTTP requests to HTTPS.
  • A mailbox address for Let’s Encrypt account notifications.
  • A directory where the Compose project and its persistent volumes can be backed up.

Check DNS from a network outside your server’s LAN. The result must be the public address of the Docker host, not a private address such as 192.168.x.x or 10.x.x.x. ACME validation cannot reach a hostname that resolves only inside your home or office network.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Check every address family you publish. If an AAAA record points to an IPv6 host where port 80 or 443 is blocked, a validator may try that address and fail even though the A record works. Remove an incorrect AAAA record or make the IPv6 route reach the same Traefik instance. Also verify that a cloud load balancer or home-router NAT rule is forwarding the selected port to this host rather than to an older web server.

Use the exact hostname in all three places: the DNS record, the browser URL, and the Traefik Host rule. A request for www.example.com will not match a router written only for example.com unless you add a second rule or redirect deliberately.

Choose the ACME challenge

Traefik supports two practical HTTP-based challenges for this deployment. Select one before writing the resolver flags.

Challenge Public port required Best fit Important constraint
TLS-ALPN-01 443 The server can send HTTPS directly to Traefik and port 80 is unavailable or unnecessary. Port 443 must reach Traefik without another TLS terminator intercepting the connection.
HTTP-01 80 (and normally 443 for the site) Port 80 is available and you want the conventional HTTP challenge path. The web entrypoint must be public; load balancers and redirects must allow /.well-known/acme-challenge/ to be served.

The choice is primarily about reachability, not WordPress. A firewall that permits only 443 favors TLS-ALPN-01. A front-end that already exposes port 80 and forwards ordinary HTTP favors HTTP-01. If a separate proxy terminates TLS on 443 and cannot pass the TLS-ALPN negotiation to Traefik, HTTP-01 is the practical option. Conversely, if another service permanently owns port 80, TLS-ALPN-01 avoids that conflict.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

When TLS-ALPN-01 is the simpler choice

Use TLS-ALPN-01 when a request to port 443 can arrive at Traefik unchanged. Enable --certificatesresolvers.myresolver.acme.tlschallenge=true and bind a websecure entrypoint to :443. A separate web entrypoint is optional unless you also want HTTP redirects.

When HTTP-01 is appropriate

Use HTTP-01 when port 80 is the port your firewall or load balancer can reliably expose. Enable --certificatesresolvers.myresolver.acme.httpchallenge=true, set --certificatesresolvers.myresolver.acme.httpchallenge.entrypoint=web, and publish the web entrypoint on :80. Do not send the challenge path to WordPress or another backend.

Do not enable a challenge merely because its option appears in an old example. Use one resolver configuration that matches the ports actually reachable from the public internet, and test that path externally. Internal DNS, split-horizon DNS, or a local hosts-file override can make the site appear healthy to you while the public validator sees a different machine.

Create the project and protect certificate storage

Make a project directory, then create the certificate directory before the first start:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
mkdir -p wordpress-traefik/letsencrypt
cd wordpress-traefik
touch letsencrypt/acme.json
chmod 600 letsencrypt/acme.json

Traefik must be able to write the file, and its permissions should prevent other users from reading private key material. Back up acme.json with the rest of the deployment, but treat that backup as sensitive. If the file is lost, Traefik may request new certificates and eventually encounter Let’s Encrypt rate limits.

The bind mount and the storage option must refer to the same location: the host directory ./letsencrypt is mounted as /letsencrypt, and Traefik writes to /letsencrypt/acme.json. A typo in either side creates a new empty file inside the container, making certificates appear to vanish after recreation. Keep the file on durable storage and include it in backup and restore tests.

Create a .env file and keep it out of public source control:

[email protected]
WORDPRESS_DB_NAME=wordpress
WORDPRESS_DB_USER=wordpress
WORDPRESS_DB_PASSWORD=replace-with-a-long-random-password
MARIADB_ROOT_PASSWORD=replace-with-a-different-long-random-password

Use different values for the WordPress database user and the MariaDB root account. Protect the .env file with the same care as the Compose project because it contains credentials.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Complete Docker Compose example using TLS-ALPN-01

The following example uses the current Traefik v3.7 image pattern, a read-only Docker socket, an explicit Docker network, and a WordPress router that listens only on HTTPS. The database has no published host port.

services:
  traefik:
    image: traefik:v3.7
    restart: unless-stopped
    command:
      - --providers.docker=true
      - --providers.docker.exposedbydefault=false
      - --entrypoints.web.address=:80
      - --entrypoints.websecure.address=:443
      - --certificatesresolvers.myresolver.acme.email=${ACME_EMAIL}
      - --certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json
      - --certificatesresolvers.myresolver.acme.tlschallenge=true
    ports:
      - '80:80'
      - '443:443'
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./letsencrypt:/letsencrypt
    networks:
      - proxy

  wordpress:
    image: wordpress:latest
    restart: unless-stopped
    environment:
      WORDPRESS_DB_HOST: db:3306
      WORDPRESS_DB_NAME: ${WORDPRESS_DB_NAME}
      WORDPRESS_DB_USER: ${WORDPRESS_DB_USER}
      WORDPRESS_DB_PASSWORD: ${WORDPRESS_DB_PASSWORD}
    volumes:
      - wordpress_data:/var/www/html
    labels:
      - traefik.enable=true
      - traefik.http.routers.wordpress.rule=Host(`example.com`)
      - traefik.http.routers.wordpress.entrypoints=websecure
      - traefik.http.routers.wordpress.tls=true
      - traefik.http.routers.wordpress.tls.certresolver=myresolver
      - traefik.http.services.wordpress.loadbalancer.server.port=80
    networks:
      - proxy
      - backend

  db:
    image: mariadb:11
    restart: unless-stopped
    environment:
      MARIADB_DATABASE: ${WORDPRESS_DB_NAME}
      MARIADB_USER: ${WORDPRESS_DB_USER}
      MARIADB_PASSWORD: ${WORDPRESS_DB_PASSWORD}
      MARIADB_ROOT_PASSWORD: ${MARIADB_ROOT_PASSWORD}
    volumes:
      - db_data:/var/lib/mysql
    networks:
      - backend

volumes:
  wordpress_data:
  db_data:

networks:
  proxy:
  backend:

Replace example.com in the Host rule with the real hostname. The backticks are part of Traefik’s rule syntax. Pin WordPress and MariaDB to versions you have tested instead of relying indefinitely on floating latest tags; the Traefik image and option names must also match the installed major version.

Compose creates the named networks and volumes on the first start. If you use an existing external network instead, declare it explicitly and ensure both services are attached to the same network name. Traefik cannot route to a container that is attached only to the database network.

What each Traefik label does

  • traefik.enable=true opts this container into Traefik. Because automatic exposure is disabled globally, containers without this label remain private.
  • traefik.http.routers.wordpress.rule=Host(...) limits the router to the requested DNS name. A typo or a request made with a different Host header will not match.
  • entrypoints=websecure binds the router to port 443.
  • tls=true tells Traefik that this router handles HTTPS. An HTTPS router should explicitly contain a TLS field.
  • tls.certresolver=myresolver connects the router to the ACME resolver defined on the Traefik command line.
  • loadbalancer.server.port=80 is the port Traefik uses inside the WordPress container. It is not a public host port.

Both containers must share the proxy network so Traefik can resolve the WordPress service. The database only needs the backend network, which prevents direct proxy access.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

If the image listens on a different internal port, change the load-balancer port label to that listening port. The host-side ports section is intentionally absent from WordPress; adding one would bypass the reverse proxy and expose an unencrypted application endpoint.

Start safely with Let’s Encrypt staging

Production ACME requests are rate-limited. Validate routing with the staging certificate authority first.

  1. Temporarily add --certificatesresolvers.myresolver.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory to the Traefik command list.
  2. Start the stack and watch the logs:
    docker compose up -d
    docker compose logs -f traefik
  3. Wait for Traefik to report a successful certificate request. A staging certificate is issued by “Fake LE Intermediate X1”; browsers will warn because it is not trusted. That warning is expected during this test.
  4. Check that DNS, the Host rule, and the network are correct before switching to production.
  5. Stop the stack, remove the staging caserver line, delete the staging letsencrypt/acme.json, recreate an empty file with mode 600, and start again:
docker compose down
touch letsencrypt/acme.json
chmod 600 letsencrypt/acme.json
docker compose up -d

Deleting the staging file matters: certificates issued by the staging authority are not trusted for normal visitors, and retaining the staging account state can make the production transition confusing.

Do not judge the staging test by the browser warning alone. Confirm that Traefik selected the requested hostname and completed the challenge in its logs. Once the production certificate is issued, keep the same persistent storage and resolver name so automatic renewal can continue.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Use HTTP-01 instead

For HTTP-01, replace the TLS challenge flag with these resolver options:

- --certificatesresolvers.myresolver.acme.httpchallenge=true
- --certificatesresolvers.myresolver.acme.httpchallenge.entrypoint=web

Keep --entrypoints.web.address=:80 and the 80:80 port mapping. The WordPress router can remain on websecure; the challenge is handled by Traefik before normal application routing. If a separate load balancer, CDN, or firewall sits in front of Traefik, ensure it forwards the challenge request to this host rather than answering it itself.

Use TLS-ALPN-01 instead if another service already occupies port 80 and cannot be reconfigured. Conversely, use HTTP-01 if port 443 is terminated elsewhere and cannot pass the TLS-ALPN negotiation directly to Traefik.

HTTP-01 requires the public validator to reach the web entrypoint, even when visitors ultimately use only HTTPS. Test port 80 from outside the server’s network and inspect any load-balancer rule that might send the request to a different backend.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Redirect ordinary HTTP traffic to HTTPS

After certificate issuance works, redirect normal HTTP requests. Add a redirect middleware and a catch-all HTTP router to the Traefik service labels:

      - traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https
      - traefik.http.routers.http-catchall.rule=HostRegexp(`{host:.+}`)
      - traefik.http.routers.http-catchall.entrypoints=web
      - traefik.http.routers.http-catchall.middlewares=redirect-to-https

Keep ACME validation in mind when using HTTP-01: the /.well-known/acme-challenge/ path must remain reachable in the way the challenge flow requires. If issuance fails after adding the redirect, remove the redirect temporarily, confirm the certificate, and then reintroduce it with your front-end firewall or load balancer configured to pass the challenge path.

Apply the redirect only to the ordinary HTTP router. The secure WordPress router remains on websecure and continues to use the certificate resolver. A redirect cannot compensate for a DNS record or firewall rule that points port 80 at the wrong machine.

Bring WordPress online and verify the HTTPS view

  1. Confirm that docker compose ps shows Traefik, WordPress, and the database as running.
  2. Read Traefik’s generated configuration and logs for router or provider errors:
    docker compose logs traefik
    docker compose logs wordpress
  3. From an external network, test DNS and the TLS handshake:
    curl -I https://example.com
    curl -I http://example.com
  4. Open https://example.com and complete the WordPress installer. Use the HTTPS URL when WordPress asks for the site address.
  5. In the WordPress administration screens, verify that both the WordPress Address and Site Address use https://example.com. Changing these values from HTTP to HTTPS after the site is already populated can require search-and-replace work for old absolute URLs.

Run the curl checks from a network that does not use your internal DNS override. The HTTPS response should present the certificate for the requested hostname, and the HTTP response should either be handled by the HTTP router or return the redirect you configured. If the two commands reach different machines, fix DNS or upstream routing before changing WordPress.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

If WordPress generates redirect loops or believes the request is HTTP, configure it to trust the proxy’s forwarded scheme. A common wp-config.php addition is:

if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
    $_SERVER['HTTPS'] = 'on';
}

Apply this only when Traefik is the trusted proxy for the site; do not accept arbitrary client-supplied forwarding headers on a deployment where untrusted traffic can bypass Traefik.

Troubleshoot the common failures

Symptom Likely cause Checks and corrective action
Traefik returns 404 The request did not match a router. Confirm the browser’s hostname exactly matches the Host rule, the router uses websecure, and the request arrived on the published 443 entrypoint. Verify that WordPress and Traefik share a Docker network.
A default certificate appears The intended router or resolver was not selected, the hostname is not covered, or ACME issuance did not complete. Inspect Traefik logs, check the resolver label spelling, verify the DNS record and public port, and confirm that the certificate state persisted in acme.json. A successful TLS handshake alone does not prove the requested hostname has a valid certificate.
ACME timeout or connection refused Port 80 or 443 is blocked, mapped to another service, or directed to the wrong machine. Test from an external network, inspect cloud security groups and upstream NAT rules, and verify that DNS resolves to this host.
HTTP-01 validation fails after redirecting The redirect or front-end proxy prevents the ACME challenge path from reaching Traefik. Temporarily remove the redirect, confirm that /.well-known/acme-challenge/ reaches Traefik, then restore the redirect while preserving that path.
Traefik cannot find WordPress The Docker provider is disabled, the container was not explicitly enabled, or the networks differ. Check --providers.docker=true, traefik.enable=true, and the Compose network names. The service port label must be the container’s listening port, normally 80 for the Apache WordPress image.
Certificate disappears after recreation The ACME file was not mounted or was not writable. Verify the bind mount ./letsencrypt:/letsencrypt, the storage path /letsencrypt/acme.json, and file mode 600. Ensure the host directory is included in backups.
WordPress redirects between HTTP and HTTPS WordPress does not recognize the forwarded HTTPS scheme or its stored site URLs are inconsistent. Set both WordPress URLs to HTTPS and, if necessary, add the guarded X-Forwarded-Proto handling shown above.

When diagnosing a 404, first determine whether it is Traefik’s response or a WordPress response. A Traefik 404 usually indicates that no router matched the Host and entrypoint; a WordPress 404 means routing succeeded and the application handled the request. This distinction prevents unnecessary database or permalink changes.

For a default certificate, inspect the hostname shown by the browser and compare it with the Host rule character for character. Then check that the resolver label name is identical to the resolver configured on the command line. Finally, verify that the ACME storage file survived restarts and that the selected challenge port is reachable externally.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Operational and security checklist

  • Keep providers.docker.exposedbydefault=false; explicitly enable only services that should be public.
  • Mount the Docker socket read-only. Access to the socket is powerful, so restrict host access to the Traefik container and trusted administrators.
  • Do not publish WordPress or MariaDB ports directly to the internet. Expose only Traefik’s required ports.
  • Use strong, distinct database passwords and store them outside the Compose file through protected environment handling.
  • Back up WordPress content, the database, and acme.json; test that each backup can be restored.
  • Review Traefik and WordPress logs after upgrades. A changed image major version can alter option names or defaults.
  • Renewal is automatic while Traefik can reach the ACME service and the hostname remains publicly valid. Monitor logs so a DNS or firewall change is found before the existing certificate expires.

Read-only socket access reduces accidental writes but does not make Docker-socket access harmless; anyone who can control the Traefik container may gain powerful visibility into the Docker host. Limit who can edit Compose files, protect the host credentials, and avoid exposing Traefik’s administrative interfaces publicly.

Back up three different kinds of state: WordPress files and uploads, the MariaDB data volume, and the ACME file. Restoring only the database does not restore themes or media, while restoring only WordPress files does not restore posts. The certificate file is separate again and should be handled as sensitive key material.

Best Value
Docker Container Linux Devops Programming Coding T-Shirt
  • Docker, Docker Swarm, Docker Compose, Programmer, Developer, Coding, Programming, Software Engineer, Code, DevOps, Deploy, Deployment, Kubernetes, Salt, Puppet, Chef, Terraform, Container, AWS, Azure, Cloud, Geek, Funny, Computer, Software, Tech, IT
  • Integration, Scrum, Compile, Compilation, Science, Bug, Debug, Python, Linux, Java, Javascript, Scala, Dotnet, Kotlin
  • Lightweight, Classic fit, Double-needle sleeve and bottom hem

Version differences to watch

Traefik v3 examples commonly use the traefik:v3.7 image and the command-line options shown here. Older v2 tutorials may use an older image, different defaults, or labels copied from a different Compose layout. Do not mix snippets blindly: check the documentation for the major version you actually run, especially the entrypoint names, ACME flags, and Docker provider settings.

The stable design does not depend on a particular WordPress release: Traefik routes to the container’s internal HTTP port, while WordPress and the database retain their data in named volumes. Pin image versions, rehearse upgrades on a staging hostname, and keep the router labels unchanged unless your hostname or network design changes.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

When upgrading Traefik, review the image tag and every command-line option together. A configuration copied from a v2 article may still look plausible while using assumptions that do not match v3. Upgrade one component at a time, watch the logs for provider or ACME errors, and retain a known-good Compose file so you can roll back without losing persistent volumes.

Frequently Asked Questions

How do I put WordPress behind Traefik with Docker Compose?

Run Traefik as the only service publishing ports 80 and 443, attach Traefik and WordPress to a shared proxy network, disable automatic Docker exposure, and add an explicit WordPress router with a Host rule, the websecure entrypoint, tls=true, a certificate resolver, and the container’s internal port 80.

How do I get a Let’s Encrypt certificate for WordPress?

Point the WordPress hostname’s public DNS record to the Docker host, make the selected ACME challenge port reachable, configure an email address and persistent /letsencrypt/acme.json storage, then reference the resolver from the WordPress router label.

Should I use HTTP-01 or TLS-ALPN-01?

Use TLS-ALPN-01 when port 443 reaches Traefik directly and another service does not terminate TLS first. Use HTTP-01 when port 80 is available and forwarded to Traefik’s web entrypoint. Choose based on firewall, load-balancer, and port ownership constraints.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Why does Traefik return a 404?

The request usually did not match a router. Check that the requested hostname exactly matches the Host rule, that the router uses the published entrypoint, and that the request reached Traefik on the expected port. Also verify the Docker provider and shared network.

Why am I seeing Traefik’s default certificate?

The intended router or resolver may not have been selected, the hostname may not be covered, or ACME issuance may have failed. Inspect Traefik logs, verify DNS and public ports, check the resolver label spelling, and confirm that acme.json is mounted and writable.

Do I need to publish a WordPress port?

No. WordPress should be reachable through the shared Docker network only. The label traefik.http.services.wordpress.loadbalancer.server.port=80 tells Traefik which internal container port to use; publishing a host port can bypass the proxy.

How do I test without hitting Let’s Encrypt production limits?

Set the resolver’s acme.caserver to the Let’s Encrypt staging directory, verify routing and challenge completion, then remove that setting, replace the staging acme.json with a new mode-600 file, and restart to request a trusted production certificate.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

What must be backed up?

Back up the WordPress volume, the MariaDB data volume, and letsencrypt/acme.json. Protect the ACME backup because it contains private key material, and test that your backups can actually be restored.

The Bottom Line

Use Traefik as the public HTTPS entry point, keep WordPress and MariaDB on private Docker networks, and expose only the services you explicitly enable. Correct DNS and public port reachability come first; then configure one ACME challenge, persist acme.json, and attach an HTTPS Host router to WordPress. Test with Let’s Encrypt staging, preserve the HTTP-01 challenge path when redirecting, and use logs plus external checks to resolve 404s, default certificates, and renewal failures.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More quests from Patch Notes

  1. How to Set Up a RedM (RDR2) Server in 2026: License Key, txAdmin and server.cfg, Step by StepBlog11min
  2. Best RedM (RDR2) Server Hosting in 2026: Comparing Four Hosts on Slots, Memory and PriceBlog10min
  3. How to Host a Mindustry Server in 2026: server-release.jar, Port 6567 and the Commands That MatterBlog7min
Recommended PC Tool
Recommended PC Tool
PC Slower Than It Used to Be?Free scan - under a minute
Crashes, No Sound, or Screen Glitches?Free driver scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.