SSD Nodes Learn Hosting plans →
Panduan Matt ConnorOleh Matt Connor · Diperbarui 2026-09-01

Cloudflare Tunnel Tanpa Port Terbuka di VPS

Panduan Cloudflare Tunnel di VPS: buat named tunnel, simpan credentials file, atur ingress, jalankan sebagai systemd service, tutup port 80 dan 443, lalu bind aplikasi ke localhost.

Fungsi Cloudflare Tunnel dan arti sebenarnya dari tidak adanya port terbuka

Cloudflare Tunnel memasang daemon kecil bernama cloudflared pada VPS Anda. Daemon tersebut membuka koneksi keluar ke Cloudflare dan mempertahankan koneksi itu tetap aktif. Permintaan untuk hostname Anda tiba di edge Cloudflare, lalu diteruskan melalui koneksi yang sudah ada tersebut. Dengan demikian, tidak ada koneksi yang perlu masuk ke server Anda.

Langkah yang tidak pernah dicapai oleh sebagian besar panduan: memasang tunnel tidak menutup port apa pun. Jika port 80 dan 443 masih terbuka pada firewall Anda dan aplikasi masih listen pada 0.0.0.0, Anda telah menambahkan jalur masuk kedua, bukan menggantikan jalur pertama. IP origin Anda masih dapat dijangkau, dan siapa pun yang menemukannya dapat melewati Cloudflare secara langsung. Menutup port tersebut adalah langkah manual. Langkah inilah yang membuat seluruh konfigurasi sebelumnya efektif.

cloudflared memerlukan akses keluar ke region1.v2.argotunnel.com dan region2.v2.argotunnel.com pada port 7844. cloudflared menggunakan UDP untuk protokol QUIC dan beralih ke TCP untuk HTTP/2 jika diperlukan. Pada jaringan dengan penyaringan egress, izinkan keduanya atau paksa penggunaan jalur TCP dengan --protocol http2.

Sebelum memulai

  • Domain sudah terdaftar pada akun Cloudflare, dan nameserver Cloudflare melayani zone tersebut. cloudflared tunnel route dns menulis record ke dalam zone itu, jadi zone harus sudah ada terlebih dahulu.
  • Akses keluar pada port 7844 dari VPS, melalui UDP dan TCP.
  • Aplikasi sudah listening secara lokal, meskipun untuk pengujian pertama hanya python3 -m http.server 8080.
  • sudo sudah tersedia pada server, dan sesi SSH kedua sudah terbuka sebelum Anda mengubah firewall.

Instal cloudflared di Ubuntu atau Debian

Cloudflare melampirkan paket .deb pada setiap rilis cloudflared, sehingga instalasinya cukup dengan satu pengunduhan dan satu pemanggilan dpkg.

curl -fsSL -o /tmp/cloudflared.deb \
  https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb
sudo dpkg -i /tmp/cloudflared.deb
cloudflared --version

Jalankan dpkg --print-architecture terlebih dahulu jika Anda tidak yakin dengan arsitektur sistem tersebut. Pada ARM 64-bit, nama filenya berakhiran arm64, bukan amd64, dan tidak ada hal lain yang berubah. cloudflared --version yang menampilkan string versi adalah satu-satunya konfirmasi yang diperlukan sebelum melanjutkan.

Paket yang diinstal dengan cara ini berada di luar jalur pembaruan apt, sehingga apt-get upgrade tidak akan pernah memperbaruinya dan pembaruannya menjadi tanggung jawab Anda. sudo cloudflared update mengunduh rilis terbaru dan mengganti binary di tempat; setelah service tersedia, lanjutkan dengan sudo systemctl restart cloudflared agar proses yang sedang berjalan menggunakan binary baru. Jadwalkan langkah ini bersamaan dengan patching lainnya, karena daemon tunnel adalah software yang menghadap Internet meskipun tidak membuka port.

Masuk dan buat tunnel bernama

cloudflared tunnel login

Pada VPS tanpa antarmuka grafis, browser tidak dapat dibuka. Salin URL yang ditampilkan ke browser di laptop Anda, lalu pilih zone. Setelah proses selesai, ~/.cloudflared/cert.pem tersedia.

