<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: hardyweb</title>
    <description>The latest articles on DEV Community by hardyweb (@hardyweb).</description>
    <link>https://dev.to/hardyweb</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F879715%2Fc1fc8a79-e567-4098-9a15-f1e401fcdb47.png</url>
      <title>DEV Community: hardyweb</title>
      <link>https://dev.to/hardyweb</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hardyweb"/>
    <language>en</language>
    <item>
      <title>Penjelasan Layman: Agent Harness (PiG / KiloCode)</title>
      <dc:creator>hardyweb</dc:creator>
      <pubDate>Sat, 10 Oct 2026 13:19:38 +0000</pubDate>
      <link>https://dev.to/hardyweb/penjelasan-layman-agent-harness-pig-kilocode-34bk</link>
      <guid>https://dev.to/hardyweb/penjelasan-layman-agent-harness-pig-kilocode-34bk</guid>
      <description>&lt;p&gt;Dokumen ini menerangkan lima komponen utama dalam workflow coding agent yang aku gunakan. Tujuannya mudah: memahami bagaimana agent menerima arahan, menyimpan konteks, mempelajari cara kerja dan mengikuti prinsip pembangunan perisian.&lt;/p&gt;

&lt;p&gt;Kita tak perlu bermula dengan jargon teknikal. Kita gunakan analogi pekerja, buku panduan dan buku log supaya konsep lebih mudah difahami.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Nota:&lt;/strong&gt; Dokumen ini menggabungkan konsep umum coding agent dengan konfigurasi peribadi aku. Tidak semua agent mempunyai mekanisme atau struktur fail yang sama. Perincian teknikal perlu dirujuk kepada dokumentasi agent masing-masing.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Skills — Buku Panduan Kerja
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Apa itu Skills?
&lt;/h3&gt;

&lt;p&gt;Bayangkan agent AI sebagai pekerja baru yang sangat pintar, tetapi belum tahu cara kerja di tempat kita.&lt;/p&gt;

&lt;p&gt;Dia tahu menulis kod, memahami arahan dan menyelesaikan masalah. Tetapi dia mungkin belum tahu:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Macam mana kita suka commit message ditulis.&lt;/li&gt;
&lt;li&gt;Format laporan bulanan yang kita gunakan.&lt;/li&gt;
&lt;li&gt;Langkah-langkah deployment ke server.&lt;/li&gt;
&lt;li&gt;Standard keselamatan dalam projek.&lt;/li&gt;
&lt;li&gt;Cara kita mengurus projek Laravel.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Skills ialah panduan yang mengajar agent cara melakukan sesuatu tugas mengikut keperluan kita.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Bezakan Capability dengan Knowledge
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Perkara&lt;/th&gt;
&lt;th&gt;Extension / Tool&lt;/th&gt;
&lt;th&gt;Skill&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Fungsi&lt;/td&gt;
&lt;td&gt;Memberi keupayaan melakukan sesuatu&lt;/td&gt;
&lt;td&gt;Memberi panduan bagaimana melakukan sesuatu&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Contoh&lt;/td&gt;
&lt;td&gt;Menjalankan arahan Git&lt;/td&gt;
&lt;td&gt;Menulis commit message mengikut format projek&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bentuk&lt;/td&gt;
&lt;td&gt;Kod, integrasi atau mekanisme alat&lt;/td&gt;
&lt;td&gt;Arahan dan bahan rujukan&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Kegunaan&lt;/td&gt;
&lt;td&gt;Agent perlu melakukan sesuatu tindakan&lt;/td&gt;
&lt;td&gt;Agent perlu mengikuti kaedah kerja tertentu&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Contoh mudah:&lt;/p&gt;

&lt;p&gt;Extension atau tool memberikan agent tangan untuk menggunakan Git. Skill pula mengajarnya cara menulis commit message yang kita kehendaki.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bagaimana Skills berfungsi?
&lt;/h3&gt;

&lt;p&gt;Dalam PiG, salah satu bentuk skill ialah fail &lt;code&gt;SKILL.md&lt;/code&gt; yang disimpan dalam direktori skill.&lt;/p&gt;

&lt;p&gt;Contoh:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/.pig/skills/commit/SKILL.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Kandungan fail boleh menerangkan nama skill, tujuan penggunaannya dan arahan yang perlu diikuti.&lt;/p&gt;

&lt;p&gt;Contoh ringkas:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;commit&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Tulis commit message mengikut format projek.&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

Gunakan format:

type(scope): ringkasan

Ringkasan mestilah padat dan jelas.
Terangkan sebab perubahan dalam body jika perlu.
Jangan masukkan perubahan yang tidak berkaitan.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Apabila agent menemui skill tersebut, ia boleh menggunakan maklumat dan arahan yang disediakan apabila skill berkenaan diperlukan.&lt;/p&gt;

&lt;p&gt;Cara pemuatan dan penggunaan skill bergantung pada implementasi agent. Jangan anggap semua agent membaca keseluruhan kandungan setiap skill pada permulaan sesi.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bagaimana PiG menemui Skills?
&lt;/h3&gt;

&lt;p&gt;PiG menyokong pemuatan skill secara eksplisit, termasuk penggunaan pilihan &lt;code&gt;--skill&lt;/code&gt;, serta mekanisme discovery daripada direktori yang disokong.&lt;/p&gt;

&lt;p&gt;Contoh:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pig &lt;span class="nt"&gt;--skill&lt;/span&gt; commit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Direktori yang digunakan perlu mengikut struktur dan konfigurasi yang disokong oleh versi PiG berkenaan.&lt;/p&gt;

&lt;h3&gt;
  
  
  Kenapa Skills berguna?
&lt;/h3&gt;

&lt;p&gt;Tanpa skill, kita mungkin perlu menerangkan semula cara kerja yang sama berulang kali.&lt;/p&gt;

&lt;p&gt;Dengan skill, kita boleh menyimpan panduan tersebut dan menggunakannya semula.&lt;/p&gt;

&lt;p&gt;Ibarat SOP (Standard Operating Procedure) untuk pekerja manusia.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ringkasan:&lt;/strong&gt; Skills ialah panduan kerja khusus yang boleh digunakan semula supaya agent dapat mengikuti kaedah kerja yang kita kehendaki.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. AGENTS.md — Buku Peraturan Tetap
&lt;/h2&gt;

&lt;p&gt;Kalau skill ialah panduan untuk tugas tertentu, &lt;code&gt;AGENTS.md&lt;/code&gt; pula boleh digunakan untuk menetapkan peraturan umum dan arahan bagi agent yang bekerja dalam sesuatu projek.&lt;/p&gt;

&lt;p&gt;Contohnya, sebelum mula bekerja, kita mahu agent memahami peraturan berikut:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Jangan mengubah fail sensitif tanpa kebenaran.&lt;/li&gt;
&lt;li&gt;Periksa struktur projek sebelum membuat perubahan.&lt;/li&gt;
&lt;li&gt;Gunakan Form Request untuk pengesahan input Laravel.&lt;/li&gt;
&lt;li&gt;Jangan membuat deployment tanpa kelulusan.&lt;/li&gt;
&lt;li&gt;Sahkan hasil perubahan sebelum menyatakan kerja selesai.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Arahan seperti ini sesuai diletakkan dalam fail arahan projek.&lt;/p&gt;

&lt;h3&gt;
  
  
  Apa yang patut ada dalam AGENTS.md?
&lt;/h3&gt;

&lt;p&gt;Dalam workflow aku, kandungannya merangkumi beberapa perkara.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Bahagian&lt;/th&gt;
&lt;th&gt;Maksud&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Global Principles&lt;/td&gt;
&lt;td&gt;Prinsip asas seperti keselamatan dan backup&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Workspace &amp;amp; Project Boundaries&lt;/td&gt;
&lt;td&gt;Had kawasan kerja agent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Workflow Preferences&lt;/td&gt;
&lt;td&gt;Cara kerja yang disukai, termasuk Laravel, Go dan Git&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;State &amp;amp; Memory&lt;/td&gt;
&lt;td&gt;Arahan tentang cara membaca dan mengemas kini konteks kerja&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Approval Gates&lt;/td&gt;
&lt;td&gt;Tindakan yang memerlukan kelulusan&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Verification&lt;/td&gt;
&lt;td&gt;Keperluan mengesahkan hasil sebelum melaporkan kejayaan&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Ini ialah susunan yang aku gunakan untuk mengurus workflow sendiri, bukan format wajib bagi semua coding agent.&lt;/p&gt;

&lt;h3&gt;
  
  
  Kenapa nama fail penting?
&lt;/h3&gt;

&lt;p&gt;Agent tidak semestinya membaca semua fail Markdown dalam direktori projek.&lt;/p&gt;

&lt;p&gt;Ia biasanya mempunyai mekanisme tertentu untuk mencari fail arahan yang dikenali. PiG mempunyai aturan pemuatan konteks tersendiri, manakala KiloCode juga mempunyai mekanisme arahan dan konfigurasi sendiri.&lt;/p&gt;

&lt;p&gt;Oleh itu, jangan menganggap fail bernama &lt;code&gt;Agent.md&lt;/code&gt;, &lt;code&gt;AGENTS.md&lt;/code&gt; atau &lt;code&gt;CLAUDE.md&lt;/code&gt; akan diproses dengan cara yang sama oleh semua agent.&lt;/p&gt;

&lt;p&gt;Jika kita mahu menggunakan fail arahan tertentu, semak dokumentasi agent yang digunakan dan pastikan fail itu benar-benar dimuatkan.&lt;/p&gt;

&lt;h3&gt;
  
  
  Kenapa AGENTS.md perlu ringkas?
&lt;/h3&gt;

&lt;p&gt;Arahan yang sentiasa dimasukkan ke dalam konteks agent menggunakan sebahagian daripada token yang tersedia.&lt;/p&gt;

&lt;p&gt;Sebab itu, aku lebih suka meletakkan peraturan umum yang penting dalam fail arahan utama. Panduan terperinci untuk tugas tertentu boleh disimpan dalam skills atau dokumen rujukan berasingan.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ringkasan:&lt;/strong&gt; &lt;code&gt;AGENTS.md&lt;/code&gt; ialah tempat untuk meletakkan arahan dan batas kerja agent. Pastikan kandungannya jelas, relevan dan benar-benar dibaca oleh agent yang digunakan.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. brain/ — Buku Ingatan Kerja
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Masalah yang cuba diselesaikan
&lt;/h3&gt;

&lt;p&gt;Apabila sesi perbualan tamat, agent mungkin tidak lagi mempunyai keseluruhan konteks kerja yang diperlukan dalam sesi seterusnya.&lt;/p&gt;

&lt;p&gt;Bayangkan kita sedang membangunkan sistem Laravel. Kita sudah memeriksa database, mengubah beberapa fail dan mengenal pasti satu masalah. Esok, kita membuka sesi baru.&lt;/p&gt;

&lt;p&gt;Kalau konteks tidak disimpan, kita mungkin terpaksa mengulangi pemeriksaan yang sama.&lt;/p&gt;

&lt;p&gt;Di sinilah konsep &lt;code&gt;brain/&lt;/code&gt; berguna.&lt;/p&gt;

&lt;p&gt;Dalam workflow aku, &lt;code&gt;brain/&lt;/code&gt; ialah direktori untuk menyimpan catatan kerja yang boleh dibaca semula oleh agent pada sesi berikutnya.&lt;/p&gt;

&lt;p&gt;Ia bukan bermaksud model AI tiba-tiba mempunyai ingatan kekal. Maklumat itu kekal kerana kita menyimpannya dalam fail dan mengarahkan agent supaya merujuknya semula.&lt;/p&gt;

&lt;h3&gt;
  
  
  Analogi buku log jurutera
&lt;/h3&gt;

&lt;p&gt;Buku log seorang jurutera biasanya merekodkan:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Apa yang sudah dilakukan.&lt;/li&gt;
&lt;li&gt;Masalah yang ditemui.&lt;/li&gt;
&lt;li&gt;Keputusan yang dibuat.&lt;/li&gt;
&lt;li&gt;Perkara yang masih belum selesai.&lt;/li&gt;
&lt;li&gt;Langkah seterusnya.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Konsep yang sama digunakan dalam &lt;code&gt;brain/&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Contoh struktur brain/
&lt;/h3&gt;

&lt;p&gt;Berikut ialah contoh struktur yang aku gunakan sebagai konvensyen kerja:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;brain/
├── task.md
├── walkthrough.md
├── architecture.md
├── ai_guidelines.md
├── gaya-penulisan.md
└── decisions/
    ├── 001-database.md
    └── 002-authentication.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fungsi setiap fail:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Fail&lt;/th&gt;
&lt;th&gt;Kegunaan&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;task.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Status tugas, masalah semasa dan langkah seterusnya&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;walkthrough.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Rekod perjalanan sesi kerja&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;architecture.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Gambaran struktur dan hubungan komponen sistem&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;decisions/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Rekod keputusan teknikal dan sebab pemilihannya&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ai_guidelines.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Prinsip kerja dan pendekatan pembangunan&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gaya-penulisan.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Panduan gaya penulisan&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Struktur ini bukan struktur wajib PiG atau KiloCode. Ia ialah reka bentuk dokumentasi yang boleh disesuaikan mengikut projek.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mental Anchor — Penanda untuk sambung kerja
&lt;/h3&gt;

&lt;p&gt;Satu idea yang aku gunakan ialah &lt;em&gt;Mental Anchor&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Pada akhir catatan sesi, agent perlu menyatakan lokasi sebenar untuk menyambung kerja.&lt;/p&gt;

&lt;p&gt;Contoh:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## Status Semasa&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; Migration telah diperiksa.
&lt;span class="p"&gt;-&lt;/span&gt; Form Request telah dikemas kini.
&lt;span class="p"&gt;-&lt;/span&gt; Feature test masih gagal pada kes authorization.

&lt;span class="gs"&gt;**Mental Anchor:**&lt;/span&gt;
Sambung dengan menyiasat kegagalan authorization
dalam feature test sebelum mengubah kod production.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Mental Anchor membantu agent mengetahui titik permulaan yang sesuai untuk sesi seterusnya.&lt;/p&gt;

&lt;p&gt;Namun, catatan ini masih perlu disahkan dengan keadaan sebenar repository. Fail boleh berubah selepas catatan ditulis.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dua jenis brain dalam workflow aku
&lt;/h3&gt;

&lt;p&gt;Aku membezakan catatan global dengan catatan khusus projek.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Jenis&lt;/th&gt;
&lt;th&gt;Contoh lokasi&lt;/th&gt;
&lt;th&gt;Tujuan&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Global&lt;/td&gt;
&lt;td&gt;&lt;code&gt;~/.config/kilo/brain/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Prinsip dan catatan umum workflow&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Projek&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;projek&amp;gt;/.agents/brain/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Konteks dan status projek tertentu&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Lokasi ini ialah konvensyen peribadi aku, bukannya lokasi standard yang dijamin dibaca secara automatik oleh PiG atau KiloCode.&lt;/p&gt;

&lt;p&gt;Agent perlu diarahkan untuk membaca lokasi yang betul. Jika ada catatan global dan projek, aturan keutamaan juga perlu ditetapkan supaya konteks tidak bercanggah.&lt;/p&gt;

&lt;h3&gt;
  
  
  Peraturan penting
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Jangan simpan password, API token atau rahsia lain dalam fail brain.&lt;/li&gt;
&lt;li&gt;Catat perkara yang benar-benar berlaku, bukan perkara yang diandaikan.&lt;/li&gt;
&lt;li&gt;Nyatakan masalah yang belum selesai dengan jelas.&lt;/li&gt;
&lt;li&gt;Rekodkan keputusan penting dan sebabnya.&lt;/li&gt;
&lt;li&gt;Gunakan Git untuk mengesan perubahan pada fail dokumentasi apabila sesuai.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Ringkasan:&lt;/strong&gt; &lt;code&gt;brain/&lt;/code&gt; ialah sistem catatan kerja yang membantu mengekalkan konteks antara sesi, dengan syarat agent membaca dan mengemas kini catatan tersebut dengan betul.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. ai_guidelines.md — Falsafah Kerja dan Cara Berfikir
&lt;/h2&gt;

&lt;p&gt;Kalau &lt;code&gt;AGENTS.md&lt;/code&gt; menerangkan arahan dan batas kerja, &lt;code&gt;ai_guidelines.md&lt;/code&gt; pula menerangkan prinsip yang menjadi panduan kepada cara kerja aku.&lt;/p&gt;

&lt;p&gt;Ia bukan fail konfigurasi ajaib. Ia ialah dokumen yang mengandungi prinsip yang mahu aku kekalkan dalam pembangunan perisian dengan bantuan AI.&lt;/p&gt;

&lt;h3&gt;
  
  
  Analogi mudah
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;AGENTS.md&lt;/code&gt;: Jangan langgar lampu merah.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ai_guidelines.md&lt;/code&gt;: Aku percaya keselamatan lebih penting daripada sampai cepat.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Yang pertama menetapkan arahan. Yang kedua menerangkan prinsip di sebalik cara kita bekerja.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prinsip utama
&lt;/h3&gt;

&lt;p&gt;Dalam workflow aku, antara prinsip yang penting ialah:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Manusia memahami dan bertanggungjawab&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;AI membantu menyediakan penyelesaian, tetapi aku perlu memahami, mengesahkan dan bertanggungjawab terhadap keputusan akhir.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Kod mudah mengatasi kod yang terlalu clever&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Penyelesaian yang mudah dibaca dan diselenggara biasanya lebih sesuai daripada kod yang kelihatan hebat tetapi sukar difahami.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Keselamatan bermula sejak reka bentuk&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Security bukan kerja tambahan selepas sistem siap. Ia perlu dipertimbangkan sejak awal pembangunan.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Periksa sebelum mengubah&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Agent perlu memahami keadaan sebenar projek sebelum membuat perubahan. Jangan mengandaikan struktur, dependency atau konfigurasi tanpa pemeriksaan.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Git dan deployment kekal di bawah kawalan manusia&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Agent boleh menyediakan perubahan, menjalankan ujian dan melaporkan hasil. Dalam workflow aku, keputusan untuk commit, push dan deploy kekal di tangan manusia.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Terus terang apabila tidak pasti&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Jika sesuatu arahan gagal, agent perlu melaporkan kegagalan tersebut dan bukannya mendakwa kerja sudah selesai.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prinsip utama aku
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;AI assists. Hardy understands, verifies, and owns the final decision.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;AI membantu. Aku memahami, mengesahkan dan bertanggungjawab terhadap keputusan akhir.&lt;/p&gt;

&lt;p&gt;Dokumen ini boleh dirujuk apabila agent perlu memahami pendekatan pembangunan yang aku utamakan. Untuk memastikan ia benar-benar digunakan, arahan utama perlu memberitahu agent bila dan bagaimana hendak membaca fail tersebut.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ringkasan:&lt;/strong&gt; &lt;code&gt;ai_guidelines.md&lt;/code&gt; ialah rujukan kepada prinsip dan pendekatan kerja yang aku mahu kekalkan dalam pembangunan perisian dengan bantuan AI.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. soul.md — Tujuan dan Falsafah Mendalam Agent
&lt;/h2&gt;

&lt;p&gt;Kalau &lt;code&gt;ai_guidelines.md&lt;/code&gt; memberikan ringkasan prinsip kerja, &lt;code&gt;soul.md&lt;/code&gt; pula digunakan dalam workflow aku untuk menghuraikan prinsip tersebut dengan lebih mendalam.&lt;/p&gt;

&lt;p&gt;Nama &lt;code&gt;soul.md&lt;/code&gt; bukan bermaksud agent mempunyai jiwa atau kesedaran seperti manusia. Ia ialah nama fail yang aku pilih untuk menyimpan falsafah dan tujuan reka bentuk agent.&lt;/p&gt;

&lt;h3&gt;
  
  
  Perbezaan antara tiga fail
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Fail&lt;/th&gt;
&lt;th&gt;Soalan utama&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;AGENTS.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Apakah arahan dan batas kerja aku?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ai_guidelines.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Apakah prinsip kerja yang perlu aku ikuti?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;soul.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Mengapa prinsip tersebut penting?&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Analogi mudah:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;AGENTS.md&lt;/code&gt; ialah buku peraturan.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ai_guidelines.md&lt;/code&gt; ialah nota ringkas di atas meja.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;soul.md&lt;/code&gt; ialah dokumen yang menerangkan sebab di sebalik prinsip tersebut.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Apa yang terkandung dalam soul.md?
&lt;/h3&gt;

&lt;p&gt;Dalam reka bentuk aku, dokumen ini merangkumi prinsip seperti:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Security First:&lt;/strong&gt; Keselamatan dipertimbangkan sejak awal.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Human Judgment First:&lt;/strong&gt; Manusia kekal bertanggungjawab terhadap keputusan.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Verify, Don't Assume:&lt;/strong&gt; Pengesahan lebih penting daripada andaian.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Production-Ready:&lt;/strong&gt; Perubahan dibuat dengan mengambil kira kebolehselenggaraan dan pemulihan.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Self-Hosted Pragmatism:&lt;/strong&gt; Mengutamakan penyelesaian open-source dan self-hosted apabila sesuai.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Learn Fundamentals:&lt;/strong&gt; Memahami asas Linux, rangkaian, SQL dan pembangunan perisian.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CLI Transparency:&lt;/strong&gt; Menunjukkan arahan dan hasil sebenar supaya kerja boleh difahami.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Backup &amp;amp; Rollback:&lt;/strong&gt; Merancang pemulihan sebelum perubahan berisiko.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Documentation:&lt;/strong&gt; Dokumentasi ialah sebahagian daripada kerja.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Preserve Context:&lt;/strong&gt; Menyimpan maklumat penting untuk sesi seterusnya.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bounded Steps:&lt;/strong&gt; Membuat perubahan secara terkawal dan berperingkat.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agent Boundaries:&lt;/strong&gt; Tidak mereka hasil, menyembunyikan ralat atau mendakwa kejayaan tanpa bukti.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Prinsip ini membentuk identiti workflow yang aku mahu bina, bukannya keupayaan yang terjamin tersedia secara automatik dalam sesuatu model.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mental Anchor — Kitaran kerja utama
&lt;/h3&gt;

&lt;p&gt;Dalam workflow aku, kerja agent mengikuti kitaran berikut:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Understand
    ↓
Inspect
    ↓
Plan
    ↓
Change
    ↓
Verify
    ↓
Document
    ↓
Next Task
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Maksudnya:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Understand:&lt;/strong&gt; Fahami permintaan dan masalah.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inspect:&lt;/strong&gt; Periksa keadaan sebenar sistem.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Plan:&lt;/strong&gt; Tentukan perubahan yang diperlukan.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Change:&lt;/strong&gt; Laksanakan perubahan secara terkawal.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Verify:&lt;/strong&gt; Jalankan ujian atau pemeriksaan yang sesuai.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Document:&lt;/strong&gt; Catat perubahan dan hasil pengesahan.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Next Task:&lt;/strong&gt; Tentukan langkah seterusnya.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Kitaran ini membantu mengelakkan agent daripada terus mengubah kod sebelum memahami masalah.&lt;/p&gt;

&lt;h3&gt;
  
  
  Satu prinsip yang aku pegang
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Do the work, verify the work, and leave enough evidence for the next person—or the next session—to understand the work.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Buat kerja, sahkan hasilnya dan tinggalkan bukti yang mencukupi supaya orang lain atau sesi seterusnya boleh memahami apa yang telah dilakukan.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ringkasan:&lt;/strong&gt; &lt;code&gt;soul.md&lt;/code&gt; ialah dokumen falsafah mendalam yang menerangkan tujuan, prinsip dan pendekatan yang aku mahu jadikan panduan kepada workflow coding agent.&lt;/p&gt;




&lt;h2&gt;
  
  
  6. Gambaran Besar — Lima Lapisan Workflow
&lt;/h2&gt;

&lt;p&gt;Selepas memahami setiap komponen, kita boleh melihat bagaimana semuanya saling melengkapi.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;soul.md
   ↓
Falsafah dan tujuan kerja

ai_guidelines.md
   ↓
Prinsip dan pendekatan pembangunan

AGENTS.md
   ↓
Arahan dan batas kerja

brain/
   ↓
Konteks dan catatan antara sesi

skills/
   ↓
Panduan bagi tugas khusus
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Setiap komponen menjawab soalan yang berbeza.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Komponen&lt;/th&gt;
&lt;th&gt;Soalan yang dijawab&lt;/th&gt;
&lt;th&gt;Peranan&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;soul.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Mengapa prinsip ini penting?&lt;/td&gt;
&lt;td&gt;Falsafah mendalam&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ai_guidelines.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Bagaimana aku mahu bekerja?&lt;/td&gt;
&lt;td&gt;Prinsip kerja&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;AGENTS.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Apakah arahan dan batas kerja?&lt;/td&gt;
&lt;td&gt;Arahan agent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;brain/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Apa yang telah berlaku dan apa seterusnya?&lt;/td&gt;
&lt;td&gt;Catatan kerja&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;skills/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Bagaimana tugas tertentu patut dilakukan?&lt;/td&gt;
&lt;td&gt;Panduan khusus&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Walaupun kelima-lima komponen ini berbeza, semuanya boleh membantu membina workflow yang lebih konsisten.&lt;/p&gt;

&lt;p&gt;Namun, keberkesanannya bergantung pada cara agent dikonfigurasikan, fail yang benar-benar dibaca dan ketepatan maklumat yang disimpan.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Kesimpulan
&lt;/h2&gt;

&lt;p&gt;Bagi aku, penggunaan coding agent bukan sekadar memberikan prompt dan menunggu kod siap.&lt;/p&gt;

