<?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: Muhammad Dhiyaul Atha</title>
    <description>The latest articles on DEV Community by Muhammad Dhiyaul Atha (@bangkah).</description>
    <link>https://dev.to/bangkah</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3665512%2Fdc6c5db5-91c9-4887-a5c6-33c8db391e07.jpeg</url>
      <title>DEV Community: Muhammad Dhiyaul Atha</title>
      <link>https://dev.to/bangkah</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bangkah"/>
    <language>en</language>
    <item>
      <title>Step-by-Step Deployment Active Directory (AD DS) pada Windows Server 2025 via PowerShel</title>
      <dc:creator>Muhammad Dhiyaul Atha</dc:creator>
      <pubDate>Fri, 15 May 2026 15:20:57 +0000</pubDate>
      <link>https://dev.to/bangkah/step-by-step-deployment-active-directory-ad-ds-pada-windows-server-2025-via-powershel-2ibb</link>
      <guid>https://dev.to/bangkah/step-by-step-deployment-active-directory-ad-ds-pada-windows-server-2025-via-powershel-2ibb</guid>
      <description>&lt;p&gt;Banyak orang masih menggunakan GUI untuk mengonfigurasi Windows Server. Padahal, menggunakan PowerShell jauh lebih cepat, ringan, dan minim &lt;em&gt;error&lt;/em&gt; navigasi. Di artikel ini, saya akan membagikan alur praktikum saya dalam membangun Forest baru &lt;code&gt;imsak.com&lt;/code&gt; di Windows Server 2025 sepenuhnya menggunakan terminal.&lt;/p&gt;




&lt;h2&gt;
  
  
  Environment Praktikum
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Platform:&lt;/strong&gt; VirtualBox (Internal Network)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OS:&lt;/strong&gt; Windows Server 2025&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Target Domain:&lt;/strong&gt; &lt;code&gt;imsak.com&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Static IP:&lt;/strong&gt; &lt;code&gt;172.20.80.10&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Tahapan Konfigurasi
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Identitas Server (Hostname)
&lt;/h3&gt;

&lt;p&gt;Langkah pertama adalah mengubah nama komputer agar lebih mudah dikenali dalam jaringan forest. Di sini saya mengubahnya menjadi &lt;code&gt;A3N4&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;Rename-Computer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-NewName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"A3N4"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Restart&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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.amazonaws.com%2Fuploads%2Farticles%2F2gc1o8gxb9slu2pddxfw.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.amazonaws.com%2Fuploads%2Farticles%2F2gc1o8gxb9slu2pddxfw.png" alt=" " width="781" height="152"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Networking: Static IP &amp;amp; DNS Loopback
&lt;/h3&gt;

&lt;p&gt;Domain Controller wajib memiliki IP statis. Selain itu, DNS harus diarahkan ke &lt;code&gt;127.0.0.1&lt;/code&gt; (loopback) karena server ini sendiri yang akan mengelola record DNS domain.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Mengatur IP Statis&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;New-NetIPAddress&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-InterfaceIndex&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-IPAddress&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;172.20.80.10&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-PrefixLength&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;24&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-DefaultGateway&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;172.20.80.1&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c"&gt;# Mengatur DNS ke Loopback&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Set-DnsClientServerAddress&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-InterfaceIndex&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-ServerAddresses&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"127.0.0.1"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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.amazonaws.com%2Fuploads%2Farticles%2Fn4wn20ipi6cghtqdw71u.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.amazonaws.com%2Fuploads%2Farticles%2Fn4wn20ipi6cghtqdw71u.png" alt=" " width="781" height="261"&gt;&lt;/a&gt;&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.amazonaws.com%2Fuploads%2Farticles%2Fb7d7jgj8idaws7h6ei28.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.amazonaws.com%2Fuploads%2Farticles%2Fb7d7jgj8idaws7h6ei28.png" alt=" " width="781" height="209"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Instalasi Fitur AD DS
&lt;/h3&gt;

&lt;p&gt;Sebelum bisa mempromosikan server menjadi DC, kita perlu memasang binary dan modul manajemen Active Directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;Install-WindowsFeature&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;AD-Domain-Services&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-IncludeManagementTools&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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.amazonaws.com%2Fuploads%2Farticles%2Fv3h9fwpcjlep8c9qycrz.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.amazonaws.com%2Fuploads%2Farticles%2Fv3h9fwpcjlep8c9qycrz.png" alt=" " width="760" height="89"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Membangun Forest Baru (Promosi Domain)
&lt;/h3&gt;

&lt;p&gt;Ini adalah inti dari praktikum. Kita akan membuat Forest baru bernama &lt;code&gt;imsak.com&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;Install-ADDSForest&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-DomainName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"imsak.com"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-DomainNetbiosName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"IMSAK"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-InstallDns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="bp"&gt;$true&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Force&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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.amazonaws.com%2Fuploads%2Farticles%2Fqp83a992a4c3syyymqp2.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.amazonaws.com%2Fuploads%2Farticles%2Fqp83a992a4c3syyymqp2.png" alt=" " width="777" height="245"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Setelah perintah dijalankan, masukkan **SafeModeAdministratorPassword&lt;/em&gt;* yang kuat. Sistem akan otomatis melakukan restart setelah proses selesai.*&lt;/p&gt;




&lt;h2&gt;
  
  
  Verifikasi &amp;amp; Pengujian
&lt;/h2&gt;

&lt;p&gt;Setelah server aktif kembali, kita perlu memastikan semuanya berjalan normal.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Cek Login Otoritas
&lt;/h3&gt;

&lt;p&gt;Pastikan user yang masuk adalah user domain.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;whoami&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# Output: imsak\administrator&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  6. Resolusi Nama DNS
&lt;/h3&gt;

&lt;p&gt;Tes apakah DNS sudah mengenali domain baru kita.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;Resolve-DnsName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;imsak.com&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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.amazonaws.com%2Fuploads%2Farticles%2Fksyj5um5uhdudfi20h48.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.amazonaws.com%2Fuploads%2Farticles%2Fksyj5um5uhdudfi20h48.png" alt=" " width="683" height="106"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Status Layanan (Health Check)
&lt;/h3&gt;

&lt;p&gt;Memastikan layanan utama AD DS (NTDS, DNS, ADWS) sudah berstatus &lt;code&gt;Running&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;Get-Service&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;adws&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;dns&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;ntds&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Select-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Status&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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.amazonaws.com%2Fuploads%2Farticles%2Fl9bzusi0tsxsoy86jjno.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.amazonaws.com%2Fuploads%2Farticles%2Fl9bzusi0tsxsoy86jjno.png" alt=" " width="800" height="130"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Kesimpulan
&lt;/h2&gt;

&lt;p&gt;Deploy Active Directory di Windows Server 2025 via PowerShell memberikan pengalaman manajemen server yang lebih profesional. Dengan mengikuti alur yang terstruktur, kita bisa meminimalisir kesalahan konfigurasi dan mempercepat proses &lt;em&gt;deployment&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Apakah kamu punya kendala saat mencoba Windows Server 2025? Yuk diskusi di kolom komentar!&lt;/strong&gt; &lt;/p&gt;

</description>
      <category>windowsserver2025</category>
      <category>powershell</category>
      <category>activedirectory</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Implementasi Kea DHCPv4 pada RHEL 10: Solusi Modern Pengelolaan Jaringan</title>
      <dc:creator>Muhammad Dhiyaul Atha</dc:creator>
      <pubDate>Thu, 30 Apr 2026 11:31:39 +0000</pubDate>
      <link>https://dev.to/bangkah/implementasi-kea-dhcpv4-pada-rhel-10-solusi-modern-pengelolaan-jaringan-23o7</link>
      <guid>https://dev.to/bangkah/implementasi-kea-dhcpv4-pada-rhel-10-solusi-modern-pengelolaan-jaringan-23o7</guid>
      <description>&lt;h3&gt;
  
  
  1. Pendahuluan
&lt;/h3&gt;

&lt;p&gt;Kea mulai diadopsi sebagai pengganti ISC DHCP dengan arsitektur yang lebih modern. Kea menawarkan performa lebih tinggi dan struktur konfigurasi berbasis JSON yang lebih modular. Artikel ini mendokumentasikan langkah-langkah konfigurasi Kea di lingkungan virtual (VirtualBox) dengan client Windows 10.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Topologi &amp;amp; Skenario Jaringan
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Server (RHEL 10)&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;  Adapter 1: NAT (Akses Internet)&lt;/li&gt;
&lt;li&gt;  Adapter 2: Internal Network (&lt;code&gt;enp0s8&lt;/code&gt;) - IP Statis: &lt;code&gt;10.0.2.1&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;  &lt;strong&gt;Client (Windows 10)&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;  Adapter 1: Internal Network - DHCP Client&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;h3&gt;
  
  
  3. Konfigurasi Interface Server
&lt;/h3&gt;

&lt;p&gt;Sebelum menjalankan Kea, interface yang mengarah ke client harus memiliki IP statis.&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;# Menambahkan IP statis ke interface internal&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;ip addr add 10.0.2.1/24 dev enp0s8
&lt;span class="nb"&gt;sudo &lt;/span&gt;ip &lt;span class="nb"&gt;link set &lt;/span&gt;enp0s8 up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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.amazonaws.com%2Fuploads%2Farticles%2Fp6r4joipaqmj42y9aewx.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.amazonaws.com%2Fuploads%2Farticles%2Fp6r4joipaqmj42y9aewx.png" alt=" " width="800" height="341"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  4. Konfigurasi Kea DHCPv4
&lt;/h3&gt;

&lt;p&gt;Edit file &lt;code&gt;/etc/kea/kea-dhcp4.conf&lt;/code&gt;. Fokus utama adalah mengarahkan &lt;code&gt;interfaces&lt;/code&gt; ke &lt;code&gt;enp0s8&lt;/code&gt; dan menentukan &lt;code&gt;pools&lt;/code&gt; alamat IP.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"Dhcp4"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"interfaces-config"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"interfaces"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"enp0s8"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"lease-database"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"memfile"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/var/lib/kea/kea-leases4.csv"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"subnet4"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"subnet"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"10.0.2.0/24"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"pools"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"pool"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"10.0.2.100 - 10.0.2.200"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"option-data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"routers"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"10.0.2.1"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"domain-name-servers"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"8.8.8.8, 8.8.4.4"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&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.amazonaws.com%2Fuploads%2Farticles%2Fu7fke9pub51ygaiemt8m.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.amazonaws.com%2Fuploads%2Farticles%2Fu7fke9pub51ygaiemt8m.png" alt=" " width="399" height="397"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  5. Keamanan &amp;amp; Aktivasi Service
&lt;/h3&gt;