cert.pem adalah kredensial account Anda. Kredensial ini mengizinkan pembuatan tunnel, penulisan record DNS ke dalam zone tersebut, dan penghapusan tunnel. Tunnel yang sedang berjalan tidak pernah menggunakannya. Perlakukan kredensial ini seperti password, karena satu salinan file tersebut sudah cukup bagi seseorang untuk memublikasikan hostname baru pada domain Anda.

cloudflared tunnel create homelab

Proses yang berhasil menampilkan kedua baris di bawah ini. UUID di dalamnya adalah nilai yang akan Anda masukkan ke file konfigurasi.

Tunnel credentials written to /home/you/.cloudflared/6ff42ae2-765d-4adf-8112-31c55c1551ef.json. cloudflared chose this file based on where your origin certificate was found. Keep this file secret. To revoke these credentials, delete the tunnel.
Created tunnel homelab with id 6ff42ae2-765d-4adf-8112-31c55c1551ef

File JSON tersebut adalah identitas tunnel dan satu-satunya kredensial yang diperlukan service yang sedang berjalan. Siapa pun yang memilikinya dapat mendaftarkan diri sebagai tunnel Anda dan menerima trafik Anda. Kredensial ini tidak dapat diputar secara mandiri. Pencabutannya berarti cloudflared tunnel delete homelab dan membuat tunnel baru.

Simpan file kredensial di lokasi yang tepat

Service berjalan sebagai root. Karena itu, simpan file di direktori yang dimiliki root, bukan di direktori home yang mungkin dapat diakses oleh tugas pencadangan atau akun login bersama.

sudo install -d -m 700 -o root -g root /etc/cloudflared
sudo install -m 600 -o root -g root \
  ~/.cloudflared/6ff42ae2-765d-4adf-8112-31c55c1551ef.json \
  /etc/cloudflared/6ff42ae2-765d-4adf-8112-31c55c1551ef.json
rm ~/.cloudflared/6ff42ae2-765d-4adf-8112-31c55c1551ef.json
sudo ls -l /etc/cloudflared
cloudflared tunnel list

ls -l seharusnya menampilkan -rw------- root root pada file JSON tersebut. cloudflared tunnel list membaca cert.pem, sehingga tetap berfungsi dan seharusnya menampilkan nama tunnel, UUID-nya, serta jumlah koneksi yang sedang ditanganinya.

Tulis config.yml dengan aturan ingress yang sebenarnya

Tulis konfigurasi di /etc/cloudflared/config.yml, bukan di direktori home Anda. Alasannya sebagai berikut. cloudflared service install menyalin konfigurasi apa pun yang ditemukan ke /etc/cloudflared/config.yml, lalu menetapkan --config /etc/cloudflared/config.yml secara hard-code ke dalam unit systemd. Jika Anda membuat file di ~/.cloudflared/config.yml, salinan tersebut hanya merupakan snapshot satu kali. Setiap perubahan berikutnya pada salinan di direktori home tidak mengubah apa pun. Service tetap menggunakan aturan lama dan tidak memberikan peringatan. Membuat file langsung di lokasi yang digunakan akan menghilangkan seluruh masalah ini.

tunnel: 6ff42ae2-765d-4adf-8112-31c55c1551ef
credentials-file: /etc/cloudflared/6ff42ae2-765d-4adf-8112-31c55c1551ef.json
loglevel: info

ingress:
  - hostname: app.example.com
    service: http://127.0.0.1:8080
  - hostname: files.example.com
    service: http://127.0.0.1:8081
  - hostname: grafana.example.com
    path: ^/api/
    service: http://127.0.0.1:3000
  - service: http_status:404

Aturan dibaca dari atas ke bawah, dan kecocokan pertama yang digunakan. Aturan tanpa hostname cocok dengan setiap hostname. Karena itu, aturan catch-all harus ditempatkan paling akhir. Jika aturan tersebut tidak ada, konfigurasi ditolak dengan The last ingress rule must match all URLs (i.e. it should not have a hostname or path filter). http_status:404 adalah service bawaan yang menjawab dengan 404 dan tidak melakukan hal lain. Service ini diperlukan: tanpanya, request untuk hostname yang tidak pernah ingin Anda publikasikan akan diteruskan ke aturan nyata mana pun yang kebetulan berada paling akhir.

