Network & Hosts Toolkit
On this page
- Sekilas
- Yang dikerjakannya
- A. Menetapkan alamat environment dengan satu perintah
- B. Merender konfigurasi web server dari template
- C. Menolak sebelum menyentuh apa pun
- D. Mengarahkan browser ke satu environment
- E. Memperlihatkan keadaan ketiganya
- Cara saya memakainya
- Keputusan rancangan
- Spesifikasi
- Terkait
- Istilah
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
| Tools | set-network, switch-env |
|---|---|
| Bentuk | Script command-line yang berbagi satu library pembantu |
| Bahasa | Bash dengan awk untuk substitusi literal, yang mengendalikan Docker dan nginx |
| Status | Stabil, berjalan di production |
| Kode sumber | Privat |
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
| Tempat | Yang diubah dalam satu run |
|---|---|
| State jaringan yang tercatat | gateway dan alamat listening environment itu |
| Konfigurasi web server | dirender ulang dari template, diuji, lalu diterapkan |
| Folder environment | gateway, rentang trusted proxy, entri host, endpoint service, dan nilai fallback |
| Docker network | dibuat ulang dengan subnet baru |
| Exit code | Arti |
|---|---|
| 0 | environment sudah memakai alamat barunya, atau memang tak ada yang perlu diubah |
| 1 | ada langkah yang gagal, jumlah argumennya salah, atau state tercatat kehilangan satu kunci; konfigurasi web server yang tak valid sudah dikembalikan |
| 2 | nilai tak sah, opsi tak dikenal, atau alamat bentrok; tak ada yang disentuh |
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
| Masukan | Nama environment, alamat host, dan subnet; atau environment yang dirender; atau environment tujuan browser |
|---|---|
| Keluaran | State 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 mesin | File override lokal di luar version control menyimpan alamat listening satu mesin; gateway tetap sama di setiap host |
| Keamanan | Pemeriksaan 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 |
| Prasyarat | Docker dan nginx di host; hak lebih tinggi hanya untuk konfigurasi web server dan /etc/hosts |
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/hostsyang 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