&lt;p&gt;Membuka port DHCP pada firewall dan merestart service Kea.&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;# Konfigurasi Firewall&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;firewall-cmd &lt;span class="nt"&gt;--add-service&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;dhcp &lt;span class="nt"&gt;--permanent&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;firewall-cmd &lt;span class="nt"&gt;--reload&lt;/span&gt;

&lt;span class="c"&gt;# Restart Service&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart kea-dhcp4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&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.amazonaws.com%2Fuploads%2Farticles%2Ffqemfvoa4yphodur24pg.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.amazonaws.com%2Fuploads%2Farticles%2Ffqemfvoa4yphodur24pg.png" alt=" " width="800" height="344"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  6. Pengujian pada Client
&lt;/h3&gt;

&lt;p&gt;Pada client Windows 10, lakukan pembaruan IP melalui Command Prompt.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ipconfig /release
ipconfig /renew
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&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.amazonaws.com%2Fuploads%2Farticles%2Fml0ykos897ksoz2h82rh.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.amazonaws.com%2Fuploads%2Farticles%2Fml0ykos897ksoz2h82rh.png" alt=" " width="552" height="224"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  7. Analisis Log &amp;amp; Database Lease
&lt;/h3&gt;

&lt;p&gt;Verifikasi terakhir adalah memeriksa apakah server mencatat penyewaan IP tersebut dalam database lokal.&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;# Melihat log aktivitas DORA secara real-time&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;journalctl &lt;span class="nt"&gt;-u&lt;/span&gt; kea-dhcp4 &lt;span class="nt"&gt;-f&lt;/span&gt;

&lt;span class="c"&gt;# Melihat database penyewaan IP&lt;/span&gt;
&lt;span class="nb"&gt;sudo cat&lt;/span&gt; /var/lib/kea/kea-leases4.csv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&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.amazonaws.com%2Fuploads%2Farticles%2Fg03f0b41kssesisz80ae.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.amazonaws.com%2Fuploads%2Farticles%2Fg03f0b41kssesisz80ae.png" alt=" " width="800" height="69"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  Kesimpulan
&lt;/h3&gt;

&lt;p&gt;Keberhasilan implementasi Kea DHCP sangat bergantung pada ketepatan penentuan interface fisik dan pengaturan IP statis pada sisi server. Dengan berpindah ke Kea, administrator jaringan mendapatkan kontrol lebih baik melalui struktur data JSON yang rapi.&lt;/p&gt;

</description>
      <category>rhel</category>
      <category>dhcp</category>
      <category>linux</category>
      <category>networking</category>
    </item>
    <item>
      <title>Setup Identity Management (FreeIPA) di RHEL 10: Fondasi Infrastruktur Server Terpusat</title>
      <dc:creator>Muhammad Dhiyaul Atha</dc:creator>
      <pubDate>Wed, 29 Apr 2026 15:21:59 +0000</pubDate>
      <link>https://dev.to/bangkah/setup-ad-ds-di-rhel-10-membangun-fondasi-infrastruktur-server-terpusat-598m</link>
      <guid>https://dev.to/bangkah/setup-ad-ds-di-rhel-10-membangun-fondasi-infrastruktur-server-terpusat-598m</guid>
      <description>&lt;p&gt;Di lingkungan enterprise, manajemen identitas terpusat adalah komponen penting untuk menjaga keamanan dan skalabilitas sistem. Jika di ekosistem Windows kita mengenal Active Directory Domain Services (AD DS), maka di dunia Linux tersedia solusi setara yaitu Identity Management (IdM) berbasis FreeIPA.&lt;/p&gt;

&lt;p&gt;Pada artikel ini, saya akan membagikan pengalaman melakukan deployment FreeIPA di RHEL 10, lengkap dengan troubleshooting yang saya temui.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Environment Setup
&lt;/h3&gt;

&lt;p&gt;Untuk tutorial ini, saya menggunakan spesifikasi sistem berikut agar performa &lt;em&gt;Identity Management&lt;/em&gt; tetap stabil:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;OS:&lt;/strong&gt; Red Hat Enterprise Linux 10.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Hardware:&lt;/strong&gt; Laptop dengan Intel i7-14650HX dan RTX 4050.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Network:&lt;/strong&gt; Pastikan sistem menggunakan IP statis.&lt;/li&gt;
&lt;/ul&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.amazonaws.com%2Fuploads%2Farticles%2F8ti5theh6glkzc8wk2w4.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.amazonaws.com%2Fuploads%2Farticles%2F8ti5theh6glkzc8wk2w4.png" alt=" " width="773" height="390"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2. The FQDN Rule: Don't Get Stuck!
&lt;/h3&gt;

&lt;p&gt;Salah satu syarat wajib untuk setup "AD DS" versi Linux ini adalah penggunaan &lt;strong&gt;Fully Qualified Domain Name (FQDN)&lt;/strong&gt;. Installer tidak akan menerima nama tunggal karena sistem identitas seperti Kerberos membutuhkan domain yang lengkap.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Masalah:&lt;/strong&gt; Menggunakan nama seperti &lt;code&gt;atha&lt;/code&gt; akan memicu error &lt;code&gt;must be fully-qualified&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Solusi:&lt;/strong&gt; Set hostname dengan format &lt;code&gt;&amp;lt;hostname&amp;gt;.&amp;lt;domain&amp;gt;&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;hostnamectl set-hostname server.atha.local
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ul&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.amazonaws.com%2Fuploads%2Farticles%2Fjfq7saxtq9agxmj8813t.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.amazonaws.com%2Fuploads%2Farticles%2Fjfq7saxtq9agxmj8813t.png" alt=" " width="600" height="92"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Step-by-Step Installation
&lt;/h3&gt;

&lt;p&gt;Gunakan perintah berikut untuk memulai instalasi server beserta DNS-nya. Saya sangat menyarankan menentukan &lt;em&gt;forwarder&lt;/em&gt; secara eksplisit untuk menghindari masalah resolusi.&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;ipa-server-install &lt;span class="nt"&gt;--setup-dns&lt;/span&gt; &lt;span class="nt"&gt;--forwarder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1.1.1.1 &lt;span class="nt"&gt;--forwarder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1.0.0.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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.amazonaws.com%2Fuploads%2Farticles%2F9wrt4jmqpc7377zs217s.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.amazonaws.com%2Fuploads%2Farticles%2F9wrt4jmqpc7377zs217s.png" alt=" " width="800" height="292"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tips Tambahan:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;NetBIOS:&lt;/strong&gt; Default-nya adalah &lt;code&gt;ATHA&lt;/code&gt;, ini berguna untuk integrasi dengan sistem Windows.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;NTP:&lt;/strong&gt; Biarkan menggunakan pool bawaan sistem kecuali Anda memiliki server waktu khusus.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Troubleshooting: Belajar dari Kesalahan
&lt;/h3&gt;

&lt;p&gt;Selama proses &lt;em&gt;sharing&lt;/em&gt; ini, ada beberapa kendala yang sempat saya alami dan bisa menjadi pelajaran buat teman-teman:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;DNS Timeout:&lt;/strong&gt; Jika installer gagal saat validasi &lt;em&gt;forwarder&lt;/em&gt;, biasanya ada masalah pada kueri IPv6 di jaringan Anda. Menggunakan flag &lt;code&gt;--forwarder&lt;/code&gt; manual adalah solusinya.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;The "yes" Confirmation:&lt;/strong&gt; Jangan terkecoh di akhir ringkasan konfigurasi. Sistem menunggu input &lt;strong&gt;&lt;code&gt;yes&lt;/code&gt;&lt;/strong&gt; secara eksplisit. Jika hanya ditekan Enter, instalasi akan otomatis batal (&lt;em&gt;Aborted&lt;/em&gt;).&lt;/li&gt;
&lt;/ul&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.amazonaws.com%2Fuploads%2Farticles%2Fz4glebmtkpxtopoylg5c.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.amazonaws.com%2Fuploads%2Farticles%2Fz4glebmtkpxtopoylg5c.png" alt=" " width="800" height="462"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Final Steps &amp;amp; Verification
&lt;/h3&gt;

