Checklist first-day di Chapter Linux Cloud Servers hanya lima menit, tetapi lima menit itu harus diulang untuk setiap server baru — dan langkah yang diulang manual pasti ada yang terlewat. cloud-init memindahkan pekerjaan itu ke dalam boot pertama instance: kita menyerahkan sebuah berkas resep bernama user-data, lalu mesin menghidupkan dirinya sampai siap pakai tanpa satu pun ketikan admin. Alat ini menjadi standar de-facto provisioning awal di seluruh cloud besar dan hadir di image Debian, Ubuntu, dan Fedora secara bawaan. Karena cloud-init hanya aktif di mesin yang benar-benar baru dibuat, container latihan ini tidak menjalankannya — jadi kita tulis berkas user-data sungguhan, lalu membedah dan memeriksa strukturnya dengan tool yang ada di terminal.

Dari Mana cloud-init Tahu Harus Berbuat Apa #

Saat instance menyala pertama kali, service cloud-init bertanya ke datasource — endpoint metadata internal milik penyedia yang bisa diakses dari dalam mesin. Datasource menjawab beberapa hal: identitas instance (ID, hostname, alamat IP), kunci SSH publik yang kita pilih saat pembuatan, dan user-data yang kita tempel. Dengan kata lain, seluruh “formulir pembuatan instance” dari chapter sebelumnya sampai ke server melalui satu jalur ini.

Prosesnya berjalan bertahap dalam tiga fase: init menyiapkan jaringan dan hostname, config membuat user serta memasang paket, dan final menjalankan runcmd setelah service lain siap. Fase-fase ini tercatat di log cloud-init-output.log, dan tiap penyedia hanya menyediakan datasource yang sesuai dengan arsitekturnya — itulah sebabnya berkas user-data yang sama bisa dipakai lintas penyedia tanpa perubahan.

