Use domain and not subdomain with docker/traefik to publish an apache webserver to the internet

New here and first time posting.

I am struggling to publish an apache website in docker to the internet when using the main domain name "example.com", every time I try I get 404 page not found. When using anything before the "example.com" it works for example "abc.example.com" will work but.

I am using Cloudflare to get wildcard certificates.

traefik/portainer docker-compose.yml

version: '3'

services:
  traefik:
    image: traefik:latest
    container_name: traefik
    restart: unless-stopped
    security_opt:
      - no-new-privileges:true
    networks:
      - proxy
    ports:
      - 80:80
      - 443:443
    environment:
      - CF_API_EMAIL="API_EMAIL"
      - CF_DNS_API_TOKEN="API_TOKEN"      
     # be sure to use the correct one depending on if you are using a token or key
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - /root/docker/traefik/data/traefik.yml:/traefik.yml:ro
      - /root/docker/traefik/data/acme.json:/acme.json
      - /root/docker/traefik/data/config.yml:/config.yml:ro
      - /root/docker/traefik/logs:/var/log
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.traefik.entrypoints=http"
      - "traefik.http.routers.traefik.rule=Host(`traefik-dashboard.example.com`)"
      - "traefik.http.middlewares.traefik-auth.basicauth.users=user123:Hash_Password"
      - "traefik.http.middlewares.traefik-https-redirect.redirectscheme.scheme=https"
      - "traefik.http.middlewares.sslheader.headers.customrequestheaders.X-Forwarded-Proto=https"
      - "traefik.http.routers.traefik.middlewares=traefik-https-redirect"
      - "traefik.http.routers.traefik-secure.entrypoints=https"
      - "traefik.http.routers.traefik-secure.rule=Host(`traefik-dashboard.example.com`)"
      - "traefik.http.routers.traefik-secure.middlewares=traefik-auth"
      - "traefik.http.routers.traefik-secure.tls=true"
      - "traefik.http.routers.traefik-secure.tls.certresolver=cloudflare"
      - "traefik.http.routers.traefik-secure.tls.domains[0].main=example.com"
      - "traefik.http.routers.traefik-secure.tls.domains[0].sans=*.example.com"
      - "traefik.http.routers.traefik-secure.service=api@internal"
  portainer:
    image: portainer/portainer-ce
    container_name: portainer
    restart: unless-stopped
    security_opt:
      - no-new-privileges:true
    networks:
      - proxy
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - /home/username/portainer/data:/data
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.portainer.entrypoints=http"
      - "traefik.http.routers.portainer.rule=Host(`portainer.example.com`)"
      - "traefik.http.middlewares.portainer-https-redirect.redirectscheme.scheme=https"
      - "traefik.http.routers.portainer.middlewares=portainer-https-redirect"
      - "traefik.http.routers.portainer-secure.entrypoints=https"
      - "traefik.http.routers.portainer-secure.rule=Host(`portainer.example.com`)"
      - "traefik.http.routers.portainer-secure.tls=true"
      - "traefik.http.routers.portainer-secure.service=portainer"
      - "traefik.http.services.portainer.loadbalancer.server.port=9000"
      - "traefik.docker.network=proxy"

networks:
  proxy:
    external: true

traefik.yml conf file

api:
  dashboard: true
  debug: true
entryPoints:
  http:
    address: ":80"
    http:
      redirections:
        entryPoint:
          to: https
          scheme: https
  https:
    address: ":443"
serversTransport:
  insecureSkipVerify: true
providers:
  docker:
    endpoint: "unix:///var/run/docker.sock"
    exposedByDefault: false
  file:
    filename: /config.yml
certificatesResolvers:
  cloudflare:
    acme:
      email: me@example.com
      storage: acme.json
      dnsChallenge:
        provider: cloudflare
        #disablePropagationCheck: true # uncomment this if you have issues pulling certificates through cloudflare, By setting this flag to true disables the need to wait for the propagation of the TXT record to all authoritative name servers.
        resolvers:
          - "1.1.1.1:53"
          - "1.0.0.1:53"
log:
  filePath: "/var/log/traefik.log"
  level: DEBUG