&lt;p&gt;Setelah instalasi selesai, buka akses layanan pada firewall agar sistem berjalan lancar:&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;firewall-cmd &lt;span class="nt"&gt;--add-service&lt;/span&gt;&lt;span class="o"&gt;={&lt;/span&gt;freeipa-ldap,freeipa-ldaps,dns,ntp,http,https,kerberos&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--permanent&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;firewall-cmd &lt;span class="nt"&gt;--reload&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Gunakan perintah &lt;code&gt;kinit admin&lt;/code&gt; untuk memverifikasi tiket Kerberos Anda.&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.amazonaws.com%2Fuploads%2Farticles%2F0clry2t01retc7x0yg82.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.amazonaws.com%2Fuploads%2Farticles%2F0clry2t01retc7x0yg82.png" alt=" " width="800" height="118"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Membangun sistem identitas terpusat dengan FreeIPA memberikan kontrol penuh atas keamanan jaringan. Sebagai mahasiswa Teknik Informatika yang fokus pada &lt;em&gt;Backend&lt;/em&gt; dan &lt;em&gt;Security&lt;/em&gt;, pemahaman ini sangat membantu saya dalam mengelola infrastruktur server yang lebih profesional.&lt;/p&gt;

&lt;p&gt;Semoga tutorial ini bermanfaat bagi teman-teman yang juga sedang mengulik ekosistem RHEL!&lt;/p&gt;

</description>
      <category>linux</category>
      <category>rhel</category>
      <category>devops</category>
      <category>freeipa</category>
    </item>
    <item>
      <title>I Built a Safety-First Workflow Layer for Pacman (ATHA)</title>
      <dc:creator>Muhammad Dhiyaul Atha</dc:creator>
      <pubDate>Tue, 31 Mar 2026 16:35:36 +0000</pubDate>
      <link>https://dev.to/bangkah/i-built-a-simple-pacman-aur-wrapper-for-arch-linux-atha-11bd</link>
      <guid>https://dev.to/bangkah/i-built-a-simple-pacman-aur-wrapper-for-arch-linux-atha-11bd</guid>
      <description>&lt;p&gt;Managing packages on Arch Linux is powerful, but sometimes it lacks visibility and safety.&lt;/p&gt;

&lt;p&gt;You run a command… and it just executes.&lt;/p&gt;

&lt;p&gt;No preview. No clear audit trail. No structured workflow.&lt;/p&gt;

&lt;p&gt;So I started building &lt;strong&gt;ATHA&lt;/strong&gt; — a safety-first workflow layer on top of pacman.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is ATHA?
&lt;/h2&gt;

&lt;p&gt;ATHA is not a replacement for pacman.&lt;/p&gt;

&lt;p&gt;It tries to enhance it with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install planning (&lt;code&gt;--plan&lt;/code&gt;) before execution&lt;/li&gt;
&lt;li&gt;Dry-run support for safer operations&lt;/li&gt;
&lt;li&gt;Confirmation layers for critical actions&lt;/li&gt;
&lt;li&gt;Operation history with timeline view&lt;/li&gt;
&lt;li&gt;Built-in system diagnostics (&lt;code&gt;atha doctor&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal is simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Make package operations more predictable, transparent, and auditable.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Example
&lt;/h2&gt;

&lt;p&gt;Before installing a package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;atha &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--plan&lt;/span&gt; neovim
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You get a preview of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;dependencies&lt;/li&gt;
&lt;li&gt;disk usage&lt;/li&gt;
&lt;li&gt;source (official repo or AUR)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why I Built This
&lt;/h2&gt;

&lt;p&gt;Arch gives full control — but sometimes operations can feel a bit “blind”.&lt;/p&gt;

&lt;p&gt;ATHA is my attempt to improve:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Safety → reduce accidental changes&lt;/li&gt;
&lt;li&gt;Transparency → understand what will happen&lt;/li&gt;
&lt;li&gt;Auditability → keep track of what happened&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Comparison
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;pacman&lt;/th&gt;
&lt;th&gt;yay&lt;/th&gt;
&lt;th&gt;ATHA&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Dry-run support&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Install planning&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Operation history&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Workflow consistency&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yay &lt;span class="nt"&gt;-S&lt;/span&gt; atha
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;GitHub: &lt;a href="https://github.com/Bangkah/Atha" rel="noopener noreferrer"&gt;https://github.com/Bangkah/Atha&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;AUR: &lt;a href="https://aur.archlinux.org/packages/atha" rel="noopener noreferrer"&gt;https://aur.archlinux.org/packages/atha&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  💬 Feedback
&lt;/h2&gt;

&lt;p&gt;This project is still evolving and definitely not perfect.&lt;/p&gt;

&lt;p&gt;I’m sure there are things that can be improved — both in design and implementation.&lt;/p&gt;

&lt;p&gt;If you have feedback, criticism, or suggestions, I’d really appreciate hearing them.&lt;/p&gt;

</description>
      <category>linux</category>
      <category>archlinux</category>
      <category>opensource</category>
      <category>cli</category>
    </item>
    <item>
      <title>My First Attempt at Building a Reasoning AI (ARC Prize 2026)</title>
      <dc:creator>Muhammad Dhiyaul Atha</dc:creator>
      <pubDate>Thu, 26 Mar 2026 07:28:57 +0000</pubDate>
      <link>https://dev.to/bangkah/my-first-attempt-at-building-a-reasoning-ai-arc-prize-2026-18dj</link>
      <guid>https://dev.to/bangkah/my-first-attempt-at-building-a-reasoning-ai-arc-prize-2026-18dj</guid>
      <description>&lt;p&gt;What if AI fails the moment the problem changes?&lt;/p&gt;

&lt;p&gt;Most AI systems today are great at recognizing patterns — but what happens when the problem itself is different from anything they’ve seen before?&lt;/p&gt;

&lt;p&gt;That’s exactly the challenge behind the ARC Prize 2026 on Kaggle.&lt;/p&gt;




&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;I recently joined the ARC-AGI-2 competition on Kaggle, which challenges participants to build AI systems capable of solving problems they’ve never seen before.&lt;/p&gt;

&lt;p&gt;Unlike typical machine learning tasks, ARC is not about training on massive datasets.&lt;/p&gt;

&lt;p&gt;Instead, it focuses on something closer to human intelligence:&lt;br&gt;
&lt;strong&gt;reasoning and generalization.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  My First Approach (Baseline)
&lt;/h2&gt;

&lt;p&gt;To get started, I built a very simple baseline model.&lt;/p&gt;

&lt;p&gt;The goal was not to solve the problem yet — but to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Understand the dataset structure&lt;/li&gt;
&lt;li&gt;Learn how submissions work&lt;/li&gt;
&lt;li&gt;Successfully make my first submission&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here’s the basic idea:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Read input grid&lt;/li&gt;
&lt;li&gt;Generate output grid with the same shape&lt;/li&gt;
&lt;li&gt;Fill it with zeros&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Yes — it's intentionally simple.&lt;/p&gt;




&lt;h2&gt;
  
  
  Code &amp;amp; Repository
&lt;/h2&gt;

&lt;p&gt;You can check my first implementation here: &lt;a href="https://github.com/Bangkah/arc-agi-learning" rel="noopener noreferrer"&gt;https://github.com/Bangkah/arc-agi-learning&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This repository documents my learning journey as I explore reasoning-based AI.&lt;/p&gt;




&lt;h2&gt;
  
  
  First Submission (Kaggle)
&lt;/h2&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.amazonaws.com%2Fuploads%2Farticles%2Fyy2p32yfqtlhigxsx467.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.amazonaws.com%2Fuploads%2Farticles%2Fyy2p32yfqtlhigxsx467.png" alt="Kaggle Submission Screenshot" width="800" height="567"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Start Simple?
&lt;/h2&gt;

&lt;p&gt;Because ARC is not about jumping into complex models.&lt;/p&gt;

&lt;p&gt;It’s about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Understanding transformations&lt;/li&gt;
&lt;li&gt;Identifying patterns&lt;/li&gt;
&lt;li&gt;Building logic step-by-step&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Even advanced AI systems still struggle with ARC tasks.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why ARC is Hard
&lt;/h2&gt;

&lt;p&gt;ARC tasks require:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Understanding abstract patterns&lt;/li&gt;
&lt;li&gt;Applying transformations&lt;/li&gt;
&lt;li&gt;Generalizing from very few examples&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Unlike traditional machine learning, there is no training phase with millions of samples.&lt;/p&gt;

&lt;p&gt;Each problem is a completely new challenge.&lt;/p&gt;




&lt;h2&gt;
  
  
  First Submission Result
&lt;/h2&gt;

&lt;p&gt;My first submission didn’t perform well — and that’s expected.&lt;/p&gt;

&lt;p&gt;The real goal was:&lt;br&gt;
✔ Understanding the pipeline&lt;br&gt;
✔ Getting familiar with the problem&lt;br&gt;
✔ Starting the journey&lt;/p&gt;




&lt;h2&gt;
  
  
  Key Insight
&lt;/h2&gt;

&lt;p&gt;ARC is fundamentally different from most AI challenges.&lt;/p&gt;

&lt;p&gt;It’s not about:&lt;br&gt;
❌ memorizing patterns&lt;/p&gt;

&lt;p&gt;It’s about:&lt;br&gt;
✔ discovering rules&lt;br&gt;
✔ applying logic&lt;br&gt;
✔ adapting to new problems&lt;/p&gt;




&lt;h2&gt;
  
  
  What’s Next?
&lt;/h2&gt;

&lt;p&gt;My next steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Solve ARC tasks manually&lt;/li&gt;
&lt;li&gt;Build rule-based solutions&lt;/li&gt;
&lt;li&gt;Improve generalization step-by-step&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  💡 Final Thoughts
&lt;/h2&gt;

&lt;p&gt;This is not just a competition — it’s a challenge to rethink how we approach AI.&lt;/p&gt;

&lt;p&gt;And I’m just getting started.&lt;/p&gt;




&lt;p&gt;Have you tried solving ARC tasks?&lt;/p&gt;

&lt;p&gt;I’d love to hear how others approach reasoning problems like this.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>kaggle</category>
      <category>programming</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>Muhammad Dhiyaul Atha</dc:creator>
      <pubDate>Tue, 24 Mar 2026 04:53:53 +0000</pubDate>
      <link>https://dev.to/bangkah/-36mp</link>
      <guid>https://dev.to/bangkah/-36mp</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/bangkah/my-first-home-server-using-a-12-year-old-laptop-2eh7" class="crayons-story__hidden-navigation-link"&gt;My First Home Server Using a 12-Year-Old Laptop&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/bangkah" class="crayons-avatar  crayons-avatar--l  "&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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3665512%2Fdc6c5db5-91c9-4887-a5c6-33c8db391e07.jpeg" alt="bangkah profile" class="crayons-avatar__image" width="800" height="599"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/bangkah" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Muhammad Dhiyaul Atha
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Muhammad Dhiyaul Atha
                
              
              &lt;div id="story-author-preview-content-3392551" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/bangkah" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3665512%2Fdc6c5db5-91c9-4887-a5c6-33c8db391e07.jpeg" class="crayons-avatar__image" alt="" width="800" height="599"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Muhammad Dhiyaul Atha&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/bangkah/my-first-home-server-using-a-12-year-old-laptop-2eh7" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Mar 24&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/bangkah/my-first-home-server-using-a-12-year-old-laptop-2eh7" id="article-link-3392551"&gt;
          My First Home Server Using a 12-Year-Old Laptop
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/linux"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;linux&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/devops"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;devops&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/productivity"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;productivity&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/homelab"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;homelab&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
            &lt;a href="https://dev.to/bangkah/my-first-home-server-using-a-12-year-old-laptop-2eh7#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              &lt;span class="hidden s:inline"&gt;Add Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            2 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>linux</category>
      <category>devops</category>
      <category>productivity</category>
      <category>homelab</category>
    </item>
    <item>
      <title>My First Home Server Using a 12-Year-Old Laptop</title>
      <dc:creator>Muhammad Dhiyaul Atha</dc:creator>
      <pubDate>Tue, 24 Mar 2026 04:41:31 +0000</pubDate>
      <link>https://dev.to/bangkah/my-first-home-server-using-a-12-year-old-laptop-2eh7</link>
      <guid>https://dev.to/bangkah/my-first-home-server-using-a-12-year-old-laptop-2eh7</guid>
      <description>&lt;h1&gt;
  
  
  When an Old Laptop Finds Its New Purpose
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Turning a 2012 MacBook Pro into My First Personal Server
&lt;/h2&gt;

&lt;p&gt;There was a 2012 MacBook Pro sitting in front of me.&lt;/p&gt;

&lt;p&gt;Not my main machine anymore.&lt;br&gt;
Definitely not fast by today’s standards.&lt;/p&gt;

&lt;p&gt;But that’s exactly where a simple question came up:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“How far can this old laptop still be useful?”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That question led me to a small experiment —&lt;br&gt;
turning this old machine into a personal server and controlling it remotely via SSH from my main laptop.&lt;/p&gt;


&lt;h2&gt;
  
  
  Why an Old Laptop?
&lt;/h2&gt;

&lt;p&gt;As a software engineering student, I started realizing something important:&lt;/p&gt;

&lt;p&gt;Learning about servers is not enough if it’s only theory.&lt;/p&gt;

&lt;p&gt;I can read documentation, watch tutorials, and follow guides —&lt;br&gt;
but there’s always a gap between &lt;em&gt;knowing&lt;/em&gt; and &lt;em&gt;actually experiencing it&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;At the same time, I had:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A 2012 MacBook Pro collecting dust&lt;/li&gt;
&lt;li&gt;A growing interest in Linux&lt;/li&gt;
&lt;li&gt;Curiosity about how servers actually work&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So instead of letting it sit unused, I turned it into a learning lab.&lt;/p&gt;


&lt;h2&gt;
  
  
  System Choice: Arch Linux on Old Hardware
&lt;/h2&gt;

&lt;p&gt;I chose &lt;strong&gt;Arch Linux&lt;/strong&gt; for this machine.&lt;/p&gt;

&lt;p&gt;Not because it’s easy — actually the opposite.&lt;/p&gt;

&lt;p&gt;But because I wanted:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A lightweight system&lt;/li&gt;
&lt;li&gt;Full control over everything installed&lt;/li&gt;
&lt;li&gt;A raw, hands-on learning experience&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For my main laptop, I use an Acer Nitro V16 running Garuda Linux —&lt;br&gt;
this is where I control everything from.&lt;/p&gt;


&lt;h2&gt;
  
  
  The Struggles: Nothing Worked Perfectly
&lt;/h2&gt;

&lt;p&gt;Of course, things didn’t go smoothly at first.&lt;/p&gt;

&lt;p&gt;Here are some challenges I faced:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;⚠️ Old hardware limitations (heat, performance)&lt;/li&gt;
&lt;li&gt;⚠️ Arch Linux setup complexity&lt;/li&gt;
&lt;li&gt;⚠️ Networking confusion (IP, services, firewall)&lt;/li&gt;
&lt;li&gt;⚠️ SSH failing due to small misconfigurations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There were frustrating moments, especially when:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“Why is SSH installed but I still can’t connect?”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But those were the moments where real learning happened:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reading logs&lt;/li&gt;
&lt;li&gt;Understanding errors&lt;/li&gt;
&lt;li&gt;Not just copy-pasting commands&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  The Goal: More Than Just Remote Access
&lt;/h2&gt;

&lt;p&gt;My goal wasn’t just:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“Connect via SSH from another laptop”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I wanted to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Understand how servers actually work&lt;/li&gt;
&lt;li&gt;Get comfortable working without a GUI&lt;/li&gt;
&lt;li&gt;Simulate a simple backend/DevOps workflow&lt;/li&gt;
&lt;li&gt;Build the habit of working remotely&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This server became my personal lab —&lt;br&gt;
a safe place to break things and learn.&lt;/p&gt;


&lt;h2&gt;
  
  
  The Breakthrough Moment
&lt;/h2&gt;

&lt;p&gt;The most satisfying moment?&lt;/p&gt;

&lt;p&gt;From my main laptop, I ran:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ssh"&gt;&lt;code&gt;&lt;span class="k"&gt;ssh&lt;/span&gt; atha@192.xxx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then…&lt;/p&gt;

&lt;p&gt;The terminal of the 2012 MacBook appeared on my screen.&lt;/p&gt;

&lt;p&gt;No GUI.&lt;br&gt;
No mouse.&lt;br&gt;
Just a terminal.&lt;/p&gt;

&lt;p&gt;But it felt like opening a door to a completely new world.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I Can Do Now
&lt;/h2&gt;

&lt;p&gt;Now I can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Manage my server from my main laptop&lt;/li&gt;
&lt;li&gt;Install and configure services remotely&lt;/li&gt;
&lt;li&gt;Bring an old machine back to life&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And this is just the beginning.&lt;/p&gt;

&lt;p&gt;Next, I plan to explore:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Setting up a web server&lt;/li&gt;
&lt;li&gt;Building a simple API&lt;/li&gt;
&lt;li&gt;SSH hardening&lt;/li&gt;
&lt;li&gt;Small automation scripts&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;This experiment taught me something important:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Learning servers doesn’t have to be expensive.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Sometimes, an old laptop and curiosity are enough.&lt;/p&gt;

&lt;p&gt;That 2012 MacBook Pro that once felt outdated&lt;br&gt;
now has a new role.&lt;/p&gt;

&lt;p&gt;Not as my main machine —&lt;br&gt;
but as a silent teacher, helping me understand systems, patience, and real learning.&lt;/p&gt;

&lt;p&gt;And this journey…&lt;/p&gt;

&lt;p&gt;is just getting started 🚀&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;What about you?&lt;/strong&gt;&lt;br&gt;
Have you ever repurposed old hardware into something useful?&lt;/p&gt;

</description>
      <category>linux</category>
      <category>devops</category>
      <category>productivity</category>
      <category>homelab</category>
    </item>
    <item>
      <title>Saya Membuat CLI Tool Jadwal Shalat dan Merilisnya ke Arch Linux AUR</title>
      <dc:creator>Muhammad Dhiyaul Atha</dc:creator>
      <pubDate>Wed, 18 Feb 2026 12:30:23 +0000</pubDate>
      <link>https://dev.to/bangkah/saya-membuat-cli-tool-jadwal-shalat-dan-merilisnya-ke-arch-linux-aur-352f</link>
      <guid>https://dev.to/bangkah/saya-membuat-cli-tool-jadwal-shalat-dan-merilisnya-ke-arch-linux-aur-352f</guid>
      <description>&lt;p&gt;Sebagai pengguna Linux dan seseorang yang sering bekerja di terminal, saya ingin bisa melihat jadwal shalat langsung dari CLI tanpa membuka browser atau aplikasi GUI.&lt;/p&gt;

&lt;p&gt;Dari kebutuhan sederhana itu, saya membuat sebuah tool bernama &lt;strong&gt;jadwal-shalat&lt;/strong&gt; — sebuah CLI tool profesional berbasis Python yang dapat menampilkan jadwal shalat secara otomatis berdasarkan lokasi pengguna.&lt;/p&gt;

&lt;p&gt;Sekarang tool ini sudah tersedia secara resmi di Arch Linux AUR.&lt;/p&gt;




&lt;h1&gt;
  
  
  Latar Belakang
&lt;/h1&gt;

&lt;p&gt;Banyak aplikasi jadwal shalat tersedia, tapi sebagian besar berbasis:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Mobile apps&lt;/li&gt;
&lt;li&gt;Website&lt;/li&gt;
&lt;li&gt;Aplikasi GUI&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Masalahnya, bagi pengguna Linux yang sering bekerja di:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;terminal&lt;/li&gt;
&lt;li&gt;server&lt;/li&gt;
&lt;li&gt;SSH session&lt;/li&gt;
&lt;li&gt;environment minimal&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;solusi tersebut tidak praktis.&lt;/p&gt;

&lt;p&gt;Saya ingin sesuatu yang:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ringan&lt;/li&gt;
&lt;li&gt;cepat&lt;/li&gt;
&lt;li&gt;otomatis&lt;/li&gt;
&lt;li&gt;dan native di terminal&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Maka saya membuat CLI tool ini.&lt;/p&gt;




&lt;h1&gt;
  
  
  Apa Itu jadwal-shalat?
&lt;/h1&gt;

&lt;p&gt;jadwal-shalat adalah CLI tool Python yang dapat:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;mendeteksi lokasi otomatis dari IP publik&lt;/li&gt;
&lt;li&gt;menentukan timezone secara akurat&lt;/li&gt;
&lt;li&gt;mengambil jadwal shalat dari API Aladhan (method Kemenag Indonesia)&lt;/li&gt;
&lt;li&gt;menampilkan jadwal secara rapi di terminal&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tool ini dirancang khusus untuk pengguna Indonesia.&lt;/p&gt;




&lt;h1&gt;
  
  
  Fitur Utama
&lt;/h1&gt;

&lt;p&gt;Beberapa fitur yang tersedia saat ini:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deteksi IP publik otomatis&lt;/li&gt;
&lt;li&gt;Deteksi lokasi otomatis (kota, negara, koordinat, timezone)&lt;/li&gt;
&lt;li&gt;Fallback API lokasi jika layanan utama gagal&lt;/li&gt;
&lt;li&gt;Menggunakan API Aladhan (method=20/Kemenag Indonesia)&lt;/li&gt;
&lt;li&gt;Jadwal shalat lengkap&lt;/li&gt;
&lt;li&gt;Menampilkan waktu shalat berikutnya + countdown&lt;/li&gt;
&lt;li&gt;Output terminal rapi dengan alignment yang baik&lt;/li&gt;
&lt;li&gt;Error handling lengkap&lt;/li&gt;
&lt;li&gt;Timeout protection untuk API&lt;/li&gt;
&lt;li&gt;Support timezone akurat&lt;/li&gt;
&lt;li&gt;Siap packaging AUR dengan auto update&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  Contoh Output
&lt;/h1&gt;

&lt;p&gt;Contoh ketika dijalankan:&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.amazonaws.com%2Fuploads%2Farticles%2Fm7e9ybq3pcq2j3xufvpx.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.amazonaws.com%2Fuploads%2Farticles%2Fm7e9ybq3pcq2j3xufvpx.png" alt=" " width="624" height="603"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Output difokuskan agar:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;mudah dibaca&lt;/li&gt;
&lt;li&gt;minimalis&lt;/li&gt;
&lt;li&gt;profesional&lt;/li&gt;
&lt;li&gt;cocok untuk penggunaan harian di terminal&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  Instalasi via Arch Linux AUR
&lt;/h1&gt;

&lt;p&gt;Tool ini sekarang tersedia di AUR, sehingga instalasi sangat mudah:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yay -S jadwal-shalat
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Atau manual:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone https://aur.archlinux.org/jadwal-shalat.git
cd jadwal-shalat
makepkg -si
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sebagai maintainer AUR, saya juga mengatur auto-update menggunakan GitHub Actions.&lt;/p&gt;




&lt;h1&gt;
  
  
  Instalasi Manual
&lt;/h1&gt;

&lt;p&gt;Jika tidak menggunakan Arch Linux:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install requests
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Clone repo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone https://github.com/Bangkah/jadwal-shalat.git
cd jadwal-shalat
chmod +x jadwal-shalat.py
./jadwal-shalat.py
&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;python jadwal-shalat.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  Cara Kerja Tool Ini
&lt;/h1&gt;

&lt;p&gt;Secara sederhana:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Mengambil IP publik user&lt;/li&gt;
&lt;li&gt;Mengubah IP menjadi lokasi geografis&lt;/li&gt;
&lt;li&gt;Menentukan timezone&lt;/li&gt;
&lt;li&gt;Mengambil jadwal shalat dari API Aladhan&lt;/li&gt;
&lt;li&gt;Menampilkan jadwal dan countdown&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Semua proses dilakukan secara otomatis.&lt;/p&gt;




&lt;h1&gt;
  
  
  Fokus pada Reliability
&lt;/h1&gt;

&lt;p&gt;Beberapa hal yang saya implementasikan untuk memastikan tool stabil:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;fallback API jika layanan lokasi gagal&lt;/li&gt;
&lt;li&gt;timeout protection&lt;/li&gt;
&lt;li&gt;error handling jaringan&lt;/li&gt;
&lt;li&gt;parsing timezone akurat&lt;/li&gt;
&lt;li&gt;output formatting konsisten&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ini penting agar tool tetap berfungsi bahkan dalam kondisi jaringan tidak stabil.&lt;/p&gt;




&lt;h1&gt;
  
  
  Integrasi dengan Arch Linux Packaging
&lt;/h1&gt;

&lt;p&gt;Salah satu milestone terbesar project ini adalah berhasil dipublish ke Arch Linux AUR.&lt;/p&gt;

&lt;p&gt;Ini berarti:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;user bisa install dengan yay&lt;/li&gt;
&lt;li&gt;update terdistribusi secara otomatis&lt;/li&gt;
&lt;li&gt;mengikuti standar packaging Linux&lt;/li&gt;
&lt;li&gt;tool menjadi lebih profesional&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Saya juga mengintegrasikan GitHub Actions untuk membantu workflow update.&lt;/p&gt;




&lt;h1&gt;
  
  
  Roadmap ke Depan
&lt;/h1&gt;

&lt;p&gt;Beberapa fitur yang direncanakan:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;input manual kota&lt;/li&gt;
&lt;li&gt;input manual koordinat&lt;/li&gt;
&lt;li&gt;output JSON&lt;/li&gt;
&lt;li&gt;notifikasi waktu shalat&lt;/li&gt;
&lt;li&gt;packaging PyPI&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tujuannya adalah membuat tool ini semakin fleksibel.&lt;/p&gt;




&lt;h1&gt;
  
  
  Kenapa Saya Membuat Project Ini?
&lt;/h1&gt;

&lt;p&gt;Selain kebutuhan pribadi, project ini juga menjadi sarana belajar tentang:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CLI development dengan Python&lt;/li&gt;
&lt;li&gt;API integration&lt;/li&gt;
&lt;li&gt;timezone handling&lt;/li&gt;
&lt;li&gt;Linux packaging (PKGBUILD)&lt;/li&gt;
&lt;li&gt;AUR maintenance&lt;/li&gt;
&lt;li&gt;CI/CD dengan GitHub Actions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Project kecil seperti ini sangat membantu meningkatkan skill sebagai developer.&lt;/p&gt;




&lt;h1&gt;
  
  
  Open Source dan Kontribusi
&lt;/h1&gt;

&lt;p&gt;Project ini open source dan tersedia di GitHub:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Bangkah/jadwal-shalat" rel="noopener noreferrer"&gt;https://github.com/Bangkah/jadwal-shalat&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Kontribusi sangat diterima.&lt;/p&gt;




&lt;h1&gt;
  
  
  Penutup
&lt;/h1&gt;

&lt;p&gt;Linux memiliki ekosistem CLI yang sangat kuat, dan saya percaya tool kecil seperti ini bisa meningkatkan produktivitas pengguna terminal.&lt;/p&gt;

&lt;p&gt;Jika kamu pengguna Arch Linux atau Linux secara umum, kamu bisa mencoba tool ini dan memberikan feedback.&lt;/p&gt;

</description>
      <category>aur</category>
      <category>python</category>
      <category>cli</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Building Sentinel AI: A Cybersecurity CLI Powered by Copilot</title>
      <dc:creator>Muhammad Dhiyaul Atha</dc:creator>
      <pubDate>Sat, 14 Feb 2026 17:30:38 +0000</pubDate>
      <link>https://dev.to/bangkah/building-sentinel-ai-a-cybersecurity-cli-powered-by-copilot-35fh</link>
      <guid>https://dev.to/bangkah/building-sentinel-ai-a-cybersecurity-cli-powered-by-copilot-35fh</guid>
      <description>&lt;h1&gt;
  
  
  From Copilot Experiment to Production-Ready CLI: Building Sentinel AI
&lt;/h1&gt;

&lt;p&gt;Cybersecurity is no longer optional — every connected system is exposed to potential threats. While there are many enterprise-grade tools available, I wanted to understand how such tools work internally.&lt;/p&gt;

&lt;p&gt;So I built my own.&lt;/p&gt;

&lt;p&gt;Sentinel AI started as a small experiment using GitHub Copilot CLI. But through iteration, debugging, and production hardening, it evolved into a fully functional, production-ready cybersecurity CLI tool for Linux.&lt;/p&gt;

&lt;p&gt;This article explains the journey — from idea to production.&lt;/p&gt;




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

&lt;p&gt;Modern systems constantly create network connections — many legitimate, some suspicious. Most users never see what is happening behind the scenes.&lt;/p&gt;

&lt;p&gt;I wanted a tool that could:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Show active network connections&lt;/li&gt;
&lt;li&gt;Identify suspicious behavior&lt;/li&gt;
&lt;li&gt;Assign risk scores&lt;/li&gt;
&lt;li&gt;Provide actionable summaries&lt;/li&gt;
&lt;li&gt;Work directly from the terminal&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It needed to be fast, simple, and transparent.&lt;/p&gt;

&lt;p&gt;That’s how Sentinel AI was born.&lt;/p&gt;




&lt;h1&gt;
  
  
  How GitHub Copilot Accelerated Development
&lt;/h1&gt;

&lt;p&gt;GitHub Copilot CLI significantly accelerated development by helping generate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Modular Python code structure&lt;/li&gt;
&lt;li&gt;CLI argument parsing using argparse&lt;/li&gt;
&lt;li&gt;Risk classification logic&lt;/li&gt;
&lt;li&gt;Error handling and logging&lt;/li&gt;
&lt;li&gt;Clean and readable code patterns&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of spending hours writing boilerplate, I could focus on architecture and functionality.&lt;/p&gt;

&lt;p&gt;Copilot acted as a coding assistant — not a replacement — helping me move faster while maintaining control over the system design.&lt;/p&gt;




&lt;h1&gt;
  
  
  Architecture Overview
&lt;/h1&gt;

&lt;p&gt;Sentinel AI is built using a modular architecture:&lt;/p&gt;

&lt;p&gt;Core components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Network Scanner — collects active connections&lt;/li&gt;
&lt;li&gt;Analyzer — evaluates connections and assigns risk scores&lt;/li&gt;
&lt;li&gt;Reporting Engine — summarizes system risk level&lt;/li&gt;
&lt;li&gt;CLI Interface — provides user interaction&lt;/li&gt;
&lt;li&gt;Logging System — records activity and errors&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Key technologies:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Python&lt;/li&gt;
&lt;li&gt;psutil&lt;/li&gt;
&lt;li&gt;colorama&lt;/li&gt;
&lt;li&gt;argparse&lt;/li&gt;
&lt;li&gt;autopep8&lt;/li&gt;
&lt;li&gt;GitHub Actions (CI/CD)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This architecture ensures maintainability and extensibility.&lt;/p&gt;




&lt;h1&gt;
  
  
  Core Features
&lt;/h1&gt;

&lt;p&gt;Sentinel AI provides several security-focused capabilities:&lt;/p&gt;

&lt;h3&gt;
  
  
  Network Scanning
&lt;/h3&gt;

&lt;p&gt;Lists all active network connections with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Protocol&lt;/li&gt;
&lt;li&gt;Local address&lt;/li&gt;
&lt;li&gt;Remote address&lt;/li&gt;
&lt;li&gt;Process ID&lt;/li&gt;
&lt;li&gt;Process name&lt;/li&gt;
&lt;/ul&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sentinel-ai scan
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Intelligent Risk Analysis
&lt;/h3&gt;

&lt;p&gt;Each connection is analyzed and assigned:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Numeric risk score (0–100)&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Risk level classification:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;LOW&lt;/li&gt;
&lt;li&gt;MEDIUM&lt;/li&gt;
&lt;li&gt;HIGH&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Explanation of the risk&lt;/p&gt;&lt;/li&gt;

&lt;/ul&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sentinel-ai analyze
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Proto  Local Address      Remote Address     PID   Process   Risk
TCP    192.168.1.10:54321 8.8.8.8:53        1234  python3   HIGH (87)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  System Risk Report
&lt;/h3&gt;

&lt;p&gt;Provides a system-level security overview:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sentinel-ai report
&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;=== Sentinel AI CLI Security Report ===
Total connections: 12
External connections: 3
High risk: 1
Medium risk: 2
Low risk: 9
Overall system risk: HIGH (72/100)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This allows users to understand their system security posture instantly.&lt;/p&gt;




&lt;h3&gt;
  
  
  System Information
&lt;/h3&gt;

&lt;p&gt;Displays system-level information:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sentinel-ai system
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;OS&lt;/li&gt;
&lt;li&gt;Kernel version&lt;/li&gt;
&lt;li&gt;CPU&lt;/li&gt;
&lt;li&gt;Memory&lt;/li&gt;
&lt;li&gt;Hostname&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Developer Utilities
&lt;/h3&gt;

&lt;p&gt;Sentinel AI also includes developer-focused tools:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sentinel-ai debug file.py
sentinel-ai explain-code file.py
sentinel-ai improve-code file.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These tools help developers analyze, debug, and improve Python code.&lt;/p&gt;




&lt;h1&gt;
  
  
  From Prototype to Production
&lt;/h1&gt;

&lt;p&gt;What started as a simple script evolved into a production-grade CLI tool.&lt;/p&gt;

&lt;p&gt;Key improvements included:&lt;/p&gt;

&lt;h3&gt;
  
  
  Modern Python Packaging
&lt;/h3&gt;

&lt;p&gt;Sentinel AI uses:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;pyproject.toml&lt;/li&gt;
&lt;li&gt;Standardized project structure&lt;/li&gt;
&lt;li&gt;Proper dependency management&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  CI/CD Pipeline
&lt;/h3&gt;

&lt;p&gt;Using GitHub Actions, Sentinel AI now has automated:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Linting (PEP8 compliance)&lt;/li&gt;
&lt;li&gt;Build validation&lt;/li&gt;
&lt;li&gt;Test execution&lt;/li&gt;
&lt;li&gt;Release safety checks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This ensures every update maintains production quality.&lt;/p&gt;




&lt;h3&gt;
  
  
  Trusted Publishing to PyPI
&lt;/h3&gt;

&lt;p&gt;Sentinel AI uses secure Trusted Publishing, allowing automated and secure package releases.&lt;/p&gt;

&lt;p&gt;This eliminates manual credential handling and improves release security.&lt;/p&gt;




&lt;h1&gt;
  
  
  Installation
&lt;/h1&gt;

&lt;p&gt;Sentinel AI is available on PyPI.&lt;/p&gt;

&lt;p&gt;Install using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install sentinel-ai-cli
&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 plaintext"&gt;&lt;code&gt;sentinel-ai report
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And immediately see your system’s security overview.&lt;/p&gt;




&lt;h1&gt;
  
  
  Challenges and Lessons Learned
&lt;/h1&gt;

&lt;p&gt;Building Sentinel AI taught me several important engineering lessons:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. CI/CD Discipline
&lt;/h3&gt;

&lt;p&gt;Fixing lint errors, formatting issues, and pipeline failures helped reinforce professional development practices.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Production Packaging
&lt;/h3&gt;

&lt;p&gt;Using modern Python packaging standards improved maintainability and reliability.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. CLI Design Principles
&lt;/h3&gt;

&lt;p&gt;Designing a clean CLI interface requires careful planning to ensure usability and clarity.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Copilot as a Force Multiplier
&lt;/h3&gt;

&lt;p&gt;Copilot accelerated development — but debugging and refinement required human understanding.&lt;/p&gt;

&lt;p&gt;AI helped build faster, but engineering discipline made it production-ready.&lt;/p&gt;




&lt;h1&gt;
  
  
  Future Plans
&lt;/h1&gt;

&lt;p&gt;Planned improvements include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Arch Linux (AUR) package&lt;/li&gt;
&lt;li&gt;Docker image&lt;/li&gt;
&lt;li&gt;Real-time monitoring mode&lt;/li&gt;
&lt;li&gt;Threat intelligence integration&lt;/li&gt;
&lt;li&gt;Plugin system&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sentinel AI will continue evolving.&lt;/p&gt;




&lt;h1&gt;
  
  
  Open Source and Availability
&lt;/h1&gt;

&lt;p&gt;GitHub Repository:&lt;br&gt;
&lt;a href="https://github.com/Bangkah/sentinel" rel="noopener noreferrer"&gt;https://github.com/Bangkah/sentinel&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;PyPI Package:&lt;br&gt;
&lt;a href="https://pypi.org/project/sentinel-ai-cli/" rel="noopener noreferrer"&gt;https://pypi.org/project/sentinel-ai-cli/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Sentinel AI is fully open source and contributions are welcome.&lt;/p&gt;




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

&lt;p&gt;Sentinel AI began as a simple experiment with GitHub Copilot CLI.&lt;/p&gt;

&lt;p&gt;Through iteration, debugging, CI/CD integration, and proper packaging, it became a production-ready cybersecurity tool.&lt;/p&gt;

&lt;p&gt;This project demonstrates how modern AI-assisted development, combined with engineering discipline, can accelerate the creation of real-world tools.&lt;/p&gt;

&lt;p&gt;Sentinel AI is not just a project — it is a foundation for building more advanced security tools in the future.&lt;/p&gt;




&lt;h1&gt;
  
  
  Author
&lt;/h1&gt;

&lt;p&gt;Muhammad Dhiyaul Atha&lt;br&gt;
Computer Science Student &amp;amp; Open Source Developer&lt;/p&gt;

</description>
      <category>githubcopilot</category>
      <category>githubchallenge</category>
      <category>cli</category>
      <category>devchallenge</category>
    </item>
    <item>
      <title>Saat Laptop Lama Menemukan Peran Barunya</title>
      <dc:creator>Muhammad Dhiyaul Atha</dc:creator>
      <pubDate>Fri, 30 Jan 2026 18:11:37 +0000</pubDate>
      <link>https://dev.to/bangkah/saat-laptop-lama-menemukan-peran-barunya-3pha</link>
      <guid>https://dev.to/bangkah/saat-laptop-lama-menemukan-peran-barunya-3pha</guid>
      <description>&lt;h1&gt;
  
  
  Mengubah MacBook Pro 2012 Menjadi Server Pribadi (Eksperimen Pertamaku)
&lt;/h1&gt;

&lt;p&gt;Ada satu MacBook Pro 2012 di hadapanku.&lt;br&gt;
Bukan laptop utama, performanya juga jelas sudah tertinggal jauh dibanding mesin-mesin modern. Tapi justru dari situ muncul satu pertanyaan sederhana:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“Sejauh apa laptop lama ini masih bisa berguna?”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Pertanyaan itu akhirnya membawaku pada sebuah eksperimen kecil: &lt;strong&gt;mengubah MacBook Pro 2012 menjadi server pribadi&lt;/strong&gt;, lalu mengontrolnya dari laptop utamaku menggunakan &lt;strong&gt;SSH&lt;/strong&gt;.&lt;/p&gt;


&lt;h2&gt;
  
  
  Latar Belakang: Kenapa Laptop Lama?
&lt;/h2&gt;

&lt;p&gt;Sebagai mahasiswa dan pembelajar di dunia software engineering, aku mulai sadar satu hal:&lt;br&gt;
&lt;strong&gt;belajar server tidak cukup hanya dari teori.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Aku bisa membaca dokumentasi, menonton video, atau mengikuti tutorial, tapi tetap ada jarak antara “tahu” dan “pernah mengalami sendiri”.&lt;/p&gt;

&lt;p&gt;Di sisi lain, aku punya:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; &lt;strong&gt;MacBook Pro 2012&lt;/strong&gt; yang jarang dipakai&lt;/li&gt;
&lt;li&gt; ketertarikan besar pada Linux&lt;/li&gt;
&lt;li&gt; rasa penasaran tentang bagaimana server bekerja di dunia nyata&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Daripada membiarkannya berdebu, aku memutuskan menjadikannya &lt;strong&gt;server eksperimen&lt;/strong&gt;.&lt;/p&gt;


&lt;h2&gt;
  
  
  Pilihan Sistem: Arch Linux di Mesin Tua
&lt;/h2&gt;

&lt;p&gt;Aku memilih &lt;strong&gt;Arch Linux&lt;/strong&gt; untuk MacBook Pro 2012 ini.&lt;/p&gt;

&lt;p&gt;Bukan karena paling mudah — justru sebaliknya.&lt;br&gt;
Tapi karena aku ingin:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;sistem yang ringan&lt;/li&gt;
&lt;li&gt;kontrol penuh terhadap apa saja yang terpasang&lt;/li&gt;
&lt;li&gt;dan pengalaman belajar yang “apa adanya”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Untuk laptop utamaku, aku menggunakan &lt;strong&gt;Acer Nitro V16 dengan Garuda Linux&lt;/strong&gt;. Dari sinilah semua kontrol dilakukan.&lt;/p&gt;


&lt;h2&gt;
  
  
  Kendala: Tidak Semua Berjalan Mulus
&lt;/h2&gt;

&lt;p&gt;Tentu saja, eksperimen ini tidak langsung berjalan mulus.&lt;/p&gt;

&lt;p&gt;Beberapa kendala yang aku temui:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;⚠️ &lt;strong&gt;Hardware lama&lt;/strong&gt;: kipas cepat panas, performa terbatas&lt;/li&gt;
&lt;li&gt;⚠️ Konfigurasi Arch Linux yang menuntut ketelitian&lt;/li&gt;
&lt;li&gt;⚠️ Networking yang awalnya membingungkan (IP, service, firewall)&lt;/li&gt;
&lt;li&gt;⚠️ SSH yang sempat gagal konek karena kesalahan kecil&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ada momen frustrasi, terutama saat:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Kenapa sudah install SSH tapi tetap tidak bisa diakses?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Namun justru di titik-titik inilah aku benar-benar belajar:&lt;br&gt;
membaca log, memahami error, dan tidak asal copy–paste perintah.&lt;/p&gt;


&lt;h2&gt;
  
  
  Tujuan: Bukan Sekadar Bisa Remote
&lt;/h2&gt;

&lt;p&gt;Tujuanku bukan hanya:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“bisa login SSH dari laptop lain”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Lebih dari itu, aku ingin:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;memahami &lt;strong&gt;konsep server secara nyata&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;membiasakan diri mengelola sistem tanpa GUI&lt;/li&gt;
&lt;li&gt;mensimulasikan workflow backend &amp;amp; DevOps sederhana&lt;/li&gt;
&lt;li&gt;dan melatih kebiasaan bekerja secara remote&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Server ini aku anggap sebagai &lt;strong&gt;laboratorium pribadi&lt;/strong&gt;, tempat aman untuk salah dan belajar.&lt;/p&gt;


&lt;h2&gt;
  
  
  Progres: Saat SSH Akhirnya Berhasil
&lt;/h2&gt;

&lt;p&gt;Momen paling memuaskan adalah saat dari Acer Nitro V16 aku menjalankan:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh atha@192.xxxx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lalu…&lt;br&gt;
terminal MacBook Pro 2012 muncul di layarku.&lt;/p&gt;

&lt;p&gt;Tidak ada tampilan grafis.&lt;br&gt;
Tidak ada mouse.&lt;br&gt;
Hanya terminal — tapi rasanya seperti membuka pintu ke dunia baru.&lt;/p&gt;

&lt;p&gt;Sekarang aku bisa:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;mengelola server dari laptop utama&lt;/li&gt;
&lt;li&gt;install service tanpa menyentuh fisik server&lt;/li&gt;
&lt;li&gt;menjadikan MacBook lama sebagai mesin yang “hidup kembali”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Dari sini, rencananya akan berlanjut ke:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;web server&lt;/li&gt;
&lt;li&gt;API sederhana&lt;/li&gt;
&lt;li&gt;hardening SSH&lt;/li&gt;
&lt;li&gt;dan mungkin automasi kecil-kecilan&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Penutup
&lt;/h2&gt;

&lt;p&gt;Eksperimen ini mengajarkanku satu hal penting:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Belajar server tidak harus mahal.&lt;br&gt;
Kadang, laptop lama dan rasa penasaran sudah cukup.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;MacBook Pro 2012 yang dulu terasa usang, kini punya peran baru.&lt;br&gt;
Bukan sebagai mesin utama, tapi sebagai &lt;strong&gt;guru diam-diam&lt;/strong&gt; yang mengajarkanku tentang sistem, kesabaran, dan proses belajar yang sebenarnya.&lt;/p&gt;

&lt;p&gt;Dan perjalanan ini… baru saja dimulai.&lt;/p&gt;




</description>
      <category>devops</category>
      <category>linux</category>
      <category>learning</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Membuat API CRUD di Laravel dengan Sanctum (Step by Step)</title>
      <dc:creator>Muhammad Dhiyaul Atha</dc:creator>
      <pubDate>Sun, 11 Jan 2026 15:00:37 +0000</pubDate>
      <link>https://dev.to/bangkah/membuat-api-crud-di-laravel-dengan-sanctum-step-by-step-id</link>
      <guid>https://dev.to/bangkah/membuat-api-crud-di-laravel-dengan-sanctum-step-by-step-id</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;"Pernah nggak, frontend kamu butuh data dari backend Laravel, tapi API-nya belum aman? Di artikel ini, kamu akan belajar bikin API CRUD yang hanya bisa diakses user terautentikasi pakai Sanctum."&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Kenapa Harus Pakai Sanctum untuk API CRUD?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Data lebih aman, hanya user login yang bisa akses&lt;/li&gt;
&lt;li&gt;Cocok untuk SPA, mobile app, dan aplikasi modern&lt;/li&gt;
&lt;li&gt;Mudah diintegrasikan dengan frontend (React, Vue, dsb)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Studi Kasus: API Artikel (CRUD + Auth)
&lt;/h2&gt;

&lt;p&gt;Kita akan membuat API CRUD Artikel yang hanya bisa diakses user yang sudah login menggunakan Laravel Sanctum.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 1: Setup Project Laravel &amp;amp; Sanctum
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer create-project &lt;span class="nt"&gt;--prefer-dist&lt;/span&gt; laravel/laravel belajar-api
&lt;span class="nb"&gt;cd &lt;/span&gt;belajar-api
composer require laravel/sanctum
php artisan vendor:publish &lt;span class="nt"&gt;--provider&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Laravel&lt;/span&gt;&lt;span class="se"&gt;\S&lt;/span&gt;&lt;span class="s2"&gt;anctum&lt;/span&gt;&lt;span class="se"&gt;\S&lt;/span&gt;&lt;span class="s2"&gt;anctumServiceProvider"&lt;/span&gt;
php artisan migrate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tambahkan middleware Sanctum di &lt;code&gt;app/Http/Kernel.php&lt;/code&gt; pada group &lt;code&gt;api&lt;/code&gt;:&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="s1"&gt;'api'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nc"&gt;\Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful&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="s1"&gt;'throttle:api'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nc"&gt;\Illuminate\Routing\Middleware\SubstituteBindings&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="p"&gt;],&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 2: Setup Model User &amp;amp; Artikel (Ownership Data)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  User
&lt;/h3&gt;

&lt;p&gt;Pastikan model &lt;code&gt;User&lt;/code&gt; pakai trait &lt;code&gt;HasApiTokens&lt;/code&gt; dan relasi ke artikel:&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="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Laravel\Sanctum\HasApiTokens&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Authenticatable&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;HasApiTokens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Notifiable&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;articles&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="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;hasMany&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Article&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="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Artikel
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan make:model Article &lt;span class="nt"&gt;-m&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Edit migration:&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;up&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Schema&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'articles'&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="kt"&gt;Blueprint&lt;/span&gt; &lt;span class="nv"&gt;$table&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$table&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nv"&gt;$table&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'title'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nv"&gt;$table&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'content'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nv"&gt;$table&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;foreignId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'user_id'&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;constrained&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;cascadeOnDelete&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nv"&gt;$table&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;timestamps&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;Jalankan migrasi:&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 migrate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Di model &lt;code&gt;Article.php&lt;/code&gt;:&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;protected&lt;/span&gt; &lt;span class="nv"&gt;$fillable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'title'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'content'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'user_id'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;user&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="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;belongsTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;User&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 3: Auth Controller (Register, Login, Logout)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan make:controller Api/AuthController
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Contoh fungsi register, login, logout:&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;register&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="nv"&gt;$validated&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;validate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
        &lt;span class="s1"&gt;'name'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'required'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'email'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'required|email|unique:users'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'password'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'required|min:6'&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;=&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;create&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
        &lt;span class="s1"&gt;'name'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$validated&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$validated&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="s1"&gt;'password'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;bcrypt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$validated&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'password'&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
    &lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="nv"&gt;$token&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;createToken&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'api-token'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;plainTextToken&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;response&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;json&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'user'&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="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'token'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$token&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="mi"&gt;201&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;login&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="nv"&gt;$credentials&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;only&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="s1"&gt;'password'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&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;attempt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$credentials&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;response&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;json&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'message'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Unauthorized'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="mi"&gt;401&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;=&lt;/span&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;user&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;tokens&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nv"&gt;$token&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;createToken&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'api-token'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;plainTextToken&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;response&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;json&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'user'&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="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'token'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$token&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;logout&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="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;user&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;currentAccessToken&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;delete&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;response&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;json&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'message'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Logged out'&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;h2&gt;
  
  
  Step 4: Article Controller (CRUD)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan make:controller Api/ArticleController &lt;span class="nt"&gt;--resource&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Contoh fungsi CRUD:&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;index&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="nc"&gt;Article&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="p"&gt;}&lt;/span&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="nv"&gt;$validated&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;validate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
        &lt;span class="s1"&gt;'title'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'required'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'content'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'required'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="c1"&gt;// Ownership: artikel milik user login&lt;/span&gt;
    &lt;span class="nv"&gt;$article&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;user&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;articles&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;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$validated&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;response&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;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$article&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;201&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;show&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="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$article&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Article&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;span class="c1"&gt;// Authorization: hanya pemilik yang boleh akses&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$article&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;user_id&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;user&lt;/span&gt;&lt;span class="p"&gt;()&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;span class="nf"&gt;abort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;403&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Unauthorized'&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="nv"&gt;$article&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&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="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$article&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Article&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;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$article&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;user_id&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;user&lt;/span&gt;&lt;span class="p"&gt;()&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;span class="nf"&gt;abort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;403&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Unauthorized'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nv"&gt;$validated&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;validate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
        &lt;span class="s1"&gt;'title'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'required'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'content'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'required'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="nv"&gt;$article&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;$validated&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;response&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;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$article&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;destroy&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="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$article&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Article&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;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$article&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;user_id&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;user&lt;/span&gt;&lt;span class="p"&gt;()&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;span class="nf"&gt;abort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;403&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Unauthorized'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nv"&gt;$article&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;delete&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;response&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;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;204&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;h2&gt;
  
  
  Step 5: Route API
