Kliniktech Knowledge Base
Infrastructure Runbook

HA 3 Server, RADIUS, dan Domain Tenant Subscriber.

Panduan ini dipakai untuk operasi tiga node: app, database Galera, FreeRADIUS, Cloudflare Load Balancer, dan provisioning domain/mailbox tenant. Tenant master `kliniktech` tetap di `apps.ion.net.id`; subscriber memakai `{slug}.kliniktech.com`.

Node dan Peran

Semua node menjalankan app, database, dan RADIUS setelah fase cutover disetujui.

server1

151.244.238.67

Node production awal. Jangan bootstrap ulang database tanpa backup dan approval maintenance.

server2

151.244.238.77

Node HA app/RADIUS/DB kedua. Health langsung: `http://151.244.238.77/api/health`.

server3

103.172.18.79

Node HA app/RADIUS/DB ketiga. Wajib Ubuntu 24.04 dan runtime sama sebelum masuk pool.

Guardrail Production

Langkah berikut tidak boleh dijalankan diam-diam.

  • DNS production, Cloudflare LB enable, Galera bootstrap, dan push config RADIUS butuh approval eksplisit untuk record/node yang akan diubah.
  • `apps.ion.net.id` tetap untuk tenant master `kliniktech`; jangan diarahkan ke flow subscriber.
  • `kliniktech.kliniktech.com` tidak boleh dipakai. Jika muncul, redirect/operator harus memakai `apps.ion.net.id`.
  • Uji satu tenant subscriber terlebih dahulu, baru aktifkan seluruh subscriber setelah health app, DB, dan RADIUS hijau.

Checklist App Node

Dipakai sebelum node dimasukkan ke Cloudflare pool.

  1. Pastikan PHP minimal 8.4, Nginx, Redis, Composer, dan ekstensi Laravel aktif.
  2. Sinkronkan `/var/www/kliniktech` dari server1 ke node baru, kecuali cache/session/log runtime yang tidak perlu.
  3. Pasang vhost HTTP direct-IP untuk health check. SSL/LB production dikerjakan setelah DNS approval.
  4. Jalankan `php -l routes/api.php` dan `php artisan route:list --path=health`.
  5. Endpoint `GET /api/health` harus `200` setelah DB lokal Galera siap. Jika DB belum siap, endpoint mengembalikan `503 database_unreachable` dengan pesan jelas.
  6. Aktifkan queue worker dan scheduler hanya setelah DB lokal siap agar tidak spam error.

Galera Runbook

Migrasi dari MySQL standalone ke MariaDB Galera harus dilakukan saat maintenance window.

  1. Ambil backup logical dan salin `.env`, config web, dan config RADIUS server1.
  2. Stop traffic subscriber menuju node yang akan dimigrasi.
  3. Bangun Galera dari server1 sebagai seed hanya setelah backup diverifikasi.
  4. Join server2 dan server3 satu per satu. Validasi `wsrep_cluster_size=3`, `wsrep_ready=ON`, dan test write/read.
  5. Set Laravel `DB_HOST=127.0.0.1` di setiap app node agar app memakai Galera lokal.
  6. Maintenance satu node dilakukan dengan drain traffic, desync/stop service, patch, rejoin, lalu cek cluster size kembali 3.

FreeRADIUS HA

Semua NAS/MikroTik harus punya tiga target RADIUS.

  • Primary: `151.244.238.67`, secondary: `151.244.238.77`, tertiary: `103.172.18.79`.
  • SQL backend RADIUS mengarah ke Galera lokal masing-masing node.
  • Shared secret harus konsisten dan disimpan sebagai secret, bukan di dokumentasi publik.
  • Health minimal: service running, SQL reachable, test auth/accounting, dan paket UDP 1812/1813 reachable dari jaringan NAS.

Tenant Domain dan Mailbox

Provisioning subscriber otomatis memakai Cloudflare dan Virtualmin.

  • Subscriber domain default: `{slug}.kliniktech.com`.
  • Mailbox default: `{slug}@kliniktech.com`.
  • Endpoint guarded: `POST /api/platform/tenants/{tenant}/provisioning/subscriber-domain/provision`.
  • Konfirmasi wajib: `PROVISION SUBSCRIBER DOMAIN`, plus FQDN persis yang akan dibuat.
  • Credential Cloudflare dan Virtualmin harus disimpan di Platform Provisioning Credential, dengan production unlock aktif hanya saat eksekusi.

Monitoring

Alert wajib sebelum traffic production diarahkan ke pool.

App dan Queue

Monitor `GET /api/health`, status `php-fpm`, Nginx, queue worker, scheduler per menit, disk, CPU, memory, dan SSL expiry.

DB dan RADIUS

Monitor `wsrep_cluster_size`, `wsrep_ready`, flow control Galera, FreeRADIUS service, auth failure rate, dan reachability UDP 1812/1813.