License Server — panduan operator

Versi 0.1.15 · Kembali ke License management

Tampilan memakai teks isi 16 px, tabel 14 px, judul lebih besar, dan formulir responsif. Tabel tetap dapat digeser horizontal pada layar kecil tanpa memperkecil teks.

Pendaftaran customer dan penerbitan lisensi

  1. Admin masuk ke License Server. Sebelum Google dikonfigurasi, gunakan administrator token yang sudah ada.
  2. Isi nama lengkap, email, nama PIC, nama perusahaan, alamat perusahaan, jumlah seat, dan catatan opsional. Untuk menambah lisensi customer yang sama, cari dan pilih profil customer yang sudah terdaftar.
  3. Klik Generate activation code. Salin kode saat ditampilkan. Kode disimpan sebagai hash sehingga tidak bisa ditampilkan ulang. Jika kode hilang, revoke kode yang belum digunakan lalu buat penggantinya.
  4. Admin customer memasukkan kode di Console → Settings → License. Nama perusahaan tampil sebagai organisasi; Console instance terhubung otomatis setelah aktivasi.
  5. Install Agent dengan alamat Console lalu setujui perangkat dari Console. Setiap identitas Agent aktif memakai satu seat. Lihat manual Agent.

Data kontak customer disimpan pada License Server dan tidak dimasukkan ke entitlement yang diterima Console. Lisensi lama tetap berlaku; detail profil lama yang belum direkam ditandai sebagai data legacy.

Menambah seat

Pilih customer yang sama, buat kode baru dengan total kapasitas yang diinginkan, lalu ganti lisensi pada Console. Contoh: lisensi 20 seat diganti 30 seat berarti kapasitas menjadi 30, bukan 50. Penggantian atomik memensiunkan kode sebelumnya, mempertahankan identitas Agent, dan menolak penurunan kapasitas. Retry penggantian yang sama mengembalikan entitlement yang sama.

Subscription tahunan

Lisensi baru adalah subscription 12 bulan. Masa aktif mulai saat Console mengaktifkan kode, bukan saat kode diterbitkan. Kode yang belum diaktifkan belum memakai masa berlangganan. Tidak ada grace period; pada waktu kedaluwarsa yang ditandatangani, Console menandai lisensi expired dan menahan operasi yang memerlukan entitlement.

Renewal sebelum masa berakhir menambah 12 bulan dari tanggal expiry lama, sehingga sisa masa yang sudah dibayar tidak hilang. Renewal setelah expiry mulai pada tanggal aktivasi baru. Tanggal dan status renewal tampil di daftar lisensi; filter tersedia untuk yang akan berakhir dalam 30 hari dan yang sudah expired. Lisensi yang diterbitkan sebelum pembaruan ini tetap tanpa tanggal kedaluwarsa dan tidak berubah.

Mengatur algoritma harga checkout

Owner mengatur harga dari panel Annual seat pricing di License Server. Portal pricing tidak memiliki pengaturan terpisah; slider meminta estimasi langsung dari License Server, sedangkan Checkout memakai angka yang sama. Setiap order menyimpan harga dan revisi algoritma saat Checkout dibuat, jadi perubahan selanjutnya hanya memengaruhi order baru.

Rumus awal tahunan memakai harga dasar S$14.40 per seat dan harga bertingkat graduated. Rasio band awal adalah 100%, 90.28%, 83.33%, 76.39%, 69.44%, dan 65.97% untuk batas 25, 50, 100, 250, 500, dan 1,000 seat. Harga satu seat di band dihitung dari harga dasar dikali rasio; pembulatan dilakukan ke sen terdekat. Setiap band hanya menghitung seat yang masuk band itu.

Harga Checkout juga menambahkan allowance variabel Stripe 3.9%, uplift kampanye 0.8%, dan biaya tetap S$0.50. Total dihitung dengan gross-up agar persentase berlaku pada jumlah yang dibayar. Uplift kampanye adalah bagian dari harga dan bukan donasi otomatis ke Stripe Climate. Pajak tidak termasuk rumus ini; bila pajak wajib dipungut, jumlahnya ditampilkan terpisah saat Checkout.

