Skip to content

Network & Hosts Toolkit

By Romi Fadli, S.Kom. 11 min read Environments & Deployment
On this page
A browser window sends one orange path into a single web server, which routes it on to the orange staging environment; dashed paths to the blue development and green production environments stay inactive

Network & Hosts Toolkit adalah dua perintah yang menjaga tiga environment tetap terpisah di satu mesin dan satu web server. Perintah pertama menetapkan alamat satu environment dan menyelaraskan setiap tempat yang menyimpannya dalam sekali jalan; perintah kedua mengarahkan browser ke environment yang saya pilih. Tak satu pun menuntut saya mengingat di mana alamat itu tertulis.

Development, staging, dan production berbagi satu nama domain dan satu nginx, dan dipisahkan hanya oleh alamat yang didengarkan masing-masing serta Docker network tempatnya berjalan. Pemisahan itu hanya sekuat konsistensinya: satu alamat basi di satu file konfigurasi sudah cukup untuk mengirim request ke environment yang salah.

Sekilas

Toolsset-network, switch-env
BentukScript command-line yang berbagi satu library pembantu
BahasaBash dengan awk untuk substitusi literal, yang mengendalikan Docker dan nginx
StatusStabil, berjalan di production
Kode sumberPrivat
Apa toolkit ini, dibangun dengan apa, dan keadaannya.

Yang dikerjakannya

A. Menetapkan alamat environment dengan satu perintah

Saya memberinya nama environment, alamat host, dan subnet. Input-nya diperiksa ketat — oktet IPv4 yang sah dan subnet dalam bentuk yang diharapkan — dan gateway diturunkan dari subnet, tak diminta terpisah. Perintah ini lalu memperbarui setiap tempat yang menyimpan alamat: state jaringan yang tercatat, konfigurasi web server, Docker network-nya sendiri, yang dibuat ulang karena subnet tak bisa diubah di tempat, dan folder environment, tempat gateway lama dan rentang lama diganti sebagai teks di mana pun keduanya muncul dalam sekitar tiga puluh empat file konfigurasi. Penggantian itu mencocokkan secara literal dan menulis isi file di tempatnya, jadi pemilik, mode, dan link file tetap selamat walau dijalankan dengan hak lebih tinggi.

B. Merender konfigurasi web server dari template

Konfigurasi nginx tiap environment dihasilkan dari template dan dipasang sebagai file biasa milik root. Blok yang identik di ketiga environment tinggal di partial bersama, jadi yang dibawa tiap template hanyalah bagian yang memang berbeda. Partial disisipkan sebagai teks, bukan lewat include milik web server, karena nama upstream berbeda per environment, dan hasilnya satu file datar yang bisa dibaca operator; setiap upstream membawa prefix environment, karena nama upstream bersifat global dan duplikatnya mematikan web server. Setiap file hasil render diberi cap waktu dan nama template asalnya, lalu dipasang dengan pertukaran atomik bermode 0644, yang sekaligus menggantikan link lama — file sementara dibuat hanya bisa dibaca pemiliknya, dan worker web server tak akan bisa membacanya. Di mesin baru, placeholder untuk banner versi staging dibuat lebih dulu, jadi render pertama tak menunggu environment staging yang belum mungkin ada. Sesudah git pull, mode render saja menulis ulang konfigurasi dari state yang tercatat tanpa menyentuh apa pun lagi, dan ia menolak argumen tambahan sambil menjelaskan alasannya, karena argumen seperti itu biasanya berarti yang dimaksud adalah mode penuh.

C. Menolak sebelum menyentuh apa pun

Sebelum satu file pun berubah, perintah ini memeriksa bahwa gateway dan alamat host baru belum dipakai environment lain, dan bahwa subnet itu belum dimiliki Docker network lain di host, dari project mana pun. Bila bentrok, run berhenti sambil menyebut network yang menghalangi beserta perintah untuk menghapusnya — pemeriksaan ini ada karena subnet yang pernah saya pilih ternyata milik network project lain — dan ia hanya dilewati bila network memang sengaja dibiarkan. Sebelum bertindak, perintah ini mencetak apa yang akan dikerjakannya, memperingatkan bila alamat host tak ada di interface mana pun atau bila ada container yang akan dimatikan, lalu meminta saya mengetik nama environment-nya, atau menerima flag untuk otomasi. Perlu tidaknya perubahan juga dinilai dari konfigurasi web server yang terpasang, setelah mesin baru pernah mendapat jawaban "tak ada perubahan" lalu dibiarkan tanpa konfigurasi sama sekali; output pemeriksaan network juga dibersihkan sebelum dibandingkan, setelah jawaban kosong pernah membuat perintah ini mencoba menghapus network yang tak pernah ada.

