| name | awcms-mini-deploy |
| description | Pilih dan jalankan profil deployment AWCMS-Mini (development/staging/production/offline-LAN). Gunakan saat menyiapkan deployment baru, memutuskan LAN-first vs registry-based, atau deploy ke Coolify. Sesuai doc 18 dan deployment-profiles.md/deploy-coolify.md. |
AWCMS-Mini — Deployment Profile & Execution
Ikuti docs/awcms-mini/deployment-profiles.md (peta profil ke berkas
deploy/*) dan docs/awcms-mini/deploy-coolify.md (khusus Coolify).
Pilih jalur
flowchart TD
A{Topologi target?} -->|LAN-first satu server,\noperator git pull in-place| B[docker-compose.yml]
A -->|Registry/CI-push,\norkestrator container| C[Dockerfile.production]
C --> D{Orkestrator?}
D -->|Docker Compose langsung| G[docker-compose.prod.yml]
D -->|Coolify| E[deploy-coolify.md]
D -->|k8s/ECS/lain| F[Adaptasi pola Dockerfile.production yang sama]
docker-compose.yml tetap jalur yang direkomendasikan untuk
LAN-first/offline satu server — jangan beralih ke Dockerfile.production
kecuali orkestrator memang mengharapkan image siap-pakai (build-saat-startup
tidak diinginkan). Untuk registry-based via Compose (bukan Coolify/k8s),
pakai docker-compose.prod.yml (Issue #682) — standalone, bukan override
docker-compose.yml.
Container hardening (Issue #682, berlaku di kedua compose file):
db/pgbouncer tidak publish port host secara default (salin
docker-compose.override.yml.example untuk akses lokal opsional);
cap_drop: [ALL] di semua service (db dapat cap_add minimal untuk
entrypoint-nya sendiri); image Bun/Postgres/PgBouncer dipin ke versi
eksplisit, bukan tag mengambang; healthcheck di db/app (migrate
one-shot dan pgbouncer opsional sengaja tanpa healthcheck — lihat
komentar masing-masing service);
docker-compose.prod.yml's app jalan read_only: true (image
registry-based tidak pernah menulis ke filesystem-nya sendiri saat
runtime). PgBouncer's deploy/pgbouncer/pgbouncer.ini.example memakai
auth_type = scram-sha-256 (bukan md5) — lihat berkas itu untuk
perintah generate userlist.txt dari pg_authid. CI
(.github/workflows/ci.yml) menjalankan docker compose config -q untuk
kedua compose file di setiap PR — jangan biarkan salah satu file punya
syntax error/env var yang tidak resolve sampai lolos ke deploy.
Edge cache Varnish (#938, opsional)
deploy/varnish/default.vcl + service cache di docker-compose.prod.yml.
Aturannya default deny — sebuah route hanya di-cache bila aplikasi secara
eksplisit menandainya cacheable. Detail lengkap:
docs/awcms-mini/http-cache-varnish.md.
Yang mudah salah saat deploy:
- Edge adalah satu-satunya ingress.
docker-compose.prod.yml sengaja tidak
lagi mem-publish port 4321 milik app. Jangan "sekalian" mem-publish
keduanya untuk debugging — permintaan yang bisa melewati edge membuat cache
tampak benar saat diuji dan bocor saat produksi.
- Jalankan
bun run varnish:cache:check setiap kali default.vcl berubah
(butuh Docker; sengaja BUKAN bagian bun run check). varnishd -C hanya
membuktikan berkasnya parse, bukan bahwa cache-nya benar-benar mengisolasi.
- Bila Varnish dijalankan sebagai sidecar di luar compose (mis. di belakang
Traefik/Coolify): VCL tidak boleh di-bind-mount dari
/tmp (dikosongkan
saat boot ⇒ varnishd gagal start ⇒ domain mati), container butuh
--health-cmd "varnishadm ping" karena image-nya tidak membawa HEALTHCHECK,
dan plafon memori harus di ATAS ukuran -s malloc,<size>. Ketiganya sudah
pernah salah pada deployment nyata — lihat §"Menjalankan Varnish sebagai
sidecar di luar compose" pada doc di atas.
Command inti (semua profil)
bun run config:validate
bun run db:migrate
bun run production:preflight
Checklist per topologi
LAN-first (docker-compose.yml): export APP_UID=$(id -u) APP_GID=$(id -g)
sebelum docker compose up --build (wajib — tanpanya container jadi root
dan menulis node_modules//dist/ sebagai root di bind mount host);
health check curl http://localhost:4321/api/v1/health.
Registry-based/Coolify (Dockerfile.production): migration one-shot
terpisah (image tidak menjalankannya — role runtime least-privilege
tidak punya hak DDL); role app selalu awcms_mini_app atau setara, tidak
pernah superuser; database tidak perlu public port bila app+DB satu
internal network; secret selalu via env var/orkestrator, tidak pernah
dibakar ke image (.dockerignore mengecualikan .env).
Multi-aplikasi dalam satu VPS/Coolify: setiap aplikasi wajib
domain/secret/database (atau minimal schema+role) terpisah — jangan reuse
AUTH_JWT_SECRET/HMAC/kredensial R2 antar aplikasi; lihat
deploy-coolify.md §Opsi PostgreSQL untuk perbandingan satu cluster vs
satu container per aplikasi vs managed database eksternal.
Model dua-peran basis data (wajib di semua profil)
Migrasi = role privileged (DDL/GRANT). Runtime app = awcms_mini_app
least-privilege, FORCE ROW LEVEL SECURITY ditegakkan untuknya. Jangan
pernah menjalankan aplikasi sebagai superuser/owner — bun run security:readiness memblokir go-live bila terdeteksi.
Credential otomasi (agent-cred)
Kalau langkah deploy ini butuh token API Coolify/Cloudflare atau kredensial
server secara interaktif (dijalankan agent/operator dalam satu sesi kerja,
bukan job cron), ambil lewat agent-cred get <service> <field> (isi dulu
dengan agent-cred set <service> bila belum ada) — jangan read -s ad-hoc
atau credential inline baru. TTL cache 3 jam. Detail: repo personal-coding
docs/sop-agent-cred-credential-cache.md. Job cron/systemd tetap pakai
env var/secret file seperti biasa (lihat deploy/backup/README.md).
Rollback
Image immutable (Pola registry) → redeploy tag sebelumnya. Migration
caution: rollback image tidak membatalkan migrasi skema yang sudah
diterapkan — uji migrasi backward-compatible (expand-first) sebelum
deploy, atau siapkan restore dari backup (deploy/backup/restore-postgres.sh)
sebagai jalur rollback skema.
Output
Laporan: profil dipilih + alasan, checklist yang terpenuhi, health check
hasil, dan (bila registry-based) rencana rollback singkat.