Merapikan fondasi konfigurasi Backstage: memahami hirarki app-config, memvalidasi schema dengan @backstage/config-lint, memakai nested config, substitusi environment variable, dan dynamic config, serta mengelola secrets berbasis environment dan integrasi dengan Vault tanpa pernah menaruh kredensial di kode.

Di episode 8, kalian mengaktifkan auth provider dan mengisi clientId serta clientSecret di app-config.yaml. Episode 9 membahas lapisan yang mengatur semua itu: konfigurasi. Saat Backstage tumbuh, file konfigurasi menjadi tempat yang paling sering dimasuki kesalahan — nilai yang salah ketik, rahasia yang lolos ke repository, atau environment yang memakai setting berbeda dari yang dibayangkan. Kali ini kita merapikannya: bagaimana app-config divalidasi, disusun bertingkat, disubstitusi dari environment, dan bagaimana rahasia dijaga lewat environment variable dan Vault.
Backstage membaca konfigurasi dari lebih dari satu file. File app-config.yaml adalah dasar yang sama untuk semua environment, lalu file tambahan di-merge di atasnya — nilai yang muncul belakangan menimpa nilai sebelumnya. Pembagian ini menjaga satu konfigurasi dasar, dengan penyesuaian per environment.
| Level | Contoh file | Tujuan | Berada di Git? |
|---|---|---|---|
| Dasar | app-config.yaml | Nilai yang sama untuk semua environment | Ya |
| Lokal | app-config.local.yaml | Override untuk pengembangan di mesin developer | Tidak (gitignored) |
| Produksi | app-config.production.yaml | Override khusus environment produksi | Ya |
| Rahasia | file .env atau secret manager | Kredensial dan nilai sensitif | Tidak pernah |
Pola ini menjelaskan kenapa app-config.local.yaml tidak pernah masuk git: di situlah developer menyimpan nilai lokal mereka. Produksi memakai app-config.production.yaml yang di-merge di atas file dasar saat aplikasi dijalankan.
Backstage menyediakan paket @backstage/config-lint untuk memvalidasi konfigurasi. Validasi ini memeriksa struktur config terhadap schema yang didefinisikan, sehingga typo, field yang tidak dikenal, atau tipe data yang salah terdeteksi sebelum aplikasi berjalan. Aturan mainnya: schema config didefinisikan di file app-config.schema.json, dan setiap field yang dipakai di app-config.yaml harus cocok dengannya.
yarn backstage-cli config:lintconfig:lint membaca app-config.yaml beserta file override, membandingkannya dengan app-config.schema.json, dan melaporkan ketidaksesuaian. Kalian bisa menambahkannya ke pipeline CI, sehingga setiap pull request yang merusak konfigurasi ditolak lebih dulu.
{
"backend": {
"baseUrl": {
"type": "string",
"description": "URL dasar dari instance Backstage"
}
},
"custom": {
"featureFlag": {
"type": "boolean",
"default": false
}
}
}Schema di atas menyatakan bahwa backend.baseUrl harus berupa string dan custom.featureFlag berupa boolean. Field di luar schema akan ditandai sebagai tidak dikenal — sinyal bahwa ada sesuatu yang salah eja atau belum dideklarasikan.
Konfigurasi Backstage disusun berjenjang (nested). Blok seperti backend, auth, catalog, dan techdocs masing-masing berisi sub-blok, dan plugin mengakses nilai lewat jalur titik seperti backend.baseUrl. Menjaga konfigurasi tetap berjenjang membuat file lebih mudah dibaca dan menghindari tabrakan nama antar plugin.
Nilai konfigurasi bisa diambil dari environment variable dengan sintaks substitusi di dalam file config. Sintaksnya hanya berlaku di dalam nilai string, dan saat config dimuat, nilai variabel menggantikannya. Inilah cara utama memasok nilai yang berbeda per environment tanpa mengubah file.
backend:
baseUrl: ${BACKSTAGE_BASE_URL}
listen:
port: 7007
auth:
providers:
github:
production:
clientId: ${AUTH_GITHUB_CLIENT_ID}
clientSecret: ${AUTH_GITHUB_CLIENT_SECRET}Saat dijalankan, placeholder BACKSTAGE_BASE_URL diganti dengan nilai environment variable BACKSTAGE_BASE_URL. Jika variabel tidak tersedia, proses akan memperingatkan — mekanisme ini membuat konfigurasi aman untuk di-commit karena tidak pernah memuat nilai rahasia itu sendiri.
Tip
Pisahkan kredensial dari konfigurasi struktural. app-config.yaml memuat nilai publik seperti backend.baseUrl dan alamat penyedia; app-config.local.yaml atau environment variable memuat kredensial. Dengan pola ini, satu file bisa di-review publik, sementara rahasia hidup di tempat yang tidak pernah menyentuh git.
Backstage juga mendukung dynamic config — mekanisme eksperimental untuk mengubah sebagian konfigurasi saat aplikasi berjalan tanpa build ulang. Sebagian plugin dapat membaca konfigurasi dinamis yang dimuat dari file khusus dan diperbarui lewat API, sehingga penyesuaian kecil tidak menunggu siklus deploy.
Pola pemakaiannya: nilai yang berubah sering (misalnya flag fitur atau daftar yang panjang) disimpan di dynamic config, sementara nilai yang stabil tetap di app-config.yaml. Gunakan dynamic config dengan hati-hati — menempatkan rahasia di dalamnya justru mengurangi manfaat kontrol lingkungan yang sudah kalian bangun.
Cara paling dasar dan paling penting untuk menyimpan rahasia Backstage adalah environment variable. clientId, clientSecret, token Vault, dan kunci akses penyedia cloud semuanya disuplai lewat environment, bukan ditulis di file config. Nilai-nilai itu biasanya didefinisikan di deployment platform, file .env lokal yang ter-gitignore, atau secret manager pada Kubernetes.
export AUTH_GITHUB_CLIENT_ID=Ov23li-example
export AUTH_GITHUB_CLIENT_SECRET=secretexample
export VAULT_TOKEN=hv-token-example
yarn devSetelah environment variable tersedia, app-config.yaml tinggal menyebutnya lewat substitusi environment seperti AUTH_GITHUB_CLIENT_ID. Kredensial tidak pernah tertulis di file yang masuk git, dan setiap environment memakai nilainya sendiri.
Ketika jumlah rahasia sudah banyak, environment variable saja mulai sulit dikelola. Vault menawarkan tempat terpusat: rahasia disimpan di Vault, dan Backstage mengambilnya lewat plugin backend Vault. Backend plugin memuat rahasia dari path tertentu dan menyediakannya untuk plugin lain seperti scaffolder atau catalog, berdasarkan konfigurasi address dan token.
vault:
baseUrl: ${VAULT_BASE_URL}
token: ${VAULT_TOKEN}
kvVersion: 2Rahasia tetap mengalir lewat environment variable (token Vault), tetapi isi rahasia itu sendiri disimpan dan dikelola di Vault — termasuk rotasi, audit log, dan kontrol akses. Ini langkah besar dari menulis kredensial di file menuju penyimpanan terpusat yang bisa diaudit.
Important
Aturan yang tidak bisa ditawar: jangan pernah hardcode credentials di kode atau di file konfigurasi yang masuk git. Jika sebuah rahasia pernah ter-commit, anggap bocor — putar nilainya. Gunakan environment variable untuk nilai dasar dan Vault untuk skala besar; dengan begitu rotasi rahasia cukup mengganti nilai di satu tempat.
Pada episode 9 ini, kalian merapikan fondasi konfigurasi: hirarki app-config.yaml dengan file override lokal dan produksi, validasi schema memakai @backstage/config-lint, nested config dengan jalur titik, substitusi environment variable, dynamic config untuk nilai yang berubah di runtime, serta pengelolaan secrets berbasis environment dan integrasi Vault tanpa pernah menaruh kredensial di kode.
Inti yang harus dibawa pulang:
config:lint menangkap typo dan tipe salah di CI, bukan di produksi.app-config.yaml tetap aman untuk di-commit.Di episode 10 berikutnya, kita kembali ke Scaffolder dengan level yang lebih tinggi: Scaffolder Advanced & Custom Actions — workflow bertingkat dengan logika kondisional, output berupa link dan entity, permission untuk template, serta action kustom yang memprovisikan resource cloud dari tooling internal.