Writing

Blog

Catatan lapangan soal homelab, jaringan, dan hal-hal yang saya bongkar lalu rakit ulang.

Teks

Membangun Ulang Situs Ini di Chyrp Lite

Ditulis oleh Gustama Dimas

Situs ini berjalan di Chyrp Lite — mesin blog self-hosted kecil yang melakukan kira-kira apa yang saya butuhkan dan tidak lebih. Sudah cukup lama berdiri dengan tema bawaan, yang sepenuhnya memadai dan sepenuhnya anonim. Akhirnya saya tulis ulang.

Yang salah

Tidak banyak, jujur saja. Temanya bekerja. Tapi tiga hal mengganggu saya.

Pertama, navigasinya mendaftar sepuluh halaman dalam satu daftar rata, dan tujuh di antaranya hanya ada untuk meng-embed layanan di dalam iframe. Beberapa embed itu menunjuk endpoint yang tidak lagi menjawab, atau menolak di-frame sama sekali. Sidebar menawarkan tautan ke panel yang rusak.

Kedua, tata letaknya satu kolom sempit dengan sidebar dan tanpa rasa situs itu untuk apa. Pengunjung mendarat dan tahu nama saya. Itu saja.

Ketiga, kontennya daftar fakta tanpa jalan masuk.

Yang saya ubah

Homepage yang sungguhan. Alih-alih menjatuhkan pengunjung langsung ke indeks blog, sekarang ada halaman depan: siapa saya, di mana, apa yang saya kerjakan, dan empat cara masuk lebih dalam. Ia menjawab pertanyaan yang situs lama biarkan menggantung.

Navigasi yang mencerminkan struktur sebenarnya. Halaman per-layanan hilang dari menu. Mereka masih ada — setiap tautan lama tetap bisa dibuka — tapi halaman Homelab sekarang menautkan langsung ke tiap layanan, dengan deskripsi satu baris tentang apa itu. Tujuh panel iframe menjadi satu indeks yang terbaca.

Tema yang punya pendapat. IBM Plex Sans dan Plex Mono, di-host sendiri ketimbang diambil dari CDN. Monospace disisihkan untuk label, metadata, dan apa pun yang terbaca sebagai data. Paletnya off-white hangat dengan satu aksen tembaga, dipakai untuk tautan dan hampir tidak untuk apa pun lagi.

Daftar layanan ditata seperti rak: nomor indeks, nama, fungsinya, dan apakah ia terbuka ke dunia atau hanya terjangkau di LAN. Kolom terakhir itu yang jujur — ia memberi tahu Anda sebelum mengklik apakah tautannya akan meminta kata sandi.

Aksesibilitas bukan tambahan

  • Tautan lompat untuk pengguna keyboard, karena sidebar muncul lebih dulu di markup
  • Garis fokus yang terlihat di setiap elemen interaktif, dalam warna aksen
  • prefers-reduced-motion dihormati — tanpa transisi, tanpa smooth scrolling, untuk siapa pun yang memintanya
  • prefers-contrast: more mendorong batas dan teks ke hitam penuh
  • Stylesheet cetak, karena halaman-halaman ini layak disimpan di atas kertas

Yang akan saya lakukan berbeda

Tulis kontennya sebelum temanya.

Saya menghabiskan waktu mendesain komponen — hero, status strip, tabel rak — lalu harus kembali dan menulis ulang teks halaman agar cocok. Desainnya jadi baik-baik saja. Urutannya yang terbalik.

Lain kali: putuskan apa yang halaman perlu katakan, lalu putuskan bagaimana ia perlu terlihat.

Teks

Gateway yang Lupa Cara Mengingat

Ditulis oleh Gustama Dimas

Pukul 00:32 sebuah baris log mulai berulang. Pukul 16:45 ia sudah muncul 785 kali.

[memory] sync failed … Plugin "memory-core" runtime is no longer active

Plugin memori di gateway asisten saya berhenti bekerja. Bukan crash — sesuatu yang lebih buruk. Ia masih terpasang, masih melaporkan diri sebagai termuat, dan sama sekali tidak bisa melakukan apa pun.

Perbaikan yang salah

Saya memuat ulang plugin. Errornya berhenti.

Selama empat belas menit.

Lalu trafik naik, dan errornya kembali persis seperti sebelumnya. Keheningan empat belas menit itu hal paling menyesatkan di seluruh insiden ini. Ia tampak seperti perbaikan. Bukan. Itu jendela menganggur tanpa apa pun tersisa untuk gagal.

Penyebab sebenarnya

Saya berhenti menebak dan membaca sumber runtime-nya.

Saat plugin dimuat ulang panas, gateway membangun generasi registry yang baru. Apa pun yang masih memegang referensi ke generasi lama sekarang memegang handle mati. Jembatan sinkronisasi memori — bagian yang meng-embed dan mengindeks konten — menangkap referensinya saat startup dan tidak pernah menunjuk ulang. Setiap panggilan setelah reload melempar.

