HTTPS / SSL Certificates in Practice

Free DV certs, Letsencrypt automation, wildcard vs multi-domain, and the exact Nginx/Traefik/Docker configs to install and rotate them.

BeginnerUpdated 2026-10-2933K views

Certificate types and what to buy vs get free

TypeValidationPrice feelUse
DV (Domain Validation)验证域名所有权(DNS/文件)免费(Let's Encrypt/云厂商免费版)个人站、内部系统、绝大多数 API
OV (Organization)验证企业真实身份(人工)数百元/年企业官网、需展示公司名
EV (Extended)最严格企业验证 + 浏览器历史显示组织名数千元/年金融、支付、高信任场景
Wildcard (*.example.com)保护一级子域名云厂商免费额度常不含子域名多 / 微服务平台
Multi-domain (SAN)一张证书保护多个域名按域名数计费多品牌/多站点合并
  • Five clouds each offer free DV certs (Tencent/Alibaba: 1-year per domain, or 3-month renewable; Huawei/Baidu similar) — apply in the console, one click to push to their CDN/SLB
  • Self-hosted → Letsencrypt with certbot/acme.sh: 90-day certs, fully automatable via HTTP-01 or DNS-01
  • DNS-01 works even when port 80 is closed or behind strict firewalls — perfect for internal services and wildcard certs

acme.sh with DNS-01: automatic wildcard certs

# 以腾讯云 DNS 为例(其他服务商换成对应 dnsapi)
curl https://get.acme.sh | sh -s email=me@example.com

# 配置 DNS API 密钥(控制台建子账号只给 DNS 权限)
export Tencent_SecretId="AKIDxxxxx"
export Tencent_SecretKey="xxxxxxxxxxxx"

# 签发泛域名证书(DNS-01)
~/.acme.sh/acme.sh --issue --dns dns_tencent -d example.com -d '*.example.com' --keylength ec-256

# 安装到 Nginx 并自动 reload:续期后自动生效
~/.acme.sh/acme.sh --install-cert -d example.com --ecc \
  --key-file       /etc/nginx/ssl/example.com.key \
  --fullchain-file /etc/nginx/ssl/example.com.crt \
  --reloadcmd      "systemctl reload nginx"
Cert renewal does not fail loudly by default. Point acme.sh notifications at yourself (--notify-hook), and put a synthetic check on your monitoring: curl the HTTPS endpoint daily and alarm when the certificate is valid for less than 14 days.

Nginx / Traefik / Docker configs

server {
    listen 443 ssl http2;
    server_name example.com;
    ssl_certificate     /etc/nginx/ssl/example.com.crt;
    ssl_certificate_key /etc/nginx/ssl/example.com.key;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 1d;
    add_header Strict-Transport-Security "max-age=31536000" always;
}
# 80 强制跳 443
server {
    listen 80;
    server_name example.com;
    return 301 https://$host$request_uri;
}
# Traefik(Docker 标签自动申请+续期)
services:
  traefik:
    image: traefik:v3
    command:
      - --certificatesresolvers.le.acme.email=me@example.com
      - --certificatesresolvers.le.acme.storage=/acme.json
      - --certificatesresolvers.le.acme.dnschallenge.provider=tencentcloud
    environment:
      TENCENTCLOUD_SECRET_ID: ${SECRET_ID}
      TENCENTCLOUD_SECRET_KEY: ${SECRET_KEY}

  api:
    labels:
      - traefik.http.routers.api.rule=Host(`api.example.com`)
      - traefik.http.routers.api.tls=true
      - traefik.http.routers.api.tls.certresolver=le
      - traefik.http.routers.api.tls.domains[0].main=example.com
      - traefik.http.routers.api.tls.domains[0].sans=api.example.com
  • TLSv1.0/1.1 are dead — disable them; PCI and modern browsers reject them anyway
  • HSTS pins HTTPS for a year per browser — make sure every subdomain is HTTPS-ready before raising max-age
  • Keep intermediate certs: a 'certificate not trusted' error on some devices is almost always a missing intermediate chain in fullchain.pem

Friends & Partners