D. Mengarahkan browser ke satu environment

Perintah kedua menulis ulang satu blok bertanda di /etc/hosts supaya kedua domain mengarah ke tepat satu environment. Alamatnya dibaca dari state tercatat yang sama, entri lain untuk domain itu yang bisa menimbulkan resolusi ganda dinonaktifkan, dan baris lain dibiarkan apa adanya. Pilihan none mengembalikan kedua domain ke DNS publik. File baru divalidasi sebelum ditulis — tiap domain aktif tepat sekali, di alamat yang diminta — dan run dibatalkan bila file-nya akan menyusut lebih dari dua belas baris, tanda penanda tak berpasangan sedang memakan isinya. Sesudah ditulis, hasilnya diperiksa lewat resolver sistem. Bila alamat tujuan tak ada di interface mana pun, peringatannya menyebut penyebab yang paling mungkin untuk environment itu, misalnya jaringan privat yang belum tersambung atau alamat laptop yang berubah, dan baru dalam keadaan itu ia meminta konfirmasi. Komentar panduan di dalam blok dibuat dari alamat tercatat yang sebenarnya, setelah komentar tetap terus menyebut alamat yang sudah tak dipakai. Berpindah ke environment yang sudah aktif tak mengubah apa pun, dan file hosts-nya bisa diarahkan ke salinan uji.

E. Memperlihatkan keadaan ketiganya

Kedua perintah punya mode show. Perintah jaringan menampilkan alamat host, gateway, dan subnet tiap environment, serta menandai konfigurasi yang alamat host-nya tak terpasang di interface mana pun — seluruh rentang loopback dianggap terpasang — network yang belum dibuat, dan subnet yang berbeda dari milik Docker. Perintah hosts menampilkan environment mana yang sedang dibuka browser.

Cara saya memakainya

bash
set-network --show
set-network dev <host-address> <subnet>    # host address + subnet
set-network --render production                   # after git pull on a server
switch-env staging                                # browser now opens staging
switch-env --show
TempatYang diubah dalam satu run
State jaringan yang tercatatgateway dan alamat listening environment itu
Konfigurasi web serverdirender ulang dari template, diuji, lalu diterapkan
Folder environmentgateway, rentang trusted proxy, entri host, endpoint service, dan nilai fallback
Docker networkdibuat ulang dengan subnet baru
Semua yang diselaraskan oleh satu perubahan alamat.
Exit codeArti
0environment sudah memakai alamat barunya, atau memang tak ada yang perlu diubah
1ada langkah yang gagal, jumlah argumennya salah, atau state tercatat kehilangan satu kunci; konfigurasi web server yang tak valid sudah dikembalikan
2nilai tak sah, opsi tak dikenal, atau alamat bentrok; tak ada yang disentuh
Cara perintah jaringan melaporkan hasilnya.

Keputusan rancangan

Satu perintah memegang setiap alamat, jadi alamat-alamat itu tak bisa saling menyimpang. Gateway dan subnet dulu ditulis dengan tangan di tempat berbeda dan akhirnya tak sinkron; menurunkan yang satu dari yang lain membuat itu mustahil. Gateway dan rentang trusted proxy ditulis ulang dalam run yang sama, jadi setiap alamat berasal dari satu sumber. Perintah ini juga satu-satunya tempat di project yang membuat Docker network, sementara service hanya bergabung ke dalamnya, jadi network dan alamat upstream web server selalu lahir dari run yang sama.

Konfigurasi dirender, tak pernah di-link ke dalam repository. Konfigurasi yang terpasang dulu berupa symlink ke working tree, sehingga git checkout biasa ikut mengubah web server yang sedang melayani trafik — dan itu sungguh terjadi: staging dan production memproksikan ke gateway lama, dan satu route yang hidup berubah jadi 502. Kini git sama sekali tak bisa menjangkau nginx, dan menjalankan tool ini tak mengotori working tree. File mana yang menyimpan satu nilai juga penting: di mesin yang punya file override lokal, alamat listening yang saya ketik ditulis ke sana, jadi ia selalu menang, setelah alamat ketikan pernah diabaikan dan konfigurasinya dirender dengan alamat lama. Template memakai placeholder @@NAME@@, karena konfigurasi nginx penuh variabel $ miliknya sendiri, dan substitusi environment biasa akan menghapus $uri diam-diam menjadi file yang tetap lolos nginx -t; render yang masih menyisakan placeholder atau direktif wajib yang kosong justru digagalkan. Partial bersama ada karena satu route pernah hilang dari satu environment dan baru ketahuan lama sesudahnya.