Berkas user-data bisa berupa shell script (#!/bin/bash di baris pertama), tetapi bentuk yang lebih terstruktur adalah #cloud-config: YAML dengan bagian-bagian bermakna yang dipahami cloud-init secara native. Bundle chapter ini membawa berkas user-data yang mencakup lima bagian paling sering dipakai:

bash
cat user-data

Output yang Dihasilkan:

text
#cloud-config
hostname: web-jakarta
users:
  - name: budi
    sudo: ALL=(ALL) NOPASSWD:ALL
    shell: /bin/bash
    ssh-authorized-keys:
      - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIContohKunciPublikBudi
packages:
  - nginx
  - fail2ban
write_files:
  - path: /etc/ssh/sshd_config.d/01-hardening.conf
    content: |
      PasswordAuthentication no
      PermitRootLogin no
runcmd:
  - [ systemctl, enable, --now, nginx ]
  - [ ufw, allow, 22,80,443/tcp ]

Mari kita bedah bagian demi bagiannya:

  1. Baris 1 (#cloud-config): penanda format — baris pertama inilah yang memberi tahu cloud-init bahwa isi berkas adalah cloud-config, bukan shell script.
  2. hostname: web-jakarta: nama mesin dipasang sebelum service lain berjalan, jadi prompt shell dan log sudah benar sejak boot pertama.
  3. users:: daftar user yang dibuat — name, aturan sudo, shell, dan ssh-authorized-keys. Perhatikan bahwa yang disuntik adalah kunci publik, bukan password; login password memang sengaja tidak dipakai.
  4. packages:: paket yang dipasang lewat package manager distro; di Debian dan Ubuntu pemanggilannya setara apt install dari Chapter Package Manager Concepts .
  5. write_files:: menulis berkas ke disk pada fase config — di sini drop-in konfigurasi sshd yang mematikan login password, meniru langkah utama Chapter SSH Hardening .
  6. runcmd:: daftar perintah yang dijalankan di fase terakhir, setelah user dan paket siap — memicu service nginx dan membuka port di firewall.

Satu berkas ini menggantikan seluruh rangkaian perintah manual dari checklist first-day: server lahir dengan user admin, paket terpasang, SSH terkunci, dan service berjalan.

Pemeriksaan Struktur Sebelum Dipasang #

Kesalahan ketik sekecil apa pun membuat provisioning gagal di tengah jalan — user terlanjur dibuat tetapi paket tidak terpasang. Di mesin sungguhan, cloud-init schema --config-file user-data memvalidasi berkas sebelum dipakai. Versi latihan kita memakai tool terminal dasar untuk memeriksa bagian-bagian penting:

bash
echo "-- baris pertama (penanda format):"
head -1 user-data
echo "-- bagian tingkat atas yang dikenali:"
grep -E '^[a-z_]+:' user-data
echo "-- jumlah paket yang akan dipasang:"
sed -n '/^packages:/,/^write_files:/p' user-data | grep -c '^  - '
echo "-- user pertama beserta shell-nya:"
awk '/^users:/{f=1;next} f && /^  - name:/{print $3; exit}' user-data
awk '/shell:/{print $2; exit}' user-data

Output yang Dihasilkan:

text
-- baris pertama (penanda format):
#cloud-config
-- bagian tingkat atas yang dikenali:
hostname: web-jakarta
users:
packages:
write_files:
runcmd:
-- jumlah paket yang akan dipasang:
2
-- user pertama beserta shell-nya:
budi
/bin/bash

Mari kita bedah perintahnya baris demi baris:

  1. head -1 user-data: memastikan penanda #cloud-config ada di baris pertama — tanpa penanda ini cloud-init menolak memproses YAML.
  2. grep -E '^[a-z_]+:': anchor ^ membuat pola hanya cocok dengan kunci di kolom nol, sehingga kunci bersarang yang menjorok dua spasi tidak ikut terhitung.
  3. sed -n '/^packages:/,/^write_files:/p': mencetak jangkauan baris dari bagian packages: sampai write_files:; grep -c '^ - ' menghitung entrinya — dua paket.
  4. Dua awk: yang pertama menyalakan flag setelah baris users: lalu mencetak argumen pertama entri - name:; yang kedua mengambil nilai shell: pertama di berkas — keduanya pola mawk yang portabel.

Sekali Jalan atau Tiap Boot #

Tidak semua bagian user-data dijalankan setiap boot. Modul cloud-init punya frequency: per-instance (sekali seumur hidup instance — default untuk users, packages, runcmd), per-once (sekali per mesin, tidak diulang walau instance dibuat ulang dari snapshot), dan per-always (setiap boot). Akibatnya, menjalankan ulang user-data pada mesin yang sama tidak akan memasang paket dua kali — perilaku yang membuat cloud-init aman diulang.

Untuk memantau hasilnya, dua perintah ini menjadi rutinitas setelah instance menyala. Berikut contoh tampilan status di mesin yang selesai provisioning:

console
$ cloud-init status --long
status: done
last update: Tue, 10 Feb 2026 08:14:02 +0000

Status done berarti seluruh fase selesai; running berarti masih bekerja, dan bila macet di situ, rincian kesalahan ada di /var/log/cloud-init-output.log. Perintah cloud-init status --wait memblokir sampai selesai — berguna di skrip yang harus menunggu server benar-benar siap sebelum melanjutkan.

cloud-init menuntaskan satu server yang sudah lahir. Namun sebelum provisioning bisa berjalan, instance itu sendiri — beserta volume, jaringan, dan DNS-nya — harus diciptakan lebih dulu, dan pekerjaan menciptakan infrastruktur itulah yang paling menyakitkan bila dilakukan manual berulang. Chapter berikutnya, Infrastructure Automation , memindahkan pembuatan infrastruktur itu ke dalam definisi kode.

Referensi lanjut: situs cloud-init untuk dokumentasi format cloud-config dan daftar datasource yang didukung.