Skip to main content

Setup TLS / HTTPS Docker Compose + Traefik v2

This guide documents how to enable HTTPS for a ReportPortal Docker Compose deployment using Traefik v2 as the reverse proxy. It covers both self-signed certificates (for local or internal testing) and Let’s Encrypt certificates (for publicly trusted TLS).

1. Supported TLS Scenarios

Certificate TypeEnvironmentPublic Internet Required
Self-signed (OpenSSL)Localhost / Internal VPCNo
Let’s Encrypt (HTTP-01)Public EC2 + Route 53Yes
Let’s Encrypt (DNS-01)Private VPCNo
important

Let’s Encrypt HTTP-01 validation requires public internet reachability.
Deployments in private subnets without an Internet Gateway must use DNS-01 instead.

2. Test Environment (Reference)

AWS Infrastructure (HTTP-01 scenario)

ComponentSpecification
EC2t3.medium (2 vCPU, 4 GB RAM) /
OSUbuntu 24.04 / Amazon Linux 2023
SubnetPublic subnet with IGW
DNSRoute 53 public hosted zone
Domaintls-docker.example.com

Using a public subnet removes ambiguity during troubleshooting.

Required Security Group Rules

TypePortSourcePurpose
HTTP800.0.0.0/0ACME HTTP-01
HTTPS4430.0.0.0/0HTTPS access
TCP8081Your IPTraefik dashboard
SSH22Your IPManagement

3. Scenario 1 — Self-Signed Certificates (OpenSSL)

3.1 Generate Certificates

mkdir -p certs

openssl genrsa -out certs/reportportal.key 2048

openssl req -new -x509 \
-key certs/reportportal.key \
-out certs/reportportal.crt \
-days 365 \
-subj "/CN=localhost" \
-addext "subjectAltName=DNS:localhost,IP:127.0.0.1"

3.2 Traefik File Provider (TLS)

Create certs/tls.yml:

tls:
certificates:
- certFile: /certs/reportportal.crt
keyFile: /certs/reportportal.key

3.3 Validation — Self-Signed TLS

Verify key matches certificate

openssl x509 -noout -modulus -in certs/reportportal.crt | openssl md5
openssl rsa -noout -modulus -in certs/reportportal.key | openssl md5

Trust validation

curl -v --cacert certs/reportportal.crt https://localhost

Fingerprint comparison

oopenssl x509 -in certs/reportportal.crt -noout -fingerprint -sha256

openssl s_client -connect localhost:443 </dev/null 2>/dev/null \
| openssl x509 -noout -fingerprint -sha256

Subject and validity

openssl s_client -connect localhost:443 </dev/null 2>/dev/null \
| openssl x509 -noout -subject -issuer -dates

4. Scenario 2 — Let’s Encrypt (HTTP-01)

4.1 Prerequisites (Mandatory)

  • Domain resolves to a public IP
  • EC2 subnet has route:
0.0.0.0/0 → Internet Gateway
  • Ports 80 and 443 reachable from the internet

4.2 Prepare ACME Storage

touch acme.json
chmod 600 acme.json

4.3 Docker Compose — Traefik Gateway

services:
gateway:
image: traefik:v2.11.32
restart: unless-stopped
ports:
- "80:80"
- "443:443"
- "8081:8081"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./acme.json:/acme.json
command:
- --providers.docker=true
- --providers.docker.exposedbydefault=false

- --entrypoints.web.address=:80
- --entrypoints.websecure.address=:443
- --entrypoints.traefik.address=:8081

- --entrypoints.web.http.redirections.entrypoint.to=websecure
- --entrypoints.web.http.redirections.entrypoint.scheme=https

- --certificatesresolvers.letsencrypt.acme.email=admin@example.com
- --certificatesresolvers.letsencrypt.acme.storage=/acme.json
- --certificatesresolvers.letsencrypt.acme.httpchallenge=true
- --certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web

- --api.dashboard=true
- --api.insecure=true

4.4 Service TLS Labels

labels:
- "traefik.enable=true"
- "traefik.http.routers.app.rule=Host(`tls-docker.example.com`)"
- "traefik.http.routers.app.entrypoints=websecure"
- "traefik.http.routers.app.tls=true"
- "traefik.http.routers.app.tls.certresolver=letsencrypt"
- "traefik.http.services.app.loadbalancer.server.port=8080"

5. Validation — Let’s Encrypt (HTTP-01)

DNS resolution

dig +short tls-docker.example.com
dig @8.8.8.8 +short tls-docker.example.com

TCP reachability

nc -vz tls-docker.example.com 80

HTTP reachability

curl -v http://tls-docker.example.com

ACME challenge path

404 Not Found is expected and correct

HTTPS validation

curl -v https://tls-docker.example.com

Certificate issuer verification

echo | openssl s_client \
-connect tls-docker.example.com:443 \
-servername tls-docker.example.com \
2>/dev/null | openssl x509 -noout -issuer -subject -dates

Expected issuer:

CN = Let's Encrypt

6. Private Subnets — Important Limitation

If the domain resolves to a private IP (RFC1918) or the subnet routes traffic via NAT Gateway only, Let’s Encrypt HTTP-01 will fail.

Symptoms

  • DNS resolves internally but not publicly
  • ACME challenge never triggered
  • Traefik serves default certificate

Solution
Use DNS-01 validation with Route 53.

7. Troubleshooting

IssueCauseResolution
ACME never triggersNo public ingressUse DNS-01
Default Traefik certNo issued certCheck ACME logs
example.com email errorInvalid ACME emailUse real domain
Permission denied acme.jsonWrong file modechmod 600
404 from HTTPSHost rule mismatchVerify router rule

8. Summary

  • Self-signed TLS works for local and internal environments
  • Let’s Encrypt HTTP-01 works only with public ingress
  • DNS-01 is required for private VPC deployments
  • Traefik configuration remains identical; only the ACME method changes