Ubah harga dasar, rasio setiap band, allowance Stripe, uplift kampanye, atau biaya tetap, lalu tinjau harga per seat yang dihitung di tabel sebelum menyimpan. Rasio harus berurutan menurun dan band pertama tetap 100%. Panel hanya dapat diubah oleh Owner dan perubahan masuk ke Recent activity.

Receipt Stripe dan email kode

PortGuard mengirim email kode aktivasi. Untuk transaksi live yang terkonfirmasi, License Server meminta Stripe mengirim receipt pembayaran tersendiri ke alamat email yang dimasukkan saat Checkout. Receipt Stripe memuat total aktual yang dibayar; receipt bukan email aktivasi. Stripe tidak mengirim receipt untuk transaksi test mode. Jika pengiriman receipt live gagal, License Server mencoba ulang otomatis.

Daftar dan aktivitas

Licenses dan Recent activity memiliki tombol Previous/Next terpisah dan pilihan 10, 25, atau 50 baris. Cari nama perusahaan/Console instance dan filter status. Tombol View customer menampilkan profil lengkap, seat, dan Console terkait. Ringkasan atas tetap menghitung seluruh lisensi, tidak mengikuti filter.

Licensed seat capacity adalah total kapasitas lisensi yang sudah diaktifkan. Penggunaan seat dan perangkat online berada di Console. Revocation mencegah aktivasi berikutnya; entitlement offline yang sudah dimiliki Console tidak langsung ditarik dari jarak jauh.

Arsip dan hapus lisensi testing

Tampilan awal Current · Issued & Active menyembunyikan lisensi revoked. Setiap lisensi yang di-revoke, termasuk lisensi lama yang diganti saat penambahan seat, otomatis masuk ke Archive · Revoked. Pilih filter tersebut untuk melihat arsip; pilih All licenses untuk menampilkan semuanya.

Untuk menghapus lisensi testing, buka Archive · Revoked, pilih Delete pada lisensi yang dimaksud, periksa nama perusahaan, seat dan ID, centang persetujuan lalu pilih Delete permanently. Hanya lisensi revoked yang dapat dihapus. Penghapusan permanen menghapus record lisensi dari database; profil customer dan audit tetap tersimpan. Tidak ada penghapusan massal otomatis. Kode yang dihapus tidak dapat diaktifkan lagi. Entitlement offline yang sudah dipegang Console tidak otomatis ditarik. Gunakan backup bila record mungkin perlu dipulihkan.

User management

Login menggunakan Google Workspace yang sama. Owner dapat menambahkan pengguna berdasarkan alamat email perusahaan dan memilih role: Owner mengelola pengguna, Admin mengelola customer/lisensi, dan Read-only hanya melihat data. Pengguna baru bisa masuk setelah memilih akun Google yang cocok. Menonaktifkan pengguna memutus aksesnya pada request berikutnya; audit tetap mencatat perubahan. Role Owner awal berasal dari daftar bootstrap LICENSING_GOOGLE_ADMIN_EMAILS. Minimal satu Owner aktif harus dipertahankan.

Backup terenkripsi dan pemulihan server

Di halaman admin, buka Backup & restore. Masukkan password minimal 12 karakter, ulangi password, lalu pilih Download encrypted backup. Simpan file .pgbackup di penyimpanan terpisah dari server dan simpan password secara terpisah. Tidak ada mekanisme untuk memulihkan password backup yang hilang.

Arsip mencakup database SQLite yang konsisten, profil customer, lisensi, riwayat, administrator token, dan private signing key Ed25519. Sesi login tidak disertakan. Enkripsi menggunakan AES-256-GCM dengan salt acak 16 byte, nonce acak 12 byte, dan scrypt N=32768/r=8/p=1. Perubahan isi atau password salah akan ditolak. Batas arsip 100 MiB.

Kunci penandatangan harus ikut dipulihkan: Console yang sudah terpasang mempercayai public key pasangannya. Restore database saja dengan kunci baru akan membuat lisensi baru tidak cocok dengan Console tersebut. Jangan menjalankan dua salinan License Server aktif dari backup yang sama.

