问题描述
希望通过使用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证书并
正文完