Skip to main content

Wildcard Certificates with Let's Encrypt

warning

Before setting up wildcard certificates, you must have a domain that you own and control. You must also have access to the DNS records for this domain.

Since Pangolin uses Traefik as a reverse proxy, it has built-in support for Let's Encrypt certificates. This allows you to easily secure your Pangolin instance and all proxied resources with HTTPS. Lets Encrypt provides free SSL certificates, which are automatically renewed.

If you used the default settings during installation, your Traefik instance should be setup to use HTTP-01 challenge for certificate generation. This challenge is the easiest to configure and requires that the Traefik instance be accessible from the internet on port 80.

It is highly reccommended that you read the official Traefik documentation on ACME and Let's Encrypt before proceeding.

Benefits of Wildcard Certificates

  1. Wildcard certificates allow you to secure your all subdomains with a single certificate. This reduces the number of certificates you need to manage.
  2. You can add new subdomains to resources without needing to generate a new certificate each time. Without a wildcard certificate, you would need to wait (up to a few minutes usually) for a new certificate to be generated and loaded by Traefik.
  • For example: A wildcard cert *.example.com could protect api.example.com, blog.example.com, and another *.subdomain.example.com could protect api.subdomain.example.com, blog.subdomain.example.com, etc.
  1. The rate limits for Let's Encrypt are per domain. Using a wildcard certificate reduces the number of domains you have, which can help you avoid hitting these limits.

Setting Up Wildcard Certificates

  1. Make sure the stack is not running.
  2. Update the Traefik configuration to use the DNS-01 challenge instead of the HTTP-01 challenge. This tells Traefik to use your DNS provider to create the DNS records needed for the challenge.
  3. Set the prefer_wildcard_cert flag to true in the Pangolin configuration file for your domain.
  • This settings will try to encourage Traefik to request one wildcard certificate for each level of the domain used by your existing resources.
  • For example: If you have two resources blog.example.com and blog.subdomain.example.com, Traefik should try to request a wildcard certificate for *.example.com and *.subdomain.example.com automatically for you.

Traefik Configuration

Default Config for HTTP-01 Challenge

This is default config generated by the installer. This is shown here for reference to compare with the wildcard config below.

  1. Tell Traefik to use the web entrypoint for the HTTP challenge.

traefik_config.yml

certificatesResolvers:
letsencrypt:
acme:
httpChallenge:
entryPoint: web
email: admin@example.com
storage: "/letsencrypt/acme.json"
caServer: "https://acme-v02.api.letsencrypt.org/directory"
  1. Set the cert resolver to letsencrypt and the entrypoint to websecure in the dynamic config.

dynamic_config.yml

next-router:
rule: "Host(`example.com`) && !PathPrefix(`/api/v1`)"
service: next-service
entryPoints:
- websecure
tls:
certResolver: letsencrypt

Wildcard Config for DNS-01 Challenge

  1. Tell Traefik to use your DNS provider for the DNS challenge. In this example, we are using Cloudflare.

traefik_config.yml

certificatesResolvers:
letsencrypt:
acme:
dnsChallenge:
provider: "cloudflare" # your DNS provider
# see https://doc.traefik.io/traefik/https/acme/#providers
email: "admin@example.com"
storage: "/letsencrypt/acme.json"
caServer: "https://acme-v02.api.letsencrypt.org/directory"
  1. Add the domain and wildcard domain to the domains section of the next (front end) router in the dynamic config. This tells Traefik to generate a wildcard certificate for the base domain and all subdomains.

dynamic_config.yml

next-router:
rule: "Host(`example.com`) && !PathPrefix(`/api/v1`)"
service: next-service
entryPoints:
- websecure
tls:
certResolver: letsencrypt
domains:
- main: "example.com"
sans:
- "*.example.com"
  1. Add the environment variables for your DNS provider to the Traefik service in the docker compose file. This allows Traefik to authenticate with your DNS provider to create the DNS records needed for the challenge.

docker-compose.yml

traefik:
image: traefik:v3.3.3
container_name: traefik
restart: unless-stopped
network_mode: service:gerbil
depends_on:
pangolin:
condition: service_healthy
command:
- --configFile=/etc/traefik/traefik_config.yml
# Add the environment variables for your DNS provider.
environment:
CLOUDFLARE_DNS_API_TOKEN: "your-cloudflare-api-token"
volumes:
- ./config/traefik:/etc/traefik:ro
- ./config/letsencrypt:/letsencrypt
note

If you're using Cloudflare, make sure your API token has the permissions Zone/Zone/Read and Zone/DNS/Edit and make sure it applies to all zones.

Traefik supports most DNS providers. You can find a full list of supported providers and how to configure them in the Traefik documentation on providers.

Verify it Works

tip

You can ensure Traefik doesn't try to use the old certs by deleting the previously used acme.json file. This will force Traefik to generate a new certificate on the next start.

Start the stack and watch the logs. You should notice that Traefik is making calls to your DNS provider to create the necessary records to complete the challenge. For debugging purposes, you may find it useful to set the log level of Traefik to debug in the traefik_config.yml file.

After Traefik is done waiting for the cert to verify, try to create a new resource with an unused subdomain. Traefik should not try to generated a new certificate, but instead use the wildcard certificate. The domain should also be secured immediately instead of waiting for a new certificate to be generated.

You can also check the volume (in the example above at config/letsencrypt/) for the correct certificates. In the acme.json file you should see something similar to the following. Note the *. in the domain.

{
"Certificates": [
{
"domain": {
"main": "*.example.com"
},
"certificate": "...",
"key": "...",
"Store": "default"
}
]
}