Backup lewat SSH/terminal

cd /opt/kamindo-licensing/releases/0.1.6
/opt/kamindo-licensing/venvs/0.1.6/bin/python -m app.recovery backup \
  --data-dir /var/lib/kamindo-licensing/data \
  --output /root/portguard-license.pgbackup

Password diminta secara interaktif; jangan menaruhnya dalam command line. Pembuatan backup boleh saat layanan berjalan. Untuk deployment yang memakai override LICENSING_ADMIN_TOKEN, jalankan perintah dengan environment layanan yang sama atau gunakan tombol backup di GUI.

Verifikasi sebelum restore

cd /opt/kamindo-licensing/releases/0.1.6
/opt/kamindo-licensing/venvs/0.1.6/bin/python -m app.recovery verify \
  /root/portguard-license.pgbackup

Perintah memeriksa autentikasi arsip, struktur/integritas database, hubungan record, dan semua entitlement terhadap signing key. Catat key ID dan jumlah lisensi yang ditampilkan.

Restore pada server pengganti atau rollback terencana

  1. Siapkan aplikasi License Server 0.1.6, Python environment, akun layanan, dan unit systemd sesuai konfigurasi deployment. Salin backup ke server melalui SSH/SCP.
  2. Restore dahulu ke direktori baru. Direktori tujuan harus belum ada:
cd /opt/kamindo-licensing/releases/0.1.6
/opt/kamindo-licensing/venvs/0.1.6/bin/python -m app.recovery restore \
  /root/portguard-license.pgbackup \
  --destination /var/lib/kamindo-licensing/data-restored
chown -R kamindo-licensing:kamindo-licensing /var/lib/kamindo-licensing/data-restored
chmod 700 /var/lib/kamindo-licensing/data-restored

Selanjutnya, pada maintenance window, hentikan layanan dan pindahkan data lama ke nama yang belum dipakai. Contoh berikut mempertahankan data lama untuk rollback:

systemctl stop kamindo-licensing
mv /var/lib/kamindo-licensing/data /var/lib/kamindo-licensing/data-before-restore-$(date +%Y%m%d-%H%M%S)
mv /var/lib/kamindo-licensing/data-restored /var/lib/kamindo-licensing/data
systemctl start kamindo-licensing
curl --fail http://127.0.0.1:8200/api/v1/health

Pada server baru yang belum memiliki direktori data, lewati perintah pertama mv. Jika stop atau pemindahan gagal, jangan lanjutkan. Pastikan key ID sesuai, masuk kembali, dan periksa jumlah lisensi/customer. Restore kembali ke waktu backup: perubahan setelah backup tidak ada pada snapshot. Simpan direktori lama hingga validasi selesai. Pemulihan melalui web tidak menimpa database yang sedang aktif; langkah terminal diperlukan agar pemindahan data terkendali.

Konfigurasi HTTPS/nginx, DNS, unit layanan, dan environment Google berada di luar data directory dan harus dicadangkan terpisah secara aman. Arsip tidak berisi Client Secret Google. Untuk kehilangan seluruh server, pulihkan konfigurasi tersebut, gunakan domain HTTPS yang sama, dan pastikan callback OAuth tetap sama. Sesi admin lama tidak berlaku setelah restore. Signing key tidak boleh diganti.

Menyiapkan login Google perusahaan

Akun Owner awal: joseph@kamindo.co.id, domain Workspace kamindo.co.id. Daftar konfigurasi ini membentuk Owner awal. Setelah masuk, Owner dapat menambahkan pengguna dari domain yang sama dan menetapkan role; karyawan lain tidak otomatis mendapat akses.

  1. Masuk ke Google Cloud Console menggunakan akun perusahaan yang dapat mengelola project. Pilih/buat project untuk PortGuard Licensing.
  2. Buka Google Auth Platform. Isi Branding (nama aplikasi dan support email), Audience (pilih Internal bila project berada dalam organisasi Google Workspace), serta kontak developer. Jika Internal tidak tersedia, pilih External dan tambahkan email admin sebagai test user selama pengujian.
  3. Pada Data Access gunakan hanya scope openid, email, dan profile. Aplikasi tidak meminta akses Gmail, Drive, atau Calendar.
  4. Pada Clients, buat OAuth client ID → Web application. Tambahkan Authorized redirect URI persis: https://licensing.kamindo.co/auth/google/callback. Alur backend tidak memerlukan Authorized JavaScript origins.
  5. Simpan Client ID dan Client Secret ke file environment server di bawah; jangan tempelkan Client Secret ke chat, repository, atau portal.