&lt;p&gt;Aku mahu agent memahami batas kerjanya, mengikuti panduan projek, mengekalkan konteks dan mengesahkan hasil perubahan. Pada masa yang sama, aku mahu proses kerja kekal telus supaya aku boleh belajar daripada setiap perubahan yang dibuat.&lt;/p&gt;

&lt;p&gt;Lima komponen ini membantu memisahkan tanggungjawab tersebut:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Skills:&lt;/strong&gt; Panduan untuk tugas tertentu.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AGENTS.md:&lt;/strong&gt; Arahan dan batas kerja.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;brain/:&lt;/strong&gt; Catatan dan konteks kerja.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ai_guidelines.md:&lt;/strong&gt; Prinsip pembangunan.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;soul.md:&lt;/strong&gt; Falsafah yang mendasari workflow.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tidak semua projek memerlukan kelima-lima komponen. Projek kecil mungkin memadai dengan arahan ringkas dan beberapa skills. Projek yang lebih kompleks mungkin memerlukan rekod keputusan, dokumentasi seni bina dan catatan sesi yang lebih tersusun.&lt;/p&gt;

&lt;p&gt;Yang penting, jangan membina terlalu banyak lapisan semata-mata kerana ia kelihatan menarik. Gunakan apa yang benar-benar membantu kerja.&lt;/p&gt;

&lt;p&gt;Bagi aku, prinsip akhirnya mudah:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Handle the routine.&lt;/strong&gt; — Urus kerja rutin.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Surface the overlooked.&lt;/strong&gt; — Bangkitkan perkara yang mungkin terlepas pandang.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Explain the complicated.&lt;/strong&gt; — Terangkan perkara yang rumit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Verify the important.&lt;/strong&gt; — Sahkan perkara yang penting.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Preserve what was learned.&lt;/strong&gt; — Simpan apa yang telah dipelajari.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Leave the human in control.&lt;/strong&gt; — Manusia kekal mengawal keputusan akhir.&lt;/p&gt;

&lt;p&gt;Itulah asas workflow coding agent yang aku mahu bina: AI membantu melakukan kerja, tetapi manusia tetap memahami sistem, mengesahkan hasil dan bertanggungjawab terhadap keputusan.&lt;/p&gt;

&lt;p&gt;Artikel ini ditulis dengan bantuan AI. &lt;/p&gt;

</description>
      <category>harness</category>
      <category>ai</category>
      <category>brain</category>
      <category>agents</category>
    </item>
    <item>
      <title>Benchmarking Gemma 4 E2B on CPU with llama.cpp: A Practical Local AI Experiment</title>
      <dc:creator>hardyweb</dc:creator>
      <pubDate>Fri, 09 Oct 2026 00:02:22 +0000</pubDate>
      <link>https://dev.to/hardyweb/benchmarking-gemma-4-e2b-on-cpu-with-llamacpp-a-practical-local-ai-experiment-56nb</link>
      <guid>https://dev.to/hardyweb/benchmarking-gemma-4-e2b-on-cpu-with-llamacpp-a-practical-local-ai-experiment-56nb</guid>
      <description>&lt;h2&gt;
  
  
  1. Why This Experiment?
&lt;/h2&gt;

&lt;p&gt;I want to run a local language model for everyday office work without depending entirely on a cloud-based AI service.&lt;/p&gt;

&lt;p&gt;My intended use cases include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A local chatbot for general questions.&lt;/li&gt;
&lt;li&gt;Drafting Malay and English letters, memoranda, and emails.&lt;/li&gt;
&lt;li&gt;Preparing technical documentation.&lt;/li&gt;
&lt;li&gt;Basic spreadsheet analysis involving hundreds of rows, rather than thousands or millions.&lt;/li&gt;
&lt;li&gt;Learning how to deploy and tune local AI models on different computers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The challenge is that not every computer has the same CPU. Some machines have older processors with only a few cores, while others have newer CPUs with more cores and threads.&lt;/p&gt;

&lt;p&gt;Instead of assuming that one configuration works everywhere, I want to establish a baseline and use the same benchmarking method across different machines.&lt;/p&gt;

&lt;p&gt;This article records my initial experiments with &lt;strong&gt;Gemma 4 E2B using &lt;code&gt;llama-server&lt;/code&gt; from llama.cpp&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Test Environment
&lt;/h2&gt;

&lt;p&gt;The initial experiment was performed on a resource-constrained machine.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Specification&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;CPU&lt;/td&gt;
&lt;td&gt;AMD Athlon 3000G&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CPU architecture&lt;/td&gt;
&lt;td&gt;2 physical cores, 4 logical threads&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Graphics&lt;/td&gt;
&lt;td&gt;Radeon Vega Graphics&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Runtime environment&lt;/td&gt;
&lt;td&gt;WSL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WSL memory limit&lt;/td&gt;
&lt;td&gt;5 GB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Inference backend&lt;/td&gt;
&lt;td&gt;llama.cpp &lt;code&gt;llama-server&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Inference mode&lt;/td&gt;
&lt;td&gt;CPU-only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Parallel slots&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The main model file was:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gemma-4-E2B-it-qat-UD-Q4_K_XL.gguf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The model is an instruction-tuned Gemma 4 E2B GGUF using the QAT Q4_K_XL quantization variant.&lt;/p&gt;

&lt;p&gt;The objective is not to establish a universal performance figure for this model. It is to understand how configuration choices affect inference on this particular machine.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: The exact llama.cpp version/build identifier was not recorded in this initial benchmark. Future tests should record it because performance and available options can change between builds.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Establishing a Baseline
&lt;/h2&gt;

&lt;p&gt;I started with a conservative configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;llama-server &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-m&lt;/span&gt; ./gemma-4-E2B-it-qat-UD-Q4_K_XL.gguf &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-t&lt;/span&gt; 2 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-tb&lt;/span&gt; 2 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-c&lt;/span&gt; 2048 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-b&lt;/span&gt; 64 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-ub&lt;/span&gt; 16 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--host&lt;/span&gt; 127.0.0.1 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--port&lt;/span&gt; 5001
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The initial reported average generation speed was approximately &lt;strong&gt;4.6 tokens per second&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I then tested different thread counts and batch sizes. The following table records the results observed during the experiments.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Test&lt;/th&gt;
&lt;th&gt;Main configuration change&lt;/th&gt;
&lt;th&gt;Reported speed&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;A&lt;/td&gt;
&lt;td&gt;&lt;code&gt;-t 2 -tb 2 -c 2048 -b 64 -ub 16&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;4.6 t/s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;B&lt;/td&gt;
&lt;td&gt;&lt;code&gt;-t 3 -tb 4 -c 2048 -b 64 -ub 16&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;5.9 t/s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;B, repeat&lt;/td&gt;
&lt;td&gt;Same thread configuration&lt;/td&gt;
&lt;td&gt;6.1 t/s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;-b 32 -ub 8&lt;/code&gt;, with &lt;code&gt;-t 3 -tb 4&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;6.0 t/s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;D&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;-t 4 -tb 4&lt;/code&gt;, with the original batch sizes&lt;/td&gt;
&lt;td&gt;5.8 t/s&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;These results suggested that using three generation threads and four batch-processing threads was worth investigating further on this CPU.&lt;/p&gt;

&lt;p&gt;Increasing the thread count did not automatically improve performance. The four-thread test was slower than the three-thread result in these particular trials.&lt;/p&gt;

&lt;p&gt;However, these were exploratory measurements rather than a controlled benchmark. They should not be interpreted as proof that three threads will always be optimal.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Testing Additional Server Parameters
&lt;/h2&gt;

&lt;p&gt;Next, I added several parameters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-np 1
-ngl 0
--temp 0.7
--top-p 0.8
--top-k 20
--metrics
--jinja
--cache-type-k q8_0
--cache-type-v q8_0
--reasoning-format none
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The reported speed was approximately &lt;strong&gt;6.4 tokens per second&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Because several options were added together, this result does not tell us which individual parameter, if any, improved generation speed.&lt;/p&gt;

&lt;p&gt;I then tested Flash Attention explicitly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-fa on
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The reported speed for that trial was approximately &lt;strong&gt;6.2 tokens per second&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This trial did not demonstrate an improvement, so I left Flash Attention out of the preferred configuration for now. A more controlled test would be needed to establish whether it helps on another CPU or build.&lt;/p&gt;

&lt;h3&gt;
  
  
  What these parameters are for
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;-np 1&lt;/code&gt;: Configures one parallel sequence slot for this single-user experiment.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-ngl 0&lt;/code&gt;: Keeps model inference on the CPU rather than offloading model layers to a GPU.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--cache-type-k q8_0&lt;/code&gt; and &lt;code&gt;--cache-type-v q8_0&lt;/code&gt;: Select quantized data types for the key and value caches.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--metrics&lt;/code&gt;: Enables the server's metrics endpoint.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--jinja&lt;/code&gt;: Enables the relevant Jinja chat-template handling.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--temp&lt;/code&gt;, &lt;code&gt;--top-p&lt;/code&gt;, and &lt;code&gt;--top-k&lt;/code&gt;: Control sampling behaviour, not a guaranteed performance improvement.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--reasoning-format none&lt;/code&gt;: Configures reasoning-format handling for the server.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The available options and their precise behaviour should be checked against the &lt;a href="https://github.com/ggml-org/llama.cpp/blob/master/tools/server/README.md" rel="noopener noreferrer"&gt;official llama.cpp server documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Best Reported Configuration So Far
&lt;/h2&gt;

&lt;p&gt;The strongest reported result from the exploratory trials was approximately &lt;strong&gt;6.6 tokens per second&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The configuration was:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;llama-server &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-m&lt;/span&gt; ./gemma-4-E2B-it-qat-UD-Q4_K_XL.gguf &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-t&lt;/span&gt; 3 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-tb&lt;/span&gt; 4 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-c&lt;/span&gt; 2048 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-b&lt;/span&gt; 128 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-ub&lt;/span&gt; 32 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-np&lt;/span&gt; 1 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-ngl&lt;/span&gt; 0 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--temp&lt;/span&gt; 0.7 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--top-p&lt;/span&gt; 0.8 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--top-k&lt;/span&gt; 20 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--metrics&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--jinja&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--cache-type-k&lt;/span&gt; q8_0 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--cache-type-v&lt;/span&gt; q8_0 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--reasoning-format&lt;/span&gt; none &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--host&lt;/span&gt; 127.0.0.1 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--port&lt;/span&gt; 5001
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is my &lt;strong&gt;provisional baseline&lt;/strong&gt;, not a claim that the configuration is universally optimal.&lt;/p&gt;

&lt;p&gt;The larger batch settings were present in the best reported trial. More repeatable testing is required to establish whether they improve performance consistently, particularly because batch settings can affect prompt processing differently from token generation.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;--no-mmap&lt;/code&gt; option has not been benchmarked in this experiment and should not be considered part of the tested configuration.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. A Real Office-Work Test
&lt;/h2&gt;

&lt;p&gt;A later trial used a Malay prompt requesting a formal memorandum about periodic maintenance for internally developed systems using Laravel and Debian Linux.&lt;/p&gt;

&lt;p&gt;The generated memorandum covered:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Security patching.&lt;/li&gt;
&lt;li&gt;Package updates.&lt;/li&gt;
&lt;li&gt;Log and performance monitoring.&lt;/li&gt;
&lt;li&gt;Risks associated with inadequate maintenance.&lt;/li&gt;
&lt;li&gt;A recommendation to include maintenance in the department's operational plan.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The reported statistics were:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Prompt tokens&lt;/td&gt;
&lt;td&gt;126&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Generated tokens&lt;/td&gt;
&lt;td&gt;391&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reported average generation speed&lt;/td&gt;
&lt;td&gt;6.0 t/s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Approximate generation time from token count and speed&lt;/td&gt;
&lt;td&gt;65 seconds&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The time is an estimate calculated from the reported token count and speed. It is not a direct end-to-end timing measurement.&lt;/p&gt;

&lt;h3&gt;
  
  
  Observations about output quality
&lt;/h3&gt;

&lt;p&gt;The memorandum had a recognisable formal structure and its recommendations were generally relevant to the requested topic.&lt;/p&gt;

&lt;p&gt;However, it also generated a specific date, 26 May 2024, even though the prompt did not provide that date. This is an important reminder that local language models can introduce unsupported details.&lt;/p&gt;

&lt;p&gt;For actual office use, the application should provide authoritative information such as dates, recipient details, reference numbers, and departmental names. Generated letters and technical recommendations should still be reviewed before they are issued or acted upon.&lt;/p&gt;

&lt;p&gt;The experiment therefore evaluates two separate dimensions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Performance:&lt;/strong&gt; How quickly the model generates output.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Quality:&lt;/strong&gt; Whether the generated output is accurate, relevant, appropriately formatted, and safe to use.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A higher tokens-per-second figure does not necessarily mean a better office assistant.&lt;/p&gt;

&lt;h2&gt;
  
  
  6.1 Testing Document Understanding and Structured Data Analysis
&lt;/h2&gt;

&lt;p&gt;After testing the model's ability to draft an office memorandum, I moved on to two additional tasks using plain-text (&lt;code&gt;.txt&lt;/code&gt;) documents.&lt;/p&gt;

&lt;p&gt;The objective was to evaluate whether Gemma 4 E2B could extract facts from a document, follow instructions, identify missing information, and analyse a small dataset without inventing values.&lt;/p&gt;

&lt;h3&gt;
  
  
  Test 1 — Document Understanding
&lt;/h3&gt;

&lt;p&gt;The first test used a simulated internal system maintenance procedure. The document covered maintenance schedules, change-management requirements, database backups, restore testing, and incident records.&lt;/p&gt;

&lt;p&gt;I asked the model nine questions, including which details were explicitly documented and which were missing.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Prompt tokens evaluated&lt;/td&gt;
&lt;td&gt;1,051&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Generated tokens&lt;/td&gt;
&lt;td&gt;638&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reported average generation speed&lt;/td&gt;
&lt;td&gt;5.0 t/s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Questions answered&lt;/td&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Overall observation&lt;/td&gt;
&lt;td&gt;Satisfactory for this test&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The model answered all nine questions correctly in this trial. It produced a structured frequency table, identified the required change-record fields, explained why a successful backup job does not guarantee that restoration will work, and avoided inventing details that were absent from the source document.&lt;/p&gt;

&lt;p&gt;This was an encouraging result for document-grounded question answering. However, it was a single qualitative test rather than a statistically validated accuracy benchmark.&lt;/p&gt;

&lt;h3&gt;
  
  
  Test 2 — ICT Asset Data Analysis
&lt;/h3&gt;

&lt;p&gt;The second test used a simulated ICT asset inventory containing eight records, including desktops, laptops, monitors, printers, and a scanner. Each record included a quantity, unit cost where available, and status.&lt;/p&gt;

&lt;p&gt;The model was asked to calculate the total number of units, calculate record-level costs, identify missing prices, summarise assets requiring inspection, and prepare a short management summary.&lt;/p&gt;

&lt;p&gt;I first ran the test with a context size of 2,048 tokens.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Prompt tokens evaluated&lt;/td&gt;
&lt;td&gt;1,462&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Generated tokens&lt;/td&gt;
&lt;td&gt;585&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reported average generation speed&lt;/td&gt;
&lt;td&gt;5.0 t/s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Output completion&lt;/td&gt;
&lt;td&gt;Incomplete&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The response stopped before all questions were answered. The reported context usage reached approximately 2,048 tokens, suggesting that the context limit may have contributed to the incomplete response. This is an observation from the reported run, not proof that context capacity was the only cause.&lt;/p&gt;

&lt;p&gt;I then repeated the test with a context size of 4,096 tokens.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Prompt tokens evaluated&lt;/td&gt;
&lt;td&gt;1,098&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Generated tokens&lt;/td&gt;
&lt;td&gt;1,696&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reported average generation speed&lt;/td&gt;
&lt;td&gt;5.3 t/s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Output completion&lt;/td&gt;
&lt;td&gt;All 10 questions answered&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;With the larger context, the model completed the requested analysis. It correctly identified 22 total units, calculated the individual costs for records with known prices, and identified two records marked &lt;em&gt;Perlu diperiksa&lt;/em&gt;, covering four units in total. It also correctly noted that this status alone does not prove that an asset is broken.&lt;/p&gt;

&lt;p&gt;However, the final cost calculation was incorrect. The model reported &lt;strong&gt;RM33,850&lt;/strong&gt;, whereas the correct sum of the seven calculable record costs is &lt;strong&gt;RM33,050&lt;/strong&gt;. The individual record-level calculations were correct, but the final addition was not.&lt;/p&gt;

&lt;p&gt;The record with a missing unit cost was correctly excluded from the total.&lt;/p&gt;

&lt;h3&gt;
  
  
  What These Tests Tell Me
&lt;/h3&gt;

&lt;p&gt;These experiments highlight three practical findings:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Document understanding looks promising.&lt;/strong&gt; In the first trial, the model extracted facts and respected missing information in a simulated maintenance procedure.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Context capacity matters for longer tasks.&lt;/strong&gt; The 2,048-token run produced an incomplete response, while the 4,096-token run completed the task. The tests were not identical in token usage, so this should be treated as an initial observation rather than a controlled performance comparison.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Correct-looking calculations still need verification.&lt;/strong&gt; The asset-analysis test contained correct individual calculations but an incorrect final sum. A fluent explanation and a completed response do not guarantee numerical accuracy.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For practical office applications, I would use the language model to interpret documents, explain results, and prepare summaries. For financial totals and other exact calculations, I would rely on deterministic tools such as PHP, SQL, or spreadsheet formulas, then provide the verified results to the model for explanation.&lt;/p&gt;

&lt;p&gt;For now, a context size of 4,096 tokens is a more useful working configuration for this type of longer document task on my test machine. I still need to monitor memory usage and repeat the tests before drawing broader conclusions about performance or reliability.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Why the Results Are Still Preliminary
&lt;/h2&gt;

&lt;p&gt;The measurements above were collected during interactive experiments. The prompts and output lengths were not identical in every trial, and some trials changed several parameters at once.&lt;/p&gt;

&lt;p&gt;Consequently, the results are useful for narrowing down configurations, but not for drawing definitive conclusions about individual options.&lt;/p&gt;

&lt;p&gt;A more reliable benchmark should:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Use the same prompt for every comparison.&lt;/li&gt;
&lt;li&gt;Set the same maximum output-token limit.&lt;/li&gt;
&lt;li&gt;Allow the model and system to reach a comparable starting state.&lt;/li&gt;
&lt;li&gt;Repeat each configuration at least three times.&lt;/li&gt;
&lt;li&gt;Record the median and average generation speed.&lt;/li&gt;
&lt;li&gt;Record prompt-processing speed separately from generation speed where possible.&lt;/li&gt;
&lt;li&gt;Monitor RAM usage, CPU utilisation, thermal behaviour, and swapping.&lt;/li&gt;
&lt;li&gt;Check output quality using the same practical tasks.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The llama.cpp server supports a Prometheus-compatible metrics endpoint when &lt;code&gt;--metrics&lt;/code&gt; is enabled. Its reported metrics can help distinguish prompt-processing throughput from generation throughput. See the &lt;a href="https://github.com/ggml-org/llama.cpp/blob/master/tools/server/README.md" rel="noopener noreferrer"&gt;server metrics documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. A Repeatable Benchmark Plan for Other PCs
&lt;/h2&gt;

&lt;p&gt;The long-term objective is to repeat this experiment across computers with different CPU generations, core counts, and memory limits.&lt;/p&gt;

&lt;p&gt;For each machine, I will record:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;What to record&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Machine ID&lt;/td&gt;
&lt;td&gt;A simple label, such as &lt;code&gt;PC-01&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CPU&lt;/td&gt;
&lt;td&gt;Exact processor model&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CPU topology&lt;/td&gt;
&lt;td&gt;Physical cores and logical threads&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Memory&lt;/td&gt;
&lt;td&gt;Installed RAM and the actual limit available to the inference environment&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Operating environment&lt;/td&gt;
&lt;td&gt;Linux, WSL, or another supported environment&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;llama.cpp build&lt;/td&gt;
&lt;td&gt;Version, build details, and relevant compilation options&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Model&lt;/td&gt;
&lt;td&gt;Exact model filename and quantization&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Context size&lt;/td&gt;
&lt;td&gt;Value of &lt;code&gt;-c&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Threads&lt;/td&gt;
&lt;td&gt;Values of &lt;code&gt;-t&lt;/code&gt; and &lt;code&gt;-tb&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Batch settings&lt;/td&gt;
&lt;td&gt;Values of &lt;code&gt;-b&lt;/code&gt; and &lt;code&gt;-ub&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cache settings&lt;/td&gt;
&lt;td&gt;K and V cache types&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Prompt and output&lt;/td&gt;
&lt;td&gt;Prompt tokens and generated tokens&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Performance&lt;/td&gt;
&lt;td&gt;Generation tokens/s and prompt tokens/s, when available&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Resource use&lt;/td&gt;
&lt;td&gt;Peak RAM, CPU utilisation, swapping, and temperature where available&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Quality&lt;/td&gt;
&lt;td&gt;Accuracy, language quality, formatting, and unsupported claims&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Recommended test sequence
&lt;/h3&gt;

&lt;p&gt;Start with the provisional baseline and change one variable at a time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stage 1 — Thread configuration&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Compare suitable values for &lt;code&gt;-t&lt;/code&gt; and &lt;code&gt;-tb&lt;/code&gt; based on the CPU's topology. For a CPU with two physical cores and four logical threads, for example, test a small range of thread settings instead of assuming that all logical threads will always help.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stage 2 — Context size&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Compare &lt;code&gt;-c 1024&lt;/code&gt; with &lt;code&gt;-c 2048&lt;/code&gt; while keeping other parameters constant. A smaller context may reduce memory requirements, but it also limits how much conversation or source material can fit into the context.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;-c 1024&lt;/code&gt; configuration is a proposed future test, not a completed measurement in this experiment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stage 3 — Batch sizes&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Test &lt;code&gt;-b&lt;/code&gt; and &lt;code&gt;-ub&lt;/code&gt; independently where practical. Record prompt-processing throughput as well as generation speed, because the effect may differ between these workloads.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stage 4 — KV cache&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Only after establishing a stable baseline, consider comparing &lt;code&gt;q8_0&lt;/code&gt; with other supported cache types, such as &lt;code&gt;q4_0&lt;/code&gt;. Measure memory use, speed, stability, and output quality. Do not assume that a smaller cache will necessarily make inference faster.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stage 5 — Practical workload&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Run the same set of tasks on each machine:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A short chatbot question.&lt;/li&gt;
&lt;li&gt;A formal Malay letter or memorandum.&lt;/li&gt;
&lt;li&gt;An English email.&lt;/li&gt;
&lt;li&gt;A structured technical document.&lt;/li&gt;
&lt;li&gt;A small spreadsheet-analysis task.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This will help determine which configurations are suitable for actual use rather than merely optimising a single benchmark prompt.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Practical Lessons So Far
&lt;/h2&gt;

&lt;p&gt;The initial experiment suggests several useful lessons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A local model can produce a structured Malay office memorandum on a CPU-only machine.&lt;/li&gt;
&lt;li&gt;The best reported speed so far was 6.6 tokens per second, but the benchmark needs more controlled repetitions.&lt;/li&gt;
&lt;li&gt;More CPU threads do not guarantee better generation speed.&lt;/li&gt;
&lt;li&gt;Sampling parameters should be chosen for the desired response behaviour, not treated as performance switches.&lt;/li&gt;
&lt;li&gt;Context size, batch configuration, and cache types should be tested separately.&lt;/li&gt;
&lt;li&gt;RAM usage and thermal stability matter, particularly on older or resource-constrained computers.&lt;/li&gt;
&lt;li&gt;Output accuracy must be evaluated separately from generation speed.&lt;/li&gt;
&lt;li&gt;For spreadsheet tasks, an application can process the actual spreadsheet with a suitable data library and pass relevant results to the model instead of sending an entire workbook into the prompt.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  10. Conclusion
&lt;/h2&gt;

&lt;p&gt;This experiment establishes a starting point for running Gemma 4 E2B with llama.cpp on modest CPU hardware.&lt;/p&gt;

&lt;p&gt;The current provisional configuration uses three generation threads, four batch threads, a context size of 2048, and batch settings of 128 and 32. It achieved a reported best speed of approximately 6.6 tokens per second in the exploratory trials.&lt;/p&gt;

&lt;p&gt;The next goal is not simply to make one computer faster. It is to build a repeatable method for finding practical configurations across several computers, including older CPUs and newer machines with more cores.&lt;/p&gt;

&lt;p&gt;The long-term measure of success is a useful local assistant for everyday office work: responsive enough for conversation, capable of producing good first drafts, and reliable enough to support documentation and basic data analysis with appropriate human review.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Benchmark status:&lt;/strong&gt; Initial exploratory phase completed. Further parameter testing is paused until a new machine or a controlled test session is selected.&lt;/p&gt;

&lt;p&gt;This article was created with the help of AI&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llamacpp</category>
      <category>linux</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Turn Your Windows PC into a Linux &amp; FreeBSD Learning Lab with WSL2 and Incus</title>
      <dc:creator>hardyweb</dc:creator>
      <pubDate>Sat, 03 Oct 2026 12:13:58 +0000</pubDate>
      <link>https://dev.to/hardyweb/turn-your-windows-pc-into-a-linux-freebsd-learning-lab-with-wsl2-and-incus-29hd</link>
      <guid>https://dev.to/hardyweb/turn-your-windows-pc-into-a-linux-freebsd-learning-lab-with-wsl2-and-incus-29hd</guid>
      <description>&lt;p&gt;If you're using Windows 11 and want to learn Linux, you don't necessarily need to dual-boot your computer, install several heavyweight virtual machines, or buy another machine just for a learning lab.&lt;/p&gt;