Gunakan 127.0.0.1 dalam URL service:, bukan localhost. Di Ubuntu, localhost me-resolve ::1 terlebih dahulu, sedangkan aplikasi yang hanya terikat pada loopback IPv4 akan menolak koneksi tersebut. Baris log-nya adalah dial tcp [::1]:8080: connect: connection refused dan pengunjung akan menerima 502.

http:// biasa sudah benar di sini karena hop tersebut tidak pernah meninggalkan mesin. Gunakan https:// hanya jika aplikasi lokal memang mengharuskan TLS (transport layer security), dan perkirakan x509: certificate is valid for example.com, not localhost jika sertifikatnya tidak cocok dengan nama yang Anda hubungi. Perbaiki masalah ini dengan originServerName di bawah originRequest, atau terima risikonya dengan noTLSVerify: true.

Periksa aturan sebelum memulai apa pun:

sudo cloudflared --config /etc/cloudflared/config.yml tunnel ingress validate
sudo cloudflared --config /etc/cloudflared/config.yml tunnel ingress rule https://app.example.com/login

ingress validate melaporkan bahwa konfigurasi valid atau menyebutkan aturan yang menyebabkan kegagalan. ingress rule menerima satu URL dan menampilkan aturan pertama yang cocok dengannya. Ini adalah cara tercepat untuk mengetahui bahwa regex path tidak cocok dengan yang Anda perkirakan.

Arahkan DNS ke tunnel

cloudflared tunnel route dns homelab app.example.com
cloudflared tunnel route dns homelab files.example.com
cloudflared tunnel route dns homelab grafana.example.com

Setiap pemanggilan perintah menulis record CNAME yang diproksikan dan mengarah ke 6ff42ae2-765d-4adf-8112-31c55c1551ef.cfargotunnel.com. Target tersebut hanya dapat di-resolve di dalam jaringan Cloudflare. Karena itu, jawaban DNS publik untuk hostname Anda adalah alamat Cloudflare dan IP VPS Anda tidak pernah muncul di dalamnya. Wildcard hostname di config.yml tetap memerlukan record DNS yang sesuai untuk setiap nama yang benar-benar Anda gunakan.

Jika sebuah record sudah ada, perintah akan gagal seperti ini:

Failed to add route: code: 1003, reason: Failed to create record app.example.com with err An A, AAAA, or CNAME record with that host already exists.

Record yang sudah ada tersebut hampir selalu merupakan record A lama yang mengarah ke IP publik VPS Anda. Record itulah yang ingin Anda hapus. Hapus record tersebut di dashboard Cloudflare, lalu jalankan kembali perintahnya. Jika record itu dibiarkan, DNS tetap memublikasikan IP origin Anda sehingga tunnel tidak menyembunyikan apa pun.

Instal sebagai service agar tetap berjalan setelah reboot

Jalankan sekali di foreground, karena kesalahan jauh lebih mudah dibaca di terminal Anda sendiri daripada di journal.

sudo cloudflared --config /etc/cloudflared/config.yml tunnel run homelab

Startup yang normal mencatat beberapa baris Registered tunnel connection, satu untuk setiap lokasi edge, dan masing-masing memiliki connIndex sendiri. Buka salah satu hostname Anda di browser dan pastikan aturan ingress mengarahkan Anda ke tujuan yang benar, lalu hentikan dengan Ctrl-C.

sudo cloudflared --config /etc/cloudflared/config.yml service install
systemctl status cloudflared

Perintah tersebut menulis /etc/systemd/system/cloudflared.service beserta cloudflared-update.service dan cloudflared-update.timer, lalu menjalankan systemctl enable cloudflared.service dan systemctl start cloudflared.service untuk Anda. enable adalah bagian yang penting di sini karena komponen inilah yang mengaktifkan kembali tunnel setelah reboot. ExecStart unit tersebut adalah cloudflared --no-autoupdate --config /etc/cloudflared/config.yml tunnel run, sehingga path konfigurasi itu wajib digunakan.