&lt;/h2&gt;

&lt;p&gt;Edit &lt;code&gt;routes/api.php&lt;/code&gt;:&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="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;App\Http\Controllers\Api\AuthController&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;App\Http\Controllers\Api\ArticleController&lt;/span&gt;&lt;span class="p"&gt;;&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;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'register'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;AuthController&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="s1"&gt;'register'&lt;/span&gt;&lt;span class="p"&gt;]);&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;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'login'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;AuthController&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="s1"&gt;'login'&lt;/span&gt;&lt;span class="p"&gt;]);&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;middleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'auth:sanctum'&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;group&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="nc"&gt;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'logout'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;AuthController&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="s1"&gt;'logout'&lt;/span&gt;&lt;span class="p"&gt;]);&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;apiResource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'articles'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;ArticleController&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="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 6: Testing API CRUD dengan Postman
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Endpoint&lt;/th&gt;
&lt;th&gt;Fungsi&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;/api/articles&lt;/td&gt;
&lt;td&gt;List semua artikel&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;POST&lt;/td&gt;
&lt;td&gt;/api/articles&lt;/td&gt;
&lt;td&gt;Simpan artikel baru&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;/api/articles/{id}&lt;/td&gt;
&lt;td&gt;Detail artikel&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PUT&lt;/td&gt;
&lt;td&gt;/api/articles/{id}&lt;/td&gt;
&lt;td&gt;Update artikel&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DELETE&lt;/td&gt;
&lt;td&gt;/api/articles/{id}&lt;/td&gt;
&lt;td&gt;Hapus artikel&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Jangan lupa kirim token di header:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Authorization: Bearer {token}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Contoh Response JSON
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Belajar Laravel API"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"content"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Laravel API itu powerful..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"user_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-01-11"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Kenapa API Ini Aman?
&lt;/h2&gt;