&lt;p&gt;You can build a surprisingly capable Linux and Unix learning environment using something you may already have:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A Windows PC.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The idea behind this project is simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Use Windows as the host, WSL2 as the foundation, and Incus as the laboratory.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;From there, you can create Linux containers, experiment with networking and services, and even run a FreeBSD virtual machine.&lt;/p&gt;

&lt;p&gt;The result is the &lt;strong&gt;&lt;a href="https://github.com/hardyweb/Incus-WSL-Learning-Laboratory" rel="noopener noreferrer"&gt;Incus WSL Learning Laboratory&lt;/a&gt;&lt;/strong&gt; — a structured, hands-on environment designed for students and beginners who want to learn Linux by actually using it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Build a Linux Lab on Windows?
&lt;/h2&gt;

&lt;p&gt;Learning Linux from a book or watching tutorials is useful, but eventually you need somewhere to experiment.&lt;/p&gt;

&lt;p&gt;You want to be able to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;create users&lt;/li&gt;
&lt;li&gt;install packages&lt;/li&gt;
&lt;li&gt;break configurations&lt;/li&gt;
&lt;li&gt;configure networking&lt;/li&gt;
&lt;li&gt;run web servers&lt;/li&gt;
&lt;li&gt;experiment with DNS&lt;/li&gt;
&lt;li&gt;manage services&lt;/li&gt;
&lt;li&gt;create multiple machines&lt;/li&gt;
&lt;li&gt;destroy them&lt;/li&gt;
&lt;li&gt;start again&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Doing these experiments directly on your main computer isn't always a good idea.&lt;/p&gt;

&lt;p&gt;Dual-booting introduces another layer of complexity.&lt;/p&gt;

&lt;p&gt;Traditional virtual machines work, but managing multiple VMs can become cumbersome, especially on a modest laptop.&lt;/p&gt;

&lt;p&gt;This is where &lt;strong&gt;WSL2 + Incus&lt;/strong&gt; becomes interesting.&lt;/p&gt;




&lt;h1&gt;
  
  
  The Architecture
&lt;/h1&gt;

&lt;p&gt;The laboratory uses several layers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Windows 11
    │
    └── WSL2
          │
          └── Debian
                │
                └── Incus
                      │
                      ├── Linux Containers
                      │     ├── Debian
                      │     ├── Ubuntu
                      │     └── Alpine
                      │
                      └── Virtual Machines
                            └── FreeBSD
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important thing here is that each layer has a different purpose.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Windows 11&lt;/strong&gt; is your everyday operating system.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;WSL2&lt;/strong&gt; provides the Linux environment running alongside Windows.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Debian&lt;/strong&gt; becomes the Linux environment where Incus is installed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Incus&lt;/strong&gt; becomes the laboratory manager.&lt;/p&gt;

&lt;p&gt;Once Incus is running, you can create isolated Linux containers and virtual machines for your experiments.&lt;/p&gt;




&lt;h1&gt;
  
  
  Why Incus?
&lt;/h1&gt;

&lt;p&gt;You may already know tools such as Docker, VirtualBox, or VMware.&lt;/p&gt;

&lt;p&gt;Incus solves a slightly different problem.&lt;/p&gt;

&lt;p&gt;It is designed to manage &lt;strong&gt;system containers and virtual machines&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Instead of thinking only in terms of application containers, you can think in terms of small Linux systems.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;incus launch images:debian/13 debian01
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you have a Debian system.&lt;/p&gt;

&lt;p&gt;You can enter it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;incus &lt;span class="nb"&gt;exec &lt;/span&gt;debian01 &lt;span class="nt"&gt;--&lt;/span&gt; bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And start working with it like a small Linux machine.&lt;/p&gt;

&lt;p&gt;You can create another one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;incus launch images:ubuntu/24.04 ubuntu01
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And perhaps an Alpine system:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;incus launch images:alpine/3.22 alpine01
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now your Windows PC has several Linux environments running side by side.&lt;/p&gt;

&lt;p&gt;That's already a useful learning laboratory.&lt;/p&gt;




&lt;h1&gt;
  
  
  From One Linux Machine to a Small Network
&lt;/h1&gt;

&lt;p&gt;This is where things become more interesting.&lt;/p&gt;

&lt;p&gt;Instead of learning Linux on one machine, you can create several machines and make them communicate with each other.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                 Incus
                   │
          ┌────────┼────────┐
          │        │        │
       Debian   Ubuntu    Alpine
       10.10.   10.10.    10.10.
       10.101   10.102    10.103
          │        │        │
          └────────┼────────┘
                   │
                Network
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can then start experimenting with concepts such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;IP addressing&lt;/li&gt;
&lt;li&gt;routing&lt;/li&gt;
&lt;li&gt;DNS&lt;/li&gt;
&lt;li&gt;SSH&lt;/li&gt;
&lt;li&gt;HTTP/HTTPS&lt;/li&gt;
&lt;li&gt;firewalls&lt;/li&gt;
&lt;li&gt;service discovery&lt;/li&gt;
&lt;li&gt;network troubleshooting&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Commands such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ping
ip
ss
curl
dig
nslookup
traceroute
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;become practical tools instead of commands you only read about.&lt;/p&gt;

&lt;p&gt;This changes the learning experience significantly.&lt;/p&gt;

&lt;p&gt;You're no longer asking:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"What does DNS do?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You're asking:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Why can't this container resolve that hostname?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's a much better question to learn from.&lt;/p&gt;




&lt;h1&gt;
  
  
  Linux Distributions Become Your Playground
&lt;/h1&gt;

&lt;p&gt;One of the advantages of using Incus is that you don't have to commit to a single Linux distribution.&lt;/p&gt;

&lt;p&gt;You can have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Debian
Ubuntu
Alpine
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;running simultaneously.&lt;/p&gt;

&lt;p&gt;This makes it easy to compare how different distributions approach similar tasks.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;h3&gt;
  
  
  Debian
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Ubuntu
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Alpine
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;apk add nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The commands are different, the package management is different, and the base systems are different.&lt;/p&gt;

&lt;p&gt;That difference is useful.&lt;/p&gt;

&lt;p&gt;It encourages you to learn &lt;strong&gt;Linux concepts&lt;/strong&gt;, rather than memorizing commands for one particular distribution.&lt;/p&gt;




&lt;h1&gt;
  
  
  And Then There Is FreeBSD
&lt;/h1&gt;

&lt;p&gt;The laboratory isn't limited to Linux.&lt;/p&gt;

&lt;p&gt;One of the things I wanted to explore was &lt;strong&gt;FreeBSD&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;FreeBSD isn't Linux.&lt;/p&gt;

&lt;p&gt;It has its own kernel, userland, tooling, filesystem concepts, service management, networking tools, and system administration philosophy.&lt;/p&gt;

&lt;p&gt;That's exactly why it makes a useful addition to a Linux learning environment.&lt;/p&gt;

&lt;p&gt;With Incus virtual machines, you can create a FreeBSD VM and start exploring another Unix-like operating system:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Windows 11
    │
    └── WSL2
          │
          └── Debian
                │
                └── Incus
                      │
                      ├── Debian container
                      ├── Ubuntu container
                      ├── Alpine container
                      │
                      └── FreeBSD VM
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives students an opportunity to ask interesting questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How is FreeBSD different from Linux?&lt;/li&gt;
&lt;li&gt;How does service management work?&lt;/li&gt;
&lt;li&gt;How does networking differ?&lt;/li&gt;
&lt;li&gt;What is a BSD jail?&lt;/li&gt;
&lt;li&gt;How does a BSD system organize its base system?&lt;/li&gt;
&lt;li&gt;What happens when you leave the Linux ecosystem?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal isn't to make FreeBSD behave like Linux.&lt;/p&gt;

&lt;p&gt;The goal is to learn &lt;strong&gt;another Unix-like operating system on its own terms&lt;/strong&gt;.&lt;/p&gt;




&lt;h1&gt;
  
  
  Breaking Things Is Part of the Curriculum
&lt;/h1&gt;

&lt;p&gt;One of the best things about a laboratory environment is that you are allowed to make mistakes.&lt;/p&gt;

&lt;p&gt;You can experiment with things like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;rm
chmod
chown
&lt;/span&gt;systemctl
ip
iptables
nft
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You might break a service.&lt;/p&gt;

&lt;p&gt;You might misconfigure networking.&lt;/p&gt;

&lt;p&gt;You might lock yourself out of something.&lt;/p&gt;

&lt;p&gt;That's okay.&lt;/p&gt;

&lt;p&gt;You can delete the container and create another one.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;incus delete debian01
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;incus launch images:debian/13 debian01
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You're back to a clean environment.&lt;/p&gt;

&lt;p&gt;This is one of the reasons I prefer learning through an isolated lab.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Failure becomes part of the learning process.&lt;/strong&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  Snapshots: Your Save Point
&lt;/h1&gt;

&lt;p&gt;Incus also provides snapshots.&lt;/p&gt;

&lt;p&gt;Before making a major change, you can create a snapshot:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;incus snapshot create debian01 before-change
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After experimenting, you can restore it if necessary.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Working system
      │
      ▼
   Snapshot
      │
      ▼
Experiment
      │
      ├── Works
      │
      └── Broken
           │
           ▼
        Restore
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Think of it as a save point for your laboratory.&lt;/p&gt;

&lt;p&gt;This is particularly useful when learning system administration because you're encouraged to experiment instead of being afraid of making mistakes.&lt;/p&gt;




&lt;h1&gt;
  
  
  What You'll Learn
&lt;/h1&gt;

&lt;p&gt;The laboratory is organized as a progression rather than simply being a collection of commands.&lt;/p&gt;

&lt;h3&gt;
  
  
  Level 1 — Windows, WSL2 and Debian
&lt;/h3&gt;

&lt;p&gt;Start from the Windows environment.&lt;/p&gt;

&lt;p&gt;You'll learn:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Windows Terminal&lt;/li&gt;
&lt;li&gt;WSL2&lt;/li&gt;
&lt;li&gt;Linux filesystem basics&lt;/li&gt;
&lt;li&gt;Debian&lt;/li&gt;
&lt;li&gt;shell commands&lt;/li&gt;
&lt;li&gt;users and permissions&lt;/li&gt;
&lt;li&gt;packages&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The objective is to become comfortable inside a Linux terminal.&lt;/p&gt;




&lt;h3&gt;
  
  
  Level 2 — Introduction to Incus
&lt;/h3&gt;

&lt;p&gt;Once Debian becomes familiar, Incus is introduced.&lt;/p&gt;

&lt;p&gt;You'll learn:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;installing Incus&lt;/li&gt;
&lt;li&gt;creating containers&lt;/li&gt;
&lt;li&gt;starting and stopping containers&lt;/li&gt;
&lt;li&gt;entering containers&lt;/li&gt;
&lt;li&gt;managing images&lt;/li&gt;
&lt;li&gt;viewing resources&lt;/li&gt;
&lt;li&gt;snapshots&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At this point, your single Linux environment becomes a small laboratory.&lt;/p&gt;




&lt;h3&gt;
  
  
  Level 3 — Networking and Services
&lt;/h3&gt;

&lt;p&gt;Now the machines start communicating.&lt;/p&gt;

&lt;p&gt;You'll explore:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Incus bridges&lt;/li&gt;
&lt;li&gt;IP addresses&lt;/li&gt;
&lt;li&gt;DNS&lt;/li&gt;
&lt;li&gt;SSH&lt;/li&gt;
&lt;li&gt;HTTP&lt;/li&gt;
&lt;li&gt;service ports&lt;/li&gt;
&lt;li&gt;network troubleshooting&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;             Incus Network
                   │
        ┌──────────┼──────────┐
        │          │          │
     web01       dns01      client01
        │          │          │
       Nginx      DNS        curl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead of simply reading about networking, you can build a small network and troubleshoot it yourself.&lt;/p&gt;




&lt;h3&gt;
  
  
  Level 4 — Programming and FreeBSD
&lt;/h3&gt;

&lt;p&gt;Once the basic system concepts are understood, the laboratory can become a programming environment.&lt;/p&gt;

&lt;p&gt;You can start building services with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PHP&lt;/li&gt;
&lt;li&gt;Laravel&lt;/li&gt;
&lt;li&gt;Python&lt;/li&gt;
&lt;li&gt;Go&lt;/li&gt;
&lt;li&gt;shell scripting&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And then introduce FreeBSD as a separate virtual machine.&lt;/p&gt;

&lt;p&gt;This creates an interesting bridge between:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Programming → Linux → Networking → Systems&lt;/strong&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Level 5 — Projects
&lt;/h3&gt;

&lt;p&gt;The final stage is intentionally open-ended.&lt;/p&gt;

&lt;p&gt;Students can build their own projects.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a small web server&lt;/li&gt;
&lt;li&gt;a DNS server&lt;/li&gt;
&lt;li&gt;a monitoring system&lt;/li&gt;
&lt;li&gt;a reverse proxy&lt;/li&gt;
&lt;li&gt;a multi-container application&lt;/li&gt;
&lt;li&gt;a network troubleshooting lab&lt;/li&gt;
&lt;li&gt;a basic security monitoring environment&lt;/li&gt;
&lt;li&gt;a self-hosted service&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At this point, the laboratory stops being a tutorial and becomes a playground.&lt;/p&gt;




&lt;h1&gt;
  
  
  What Makes This Different from a Typical Linux Tutorial?
&lt;/h1&gt;

&lt;p&gt;A lot of beginner Linux tutorials follow this pattern:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Read
 ↓
Copy command
 ↓
See output
 ↓
Next command
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That can teach syntax, but it doesn't necessarily teach systems thinking.&lt;/p&gt;

&lt;p&gt;This project tries to follow a different approach:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Concept
   ↓
Build
   ↓
Experiment
   ↓
Break
   ↓
Troubleshoot
   ↓
Understand
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example, instead of simply explaining what DNS is, you can create a small environment where one machine provides DNS and another machine consumes it.&lt;/p&gt;

&lt;p&gt;Instead of explaining HTTP theoretically, you can deploy Nginx and connect to it from another container.&lt;/p&gt;

&lt;p&gt;Instead of explaining SSH, you can actually log into another machine.&lt;/p&gt;

&lt;p&gt;The computer becomes the classroom.&lt;/p&gt;




&lt;h1&gt;
  
  
  Prerequisites
&lt;/h1&gt;

&lt;p&gt;You don't need an expensive server.&lt;/p&gt;

&lt;p&gt;The basic requirements are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;64-bit Windows 11&lt;/li&gt;
&lt;li&gt;WSL2 support&lt;/li&gt;
&lt;li&gt;Internet connection&lt;/li&gt;
&lt;li&gt;Administrator access for initial setup&lt;/li&gt;
&lt;li&gt;Approximately 20 GB of available storage&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;More RAM and CPU will obviously make the laboratory more comfortable, especially when running several environments simultaneously.&lt;/p&gt;

&lt;p&gt;You don't need a dedicated server.&lt;/p&gt;

&lt;p&gt;You don't need dual-boot.&lt;/p&gt;

&lt;p&gt;You don't need a cloud VPS.&lt;/p&gt;

&lt;p&gt;Your existing Windows PC can become the lab.&lt;/p&gt;




&lt;h1&gt;
  
  
  Suggested Learning Path
&lt;/h1&gt;

&lt;p&gt;A possible progression looks like this:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Stage&lt;/th&gt;
&lt;th&gt;Topic&lt;/th&gt;
&lt;th&gt;Suggested Time&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Windows, WSL2 &amp;amp; Debian&lt;/td&gt;
&lt;td&gt;1–2 hours&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Linux fundamentals&lt;/td&gt;
&lt;td&gt;2–3 hours&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;Incus &amp;amp; first container&lt;/td&gt;
&lt;td&gt;1–2 hours&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;Multiple distributions&lt;/td&gt;
&lt;td&gt;2–3 hours&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;Networking &amp;amp; services&lt;/td&gt;
&lt;td&gt;2–3 hours&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;Programming laboratory&lt;/td&gt;
&lt;td&gt;2–3 hours&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;FreeBSD introduction&lt;/td&gt;
&lt;td&gt;2–4 hours&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;Student projects&lt;/td&gt;
&lt;td&gt;Ongoing&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;These aren't strict course durations.&lt;/p&gt;

&lt;p&gt;The idea is to give learners a direction rather than a deadline.&lt;/p&gt;




&lt;h1&gt;
  
  
  Where Can You Go After This?
&lt;/h1&gt;

&lt;p&gt;Once you understand the basics, the same laboratory can grow with you.&lt;/p&gt;

&lt;h3&gt;
  
  
  Linux Administration
&lt;/h3&gt;

&lt;p&gt;Move into:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;users and groups&lt;/li&gt;
&lt;li&gt;permissions&lt;/li&gt;
&lt;li&gt;filesystems&lt;/li&gt;
&lt;li&gt;storage&lt;/li&gt;
&lt;li&gt;processes&lt;/li&gt;
&lt;li&gt;services&lt;/li&gt;
&lt;li&gt;system logs&lt;/li&gt;
&lt;li&gt;systemd&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Networking
&lt;/h3&gt;

&lt;p&gt;Explore:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;TCP/IP&lt;/li&gt;
&lt;li&gt;DNS&lt;/li&gt;
&lt;li&gt;routing&lt;/li&gt;
&lt;li&gt;firewalls&lt;/li&gt;
&lt;li&gt;reverse proxies&lt;/li&gt;
&lt;li&gt;VLAN concepts&lt;/li&gt;
&lt;li&gt;network troubleshooting&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Web Development
&lt;/h3&gt;

&lt;p&gt;Build environments containing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Nginx
PHP
Laravel
MariaDB/PostgreSQL
Redis
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can turn Incus into a local development laboratory.&lt;/p&gt;

&lt;h3&gt;
  
  
  DevOps
&lt;/h3&gt;

&lt;p&gt;Continue with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Git&lt;/li&gt;
&lt;li&gt;CI/CD&lt;/li&gt;
&lt;li&gt;automation&lt;/li&gt;
&lt;li&gt;configuration management&lt;/li&gt;
&lt;li&gt;service deployment&lt;/li&gt;
&lt;li&gt;monitoring&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cybersecurity
&lt;/h3&gt;

&lt;p&gt;Once the fundamentals are understood, you can build controlled security labs for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;system hardening&lt;/li&gt;
&lt;li&gt;log monitoring&lt;/li&gt;
&lt;li&gt;network monitoring&lt;/li&gt;
&lt;li&gt;vulnerability testing&lt;/li&gt;
&lt;li&gt;incident response exercises&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The important part is that these advanced topics are built on top of the fundamentals.&lt;/p&gt;




&lt;h1&gt;
  
  
  The Bigger Idea
&lt;/h1&gt;

&lt;p&gt;The project is not really about Incus.&lt;/p&gt;

&lt;p&gt;It is about creating a place where you can &lt;strong&gt;learn by doing&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A Windows laptop can become:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;             Your Windows PC
                    │
                  WSL2
                    │
                 Debian
                    │
                  Incus
          ┌─────────┴─────────┐
          │                   │
     Containers               VMs
          │                   │
    ┌─────┼─────┐          FreeBSD
    │     │     │
 Debian Ubuntu Alpine
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And from there, the possibilities expand.&lt;/p&gt;

&lt;p&gt;You can learn Linux.&lt;/p&gt;

&lt;p&gt;Then networking.&lt;/p&gt;

&lt;p&gt;Then programming.&lt;/p&gt;

&lt;p&gt;Then system administration.&lt;/p&gt;

&lt;p&gt;Then DevOps.&lt;/p&gt;

&lt;p&gt;Then security.&lt;/p&gt;

&lt;p&gt;You don't need to start with a rack full of servers.&lt;/p&gt;

&lt;p&gt;You need a computer, some curiosity, and a safe place to experiment.&lt;/p&gt;




&lt;h1&gt;
  
  
  Final Thoughts
&lt;/h1&gt;

&lt;p&gt;I built the &lt;strong&gt;Incus WSL Learning Laboratory&lt;/strong&gt; around a simple idea:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Don't just read about Linux. Build a Linux environment and use it.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;WSL2 makes Linux accessible from Windows.&lt;/p&gt;

&lt;p&gt;Incus turns that Linux environment into a laboratory where you can create and destroy systems, experiment with networking, run services, and explore different operating systems.&lt;/p&gt;

&lt;p&gt;And because the environment is reproducible, breaking something isn't the end of the world.&lt;/p&gt;

&lt;p&gt;It is often the beginning of the lesson.&lt;/p&gt;

&lt;p&gt;If you're a student, teacher, developer, or simply someone curious about Linux, this can be a practical starting point for building your own systems laboratory without needing another computer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start the Lab
&lt;/h2&gt;

&lt;p&gt;The complete learning material, setup instructions, exercises, and documentation are available here:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/hardyweb/Incus-WSL-Learning-Laboratory" rel="noopener noreferrer"&gt;https://github.com/hardyweb/Incus-WSL-Learning-Laboratory&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The project is open source and released under the MIT License.&lt;/p&gt;

&lt;p&gt;So, if you're sitting in front of a Windows PC right now, maybe you already have everything you need to start learning Linux.&lt;/p&gt;

&lt;h2&gt;
  
  
  You don't need big tech to build big things.
&lt;/h2&gt;

&lt;p&gt;You just need a place to experiment, the willingness to break things, and enough curiosity to figure out how to fix them.&lt;/p&gt;

</description>
      <category>linux</category>
      <category>windows</category>
      <category>devops</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Learning Distributed Object Storage with Incus and PGSTY SILO</title>
      <dc:creator>hardyweb</dc:creator>
      <pubDate>Fri, 02 Oct 2026 12:42:20 +0000</pubDate>
      <link>https://dev.to/hardyweb/learning-distributed-object-storage-with-incus-and-pgsty-silo-3ad9</link>
      <guid>https://dev.to/hardyweb/learning-distributed-object-storage-with-incus-and-pgsty-silo-3ad9</guid>
      <description>&lt;p&gt;Aku buat R&amp;amp;D homelab untuk memahami konsep &lt;strong&gt;distributed storage&lt;/strong&gt;, khususnya bagaimana object storage seperti MinIO/SILO menggunakan beberapa storage drives dan nodes untuk menyediakan redundancy dan survive daripada kegagalan storage.&lt;/p&gt;