Inilah kenapa memuat ulang plugin selamanya tidak akan pernah berhasil. Pluginnya baik-baik saja. Yang memanggilnya memegang pointer basi, dan tidak ada reload plugin yang bisa memperbaiki itu.

Perbaikannya

Restart gateway penuh. Itu membangun ulang setiap generasi dari nol, jadi jembatan menangkap handle yang hidup lagi.

Angkanya sebelum dan sesudah: 815 kemunculan error sepanjang hari, terakhir pukul 16:52:03. Setelah restart, nol. Bukan "nol sejauh ini" — nol di setiap sinkronisasi sejak itu.

Dua hal yang layak diingat

CLI sehat sepanjang waktu.

Sepanjang 785 kegagalan itu, memory status --deep melaporkan embeddings siap, vector store siap, semantic vectors siap. Lapisan datanya tidak pernah rusak. Hanya jalur di dalam gateway yang rusak.

Kalau saya memercayai perintah status itu dan berhenti di situ, saya akan menyimpulkan semuanya baik-baik saja — dan salah dengan cara yang penting. Pemeriksaan kesehatan yang menguji jalur yang salah lebih buruk daripada tidak ada pemeriksaan, karena ia memberi Anda keyakinan yang tidak Anda peroleh.

Jendela sepi bukan bukti.

Saya memeriksa setelah reload, tidak melihat apa pun selama empat belas menit, dan hampir menyebutnya beres. Pemeriksaan yang benar adalah di bawah beban, atau dengan pemicu sengaja. Keheningan saat menganggur tidak membuktikan apa pun tentang jalur kode yang hanya berjalan saat ada kerja.

Yang kedua itu sudah saya catat dengan benar, karena saya pernah membuat kesalahan yang sama dengan kostum berbeda.

Teks

MCB Trip Pukul 18:57

Ditulis oleh Gustama Dimas

Pukul 18:57, tiga mesin saya mati dalam rentang sekitar empat menit satu sama lain.

Saat itu saya belum tahu. Yang saya tahu: gateway sudah kembali dan melaporkan dirinya sehat, dan beberapa sesi tampak terpotong di tengah kalimat. Dugaan pertama — dan yang salah — adalah kesalahan perangkat lunak.

Lalu saya tahu apa yang sebenarnya terjadi: pemadaman listrik singkat. MCB utama trip. Beban berlebih.

Linimasa

msi-server    18:57
.185          19:01
pi-server     19:01:33
arm-server    tidak terpengaruh — uptime 3 minggu

Baris terakhir itu yang menarik.

arm-server ada di sirkuit yang berbeda. Pemadaman mengambil satu jalur, bukan seluruh rumah. Artinya mesin yang mati dan mesin yang tidak justru memberi tahu saya sesuatu tentang instalasi listriknya — bukan tentang mesinnya.

Bentuk pemulihannya

Setiap host yang terdampak kembali sendiri. Itu memang inti kenapa saya mengaturnya begitu, tapi layak dikonfirmasi ketimbang diasumsikan:

  • Proses gateway kembali, nol restart, probe kesehatan 200
  • Tidak ada error sinkronisasi memori sejak boot — lembar bersih
  • Kanal pesan tersambung lagi pukul 19:00:36
  • Tidak ada error I/O kernel, semua mount utuh

Di .185 ada dua pesan journal corrupted or uncleanly shut down. Itu terdengar lebih buruk daripada kenyataannya. journald menyadari shutdown tidak bersih dan melakukan persis apa yang dirancang untuknya. Ada juga pemeriksaan filesystem advisory pada partisi FAT — advisory artinya ia ingin perhatian, bukan bahwa ada yang rusak.

Bagian yang saya kurang senang

Dua run agen terputus di msi-server.

Satu context overflow pada sesi yang bekerja berat sepanjang hari. Itu akan gagal juga; pemadaman hanya sampai lebih dulu. Satu lagi korban asli — panggilan LLM yang sedang berjalan saat lampu mati.

Tidak ada kehilangan data. Keduanya pekerjaan yang harus diulang. Itulah biaya jujur sebuah pemadaman: bukan korupsi, hanya pengulangan.

Di mana UPS sebenarnya berada

Ini yang saya salah asumsikan.

Saya membayangkan UPS mencakup "server-servernya". Ternyata tidak. UPS kecil itu mencakup inti router, arm-server, dan CCTV. Sisanya — termasuk dua mesin yang paling saya pedulikan — langsung dari jala-jala.

Itu menjelaskan pola di atas sepenuhnya. arm-server selamat karena terlindungi. Sisanya tidak, karena tidak.

Yang akan saya ubah

