nginx reverse proxy 用 letsencrypt 加 SSL

我習慣喺隻 web server 之前放一隻 reverse proxy,而哩隻 reverse proxy 我通常係用 nginx,依家要做嘅嘢係:喺隻 nginx 加 SSL 俾不同嘅 websites (即係 multiple domains),而隻 SSL cert 就用 Let’s Encrypt 提供嘅免費服務。Let’s Encrypt 係免費嘅(有啲業界認為佢係搞破壞,我就舉手歡迎 😜),唯一嘅問題係每 90 天就要 renew 一次。

我哋嚟睇下點做:

哩個係我隻 Google Compute Engine 嘅 dashboard,用緊隻 reverse proxy 叫 inst-1-nginx。 我重新 create 一隻 nginx 然後慢慢 migrate 啲目前嘅 websites 去隻新 nginx,由 http 轉用 https。  立即多咗一隻 nginx(inst-2-nginx)。
Login 隻 nginx 初次 login 畫面 改番個 Time Zone 等啲時間 logs 易睇啲。
好容易,冇咩難度。 雖然隻 server 喺台灣,我習慣 sync 個時間,使用同一時區(香港)。 記低個 storage 使用情淘,目前 sda1 用咗 13%
安裝 nginx 閃下眼就裝好 nginx 1.10.3 用隻 browser  去試下
加個 default 嘅 configuration file 俾隻 nginx:/etc/nginx/conf.d/proxy.conf 內容好簡單(如圖),日後有咩 global 嘅改動就可以喺哩度搞。 可以開始 migrate 第一個 website,首先喺 /etc/nginx/sites-enabled create 一個 conf 檔案。
Create 一個 http (port 80) 嘅 conf 檔案,然後 restart 隻 nginx,然後就可以去試下 visit 個 website。我冇寫點樣改個 domain 嘅 Name Server 紀錄(A-Record),各人唔同,我當你識。😁 輪到搞 Let’s Encrypt,先去下載隻 certbot-auto script,我放喺 /etc/nginx/cerbot 之內。 開頭試咗好多次都 cert 唔倒,唔知咩原因,我估計係 Let’s Encrypt 用嘅 NS record 未更新。
哩個係成功 cert 到嘅畫面。 List 個檔案夾睇下啲 cert 檔案 可以修改之前嗰隻 conf file 去加番同 https 有關嘅嘢,再 restart 一下隻 nginx 就 OK 哂!
輪到搞自動 renew 張 cert,我哋會用到 supervisor 插件,先去 install 一下。 用 ls -l cron* 睇下目前有啲咩嘢 cron jobs。cron.monthly 係吉嘅,我哋就係要將個自動 renew 放喺每個月一號 3:45AM 執行。 去 cron.monthly 檔案夾 create 一個叫 letsencrypt 嘅檔案,叫咩名冇咩所謂,容易記嘅就好。
內容如上,renew > stop nginx > start nginx,即係更新,再 reload 張 cert。 再後,將個 script 設為 executable,完成!😎

以下係啲 Scripts:

攞 cert:

root@inst-2-nginx:/etc/nginx/certbot# ./certbot-auto certonly --standalone -d jb5.marche.com.hk
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Obtaining a new certificate
Performing the following challenges:
tls-sni-01 challenge for jb5.marche.com.hk
Waiting for verification...
Cleaning up challenges
IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/jb5.marche.com.hk/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/jb5.marche.com.hk/privkey.pem
   Your cert will expire on 2017-11-15. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot-auto
   again. To non-interactively renew *all* of your certificates, run
   "certbot-auto renew"
 - If you like Certbot, please consider supporting our work by:
   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le
root@inst-2-nginx:/etc/nginx/certbot#

 

http conf file:

server {
        listen          80;
        server_name     jb5.marche.com.hk;
        #access_log     /var/log/nginx/marche.access.log;
        #error_log      /var/log/nginx/marche.error.log debug;
        location / {
                proxy_pass              http://iis1-apps;
                proxy_redirect          off;
                proxy_set_header        Host                    $host;
                proxy_set_header        X-Real-IP               $remote_addr;
                proxy_set_header        X-Forwarded_For         $proxy_add_x_forwarded_for;
                proxy_max_temp_file_size        0;
                client_max_body_size            512m;
                client_body_buffer_size         128k;
                proxy_connect_timeout           90;
                proxy_send_timeout              90;
                proxy_read_timeout              90;
                proxy_buffer_size               4k;
                proxy_buffers                   4 32k;
                proxy_busy_buffers_size         64k;
                proxy_temp_file_write_size      64k;
                #proxy_cache            one;
                #proxy_cache_key                $host;
                #proxy_cache_valid      200 1h;
                #proxy_cache_use_stale  error timeout invalid_header;
        }
}

 

https conf file:

## Handle http:// connections
server  {
  listen		80;
  server_name	jb5.marche.com.hk;
  return 301 https://$server_name$request_uri;
}

## Handle https:// connections
server  {
  listen		443 ssl;
  server_name	y5.directoutput.com.hk;

  access_log	/var/log/nginx/jb5.marche.access.log;
  error_log	/var/log/nginx/jb5.marche.error.log debug;

    ##
    # SSL Settings
    ##

    ssl            on;

    # Set cert locations
    ssl_certificate    /etc/letsencrypt/live/jb5.marche.com.hk/fullchain.pem;
    ssl_certificate_key    /etc/letsencrypt/live/jb5.marche.com.hk/privkey.pem;

    ssl_session_cache    shared:SSL:10m;
    ssl_session_timeout    10m;
    ssl_protocols        SSLv3 TLSv1 TLSv1.1 TLSv1.2;

    ssl_ciphers            RC4:HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers    on;

    keepalive_timeout    60;

    location / {


        ##
        # Proxy settings
        ##

        proxy_pass			http://10.240.0.3;

        # Convert all inbound request into http:// request to upstream server
        proxy_redirect		http:// $scheme://;

        proxy_set_header    Accept-Encoding "";
        proxy_set_header	Host				$host;
        proxy_set_header    X-Real-IP			$remote_addr;
        proxy_set_header    X-Forwarded-For		$remote_addr;
        proxy_set_header    X-Forwarded-Proto    $scheme;


        add_header        Front-End-Https    on;

        proxy_max_temp_file_size    0;
        proxy_connect_timeout        90;
        proxy_send_timeout        90;
        proxy_read_timeout        90;
        proxy_buffer_size        4k;
        proxy_buffers            4 32k;
        proxy_busy_buffers_size    64k;
        proxy_temp_file_write_size    64k;

        client_max_body_size        512m;
        client_body_buffer_size    512k;

        ##
        # Filter response settings
        ##

        # Filter all response content with http://jb5.marche.com.hk into https://jb5.marchet.com.hk
        sub_filter	http://jb5.marche.com.hk/ https://jb5.marche.com.hk/;

        # Filter not only response type text/html but also text/css and text/xml
        sub_filter_types    text/css text/xml;

        # Filter all response
        sub_filter_once    off;
    }
}

 

cron.monthly:

#!/bin/bash
 
/etc/nginx/certbot/certbot-auto renew  --text --no-self-upgrade > /var/log/letsencrypt/letsencrypt_cron.log 2>&1
 
supervisorctl stop nginx
supervisorctl start nginx

P.S. 如果 cert 的時候出現 error: can not bind to IPv4 or IPv6,你要先停咗隻 nginx: systemctl stop nginx,cert 完再開番: systemctl start nginx,因為 –standalone 會用自己嘅 web service,同 nginx 有沖突。