apache/php/mysql docker-compose.yml

version: '2.1'
services:
  legacy-php:
    hostname: php
    build: ./php
    restart: unless-stopped
    security_opt:
      - no-new-privileges:true
    depends_on:
      - db
    networks:
      - proxy
    volumes:
      - "./php/conf.d/00-ioncube.ini:/usr/local/etc/php/conf.d/00-ioncube.ini"
      - "./php/conf.d/99-custom.ini:/usr/local/etc/php/conf.d/99-custom.ini"
      - "./php/home/.bash_aliases:/root/.bash_aliases"
      - "./php/home/.bash_git:/root/.bash_git"
      - "./php/home/.bash_profile:/root/.bash_profile"
      - "./php/home/.bashrc:/root/.bashrc"
      - "./php/home/.git-completion.bash:/root/.git-completion.bash"
      - "./php/home/.git-prompt.sh:/root/.git-prompt.sh"
      - "./php/home/.vimrc:/root/.vimrc"
      - "./htdocs:/var/www/html"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.nginx.entrypoints=http"
      - "traefik.http.routers.nginx.rule=Host(`example.com`, `www.example.com)"
      - "traefik.http.middlewares.nginx-https-redirect.redirectscheme.scheme=https"
      - "traefik.http.routers.nginx.middlewares=nginx-https-redirect"
      - "traefik.http.routers.nginx-secure.entrypoints=https"
      - "traefik.http.routers.nginx-secure.rule=Host(`example.com`)"
      - "traefik.http.routers.nginx-secure.tls=true"
      - "traefik.http.routers.nginx-secure.service=nginx"
      - "traefik.http.services.nginx.loadbalancer.server.port=80"
      - "traefik.docker.network=proxy"
  db:
    image: mysql:5.6
    restart: unless-stopped
    networks:
      - proxy
    environment:
      MYSQL_ROOT_PASSWORD: toor
      MYSQL_USER: user
      MYSQL_PASSWORD: admin
      MYSQL_DATABASE: database
    volumes:
      - ./mysql/conf.d/custom.cnf:/etc/mysql/conf.d/custom.cnf
      - ./mysql/data:/var/lib/mysql:rw
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql
    ports:
      - "8181:3306"

networks:
  proxy:
    external: true

I think you missed to assign your certresolver either to the static entrypoint or to the dynamic router.

How would I properly assign my certresolver?
The way it is now is I have this line - "traefik.http.routers.traefik-secure.tls.certresolver=cloudflare" in my docker-compose file for traefik.

That’s correct, but just for the router

You also need it for nginx-secure.

I have tried it with this config.
But it didn't work. What am I missing?

version: '2.1'
services:
  legacy-php:
    hostname: php
    build: ./php
    restart: unless-stopped
    security_opt:
      - no-new-privileges:true
    depends_on:
      - db
    networks:
      - proxy
    volumes:
      - "./php/conf.d/00-ioncube.ini:/usr/local/etc/php/conf.d/00-ioncube.ini"
      - "./php/conf.d/99-custom.ini:/usr/local/etc/php/conf.d/99-custom.ini"
      - "./php/home/.bash_aliases:/root/.bash_aliases"
      - "./php/home/.bash_git:/root/.bash_git"
      - "./php/home/.bash_profile:/root/.bash_profile"
      - "./php/home/.bashrc:/root/.bashrc"
      - "./php/home/.git-completion.bash:/root/.git-completion.bash"
      - "./php/home/.git-prompt.sh:/root/.git-prompt.sh"
      - "./php/home/.vimrc:/root/.vimrc"
      - "./htdocs:/var/www/html"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.apache.entrypoints=http"
      - "traefik.http.routers.apache.rule=Host(`example.com`)"
      - "traefik.http.middlewares.apache-https-redirect.redirectscheme.scheme=https"
      - "traefik.http.routers.apache.middlewares=apache-https-redirect"
      - "traefik.http.routers.apache-secure.entrypoints=https"
      - "traefik.http.routers.apache-secure.rule=Host(`example.com`)"
      - "traefik.http.routers.apache-secure.tls=true"
      - "traefik.http.routers.apache-secure.tls.certresolver=cloudflare"
      - "traefik.http.routers.apache-secure.service=apache"
      - "traefik.http.services.apache.loadbalancer.server.port=80"
      - "traefik.docker.network=proxy"
  db:
    image: mysql:5.6
    restart: unless-stopped
    networks:
      - proxy
    environment:
      MYSQL_ROOT_PASSWORD: toor
      MYSQL_USER: user
      MYSQL_PASSWORD: admin
      MYSQL_DATABASE: database
    volumes:
      - ./mysql/conf.d/custom.cnf:/etc/mysql/conf.d/custom.cnf
      - ./mysql/data:/var/lib/mysql:rw
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql
    ports:
      - "8181:3306"

