使用 nginx 的 docker certbot 容器检索证书时出现用户权限问题

Mog*_*get 3 nginx docker docker-compose certbot

我意识到这个问题写得有多糟糕,所以我重写了整个问题并给出了解决方案。

TLDR:我想要一个关于如何让 docker certbot/certbot 容器检索到的 LetsEncrypt 证书和密钥可供 nginx:latest 容器读取的解决方案或建议。

它不可读的原因是证书存储在一个文件夹中,通常是 /etc/letsencrypt/archive/domain/certificates,并且文件夹存档的所有者设置为 root,组设置为 root,模式为 0700。密钥的所有者也设置为 root,组设置为 root,模式为 0600。

nginx 容器将 pid 0 设置为 nginx 主进程并由 root 运行,但它会生成一个需要读取证书和密钥的工作进程。该工作进程由非特权用户拥有。

DOCKER-COMPOSE 配置

---

version: '3'
services:

  nginx:
    container_name: nginx
    image: nginx:latest
    ports:
      - 80:80
      - 443:443
    volumes:
      - ./data/nginx/conf:/etc/nginx/conf.d
      # The volume under is to provide the DHPARAM file.
      - ./data/nginx/tls:/etc/pki/tls
      - ./data/certbot/conf:/etc/letsencrypt
      - ./data/certbot/www:/var/www/certbot
    # This reloads the certificates every 24h as long as the container is running
    command: "/bin/sh -c 'while :; do sleep 24h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'"

#  certbot:
#    container_name: certbot
#    image: certbot/certbot
#    volumes:
#      - ./data/certbot/conf:/etc/letsencrypt
#      - ./data/certbot/www:/var/www/certbot
#    depends_on:
#      - nginx
#    # This checks if the certificates need to be renewed every 12 hours.
#    entrypoint: "/bin/sh -c \"trap exit TERM; while :; do certbot renew; #sleep 12h & wait $${!}; done;\""


Run Code Online (Sandbox Code Playgroud)

NGINX 配置

server {
  listen 80 default_server;
  server_name _;

  location /.well-known/acme-challenge/ {
    allow all;
    root /var/www/certbot;
  }

  location / {
    return 301 https://$host$request_uri;
  }
}
Run Code Online (Sandbox Code Playgroud)

我已经排除了配置中不必要的行。完成证书的初始检索后,我将删除 yaml 文件中的注释,以便 certbot 容器在下次执行 docker-compose up -d 时自动检索新证书。

我在启动 nginx 容器后运行的命令。

---

version: '3'
services:

  nginx:
    container_name: nginx
    image: nginx:latest
    ports:
      - 80:80
      - 443:443
    volumes:
      - ./data/nginx/conf:/etc/nginx/conf.d
      # The volume under is to provide the DHPARAM file.
      - ./data/nginx/tls:/etc/pki/tls
      - ./data/certbot/conf:/etc/letsencrypt
      - ./data/certbot/www:/var/www/certbot
    # This reloads the certificates every 24h as long as the container is running
    command: "/bin/sh -c 'while :; do sleep 24h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'"

#  certbot:
#    container_name: certbot
#    image: certbot/certbot
#    volumes:
#      - ./data/certbot/conf:/etc/letsencrypt
#      - ./data/certbot/www:/var/www/certbot
#    depends_on:
#      - nginx
#    # This checks if the certificates need to be renewed every 12 hours.
#    entrypoint: "/bin/sh -c \"trap exit TERM; while :; do certbot renew; #sleep 12h & wait $${!}; done;\""


Run Code Online (Sandbox Code Playgroud)

根据您在上面看到的内容,我获得了有效的证书,但它们只能由 root 读取。

我希望此设置在需要时检索新证书,但如果我手动更改文件夹/文件的所有权和模式,将其限制为仅根目录,那么在检索新证书时,这些更改将被撤消。

我想要一个解决方案,以便非特权 nginx 用户可以读取这些证书和密钥,而无需在检索新证书时进行手动工作。

Mog*_*get 5

我检查了 certbot 中是否有有用的选项。执行 certbot --help 后,我看到存在一个 certbot -h all 选项,它为您提供了 certbot 的每个选项。

在那里我找到了一个后挂钩选项,该选项仅在成功检索新证书时运行。

解决方案是更改 docker-compose yaml 文件中的以下行。

entrypoint: "/bin/sh -c \"trap exit TERM; while :; do certbot renew; #sleep 12h & wait $${!}; done;\""
Run Code Online (Sandbox Code Playgroud)

我将其更改为以下内容。

entrypoint: "/bin/sh -c \"trap exit TERM; while :; do certbot renew --post-hook 'chown root:NGINXUID /etc/letsencrypt/live /etc/letsencrypt/archive && chmod 750 /etc/letsencrypt/live /etc/letsencrypt/archive && chown root:NGINXUID /etc/letsencrypt/archive/DOMAIN/privkey*.pem && chmod 640 /etc/letsencrypt/archive/DOMAIN/privkey*.pem'; sleep 12h & wait $${!}; done;\""
Run Code Online (Sandbox Code Playgroud)