Development Skills
  • Development Skills
  • Server-side
    • Reverse SSH
    • Let's encrypt with Nginx
    • Miniconda
    • OpenSSL
    • Windows Skills
    • Crobtab
  • Set up Workspace
    • Setup basic environment
  • Bandit - Check your code's safeness
    • Introduction
    • Getting Started
    • Usage
    • Banditfile
    • Tailor-made testing
    • Tailor-made blacklist
    • Tailor-made formatter
    • Reference
Powered by GitBook
On this page
  • Let’s Encrypt + Nginx + Docker
  • Nginx
  • Configure files for Nginx
  • Let's Encrypt
  • References
  1. Server-side

Let's encrypt with Nginx

In this article, I will share the way of using nginx, let’s encrypt and docker/docker-compose to deploy ssl with automatically cert-renew.

PreviousReverse SSHNextMiniconda

Last updated 5 years ago

Let’s Encrypt + Nginx + Docker

is a web server that I used to replace . Since I have to deploy my application which will provide SSL connection through the internet, I utilize Let’s Encrypt, a that provides free for (TLS) encryption.

Apart from that, docker and docker-compose will be used to setup my environment which is really really convenient tools for deployment. I guess you should already know what this items are so I am not going to explain how to use these tools here.

Given the directory structure like this:

/
|- certs
|- certs-data
|- conf.d
|- log
    |- renew
    |- nginx
|- www

Nginx

Create a docker-compose.yml file under root directory.

version: '3'
services:
  nginx:
    container_name: nginx
    image: nginx:latest
    restart: always
    volumes:
      - ./www:/usr/share/nginx/html
      - ./conf.d:/etc/nginx/conf.d
      - ./log:/var/log/nginx
      - ./certs:/etc/letsencrypt
      - ./certs-data:/var/lib/letsencrypt
    environment:
    TZ: Asia/Hong_Kong
    ports:
      - 80:80
      - 443:443

Configure files for Nginx

Create and configure Nginx configure in cond.d directory.

You can apply proxy_pass in location if you need.

Configure 1

  • normal.conf

server {
    listen       80;
    server_name  <url>;

    #charset koi8-r;
    access_log  /var/log/nginx/host.access.log  main;

    location / {
        rewrite ^ https://$host$request_uri? permanent;
    }

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

    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    #
    #location ~ \.php$ {
    #    root           html;
    #    fastcgi_pass   127.0.0.1:9000;
    #    fastcgi_index  index.php;
    #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
    #    include        fastcgi_params;
    #}

    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    #location ~ /\.ht {
    #    deny  all;
    #}
}

Configure 2

  • ssl.conf

server {
    listen      443           ssl http2;
    listen [::]:443           ssl http2;
    server_name               <url>;

    ssl                       on;

    add_header                Strict-Transport-Security "max-age=31536000" always;

    ssl_session_cache         shared:SSL:20m;
    ssl_session_timeout       10m;

    ssl_protocols             TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;
    ssl_ciphers               "ECDH+AESGCM:ECDH+AES256:ECDH+AES128:!ADH:!AECDH:!MD5;";

    ssl_stapling              on;
    ssl_stapling_verify       on;
    resolver                  8.8.8.8 8.8.4.4;

    ssl_certificate           /etc/letsencrypt/live/<url>/fullchain.pem;
    ssl_certificate_key       /etc/letsencrypt/live/<url>/privkey.pem;
    ssl_trusted_certificate   /etc/letsencrypt/live/<url>/chain.pem;

    access_log                /dev/stdout;
    error_log                 /dev/stderr info;

    # other configs
    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }

    # proxy the PHP scripts to Apache listening on 127.0.0.1:80
    #
    #location ~ \.php$ {
    #    proxy_pass   http://127.0.0.1;
    #}

}

Let's Encrypt

Sign Cert

Navigate to the root directory and run the following command to sign the certificate from Let’s Encrypt.

sudo docker run -it --rm \
    -v $PWD/certs:/etc/letsencrypt \
    -v $PWD/certs-data:/var/lib/letsencrypt deliverous/certbot certonly\
    --webroot --webroot-path=/var/lib/letsencrypt -d <domain>
    

Note! You have to use full path in Volume Mirror

Renew

If you want to automatically renew the cert, you can use crontab to do the schedule job. You can use contab -e to do the job but this will only apply in the user-level. I would recommend you to do this in system-level — edit the config directly in /etc/crontab.

You can use following script to schedule the task. it will run every 15 days.

Note! Cert can only be renewed within last 30 days.

0 0 */15 * * docker run -it --rm -v /root/nginx/certs:/etc/letsencrypt -v /root/nginx/certs-data:/var/lib/letsencrypt -v /root/nginx/letsencryptlog:/var/log/letsencrypt deliverous/certbot renew --webroot --webroot-path=/var/lib/letsencrypt >> renew_log.log &&  docker kill -s HUP nginx >/dev/null 2>&1

References

這個『 crontab -e 』是針對使用者的 cron 來設計的,如果是『系統的例行性任務』時, 該怎麼辦呢?是否還是需要以 crontab -e 來管理你的例行性工作排程呢?當然不需要,你只要編輯 /etc/crontab 這個檔案就可以啦!有一點需要特別注意喔!那就是 crontab -e 這個 crontab 其實是 /usr/bin/crontab 這個執行檔,但是 /etc/crontab 可是一個『純文字檔』喔!你可以 root 的身份編輯一下這個檔案哩! -

The renew command will take a look at all active certificates and renew those who are close to expiring — which is currently defined as 30 days before the expiration date. If your certificates aren’t due for renewal yet, the client won’t renew them. The reason why a daily cronjob is recommended is in order to avoid issues caused by service downtime on Let’s Encrypt’s end, or any issues your server might have. If you, for example, run the cronjob just once every month or every two months, and the service just happens to be down during those times, you’ll end up with an expired certificate eventually. By doing it daily instead, Let’s Encrypt would have to be down for 30 consecutive days for that to happen, which is rather unlikely. -

Nginx
Apache
certificate authority
X.509
certificates
Transport Layer Security
鳥哥的 Linux 私房菜 — 第十五章、例行性工作排程(crontab)
[SOLVED] How often to renew?
Docker + Nginx + LetsEncrypt
Let’s Encrypt TLS Certificates via Docker and Certbot
佛心來了,快用 Let’s Encrypt 免費 SSL 憑證幫網站加密吧!
deliverous/certbot
nginx配置location总结及rewrite规则写法 | Sean’s Notes