&lt;p&gt;Dengan Sanctum + &lt;code&gt;auth:sanctum&lt;/code&gt;, API ini tidak bisa diakses tanpa token. Setiap request divalidasi berdasarkan user yang login, dan hanya pemilik data yang bisa mengakses/mengubah artikelnya sendiri.&lt;/p&gt;




&lt;h2&gt;
  
  
  Kalau Mau Dipakai di Frontend
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;React: simpan token di localStorage, kirim di header Authorization setiap request&lt;/li&gt;
&lt;li&gt;Axios: gunakan interceptor untuk otomatis attach token&lt;/li&gt;
&lt;li&gt;Jangan expose token di public repo!&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Error Handling &amp;amp; Status Code
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;201 Created: Data berhasil dibuat&lt;/li&gt;
&lt;li&gt;200 OK: Data berhasil diambil/diupdate&lt;/li&gt;
&lt;li&gt;204 No Content: Data dihapus&lt;/li&gt;
&lt;li&gt;401 Unauthorized: Token salah/expired&lt;/li&gt;
&lt;li&gt;404 Not Found: Data tidak ditemukan&lt;/li&gt;
&lt;li&gt;422 Unprocessable Entity: Validasi gagal&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Common Mistake Pemula
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Lupa migrate/publish Sanctum&lt;/li&gt;
&lt;li&gt;Lupa middleware &lt;code&gt;auth:sanctum&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Token tidak dikirim di header&lt;/li&gt;
&lt;li&gt;Lupa set &lt;code&gt;Accept: application/json&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Salah endpoint (POST login, bukan GET)&lt;/li&gt;
&lt;li&gt;Salah group route (harus di dalam middleware)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Next Step
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;API Resource (response lebih rapi)&lt;/li&gt;
&lt;li&gt;Pagination &amp;amp; filtering&lt;/li&gt;
&lt;li&gt;Role &amp;amp; permission&lt;/li&gt;
&lt;li&gt;Testing dengan Thunder Client&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🚀 Yuk Diskusi &amp;amp; Share!
&lt;/h2&gt;

