You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Docker+Nginx环境下Certbot SSL证书认证失败问题

问题:Certbot域名认证失败(访问acme-challenge返回前端HTML)

基于Docker部署的Django+React+Nginx Web应用,使用Certbot的webroot方式申请SSL证书时失败,example.net和www.example.net均提示unauthorized,CA反馈访问acme-challenge路径返回前端HTML页面,无法下载验证文件。

现有配置

docker-compose.yml

services:
  db:
    image: postgres:13.2
    container_name: _database
    restart: always
    volumes:
      - ./database:/var/lib/postgresql/data
    environment:
      POSTGRES_DB: 
      POSTGRES_USER: 
      POSTGRES_PASSWORD:
    ports:
      - 5432:5432

  backend:
    build:
      context: ./backend
      dockerfile: dockerfile
    container_name: backend_jkr
    volumes:
      # Source code directory:
      - type: bind
        source: ./backend
        target: /app/backend
    ports:
      - "8000:8000"
    stdin_open: true
    tty: true
    # command: sh -c "cd /app/backend && python3 manage.py runserver 0.0.0.0:8000"

  frontend:
      build:
        context: ./frontend/
        dockerfile: Dockerfile
      container_name: frontend_jkr
      volumes:
        # Source code directory:
        - type: bind
          source: ./frontend
          target: /app/frontend
        - type: bind
          source: ./frontend/node_modules
          target: /app/frontend/node_modules
      ports:
        - "3001:3000"
        #3001 el primero en produccion
      environment:
        - WATCHPACK_POLLING=true
        - NODE_ENV=development
        - CHOKIDAR_USEPOLLING=true
      depends_on:
        - backend
      stdin_open: true
      # command: npm start

  nginx:
      image: nginx:latest
      container_name: nginx_jkr
      build: .
      restart: always
      ports:
        - "80:80"
      volumes:
        - ./nginx.conf:/nginx.conf:ro
        - ./certbot/conf:/etc/letsencrypt
        - ./certbot/www:/var/www/certbot

      depends_on:
        - backend
        - frontend

  certbot:
   image: certbot/certbot
   volumes:
    - ./certbot/conf:/etc/letsencrypt
    - ./certbot/www:/var/www/certbot

nginx.conf

# Configuración para el backend Django
server {
    listen 8000;  # Puerto en el que se escucharán las solicitudes al backend
    server_name IP localhost example.net www.example.net ;  # Dirección IP del servidor

    location / {
        proxy_pass http://backend:8000;  # Nombre del servicio Docker del backend Django
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

# Configuración para servir el frontend React y manejar los desafíos de Certbot
server {
    listen 80;
    server_name IP example.net www.example.net;

    # Configuración para servir el frontend React
    location / {
        root /usr/share/nginx/html;
        index index.html;
        try_files $uri /index.html =404;
    }

    location /api {
        proxy_pass http://backend:8000;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Host $server_name;
    }

    # Configuración para manejar los desafíos de Certbot
    location /.well-known/acme-challenge/ {
        root /var/www/certbot;
    }
}

# Configuración SSL
server {
    listen 443 ssl;
    server_name ip example.net www.example.net;

    ssl_certificate /etc/letsencrypt/live/example.net/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.net/privkey.pem;

    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    location / {
        root /usr/share/nginx/html;
        index index.html;
        try_files $uri /index.html =404;
    }

    location /api {
        proxy_pass http://backend:8000;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Host $server_name;
    }
}

解决方案

1. 优先匹配ACME挑战路径

修改Nginx配置中处理ACME挑战的location块,添加^~前缀确保该路径优先被匹配,避免被前端的路由规则拦截:

# 替换原ACME挑战配置
location ^~ /.well-known/acme-challenge/ {
    root /var/www/certbot;
    default_type text/plain; # 强制返回纯文本类型,避免CA解析错误
}

2. 拆分Server Name避免匹配混淆

将不同端口的server_name拆分,确保请求匹配到正确的server块:

  • 后端8000端口的server块仅保留本地访问标识:
server {
    listen 8000;
    server_name localhost 你的服务器IP;
    # 其余配置不变
}
  • 前端80/443端口的server块仅保留域名:
server {
    listen 80;
    server_name example.net www.example.net;
    # 其余配置不变
}

server {
    listen 443 ssl;
    server_name example.net www.example.net;
    # 其余配置不变
}

3. 执行Certbot认证命令

运行Certbot容器执行webroot认证,指定正确的webroot路径和域名:

docker-compose run certbot certonly --webroot -w /var/www/certbot -d example.net -d www.example.net

4. 验证配置并重启服务

  • 检查Nginx配置是否合法:
docker-compose exec nginx nginx -t
  • 重启Nginx使配置生效:
docker-compose restart nginx

5. 验证路径可访问

测试访问ACME挑战路径,确认返回验证文件内容而非前端HTML:

curl http://example.net/.well-known/acme-challenge/你的验证文件名

内容的提问来源于stack exchange,提问作者Juan Esteban Labayen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 10:34:58