Tiga kegagalan pada langkah ini memiliki pesan yang spesifik. possible conflicting configuration in /home/you/.cloudflared/config.yml and /etc/cloudflared/config.yml berarti kedua file ada dan cloudflared menolak memilih secara otomatis: hapus file yang tidak ingin digunakan. configuration file ... must contain entries for the tunnel to run and its associated credentials (tunnel: TUNNEL-UUID, credentials-file: CREDENTIALS-FILE) berarti konfigurasi Anda menggunakan singkatan quick url:, bukan key named-tunnel, dan singkatan tersebut tidak dapat dijalankan sebagai service. cloudflared service is already installed berarti unit lama masih ada, jadi jalankan sudo cloudflared service uninstall terlebih dahulu.

Tidak ada reload. Setelah mengedit /etc/cloudflared/config.yml, jalankan sudo systemctl restart cloudflared. Kemudian buktikan bahwa reboot ditangani dengan benar, bukan sekadar menganggapnya demikian:

sudo reboot
# once it is back
systemctl is-enabled cloudflared
systemctl is-active cloudflared
journalctl -u cloudflared -n 50 --no-pager
curl -sI https://app.example.com

is-enabled yang menampilkan enabled dan is-active yang menampilkan active adalah inti bagian ini. Setelah route tersedia dan service berjalan, cert.pem tidak lagi memiliki tugas di server: rm ~/.cloudflared/cert.pem. Jika nanti menambahkan hostname, cukup jalankan cloudflared tunnel login lagi.

Tutup port 80 dan 443, atau tunnel hanya menjadi jalur tambahan

Ada dua perubahan, dan keduanya diperlukan. Jika hanya satu yang dilakukan, origin tetap dapat diakses.

Pertama, bind aplikasi ke alamat loopback. Dalam nginx, ini berarti menggunakan listen 127.0.0.1:8080; sebagai pengganti listen 80;, seperti pada langkah-langkah di penjelasan konfigurasi reverse proxy nginx ini. Dalam Docker Compose, ini berarti ports: - "127.0.0.1:8080:80". Bentuk "8080:80" yang sederhana memublikasikan port pada semua interface. Docker juga menulis aturan NAT (network address translation) sendiri yang diproses paket sebelum ufw melihatnya. Karena itu, aturan deny ufw tidak akan menghentikannya. Jebakan ini dibahas dalam alasan port yang dipublikasikan Docker mengabaikan ufw.

sudo ss -lntp

Setiap service yang dipindahkan sekarang seharusnya menampilkan 127.0.0.1:8080 pada kolom Local Address. Baris yang berisi 0.0.0.0:8080 atau *:8080 masih mendengarkan koneksi dari jaringan publik.

Kedua, tutup port tersebut.

sudo ufw status numbered
sudo ufw delete allow 'Nginx Full'
sudo ufw status

Hapus aturan allow untuk port 80 dan 443, jangan menambahkan aturan deny di atasnya. ufw berhenti pada aturan pertama yang cocok, sehingga aturan allow lama yang posisinya lebih tinggi dalam daftar akan tetap berlaku. Pertahankan aturan SSH. Panduan dasar firewall ufw membahas aturan lainnya. Sebagian besar penyedia VPS juga menjalankan firewall jaringan terpisah pada control panel. Firewall tersebut bukan ufw, jadi tutup port 80 dan 443 di sana juga.

Sekarang lakukan verifikasi dari lokasi lain, karena curl http://127.0.0.1:8080 pada server itu sendiri tidak membuktikan apa pun tentang akses dari luar.

# run these from a different machine
nc -vz 203.0.113.10 443
curl -sI https://app.example.com

nc yang ditolak atau mengalami timeout terhadap IP mentah, ditambah 200 melalui hostname, adalah hasil yang Anda cari. Memeriksa apakah port benar-benar terbuka membahas cara lain untuk mengujinya.

Tunnel adalah sarana transportasi, bukan autentikasi. Apa pun yang Anda publikasikan melaluinya dapat diakses secara publik kecuali Anda menambahkan login di depannya, baik Cloudflare Access pada edge maupun proxy OAuth2 yang ditempatkan di depan aplikasi pada server. SSH juga memerlukan pengaturan tersendiri karena tunnel tidak mencakupnya: biarkan port 22 tetap terbuka, tetapi batasi aksesnya ke alamat sumber milik Anda sendiri.