&lt;p&gt;Kalau kamu stuck di step tertentu, tulis di komentar ya! Share juga pengalaman kamu bikin API CRUD Laravel, atau request topik lanjutan (API Resource, pagination, dsb).&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Referensi:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://laravel.com/docs/10.x/sanctum" rel="noopener noreferrer"&gt;Laravel Sanctum Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://laravel.com/docs/10.x/eloquent-resources" rel="noopener noreferrer"&gt;Laravel API Resource&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://laravel.com/docs/10.x/controllers#resource-controllers" rel="noopener noreferrer"&gt;Laravel CRUD API&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>laravel</category>
      <category>crud</category>
      <category>api</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Laravel API Authentication dengan Sanctum</title>
      <dc:creator>Muhammad Dhiyaul Atha</dc:creator>
      <pubDate>Sun, 11 Jan 2026 14:50:53 +0000</pubDate>
      <link>https://dev.to/bangkah/laravel-api-authentication-dengan-sanctum-5fm</link>
      <guid>https://dev.to/bangkah/laravel-api-authentication-dengan-sanctum-5fm</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;"Pernah nggak, API kamu bisa diakses siapa saja tanpa login? Atau frontend sudah jadi, tapi bingung gimana cara login ke backend Laravel? Di sinilah Laravel Sanctum jadi solusi autentikasi API yang simpel dan powerful."&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Kenapa Perlu Autentikasi API?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Melindungi data dari akses sembarangan&lt;/li&gt;
