Pengalaman Setting Reverse Proxy Traefik oleh Pemula
Saya sering melihat orang-orang berbagi cara membuat reverse proxy untuk menjalankan layanan online, tetapi saya menganggapnya terlalu rumit. Bukankah cukup menggunakan tunnel dari Cloudflare? Namun, setelah saya mencoba sendiri, saya menyadari bahwa itu tidak sesulit yang saya kira (setelah saya mengerti konsepnya).
Saya tidak punya alasan khusus untuk membuat reverse proxy, karena saya hanya meminjam internet dari orang lain dan tidak memiliki IP publik sendiri. Bagi mereka yang memiliki IP publik, reverse proxy bisa membantu mengakses layanan online dengan DDNS.
Software reverse proxy pun ada bermacam-macam, yang paling terkenal adalah nginx dan traefik. Kalau nginx saya kira gara-gara nginx juga sebagai webserver jadi sekalian, meskipun kalau saya tengok, hampir semua webserver bisa berfungsi sebagai reverse proxy.
Alasan saya mencoba reverse proxy
Saya ingin belajar tentang reverse proxy, jadi saya memilih Traefik sebagai alatnya. Saya tidak tertarik dengan Nginx atau yang lainnya. Saya tahu reverse proxy bisa digunakan untuk mengekspos layanan lokal, load balancing, dan keamanan, tetapi saya tidak membutuhkannya. Saya sudah menggunakan tunnel Cloudflare yang memberikan SSL/TLS, meskipun hanya dalam mode fleksibel. Saya rasa itu sudah cukup.
Cloudflare tunnel + Traefik?
Hampir semua layanan yang berjalan di RPi0W saya adalah docker, dan
untuk mengeksposnya, saya cukup memetakan port saja, dan pada pengaturan
tunnel tinggal memanggil localhost:port
.
Muncul masalah lain, yaitu cloudflared lama saya yang menggunakan network_mode=host, yang memudahkan saya untuk mengatur tunnel. Sebenarnya, saya hanya perlu memasang port saja. Namun, ketika menggunakan Traefik, saya sekarang berpikir tentang bagaimana caranya agar saya tidak menggunakan host networking dan menggunakan network internal dari Docker. Tentu saja, saya akan kehilangan akses langsung dari host ke Docker ataupun sebaliknya.
Setup Traefik dan Providernya
Mari kita lanjutkan untuk setup (pengaturan) nya, berikut contekan dari docker-compose yang saya gunakan:
version: "3"
services:
cloudflared:
container_name: cloudflared-tunnel
image: cloudflare/cloudflared
restart: unless-stopped
command: tunnel run
environment:
- TUNNEL_TOKEN=<YOUR TUNNEL TOKEN>
networks:
- cftunnel
traefik:
image: traefik/latest
container_name: traefik
restart: always
networks:
- cftunnel
- traefiktun
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro # provider docker harus expose ini
- ./traefik.yaml:/traefik.yaml:ro # static config
- ./dynamic_conf.yaml:/dynamic_conf.yaml # dynamic config
- ./cert:/cert:ro # untuk origin certificate
networks:
cftunnel:
traefiktun:
external: true
Contoh isi docker-compose.yml
Karena di sini kita membutuhkan external network, maka kita
perlu terlebih dahulu membuat network-nya pada Docker dengan perintah
docker network create traefiktun
. Untuk konfigurasi
statisnya, saya isi tentang logging, provider (Docker dan file), dan
entrypoints.
log:
level: DEBUG # untuk keperluan testing & monitoring, bisa diganti jika tidak diperlukan.
entryPoints:
websecure:
address: ":443"
providers:
docker:
endpoint: "unix:///var/run/docker.sock"
exposedByDefault: false
file:
filename: dynamic_conf.yaml
Isi dari traefik.yaml
Secara default, alasan menggunakan file provider adalah dynamic load, di mana Traefik secara berkala akan melakukan cek terhadap file tersebut, apakah diubah atau tidak, dan akan memperbarui konfigurasi Traefik tanpa harus melakukan restart.
Isi dari dynamic_conf.yaml
saya masukkan pengaturan
Certificate Origin Server dari Cloudflare. Untuk pembuatan
Origin Server cukup mudah, jadi saya tidak menuliskannya. Silakan cek
dokumentasi Cloudflared.
tls:
stores:
default:
defaultCertificate:
certFile: /cert/mydomain.tld.pem
keyFile: /cert/mydomain.tld.key
certificates:
- certFile: /cert/mydomain.tld.pem
keyFile: /cert/mydomain.tld.key
isi daru dynamic_conf.yaml
Kemudian, untuk mengatur per-service pada Docker, kita hanya
perlu menambahkan label
dan network
saja. Kita
tidak perlu memetakan port pada Docker karena Traefik secara otomatis
akan menggunakan port yang di-expose (sesuai Dockerfile-nya)
untuk komunikasi secara privat. Misalnya, saya ingin menjalankan
ntfy
:
version: "3"
services:
ntfy:
image: binwiederhier/ntfy
container_name: ntfy
command:
- serve
volumes:
- /var/cache/ntfy:/var/cache/ntfy
- ./ntfy-data:/etc/ntfy
restart: always
Setup minimal ntfy
Mari kita tambahkan label
dan network
seperti berikut:
labels:
- traefik.enable=true
- traefik.http.routers.ntfy.rule=Host(`sub.mydomain.tld`) # sesuaikan dengan nama domain
- traefik.http.routers.ntfy.tls=true # wajib karena entrypoint hanya menggunakan websecure / https
networks:
- traefiktun
Baris tambahan agar terhubung dengan traefik
Perlu diketahui bahwa ntfy
dalam
traefik.http.routers.**ntfy**.tls
merupakan label dinamis,
jadi bisa saja saya menamai
traefik.http.routers.**notif**.tls
, yang penting konsisten
pada setiap layanan. Setelah kita jalankan, maka traefik akan secara
otomatis menambahkan route untuk ntfy
.
Setup Cloudflared
Setelah semua berjalan, kita bisa lanjut ke pengaturan tunnel di Cloudflare. Silakan tambahkan Public Hostname pada Cloudflare Zero Trust, sebagai contoh seperti ini:
Pengaturan tunnel di Cloudflare Zero Trust
Untuk layanan kita, sebaiknya langsung memanggil
https://traefik
karena traefik
dan
cloudflared
berada dalam satu network di
docker-compose.yml
.
Kemudian, di pengaturan TLS, kita perlu mengatur Origin Server
Name dengan hostname yang sudah kita atur. Di sini, saya
berikan contoh.testeraphy.cf
. Pada bagian HTTP2
connection, kita bisa mengaktifkannya karena kita sudah menggunakan
https dan mengaktifkan TLS menjadi Full(Strict). Kalau
tidak diaktifkan juga tidak apa-apa.
Selesai! Kamu sudah bisa menggunakan Traefik untuk keperluan reverse proxy aplikasi Docker!
Temuan - temuan
Mudah? Tidak juga. Di atas adalah contoh yang mudah, karena gambar
ntfy
secara default sudah mengekspos port 80, dan
saya juga tidak menjelaskan bagaimana jika saya ingin mengekspos
service yang berjalan lokal di luar Docker.
Pada bagian ini saya akan mencoba temuan saya ketika mengatur Traefik+cloudflared yang mungkin berguna.
App tidak mengekspos port, perlukah mapping port?
Tidak, daripada harus melakukan mapping port (dan tidak akan diakses juga di local server) kamu bisa mengekspos port secara manual dengan menambahkan berita seperti berikut pada docker compose.
expose:
- 8080
mengekspos port jika tidak diberikan ketika build
Kenapa tidak mapping port? karena traefik secara pintar akan
menggunakan port yang sudah diekspos untuk keperluan reverse proxy.
Langkah lain adalah dengan menambahkan label
traefik.http.services.ntfy.loadbalancer.server.port=80
(Misalnya, jika aplikasi tersebut berjalan pada port 80.).
Kecuali jika layanan Docker kamu ingin bisa diakses dari localhost, ya harus di-expose.
Akses localhost dari dalam docker
Seperti yang sudah ditulis sebelumnya, kita dengan mudah bisa ‘mengakali’ ini dengan menggunakan host networking. Namun karena di sini kita ingin mengisolasi jaringan di dalam docker, maka untuk service traefik kita tambahkan:
extra_hosts:
- "host.docker.internal:host-gateway"
baris tambahan untuk akses localhost dari dalam docker
Alhasil, kita bisa membuat layanan reverse proxy di luar Docker
dengan menggunakan alamat host.docker.internal
.
Reverse proxy untuk service diluar docker
Bagian ini masuk ke dalam bagian konfigurasi dinamis Traefik, yang
mana kita akan menggunakan file dynamic_conf.yaml
. Sebagai
contoh, saya akan membuat reverse proxy dari Prometheus yang tidak
berjalan di dalam Docker, maka di dalam dynamic_conf.yaml
tambahkan baris berikut:
http:
routers:
prometheus:
rule: 'Host(`prometheus.mydomain.tld`)'
service: prometheus
tls: true
services:
prometheus:
loadBalancer:
servers:
- url: "http://host.docker.internal:9090"
membuat reverse porxy untuk prometheus
Pada setiap service yang ingin kita buatkan reverse proxynya kita
memerlukan 2 baris yaitu routers
dan services
.
Untuk url
pada services
karena servicenya
berada di localhost dan diluar docker, maka kita akses dari
http://host.docker.internal
.
Jika diperhatikan, sebenarnya formatnya sama seperti ketika kita memberikan label pada Docker, yang berarti kita juga bisa ‘nebeng’ label di Docker.
Bingung formatnya berasal dari mana? Perhatikan format host pada
ntfy
yang tertulis
traefik.http.routers.ntfy.rule=Host(`sub.mydomain.tld`)
.
Jika kita ubah menjadi format yaml
, menjadi:
http:
routers:
ntfy:
rule: 'Host(`sub.mydomain.tld`)'
konversi dari baris ke file yaml
Untuk yang lain, saya rasa sudah cukup jelas, dan tentu saja dokumentasi dari Traefik lebih lengkap.
Now the question? did you really need reverse proxy while using cloudflared tunnel?
Hehe, sok inggris. Tapi jawabnya adalah tidak. Cukup gunakan saja tunnel, karena pada dasarnya sama saja, untuk akses.
Hal lain yang saya dapatkan ketika mencoba ini adalah… mending pakai nginx, cuma butuh 7 MiB daripada traefik yang makan 50 MiB.