# /etc/kamindo-licensing/google.env — root:root, mode 600
LICENSING_PUBLIC_ORIGIN=https://licensing.kamindo.co
LICENSING_GOOGLE_DOMAIN=kamindo.co.id
LICENSING_GOOGLE_ADMIN_EMAILS=joseph@kamindo.co.id
LICENSING_GOOGLE_CLIENT_ID=ISI_CLIENT_ID_DARI_GOOGLE
LICENSING_GOOGLE_CLIENT_SECRET=ISI_CLIENT_SECRET_DARI_GOOGLE
LICENSING_ALLOW_TOKEN_LOGIN=0

File konfigurasi di server disiapkan dengan Client ID/Secret kosong sampai Anda mengisinya. Setelah diisi, restart layanan dan buka halaman login:

sudoedit /etc/kamindo-licensing/google.env
systemctl restart kamindo-licensing
curl --fail http://127.0.0.1:8200/api/v1/auth/config

Hasil yang diharapkan: google_enabled: true, token_enabled: false. Klik Sign in with company Google account dan pilih akun admin. Server memverifikasi signature Google, issuer, audience, expiry, nonce, state, email terverifikasi, hosted domain, dan status akun aktif pada database user. Alur memakai PKCE; sesi admin memakai cookie Secure/HttpOnly selama maksimal 8 jam, dengan proteksi CSRF untuk perubahan data. Sign out menghapus sesi pada server.

Untuk pemulihan akses darurat oleh operator root, set LICENSING_ALLOW_TOKEN_LOGIN=1 lalu restart, gunakan administrator token yang sudah ada, perbaiki konfigurasi Google, dan kembalikan nilainya ke 0. Jangan membagikan token kepada pengguna umum.

Sumber konfigurasi: Google OpenID Connect dan Authlib Starlette OAuth. Uji login Google langsung tetap memerlukan Client ID/Secret dari project perusahaan.

API dan batas kepemilikan

Console tetap memakai POST /api/v1/activate dengan activation code dan Console instance ID. Login Google hanya untuk administrasi License Server dan tidak mengubah protokol aktivasi, signing key, maupun kontrak Agent. Entitlement subscription baru menyertakan expires_at; Console yang mendukung claim ini menandai masa yang habis sebagai expired. Entitlement lama tanpa expiry tetap valid. Token admin hanya berlaku jika mode token diaktifkan. Lisensi memakai schema 1 dan signature Ed25519, bukan enkripsi nama perusahaan.

Pengaturan email transaksi Brevo

Owner dapat membuka panel Brevo transactional email pada halaman License Server. Atur nama dan alamat pengirim yang sudah diverifikasi di Brevo, alamat reply-to bila diperlukan, lalu masukkan API key. API key disimpan terenkripsi oleh server dan tidak ditampilkan kembali. Sebelum menyimpan API key, operator server harus membuat LICENSING_BREVO_SETTINGS_KEY dengan openssl rand -base64 32 dan menyimpannya pada environment file License Server dengan izin akses terbatas. Cadangkan kunci ini secara terpisah; database saja tidak cukup untuk memulihkan integrasi.

Gunakan kolom penerima dan tombol Send test email untuk memeriksa pengiriman. Pengiriman baru terjadi setelah tombol ditekan. Brevo memakai HTTPS port 443, sehingga dapat digunakan pada DigitalOcean yang membatasi SMTP keluar. Verifikasi SPF, DKIM, dan DMARC domain pengirim di Brevo. API key tidak boleh dimasukkan ke Website atau repository.