networks:
  proxy:
    external: true

To reduce config, maybe just move it to the global level:

entryPoints:
  http:
    address: ":80"
    http:
      redirections:
        entryPoint:
          to: https
          scheme: https
  https:
    address: ":443"
    http:
      tls:
        certResolver: cloudflare

You also don't need the redirect middleware in labels, as you have it on a global level already.

These are my files
apache/mysql docker-compose.yaml

version: '2.1'
services:
  legacy-php:
    hostname: php
    build: ./php
    restart: unless-stopped
    security_opt:
      - no-new-privileges:true
    depends_on:
      - db
    networks:
      - proxy
    volumes:
      - "./php/conf.d/00-ioncube.ini:/usr/local/etc/php/conf.d/00-ioncube.ini"
      - "./php/conf.d/99-custom.ini:/usr/local/etc/php/conf.d/99-custom.ini"
      - "./php/home/.bash_aliases:/root/.bash_aliases"
      - "./php/home/.bash_git:/root/.bash_git"
      - "./php/home/.bash_profile:/root/.bash_profile"
      - "./php/home/.bashrc:/root/.bashrc"
      - "./php/home/.git-completion.bash:/root/.git-completion.bash"
      - "./php/home/.git-prompt.sh:/root/.git-prompt.sh"
      - "./php/home/.vimrc:/root/.vimrc"
      - "./htdocs:/var/www/html"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.apache.entrypoints=http"
      - "traefik.http.routers.apache.rule=Host(`example.com`)"
      - "traefik.http.routers.apache-secure.entrypoints=https"
      - "traefik.http.routers.apache-secure.rule=Host(`example.com`)"
      - "traefik.http.routers.apache-secure.tls=true"
      - "traefik.http.routers.apache-secure.service=apache"
      - "traefik.http.services.apache.loadbalancer.server.port=80"
      - "traefik.docker.network=proxy"
  db:
    image: mysql:5.6
    restart: unless-stopped
    networks:
      - proxy
    environment:
      MYSQL_ROOT_PASSWORD: toor
      MYSQL_USER: user
      MYSQL_PASSWORD: admin
      MYSQL_DATABASE: database
    volumes:
      - ./mysql/conf.d/custom.cnf:/etc/mysql/conf.d/custom.cnf
      - ./mysql/data:/var/lib/mysql:rw
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql
    ports:
      - "8181:3306"

networks:
  proxy:
    external: true

Traefik/portainer docker-compose.yaml

version: '3'