&lt;p&gt;Untuk lab ini, aku gunakan:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Windows + WSL2&lt;/li&gt;
&lt;li&gt;Debian&lt;/li&gt;
&lt;li&gt;Incus&lt;/li&gt;
&lt;li&gt;Debian VM &lt;/li&gt;
&lt;li&gt;PGSTY SILO&lt;/li&gt;
&lt;li&gt;MinIO Client (&lt;code&gt;mc&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;ext4 filesystem&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tujuan utama bukan untuk membina production storage cluster, tetapi untuk &lt;strong&gt;memahami apa yang berlaku apabila storage drive atau node gagal&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;PGSTY SILO ialah fork daripada MinIO yang mengekalkan compatibility dengan S3 dan MinIO tooling. (&lt;a href="https://github.com/pgsty/silo?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;github.com&lt;/a&gt;)&lt;/p&gt;




&lt;h1&gt;
  
  
  1. Apa yang aku cuba faham?
&lt;/h1&gt;

&lt;p&gt;Istilah seperti:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;distributed storage&lt;/li&gt;
&lt;li&gt;object storage&lt;/li&gt;
&lt;li&gt;erasure coding&lt;/li&gt;
&lt;li&gt;quorum&lt;/li&gt;
&lt;li&gt;storage node&lt;/li&gt;
&lt;li&gt;storage drive&lt;/li&gt;
&lt;li&gt;drive failure&lt;/li&gt;
&lt;li&gt;node failure&lt;/li&gt;
&lt;li&gt;healing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;nampak macam konsep yang berasingan.&lt;/p&gt;

&lt;p&gt;Jadi aku nak buat experiment yang mudah:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Kalau satu storage drive mati, adakah object masih boleh dibaca?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Kemudian:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Apa pula yang berlaku kalau satu server/node mati?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Daripada sini kita boleh faham konsep distributed storage melalui experiment sebenar.&lt;/p&gt;




&lt;h1&gt;
  
  
  2. Kenapa guna Incus?
&lt;/h1&gt;

&lt;p&gt;Aku tidak mempunyai beberapa physical server untuk dijadikan storage nodes.&lt;/p&gt;

&lt;p&gt;Jadi Incus digunakan untuk &lt;strong&gt;simulate beberapa server&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Topology:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;WSL2
 │
 └── Incus
      │
      ├── debian-vm
      │    ├── sdb → storage drive 1
      │    └── sdc → storage drive 2
      │
      └── debian-vm2
           ├── sdb → storage drive 3
           └── sdc → storage drive 4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;VM bukan distributed storage itu sendiri.&lt;/p&gt;

&lt;p&gt;VM hanya digunakan sebagai &lt;strong&gt;simulation of storage nodes&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Distributed storage berlaku pada layer SILO.&lt;/p&gt;




&lt;h1&gt;
  
  
  3. Kenapa guna VM, bukan container?
&lt;/h1&gt;

&lt;p&gt;Pada awalnya aku cuba menggunakan Incus container. Incus Container menggunakan root block sebagai virtual  hdd. cara lain adalah menggunakan real block device  seperti:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/dev/sdb
/dev/sdc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ia diperlukan agar dapat simulate storage drive sebenar.&lt;/p&gt;

&lt;p&gt;Incus custom block volumes boleh digunakan pada VM dan disk devices VM menyokong hotplug. (&lt;a href="https://linuxcontainers.org/incus/docs/main/reference/devices_disk/?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;linuxcontainers.org&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Jadi architecture akhirnya:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Incus
 │
 ├── debian-vm
 │    ├── /dev/sdb
 │    └── /dev/sdc
 │
 └── debian-vm2
      ├── /dev/sdb
      └── /dev/sdc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  4. Membina storage drives
&lt;/h1&gt;

&lt;p&gt;Untuk setiap VM, aku create dua Incus block volumes.&lt;/p&gt;

&lt;p&gt;Contohnya:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;incus storage volume create default silo1 &lt;span class="nv"&gt;size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;5GiB &lt;span class="nt"&gt;--type&lt;/span&gt; block
incus storage volume create default silo1-extra &lt;span class="nv"&gt;size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;5GiB &lt;span class="nt"&gt;--type&lt;/span&gt; block
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Kemudian attach kepada VM:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;incus config device add debian-vm silo-disk &lt;span class="se"&gt;\&lt;/span&gt;
    disk &lt;span class="nv"&gt;pool&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;default &lt;span class="nb"&gt;source&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;silo1

incus config device add debian-vm silo-disk2 &lt;span class="se"&gt;\&lt;/span&gt;
    disk &lt;span class="nv"&gt;pool&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;default &lt;span class="nb"&gt;source&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;silo1-extra
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hasilnya:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;debian-vm

sda  30G   OS
sdb   5G   storage
sdc   5G   storage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Perkara yang sama dibuat pada &lt;code&gt;debian-vm2&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Akhirnya:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2 nodes × 2 drives = 4 storage endpoints
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  5. Format dan mount storage
&lt;/h1&gt;

&lt;p&gt;Setiap block device diformat sebagai ext4:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;mkfs.ext4 /dev/sdb
&lt;span class="nb"&gt;sudo &lt;/span&gt;mkfs.ext4 /dev/sdc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Kemudian:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /mnt/export1
&lt;span class="nb"&gt;sudo mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /mnt/export2

&lt;span class="nb"&gt;sudo &lt;/span&gt;mount /dev/sdb /mnt/export1
&lt;span class="nb"&gt;sudo &lt;/span&gt;mount /dev/sdc /mnt/export2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Jadi setiap node mempunyai:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/mnt/export1
/mnt/export2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;yang masing-masing berada pada storage drive berbeza.&lt;/p&gt;

&lt;p&gt;Untuk lab ini, mount dilakukan secara manual. &lt;code&gt;fstab&lt;/code&gt; belum digunakan kerana fokusnya adalah experiment storage failure.&lt;/p&gt;




&lt;h1&gt;
  
  
  6. Network antara nodes
&lt;/h1&gt;

&lt;p&gt;SILO memerlukan nodes berkomunikasi antara satu sama lain.&lt;/p&gt;

&lt;p&gt;Incus menyediakan network dan DNS antara instances.&lt;/p&gt;

&lt;p&gt;Contohnya:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ping debian-vm2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;berjaya dari &lt;code&gt;debian-vm&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Jadi SILO boleh menggunakan hostname:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;debian-vm
debian-vm2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;sebagai storage endpoints.&lt;/p&gt;




&lt;h1&gt;
  
  
  7. Setup SILO authentication
&lt;/h1&gt;

&lt;p&gt;Sebelum menjalankan SILO, kita set credential untuk S3/API.&lt;/p&gt;

&lt;p&gt;Untuk lab, kita gunakan environment variables:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;SILO_ROOT_USER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"siloadmin"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;SILO_ROOT_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"change-this-password"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Jangan gunakan password contoh ini untuk production.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Password perlu cukup kuat dan sebaiknya disimpan melalui secret-management mechanism apabila deployment sudah menjadi production.&lt;/p&gt;

&lt;p&gt;Kemudian jalankan SILO dengan storage endpoints:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;silo server &lt;span class="se"&gt;\&lt;/span&gt;
    http://debian-vm/mnt/export1 &lt;span class="se"&gt;\&lt;/span&gt;
    http://debian-vm/mnt/export2 &lt;span class="se"&gt;\&lt;/span&gt;
    http://debian-vm2/mnt/export1 &lt;span class="se"&gt;\&lt;/span&gt;
    http://debian-vm2/mnt/export2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Nama environment variable dan authentication mechanism perlu disesuaikan dengan versi SILO yang digunakan. Semak &lt;code&gt;silo server --help&lt;/code&gt; atau dokumentasi versi yang dipasang sebelum production deployment.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h1&gt;
  
  
  8. Connect menggunakan &lt;code&gt;mc&lt;/code&gt;
&lt;/h1&gt;

&lt;p&gt;Selepas SILO berjalan, &lt;code&gt;mc&lt;/code&gt; digunakan sebagai S3 client.&lt;/p&gt;

&lt;p&gt;Contohnya:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mc &lt;span class="nb"&gt;alias set &lt;/span&gt;silo &lt;span class="se"&gt;\&lt;/span&gt;
    http://debian-vm:9000 &lt;span class="se"&gt;\&lt;/span&gt;
    siloadmin &lt;span class="se"&gt;\&lt;/span&gt;
    change-this-password
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Kemudian check:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mc &lt;span class="nb"&gt;alias &lt;/span&gt;list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;dan:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mc admin info silo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;mc&lt;/code&gt; sekarang boleh digunakan untuk:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;create bucket&lt;/li&gt;
&lt;li&gt;upload object&lt;/li&gt;
&lt;li&gt;download object&lt;/li&gt;
&lt;li&gt;inspect server&lt;/li&gt;
&lt;li&gt;inspect storage status&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Contoh:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mc mb silo/test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Kemudian upload:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"distributed storage test"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; test.txt

mc &lt;span class="nb"&gt;cp &lt;/span&gt;test.txt silo/test/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dan verify:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mc &lt;span class="nb"&gt;ls &lt;/span&gt;silo/test/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  9. Membina distributed SILO pool
&lt;/h1&gt;

&lt;p&gt;SILO dijalankan menggunakan keempat-empat storage endpoints:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;silo server &lt;span class="se"&gt;\&lt;/span&gt;
    http://debian-vm/mnt/export1 &lt;span class="se"&gt;\&lt;/span&gt;
    http://debian-vm/mnt/export2 &lt;span class="se"&gt;\&lt;/span&gt;
    http://debian-vm2/mnt/export1 &lt;span class="se"&gt;\&lt;/span&gt;
    http://debian-vm2/mnt/export2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sekarang SILO tidak lagi melihat storage sebagai empat directory yang tidak berkaitan.&lt;/p&gt;

&lt;p&gt;Ia melihatnya sebagai satu distributed storage pool.&lt;/p&gt;

&lt;p&gt;Topology:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                    SILO
                     │
              Distributed Pool
                     │
        ┌────────────┴────────────┐
        │                         │
   debian-vm                 debian-vm2
        │                         │
    ┌───┴───┐                 ┌───┴───┐
    │       │                 │       │
   sdb     sdc               sdb     sdc
    │       │                 │       │
   D1      D2                D3      D4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dalam experiment ini, &lt;code&gt;mc admin info&lt;/code&gt; menunjukkan:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Pool: 1

Drives: 2/2 OK
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;dan:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Pool | Drives Usage | Erasure stripe size | Erasure sets
1st  | 0.0%         | 4                   | 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Jadi empat storage endpoints tersebut membentuk:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1 pool
1 erasure set
4 drives
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  10. Distributed storage bukan sekadar "copy file"
&lt;/h1&gt;

&lt;p&gt;Salah satu perkara penting yang aku mula faham:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;4 drives ≠ semestinya 4 copies
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Distributed object storage menggunakan mekanisme seperti &lt;strong&gt;erasure coding&lt;/strong&gt; untuk menyediakan redundancy.&lt;/p&gt;

&lt;p&gt;Secara konsep:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;             Object
                │
          Erasure Coding
                │
       ┌────────┼────────┐
       │        │        │
      D1       D2       D3 ... Dn
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Data object dipecahkan kepada beberapa shards dan sebahagian shard digunakan sebagai parity.&lt;/p&gt;

&lt;p&gt;SILO menggunakan storage class dengan konfigurasi parity seperti &lt;code&gt;EC:n&lt;/code&gt;. Konfigurasi sebenar perlu disemak daripada cluster configuration dan &lt;code&gt;mc admin info&lt;/code&gt;, bukan diandaikan hanya berdasarkan jumlah drive. (&lt;a href="https://github.com/pgsty/silo/blob/main/docs/config/README.md?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;github.com&lt;/a&gt;)&lt;/p&gt;




&lt;h1&gt;
  
  
  11. Drive failure experiment
&lt;/h1&gt;

&lt;p&gt;Ini experiment yang paling menarik.&lt;/p&gt;

&lt;p&gt;Aku mahu simulate:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Satu physical drive rosak tetapi server masih hidup.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Kita tidak shutdown VM.&lt;/p&gt;

&lt;p&gt;Contohnya:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;debian-vm

sdb → /mnt/export1
sdc → /mnt/export2
              ↑
           FAILURE
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pertama, filesystem di-unmount:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;umount /mnt/export2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tetapi:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;umount&lt;/code&gt; sahaja bukan bermaksud drive rosak.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ia cuma unmount filesystem.&lt;/p&gt;

&lt;p&gt;Untuk simulate drive benar-benar hilang daripada VM, kita remove Incus disk device:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;incus config device remove debian-vm silo-disk2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Kemudian:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;incus &lt;span class="nb"&gt;exec &lt;/span&gt;debian-vm &lt;span class="nt"&gt;--&lt;/span&gt; lsblk
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;/dev/sdc&lt;/code&gt; sudah tidak kelihatan.&lt;/p&gt;

&lt;p&gt;Sekarang simulation menjadi:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;debian-vm
 │
 ├── sdb  ONLINE
 │
 └── sdc  OFFLINE
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;tetapi:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;debian-vm = RUNNING
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Jadi kita sedang menguji &lt;strong&gt;drive failure&lt;/strong&gt;, bukan node failure.&lt;/p&gt;




&lt;h1&gt;
  
  
  12. Apa yang berlaku kepada object?
&lt;/h1&gt;

&lt;p&gt;Sebelum melakukan failure test, upload satu object:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mc &lt;span class="nb"&gt;cp &lt;/span&gt;test.txt silo/test/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Kemudian pastikan object boleh dibaca:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mc &lt;span class="nb"&gt;cat &lt;/span&gt;silo/test/test.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Selepas satu drive ditarik keluar, cuba lagi:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mc &lt;span class="nb"&gt;cat &lt;/span&gt;silo/test/test.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inilah experiment sebenar yang kita mahu lihat.&lt;/p&gt;

&lt;p&gt;Jika cluster masih mempunyai quorum yang diperlukan untuk operasi tersebut, object boleh terus diakses walaupun satu storage endpoint offline.&lt;/p&gt;

&lt;p&gt;Ini bergantung kepada erasure-set dan storage-class configuration.&lt;/p&gt;




&lt;h1&gt;
  
  
  13. Memasukkan drive kembali
&lt;/h1&gt;

&lt;p&gt;Selepas experiment selesai, drive boleh attach kembali.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;incus config device add debian-vm silo-disk2 &lt;span class="se"&gt;\&lt;/span&gt;
    disk &lt;span class="nv"&gt;pool&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;default &lt;span class="nb"&gt;source&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;silo1-extra
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;incus &lt;span class="nb"&gt;exec &lt;/span&gt;debian-vm &lt;span class="nt"&gt;--&lt;/span&gt; lsblk
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Kita mahu lihat:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sda
sdb
sdc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Kemudian mount kembali:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;incus &lt;span class="nb"&gt;exec &lt;/span&gt;debian-vm &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;mount /dev/sdc /mnt/export2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verify:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;incus &lt;span class="nb"&gt;exec &lt;/span&gt;debian-vm &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nb"&gt;df&lt;/span&gt; &lt;span class="nt"&gt;-hT&lt;/span&gt; /mnt/export2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Kemudian:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mc admin info silo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;untuk melihat status drive dan cluster.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Jangan jalankan &lt;code&gt;mkfs&lt;/code&gt; pada drive yang sama.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Kita mahu preserve filesystem dan storage data yang sedia ada.&lt;/p&gt;




&lt;h1&gt;
  
  
  14. Drive failure vs Node failure
&lt;/h1&gt;

&lt;p&gt;Ini satu lagi konsep penting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Drive failure
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;debian-vm
 │
 ├── drive 1  ONLINE
 └── drive 2  OFFLINE
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Server masih hidup.&lt;/p&gt;

&lt;p&gt;SILO masih boleh berkomunikasi dengan node tersebut.&lt;/p&gt;




&lt;h2&gt;
  
  
  Node failure
&lt;/h2&gt;

&lt;p&gt;Sekarang kita shutdown keseluruhan VM:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;debian-vm          OFFLINE
 │
 ├── drive 1
 └── drive 2

debian-vm2         ONLINE
 ├── drive 3
 └── drive 4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dalam keadaan ini dua storage endpoints hilang serentak.&lt;/p&gt;

&lt;p&gt;Jadi:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1 drive failure ≠ 1 node failure
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ini adalah sebab penting kenapa distributed storage perlu dilihat berdasarkan &lt;strong&gt;failure domain&lt;/strong&gt;, bukan sekadar jumlah drives.&lt;/p&gt;




&lt;h1&gt;
  
  
  15. Current lab topology
&lt;/h1&gt;

&lt;p&gt;Topology semasa:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                     WSL2
                       │
                     Incus
                       │
          ┌────────────┴────────────┐
          │                         │
     debian-vm                 debian-vm2
          │                         │
     ┌────┴────┐               ┌────┴────┐
     │         │               │         │
    sdb       sdc             sdb       sdc
     │         │               │         │
   5 GiB     5 GiB            5 GiB     5 GiB
     │         │               │         │
 export1    export2          export1    export2
     └─────────┴───────────────┴─────────┘
                       │
                      SILO
                       │
                    Pool 1
                 1 erasure set
                    4 drives
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Authentication:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;S3/API user:
siloadmin

Password:
set melalui SILO environment variable
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Client:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mc
 │
 └── silo alias
       │
       └── http://debian-vm:9000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  16. Apa yang aku belajar
&lt;/h1&gt;

&lt;p&gt;Lab ini bermula dengan soalan:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Macam mana distributed storage sebenarnya bekerja?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Sekarang konsepnya lebih jelas:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Node
 │
 ├── Drive
 ├── Drive
 │
 └── SILO
       │
       ├── Erasure Set
       ├── Erasure Coding
       ├── Quorum
       ├── Failure Detection
       └── Recovery / Healing
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Incus pula digunakan untuk simulate infrastructure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Incus
  ↓
Virtual Machines
  ↓
Block Devices
  ↓
Filesystems
  ↓
SILO
  ↓
Distributed Object Storage
  ↓
S3 Client (mc)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  17. Next experiment
&lt;/h1&gt;

&lt;p&gt;Selepas berjaya memahami single-drive failure, experiment seterusnya:&lt;/p&gt;

&lt;h3&gt;
  
  
  Experiment 1 — Node failure
&lt;/h3&gt;

&lt;p&gt;Shutdown:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;debian-vm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Kemudian lihat behaviour cluster.&lt;/p&gt;

&lt;h3&gt;
  
  
  Experiment 2 — Node recovery
&lt;/h3&gt;

&lt;p&gt;Start semula:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;debian-vm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Kemudian observe status drives.&lt;/p&gt;

&lt;h3&gt;
  
  
  Experiment 3 — Healing
&lt;/h3&gt;

&lt;p&gt;Perhatikan sama ada cluster melakukan recovery/healing selepas storage kembali.&lt;/p&gt;

&lt;h3&gt;
  
  
  Experiment 4 — Load balancer
&lt;/h3&gt;

&lt;p&gt;Selepas memahami storage layer, baru tambah Nginx sebagai client-facing endpoint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                 Client
                    │
                  Nginx
                    │
          ┌─────────┴─────────┐
          │                   │
      debian-vm           debian-vm2
          │                   │
       D1   D2              D3   D4
          \                   /
           \────── SILO ─────/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ini memisahkan dua konsep:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SILO
→ distributed storage / data resilience

Nginx
→ client traffic / endpoint failover
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Apa yang menarik tentang lab ini ialah kita tidak hanya menjalankan MinIO/SILO.&lt;/p&gt;

&lt;p&gt;Kita cuba &lt;strong&gt;merosakkan storage secara sengaja&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Mula dengan:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;4 drives
2 nodes
1 erasure set
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Kemudian:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pull 1 drive
        ↓
observe
        ↓
attach kembali
        ↓
observe recovery
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Daripada experiment ini, konsep distributed storage menjadi lebih mudah difahami kerana kita boleh melihat sendiri hubungan antara:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Node
+
Drive
+
Erasure Coding
+
Erasure Set
+
Quorum
+
Failure
+
Recovery
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Seterusnya kita akan cuba &lt;strong&gt;matikan satu node&lt;/strong&gt;, bukan sekadar satu drive.&lt;/p&gt;

&lt;p&gt;Itulah beza antara:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;"satu disk rosak"&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;dan&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;"satu server storage hilang."&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>architecture</category>
      <category>backend</category>
      <category>cloud</category>
      <category>linux</category>
    </item>
    <item>
      <title>Stop AI From Writing Sloppy Laravel Code: My Kilo Code + AGENTS.md Workflow</title>
      <dc:creator>hardyweb</dc:creator>
      <pubDate>Fri, 25 Sep 2026 12:41:29 +0000</pubDate>
      <link>https://dev.to/hardyweb/stop-ai-from-writing-sloppy-laravel-code-my-kilo-code-agentsmd-workflow-3556</link>
      <guid>https://dev.to/hardyweb/stop-ai-from-writing-sloppy-laravel-code-my-kilo-code-agentsmd-workflow-3556</guid>
      <description>&lt;p&gt;AI coding assistants are getting very good at generating Laravel code.&lt;/p&gt;

&lt;p&gt;Give an AI a feature request and it can probably create:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;migrations&lt;/li&gt;
&lt;li&gt;models&lt;/li&gt;
&lt;li&gt;controllers&lt;/li&gt;
&lt;li&gt;Form Requests&lt;/li&gt;
&lt;li&gt;Blade views&lt;/li&gt;
&lt;li&gt;routes&lt;/li&gt;
&lt;li&gt;tests&lt;/li&gt;
&lt;li&gt;JavaScript&lt;/li&gt;
&lt;li&gt;CSS&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The problem is not whether the code works.&lt;/p&gt;

&lt;p&gt;The problem is whether the code &lt;strong&gt;belongs in the project&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;AI can easily generate Laravel code that works today but becomes a maintenance problem tomorrow:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;fat controllers&lt;/li&gt;
&lt;li&gt;duplicated business logic&lt;/li&gt;
&lt;li&gt;unnecessary service/repository layers&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$request-&amp;gt;all()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;N+1 queries&lt;/li&gt;
&lt;li&gt;database queries inside Blade&lt;/li&gt;
&lt;li&gt;huge inline &lt;code&gt;&amp;lt;style&amp;gt;&lt;/code&gt; blocks&lt;/li&gt;
&lt;li&gt;huge inline &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; blocks&lt;/li&gt;
&lt;li&gt;introducing another frontend framework&lt;/li&gt;
&lt;li&gt;ignoring existing components&lt;/li&gt;
&lt;li&gt;rewriting parts of the starter kit&lt;/li&gt;
&lt;li&gt;unrelated refactoring&lt;/li&gt;
&lt;li&gt;debug code left behind&lt;/li&gt;
&lt;li&gt;tests that were never actually executed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For me, the solution is not to tell the AI to "write better code".&lt;/p&gt;

&lt;p&gt;The better approach is to &lt;strong&gt;define the engineering rules and make the AI work inside the existing project architecture&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;My current workflow is built around:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Laravel Project
      │
      ├── AGENTS.md
      │      └── Engineering rules
      │
      ├── skills.md
      │      └── Knowledge / examples / procedures
      │
      └── Kilo Code
             └── Implement within those rules
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And for longer-running projects, there is another layer that can work alongside them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DSOM Brain
└── Project state, decisions, continuity and context
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I'll come back to that near the end.&lt;/p&gt;




&lt;h1&gt;
  
  
  1. First Rule: Inspect Before You Code
&lt;/h1&gt;

&lt;p&gt;Before asking an AI coding agent to implement anything, I want it to understand the project that already exists.&lt;/p&gt;

&lt;p&gt;This is probably the most important rule in my workflow.&lt;/p&gt;

&lt;p&gt;Don't start with:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Build a user management system."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Start with:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Inspect the existing project first."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The AI should inspect things such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Laravel version&lt;/li&gt;
&lt;li&gt;&lt;code&gt;composer.json&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;existing application structure&lt;/li&gt;
&lt;li&gt;authentication system&lt;/li&gt;
&lt;li&gt;authorization approach&lt;/li&gt;
&lt;li&gt;existing routes&lt;/li&gt;
&lt;li&gt;controllers&lt;/li&gt;
&lt;li&gt;models&lt;/li&gt;
&lt;li&gt;Form Requests&lt;/li&gt;
&lt;li&gt;policies&lt;/li&gt;
&lt;li&gt;migrations&lt;/li&gt;
&lt;li&gt;tests&lt;/li&gt;
&lt;li&gt;frontend architecture&lt;/li&gt;
&lt;li&gt;starter kit&lt;/li&gt;
&lt;li&gt;CSS framework&lt;/li&gt;
&lt;li&gt;JavaScript/TypeScript structure&lt;/li&gt;
&lt;li&gt;existing components&lt;/li&gt;
&lt;li&gt;project conventions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The reason is simple.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The existing project is already an architecture.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If the application already uses Livewire, don't suddenly introduce Inertia and React just because the AI knows how to generate them.&lt;/p&gt;

&lt;p&gt;If the application already uses React + Inertia, don't create a random Blade-based application UI.&lt;/p&gt;

&lt;p&gt;If the application uses Tailwind, don't introduce Bootstrap.&lt;/p&gt;

&lt;p&gt;If the project already has reusable components, don't create another component that does the same thing.&lt;/p&gt;

&lt;p&gt;AI should extend the project, not accidentally redesign it.&lt;/p&gt;




&lt;h1&gt;
  
  
  2. Why AI-Generated Laravel Code Can Become Sloppy
&lt;/h1&gt;

&lt;p&gt;AI optimizes heavily for producing a plausible solution.&lt;/p&gt;

&lt;p&gt;That doesn't necessarily mean it optimizes for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;consistency&lt;/li&gt;
&lt;li&gt;simplicity&lt;/li&gt;
&lt;li&gt;maintainability&lt;/li&gt;
&lt;li&gt;project conventions&lt;/li&gt;
&lt;li&gt;long-term architecture&lt;/li&gt;
&lt;li&gt;minimal changes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, imagine this request:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Add an endpoint to update a user's profile.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A simplistic AI implementation might put everything inside the controller:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Request&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;User&lt;/span&gt; &lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

    &lt;span class="c1"&gt;// validation&lt;/span&gt;
    &lt;span class="c1"&gt;// authorization&lt;/span&gt;
    &lt;span class="c1"&gt;// business logic&lt;/span&gt;
    &lt;span class="c1"&gt;// logging&lt;/span&gt;
    &lt;span class="c1"&gt;// notifications&lt;/span&gt;
    &lt;span class="c1"&gt;// other operations...&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;back&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It might work.&lt;/p&gt;

&lt;p&gt;But the better Laravel implementation should consider:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Form Request validation&lt;/li&gt;
&lt;li&gt;authorization&lt;/li&gt;
&lt;li&gt;mass-assignment rules&lt;/li&gt;
&lt;li&gt;route model binding&lt;/li&gt;
&lt;li&gt;business logic placement&lt;/li&gt;
&lt;li&gt;transactions if required&lt;/li&gt;
&lt;li&gt;testing&lt;/li&gt;
&lt;li&gt;security implications&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal isn't to make the code more complicated.&lt;/p&gt;

&lt;p&gt;The goal is to put each responsibility where it belongs.&lt;/p&gt;




&lt;h1&gt;
  
  
  This Concept Is Not Kilo Code Specific
&lt;/h1&gt;

&lt;p&gt;Although this workflow was developed and tested with Kilo Code, the underlying idea is not tied to Kilo Code.&lt;/p&gt;

&lt;p&gt;The important part is not the tool name. The important part is giving an AI coding agent a clear set of engineering rules, project knowledge, and working context before asking it to write code.&lt;/p&gt;

&lt;p&gt;If you use other coding agents such as OpenCode, Codex, or Claude Code, you can apply the same concept.&lt;/p&gt;

&lt;p&gt;The exact mechanism may be different:&lt;/p&gt;

&lt;p&gt;the instruction file may have a different name,&lt;br&gt;
the location may be different,&lt;br&gt;
the way instructions are loaded may be different,&lt;br&gt;
and each tool may have its own instruction hierarchy or configuration.&lt;/p&gt;

&lt;p&gt;But the architecture can remain the same:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                AI Coding Agent
                       │
          ┌────────────┼────────────┐
          ▼            ▼            ▼
    Engineering     Project      Working
       Rules       Knowledge      Context
          │            │            │
          └────────────┼────────────┘
                       ▼
                Laravel Project
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;For example, the same principles can be adapted to:&lt;/p&gt;

&lt;p&gt;Kilo Code    → AGENTS.md + skills&lt;br&gt;
OpenCode     → project instructions / AGENTS.md&lt;br&gt;
Codex        → project instructions / AGENTS.md&lt;br&gt;
Claude Code  → project instructions / CLAUDE.md&lt;/p&gt;

&lt;p&gt;The exact filenames and supported features should be checked against the documentation for the coding agent you are using.&lt;/p&gt;

&lt;p&gt;The key idea&lt;/p&gt;

&lt;p&gt;Don't think:&lt;/p&gt;

&lt;p&gt;"I need to use Kilo Code because this workflow uses AGENTS.md."&lt;/p&gt;

&lt;p&gt;Think instead:&lt;/p&gt;

&lt;p&gt;"I need to give my coding agent an engineering contract."&lt;/p&gt;

&lt;p&gt;That contract should tell the agent things such as:&lt;/p&gt;

&lt;p&gt;how the project is structured,&lt;br&gt;
which Laravel conventions to follow,&lt;br&gt;
how authorization should be handled,&lt;br&gt;
where validation belongs,&lt;br&gt;
how database access should be designed,&lt;br&gt;
what security practices are required,&lt;br&gt;
how tests should be written,&lt;br&gt;
what the agent must inspect before changing code,&lt;br&gt;
and what it should not change unnecessarily.&lt;/p&gt;

&lt;p&gt;So if you move from Kilo Code to OpenCode, Codex, or Claude Code, you don't have to throw away the workflow.&lt;/p&gt;

&lt;p&gt;You adapt the instruction layer, while keeping the underlying engineering principles.&lt;/p&gt;

&lt;p&gt;This makes the workflow tool-agnostic, even though my current implementation and examples are based on Kilo Code.&lt;/p&gt;
&lt;h1&gt;
  
  
  3. &lt;code&gt;AGENTS.md&lt;/code&gt; as the Project Engineering Contract
&lt;/h1&gt;

&lt;p&gt;This is where &lt;code&gt;AGENTS.md&lt;/code&gt; becomes useful.&lt;/p&gt;

&lt;p&gt;Instead of repeating the same instructions every time I ask the AI to implement something, I keep the important engineering rules inside the repository.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my-laravel-app/
├── AGENTS.md
├── skills.md
├── composer.json
├── artisan
├── app/
├── bootstrap/
├── config/
├── database/
├── public/
├── resources/
├── routes/
├── storage/
└── tests/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important idea is that &lt;code&gt;AGENTS.md&lt;/code&gt; is not documentation for humans only.&lt;/p&gt;

&lt;p&gt;It becomes a &lt;strong&gt;working contract between the project and the AI coding agent&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# Laravel Engineering Rules&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; Follow the existing project architecture.
&lt;span class="p"&gt;-&lt;/span&gt; Inspect existing code before implementation.
&lt;span class="p"&gt;-&lt;/span&gt; Keep controllers thin.
&lt;span class="p"&gt;-&lt;/span&gt; Use Form Requests for validation.
&lt;span class="p"&gt;-&lt;/span&gt; Use policies for authorization.
&lt;span class="p"&gt;-&lt;/span&gt; Prefer Eloquent over unnecessary repository abstractions.
&lt;span class="p"&gt;-&lt;/span&gt; Do not put business logic in Blade.
&lt;span class="p"&gt;-&lt;/span&gt; Avoid N+1 queries.
&lt;span class="p"&gt;-&lt;/span&gt; Use migrations for database changes.
&lt;span class="p"&gt;-&lt;/span&gt; Write tests for application behaviour.
&lt;span class="p"&gt;-&lt;/span&gt; Do not introduce another frontend framework without a clear requirement.
&lt;span class="p"&gt;-&lt;/span&gt; Reuse existing components.
&lt;span class="p"&gt;-&lt;/span&gt; Do not add unnecessary abstractions.
&lt;span class="p"&gt;-&lt;/span&gt; Do not refactor unrelated code.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the AI has something concrete to follow.&lt;/p&gt;




&lt;h1&gt;
  
  
  4. Follow the Existing Laravel Starter Kit
&lt;/h1&gt;

&lt;p&gt;Laravel applications don't all have the same frontend architecture.&lt;/p&gt;

&lt;p&gt;A project may use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Livewire&lt;/li&gt;
&lt;li&gt;React + Inertia&lt;/li&gt;
&lt;li&gt;Vue + Inertia&lt;/li&gt;
&lt;li&gt;Blade&lt;/li&gt;
&lt;li&gt;Tailwind&lt;/li&gt;
&lt;li&gt;another existing frontend setup&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Laravel's current starter kits also provide different application stacks, so the starter kit already present in a project should be treated as part of that project's architecture.&lt;/p&gt;

&lt;p&gt;My rule is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Inspect the starter kit before creating new UI.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If the project already has a component system, use it.&lt;/p&gt;

&lt;p&gt;If the project already has layouts, use them.&lt;/p&gt;

&lt;p&gt;If the project already has navigation components, don't create another navigation implementation.&lt;/p&gt;

&lt;p&gt;The starter kit is a starting architecture, not something the AI should casually replace.&lt;/p&gt;




&lt;h1&gt;
  
  
  5. Don't Introduce Another Frontend Stack
&lt;/h1&gt;

&lt;p&gt;This is one of the easiest ways for AI-generated code to become messy.&lt;/p&gt;

&lt;p&gt;Imagine an existing Laravel project using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Blade + Alpine + Tailwind
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then an AI decides to add:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;React + Vite + another component library
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the project has two frontend architectures.&lt;/p&gt;

&lt;p&gt;That might be justified in some applications.&lt;/p&gt;

&lt;p&gt;But it should never happen simply because the AI generated a React solution faster.&lt;/p&gt;

&lt;p&gt;The rule should be:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Follow the frontend architecture already used by the project unless there is an explicit reason to change it.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h1&gt;
  
  
  6. Reuse Existing Components
&lt;/h1&gt;

&lt;p&gt;Before creating a new component, look for an existing one.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resources/views/components/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;might already contain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;button.blade.php
input.blade.php
modal.blade.php
alert.blade.php
table.blade.php
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the application already has a button component, don't generate another button implementation.&lt;/p&gt;

&lt;p&gt;The AI should inspect first.&lt;/p&gt;

&lt;p&gt;This simple rule prevents a lot of duplication.&lt;/p&gt;




&lt;h1&gt;
  
  
  7. Don't Put Raw CSS Inside Blade
&lt;/h1&gt;

&lt;p&gt;Another common AI-generated pattern is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;style&amp;gt;
    .some-big-component {
        ...
    }

    .another-component {
        ...
    }

    /* 200 more lines */
&amp;lt;/style&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This may work, but it can quickly become difficult to maintain.&lt;/p&gt;

&lt;p&gt;If the project uses Tailwind, use Tailwind.&lt;/p&gt;

&lt;p&gt;If the project uses Bootstrap, use Bootstrap.&lt;/p&gt;

&lt;p&gt;If custom CSS is genuinely required, put it into the project's existing CSS structure.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resources/
└── css/
    ├── app.css
    └── components/
        └── editor.css
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The exact structure depends on the project.&lt;/p&gt;

&lt;p&gt;The important rule is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Follow the project's existing CSS architecture instead of dumping large amounts of CSS into Blade.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The same principle applies to JavaScript.&lt;/p&gt;

&lt;p&gt;Don't create a huge:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;script&amp;gt;
    // 300 lines of application logic
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;inside a Blade view if the project already has a proper JavaScript/TypeScript structure.&lt;/p&gt;




&lt;h1&gt;
  
  
  8. My Basic Laravel Architecture Rules
&lt;/h1&gt;

&lt;p&gt;These are the rules I want an AI coding agent to understand before it starts changing my Laravel application.&lt;/p&gt;




&lt;h2&gt;
  
  
  Thin Controllers
&lt;/h2&gt;

&lt;p&gt;Controllers should coordinate the request.&lt;/p&gt;

&lt;p&gt;They shouldn't become the entire application.&lt;/p&gt;

&lt;p&gt;Bad:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Request&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// validation&lt;/span&gt;

    &lt;span class="c1"&gt;// authorization&lt;/span&gt;

    &lt;span class="c1"&gt;// database queries&lt;/span&gt;

    &lt;span class="c1"&gt;// business rules&lt;/span&gt;

    &lt;span class="c1"&gt;// notifications&lt;/span&gt;

    &lt;span class="c1"&gt;// logging&lt;/span&gt;

    &lt;span class="c1"&gt;// calculations&lt;/span&gt;

    &lt;span class="c1"&gt;// 100 more lines&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Better:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;StoreOrderRequest&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;authorize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'create'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Order&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nv"&gt;$order&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;orderService&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;validated&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'orders.show'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$order&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The exact architecture depends on the project.&lt;/p&gt;

&lt;p&gt;The important part is keeping responsibilities separated.&lt;/p&gt;




&lt;h1&gt;
  
  
  9. Form Requests Instead of &lt;code&gt;$request-&amp;gt;all()&lt;/code&gt;
&lt;/h1&gt;

&lt;p&gt;I don't want AI-generated Laravel code to casually do this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Especially when the data is going into a model.&lt;/p&gt;

&lt;p&gt;Use a Form Request when validation and authorization belong there:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;validated&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;safe&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;only&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="s1"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'email'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This makes the input boundary explicit.&lt;/p&gt;

&lt;p&gt;It also reduces the chance of accidentally passing unexpected fields into application logic.&lt;/p&gt;




&lt;h1&gt;
  
  
  10. Authorization Is Not Authentication
&lt;/h1&gt;

&lt;p&gt;Another common mistake is confusing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Who are you?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Are you allowed to do this?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Authentication identifies the user.&lt;/p&gt;

&lt;p&gt;Authorization determines whether that user can perform the operation.&lt;/p&gt;

&lt;p&gt;Laravel provides policies and gates for this.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;authorize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'update'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$post&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The AI should not assume that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nf"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;check&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;means the user is allowed to modify the resource.&lt;/p&gt;




&lt;h1&gt;
  
  
  11. Eloquent First
&lt;/h1&gt;

&lt;p&gt;Laravel already provides a powerful ORM.&lt;/p&gt;

&lt;p&gt;I don't want an AI to create:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Repository
    ↓
Interface
    ↓
Repository Implementation
    ↓
Manager
    ↓
Service
    ↓
Model
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;for a simple CRUD operation.&lt;/p&gt;

&lt;p&gt;If Eloquent is enough:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;findOrFail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;use Eloquent.&lt;/p&gt;

&lt;p&gt;Repositories can be useful in the right context.&lt;/p&gt;

&lt;p&gt;But abstraction should solve a problem, not create one.&lt;/p&gt;




&lt;h1&gt;
  
  
  12. Check for N+1 Queries
&lt;/h1&gt;

&lt;p&gt;AI-generated Laravel code can easily create N+1 queries.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$posts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Post&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$posts&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$post&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$post&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The correct implementation may need:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$posts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Post&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'author'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The AI should inspect relationships and query behaviour rather than assuming that syntactically valid Eloquent code is automatically efficient.&lt;/p&gt;




&lt;h1&gt;
  
  
  13. Don't Put Business Logic in Blade
&lt;/h1&gt;

&lt;p&gt;Blade should primarily handle presentation.&lt;/p&gt;

&lt;p&gt;I don't want this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@php
    $orders = Order::where('user_id', auth()-&amp;gt;id())-&amp;gt;get();

    // business logic
    // calculations
    // database operations
@endphp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The view should receive the data it needs.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$orders&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;latest&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;view&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'orders.index'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;compact&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'orders'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then Blade renders it.&lt;/p&gt;




&lt;h1&gt;
  
  
  14. Services and Actions Only When Needed
&lt;/h1&gt;

&lt;p&gt;I'm not against service classes.&lt;/p&gt;

&lt;p&gt;I'm against creating them automatically.&lt;/p&gt;

&lt;p&gt;A service or action can make sense when there is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;complex business logic&lt;/li&gt;
&lt;li&gt;reusable application behaviour&lt;/li&gt;
&lt;li&gt;multiple steps&lt;/li&gt;
&lt;li&gt;transaction boundaries&lt;/li&gt;
&lt;li&gt;difficult-to-test logic&lt;/li&gt;
&lt;li&gt;meaningful separation of responsibilities&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CreateUserService
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;for a three-line CRUD operation may simply add another layer.&lt;/p&gt;

&lt;p&gt;The rule is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Introduce abstractions because the problem requires them, not because AI likes generating classes.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h1&gt;
  
  
  15. Database Changes Through Migrations
&lt;/h1&gt;

&lt;p&gt;Don't manually modify production database structures.&lt;/p&gt;

&lt;p&gt;Use migrations.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan make:migration add_status_to_orders_table
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then define the change.&lt;/p&gt;

&lt;p&gt;Database design should also consider:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;foreign keys&lt;/li&gt;
&lt;li&gt;indexes&lt;/li&gt;
&lt;li&gt;unique constraints&lt;/li&gt;
&lt;li&gt;nullable columns&lt;/li&gt;
&lt;li&gt;data types&lt;/li&gt;
&lt;li&gt;relationships&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;AI should inspect the existing schema before creating another migration.&lt;/p&gt;




&lt;h1&gt;
  
  
  16. Transactions When Atomicity Matters
&lt;/h1&gt;

&lt;p&gt;If an operation modifies several related records and they must succeed or fail together, consider a transaction.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="no"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;transaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// create order&lt;/span&gt;

    &lt;span class="c1"&gt;// create order items&lt;/span&gt;

    &lt;span class="c1"&gt;// update inventory&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But again, don't wrap every single database query inside a transaction just because the AI knows the API exists.&lt;/p&gt;

&lt;p&gt;Use transactions when atomicity matters.&lt;/p&gt;




&lt;h1&gt;
  
  
  17. Security Is Part of the Coding Standard
&lt;/h1&gt;

&lt;p&gt;Security shouldn't be an afterthought.&lt;/p&gt;

&lt;p&gt;For Laravel development, I want the AI to consider:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;authentication&lt;/li&gt;
&lt;li&gt;authorization&lt;/li&gt;
&lt;li&gt;validation&lt;/li&gt;
&lt;li&gt;mass assignment&lt;/li&gt;
&lt;li&gt;CSRF&lt;/li&gt;
&lt;li&gt;XSS&lt;/li&gt;
&lt;li&gt;SQL injection&lt;/li&gt;
&lt;li&gt;file uploads&lt;/li&gt;
&lt;li&gt;path traversal&lt;/li&gt;
&lt;li&gt;rate limiting&lt;/li&gt;
&lt;li&gt;secrets&lt;/li&gt;
&lt;li&gt;logging&lt;/li&gt;
&lt;li&gt;access control&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nc"&gt;Log&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'User updated profile'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s1"&gt;'user_id'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;is useful.&lt;/p&gt;

&lt;p&gt;But:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nc"&gt;Log&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;could expose sensitive information.&lt;/p&gt;

&lt;p&gt;The AI should understand that logging itself can become a security problem.&lt;/p&gt;




&lt;h1&gt;
  
  
  18. Testing Is Part of the Workflow
&lt;/h1&gt;

&lt;p&gt;I don't want AI to say:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Tests should be added later.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If a feature changes application behaviour, testing should be part of the implementation.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Feature
├── implementation
├── validation
├── authorization
└── tests
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Feature tests are useful for application behaviour.&lt;/p&gt;

&lt;p&gt;Unit tests are useful for isolated logic.&lt;/p&gt;

&lt;p&gt;And one important rule:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Never claim that tests passed unless they were actually executed.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;An AI saying:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;All tests pass.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;without running them is not useful.&lt;/p&gt;




&lt;h1&gt;
  
  
  19. The "No Sloppy AI Code" Checklist
&lt;/h1&gt;

&lt;p&gt;Before accepting AI-generated code, I can ask:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- Did you inspect the existing architecture first?
- Did you follow the existing starter kit?
- Did you reuse existing components?
- Did you follow the existing CSS/JS structure?
- Are controllers still thin?
- Is validation handled properly?
- Is authorization handled separately?
- Did you use Eloquent before introducing abstractions?
- Did you check for N+1 queries?
- Is business logic outside Blade?
- Are services/actions actually justified?
- Are database changes done through migrations?
- Are transactions used only where needed?
- Did you consider security?
- Did you add appropriate tests?
- Did you avoid unrelated refactoring?
- Did you remove debug code?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This checklist is often more valuable than telling an AI:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Write clean code."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Because "clean" is subjective.&lt;/p&gt;

&lt;p&gt;Rules are more explicit.&lt;/p&gt;




&lt;h1&gt;
  
  
  20. &lt;code&gt;skills.md&lt;/code&gt; Is Different From &lt;code&gt;AGENTS.md&lt;/code&gt;
&lt;/h1&gt;

&lt;p&gt;I also like separating &lt;strong&gt;rules&lt;/strong&gt; from &lt;strong&gt;knowledge&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;AGENTS.md&lt;/code&gt; answers:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;How should the AI work on this project?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;While &lt;code&gt;skills.md&lt;/code&gt; can contain:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;useful procedures&lt;/li&gt;
&lt;li&gt;project-specific knowledge&lt;/li&gt;
&lt;li&gt;examples&lt;/li&gt;
&lt;li&gt;commands&lt;/li&gt;
&lt;li&gt;troubleshooting&lt;/li&gt;
&lt;li&gt;reusable implementation patterns&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AGENTS.md
└── Rules

skills.md
└── Knowledge / procedures / examples
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This keeps the main engineering contract focused.&lt;/p&gt;

&lt;p&gt;The AI doesn't need every piece of project knowledge to become a hard rule.&lt;/p&gt;




&lt;h1&gt;
  
  
  21. Why I Use Kilo Code
&lt;/h1&gt;

&lt;p&gt;My current workflow uses &lt;strong&gt;Kilo Code&lt;/strong&gt; as the coding agent.&lt;/p&gt;

&lt;p&gt;I don't need to run four different coding agents for every Laravel project.&lt;/p&gt;

&lt;p&gt;The important part isn't how many AI tools are involved.&lt;/p&gt;

&lt;p&gt;The important part is whether the AI is working inside a clear engineering environment.&lt;/p&gt;

&lt;p&gt;My basic setup is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Kilo Code
    │
    ├── Inspect project
    │
    ├── Read AGENTS.md
    │
    ├── Load relevant skills
    │
    ├── Plan
    │
    ├── Implement
    │
    ├── Test
    │
    └── Review changes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another developer may prefer another coding agent.&lt;/p&gt;

&lt;p&gt;That's fine.&lt;/p&gt;

&lt;p&gt;The principles remain the same.&lt;/p&gt;




&lt;h1&gt;
  
  
  22. Windows, Linux and WSL
&lt;/h1&gt;

&lt;p&gt;My development environment is not necessarily a traditional Linux workstation.&lt;/p&gt;

&lt;p&gt;I work across:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Windows
   │
   └── WSL2
          │
          ├── Linux
          ├── Laravel
          ├── Git
          └── Kilo Code
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is another reason why project-local instructions are useful.&lt;/p&gt;

&lt;p&gt;The AI shouldn't assume a generic environment.&lt;/p&gt;

&lt;p&gt;If the project has specific commands, paths, services or development procedures, document them.&lt;/p&gt;




&lt;h1&gt;
  
  
  23. Don't Put Secrets in &lt;code&gt;AGENTS.md&lt;/code&gt;
&lt;/h1&gt;

&lt;p&gt;&lt;code&gt;AGENTS.md&lt;/code&gt; belongs in the project.&lt;/p&gt;

&lt;p&gt;That means it may eventually be committed to Git.&lt;/p&gt;

&lt;p&gt;Therefore:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Don't put secrets inside it.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Never store:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;API keys
passwords
tokens
private credentials
production secrets
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead document the expected configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MAIL_USERNAME=&amp;lt;configured through environment&amp;gt;
MAIL_PASSWORD=&amp;lt;configured through environment&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The actual secret belongs in the appropriate secret/configuration mechanism.&lt;/p&gt;




&lt;h1&gt;
  
  
  24. A Practical Project Structure
&lt;/h1&gt;

&lt;p&gt;A simple Laravel project can look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my-laravel-app/
├── AGENTS.md
├── skills.md
├── composer.json
├── artisan
├── app/
├── bootstrap/
├── config/
├── database/
├── public/
├── resources/
├── routes/
├── storage/
└── tests/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important part isn't the number of files.&lt;/p&gt;

&lt;p&gt;It is that the project contains a small, visible place where the AI can learn:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Rules
Knowledge
Code
Tests
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  25. A Real Example: My Kilo Code Configuration
&lt;/h1&gt;

&lt;p&gt;The examples above describe the workflow conceptually.&lt;/p&gt;

&lt;p&gt;If you want to see how I actually structure these files in a working repository, I keep a practical example here:&lt;/p&gt;

&lt;p&gt;GitHub:&lt;br&gt;
&lt;a href="https://github.com/hardyweb/kilo" rel="noopener noreferrer"&gt;https://github.com/hardyweb/kilo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The repository contains the project-level instructions and skills I use with Kilo Code.&lt;/p&gt;

&lt;p&gt;The important part is not to copy the repository blindly.&lt;/p&gt;

&lt;p&gt;Instead, look at how the responsibilities are separated:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kilo/
├── AGENTS.md
│
└── skills/
    └── laravel/
        └── SKILL.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The idea is simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;AGENTS.md
    │
    └── Project-wide engineering rules
             │
             ▼
skills/
    │
    └── Domain-specific knowledge
             │
             ▼
       Coding Agent
             │
             ▼
       Laravel Project
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example, AGENTS.md can define rules such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;inspect before changing code
follow the existing architecture
keep controllers thin
use Form Requests for validation
use policies for authorization
avoid unnecessary abstractions
reuse existing components
test behaviour
don't claim tests passed unless they were actually run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Laravel skill can then contain more detailed Laravel-specific knowledge, procedures, conventions and implementation guidance.&lt;/p&gt;

&lt;p&gt;This separation is useful because not everything needs to become a global rule.&lt;/p&gt;

&lt;h1&gt;
  
  
  26. What If You Want More Than Coding Rules?
&lt;/h1&gt;

&lt;p&gt;This is where another interesting layer comes in.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;AGENTS.md&lt;/code&gt; is useful for defining &lt;strong&gt;how the AI should work&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;skills.md&lt;/code&gt; is useful for giving the AI &lt;strong&gt;knowledge, procedures and examples&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;But long-running projects can have another problem:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;What does the AI need to remember about the project over time?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Architecture decisions.&lt;/p&gt;

&lt;p&gt;Previous work.&lt;/p&gt;

&lt;p&gt;Current project state.&lt;/p&gt;

&lt;p&gt;Session handovers.&lt;/p&gt;

&lt;p&gt;Decisions that were already made.&lt;/p&gt;

&lt;p&gt;Things that should not be repeated.&lt;/p&gt;

&lt;p&gt;This is a different problem from coding rules.&lt;/p&gt;

&lt;p&gt;One project I came across is &lt;strong&gt;Deep State of Mind (DSOM)&lt;/strong&gt;, which approaches this problem as a persistent AI context and governance layer. Its DSOM architecture includes persistent project state, decision/context artifacts, session continuity and a Git-oriented workflow.&lt;/p&gt;

&lt;p&gt;Conceptually, I see the layers like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                    AI Coding Workflow
                           │
          ┌────────────────┼────────────────┐
          │                │                │
          ▼                ▼                ▼
     AGENTS.md         skills.md        DSOM Brain
          │                │                │
       Rules          Knowledge       Project State
     &amp;amp; standards       &amp;amp; examples     &amp;amp; continuity
          │                │                │
          └────────────────┼────────────────┘
                           │
                           ▼
                       Kilo Code
                           │
                           ▼
                    Laravel Project
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The distinction is important:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AGENTS.md
"What rules should the AI follow?"

skills.md
"What knowledge/procedures can help the AI?"

DSOM Brain
"What does the AI need to remember about this project?"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I don't see DSOM Brain as something that replaces &lt;code&gt;AGENTS.md&lt;/code&gt; or &lt;code&gt;skills.md&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Instead, it can &lt;strong&gt;run alongside them&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For a small Laravel project, &lt;code&gt;AGENTS.md&lt;/code&gt; and a small set of skills may already be enough.&lt;/p&gt;

&lt;p&gt;For a long-running project, however, persistent project state and context can become useful.&lt;/p&gt;

&lt;p&gt;That's where &lt;strong&gt;DSOM Brain&lt;/strong&gt; becomes interesting.&lt;/p&gt;

&lt;p&gt;I'm keeping the DSOM Brain implementation out of this article because it deserves its own discussion.&lt;/p&gt;

&lt;p&gt;I'll cover that separately in another article.&lt;/p&gt;

&lt;p&gt;For reference:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://linuxmalaysia.github.io/deep-state-of-mind-for-my-ai/?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;Deep State of Mind (DSOM) For My AI&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  27. The Real Goal
&lt;/h1&gt;

&lt;p&gt;The goal isn't to make AI write more code.&lt;/p&gt;

&lt;p&gt;The goal is to make AI work &lt;strong&gt;inside an engineering system&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;My current thinking is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AGENTS.md
    │
    └── Engineering rules

skills.md
    │
    └── Knowledge and procedures

DSOM Brain
    │
    └── Persistent project context

Kilo Code
    │
    └── Implementation

Git
    │
    └── History and audit trail

Laravel
    │
    └── The actual application
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This changes the relationship with an AI coding agent.&lt;/p&gt;

&lt;p&gt;Instead of:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"AI, build this feature."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The workflow becomes:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Here is the project. Inspect it first. Here are the engineering rules. Here are the relevant skills. Here is the project context. Now implement the feature within the existing architecture."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That is a much more useful way for me to think about AI-assisted Laravel development.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Don't try to teach the AI everything. Define the rules that matter, inspect the existing project first, keep those rules close to the project, and make the AI work within the architecture that already exists.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>laravel</category>
      <category>programming</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Testing Laravel 13 dengan PHP 8.5 dan PHP 8.6 Menggunakan Incus</title>
      <dc:creator>hardyweb</dc:creator>
      <pubDate>Mon, 21 Sep 2026 20:43:44 +0000</pubDate>
      <link>https://dev.to/hardyweb/testing-laravel-13-dengan-php-85-dan-php-86-menggunakan-incus-26np</link>
      <guid>https://dev.to/hardyweb/testing-laravel-13-dengan-php-85-dan-php-86-menggunakan-incus-26np</guid>
      <description>&lt;p&gt;Dalam proses pembangunan sistem yang mengikuti kitaran SDLC, seperti KRISA, pengujian bukan hanya dilakukan pada penghujung pembangunan. Pengujian perlu dilaksanakan secara berterusan bagi memastikan sistem yang dibangunkan kekal serasi dengan perubahan pada persekitaran teknikalnya.&lt;/p&gt;

&lt;p&gt;Salah satu perkara yang boleh diuji ialah keserasian antara interpreter atau runtime yang digunakan dengan software framework yang dibangunkan. Dalam konteks aplikasi Laravel, contohnya, kita boleh menguji aplikasi yang sama menggunakan versi PHP yang lebih baharu untuk melihat sama ada terdapat perubahan pada dependency, extension, API atau tingkah laku runtime yang memberi kesan kepada sistem.&lt;/p&gt;

&lt;p&gt;Pendekatan ini membolehkan kita mengesan isu keserasian lebih awal dalam kitaran pembangunan, bukannya hanya selepas sesuatu versi PHP mula digunakan di production.&lt;/p&gt;

&lt;p&gt;Dalam nota ini, Incus digunakan untuk menyediakan environment PHP yang berbeza supaya aplikasi Laravel yang sama boleh diuji secara berulang terhadap beberapa versi PHP.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;WSL
└── Incus
    ├── laravel13-php85
    │   └── PHP 8.5
    │
    └── laravel13-php86
        └── PHP 8.6
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tujuannya bukan untuk menjalankan dua project yang berbeza, tetapi untuk menguji &lt;strong&gt;codebase dan dependency yang sama&lt;/strong&gt; pada runtime PHP yang berbeza.&lt;/p&gt;




&lt;h2&gt;
  
  
  Prinsip penting: gunakan &lt;code&gt;composer.lock&lt;/code&gt; yang sama
&lt;/h2&gt;

&lt;p&gt;Untuk compatibility testing, kita mahu kedua-dua environment menggunakan dependency yang sama.&lt;/p&gt;

&lt;p&gt;Jadi jangan terus buat:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer update
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;dalam setiap container.&lt;/p&gt;

&lt;p&gt;Sebaliknya gunakan:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;composer install&lt;/code&gt; akan menggunakan &lt;code&gt;composer.lock&lt;/code&gt; yang sedia ada.&lt;/p&gt;

&lt;p&gt;Contohnya:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                composer.lock
                     │
             ┌───────┴───────┐
             ▼               ▼
          PHP 8.5          PHP 8.6
             │               │
          test #1          test #2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dengan cara ini, perbezaan yang kita lihat lebih tertumpu kepada PHP runtime, bukan kerana Composer memilih versi dependency yang berbeza.&lt;/p&gt;




&lt;h1&gt;
  
  
  Flow 1 — Bind Mount
&lt;/h1&gt;

&lt;p&gt;Ini ialah flow yang paling mudah untuk development dan testing harian.&lt;/p&gt;

&lt;p&gt;Source code kekal di WSL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/home/hardy/projects/laravel13
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Kemudian directory tersebut di-mount ke kedua-dua container.&lt;/p&gt;

&lt;p&gt;Contoh:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;incus config device add laravel13-php85 app disk &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nb"&gt;source&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/home/hardy/projects/laravel13 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nv"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/var/www/html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dan:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;incus config device add laravel13-php86 app disk &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nb"&gt;source&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/home/hardy/projects/laravel13 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nv"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/var/www/html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sekarang kedua-dua container melihat source code yang sama.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;WSL
└── projects/
    └── laravel13/
        ├── app/
        ├── config/
        ├── routes/
        ├── composer.json
        └── composer.lock
             │
             ├──────────────► PHP 8.5 container
             │
             └──────────────► PHP 8.6 container
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Install dependency
&lt;/h2&gt;

&lt;p&gt;Masuk ke container PHP 8.5:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;incus &lt;span class="nb"&gt;exec &lt;/span&gt;laravel13-php85 &lt;span class="nt"&gt;--&lt;/span&gt; bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Kemudian:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /var/www/html

php &lt;span class="nt"&gt;-v&lt;/span&gt;
composer &lt;span class="nb"&gt;install
&lt;/span&gt;composer check-platform-reqs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run test:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Kemudian ulangi pada PHP 8.6:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;incus &lt;span class="nb"&gt;exec &lt;/span&gt;laravel13-php86 &lt;span class="nt"&gt;--&lt;/span&gt; bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /var/www/html

php &lt;span class="nt"&gt;-v&lt;/span&gt;
composer &lt;span class="nb"&gt;install
&lt;/span&gt;composer check-platform-reqs
php artisan &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  Perkara yang perlu diperhatikan dengan bind mount
&lt;/h1&gt;

&lt;p&gt;Bind mount sangat convenient, tetapi filesystem host dan container menjadi agak coupled.&lt;/p&gt;

&lt;p&gt;Antara masalah yang mungkin muncul ialah UID/GID dan permission.&lt;/p&gt;

&lt;p&gt;Dalam sesetengah setup Incus, kita mungkin menggunakan:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;shift&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;pada disk device.&lt;/p&gt;

&lt;p&gt;Contohnya:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;incus config device &lt;span class="nb"&gt;set &lt;/span&gt;laravel13-php85 app &lt;span class="nb"&gt;shift&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tetapi ini bukan sesuatu yang perlu dijadikan default untuk flow kita.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;shift=true&lt;/code&gt; boleh mempengaruhi bagaimana ownership file dipersembahkan antara host dan container. Untuk development workflow, kita lebih baik kekalkan setup mount yang simple dan hanya tackle UID/GID apabila memang diperlukan.&lt;/p&gt;

&lt;p&gt;Jika selesai testing dan sebelum kembali kepada workflow biasa, kita boleh set:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;incus config device &lt;span class="nb"&gt;set &lt;/span&gt;laravel13-php85 app &lt;span class="nb"&gt;shift&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false
&lt;/span&gt;incus config device &lt;span class="nb"&gt;set &lt;/span&gt;laravel13-php86 app &lt;span class="nb"&gt;shift&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  Flow 2 — Rsync atau Git
&lt;/h1&gt;

&lt;p&gt;Untuk environment yang lebih clean, kita boleh elakkan bind mount.&lt;/p&gt;

&lt;p&gt;Sebaliknya, source code disalin ke dalam filesystem container.&lt;/p&gt;

&lt;p&gt;Contohnya menggunakan &lt;code&gt;rsync&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;WSL source
    │
    │ rsync
    ▼
Incus container
    │
    └── /var/www/html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Contoh:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rsync &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;--delete&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--exclude&lt;/span&gt; vendor &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--exclude&lt;/span&gt; node_modules &lt;span class="se"&gt;\&lt;/span&gt;
    ./ /path/to/container/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Atau kita boleh gunakan Git:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone &amp;lt;repository&amp;gt; /var/www/html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Kemudian:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /var/www/html
composer &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Penting: &lt;code&gt;composer.lock&lt;/code&gt; masih digunakan
&lt;/h2&gt;

&lt;p&gt;Rsync atau Git &lt;strong&gt;tidak bermaksud Composer akan ignore &lt;code&gt;composer.lock&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Selagi file ini ada:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;composer.json
composer.lock
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;dan kita menjalankan:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Composer akan menggunakan &lt;code&gt;composer.lock&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Apa yang fresh ialah directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;vendor/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Contohnya:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Source repository
│
├── composer.json
├── composer.lock
├── app/
├── routes/
└── ...
        │
        │ rsync / git
        ▼
Container
│
├── composer.json
├── composer.lock
├── app/
├── routes/
└── ...
        │
        │ composer install
        ▼
    vendor/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Jadi kita masih mendapat dependency versions yang sama.&lt;/p&gt;




&lt;h1&gt;
  
  
  Kenapa Flow 2 lebih clean?
&lt;/h1&gt;

&lt;p&gt;Dengan Git atau rsync, container mempunyai filesystem sendiri.&lt;/p&gt;

&lt;p&gt;Contohnya:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;laravel13-php85
└── /var/www/html
    ├── app
    ├── config
    ├── composer.json
    ├── composer.lock
    └── vendor

laravel13-php86
└── /var/www/html
    ├── app
    ├── config
    ├── composer.json
    ├── composer.lock
    └── vendor
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Setiap environment mempunyai &lt;code&gt;vendor/&lt;/code&gt; sendiri.&lt;/p&gt;

&lt;p&gt;Ini lebih dekat dengan situasi:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CI/CD&lt;/li&gt;
&lt;li&gt;staging&lt;/li&gt;
&lt;li&gt;deployment&lt;/li&gt;
&lt;li&gt;production build&lt;/li&gt;
&lt;li&gt;compatibility testing yang isolated&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cuma workflow menjadi sedikit lebih lambat kerana setiap perubahan source perlu di-sync atau checkout semula.&lt;/p&gt;




&lt;h1&gt;
  
  
  Mana satu digunakan?
&lt;/h1&gt;

&lt;p&gt;Untuk kerja harian, saya akan gunakan &lt;strong&gt;Flow 1 — bind mount&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Sebabnya mudah:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Edit code
   ↓
WSL
   ↓
Container nampak perubahan terus
   ↓
Run test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ia sangat sesuai untuk exploratory testing.&lt;/p&gt;

&lt;p&gt;Manakala Flow 2 lebih sesuai apabila kita mahu memastikan environment betul-betul isolated:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Git/Rsync
   ↓
Container
   ↓
composer install
   ↓
Test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  Checklist compatibility test
&lt;/h1&gt;

&lt;p&gt;Untuk setiap versi PHP:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php &lt;span class="nt"&gt;-v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Kemudian:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Semak platform requirements:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer check-platform-reqs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run Laravel test:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Jika mahu periksa dependency yang menghalang PHP tertentu:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer why-not php 8.6
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Untuk melihat apa yang akan berubah tanpa benar-benar update:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer update &lt;span class="nt"&gt;--dry-run&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tetapi command ini digunakan untuk &lt;strong&gt;mengkaji dependency resolution&lt;/strong&gt;, bukan baseline compatibility test.&lt;/p&gt;




&lt;h1&gt;
  
  
  Contoh workflow
&lt;/h1&gt;

&lt;p&gt;Katakan kita sedang berada pada PHP 8.5.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;incus &lt;span class="nb"&gt;exec &lt;/span&gt;laravel13-php85 &lt;span class="nt"&gt;--&lt;/span&gt; bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /var/www/html

php &lt;span class="nt"&gt;-v&lt;/span&gt;
composer &lt;span class="nb"&gt;install
&lt;/span&gt;composer check-platform-reqs
php artisan &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Kemudian test PHP 8.6:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;incus &lt;span class="nb"&gt;exec &lt;/span&gt;laravel13-php86 &lt;span class="nt"&gt;--&lt;/span&gt; bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /var/www/html

php &lt;span class="nt"&gt;-v&lt;/span&gt;
composer &lt;span class="nb"&gt;install
&lt;/span&gt;composer check-platform-reqs
php artisan &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hasilnya boleh dibandingkan:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Laravel 13
│
├── PHP 8.5
│   ├── composer install    ✓
│   ├── platform reqs       ✓
│   └── tests               ✓
│
└── PHP 8.6
    ├── composer install    ✓
    ├── platform reqs       ✓
    └── tests               ✓
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Jika PHP 8.6 gagal, kita boleh isolate puncanya:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PHP runtime?
    │
    ├── Extension missing?
    │
    ├── Platform requirement?
    │
    ├── Composer dependency?
    │
    └── Application/test failure?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Contohnya, error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Class "Normalizer" not found
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;boleh menunjukkan PHP &lt;code&gt;intl&lt;/code&gt; extension belum tersedia.&lt;/p&gt;

&lt;p&gt;Check:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php &lt;span class="nt"&gt;-m&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; intl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dan:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'var_dump(class_exists("Normalizer"));'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  Kesimpulan
&lt;/h1&gt;

&lt;p&gt;Incus sesuai digunakan untuk membuat compatibility matrix yang kecil tanpa perlu Docker atau VM penuh.&lt;/p&gt;

&lt;p&gt;Untuk development/testing cepat:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Bind mount
    ↓
PHP 8.5 / PHP 8.6
    ↓
composer install
    ↓
composer check-platform-reqs
    ↓
php artisan test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Untuk environment yang lebih isolated:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Git / rsync
    ↓
Container filesystem
    ↓
composer install
    ↓
php artisan test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Perkara paling penting ialah &lt;strong&gt;jangan ubah dependency set ketika membandingkan PHP versions&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Gunakan:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;dengan &lt;code&gt;composer.lock&lt;/code&gt; yang sama.&lt;/p&gt;

&lt;p&gt;Dengan itu kita boleh membezakan dengan lebih jelas sama ada sesuatu masalah datang daripada &lt;strong&gt;PHP version&lt;/strong&gt;, &lt;strong&gt;PHP extension&lt;/strong&gt;, &lt;strong&gt;dependency&lt;/strong&gt;, atau memang daripada application code itu sendiri.&lt;/p&gt;

</description>
      <category>incus</category>
      <category>laravel</category>
      <category>php</category>
      <category>testing</category>
    </item>
    <item>
      <title>Incus Lab: Belajar Rangkaian Dengan Cara Mencuba</title>
      <dc:creator>hardyweb</dc:creator>
      <pubDate>Fri, 18 Sep 2026 13:30:59 +0000</pubDate>
      <link>https://dev.to/hardyweb/incus-lab-belajar-rangkaian-dengan-cara-mencuba-5fla</link>
      <guid>https://dev.to/hardyweb/incus-lab-belajar-rangkaian-dengan-cara-mencuba-5fla</guid>
      <description>&lt;p&gt;Belajar tentang rangkaian kadang-kadang agak sukar apabila semuanya hanya diterangkan melalui rajah, nota dan teori.&lt;/p&gt;

&lt;p&gt;Apa sebenarnya berlaku apabila kita melakukan ping?&lt;/p&gt;

&lt;p&gt;Kenapa satu port boleh dibuka tetapi port yang lain tidak?&lt;/p&gt;

&lt;p&gt;Bagaimana nmap mengenal pasti perkhidmatan yang sedang berjalan? Dan apabila kita menggunakan dig, dari mana sebenarnya maklumat DNS itu datang?&lt;/p&gt;

&lt;p&gt;Incus Lab dibangunkan sebagai satu ruang kecil untuk pelajar mencuba dan melihat sendiri perkara-perkara tersebut.&lt;/p&gt;

&lt;p&gt;Incus Lab menggunakan Incus, iaitu platform untuk menjalankan system container dan virtual machine. Dalam projek ini, beberapa container Linux digunakan sebagai persekitaran latihan rangkaian.&lt;/p&gt;

&lt;p&gt;Konsepnya mudah.&lt;/p&gt;

&lt;p&gt;Pelajar tidak perlu membayangkan bahawa terdapat sebuah server di sebelah sana atau sebuah network di belakang sesuatu rajah. Sebaliknya, mereka boleh melihat dan berinteraksi dengan persekitaran tersebut secara langsung.&lt;/p&gt;

&lt;p&gt;Dalam Incus Lab terdapat container seperti lab-scanner dan lab-target. Daripada persekitaran ini, pelajar boleh mencuba beberapa perkara asas seperti:&lt;/p&gt;

&lt;p&gt;ping dan pemeriksaan connectivity&lt;br&gt;
ip addr, ip route dan ip neigh&lt;br&gt;
nmap untuk melihat port dan service&lt;br&gt;
ss, nc dan curl&lt;br&gt;
dig dan nslookup untuk memahami DNS&lt;br&gt;
kemudian berkembang kepada traceroute, packet inspection dan troubleshooting&lt;/p&gt;

&lt;p&gt;Setiap percubaan boleh menjadi satu soalan kecil.&lt;/p&gt;

&lt;p&gt;"Apa yang berlaku kalau port ini ditutup?"&lt;/p&gt;

&lt;p&gt;"Kenapa ping berjaya tetapi sambungan ke port tertentu gagal?"&lt;/p&gt;

&lt;p&gt;"Apa yang sebenarnya berlaku apabila kita membuat DNS lookup?"&lt;/p&gt;

&lt;p&gt;Daripada situ, pelajar boleh melihat hubungan antara arahan yang mereka jalankan dengan keadaan sebenar dalam network.&lt;/p&gt;

&lt;p&gt;Satu lagi perkara yang cuba diketengahkan ialah command yang sebenar. Incus Lab bukan sekadar memaparkan keputusan akhir. Command yang dijalankan turut boleh dilihat melalui command log, supaya pelajar boleh menghubungkan apa yang mereka klik pada antaramuka dengan arahan Linux yang berlaku di belakangnya.&lt;/p&gt;

&lt;p&gt;Pendekatan ini diharapkan dapat menjadikan pembelajaran lebih dekat dengan pengalaman sebenar seorang system atau network engineer.&lt;/p&gt;

&lt;p&gt;Tidak perlu bermula dengan memahami semuanya.&lt;/p&gt;

&lt;p&gt;Cuba satu command.&lt;/p&gt;

&lt;p&gt;Lihat hasilnya.&lt;/p&gt;

&lt;p&gt;Buat perubahan kecil.&lt;/p&gt;

&lt;p&gt;Cuba lagi.&lt;/p&gt;

&lt;p&gt;Kemudian mula bertanya "kenapa?"&lt;/p&gt;

&lt;p&gt;Itulah idea ringkas di sebalik Incus Lab — menyediakan ruang yang selamat untuk belajar network melalui percubaan, pemerhatian dan sedikit rasa ingin tahu.&lt;/p&gt;

&lt;p&gt;Projek ini masih berkembang. Beberapa topik seperti routing, packet inspection dan troubleshooting dirancang untuk ditambah secara berperingkat.&lt;/p&gt;

&lt;p&gt;Jika anda seorang pelajar IT dan ingin mencuba, projek ini boleh dilihat di GitHub:&lt;/p&gt;

&lt;p&gt;github.com/hardyweb/incus-lab&lt;/p&gt;

&lt;p&gt;Mungkin daripada satu ping yang ringkas, kita mula nampak bahawa network sebenarnya mempunyai banyak cerita di sebaliknya.&lt;/p&gt;

</description>
      <category>network</category>
      <category>operation</category>
      <category>ping</category>
      <category>curl</category>
    </item>
    <item>
      <title>Nginx Load Balancing with DNS-Based Service Discovery on Incus</title>
      <dc:creator>hardyweb</dc:creator>
      <pubDate>Sun, 30 Aug 2026 06:31:30 +0000</pubDate>
      <link>https://dev.to/hardyweb/nginx-load-balancing-with-dns-based-service-discovery-on-incus-2kom</link>
      <guid>https://dev.to/hardyweb/nginx-load-balancing-with-dns-based-service-discovery-on-incus-2kom</guid>
      <description>&lt;h1&gt;
  
  
  Nginx Load Balancing with DNS-Based Service Discovery on Incus
&lt;/h1&gt;

&lt;p&gt;Hari ini saya buat satu practical lab untuk memahami &lt;strong&gt;Nginx Load Balancing&lt;/strong&gt;, &lt;strong&gt;DNS-based Service Discovery&lt;/strong&gt;, dan &lt;strong&gt;operational logging&lt;/strong&gt; dalam persekitaran self-hosted menggunakan Incus.&lt;/p&gt;

&lt;p&gt;Lab ini bermula dengan architecture yang simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Client
   │
   ▼
Nginx LB
   │
   ├──► web01
   └──► web02
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Kemudian saya tambah satu DNS server supaya backend tidak perlu bergantung sepenuhnya kepada hard-coded IP address.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Architecture
&lt;/h2&gt;

&lt;p&gt;Final architecture:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                         DNS
                    dns / dnsmasq
                    10.107.109.18
                         ▲
                         │
                  DNS lookup:
                   web.incus
                         │
                         │
                    Nginx LB
                   10.107.109.69
                         │
                  Load Balancing
              ┌──────────┼──────────┐
              ▼          ▼          ▼
            web01      web02      web03
            .100        .253        .xxx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ada dua jenis communication flow dalam architecture ini.&lt;/p&gt;

&lt;h3&gt;
  
  
  DNS resolution
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Nginx LB ──────► DNS
                  │
                  └── web.incus
                       ↓
                  .100, .253, .xxx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;DNS hanya digunakan untuk mengetahui IP address backend.&lt;/p&gt;

&lt;h3&gt;
  
  
  HTTP traffic
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Client
  │
  ▼
Nginx LB
  │
  ├────► web01
  ├────► web02
  └────► web03
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;DNS &lt;strong&gt;tidak membawa HTTP traffic&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;DNS hanya menjawab:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Where is &lt;code&gt;web.incus&lt;/code&gt;?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Nginx kemudian menggunakan IP yang diperoleh daripada DNS untuk melakukan load balancing.&lt;/p&gt;




&lt;h1&gt;
  
  
  2. Static / Hard-Coded Upstream
&lt;/h1&gt;

&lt;p&gt;Cara paling mudah untuk configure Nginx Load Balancer ialah dengan meletakkan IP backend secara terus.&lt;/p&gt;

&lt;p&gt;Contoh:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;upstream&lt;/span&gt; &lt;span class="s"&gt;backend&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="mf"&gt;10.107&lt;/span&gt;&lt;span class="s"&gt;.109.100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="mf"&gt;10.107&lt;/span&gt;&lt;span class="s"&gt;.109.253&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Architecture:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Nginx LB
   │
   ├──► 10.107.109.100
   │
   └──► 10.107.109.253
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Kelebihan
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Simple&lt;/li&gt;
&lt;li&gt;Mudah difahami&lt;/li&gt;
&lt;li&gt;Predictable&lt;/li&gt;
&lt;li&gt;Sesuai untuk environment kecil&lt;/li&gt;
&lt;li&gt;Tidak memerlukan DNS service discovery&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Kekurangan
&lt;/h3&gt;

&lt;p&gt;Kalau tambah &lt;code&gt;web03&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;web01
web02
web03
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nginx configuration perlu diubah:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;upstream&lt;/span&gt; &lt;span class="s"&gt;backend&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="mf"&gt;10.107&lt;/span&gt;&lt;span class="s"&gt;.109.100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="mf"&gt;10.107&lt;/span&gt;&lt;span class="s"&gt;.109.253&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="mf"&gt;10.107&lt;/span&gt;&lt;span class="s"&gt;.109.xxx&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Kemudian configuration perlu divalidasi dan biasanya Nginx perlu di-reload.&lt;/p&gt;




&lt;h1&gt;
  
  
  3. DNS-Based Service Discovery
&lt;/h1&gt;

&lt;p&gt;Pendekatan kedua ialah menggunakan hostname sebagai service identity.&lt;/p&gt;

&lt;p&gt;Contohnya:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;web.incus
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;DNS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;web.incus
 ├── 10.107.109.100
 ├── 10.107.109.253
 └── 10.107.109.xxx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nginx tidak perlu mengetahui backend IP secara hard-coded.&lt;/p&gt;

&lt;p&gt;Contoh:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;resolver&lt;/span&gt; &lt;span class="mf"&gt;10.107&lt;/span&gt;&lt;span class="s"&gt;.109.18&lt;/span&gt; &lt;span class="s"&gt;valid=5s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;upstream&lt;/span&gt; &lt;span class="s"&gt;backend&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;zone&lt;/span&gt; &lt;span class="s"&gt;backend&lt;/span&gt; &lt;span class="mi"&gt;64k&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="s"&gt;web.incus&lt;/span&gt; &lt;span class="s"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Konsepnya:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;             DNS
              │
              │ web.incus
              ▼
         ┌─────────────┐
         │  Nginx LB   │
         └──────┬──────┘
                │
       ┌────────┼────────┐
       ▼        ▼        ▼
     web01    web02    web03
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  4. Why Use DNS?
&lt;/h1&gt;

&lt;p&gt;DNS memberikan abstraction layer antara Load Balancer dan backend server.&lt;/p&gt;

&lt;p&gt;Tanpa DNS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Nginx
  │
  ├── 10.107.109.100
  ├── 10.107.109.253
  └── 10.107.109.xxx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dengan DNS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Nginx
  │
  └── web.incus
         │
         ├── .100
         ├── .253
         └── .xxx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ini bermaksud &lt;strong&gt;service identity&lt;/strong&gt; dipisahkan daripada &lt;strong&gt;server identity&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Contohnya, kalau &lt;code&gt;web01&lt;/code&gt; mendapat IP baru:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;web.incus
    ↓
10.107.109.200
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nginx tidak perlu mempunyai IP tersebut secara hard-coded.&lt;/p&gt;

&lt;p&gt;DNS menjadi source of information mengenai lokasi service.&lt;/p&gt;




&lt;h1&gt;
  
  
  5. dnsmasq
&lt;/h1&gt;

&lt;p&gt;Dalam lab ini saya menggunakan &lt;code&gt;dnsmasq&lt;/code&gt; sebagai DNS service.&lt;/p&gt;

&lt;p&gt;DNS server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;10.107.109.18
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nginx LB menggunakan DNS tersebut:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;resolver&lt;/span&gt; &lt;span class="mf"&gt;10.107&lt;/span&gt;&lt;span class="s"&gt;.109.18&lt;/span&gt; &lt;span class="s"&gt;valid=5s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Test DNS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dig @10.107.109.18 web.incus
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Contoh result:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;web.incus.    0    IN    A    10.107.109.100
web.incus.    0    IN    A    10.107.109.253
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Apabila &lt;code&gt;web03&lt;/code&gt; ditambah:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;web.incus.    0    IN    A    10.107.109.100
web.incus.    0    IN    A    10.107.109.253
web.incus.    0    IN    A    10.107.109.xxx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  6. Dynamic DNS Resolution in Nginx
&lt;/h1&gt;

&lt;p&gt;Bahagian penting dalam configuration ialah:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;resolver&lt;/span&gt; &lt;span class="mf"&gt;10.107&lt;/span&gt;&lt;span class="s"&gt;.109.18&lt;/span&gt; &lt;span class="s"&gt;valid=5s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;dan:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="s"&gt;web.incus&lt;/span&gt; &lt;span class="s"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;resolver&lt;/code&gt; memberitahu Nginx DNS server yang perlu digunakan.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;valid=5s&lt;/code&gt; menentukan tempoh DNS result dianggap valid oleh Nginx.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;resolve&lt;/code&gt; membolehkan Nginx resolve hostname backend secara dynamic.&lt;/p&gt;

&lt;p&gt;Konsep:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DNS changes
     │
     ▼
web.incus
     │
     ▼
Nginx re-resolves
     │
     ▼
Backend pool updated
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ini lebih flexible berbanding hard-coded IP.&lt;/p&gt;




&lt;h1&gt;
  
  
  7. Adding a New Backend
&lt;/h1&gt;

&lt;p&gt;Salah satu test penting ialah menambah &lt;code&gt;web03&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Sebelum:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;web.incus
 ├── web01
 └── web02
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Selepas:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;web.incus
 ├── web01
 ├── web02
 └── web03
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yang menarik ialah Nginx configuration tidak perlu ditukar untuk menambah backend baru.&lt;/p&gt;

&lt;p&gt;DNS yang berubah.&lt;/p&gt;

&lt;p&gt;Kemudian Nginx akan mendapatkan DNS information yang baru berdasarkan konfigurasi &lt;code&gt;resolver&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Ini menunjukkan salah satu kelebihan utama DNS-based service discovery.&lt;/p&gt;




&lt;h1&gt;
  
  
  8. Important Lesson: DNS Discovery Is Not Health Checking
&lt;/h1&gt;

&lt;p&gt;Satu perkara yang saya belajar ialah:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;DNS Service Discovery ≠ Health Checking&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;DNS memberitahu:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;web.incus
    ↓
IP addresses
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tetapi DNS tidak semestinya tahu sama ada HTTP service pada IP tersebut sedang berfungsi.&lt;/p&gt;

&lt;p&gt;Contohnya:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;web.incus
 ├── web01 ✅
 ├── web02 ❌
 └── web03 ✅
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;DNS mungkin masih return:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.100
.253
.xxx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;walaupun &lt;code&gt;web02&lt;/code&gt; tidak boleh menerima HTTP connection.&lt;/p&gt;

&lt;p&gt;Oleh itu, production architecture mungkin memerlukan additional health-checking atau failure-handling mechanism.&lt;/p&gt;




&lt;h1&gt;
  
  
  9. Load Balancing vs High Availability
&lt;/h1&gt;

&lt;p&gt;Saya juga belajar bahawa &lt;strong&gt;Load Balancing dan High Availability bukan perkara yang sama&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Load Balancing
&lt;/h3&gt;

&lt;p&gt;Tujuan:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Client
  │
  ▼
Nginx LB
 ├──► web01
 ├──► web02
 └──► web03
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ia mengagihkan traffic.&lt;/p&gt;

&lt;h3&gt;
  
  
  High Availability
&lt;/h3&gt;

&lt;p&gt;Tujuan:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;           LB / HA
          /       \
       LB01      LB02
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ia memastikan service masih tersedia jika salah satu infrastructure component gagal.&lt;/p&gt;

&lt;p&gt;Contohnya, Keepalived boleh digunakan untuk menyediakan virtual IP dan failover antara Load Balancer.&lt;/p&gt;

&lt;p&gt;Jadi:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Load Balancing
    ≠
High Availability
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tetapi kedua-duanya boleh digunakan bersama.&lt;/p&gt;




&lt;h1&gt;
  
  
  10. Nginx Operational Logging
&lt;/h1&gt;

&lt;p&gt;Selepas Load Balancing berfungsi, saya tambah logging untuk melihat backend mana yang menerima request.&lt;/p&gt;

&lt;p&gt;Contoh log format:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;log_format&lt;/span&gt; &lt;span class="s"&gt;lb&lt;/span&gt; &lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="nv"&gt;$remote_addr&lt;/span&gt; &lt;span class="s"&gt;-&lt;/span&gt; &lt;span class="nv"&gt;$host&lt;/span&gt; &lt;span class="s"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$time_local&lt;/span&gt;&lt;span class="s"&gt;]&lt;/span&gt; &lt;span class="s"&gt;'&lt;/span&gt;
              &lt;span class="s"&gt;'"&lt;/span&gt;&lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt; &lt;span class="nv"&gt;$status&lt;/span&gt; &lt;span class="nv"&gt;$body_bytes_sent&lt;/span&gt; &lt;span class="s"&gt;'&lt;/span&gt;
              &lt;span class="s"&gt;'upstream=&lt;/span&gt;&lt;span class="nv"&gt;$upstream_addr&lt;/span&gt; &lt;span class="s"&gt;'&lt;/span&gt;
              &lt;span class="s"&gt;'upstream_status=&lt;/span&gt;&lt;span class="nv"&gt;$upstream_status&lt;/span&gt; &lt;span class="s"&gt;'&lt;/span&gt;
              &lt;span class="s"&gt;'request_time=&lt;/span&gt;&lt;span class="nv"&gt;$request_time&lt;/span&gt; &lt;span class="s"&gt;'&lt;/span&gt;
              &lt;span class="s"&gt;'upstream_response_time=&lt;/span&gt;&lt;span class="nv"&gt;$upstream_response_time&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Kemudian:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;access_log&lt;/span&gt; &lt;span class="n"&gt;/var/log/nginx/lb_access.log&lt;/span&gt; &lt;span class="s"&gt;lb&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Log boleh mengandungi:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;upstream=10.107.109.100:80
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;atau:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;upstream=10.107.109.253:80
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;atau:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;upstream=10.107.109.xxx:80
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ini memberikan visibility kepada Load Balancer behaviour.&lt;/p&gt;




&lt;h1&gt;
  
  
  11. Testing
&lt;/h1&gt;

&lt;h3&gt;
  
  
  Test DNS
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dig @10.107.109.18 web.incus
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Test backend
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;--noproxy&lt;/span&gt; &lt;span class="s1"&gt;'*'&lt;/span&gt; http://10.107.109.100/
curl &lt;span class="nt"&gt;--noproxy&lt;/span&gt; &lt;span class="s1"&gt;'*'&lt;/span&gt; http://10.107.109.253/
curl &lt;span class="nt"&gt;--noproxy&lt;/span&gt; &lt;span class="s1"&gt;'*'&lt;/span&gt; http://10.107.109.xxx/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Test Nginx configuration
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nginx &lt;span class="nt"&gt;-t&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Inspect effective configuration
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nginx &lt;span class="nt"&gt;-T&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Test Load Balancer
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;--noproxy&lt;/span&gt; &lt;span class="s1"&gt;'*'&lt;/span&gt; http://10.107.109.69/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Watch Load Balancer logs
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; /var/log/nginx/lb_access.log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  12. Troubleshooting Lesson
&lt;/h1&gt;

&lt;p&gt;Satu masalah yang berlaku dalam lab ialah default Nginx configuration masih aktif.&lt;/p&gt;

&lt;p&gt;Contohnya:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/etc/nginx/conf.d/default.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Configuration tersebut menyebabkan Nginx default welcome page dipaparkan.&lt;/p&gt;

&lt;p&gt;Walaupun Load Balancer configuration telah dibuat dengan betul, request masih boleh masuk ke default server.&lt;/p&gt;

&lt;p&gt;Penyelesaian ialah memastikan hanya configuration yang diperlukan digunakan.&lt;/p&gt;

&lt;p&gt;Ini mengajar satu perkara penting:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Jangan hanya melihat configuration file yang kita edit. Periksa &lt;strong&gt;effective configuration&lt;/strong&gt; yang sebenarnya digunakan oleh Nginx.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Command yang berguna:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nginx &lt;span class="nt"&gt;-T&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Kemudian:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nginx &lt;span class="nt"&gt;-t&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;sebelum reload.&lt;/p&gt;




&lt;h1&gt;
  
  
  13. Configuration Validation Workflow
&lt;/h1&gt;

&lt;p&gt;Workflow yang saya gunakan:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Edit Configuration
       │
       ▼
    nginx -t
       │
       ▼
   Configuration OK?
      /       \
    NO         YES
    │           │
    ▼           ▼
 Fix config   Reload
                │
                ▼
             Test
                │
                ▼
              Logs
                │
                ▼
            Verify
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ini lebih baik daripada terus restart service setiap kali membuat perubahan.&lt;/p&gt;




&lt;h1&gt;
  
  
  14. Security Perspective
&lt;/h1&gt;

&lt;p&gt;Walaupun lab ini fokus kepada Load Balancing, terdapat beberapa security principles yang boleh dipelajari.&lt;/p&gt;

&lt;h3&gt;
  
  
  Configuration Management
&lt;/h3&gt;

&lt;p&gt;Configuration perlu:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;dikenal pasti&lt;/li&gt;
&lt;li&gt;diubah secara terkawal&lt;/li&gt;
&lt;li&gt;divalidasi&lt;/li&gt;
&lt;li&gt;diuji&lt;/li&gt;
&lt;li&gt;didokumentasikan&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Network Security
&lt;/h3&gt;

&lt;p&gt;Perlu memahami:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Client
  ↓
Load Balancer
  ↓
Backend network
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;dan service mana yang boleh berkomunikasi antara satu sama lain.&lt;/p&gt;

&lt;h3&gt;
  
  
  Logging
&lt;/h3&gt;

&lt;p&gt;Load Balancer logs membantu:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;troubleshooting&lt;/li&gt;
&lt;li&gt;monitoring&lt;/li&gt;
&lt;li&gt;incident investigation&lt;/li&gt;
&lt;li&gt;performance analysis&lt;/li&gt;
&lt;li&gt;verification&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Availability
&lt;/h3&gt;

&lt;p&gt;Multiple backend servers boleh mengurangkan dependency kepada single server.&lt;/p&gt;




&lt;h1&gt;
  
  
  15. ISO/IEC 27001 Perspective
&lt;/h1&gt;

&lt;p&gt;Lab ini bukan implementation penuh ISO/IEC 27001.&lt;/p&gt;

&lt;p&gt;Sebaliknya, ISO/IEC 27001 digunakan sebagai reference framework untuk memahami bagaimana technical infrastructure berkait dengan information security.&lt;/p&gt;

&lt;p&gt;Beberapa control yang relevan untuk pembelajaran:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Control&lt;/th&gt;
&lt;th&gt;Relevance&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;A.8.9 Configuration Management&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Nginx, DNS dan network configuration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;A.8.15 Logging&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Nginx Load Balancer logs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;A.8.16 Monitoring Activities&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Monitoring behaviour dan troubleshooting&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;A.8.20 Networks Security&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Network architecture dan communication&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;A.8.21 Security of Network Services&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;DNS, HTTP dan Load Balancing services&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;A.8.32 Change Management&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Controlled configuration changes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;A.5.30 ICT Readiness for Business Continuity&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Redundancy dan availability concepts&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Penting untuk difahami bahawa control mapping sahaja tidak bermaksud sesuatu environment itu compliant.&lt;/p&gt;

&lt;p&gt;Dalam audit sebenar, auditor masih memerlukan:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Risk
 ↓
Control
 ↓
Implementation
 ↓
Evidence
 ↓
Monitoring
 ↓
Review
 ↓
Improvement
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  16. Key Lessons
&lt;/h1&gt;

&lt;p&gt;Antara perkara utama yang saya pelajari:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Load Balancing dan High Availability adalah dua fungsi yang berbeza.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Nginx boleh digunakan sebagai HTTP Load Balancer.&lt;/li&gt;
&lt;li&gt;Backend boleh dirujuk menggunakan IP secara static.&lt;/li&gt;
&lt;li&gt;Backend juga boleh ditemui menggunakan DNS-based service discovery.&lt;/li&gt;
&lt;li&gt;DNS memberikan abstraction layer antara service dan server IP.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;resolver&lt;/code&gt; dan &lt;code&gt;resolve&lt;/code&gt; membolehkan Nginx menggunakan dynamic DNS resolution.&lt;/li&gt;
&lt;li&gt;DNS discovery tidak sama dengan health checking.&lt;/li&gt;
&lt;li&gt;Logging penting untuk visibility dan troubleshooting.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nginx -T&lt;/code&gt; sangat berguna untuk melihat effective configuration.&lt;/li&gt;
&lt;li&gt;Configuration changes perlu divalidasi sebelum reload.&lt;/li&gt;
&lt;li&gt;Redundancy pada backend membantu meningkatkan availability.&lt;/li&gt;
&lt;li&gt;Technical implementation boleh dianalisis menggunakan perspektif ISO/IEC 27001 tanpa mendakwa bahawa lab tersebut sendiri merupakan ISMS.&lt;/li&gt;
&lt;/ol&gt;




&lt;h1&gt;
  
  
  17. Final Architecture
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                         DNS
                    dns / dnsmasq
                    10.107.109.18
                         ▲
                         │
                  DNS lookup
                   web.incus
                         │
                         │
                    Nginx LB
                   10.107.109.69
                         │
                  Load Balancing
              ┌──────────┼──────────┐
              ▼          ▼          ▼
            web01      web02      web03
            .100        .253        .xxx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The key concept is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DNS = Service Discovery

Nginx = Load Balancer

Web01/Web02/Web03 = Backend Services

Nginx Logs = Operational Visibility
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;The practical exercise demonstrated two fundamental approaches to Nginx Load Balancing.&lt;/p&gt;

&lt;p&gt;The first approach uses &lt;strong&gt;static IP addresses&lt;/strong&gt;, which is simple and suitable for small, stable environments.&lt;/p&gt;

&lt;p&gt;The second approach uses &lt;strong&gt;DNS-based service discovery&lt;/strong&gt;, where Nginx resolves a service name such as &lt;code&gt;web.incus&lt;/code&gt; to determine the backend servers.&lt;/p&gt;

&lt;p&gt;The second approach introduces additional flexibility but also introduces dependencies on DNS availability, DNS caching, TTL behaviour and backend health handling.&lt;/p&gt;

&lt;p&gt;The most important lesson is that infrastructure components should not be viewed independently. &lt;strong&gt;DNS, Load Balancing, networking, configuration management, logging, availability and security all interact with each other.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;From an ISO/IEC 27001 perspective, the exercise demonstrates how technical controls can be understood through the broader cycle of &lt;strong&gt;risk, control, implementation, evidence, monitoring and continual improvement&lt;/strong&gt;.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>devops</category>
      <category>infrastructure</category>
      <category>networking</category>
    </item>
    <item>
      <title>Building a PDF from Markdown with Pandoc: Images, Code Blocks, TOC and Mermaid</title>
      <dc:creator>hardyweb</dc:creator>
      <pubDate>Wed, 19 Aug 2026 05:45:12 +0000</pubDate>
      <link>https://dev.to/hardyweb/building-a-pdf-from-markdown-with-pandoc-images-code-blocks-toc-and-mermaid-5f8j</link>
      <guid>https://dev.to/hardyweb/building-a-pdf-from-markdown-with-pandoc-images-code-blocks-toc-and-mermaid-5f8j</guid>
      <description>&lt;p&gt;Pandoc is one of those tools that looks simple at first:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pandoc input.md &lt;span class="nt"&gt;-o&lt;/span&gt; output.pdf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But when Markdown becomes a real document, things become more interesting.&lt;/p&gt;

&lt;p&gt;Images may disappear, long shell commands can overflow the page, Mermaid diagrams need additional processing, and the generated table of contents may contain sections that we do not want.&lt;/p&gt;

&lt;p&gt;This note documents the practical techniques for building a clean PDF from Markdown using Pandoc.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Example Project Structure
&lt;/h2&gt;

&lt;p&gt;Let's use a fictional project called &lt;strong&gt;Internal API Deployment Guide&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The directory structure is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docs/
├── assets/
│   ├── architecture.png
│   └── logo.png
├── chapters/
│   ├── introduction.md
│   ├── installation.md
│   └── deployment.md
└── main.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important point is that image paths are relative to the Markdown file or the working directory used by Pandoc.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="p"&gt;![&lt;/span&gt;&lt;span class="nv"&gt;System Architecture&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;assets/architecture.png&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the image is located elsewhere:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docs/
├── assets/
│   └── architecture.png
└── chapters/
    └── deployment.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;then the path from &lt;code&gt;deployment.md&lt;/code&gt; would be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="p"&gt;![&lt;/span&gt;&lt;span class="nv"&gt;System Architecture&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;../assets/architecture.png&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  2. Cover Image
&lt;/h2&gt;

&lt;p&gt;A cover image can simply be inserted using Markdown:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="p"&gt;![&lt;/span&gt;&lt;span class="nv"&gt;Cover&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;assets/logo.png&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, if the intention is to create a proper PDF title page, it is often cleaner to use YAML metadata and a dedicated LaTeX template.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Internal&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;API&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Deployment&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Guide"&lt;/span&gt;
&lt;span class="na"&gt;author&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Example&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Engineering&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Team"&lt;/span&gt;
&lt;span class="na"&gt;date&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2026"&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pandoc main.md &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--pdf-engine&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;xelatex &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-o&lt;/span&gt; deployment-guide.pdf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important lesson is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Pandoc does not treat a Markdown image as a special "cover page". It is simply an image in the document flow.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you need a dedicated cover page, control the layout using LaTeX/template mechanisms.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Image Paths
&lt;/h2&gt;

&lt;p&gt;One common problem is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Image not found
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or the image simply does not appear in the PDF.&lt;/p&gt;

&lt;p&gt;Consider:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;project/
├── main.md
└── assets/
    └── architecture.png
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Markdown should use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="p"&gt;![&lt;/span&gt;&lt;span class="nv"&gt;Architecture&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;assets/architecture.png&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then run Pandoc from the &lt;code&gt;project&lt;/code&gt; directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pandoc main.md &lt;span class="nt"&gt;-o&lt;/span&gt; output.pdf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A useful debugging technique is to verify the file first:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-lh&lt;/span&gt; assets/architecture.png
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then test Pandoc:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pandoc main.md &lt;span class="nt"&gt;-o&lt;/span&gt; test.pdf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the image still does not appear, check the actual working directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Relative paths are one of the easiest things to overlook when working with Pandoc.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Table of Contents
&lt;/h2&gt;

&lt;p&gt;Pandoc can automatically generate a table of contents:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pandoc main.md &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--toc&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-o&lt;/span&gt; output.pdf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The heading levels included in the TOC can be controlled:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pandoc main.md &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--toc&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--toc-depth&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-o&lt;/span&gt; output.pdf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# Deployment Guide&lt;/span&gt;

&lt;span class="gu"&gt;## Installing Dependencies&lt;/span&gt;

&lt;span class="gu"&gt;### Installing PHP&lt;/span&gt;

&lt;span class="gu"&gt;### Installing Composer&lt;/span&gt;

&lt;span class="gu"&gt;## Configuring Nginx&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nt"&gt;--toc-depth&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the TOC will contain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Deployment Guide
  Installing Dependencies
  Configuring Nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;but not:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Installing PHP
Installing Composer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is useful for keeping a technical PDF readable.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Removing Unwanted Sections from the TOC
&lt;/h2&gt;

&lt;p&gt;Sometimes the document contains front matter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# Front Matter&lt;/span&gt;

&lt;span class="gu"&gt;## Title Page&lt;/span&gt;

&lt;span class="gu"&gt;## Copyright&lt;/span&gt;

&lt;span class="gu"&gt;## Disclaimer&lt;/span&gt;

&lt;span class="gh"&gt;# Chapter 1&lt;/span&gt;

&lt;span class="gu"&gt;## Installation&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You may not want every front-matter section appearing in the TOC.&lt;/p&gt;

&lt;p&gt;One approach is to control the heading hierarchy carefully.&lt;/p&gt;

&lt;p&gt;For example, instead of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# Front Matter&lt;/span&gt;

&lt;span class="gu"&gt;## Title Page&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;use a custom LaTeX structure or unnumbered headings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# Title Page {.unnumbered}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# Copyright {.unnumbered}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Depending on the output format and template, this can prevent unwanted numbering and help keep the document structure clean.&lt;/p&gt;




&lt;h2&gt;
  
  
  6. Code Blocks
&lt;/h2&gt;

&lt;p&gt;Pandoc handles fenced code blocks naturally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="p"&gt;```&lt;/span&gt;&lt;span class="nl"&gt;bash
&lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart nginx
&lt;span class="p"&gt;```&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Language identifiers are useful:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="p"&gt;```&lt;/span&gt;&lt;span class="nl"&gt;php
&lt;/span&gt;&lt;span class="nc"&gt;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/health'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'status'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'ok'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;```&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pandoc can then pass the code through syntax highlighting when configured.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pandoc main.md &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--highlight-style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;tango &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-o&lt;/span&gt; output.pdf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  7. The Long Bash Command Problem
&lt;/h2&gt;

&lt;p&gt;Technical documentation often contains commands such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--name&lt;/span&gt; production-api &lt;span class="nt"&gt;--restart&lt;/span&gt; unless-stopped &lt;span class="nt"&gt;-p&lt;/span&gt; 8080:8080 &lt;span class="nt"&gt;-v&lt;/span&gt; /opt/application/config:/app/config:ro &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;APP_ENV&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;production example/api-server:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The problem is that this line may be wider than the printable area of an A4 page.&lt;/p&gt;

&lt;p&gt;LaTeX may produce an overfull line.&lt;/p&gt;

&lt;p&gt;A better solution is to format the command over multiple lines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; production-api &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--restart&lt;/span&gt; unless-stopped &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-p&lt;/span&gt; 8080:8080 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-v&lt;/span&gt; /opt/application/config:/app/config:ro &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;APP_ENV&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;production &lt;span class="se"&gt;\&lt;/span&gt;
  example/api-server:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is not only better for PDF generation.&lt;/p&gt;

&lt;p&gt;It is also easier for humans to read.&lt;/p&gt;




&lt;h2&gt;
  
  
  8. Long Inline Commands
&lt;/h2&gt;

&lt;p&gt;Inline code can also cause problems:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;Run &lt;span class="sb"&gt;`docker run --name production-api --restart unless-stopped -p 8080:8080 example/api-server:latest`&lt;/span&gt;.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For short commands this is fine.&lt;/p&gt;

&lt;p&gt;For long commands, use a fenced block instead:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="p"&gt;```&lt;/span&gt;&lt;span class="nl"&gt;bash
&lt;/span&gt;docker run &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; production-api &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--restart&lt;/span&gt; unless-stopped &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-p&lt;/span&gt; 8080:8080 &lt;span class="se"&gt;\&lt;/span&gt;
  example/api-server:latest
&lt;span class="p"&gt;```&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A useful documentation rule is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If a command is difficult to read in Markdown, it will probably be even worse in PDF.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  9. Mermaid Diagrams
&lt;/h2&gt;

&lt;p&gt;Pandoc does not natively turn every Mermaid code block into a rendered diagram.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="p"&gt;```&lt;/span&gt;&lt;span class="nl"&gt;mermaid
&lt;/span&gt;&lt;span class="sb"&gt;flowchart TB
    Client --&amp;gt; API
    API --&amp;gt; Database&lt;/span&gt;
&lt;span class="p"&gt;```&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Markdown parser can understand the fenced block, but a PDF engine such as XeLaTeX does not automatically know how to render Mermaid.&lt;/p&gt;

&lt;p&gt;A common solution is to convert Mermaid separately.&lt;/p&gt;

&lt;p&gt;Create:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;architecture.mmd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flowchart TB
    Client --&amp;gt; API
    API --&amp;gt; Database
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then generate an image:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mmdc &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-i&lt;/span&gt; architecture.mmd &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-o&lt;/span&gt; architecture.png
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now include the generated image:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="p"&gt;![&lt;/span&gt;&lt;span class="nv"&gt;System Architecture&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;assets/architecture.png&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This separates diagram generation from PDF generation.&lt;/p&gt;




&lt;h2&gt;
  
  
  10. Mermaid Workflow
&lt;/h2&gt;

&lt;p&gt;A practical workflow is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Mermaid source
      |
      v
   mmdc
      |
      v
 PNG / SVG
      |
      v
   Markdown
      |
      v
   Pandoc
      |
      v
    PDF
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mmdc &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-i&lt;/span&gt; assets/architecture.mmd &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-o&lt;/span&gt; assets/architecture.png
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pandoc main.md &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--toc&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--pdf-engine&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;xelatex &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-o&lt;/span&gt; output.pdf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This approach is easier to troubleshoot than trying to make every component work inside one command.&lt;/p&gt;




&lt;h2&gt;
  
  
  11. PNG vs SVG
&lt;/h2&gt;

&lt;p&gt;Mermaid can generate both PNG and SVG.&lt;/p&gt;

&lt;p&gt;PNG:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mmdc &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-i&lt;/span&gt; architecture.mmd &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-o&lt;/span&gt; architecture.png
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;SVG:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mmdc &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-i&lt;/span&gt; architecture.mmd &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-o&lt;/span&gt; architecture.svg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;SVG is useful because it is vector-based.&lt;/p&gt;

&lt;p&gt;However, the complete toolchain matters.&lt;/p&gt;

&lt;p&gt;If SVG rendering causes problems in the LaTeX/PDF pipeline, PNG is often the simpler solution.&lt;/p&gt;

&lt;p&gt;For technical documentation, a good starting point is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Mermaid → PNG → Pandoc → XeLaTeX → PDF
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once the pipeline is stable, SVG can be introduced if higher-quality vector diagrams are required.&lt;/p&gt;




&lt;h2&gt;
  
  
  12. Using XeLaTeX
&lt;/h2&gt;

&lt;p&gt;For modern technical documents, XeLaTeX is a useful PDF engine.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pandoc main.md &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--pdf-engine&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;xelatex &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-o&lt;/span&gt; output.pdf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It provides better control over fonts and Unicode than some older LaTeX workflows.&lt;/p&gt;

&lt;p&gt;You can specify a main font:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pandoc main.md &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--pdf-engine&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;xelatex &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-V&lt;/span&gt; &lt;span class="nv"&gt;mainfont&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"DejaVu Serif"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-o&lt;/span&gt; output.pdf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nt"&gt;-V&lt;/span&gt; &lt;span class="nv"&gt;monofont&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"DejaVu Sans Mono"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  13. Unicode Problems
&lt;/h2&gt;

&lt;p&gt;Technical documentation often contains symbols such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;✓
→
⚠
✅
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the selected font does not contain these glyphs, XeLaTeX may display warnings such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Missing character
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[WARNING] Missing character: There is no ✅
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The problem is usually not Pandoc itself.&lt;/p&gt;

&lt;p&gt;It is a font coverage problem.&lt;/p&gt;

&lt;p&gt;One solution is to use a font with better Unicode coverage.&lt;/p&gt;

&lt;p&gt;Another is to avoid unnecessary emoji in PDF source documents.&lt;/p&gt;

&lt;p&gt;For technical books, simple ASCII characters are often safer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[OK]
[WARNING]
[ERROR]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;instead of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;✅
⚠️
❌
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  14. A Simple Build Command
&lt;/h2&gt;

&lt;p&gt;Once the document is ready, a simple build command might be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pandoc main.md &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--toc&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--toc-depth&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--pdf-engine&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;xelatex &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--highlight-style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;tango &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-o&lt;/span&gt; output.pdf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives us:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Markdown input&lt;/li&gt;
&lt;li&gt;automatic TOC&lt;/li&gt;
&lt;li&gt;maximum TOC depth of 2&lt;/li&gt;
&lt;li&gt;XeLaTeX PDF generation&lt;/li&gt;
&lt;li&gt;syntax-highlighted code&lt;/li&gt;
&lt;li&gt;PDF output&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  15. Separate the Build Process
&lt;/h2&gt;

&lt;p&gt;Instead of remembering a long command, create a script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/usr/bin/env bash&lt;/span&gt;

&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt;

pandoc main.md &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--toc&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--toc-depth&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--pdf-engine&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;xelatex &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--highlight-style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;tango &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-o&lt;/span&gt; output.pdf

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"PDF generated: output.pdf"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save it as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;build.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chmod&lt;/span&gt; +x build.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./build.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This makes the document reproducible.&lt;/p&gt;




&lt;h2&gt;
  
  
  16. A Better Project Layout
&lt;/h2&gt;

&lt;p&gt;For a larger documentation project, a structure like this works well:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;documentation/
├── assets/
│   ├── architecture.png
│   ├── database.png
│   └── logo.png
├── diagrams/
│   ├── architecture.mmd
│   └── database.mmd
├── chapters/
│   ├── introduction.md
│   ├── installation.md
│   └── deployment.md
├── main.md
├── build.sh
└── output/
    └── documentation.pdf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The responsibilities are clear:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chapters/   → Markdown content
diagrams/   → Mermaid source
assets/     → generated/static images
main.md     → document entry point
build.sh    → reproducible build
output/     → generated PDF
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  17. The Important Lesson
&lt;/h2&gt;

&lt;p&gt;Pandoc itself is only one part of the pipeline.&lt;/p&gt;

&lt;p&gt;A real Markdown-to-PDF workflow can look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Markdown
   |
   +---- Images
   |
   +---- Code
   |
   +---- Mermaid
   |
   v
Pandoc
   |
   v
XeLaTeX
   |
   v
PDF
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When something goes wrong, debug the pipeline one component at a time.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Image missing
    ↓
Check Markdown path

Mermaid missing
    ↓
Check Mermaid conversion

Unicode warning
    ↓
Check font

Code overflowing page
    ↓
Reformat long command

TOC incorrect
    ↓
Check heading hierarchy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This mindset is much more useful than trying random Pandoc options.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Pandoc is powerful because Markdown can remain the source of truth while the final document can be generated in different formats.&lt;/p&gt;

&lt;p&gt;For a reliable technical-documentation workflow, keep the pipeline simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Markdown
    ↓
Pandoc
    ↓
XeLaTeX
    ↓
PDF
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And treat external content such as Mermaid diagrams as separate build inputs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Mermaid
    ↓
PNG/SVG
    ↓
Markdown
    ↓
Pandoc
    ↓
PDF
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The key is not finding one giant Pandoc command.&lt;/p&gt;

&lt;p&gt;The key is building a &lt;strong&gt;reproducible document pipeline that is easy to debug&lt;/strong&gt;.&lt;/p&gt;

</description>
      <category>pandoc</category>
      <category>mermaid</category>
      <category>pdf</category>
    </item>
    <item>
      <title>Run Simple Web Server On The Spot</title>
      <dc:creator>hardyweb</dc:creator>
      <pubDate>Sun, 02 Aug 2026 07:19:19 +0000</pubDate>
      <link>https://dev.to/hardyweb/run-simple-server-on-the-spot-3eji</link>
      <guid>https://dev.to/hardyweb/run-simple-server-on-the-spot-3eji</guid>
      <description>&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;PHP php &lt;span class="nt"&gt;-S&lt;/span&gt; localhost:8000

PHP &lt;span class="o"&gt;(&lt;/span&gt;public&lt;span class="o"&gt;)&lt;/span&gt;    php &lt;span class="nt"&gt;-S&lt;/span&gt; localhost:8000 &lt;span class="nt"&gt;-t&lt;/span&gt; public

Python  python3 &lt;span class="nt"&gt;-m&lt;/span&gt; http.server 8000

Node    npx serve &lt;span class="nt"&gt;-p&lt;/span&gt; 8000

BusyBox busybox httpd &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 8000

Ruby    ruby &lt;span class="nt"&gt;-run&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; httpd &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 8000

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>node</category>
      <category>php</category>
      <category>python</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Panduan Teknikal: Compile llama.cpp di Debian 12/13 dan Cross Compile ARM64</title>
      <dc:creator>hardyweb</dc:creator>
      <pubDate>Tue, 14 Jul 2026 07:52:24 +0000</pubDate>
      <link>https://dev.to/hardyweb/panduan-teknikal-compile-llamacpp-di-debian-1213-dan-cross-compile-arm64-1pj3</link>
      <guid>https://dev.to/hardyweb/panduan-teknikal-compile-llamacpp-di-debian-1213-dan-cross-compile-arm64-1pj3</guid>
      <description>&lt;p&gt;&lt;strong&gt;1. Pengenalan&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;llama.cpp ialah runtime inference LLM berasaskan C/C++ yang popular kerana ringan, pantas, dan sesuai untuk menjalankan model GGUF secara local. Ia boleh digunakan pada:&lt;/p&gt;

&lt;p&gt;Server x86_64&lt;br&gt;
Workstation Linux&lt;br&gt;
Mini PC&lt;br&gt;
Raspberry Pi&lt;br&gt;
Orange Pi&lt;br&gt;
SBC ARM64&lt;br&gt;
Container Linux&lt;/p&gt;

&lt;p&gt;Dalam deployment sebenar, terdapat dua pendekatan utama:&lt;/p&gt;

&lt;p&gt;Native build&lt;br&gt;
Compile terus pada mesin yang akan menjalankan llama.cpp.&lt;br&gt;
Cross compile&lt;br&gt;
Compile pada mesin lebih laju (contohnya PC x86_64), tetapi menghasilkan binary untuk platform lain (contohnya ARM64 Orange Pi).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bahagian 1 — Persediaan Debian 12/13&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;1.1 Install dependency asas&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update

&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    git &lt;span class="se"&gt;\&lt;/span&gt;
    build-essential &lt;span class="se"&gt;\&lt;/span&gt;
    cmake &lt;span class="se"&gt;\&lt;/span&gt;
    ninja-build &lt;span class="se"&gt;\&lt;/span&gt;
    pkg-config
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Komponen utama:&lt;/p&gt;

&lt;p&gt;Package Fungsi&lt;br&gt;
git Ambil source code&lt;br&gt;
build-essential GCC, G++, make&lt;br&gt;
cmake   Build configuration&lt;br&gt;
ninja-build Build engine lebih pantas&lt;br&gt;
pkg-config  Cari library dependency&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bahagian 2 — Clone llama.cpp&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/ggml-org/llama.cpp.git

&lt;span class="nb"&gt;cd &lt;/span&gt;llama.cpp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Semak versi:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git log &lt;span class="nt"&gt;-1&lt;/span&gt; &lt;span class="nt"&gt;--oneline&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Bahagian 3 — Compile Native (Mesin Sama)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Contoh:&lt;/p&gt;

&lt;p&gt;Debian 12/13 x86_64&lt;br&gt;
Debian ARM64&lt;br&gt;
Orange Pi&lt;br&gt;
Raspberry Pi&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3.1 Configure CMake&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Build menggunakan Ninja:

cmake &lt;span class="nt"&gt;-B&lt;/span&gt; build &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-G&lt;/span&gt; Ninja &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-DCMAKE_BUILD_TYPE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Release
3.2 Compile
ninja &lt;span class="nt"&gt;-C&lt;/span&gt; build &lt;span class="nt"&gt;-j&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;nproc&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;atau:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;cmake --build build
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
plaintext&lt;br&gt;
&lt;strong&gt;3.3 Hasil build&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Semak:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ls build/bin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
plaintext&lt;br&gt;
Contoh:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;llama-cli
llama-server
llama-bench
llama-perplexity
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
shell&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bahagian 4 — Enable OpenBLAS (Pilihan)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;OpenBLAS boleh membantu operasi matrix CPU.&lt;/p&gt;

&lt;p&gt;Install:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt install libopenblas-dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
cmake&lt;br&gt;
Build:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cmake -B build \
    -G Ninja \
    -DCMAKE_BUILD_TYPE=Release \
    -DGGML_BLAS=ON \
    -DGGML_BLAS_VENDOR=OpenBLAS
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
shell&lt;br&gt;
Kemudian:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ninja &lt;span class="nt"&gt;-C&lt;/span&gt; build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nota Penting: CMake Cache&lt;/p&gt;

&lt;p&gt;Jika pernah configure dengan:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nt"&gt;-DGGML_BLAS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ON
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;kemudian buang option tersebut, CMake masih menyimpan konfigurasi lama.&lt;/p&gt;

&lt;p&gt;Contoh masalah:&lt;/p&gt;

&lt;p&gt;BLAS not found&lt;br&gt;
missing: BLAS_LIBRARIES&lt;/p&gt;

&lt;p&gt;Penyelesaian:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Kemudian configure semula.&lt;/p&gt;

&lt;p&gt;Sentiasa ingat:&lt;/p&gt;

&lt;p&gt;CMakeCache.txt menyimpan konfigurasi lama.&lt;br&gt;
&lt;strong&gt;Bahagian 5 — Cross Compile x86_64 → ARM64&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Contoh:&lt;/p&gt;

&lt;p&gt;PC Debian 12 x86_64&lt;br&gt;
        |&lt;br&gt;
        |&lt;br&gt;
        v&lt;br&gt;
Orange Pi ARM64&lt;/p&gt;

&lt;p&gt;Kelebihan:&lt;/p&gt;

&lt;p&gt;Compile lebih cepat&lt;br&gt;
Tidak membebankan SBC&lt;br&gt;
Sesuai untuk production image&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5.1 Install ARM64 cross compiler&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    gcc-12-aarch64-linux--gnu&lt;span class="se"&gt;\&lt;/span&gt;
    g++-12-aarch64-linux-gnu
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    gcc-13-aarch64-linux--gnu&lt;span class="se"&gt;\&lt;/span&gt;
    g++-13-aarch64-linux-gnu
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Semak:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aarch64-linux-gnu-gcc &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;5.2 Configure cross build&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Bersihkan dahulu:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; build-arm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Kemudian:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cmake"&gt;&lt;code&gt;cmake -B build-arm \
    -G Ninja \
    -DCMAKE_BUILD_TYPE=Release \
    -DCMAKE_SYSTEM_NAME=Linux \
    -DCMAKE_SYSTEM_PROCESSOR=aarch64 \
    -DCMAKE_C_COMPILER=aarch64-linux-gnu-gcc \
    -DCMAKE_CXX_COMPILER=aarch64-linux-gnu-g++
5.3 Compile
ninja -C build-arm -j$&lt;span class="p"&gt;(&lt;/span&gt;nproc&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hasil:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ls &lt;/span&gt;build-arm/bin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Bahagian 6 — Semak Architecture Binary&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Gunakan:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;file build-arm/bin/llama-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Contoh output berjaya:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ELF 64-bit LSB pie executable,
ARM aarch64,
dynamically linked
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Maksud:&lt;/p&gt;

&lt;p&gt;Output  Maksud&lt;br&gt;
ELF 64-bit  Binary 64-bit&lt;br&gt;
ARM aarch64 Untuk ARM64&lt;br&gt;
dynamically linked  Perlukan shared library&lt;br&gt;
PIE executable  Linux security hardening&lt;br&gt;
Bahagian 7 — Semak Dependency .so&lt;br&gt;
Jangan guna ldd untuk cross binary&lt;/p&gt;

&lt;p&gt;Jika compile ARM64 tetapi check pada PC x86:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ldd llama-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;boleh gagal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;not a dynamic executable
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sebab:&lt;/p&gt;

&lt;p&gt;PC:&lt;/p&gt;

&lt;p&gt;x86_64 loader&lt;/p&gt;

&lt;p&gt;Binary:&lt;/p&gt;

&lt;p&gt;ARM64 loader&lt;br&gt;
Gunakan readelf&lt;br&gt;
aarch64-linux-gnu-readelf \&lt;br&gt;
-d build-arm/bin/llama-server | grep NEEDED&lt;/p&gt;

&lt;p&gt;Contoh:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Shared library: [libllama.so]
Shared library: [libggml.so]
Shared library: [libstdc++.so.6]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cari semua .so&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;find build-arm &lt;span class="nt"&gt;-name&lt;/span&gt; &lt;span class="s2"&gt;"*.so"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Contoh:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;libllama.so
libggml.so
libggml-base.so
libggml-cpu.so
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Semak architecture:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;file build-arm/bin/&lt;span class="k"&gt;*&lt;/span&gt;.so
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ARM aarch64
Bahagian 8 — Dynamic vs Static Binary
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Semak:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;file llama-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Contoh dynamic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dynamically linked
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Perlu:&lt;/p&gt;

&lt;p&gt;lib*.so&lt;/p&gt;

&lt;p&gt;Contoh static:&lt;/p&gt;

&lt;p&gt;statically linked&lt;/p&gt;

&lt;p&gt;Tidak perlu .so.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bahagian 9 — Installation ke Linux&lt;/strong&gt;&lt;br&gt;
Pilihan standard&lt;/p&gt;

&lt;p&gt;Binary:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/usr/local/bin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Library:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/usr/local/lib
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Contoh:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo cp &lt;/span&gt;llama-server /usr/local/bin/
&lt;span class="nb"&gt;sudo cp &lt;/span&gt;llama-cli /usr/local/bin/

&lt;span class="nb"&gt;sudo cp&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt;.so /usr/local/lib/

&lt;span class="nb"&gt;sudo &lt;/span&gt;ldconfig
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pilihan appliance / embedded&lt;/p&gt;

&lt;p&gt;Untuk SBC:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/opt/llama.cpp/

    llama-server
    llama-cli
    libllama.so
    libggml.so
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Kemudian:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;LD_LIBRARY_PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/opt/llama.cpp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sesuai untuk:&lt;/p&gt;

&lt;p&gt;Orange Pi&lt;br&gt;
kiosk AI&lt;br&gt;
edge inference node&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bahagian 10 — Deploy ke Orange Pi&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Copy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;scp build-arm/bin/llama-server &lt;span class="se"&gt;\&lt;/span&gt;
orangepi:/usr/local/bin/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;scp build-arm/bin/llama-cli &lt;span class="se"&gt;\&lt;/span&gt;
orangepi:/usr/local/bin/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Jika perlu:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;scp build-arm/bin/&lt;span class="k"&gt;*&lt;/span&gt;.so &lt;span class="se"&gt;\&lt;/span&gt;
orangepi:/usr/local/lib/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pada Orange Pi:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;ldconfig
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Semak:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;uname&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expected:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aarch64
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Bahagian 11 — Cadangan Production Architecture&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Untuk sistem AI agent:&lt;/p&gt;

&lt;p&gt;+----------------+&lt;br&gt;
| Go Agent       |&lt;br&gt;
| Tool Router    |&lt;br&gt;
+-------+--------+&lt;br&gt;
        |&lt;br&gt;
        |&lt;br&gt;
 HTTP API&lt;br&gt;
        |&lt;br&gt;
        v&lt;br&gt;
+----------------+&lt;br&gt;
| llama-server   |&lt;br&gt;
| llama.cpp      |&lt;br&gt;
+----------------+&lt;br&gt;
        |&lt;br&gt;
        |&lt;br&gt;
      GGUF&lt;br&gt;
      Model&lt;/p&gt;

&lt;p&gt;Kelebihan:&lt;/p&gt;

&lt;p&gt;Go agent tidak perlu embed model&lt;br&gt;
Model boleh tukar tanpa rebuild&lt;br&gt;
llama.cpp boleh upgrade sendiri&lt;br&gt;
Mudah scale ke banyak node&lt;br&gt;
Kesimpulan&lt;/p&gt;

&lt;p&gt;Workflow yang stabil:&lt;/p&gt;

&lt;p&gt;Native&lt;br&gt;
cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Release&lt;/p&gt;

&lt;p&gt;ninja -C build&lt;br&gt;
Cross Compile ARM64&lt;br&gt;
sudo apt install gcc-aarch64-linux-gnu g++-aarch64-linux-gnu&lt;/p&gt;

&lt;p&gt;rm -rf build-arm&lt;/p&gt;

&lt;p&gt;cmake -B build-arm \&lt;br&gt;
-G Ninja \&lt;br&gt;
-DCMAKE_SYSTEM_NAME=Linux \&lt;br&gt;
-DCMAKE_SYSTEM_PROCESSOR=aarch64 \&lt;br&gt;
-DCMAKE_C_COMPILER=aarch64-linux-gnu-gcc \&lt;br&gt;
-DCMAKE_CXX_COMPILER=aarch64-linux-gnu-g++&lt;/p&gt;

&lt;p&gt;ninja -C build-arm&lt;br&gt;
Verification&lt;br&gt;
file llama-server&lt;/p&gt;

&lt;p&gt;aarch64-linux-gnu-readelf -d llama-server | grep NEEDED&lt;/p&gt;

&lt;p&gt;find . -name "*.so"&lt;/p&gt;

&lt;p&gt;Dengan proses ini, satu mesin Debian 12/13 boleh menjadi build server untuk menghasilkan node AI ARM64 seperti Orange Pi, Raspberry Pi, atau edge inference appliance.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>linux</category>
      <category>llm</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Kaedah Saliran Pasif Menggunakan Struktur Sumbu Kapilari Berasaskan Cable Tie</title>
      <dc:creator>hardyweb</dc:creator>
      <pubDate>Tue, 23 Jun 2026 02:56:10 +0000</pubDate>
      <link>https://dev.to/hardyweb/kaedah-saliran-pasif-menggunakan-struktur-sumbu-kapilari-berasaskan-cable-tie-2o7o</link>
      <guid>https://dev.to/hardyweb/kaedah-saliran-pasif-menggunakan-struktur-sumbu-kapilari-berasaskan-cable-tie-2o7o</guid>
      <description>&lt;ol&gt;
&lt;li&gt;Abstrak&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Dokumen ini membentangkan satu mekanisme saliran pasif berskala mikro menggunakan cable tie yang dibentuk sebagai struktur gelung (loop) untuk bertindak sebagai medium sumbu kapilari. Sistem ini membolehkan pemindahan air dari takungan ke saluran keluar melalui gabungan tindakan kapilari, adhesi, kohesi, serta graviti tanpa penggunaan tenaga luaran.&lt;/p&gt;

&lt;p&gt;Kaedah ini sesuai untuk aplikasi DIY, pengurusan air bertakung kecil, serta demonstrasi pendidikan dalam bidang mekanik bendalir.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Latar Belakang Masalah&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Dalam sistem saliran berskala kecil, kegagalan aliran sering berlaku walaupun terdapat perbezaan aras cecair yang sepatutnya mencukupi secara teori. Antara punca utama:&lt;/p&gt;

&lt;p&gt;Pembentukan air lock dalam saluran kecil&lt;br&gt;
Tegangan permukaan menghalang kemasukan awal bendalir&lt;br&gt;
Ketiadaan medium “wetting path” awal untuk memulakan aliran&lt;br&gt;
Ketidakstabilan aliran pada bukaan kecil (intermittent flow)&lt;/p&gt;

&lt;p&gt;Fenomena ini menyebabkan sistem gagal “start flow” walaupun graviti tersedia.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Objektif
Menyediakan mekanisme saliran pasif tanpa tenaga luaran
Mengatasi masalah permulaan aliran (flow initiation problem)
Mengurangkan kesan air lock dan tegangan permukaan
Mewujudkan laluan basah berterusan sebagai pemangkin aliran&lt;/li&gt;
&lt;li&gt;Prinsip Fizik Terlibat
4.1 Graviti&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Mendorong aliran akhir dari kawasan berpotensi tinggi ke rendah.&lt;/p&gt;

&lt;p&gt;4.2 Tekanan Hidrostatik&lt;br&gt;
P=ρgh&lt;/p&gt;

&lt;p&gt;Perbezaan aras cecair menghasilkan tekanan pendorong aliran.&lt;/p&gt;

&lt;p&gt;4.3 Tegangan Permukaan&lt;/p&gt;

&lt;p&gt;Menentang kemasukan air ke dalam bukaan kecil tanpa bantuan awal.&lt;/p&gt;

&lt;p&gt;4.4 Tindakan Kapilari&lt;br&gt;
 h∝r1​&lt;br&gt;
    ​&lt;/p&gt;

&lt;p&gt;Air merambat melalui permukaan kabel berdasarkan interaksi molekul.&lt;/p&gt;

&lt;p&gt;4.5 Adhesi &amp;amp; Kohesi&lt;br&gt;
Adhesi: air melekat pada permukaan cable tie&lt;br&gt;
Kohesi: molekul air mengekalkan kesinambungan aliran&lt;br&gt;
4.6 Interaksi Multi-Fasa&lt;/p&gt;

&lt;p&gt;Peralihan daripada fasa “wetting initiation” → “continuous flow”&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Reka Bentuk Sistem&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Sistem terdiri daripada cable tie yang dibentuk menjadi gelung dan diposisikan merentasi lubang saliran.&lt;/p&gt;

&lt;p&gt;Ciri reka bentuk:&lt;/p&gt;

&lt;p&gt;Gelung separa terendam dalam takungan&lt;br&gt;
Titik sentuhan di kawasan lubang bertindak sebagai “wick transfer point”&lt;br&gt;
Kepala cable tie bertindak sebagai pengunci mekanikal&lt;br&gt;
Skema Konsep&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fafpqihxir5dadvu56w1k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fafpqihxir5dadvu56w1k.png" alt=" " width="800" height="470"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Mekanisme Operasi&lt;br&gt;
Air bersentuhan dengan permukaan cable tie&lt;br&gt;
Molekul air membentuk lapisan awal melalui adhesi&lt;br&gt;
Laluan basah terbentuk sepanjang gelung (capillary propagation)&lt;br&gt;
Air mencapai titik lubang saliran&lt;br&gt;
Graviti mengambil alih dan mengekalkan aliran berterusan&lt;br&gt;
Sistem mencapai keadaan steady-state micro flow&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ciri Sistem&lt;br&gt;
Tanpa tenaga elektrik&lt;br&gt;
Kos hampir sifar&lt;br&gt;
Struktur mudah dan boleh diulang&lt;br&gt;
Boleh dipasang tanpa modifikasi besar sistem asal&lt;br&gt;
Sesuai untuk prototaip pantas (rapid prototyping)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Had Sistem&lt;br&gt;
Aliran rendah (micro-scale throughput)&lt;br&gt;
Sensitif kepada minyak, habuk, dan kontaminasi permukaan&lt;br&gt;
Tidak sesuai untuk volum besar&lt;br&gt;
Prestasi bergantung pada material (surface energy &amp;amp; roughness)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Aplikasi Potensi&lt;br&gt;
Sistem saliran air hujan mikro&lt;br&gt;
Sistem tanaman pasif (hybrid wicking-drainage)&lt;br&gt;
Pengurusan kondensasi (AC / cooling drip control)&lt;br&gt;
Demonstrasi fizik bendalir untuk pendidikan STEM&lt;br&gt;
Prototaip sistem IoT pasif (no-power fluid indicator)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Kesimpulan&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Kaedah ini menunjukkan bahawa sistem saliran mikro tidak bergantung sepenuhnya kepada graviti, tetapi kepada interaksi kompleks antara tegangan permukaan, kapilari, dan sifat bahan.&lt;/p&gt;

&lt;p&gt;Struktur gelung cable tie bertindak sebagai “capillary bridge” yang menstabilkan permulaan aliran, sekaligus mengatasi masalah air lock dalam sistem bukaan kecil.&lt;/p&gt;

</description>
      <category>stem</category>
      <category>fizik</category>
      <category>bendalir</category>
      <category>kejuruteraan</category>
    </item>
  </channel>
</rss>
