Skip to content

Fix: qual.portugalodyssey.pt Self-Signed Certificate

Problem

qual.portugalodyssey.pt is serving a self-signed certificate instead of a Let's Encrypt certificate, even though: - Traefik certificate resolver is working (certificates issued for s3.portugalodyssey.pt and s3-console.portugalodyssey.pt) - Router configuration includes tls.certresolver=letsencrypt

Root Cause

The certificate resolver is configured correctly, but Traefik hasn't attempted to issue a certificate for qual.portugalodyssey.pt yet. This can happen when: 1. The container was started before the certificate resolver was properly configured 2. Traefik hasn't detected the router labels yet 3. The HTTP challenge hasn't been triggered

Solution

Restart the public-fo-qual container to trigger Traefik to detect the router and request a certificate:

# On VPS
docker compose -f infrastructure/compose/qualification.yml --env-file .env.qual restart public-fo-qual

# Or recreate to ensure fresh labels
docker compose -f infrastructure/compose/qualification.yml --env-file .env.qual up -d --force-recreate public-fo-qual

Verification

After restarting, check Traefik logs:

docker logs po-traefik 2>&1 | grep -i "qual.portugalodyssey.pt\|certificate\|acme" | tail -30

You should see: - Certificate request attempts - HTTP challenge attempts - Certificate issuance success

Wait a few minutes for Let's Encrypt to issue the certificate, then verify:

curl -I https://qual.portugalodyssey.pt
# Should NOT show "self-signed certificate" error

# Or check acme.json
cat infrastructure/config/traefik/acme.json | jq '.letsencrypt.Certificates[] | select(.domain.main == "qual.portugalodyssey.pt")'

Configuration

The router is correctly configured in infrastructure/compose/qualification.yml:

labels:
  - "traefik.http.routers.public-fo-qual.rule=Host(`public-fo-qual.portugalodyssey.pt`) || Host(`qual.portugalodyssey.pt`)"
  - "traefik.http.routers.public-fo-qual.tls=true"
  - "traefik.http.routers.public-fo-qual.tls.certresolver=letsencrypt"

Troubleshooting

If certificate still isn't issued after restart:

  1. Check Traefik logs for errors:

    docker logs po-traefik 2>&1 | grep -i error | tail -20
    

  2. Verify HTTP challenge is accessible:

    curl -I http://qual.portugalodyssey.pt/.well-known/acme-challenge/test
    
    Should return 404 (not connection refused), which means Traefik can reach the domain.

  3. Check DNS resolution:

    dig qual.portugalodyssey.pt
    
    Should resolve to your VPS IP address.

  4. Verify port 80 is accessible:

    curl -I http://qual.portugalodyssey.pt
    
    Should return HTTP response (may redirect to HTTPS).

  5. Force certificate renewal:

    # Restart Traefik to force certificate check
    docker compose -f infrastructure/compose/shared.yml --env-file infrastructure/compose/.env.shared restart traefik
    

  • Certificate resolver configuration: infrastructure/compose/shared.yml
  • Router configuration: infrastructure/compose/qualification.yml (public-fo-qual service)
  • ACME storage: infrastructure/config/traefik/acme.json