services:
  traefik:
    image: traefik:latest
    container_name: traefik
    restart: unless-stopped
    security_opt:
      - no-new-privileges:true
    networks:
      - proxy
    ports:
      - 80:80
      - 443:443
    environment:
      - CF_API_EMAIL=pits-blazers-0c@icloud.com
      - CF_DNS_API_TOKEN=JbIrYkbksXtM8_uFg9i5jHnz_-nd-3AGICFTZBLM
      #- CF_DNS_API_TOKEN=x6IFl0XG9WIdUWKsad3IXNAlHuRcVOw11VpWH2IJ
      #- CF_API_KEY=f16348bf50f68397286b5ffb01168407abe56
      # be sure to use the correct one depending on if you are using a token or key
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - /root/docker/traefik/data/traefik.yml:/traefik.yml:ro
      - /root/docker/traefik/data/acme.json:/acme.json
      - /root/docker/traefik/data/config.yml:/config.yml:ro
      - /root/docker/traefik/logs:/var/log
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.traefik.entrypoints=http"
      - "traefik.http.routers.traefik.rule=Host(`traefik-dashboard.example.com`)"
      - "traefik.http.middlewares.traefik-auth.basicauth.users=user:password"
      - "traefik.http.middlewares.traefik-https-redirect.redirectscheme.scheme=https"
      - "traefik.http.middlewares.sslheader.headers.customrequestheaders.X-Forwarded-Proto=https"
      - "traefik.http.routers.traefik.middlewares=traefik-https-redirect"
      - "traefik.http.routers.traefik-secure.entrypoints=https"
      - "traefik.http.routers.traefik-secure.rule=Host(`traefik-dashboard.example.com`)"
      - "traefik.http.routers.traefik-secure.middlewares=traefik-auth"
      - "traefik.http.routers.traefik-secure.tls=true"
      - "traefik.http.routers.traefik-secure.tls.domains[0].main=example.com"
      - "traefik.http.routers.traefik-secure.tls.domains[0].sans=*.example.com"
      - "traefik.http.routers.traefik-secure.service=api@internal"
  portainer:
    image: portainer/portainer-ce
    container_name: portainer
    restart: unless-stopped
    security_opt:
      - no-new-privileges:true
    networks:
      - proxy
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - /home/username/portainer/data:/data
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.portainer.entrypoints=http"
      - "traefik.http.routers.portainer.rule=Host(`portainer.example.com`)"
      - "traefik.http.middlewares.portainer-https-redirect.redirectscheme.scheme=https"
      - "traefik.http.routers.portainer.middlewares=portainer-https-redirect"
      - "traefik.http.routers.portainer-secure.entrypoints=https"
      - "traefik.http.routers.portainer-secure.rule=Host(`portainer.example.com`)"
      - "traefik.http.routers.portainer-secure.tls=true"
      - "traefik.http.routers.portainer-secure.service=portainer"
      - "traefik.http.services.portainer.loadbalancer.server.port=9000"
      - "traefik.docker.network=proxy"

networks:
  proxy:
    external: true

traefik.yml

api:
  dashboard: true
  debug: true
entryPoints:
  http:
    address: ":80"
    http:
      redirections:
        entryPoint:
          to: https
          scheme: https
  https:
    address: ":443"
    http:
      tls:
        certResolver: cloudflare
serversTransport:
  insecureSkipVerify: true
providers:
  docker:
    endpoint: "unix:///var/run/docker.sock"
    exposedByDefault: false
  file:
    filename: /config.yml
certificatesResolvers:
  cloudflare:
    acme:
      email: name@me.com
      storage: acme.json
      dnsChallenge:
        provider: cloudflare
        #disablePropagationCheck: true # uncomment this if you have issues pulling certificates through cloudflare, By setting this flag to true disables the need to wait for the propagation of the TXT record to all authoritative name servers.
        resolvers:
          - "1.1.1.1:53"
          - "1.0.0.1:53"
log:
  filePath: "/var/log/traefik.log"
  level: DEBUG

Stil getting 404 page not found on example.com. traefik-dashboard.example.com and portainer.example.com work fine.
Extra note when surfing to example.com I get 404 page not found put the certificate works.
Yesterday I also tried another domain name that I own lets call it "homelab.com" and this domain name worked instead of "example.com". Don't know if you can do anything with this info.

What does Traefik Dashboard tell you?

Maybe up your compose file version to 3.

Remove not needed labels:

 - "traefik.http.routers.apache.entrypoints=http"
 - "traefik.http.routers.apache.rule=Host(`example.com`)"

I fixed my issue by changing this line:

      - "traefik.http.routers.apache.rule=Host(`example.com`)"

into this:

      - "traefik.http.routers.apache.rule=Host(`example.com, `www.example.com`)"

But really appreciated the help, found out a lot more about traefik with your expertise.

1 Like

You saved my week ! thanks a lot !

Traefik v3 will only accept a single domain in Host(), so you can already prepare by using

Host(`example.com`) || Host(`www.example.com`)