Nginx-Proxy-Manager (NPM) adalah tool yang sangat bagus, terutama bagi mereka yang baru memulai di dunia self-hosting. Tampilannya yang berbasis web (GUI) membuatnya sangat mudah untuk mengatur reverse proxy dan mendapatkan sertifikat SSL. Namun, seiring berjalannya waktu dan semakin banyaknya layanan yang kita hosting, ada kalanya pendekatan GUI justru terasa sedikit merepotkan.
Kadang saya merasa kesusahan, jika hanya menambah satu servis, saya harus membuka dashboard, login, klik sana-sini hanya untuk menambahkan satu host. Proses ini terasa kurang efisien, terutama jika kita ingin semua konfigurasi terdokumentasi sebagai kode (Infrastructure as Code).
Di sinilah Traefik menjadi solusi. Traefik adalah reverse proxy modern yang dirancang untuk dunia cloud-native, terintegrasi sempurna dengan Docker. Konsep utamanya adalah kita mendefinisikan semua konfigurasi routing dan SSL langsung pada label di file compose.yaml milik servis itu sendiri. Tidak perlu lagi buka dashboard terpisah.
Jadi yang saya perlukan agar servis Docker saya dapat diakses yaitu:
- Reverse Proxy yang disini saya gunakan yaitu traefik
- SSL Otomatis dengan Let's Encrypt, khususnya disini saya menggunakan DNS-01 Challenge dari Cloudflare untuk wildcard certificate maupun sertifikat biasa tanpa harus membuka port 80 ke dunia luar.
Step Instalasi
1. Buat Secret untuk Credentials Dashboard Traefik
Pertama, kita perlu mengamankan dashboard Traefik dengan basic authentication. Kita akan membuat hash password menggunakan htpasswd.
# Buat direktori kerja untuk Traefik
mkdir traefik
cd traefik
# Hasilkan username dan hash password
# Ganti <yourPassword> dengan password yang kuat
htpasswd -nb admin "<yourPassword>" | sed -e 's/\$/\$\$/g'
# Hasilnya akan seperti ini: admin:$$apr1$$...
# Copy hasil lengkapnya untuk langkah selanjutnyaKeterangan: Perintah
sed -e 's/\$/\$\$/g'sangat penting. Ini berfungsi untuk melakukan escape pada karakter$di dalam hash password. Tanpa ini, Docker Compose akan salah menginterpretasikannya sebagai variabel dan menyebabkan otentikasi gagal.
2. Buat Credentials untuk Cloudflare
Selanjutnya, buat file .env untuk menyimpan kredensial Cloudflare. Traefik akan menggunakan ini untuk memvalidasi kepemilikan domain melalui DNS Challenge (DNS-01).
# Buat file .env dan isi dengan kredensial Anda
cat << EOF | tee .env
CF_API_EMAIL="<email_cloudflare_anda>"
CF_DNS_API_TOKEN="<token_api_cloudflare_anda>"
EOFKeterangan: Sangat disarankan untuk membuat API Token di Cloudflare dengan permission sebatas
Zone:DNS:Edituntuk domain yang bersangkutan, daripada menggunakan Global API Key. Ini adalah praktik keamanan yang lebih baik (_least privilege_).
3. Buat compose.yaml
Ini adalah inti dari instalasi Traefik kita. File ini mendefinisikan servis Traefik itu sendiri, beserta konfigurasi dasarnya melalui label Docker.
services:
traefik:
image: traefik:v3.0 # Selalu baik untuk menggunakan versi spesifik
container_name: traefik
restart: unless-stopped
environment:
- CF_API_EMAIL=${CF_API_EMAIL}
- CF_DNS_API_TOKEN=${CF_DNS_API_TOKEN}
security_opt:
- no-new-privileges:true
networks:
- proxy
ports:
- "80:80"
- "443:443"
# - "8080:8080" # Opsional: jika ingin expose dashboard tanpa proxy
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./certs:/certs
- ./traefik.yaml:/etc/traefik/traefik.yaml:ro
# Traefik Dynamic configuration via Docker labels
labels:
# Enable self‑routing
- "traefik.enable=true"
# Dashboard router
- "traefik.http.routers.dashboard.rule=Host(`dashboard.domain-anda.com`)"
- "traefik.http.routers.dashboard.entrypoints=websecure"
- "traefik.http.routers.dashboard.service=api@internal"
- "traefik.http.routers.dashboard.tls=true"
- "traefik.http.routers.dashboard.tls.certresolver=letencrypt"
# Basic‑auth middleware
- "traefik.http.middlewares.dashboard-auth.basicauth.users=<Paste Credentials dari Langkah 1 Disini>"
- "traefik.http.routers.dashboard.middlewares=dashboard-auth@docker"
networks:
proxy:
name: proxyKeterangan:
- environment: Mengambil nilai variabel dari file .env yang kita buat tadi dan memberikannya ke kontainer Traefik.
- networks: - proxy: Ini krusial. Kita membuat sebuah network khusus bernama proxy. Semua servis yang ingin di-ekspos melalui Traefik harus terhubung ke network ini.
- volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro: Ini adalah "sihir"-nya. Dengan me-mounting Docker socket (dalam mode read-only untuk keamanan), Traefik bisa "mendengarkan" setiap kejadian di Docker (misal: kontainer start/stop) dan secara otomatis memperbarui konfigurasinya tanpa perlu di-restart.
- ./certs:/certs: Volume untuk menyimpan sertifikat SSL yang dihasilkan oleh Let's Encrypt secara persisten.
- ./traefik.yaml:/etc/traefik/traefik.yaml:ro: File konfigurasi statis Traefik yang akan kita buat selanjutnya.
- labels: Di sini kita mengkonfigurasi Traefik untuk dirinya sendiri. Kita memberitahu Traefik untuk membuat sebuah router untuk dashboard-nya, mengamankannya dengan HTTPS websecure), menggunakan resolveletencrypt, dan menerapkan middleware otentikasi dasar yang telah kita siapkan.
4. Buat Konfigurasi Statis Traefik
File ini berisi konfigurasi yang jarang berubah, seperti mendefinisikan entrypoints (port masuk), provider Docker, dan konfigurasi Let's Encrypt.
cat << EOF > traefik.yaml
entryPoints:
web:
address: ":80"
http:
redirections:
entryPoint:
to: websecure
scheme: https
permanent: true
websecure:
address: ":443"
http:
tls: {}
providers:
docker:
exposedByDefault: false
network: proxy
api:
dashboard: true
insecure: false
log:
level: INFO
accessLog: {}
certificatesResolvers:
letencrypt:
acme:
email: email-anda@email.com
storage: /certs/acme.json
caServer: [https://acme-v02.api.letsencrypt.org/directory](https://acme-v02.api.letsencrypt.org/directory) # production (default)
# caServer: [https://acme-staging-v02.api.letsencrypt.org/directory](https://acme-staging-v02.api.letsencrypt.org/directory) # staging (gunakan ini saat development)
dnsChallenge:
provider: cloudflare
delayBeforeCheck: 10 # Opsional, menunggu 10 detik sebelum verifikasi DNS
EOFKeterangan:
- entryPoints: Mendefinisikan "pintu masuk" traffic. web (port 80) diatur untuk secara otomatis me-redirect semua permintaan ke websecure (port 443/HTTPS).
- providers.docker: Mengaktifkan Docker sebagai provider konfigurasi. exposedByDefault: false adalah setelan keamanan yang penting, artinya kita harus secara eksplisit menambahkan label traefik.enable=true pada setiap servis yang ingin di-ekspos.
- certificatesResolvers.letencrypt: Di sinilah kita mendefinisikan resolver sertifikat kita, memberitahu Traefik untuk menggunakan email dan penyimpanan yang ditentukan, serta memakai dnsChallenge dengan provider cloudflare. Penting: Gunakan caServer staging selama masa percobaan untuk menghindari rate limit dari Let's Encrypt. Ganti ke production jika semua sudah berjalan lancar.
5. Compose UP!
Sekarang, saatnya menjalankan Traefik.
sudo docker compose up -dJika semua berjalan lancar, Anda seharusnya sudah bisa mengakses https://dashboard.domain-anda.com dan akan diminta memasukkan username dan password yang telah dibuat di langkah pertama.

Expose Service Lain
Inilah bagian terbaiknya. Untuk mengekspos servis baru, kita hanya perlu menambahkan beberapa baris labels di file compose.yaml servis tersebut.
Disini saya mencontohkan untuk expose WordPress. Anggap kita punya compose.yaml untuk WordPress, kita hanya perlu memodifikasinya seperti ini:
services:
# ... (definisi servis database, jika ada)
wordpress:
image: wordpress:latest
restart: unless-stopped
environment:
WORDPRESS_DB_HOST: db
# ... env lain
networks:
- proxy # <--- PENTING: Hubungkan ke network proxy
- internal # network untuk komunikasi dengan db
labels:
- "traefik.enable=true"
- "traefik.http.routers.wordpress-https.rule=Host(`wp.domain-anda.com`)" # sesuaikan dengan dns nya
- "traefik.http.routers.wordpress-https.entrypoints=websecure"
- "traefik.http.routers.wordpress-https.tls=true"
- "traefik.http.routers.wordpress-https.tls.certresolver=letencrypt"
# Memberitahu Traefik port internal mana yang harus dihubungi
- "traefik.http.services.wordpress-svc.loadbalancer.server.port=80"
# ... (definisi network lain)
networks:
proxy:
external: true
internal:
external: falseKeterangan:
- *networks**: Pertama dan terpenting, pastikan kontainer WordPress terhubung ke jaringan proxy yang sama dengan Traefik.
- *traefik.enable: "true"**: "Saklar" untuk memberitahu Traefik agar mengelola proxy untuk servis ini.
- *traefik.http.routers...rule**: Menentukan aturan routing. Dalam hal ini, semua traffic untuk wp.domain-anda.com akan diarahkan ke kontainer ini.
- *traefik.http.routers...entrypoints**: Menentukan bahwa router ini hanya mendengarkan di pintu masuk websecure (HTTPS).
- *traefik.http.routers...tls.certresolver**: Menyuruh Traefik untuk secara otomatis mendapatkan sertifikat SSL untuk domain ini menggunakan resolver letencrypt yang telah kita buat.
- *traefik.http.services...port**: Menentukan port internal dari servis yang dituju (WordPress berjalan di port 80 di dalam kontainernya).
Setelah menambahkan label ini, cukup jalankan docker compose up -d di direktori WordPress, dan Traefik akan secara otomatis mendeteksinya, meminta sertifikat SSL, dan mulai mengarahkan traffic. Semuanya tanpa menyentuh konfigurasi Traefik sama sekali.