Tidak ada soal perangkat lunak. Semuanya pulih tanpa dihadiri, dan itu tes yang penting.

Yang saya ubah adalah urutan prioritas. Host gateway sekarang melakukan kerja nyata, dan itu satu mesin di mana shutdown tidak bersih membuat saya kehilangan sesi ketimbang sekadar reboot. Itu masalah seukuran UPS.

Pelajaran bukan "beli UPS". Tapi: cari tahu mesin mana berada di sirkuit mana sebelum Anda perlu tahu.

Teks

Dua Mesin, Satu Utas

Ditulis oleh Gustama Dimas

Saya punya dua mesin yang penting.

msi-server yang lebih baru — MSI Cubi 5 kecil yang menjalankan Ubuntu Server, dan kotak tempat gateway asisten saya tinggal. .185 adalah desktop lama, masih bekerja berguna, masih menyimpan beberapa hal yang belum saya migrasikan.

Untuk waktu yang lama satu-satunya saluran antara keduanya adalah saya sendiri. Saya melihat sesuatu di satu mesin, berjalan ke mesin lain, dan mengetik ulang. Itu berjalan baik sampai tidak.

Jadi saya membangun relay. Bukan yang pintar — dua pipa satu arah.

Pipa satu: .185 → saya

Skrip kecil di .185 mengirim pesan ke endpoint HTTPS di gateway. Terautentikasi token, dibatasi ke satu agen, dan dikirim ke ponsel saya dengan label 📡 .185 supaya saya selalu tahu mesin mana yang sedang bicara.

Bagian pentingnya adalah apa yang tidak dilakukannya. Tidak ada apa pun di .185 yang mendengarkan koneksi masuk untuk ini. Mesin itu hanya membuat permintaan keluar. Tidak ada port baru, tidak ada permukaan serangan baru.

Pipa dua: saya → .185

Ini bagian yang menarik, karena desain yang jelas terlihat benar justru salah.

Pendekatan cermin adalah endpoint HTTP di .185 yang saya kirimi permintaan. Saya menolaknya. Mesin itu punya sejarah: proses gateway yang kadang menggantung, dan basis data agen yang sudah cukup besar untuk melampaui jendela konteksnya saat kerja nyata. Menambahkan permukaan masuk yang selalu mendengarkan ke kotak dengan sifat seperti itu adalah cara Anda berakhir dengan layanan yang mati pukul 3 pagi tanpa jejak kenapa.

Sebagai gantinya saya memakai ulang sesuatu yang sudah dipercaya dan sudah teruji: SSH.

Alurnya satu perintah:

  1. Saya memutuskan mengirim sesuatu ke .185
  2. Skrip di msi-server membuka koneksi SSH
  3. Ia menjalankan CLI agen di sana terhadap session key yang tetap
  4. Balasan agen kembali lewat stdout
  5. Saya teruskan ke utas obrolan

Satu perjalanan pulang-pergi. Tidak ada port baru yang terbuka di mana pun.

Bentuknya saat berhasil

Empat tes, semuanya end to end:

transport smoke     → PONG-185-FASE2
simple message      → FASE2-V2-OK
tool use on .185    → returned hostname, uptime, version
final               → FASE2-FINAL-OK

Yang ketiga yang paling penting. Ia tidak hanya membuktikan pipa bisa membawa teks — ia membuktikan bahwa permintaan yang berasal dari satu mesin bisa mencapai mesin lain, menyebabkan mesin itu menjalankan perintah shell di sana, dan membawa keluaran aslinya kembali. Itu bedanya notifikasi dengan kendali jarak jauh.

Batasannya, dinyatakan jujur

Relay ini sinkron. Permintaan menunggu balasan, dan timeout-nya 300 detik secara default. Untuk obrolan dan kueri pendek itu cukup lega. Untuk apa pun yang berat — build sepuluh menit, tugas coding panjang — ia akan timeout, dan pekerjaannya jadi yatim.

Perbaikannya adalah varian async: tembak permintaan, dapat konfirmasi, kirim hasilnya saat siap. Saya belum membangunnya, karena belum ada yang membutuhkannya. Menulisnya sekarang berarti menulis kode untuk masalah yang belum saya punya.

Yang saya ambil dari ini

Antarmuka terbaik antara dua mesin biasanya yang sudah ada di sana.

SSH sudah dipercaya, sudah berkunci, sudah dipahami. Endpoint HTTP akan lebih modern dan kurang andal. Pertanyaannya bukan "apa cara yang benar untuk melakukan ini" — tapi "apa hal baru terkecil yang bisa saya tambahkan supaya ini bekerja."

Di sini jawabannya ternyata: tidak ada, di sisi penerima. Hanya skrip dan kunci yang sudah ada.

Teks

Opo-tech Support

Ditulis oleh Gustama Dimas

View this post on Instagram

A post shared by opo-tech support (@opotech.support)