使用Ansible设置Let’s Encrypt证书

59次阅读
没有评论

问题描述

希望通过使用Ansible来获取Let’s Encrypt证书,但在执行任务时遇到了问题。他的Ansible playbook结合了一个教程和Ansible官方文档中的内容。然而,当他运行这个playbook时,遇到了一个错误,导致无法成功验证Let’s Encrypt的挑战。他希望了解问题的来源并找到解决方法。

解决方案

根据您提供的问答数据,以及前面用户的问题描述和回复,以下是关于如何在Ansible中设置Let’s Encrypt证书的解决方案。在这个解决方案中,我们将讨论playbook的改进、Nginx的配置和其他可能的问题。

请注意以下操作可能需要根据您的实际情况进行适当的修改和调整。

改进Ansible Playbook

您的Ansible playbook中存在一些问题,可能导致Let’s Encrypt挑战验证失败。以下是改进后的任务示例:

---
# 创建存储密钥和证书的目录
- name: "创建/etc/letsencrypt所需的目录"
  become: yes
  file:
    path: "/etc/letsencrypt/{{ item }}"
    state: directory
    owner: root
    group: root
    mode: u=rwx,g=x,o=x
  with_items:
    - account
    - certs
    - csrs
    - keys

# 生成Let's Encrypt账户密钥
- name: 生成Let's Encrypt账户密钥
  become: yes
  openssl_privatekey:
    path: "{{ letsencrypt_account_key }}"

# 生成默认值(4096位RSA)的Let's Encrypt私钥
- name: 生成默认值(4096位RSA)的Let's Encrypt私钥
  become: yes
  openssl_privatekey:
    path: "{{ letsencrypt_keys_dir }}/{{ domain_name }}.key"

# 生成OpenSSL证书签名请求
- name: 生成OpenSSL证书签名请求
  become: yes
  community.crypto.openssl_csr:
    path: "{{ letsencrypt_csrs_dir }}/{{ domain_name }}.csr"
    privatekey_path: "{{ letsencrypt_keys_dir }}/{{ domain_name }}.key"
    common_name: "{{ domain_name }}"

# 创建Let's Encrypt挑战
- name: 创建Let's Encrypt挑战
  become: yes
  community.crypto.acme_certificate:
    acme_directory: "{{ acme_directory }}"
    acme_version: "{{ acme_version }}"
    account_email: "{{ acme_email }}"
    terms_agreed: yes
    account_key_src: "{{ letsencrypt_account_key }}"
    csr: "{{ letsencrypt_csrs_dir }}/{{ domain_name }}.csr"
    dest: "{{ letsencrypt_certs_dir }}/{{ domain_name }}.crt"
    remaining_days: "{{ remaining_days }}"
  register: acme_challenge

# 创建目录以存放验证令牌
- name: "创建目录以存放验证令牌"
  become: yes
  file:
    path: "{{ project_path }}/.well-known/acme-challenge"
    state: directory
    owner: root
    group: root
    mode: u=rwx,g=rx,o=rx

# 复制http-01挑战所需文件
- name: 复制http-01挑战所需文件
  become: yes
  copy:
    dest: "{{ project_path }}/{{ acme_challenge['challenge_data'][item]['http-01']['resource'] }}"
    content: "{{ acme_challenge['challenge_data'][item]['http-01']['resource_value'] }}"
  with_items:
    - "{{ domain_name }}"
  when: acme_challenge is changed and domain_name|string in acme_challenge['challenge_data']

# 执行Let's Encrypt挑战验证并获取证书
- name: 执行Let's Encrypt挑战验证并获取证书
  become: yes
  community.crypto.acme_certificate:
    account_key_src: "{{ letsencrypt_account_key }}"
    csr: "{{ letsencrypt_csrs_dir }}/{{ domain_name }}.csr"
    cert: "{{ letsencrypt_certs_dir }}/{{ domain_name }}.crt"
    acme_directory: "{{ acme_directory }}"
    acme_version: "{{ acme_version }}"
    account_email: "{{ acme_email }}"
    challenge: "{{ acme_challenge_type }}"
    fullchain: "{{ letsencrypt_certs_dir }}/{{ domain_name }}-fullchain.crt"
    chain: "{{ letsencrypt_certs_dir }}/{{ domain_name }}-intermediate.crt"
    remaining_days: "{{ remaining_days }}"
    data: "{{ acme_challenge }}"
  when: acme_challenge is changed

优化Nginx配置

为了让Let’s Encrypt能够成功验证挑战,您需要确保.well-known/acme-challenge/路径在http请求中可访问。这是因为Let’s Encrypt需要访问这些文件以验证您对域名的控制权。

server {
    listen 80;
    location /.well-known/acme-challenge/ {
        root {{ project_path }};
    }
    server_name {{ domain_name }} www.{{ domain_name }} {{ web_server_ip }};
    return 301 https://{{ domain_name }}$request_uri;
}

server {
    listen 443 ssl;
    ssl_certificate /etc/letsencrypt/certs/{{ domain_name }}-fullchain.crt;
    ssl_certificate_key /etc/letsencrypt/keys/{{ domain_name }}.key;
    charset utf-8;
    client_max_body_size 4M;

    # Serving static files directly from Nginx without passing through uwsgi
    location /app/static/ {
        alias {{ project_path }}/app/static/;
    }

    location /.well-known/acme-challenge/ {
        root {{ project_path }};
    }

    location / {
        # kill cache
        add_header Last-Modified $date_gmt;
        add_header Cache-Control 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0';
        if_modified_since off;
        expires off;
        etag off;
        uwsgi_pass {{ project_name }};
        include {{ project_path }}/uwsgi_params;
    }
}

解决连接问题

您的错误消息中提到连接被拒绝,可能是由于防火墙或网络配置问题引起的。请确保您的服务器能够正常访问http协议的端口(默认为80)。

总结

通过改进Ansible playbook、优化Nginx配置和检查网络连接,您应该能够成功获取Let’s Encrypt证书并

正文完