Cara Konfigurasi Nginx Reverse Proxy + SSL Let’s Encrypt di Docker
Nginx adalah salah satu web server yang paling populer dan banyak digunakan di dunia. Selain sebagai web server, Nginx juga dapat digunakan sebagai reverse proxy server. Apa itu reverse proxy? Reverse proxy adalah sebuah server yang berfungsi untuk menerima permintaan (request) dari klien (browser) dan meneruskannya ke server lain, seperti web server atau aplikasi backend.
Sebagai reverse proxy, Nginx menerima permintaan HTTP dari klien dan mengirimkannya ke server backend yang sesuai. Ini memungkinkan kita untuk memiliki beberapa aplikasi berjalan di server yang berbeda, tetapi dapat diakses melalui satu titik masuk tunggal. Klien tidak perlu tahu di mana aplikasi sebenarnya berjalan, karena mereka berinteraksi melalui Nginx.
Dalam tutorial ini, kita akan membahas bagaimana cara deploy website HTML, mengkonfigurasi Nginx reverse proxy, serta menerapkan protokol HTTPS dengan sertifikat SSL dari Let’s Encrypt yang kesemuanya berjalan dengan menggunakan Docker container.
1. Install Docker
Langkah awal yang harus dilakukan yaitu install Docker terlebih dulu jika belum tersedia. Berikut ini langkah-langkah install Docker di Ubuntu.
Memasang key untuk repository Docker.
1 | curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg |
Memasang repository Docker.
1 2 3 | echo \ "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null |
Update repository.
1 | sudo apt update |
Menginstall Docker.
1 | sudo apt install docker-ce docker-ce-cli containerd.io -y |
2. Deploy Website
Langkah berikutnya yaitu kita deploy website HTML sederhana yang akan dijalankan dengan menggunakan Docker container.
Membuat direktori untuk project website, misal nginx-domainxyz
.
1 | mkdir nginx-domainxyz |
Masuk ke direktori nginx-domainxyz
.
1 | cd nginx-domainxyz |
Membuat direktori www
untuk penyimpanan semua file website.
1 | mkdir www |
Membuat file index.html
sederhana di dalam direktori www
.
1 | nano www/index.html |
Contoh isi file index.html
.
1 2 3 4 5 6 7 8 9 10 | <!DOCTYPE html> <html> <head> <title>Website XYZ</title> </head> <body> <h1>Selamat datang di website XYZ</h1> <p>Ini adalah contoh halaman web HTML yang dijalankan menggunakan Docker.</p> </body> </html> |
Membuat file docker-compose.yml
untuk build dan deploy website HTML di atas Docker container.
1 | nano docker-compose.yml |
Masukkan konfigurasi docker-compose.yml
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | version: '3.8' services: nginx-web: image: nginx:latest container_name: nginx-domainxyz ports: - "127.0.0.1:8080:80" networks: - app-net volumes: - ./www:/usr/share/nginx/html restart: always networks: app-net: external: true |
Penjelasan baris konfigurasi docker-compose.yml
untuk nginx-domainxyz
.
- Membuat container dengan nama
nginx-domainxyz
yang dibuat berdasarkan Docker imagenginx-latest
. - Website dapat diakses melalui IP 127.0.0.1 dan port 8080 pada host yang diarahkan ke port 80 pada container
nginx-domainxyz
. - Container terhubung ke network
app-net
yang berada di luar konfigurasi Docker Compose, harus dibuat terlebih dulu. - Direktori
www
di-mount ke direktori/usr/share/nginx/html
di dalam container.
Membuat network app-net
.
1 | sudo docker network create app-net |
Menjalankan konfigurasi docker-compose.yml
.
1 | sudo docker compose up -d |
Pesan yang ditampilkan jika proses docker compose
sudah selesai.
1 | Container nginx-domainxyz Started |
Memeriksa container yang berjalan saat ini, apakah sudah ada container dengan nama nginx-domainxyz
.
1 | sudo docker ps |
Contoh hasilnya.
1 2 | CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 1e9531cb0f0b nginx:latest "/docker-entrypoint.…" 56 seconds ago Up 54 seconds 127.0.0.1:8080->80/tcp nginx-domainxyz |
Menguji apakah website sudah dapat diakses melalui http://127.0.0.1:8080
.
1 | curl http://127.0.0.1:8080 |
Jika berhasil, akan menampilkan source code index.html
.
3. Membuat Reverse Proxy
Selanjutnya membuat container untuk Nginx reverse proxy.
Membuat direktori nginx-proxy
terlebih dulu, lalu masuk ke direktori tersebut.
1 2 3 | cd mkdir nginx-proxy cd nginx-proxy |
Membuat direktori nginx
, conf
, dan log
.
1 2 3 | mkdir nginx mkdir nginx/conf mkdir nginx/log |
Membuat file konfigurasi Nginx server block default.conf
. Jika mengakses (browsing) IP address server, konfigurasi ini yang akan dijalankan, menampilkan halaman default Nginx.
1 | nano nginx/conf/default.conf |
Masukkan konfigurasinya.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | server { listen 80 default_server; listen [::]:80 default_server; server_name _; root /usr/share/nginx/html; index index.html; location / { try_files $uri $uri/ =404; } access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; } |
Membuat file konfigurasi Nginx server block untuk website misal dengan nama domain domainxyz.com
.
1 | nano nginx/conf/domainxyz.com.conf |
Masukkan konfigurasinya.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | server { listen 80; listen [::]:80; server_name domainxyz.com www.domainxyz.com; location / { proxy_pass http://nginx-domainxyz; 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_set_header X-Forwarded-Host $server_name; } access_log /var/log/nginx/domainxyz.com_access.log; error_log /var/log/nginx/domainxyz.com_error.log; } |
Pada file konfigurasi di atas yang berhubungan dengan reverse proxy:
- Website dengan nama domain
domainxyz.com
dapat diakses melalui port 80 atau HTTP. - Permintaan akses ke website terebut,
location /
akan diteruskan kehttp://nginx-domainxyz
yang merupakan Nginx container yang menjalankan website HTML yang sebelumnya telah kita deploy.
Membuat file konfigurasi docker-compose.yml
untuk container nginx-proxy
.
1 | nano docker-compose.yml |
Masukkan konfigurasinya.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | version: '3.8' services: nginx-proxy: image: nginx:latest container_name: nginx-proxy ports: - "80:80" networks: - app-net volumes: - ./nginx/conf:/etc/nginx/conf.d - ./nginx/log:/var/log/nginx restart: always networks: app-net: external: true |
Maksud konfigurasi docker-composer.yml
di atas:
- Membuat container
nginx-proxy
yang berbasis Docker imagenginx:latest
. - Port 80 pada host dapat diakses dari semua IP address, termasuk Public IP dan diarahkan ke port 80 di container.
- Terhubung ke network
app-net
. - Mount direktori
conf
danlog
.
Menjalankan konfigurasi docker-compose.yml
untuk membuat container dan menjalankannya.
1 | sudo docker compose up -d |
Jika proses docker compose
selesai dan berhasil ditampilkan pesan:
1 | Container nginx-proxy Started |
Menampilkan container yang sedang berjalan untuk melihat apakah sudah ada container nginx-proxy
yang berjalan.
1 | sudo docker ps |
Contoh hasilnya.
1 2 | CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 4ddb651a03c5 nginx:latest "/docker-entrypoint.…" 33 seconds ago Up 32 seconds 0.0.0.0:80->80/tcp, :::80->80/tcp nginx-proxy |
Menguji mengakses website dari nama domain http://domainxyz.com
dengan curl
.
1 | curl http://domainxyz.com |
Hasilnya harus menampilkan source code index.html
, sama seperti pengujian lewat curl
sebelumnya.
Menguji mengakses http://IP-Server
, hasilnya halaman Welcome to nginx!
.
Menguji mengakses http://domainxyz.com
, hasilnya halaman index.html
yang berisi pesan Selamat datang di website XYZ
.
Sampai di sini, kita sudah berhasil melakukan deploy website dan mengkonfigurasikan Nginx reverse proxy dengan menggunakan Docker container.
4. Memasang SSL (HTTPS)
Deploy website dan konfigurasi Nginx reverse proxy sudah berjalan dengan baik, tetapi masih menggunakan protokol HTTP. Pada langkah terakhir ini, kita akan belajar bagaimana cara menerapkan protokol HTTPS atau memasang sertifikat SSL pada Nginx reverse proxy yang sebelumnya telah berjalan di Docker.
Membuat direktori certbot
untuk penyimpanan konfigurasi dan sertifikat SSL Let’s Encrypt. Posisi direktori saat ini masih di dalam direktori nginx-proxy
.
1 2 3 4 | cd ~/nginx-proxy mkdir certbot mkdir certbot/etc mkdir certbot/www |
Membuat file dhparam.pem
yang merupakan protokol kriptografi untuk proses pertukaran key antara server dan client pada TLS/SSL.
1 | openssl dhparam -out nginx/dhparam.pem 2048 |
Membuka kembali file docker-compose.yml
.
1 | nano docker-compose.yml |
Mengubah konfigurasi docker-compose.yml
seperti berikut ini:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | version: '3.8' services: nginx-proxy: image: nginx:latest container_name: nginx-proxy ports: - "80:80" - "443:443" networks: - app-net volumes: - ./nginx/conf:/etc/nginx/conf.d - ./nginx/dhparam.pem:/etc/nginx/dhparam.pem - ./nginx/log:/var/log/nginx - ./certbot/etc:/etc/letsencrypt - ./certbot/www:/var/www/certbot restart: always certbot: image: certbot/certbot:latest container_name: certbot volumes: - ./certbot/etc:/etc/letsencrypt - ./certbot/www:/var/www/certbot networks: - app-net networks: app-net: external: true |
Beberapa tambahan yang berhubungan dengan kebutuhan install SSL:
- Membuka port 443 (HTTPS).
- Mount direktori untuk
certbot
. - Membuat container untuk
certbot
, mount direktoricertbot
, dan menghubungkannya ke networkapp-net
.
Membuka kembali file Nginx server block domainxyz.com.conf
.
1 | nano nginx/conf/domainxyz.com.conf |
Mengubah konfigurasinya dengan menambahkan blok konfigurasi location /.well-known/acme-challenge/
untuk kebutuhan install SSL Let’s Encrypt. Hasilnya menjadi seperti di bawah ini:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | server { listen 80; listen [::]:80; server_name domainxyz.com www.domainxyz.com; location / { proxy_pass http://nginx-domainxyz; 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_set_header X-Forwarded-Host $server_name; } location /.well-known/acme-challenge/ { root /var/www/certbot; } access_log /var/log/nginx/domainxyz.com_access.log; error_log /var/log/nginx/domainxyz.com_error.log; } |
Karena sudah mengubah konfigurasi docker-compose
, kita perlu menghentikan container dan menjalankan kembali konfigurasinya untuk membuat ulang service nginx-proxy
.
1 2 | sudo docker compose down sudo docker compose up -d nginx-proxy |
Menguji kembali mengakses http://domainxyz.com
untuk memastikan website masih bisa diakses setelah mengubah konfigurasi.
Menjalankan simulasi permintaan SSL dengan menambahkan opsi --dry-run
pada bagian akhir perintah untuk domainxyz.com
yang dilakukan oleh container certbot
. Hal ini dilakukan untuk menguji semua konfigurasi yang berhubungan dengan permintaan SSL Let’s Encrypt apakah tidak ada lagi kekurangan atau kesalahan.
1 2 3 4 5 6 7 8 | sudo docker compose run \ --rm certbot certonly \ --webroot --webroot-path /var/www/certbot \ -d domainxyz.com -d www.domainxyz.com \ --non-interactive \ -m admin@domainxyz.com \ --agree-tos --no-eff-email \ --dry-run |
Jika simulasi berhasil ditampilkan pesan seperti berikut ini:
1 2 3 | Account registered. Simulating a certificate request for domainxyz.com and www.domainxyz.com The dry run was successful. |
Selanjutnya menjalankan ulang perintah certbot
di atas tanpa opsi perintah --dry-run
.
1 2 3 4 5 6 7 | sudo docker compose run \ --rm certbot certonly \ --webroot --webroot-path /var/www/certbot \ -d domainxyz.com -d www.domainxyz.com \ --non-interactive \ -m admin@domainxyz.com \ --agree-tos --no-eff-email |
Jika permintaan SSL Let’s Encrypt berhasil ditampilkan pesan seperti berikut ini:
1 2 3 4 5 6 7 | Requesting a certificate for domainxyz.com and www.domainxyz.com Successfully received certificate. Certificate is saved at: /etc/letsencrypt/live/domainxyz.com/fullchain.pem Key is saved at: /etc/letsencrypt/live/domainxyz.com/privkey.pem This certificate expires on 2024-01-13. These files will be updated when the certificate renews. |
Menampilkan isi direktori ‘certbot/etc/’ untuk memastikan sertifikat SSL sudah tersedia di direktori tersebut.
1 | sudo ls certbot/etc/live/domainxyz.com |
Contoh hasilnya.
1 | cert.pem chain.pem fullchain.pem privkey.pem README |
Membuka kembali file Nginx server block domainxyz.com.conf
.
1 | nano nginx/conf/domainxyz.com.conf |
Menambahkan blok konfigurasi untuk port 443 dan redirect port 80 (HTTP) ke https://domainxyz.com
. Hasil akhirnya seperti di bawah ini:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | server { listen 443 ssl; listen [::]:443 ssl; server_name domainxyz.com www.domainxyz.com; ssl_certificate /etc/letsencrypt/live/domainxyz.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/domainxyz.com/privkey.pem; ssl_dhparam /etc/nginx/dhparam.pem; location / { proxy_pass http://nginx-domainxyz; 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_set_header X-Forwarded-Host $server_name; } access_log /var/log/nginx/domainxyz.com_access.log; error_log /var/log/nginx/domainxyz.com_error.log; } server { listen 80; listen [::]:80; server_name domainxyz.com www.domainxyz.com; location / { return 301 https://domainxyz.com$request_uri; } location /.well-known/acme-challenge/ { root /var/www/certbot; } } |
Setelah itu, restart container nginx-proxy
, karena telah melakukan perubahan pada konfigurasi Nginx perlu untuk reload konfigurasi.
1 | sudo docker compose restart nginx-proxy |
Menguji hasil pemasangan SSL pada Nginx reverse proxy dengan mengakses http://domainxyz.com
akan secara otomatis redirect ke https://domainxyz.com
.
Kita telah berhasil deploy website, konfigurasi Nginx reverse proxy, dan memasang sertifikat SSL untuk menerapkan protokol HTTPS.
5. Menambah Website Baru
Jika ingin menambah website atau domain baru langkah yang perlu dilakukan yaitu:
- Deploy website seperti pada Langkah 2.
- Membuat file konfigurasi Nginx reverse proxy, lalu restart container nginx-proxy.
- Melakukan permintaan SSL.
- Memperbarui konfigurasi Nginx untuk menambahkan konfigurasi SSL, lalu restart container nginx-proxy.
6. Memperbarui Sertifikat SSL
Sertifikat SSL dari Let’s Encrypt hanya berlaku selama 90 hari. Oleh karena itu perlu dilakukan perpanjangan atau permintaan sertifikat SSL yang baru jika mendekati masa habis berlakunya.
Perintahnya cukup mudah, cukup menjalankan certbot renew
dari container certbot
.
1 | sudo docker compose run --rm certbot renew |
Penutup
Dengan mengikuti langkah-langkah di atas, kita dapat mengkonfigurasi Nginx reverse proxy dengan sertifikat SSL dari Let’s Encrypt yang kesemuanya dijalankan di atas Docker container. Kunci utamanya ada pada pemahaman tentang konfigurasi docker-compose.yml
yang mendefinisikan service dan container yang dibangun. Sementara untuk konfigurasi Nginx reverse proxy dan SSL sama saja seperti konfigurasi tanpa menggunakan Docker.
Semoga tutorial ini bermanfaat bagi teman-teman semua.
Selamat mencoba 🙂
misi mas apakah cara ini juga cocok untuk rest api?
iya, bisa juga.
mas saya pas try SSLnya ada error
Certbot failed to authenticate some domains (authenticator: webroot)
ini knp ya ?
mungkin ada pencerahan
Terima kasih
coba ikuti petunjuk ini https://bobcares.com/blog/certbot-failed-to-authenticate-some-domains-apache/