&lt;li&gt;Wajib untuk aplikasi SPA, mobile, dan public API&lt;/li&gt;
&lt;li&gt;User harus login untuk akses data pribadi&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Cara Kerja Sanctum (Token Based Auth)
&lt;/h2&gt;

&lt;p&gt;Laravel Sanctum menggunakan token-based authentication. Artinya, setelah login, user akan mendapatkan token yang harus dikirim di setiap request API melalui header Authorization. Ini membuat API lebih aman dan mudah diintegrasikan dengan frontend atau mobile app.&lt;/p&gt;




&lt;h2&gt;
  
  
  Studi Kasus: API Artikel dengan Login
&lt;/h2&gt;

&lt;p&gt;Di artikel ini, kita akan membuat API Artikel yang hanya bisa diakses user yang sudah login menggunakan Laravel Sanctum.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 1: Install Sanctum
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require laravel/sanctum
php artisan vendor:publish &lt;span class="nt"&gt;--provider&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Laravel&lt;/span&gt;&lt;span class="se"&gt;\S&lt;/span&gt;&lt;span class="s2"&gt;anctum&lt;/span&gt;&lt;span class="se"&gt;\S&lt;/span&gt;&lt;span class="s2"&gt;anctumServiceProvider"&lt;/span&gt;
php artisan migrate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Command ini akan menambahkan tabel &lt;code&gt;personal_access_tokens&lt;/code&gt; yang digunakan untuk menyimpan token API user.&lt;/p&gt;

