有一个自己的项目需要上线,域名解析完成后,发现只能使用 http 协议,这在浏览器上会限制,提示用户不安全,所以需要把 HTTP 升级成 HTTPS 协议,但又不想花钱。
前提条件:
-
已经配置好 Nginx 服务器
-
域名已解析到您的服务器 IP
-
已开放 80 和 443 端口(可在阿里云控制台的安全组设置中配置)
获取证书
我们先获取证书,我使用的是「Let's Encrypt」,这是一家为6亿多个网站提供免费 TLS 证书的非营利组织。
Let's Encrypt 提供免费的证书,有效期为 90 天,可以自动续期。
安装证书
我们需要先安装 Certbot 和 Nginx 插件:
# 安装 EPEL 仓库sudo yum install epel-release -y# 安装 Certbot 和 Nginx 插件sudo yum install certbot python3-certbot-nginx -y
获取,然后安装证书
sudo certbot --nginx -d your-domain.com
-
在操作过程中,Certbot 会询问几个问题:
-
输入您的邮箱地址(用于紧急续期通知和安全公告)
-
同意服务条款
-
是否愿意共享邮箱(可选)
-
是否希望将所有 HTTP 流量重定向到 HTTPS(建议选择 2,完全重定向)
配置 Nginx
提供一个 AI 反馈的 Nginx 配置:
server { listen 443 ssl; server_name example.com www.example.com; ssl_certificate /path/to/your/certificate.crt; ssl_certificate_key /path/to/your/private.key; # 其他 SSL 配置 ssl_protocols TLSv1.2 TLSv1.3; ssl_prefer_server_ciphers on; ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384; # 网站根目录等配置 root /var/www/html; index index.html; # 其他配置...}# HTTP 重定向到 HTTPSserver { listen 80; server_name example.com www.example.com; return 301 https://$host$request_uri;}
另外提供一个 Apache 的配置
<VirtualHost *:443> ServerName example.com ServerAlias www.example.com SSLEngine on SSLCertificateFile /path/to/your/certificate.crt SSLCertificateKeyFile /path/to/your/private.key # 其他配置 DocumentRoot /var/www/html # 其他设置...</VirtualHost># HTTP 重定向到 HTTPS<VirtualHost *:80> ServerName example.com ServerAlias www.example.com Redirect permanent / <https://example.com/></VirtualHost>
检查 Nginx 配置
配置好以后,您可以检查 Nginx 的配置,
sudo cat /etc/nginx/conf.d/your-config-file.conf
我服务器上 Nginx 的内容如下:
server { listen 80; listen [::]:80; server_name your-domain.com; # 添加网站根目录 root /usr/share/nginx/your-domain; # 为 Let's Encrypt 验证添加特殊处理 location /.well-known/acme-challenge/ { allow all; } # 其他请求继续重定向到 HTTPS location / { return 301 https://$server_name$request_uri; }}# HTTPS serverserver { listen 443 ssl http2; listen [::]:443 ssl http2; server_name your-domain.com; client_max_body_size 50M; # 下载优化 proxy_buffer_size 128k; # 代理响应的缓冲区大小 proxy_buffers 4 256k; # 缓冲区数量和大小 proxy_busy_buffers_size 256k; # 繁忙时缓冲区大小 proxy_temp_file_write_size 256k; # 临时文件写入大小 # 开启 gzip 压缩 gzip on; gzip_min_length 1k; gzip_comp_level 6; gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; # 修改证书路径为 Let's Encrypt 的证书路径 ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem; ssl_session_cache shared:SSL:1m; ssl_session_timeout 10m; ssl_ciphers PROFILE=SYSTEM; ssl_prefer_server_ciphers on; # 添加反向代理配置 location / { proxy_pass <http://localhost:3100>; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; } # Load configuration files for the default server block. include /etc/nginx/default.d/*.conf; error_page 404 /404.html; location = /40x.html { } error_page 500 502 503 504 /50x.html; location = /50x.html { }}
自动续期脚本
如果到期怎么办?
我们可以设置自动续期的脚本:
确认当前状态
# 检查 Certbot 版本certbot --version# 查看当前证书信息sudo certbot certificates
测试续期功能
# 执行干运行测试,不实际更新证书sudo certbot renew --dry-run
创建脚本
sudo nano /usr/local/bin/renew-letsencrypt.sh
添加内容:
#!/bin/bash# 日志文件LOG_FILE="/var/log/letsencrypt-renewal.log"DATE=$(date "+%Y-%m-%d %H:%M:%S")# 记录开始信息echo "[$DATE] 开始证书续期检查..." >> $LOG_FILE# 执行续期操作并记录输出RENEWAL_OUTPUT=$(certbot renew --quiet 2>&1)RENEWAL_STATUS=$?# 检查续期状态if [ $RENEWAL_STATUS -eq 0 ]; then echo "[$DATE] 证书检查/续期成功" >> $LOG_FILE # 检查是否有证书被实际更新 if echo "$RENEWAL_OUTPUT" | grep -q "renewal"; then echo "[$DATE] 检测到证书已更新,重新加载 Nginx" >> $LOG_FILE systemctl reload nginx NGINX_STATUS=$? if [ $NGINX_STATUS -eq 0 ]; then echo "[$DATE] Nginx 重新加载成功" >> $LOG_FILE else echo "[$DATE] 错误:Nginx 重新加载失败,返回码: $NGINX_STATUS" >> $LOG_FILE fi else echo "[$DATE] 没有证书需要更新" >> $LOG_FILE fielse echo "[$DATE] 错误:证书续期失败,返回码: $RENEWAL_STATUS" >> $LOG_FILE echo "[$DATE] 错误详情: $RENEWAL_OUTPUT" >> $LOG_FILEfiecho "[$DATE] 证书续期流程完成" >> $LOG_FILEecho "----------------------------------------" >> $LOG_FILE
设置执行权限
sudo chmod +x /usr/local/bin/renew-letsencrypt.sh
创建任务
sudo crontab -e
添加以下内容:
# 每天凌晨 2:15 和下午 2:15 运行证书续期15 2,14 * * * /usr/local/bin/renew-letsencrypt.sh
验证任务设置
sudo crontab -l
设置每周运行一次
sudo chmod +x /usr/local/bin/renew-letsencrypt.shsudo crontab -e
每周检查一次
# 每周一上午9点检查证书状态0 9 * * 1 /usr/local/bin/renew-letsencrypt.sh
手动续签脚本
# 执行脚本sudo /usr/local/bin/renew-letsencrypt.sh# 检查文件输出sudo tail -f /var/log/letsencrypt-renewal.log
查看证书信息
sudo certbot certificates
会显示出「已安装证书的域名、存储位置、到期日期、续期设置」证书有效期
比如:从 2025-04-21 到 2025-07-20(共 90 天,符合 Let's Encrypt 标准)。
Certbot 会在到期前 30 天(即 2025-06-20 左右)自动尝试续期(你之前的 -dry-run 测试已确认续期配置正常)。
无需手动操作,除非续期失败。