刚刚学会怎么给自己的网站升级到 HTTPS,使用了 nginx + certbot,实现自动更新证书。

安装 nginx 和 certbot

首先我们需要去给服务器安装 nginx,这个就按照官网来就行。

然后我们还要装 certbot,也是去官网跟着下完就行。

配置 nginx

我们先需要去 /etc/nginx/nginx.conf,给配置文件包含一下 conf.d 目录,这样我们就可以将配置文件按照域名来隔离开配置。

  
$ cd /etc/nginx/nginx.conf

我的配置如下,当然具体配置需按照实际情况进行修改:

  
user root;
worker_processes auto;

error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;


events {
   worker_connections 102400;
}


http {
   include /etc/nginx/mime.types;
   default_type application/octet-stream;

   log_format main '$remote_addr - $remote_user [$time_local] "$request" '
   '$status $body_bytes_sent "$http_referer" '
   '"$http_user_agent" "$http_x_forwarded_for"'
   '$request_time $upstream_response_time $upstream_addr $upstream_status';

   access_log /var/log/nginx/access.log main;

   sendfile on;
   #tcp_nopush on;

   keepalive_timeout 65;

   #gzip  on;
   map $http_upgrade $connection_upgrade {
      default upgrade;
      '' close;
   }

   # 包含 conf.d 目录下所有配置文件
   include /etc/nginx/conf.d/*.conf;
}

然后我们进到 conf.d 目录,新建一个 root.conf 来配置一些通用的配置:

  
server {
   listen 80;
   server_name example.com;

   # acme-challenge 目录,签署证书时需要来访问这里面的文件来验证身份
   location ^~ /.well-known/acme-challenge/ {
      default_type "text/plain";
      # 签证书时,会去校验你的网站身份,这个文件会被自动生成到这个目录下,然后请求它
      # http://example.com/.well-known/acme-challenge/xxxxxx
      root /var/www/letsencrypt;
   }

   location = /.well-known/acme-challenge/ {
      return 404;
   }

   # 将根域名的请求重定向到 www 子域名上(如果没有这个需求,就不要配这个)
   location / {
      return 301 https://www.example.com$request_uri;
   }
}

# 对所有子域名,保证签证书的时候还能访问到 /var/www/letsencrypt 下的静态资源
server {
   listen 80;
   server_name *.example.com;

   location ^~ /.well-known/acme-challenge/ {
      default_type "text/plain";
      root /var/www/letsencrypt;
   }

   location = /.well-known/acme-challenge/ {
      return 404;
   }

   location / {
      return 301 https://$host$request_uri;
   }
}

server {
   listen 443 ssl;
   listen 443 quic;
   http2 on;
   server_name example.com;

   ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
   ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
   ssl_session_timeout 1d;
   ssl_session_cache shared:MozSSL:10m; # about 40000 sessions
   ssl_session_tickets off;
   ssl_early_data on;

   quic_retry on;
   quic_gso on;

   # modern configuration
   ssl_protocols TLSv1.3;
   ssl_prefer_server_ciphers off;

   add_header Alt-Svc 'h3=":443"; ma=86400';

   location ^~ /.well-known/acme-challenge/ {
      default_type "text/plain";
      root /var/www/letsencrypt;
   }

   location = /.well-known/acme-challenge/ {
      return 404;
   }

   location / {
      return 301 https://www.example.com$request_uri;
   }
}

现在我们完成了基本的配置,可以使用 nginx -t 检查一下配置文件是否正确,然后启动一下服务(如果你起不来,就改下配置让他能起来先,比如注释掉第三个 server 块,因为它配置了证书,而这时候还没有证书,所以肯定找不到,但其实我感觉第三个 server 块也没有用,应该可以删?)。

然后我们就可以指定具体子域名的配置,比如我有一个 test.example.com 的子域名用于测试环境:

  
server {
   listen 443 ssl;
   listen 443 quic;
   http2 on;
   server_name test.example.com;

   ssl_certificate /etc/letsencrypt/live/test.example.com/fullchain.pem;
   ssl_certificate_key /etc/letsencrypt/live/test.example.com/privkey.pem;
   ssl_session_timeout 1d;
   ssl_session_cache shared:MozSSL:10m; # about 40000 sessions
   ssl_session_tickets off;
   ssl_early_data on;

   quic_retry on;
   quic_gso on;

   # modern configuration
   ssl_protocols TLSv1.3;
   ssl_prefer_server_ciphers off;

   add_header Alt-Svc 'h3=":443"; ma=86400';

   proxy_set_header X-Real-IP $remote_addr;
   proxy_http_version 1.1;
   proxy_set_header Upgrade $http_upgrade;
   proxy_set_header Connection $connection_upgrade;
   proxy_set_header Host $host;
   proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
   proxy_set_header X-Forwarded-Proto $scheme;
   proxy_set_header X-Forwarded-Ssl on;
   proxy_set_header Accept-Encoding gzip;
   proxy_redirect off;

   gzip on;
   gzip_min_length 10k;
   gzip_buffers 4 16k;
   gzip_http_version 1.1;
   gzip_comp_level 2;
   gzip_types text/plain application/x-javascript text/css application/xml text/javascript application/x-httpd-php application/javascript application/json;
   gzip_disable "MSIE [1-6]\.";
   gzip_vary on;

   client_max_body_size 20M;

   # 下面就是具体的转发规则了,这里只是随便写了个流量转发
   location / {
      proxy_pass http://127.0.0.1:8080/;
   }
}

由于上面我们已经配置过任意子域名对 /var/www/letsencrypt 的转发,所以现在我们就可以直接来签证书了:

  
$ certbot certonly --webroot -w /var/www/letsencrypt -d test.example.com

如果这里提示超时失败,可以多尝试几次,但是一个小时内只能失败 5 次,如果超了 5 次,则需要等一个小时后再试。

如果成功了,那么恭喜你,证书已经拿下了。而且 certbot 会启动定时任务,来自动帮你续证书。我们可以使用以下命令测试自动续签:

  
$ certbot renew --dry-run

还可以查看证书信息:

  
$ certbot certificates