&lt;p&gt;Tambahkan middleware Sanctum di &lt;code&gt;app/Http/Kernel.php&lt;/code&gt; pada group &lt;code&gt;api&lt;/code&gt;:&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="s1"&gt;'api'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nc"&gt;\Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful&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="s1"&gt;'throttle:api'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nc"&gt;\Illuminate\Routing\Middleware\SubstituteBindings&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="p"&gt;],&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 2: Setup Model User
&lt;/h2&gt;

&lt;p&gt;Pastikan model &lt;code&gt;User&lt;/code&gt; pakai trait &lt;code&gt;HasApiTokens&lt;/code&gt;:&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="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Laravel\Sanctum\HasApiTokens&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Authenticatable&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;HasApiTokens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Notifiable&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 3: Membuat Endpoint Auth (Login, Register, Logout)
&lt;/h2&gt;

&lt;p&gt;Buat controller misal &lt;code&gt;AuthController&lt;/code&gt;:&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:controller Api/AuthController
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Contoh fungsi register, login, dan logout:&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;register&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="nv"&gt;$validated&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;validate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
        &lt;span class="s1"&gt;'name'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'required'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'email'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'required|email|unique:users'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'password'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'required|min:6'&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;=&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;create&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
        &lt;span class="s1"&gt;'name'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$validated&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$validated&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="s1"&gt;'password'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;bcrypt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$validated&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'password'&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
    &lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="nv"&gt;$token&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;createToken&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'api-token'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;plainTextToken&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;response&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;json&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'user'&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="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'token'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$token&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="mi"&gt;201&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;login&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="nv"&gt;$credentials&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;only&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="s1"&gt;'password'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&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;attempt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$credentials&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;response&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;json&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'message'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Unauthorized'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="mi"&gt;401&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;=&lt;/span&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;user&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;tokens&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// hapus token lama, 1 user = 1 token aktif&lt;/span&gt;
    &lt;span class="nv"&gt;$token&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;createToken&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'api-token'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;plainTextToken&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;response&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;json&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'user'&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="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'token'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$token&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;logout&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="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;user&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;currentAccessToken&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="c1"&gt;// Logout akan menghapus token aktif sehingga request berikutnya akan ditolak.&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;response&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;json&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'message'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Logged out'&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;h2&gt;
  
  
  Step 4: Route API Auth &amp;amp; Proteksi Artikel
&lt;/h2&gt;

&lt;p&gt;Edit &lt;code&gt;routes/api.php&lt;/code&gt;:&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;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'register'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;AuthController&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="s1"&gt;'register'&lt;/span&gt;&lt;span class="p"&gt;]);&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;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'login'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;AuthController&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="s1"&gt;'login'&lt;/span&gt;&lt;span class="p"&gt;]);&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;middleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'auth:sanctum'&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;group&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="nc"&gt;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'logout'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;AuthController&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="s1"&gt;'logout'&lt;/span&gt;&lt;span class="p"&gt;]);&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;apiResource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'articles'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;ArticleController&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="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 5: Testing API Auth dengan Postman
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Register
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;POST /api/register
Content-Type: application/json
{
  "name": "Atha",
  "email": "atha@mail.com",
  "password": "password123"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Login
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;POST /api/login
Content-Type: application/json
{
  "email": "atha@mail.com",
  "password": "password123"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Atha"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"token"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1|longapitoken..."&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Akses Artikel (dengan token)
&lt;/h3&gt;

&lt;p&gt;Tambahkan header:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Authorization: Bearer 1|longapitoken...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET /api/articles
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Error Handling &amp;amp; Status Code
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;201 Created: Register sukses&lt;/li&gt;
&lt;li&gt;200 OK: Login sukses, data diambil&lt;/li&gt;
&lt;li&gt;401 Unauthorized: Token salah/expired&lt;/li&gt;
&lt;li&gt;422 Unprocessable Entity: Validasi gagal&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Common Mistake Pemula
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Lupa publish/migrate Sanctum&lt;/li&gt;
&lt;li&gt;Lupa tambahkan middleware &lt;code&gt;auth:sanctum&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Token tidak dikirim di header&lt;/li&gt;
&lt;li&gt;Lupa set &lt;code&gt;Accept: application/json&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Salah endpoint (POST login, bukan GET)&lt;/li&gt;
&lt;li&gt;Salah group route (harus di dalam middleware)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Next Step
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Refresh token&lt;/li&gt;
&lt;li&gt;Role/permission&lt;/li&gt;
&lt;li&gt;API Resource&lt;/li&gt;
&lt;li&gt;Testing dengan Thunder Client&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🚀 Yuk Diskusi &amp;amp; Share!
&lt;/h2&gt;

&lt;p&gt;Kalau kamu stuck di step tertentu, tulis di komentar ya! Share juga pengalaman kamu pakai Sanctum, atau request topik lanjutan (refresh token, role, dsb).&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Referensi:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://laravel.com/docs/10.x/sanctum" rel="noopener noreferrer"&gt;Laravel Sanctum Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://laravel.com/docs/10.x/authentication" rel="noopener noreferrer"&gt;Laravel API Authentication&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>laravel</category>
      <category>api</category>
      <category>authentication</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