Ia menolak sejak awal, dan di web server yang bukan miliknya seorang ia mengembalikan apa yang bisa dikembalikan. Konfigurasi web server yang rusak menjatuhkan setiap situs yang dilayaninya. Bentrok alamat ditemukan sebelum apa pun ditulis. Docker network dibuat sebelum konfigurasi dirender, karena gateway baru harus sudah ada di host sebelum nginx bisa listen di sana. Konfigurasi lama disimpan di luar direktori yang dibaca nginx, sebab file backup di sana ikut di-parse; bila uji gagal, konfigurasi dan state yang tercatat dikembalikan, lalu server diuji sekali lagi, dan rollback yang masih gagal dilaporkan fatal dengan konfigurasi lama tetap disimpan. Hasil ujinya ditangkap dengan cara yang tak bisa dipotong oleh penanganan error yang ketat, setelah satu uji membuktikan cabang rollback tak pernah tercapai dan konfigurasi rusak tetap terpasang sementara nginx mati. Ujinya juga membedakan konfigurasi rusak dari konfigurasi yang tak bisa diuji karena kurang hak, yang menyimpan file dan stash-nya lalu mencetak perintah pemulihan, bukan menebak, dan web server yang sedang mati dinyalakan, dengan penghitung kegagalannya di-reset bila sudah mencapai batas start. Ia memakai reload bila himpunan alamat listening tak berubah, supaya domain lain tetap mempertahankan koneksinya, dan baru restart bila ada alamat yang berubah, karena reload tak pernah mem-bind alamat baru. Mode show menandai alamat host yang hilang justru karena nginx -t tak melakukannya.

Berpindah environment cukup dengan satu perintah sehari-hari. Perintah hosts membaca alamat dari state yang tercatat, jadi ia mengikuti perubahan jaringan terakhir tanpa perlu diberi tahu. Ia menjamin tepat satu alamat aktif per domain dan mem-backup file-nya sebelum menulis. Ia memanggil sudo sendiri, sama seperti perintah jaringan lewat library bersama — pilihan yang disengaja, karena perpindahan terjadi berkali-kali dalam sehari dan pilihan lainnya adalah menyunting /etc/hosts dengan tangan setiap kali. Sesudah berpindah, ia me-restart web server supaya alamat yang diubah perintah jaringan benar-benar ter-bind.

Ia tuntas walau tanpa terminal. Ia dibuat supaya tuntas juga di sesi non-interaktif, setelah dua run semacam itu pernah berhenti di tengah, dengan konfigurasi sudah tertulis tapi file environment dan network belum.

Spesifikasi

MasukanNama environment, alamat host, dan subnet; atau environment yang dirender; atau environment tujuan browser
KeluaranState jaringan yang diperbarui, konfigurasi web server hasil render, file environment yang ditulis ulang, Docker network yang dibuat ulang, dan satu blok aktif di /etc/hosts
Nilai per mesinFile override lokal di luar version control menyimpan alamat listening satu mesin; gateway tetap sama di setiap host
KeamananPemeriksaan bentrok sebelum menulis; konfigurasi diuji sebelum diterapkan dan dikembalikan bila tak valid; reload, bukan restart, bila alamat listening tak berubah; container yang terhubung ke network dimatikan dulu sebelum network itu dibuat ulang; file hosts divalidasi dan di-backup
PrasyaratDocker dan nginx di host; hak lebih tinggi hanya untuk konfigurasi web server dan /etc/hosts
Masukan, keluaran, dan jaminan toolkit ini.

Terkait

Cerita tentang melayani tiga environment dari satu nama domain yang tak bisa diganti.

Kenapa saya mengembangkan aplikasi dengan domain sungguhan dan HTTPS sungguhan, yang menjadi praktis berkat perpindahan hosts ini.

Prosedur rilis, tempat render ulang konfigurasi selalu menyusul setiap pull di server.

Setiap script mengikuti bentuk yang saya berikan pada setiap tool kecil, dalam varian Bash-nya.

Toolkit yang membangun environment staging di atas network yang dicatat toolkit ini.

Kenapa setiap environment di satu mesin butuh subnet, network, dan identitasnya sendiri.

Perintah pendek yang saya pakai untuk membaca network mana saja yang ada dan subnet mana yang dipegang tiap stack.

Istilah