Keuntungan dan biaya Cloudflare Tunnel

Keuntungan yang Anda dapatkan bersifat nyata. IP origin Anda tidak lagi dipublikasikan, tidak ada port inbound yang terekspos, dan konfigurasi ini dapat bekerja dari mesin yang sama sekali tidak memiliki IP publik. Sertifikat publik menjadi tanggung jawab Cloudflare, sehingga tidak ada klien ACME (automatic certificate management environment) yang berjalan di server Anda. Serangan volumetrik juga ditangani di edge, bukan pada kuota bandwidth Anda.

Biayanya juga nyata. Cloudflare menghentikan TLS di edge mereka: permintaan pengunjung didekripsi di sana lalu dienkripsi kembali ke dalam tunnel, sehingga Cloudflare dapat membaca trafik tersebut. Hal ini memungkinkan firewall, caching, dan aturan Access mereka berfungsi. Tidak ada pengaturan yang dapat menonaktifkannya selama Anda masih menggunakan proxy mereka. Jika pihak ketiga yang memegang plaintext Anda tidak dapat diterima, berhenti di sini dan pilih solusi lain.

Cloudflare juga menjadi dependensi mutlak untuk keterjangkauan. Saat cloudflared tidak terhubung, pengunjung akan menerima halaman Error 1033 dari Cloudflare, bukan aplikasi Anda. Anda juga telah sengaja menghapus rute langsung yang dapat digunakan sebagai cadangan.

Dari browser biasa, hanya HTTP, HTTPS, dan WebSocket yang dapat menjangkau hostname publik. Protokol TCP lain, SSH, RDP (remote desktop protocol), atau server game juga memerlukan perangkat lunak di sisi klien: cloudflared access tcp untuk meneruskan port lokal, atau klien WARP. Tidak ada jalur tanpa klien untuk protokol-protokol tersebut.

Ukuran body permintaan dibatasi di edge. Upload yang melebihi batas akan ditolak dengan HTTP 413 sebelum pernah mencapai aplikasi Anda. Per Agustus 2026, batas tersebut adalah 100 MB pada paket Free dan Pro, serta lebih tinggi pada tier berbayar. Periksa halaman batas Cloudflare terbaru sebelum merancang sistem berdasarkan angka tertentu. Ketentuan layanan mandiri Cloudflare juga membatasi penggunaan proxy yang terutama ditujukan untuk menyajikan video dan file non-HTML berukuran besar lainnya. Baca ketentuan tersebut sebelum mengarahkan pustaka media ke tunnel gratis.

Cloudflare Tunnel, reverse SSH tunnel, atau Tailscale Funnel

Ketiganya hanya membuat koneksi keluar, sehingga semuanya dapat digunakan dari server yang tidak memiliki port masuk dan IP publik. Perbedaannya terletak pada pihak yang menyimpan data plaintext dan hostname yang dilihat publik.

Reverse SSH tunnel memerlukan mesin kedua yang memiliki IP publik. Mesin tersebut menjadi pintu masuk: sertifikat, reverse proxy, dan firewall di sana semuanya Anda kelola sendiri. Tidak ada pihak lain yang mendekripsi data. Komponennya lebih banyak, dan Anda memerlukan autossh atau unit systemd dengan Restart=always agar tunnel tetap berjalan setelah gangguan jaringan singkat. Panduan reverse SSH tunnel untuk CGNAT menjelaskan proses pembuatannya.

Tailscale Funnel adalah perbandingan yang paling dekat. Funnel juga hanya membuat koneksi keluar, dan TLS dihentikan di mesin Anda sendiri, sehingga relay Tailscale tidak pernah melihat data plaintext. Konsekuensinya adalah penamaan dan port: Funnel hanya melayani nama di bawah domain ts.net milik tailnet Anda, dan hanya pada port 443, 8443, dan 10000. Perbedaan antara Tailscale Serve dan Funnel membahas kedua sisi tersebut.

