Cara proteksi Nginx dengan Let’s Encrypt di Ubuntu 18.04
Tags: nginx, ubuntu, indonesia, linux
Published: 2021-03-10 16:30:36

Let’s Encrypt dikembangkan oleh Internet Security Research Group (ISRG) yang memungkinkan semua website di internet memperoleh sertifikat SSL dengan gratis dan terpercaya.

Pembahasan dalam tutorial ini akan menunjukkan cara memproteksi Nginx server dengan Let’s Encrypt menggunakan certbot tool pada Ubuntu 18.04.

## Persiapan

Pastikan beberapa hal berikut ini sudah dilakukan lebih dulu.

- Domain sudah diset mengarah ke IP server. Artikel ini akan menggunakan domain `contoh.com`
- Nginx sudah terpasang. Jika belum, silahkan ikuti langkahnya pada artikel berikut ini.

{% post https://dev.to/erolj/cara-install-nginx-di-ubuntu-18-04-43k2 %}

## Instalasi Certbot

Certbot adalah tool yang akan memudahkan dalam proses membuat, memperpanjang, dan mengatur penggunaan sertifikat SSL dari Let’s Encrypt.

Untuk mendaftarkan certbot, jalankan perintah berikut secara berurutan. Perintah pada baris terakhir akan membutuhkan waktu yang agak lama, harap sabar menunggu hingga selesai.
```
sudo apt install certbot
sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048
```

## Pendaftaran sertifikat SSL dari Let’s Encrypt

Jalankan perintah berikut secara berurutan.
```
mkdir -p /var/lib/letsencrypt/.well-known
chgrp www-data /var/lib/letsencrypt
chmod g+s /var/lib/letsencrypt
```

Langkah selanjutnya adalah dengan membuat 2 (dua) buah file snippet yang dibutuhkan, yaitu file `letsencrypt.conf` dan `ssl.conf`. Untuk membuat file yang pertama, jalankan perintah ini.
```
vi /etc/nginx/snippets/letsencrypt.conf
```

Pada editor teks yang terbuka, salin kode dibawah ini.
```
location ^~ /.well-known/acme-challenge/ {
  allow all;
  root /var/lib/letsencrypt/;
  default_type "text/plain";
  try_files $uri =404;
}
```

Simpan perubahan, dan lanjutkan dengan menjalankan perintah berikut ini untuk membuat file yang kedua.
```
vi /etc/nginx/snippets/ssl.conf
```

Pada editor teks yang terbuka, salin kode berikut.
```
ssl_dhparam /etc/ssl/certs/dhparam.pem;

ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS';
ssl_prefer_server_ciphers on;

ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 30s;

add_header Strict-Transport-Security "max-age=15768000; includeSubdomains; preload";
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;
```

Simpan perubahan, selanjutnya tambahkan file `letsencrypt.conf` pada server block milik domain `contoh.com`
```
sudo vi /etc/nginx/sites-available/contoh.com
```

Tambahkan baris kode berikut ini dalam file tersebut.
```
  include snippets/letsencrypt.conf;
```

Konfigurasinya akan terlihat seperti ini.
```
server {
  listen 80;
  server_name example.com www.example.com;

  include snippets/letsencrypt.conf;
}
```

Simpan perubahannya, dan jalankan perintah berikut untuk mengaktifkannya.
```
sudo ln -s /etc/nginx/sites-available/contoh.com /etc/nginx/sites-enabled/
```

Jika muncul pesan “File exists” seperti dibawah ini, abaikan saja dan lanjutkan ke langkah berikut. Pesan ini berarti symbolic link untuk file ini sudah ada, dan itu bukanlah sebuah masalah.
```
ln: failed to create symbolic link '/etc/nginx/sites-enabled/contoh.com': File exists
```

Langkah berikutnya, restart Nginx.
```
sudo systemctl restart nginx
```

Sesudah restart, jalankan perintah berikut untuk mendaftarkan sertifikat SSL untuk server block domain yang baru dibuat diatas.
```
sudo certbot certonly --agree-tos --email admin@contoh.com --webroot -w /var/lib/letsencrypt/ -d contoh.com -d www.contoh.com
```

Output yang dihasilkan apabila sertifikat SSL berhasil diperoleh, akan terlihat seperti dibawah ini.
```
IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/contoh.com/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/contoh.com/privkey.pem
   Your cert will expire on 2019-07-28. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot
   again. To non-interactively renew *all* of your certificates, run
   "certbot renew"
 - Your account credentials have been saved in your Certbot
   configuration directory at /etc/letsencrypt. You should make a
   secure backup of this folder now. This configuration directory will
   also contain certificates and private keys obtained by Certbot so
   making regular backups of this folder is ideal.
 - 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
```

Sekarang setelah sertifikat SSL sudah diperoleh, edit kembali file konfigurasi server block.
```
sudo vi /etc/nginx/sites-available/contoh.com
```

Untuk editor teks yang muncul, salin dan update dengan menggunakan kode dibawah ini.
```
server {
    listen 80;
    server_name www.contoh.com contoh.com;

    root /var/www/contoh.com/public_html;

    index index.html;

    include snippets/letsencrypt.conf;

    access_log /var/log/nginx/contoh.com.access.log;
    error_log /var/log/nginx/contoh.com.error.log;

    location / {
        try_files $uri $uri/ =404;
    }

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

server {
    listen 443 ssl http2;
    server_name www.contoh.com;

    root /var/www/contoh.com/public_html;

    index index.html;

    ssl_certificate /etc/letsencrypt/live/contoh.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/contoh.com/privkey.pem;
    ssl_trusted_certificate /etc/letsencrypt/live/contoh.com/chain.pem;
    include snippets/ssl.conf;
    include snippets/letsencrypt.conf;

    return 301 https://contoh.com$request_uri;
}

server {
    listen 443 ssl http2;
    server_name contoh.com;

    root /var/www/contoh.com/public_html;

    index index.html;

    ssl_certificate /etc/letsencrypt/live/contoh.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/contoh.com/privkey.pem;
    ssl_trusted_certificate /etc/letsencrypt/live/contoh.com/chain.pem;
    include snippets/ssl.conf;
    include snippets/letsencrypt.conf;

    # . . . kode lainnya
}
```

Dengan kode diatas, domain `contoh.com` akan dipaksa menggunakan https sekaligus redirect akses menggunakan `www.contoh.com` ke `contoh.com` (non-www).

Simpan perubahannya dan reload Nginx.
```
sudo systemctl reload nginx
```

Buka browser, lalu akses dengan menggunakan `https://contoh.com`

## Perpanjang otomatis sertifikat SSL

Sertifikat SSL Let’s Encrypt berlaku selama `90` hari. Untuk membuatnya otomatis memperpanjang sertifikat yang akan habis masa berlakunya, certbot membuat sebuah cronjob yang berjalan sebanyak 2x tiap hari, dan akan langsung memperpanjang sertifikat yang akan habis masa berlaku dalam `30` hari.

Berikut ini adalah cara untuk membuat cronjob yang akan memperpanjang otomatis sertifikat SSL yang akan expired, sekaligus melakukan reload pada Nginx.

Pertama, edit cronjob milik certbot dengan perintah ini.
```
sudo vi /etc/cron.d/certbot
```

Ubah baris cronjob yang sudah ada menjadi seperti dibawah ini.
```
0 */12 * * * root test -x /usr/bin/certbot -a \! -d /run/systemd/system && perl -e 'sleep int(rand(3600))' && certbot -q renew --renew-hook "systemctl reload nginx"
```

Simpan perubahan diatas, selanjutnya untuk mengecek proses perpanjangan sertifikat SSL, bisa dicoba dengan perintah `--dry-run` berikut ini.
```
sudo certbot renew --dry-run
```

Jika tidak muncul error, maka outputnya akan terlihat seperti ini.
```
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
** DRY RUN: simulating 'certbot renew' close to cert expiry
**          (The test certificates below have not been saved.)

Congratulations, all renewals succeeded. The following certs have been renewed:
  /etc/letsencrypt/live/contoh.com/fullchain.pem (success)
** DRY RUN: simulating 'certbot renew' close to cert expiry
**          (The test certificates above have not been saved.)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

IMPORTANT NOTES:
 - Your account credentials have been saved in your Certbot
   configuration directory at /etc/letsencrypt. You should make a
   secure backup of this folder now. This configuration directory will
   also contain certificates and private keys obtained by Certbot so
   making regular backups of this folder is ideal.
```

## Penutup

Sampai pada langkah ini, Let’s Encyrpt sudah terpasang dan akan secara otomatis memperpanjang sertifikat SSL sebelum masa aktif berakhir.

Untuk penjelasan detail bagaimana cara pengaturan Server Block milik Nginx, silahkan lihat artikel berikut ini.

{% post https://dev.to/erolj/cara-membuat-server-block-nginx-di-ubuntu-18-04-3cfk %}