Subnet dan gateway
Rentang alamat satu Docker network, dan alamat di sisi host tempat container-container di dalamnya dijangkau.
Alamat listening
Alamat dan port tempat web server menerima koneksi; di sini, garis yang memisahkan satu environment dari yang lain.
Reload dan restart
Reload memuat konfigurasi baru sambil mempertahankan koneksi yang terbuka; restart mematikan lalu menyalakan server, satu-satunya cara mem-bind alamat baru.
File hosts
File lokal /etc/hosts yang memetakan nama ke alamat sebelum DNS ditanya.
Render template
Menghasilkan file konfigurasi dengan mengisi placeholder di template memakai nilai yang tercatat.
Trusted proxy
Rentang alamat yang dipercaya service ketika ia melaporkan alamat client aslinya.

Technologies covered

  • Bash
  • Docker
  • nginx

About the author

Photo of Romi Fadli

Romi Fadli, S.Kom.

Solution Architect · Backend Engineer · Embedded Systems

In my day job I work as a solution architect. I design the system, lead the team that builds it — quality assurance, backend developers, a UI developer, DevOps and DevSecOps — and write the most critical modules myself, such as a certificate authority, a long-term PDF signer, and the core API of a personnel system.

I work across the whole stack that a running system actually needs. On the hardware side that means PCB design, microcontrollers, and embedded firmware — including RISC-V boards running FreeRTOS and Embassy, speaking MQTT over mutually authenticated TLS on a microcontroller with 64 KB of SRAM.

Most of my day-to-day work is software: Rust backends and API modules built on Clean Architecture, an OAuth2/OpenID Connect authorization server written from scratch, PAdES document signing, and certificate authorities — root CAs, timestamping authorities, and OCSP responders. I also build the frontends that sit on top of them.

Running all of that means infrastructure: Docker Compose stacks, networking, Mikrotik and RADIUS, observability with OpenTelemetry, and a steady habit of writing command-line tools and utilities for Linux when the existing ones do not fit.

Share

Enjoyed this?

Get an email when a new article is published.

Referenced by

An old layout with a grey banner and a new structure with a green banner, each holding a blue database, a purple document store, and an orange telemetry store; three coloured paths pass through one export package marked with a green check

Empat perintah yang memindahkan stack dari layout lama ke struktur baru melintasi versi mayor: export tanpa mengubah data sumber, import tiap store sesuai cara yang diizinkan versinya, verifikasi apa yang benar-benar tiba, dan rename modul sambil memindahkan datanya.

11 min read Read more →
A staging configuration with an orange banner and a production configuration with a green banner; ordinary keys cross over with arrows, while a locked secret is stopped halfway by a red cross and production keeps its own lock

Tiga perintah yang membawa rilis teruji ke production tanpa menimpa apa yang dimilikinya: mempromosikan struktur konfigurasi tapi mempertahankan rahasia dan alamatnya, menolak menyalin rahasia baru, dan menerapkan migration yang dibawa image.

10 min read Read more →
A purple root circle linked to a blue and an orange intermediate circle, which lead to a signed document with a green seal and to a clock.

Aurograf

DevOps

Platform tanda tangan digital Pemerintah Kota Tangerang Selatan: penanda tangan membuktikan identitasnya, menandatangani PDF hingga PAdES B-LTA dengan sertifikat dari otoritas milik platform sendiri, dan siapa pun bisa memverifikasinya — versi 2, yang saya rancang, bangun, dan operasikan.

10 min read Read more →

Related Articles

A stack of Markdown documents and an orange arrow leading to a browser page with a side menu, a heading, paragraphs, a dark code panel, and a table of contents with its active entry highlighted

Satu script yang mengubah dokumentasi Markdown satu project menjadi situs statis yang terbuka dari folder tanpa server maupun internet: menu, daftar isi yang mengikuti pembaca, tabel yang tak pernah terpotong, kode dengan tombol salin, dan tautan yang tetap berfungsi.

7 min read Read more →
An old layout with a grey banner and a new structure with a green banner, each holding a blue database, a purple document store, and an orange telemetry store; three coloured paths pass through one export package marked with a green check

Empat perintah yang memindahkan stack dari layout lama ke struktur baru melintasi versi mayor: export tanpa mengubah data sumber, import tiap store sesuai cara yang diizinkan versinya, verifikasi apa yang benar-benar tiba, dan rename modul sambil memindahkan datanya.

11 min read Read more →
Three image layer stacks, each with a version tag of its own colour, blue, orange, and green, each leading to an archive file banded in the same colour

Perintah yang memberi versi tersendiri pada tiap modul stack, mem-build image-nya di bawah tag yang berarti tepat satu build, menolak memakai ulang versi atau menelan compile yang gagal, dan mengarsipkan image menurut nama dan tag supaya versi tak saling menimpa.

7 min read Read more →