Jadi, pilih berdasarkan batasan yang benar-benar berlaku bagi Anda. Pilih Cloudflare Tunnel jika publik harus dapat mengakses domain Anda sendiri dan Anda menerima bahwa Cloudflare dapat membaca trafik tersebut. Pilih Tailscale Funnel jika hostname ts.net dapat diterima dan Anda tidak ingin menyerahkan data plaintext kepada proxy. Pilih reverse SSH tunnel jika Anda sudah memiliki server publik dan tidak ingin ada pihak ketiga sama sekali di jalur koneksi.

FAQ

Apakah saya masih perlu membuka port 443 dengan Cloudflare Tunnel?

Tidak. cloudflared membuat koneksi keluar ke Cloudflare melalui port 7844, dan setiap request dikirim kembali melalui koneksi tersebut, sehingga tidak ada port masuk yang digunakan. Namun, pemasangan tunnel tidak menutup port apa pun secara otomatis. Hapus aturan allow untuk 80 dan 443 di ufw, tutup port tersebut pada network firewall terpisah milik provider, bind aplikasi ke 127.0.0.1, dan hapus A record tersisa yang masih memublikasikan IP VPS Anda. Konfirmasikan dari server dengan sudo ss -lntp dan dari mesin lain dengan nc -vz <your-ip> 443.

Mengapa hostname saya menampilkan Cloudflare Error 1033?

Error 1033 berarti Cloudflare menyimpan DNS record untuk hostname tersebut, tetapi tidak menemukan cloudflared yang sehat dan terhubung untuk menerima request. Prosesnya mungkin berhenti, atau proses tersebut berjalan tetapi tidak dapat terhubung ke Cloudflare. Periksa systemctl status cloudflared dan journalctl -u cloudflared -n 50, lalu pastikan port keluar 7844 diizinkan untuk UDP dan TCP. Firewall yang memblokir UDP dan QUIC tanpa mengizinkan fallback TCP akan menghasilkan kondisi ini. cloudflared tunnel info homelab menampilkan koneksi yang saat ini dilihat Cloudflare. Jika daftarnya kosong, masalahnya berada di sisi Anda.

Mengapa saya mendapatkan 502 Bad Gateway melalui tunnel?

Error 502 berarti cloudflared berhasil dijangkau, tetapi tidak dapat menjangkau service lokal Anda. Jadi, masalahnya berada di antara kedua titik tersebut, bukan di Cloudflare. Baca log. dial tcp [::1]:8080: connect: connection refused berarti tidak ada proses yang listening pada alamat yang Anda tentukan. [::1] dalam pesan tersebut biasanya berarti Anda menulis localhost pada URL service:, sedangkan aplikasi hanya bind ke IPv4. Karena itu, tulis http://127.0.0.1:8080. HTTP/1.x transport connection broken: malformed HTTP response menunjukkan ketidaksesuaian sebaliknya: Anda menulis https:// pada origin yang menggunakan HTTP biasa.

Dapatkah saya menjalankan SSH, RDP, atau game server melalui Cloudflare Tunnel?

Tidak dengan client biasa. Public hostname melalui tunnel membawa HTTP, HTTPS, dan WebSocket, yaitu protokol yang digunakan browser. Protokol TCP lain juga memerlukan software pada mesin client, baik cloudflared access tcp untuk meneruskan port lokal maupun client WARP. Jika Anda ingin menggunakan SSH dari mesin apa pun tanpa memasang software, tunnel bukan tool yang tepat. Biarkan port 22 terbuka dan batasi berdasarkan alamat sumber.

Apakah Cloudflare dapat melihat traffic saya melalui tunnel?

Ya. Cloudflare melakukan terminasi TLS di edge mereka, mendekripsi request di sana, lalu mengenkripsinya kembali ke tunnel menuju server Anda. Dekripsi tersebut memungkinkan firewall, caching, dan kebijakan Access mereka berfungsi. Ini juga berarti plaintext Anda ada pada mesin Cloudflare. Tidak ada konfigurasi yang dapat menghindari hal tersebut selama Anda menggunakan proxy mereka. Jika kondisi ini tidak dapat diterima, gunakan Tailscale Funnel atau jalankan reverse proxy sendiri pada server publik.

#cloudflare-tunnel#cloudflared#zero-trust#firewall#self-hosting