Dokumen ini menjelaskan langkah-langkah deploy aplikasi Layanan OpenDESA ke lingkungan produksi, termasuk konfigurasi API Signature, RSA key pair, push token ke OpenSID, dan setup queue worker menggunakan Supervisor.
.envcp .env.example .env
php artisan key:generate
php artisan jwt:secret --force
Buka file .env dan pastikan nilai berikut sudah sesuai:
# --- API Signature (WAJIB untuk production) ---
API_SIGNATURE_ENABLED=true
API_SIGNATURE_PLACEMENT=headers
API_SIGNATURE_TOLERANCE=300
# --- Push Token ke OpenSID (WAJIB) ---
PUSH_TOKEN_ENABLED=true
PUSH_TOKEN_CONNECTION=database
PUSH_TOKEN_TIMEOUT=10
PUSH_TOKEN_TRIES=1
PUSH_TOKEN_QUEUE=default
PUSH_TOKEN_WEBHOOK=/api/webhook/pelanggan/perbarui-langganan
# --- Queue (gunakan driver database untuk production) ---
QUEUE_CONNECTION=database
Catatan:
API_SIGNATURE_ENABLED=truemengaktifkan verifikasi RSA signature pada semua API response.PUSH_TOKEN_CONNECTION=databasememastikan push token diproses via queue database (bukan sync), agar operasi massal tidak memblokir aplikasi.QUEUE_CONNECTION=databasemenggunakan tabeljobsuntuk queue, cocok untuk shared hosting tanpa Redis.
Aplikasi menggunakan RSA key pair untuk:
# Generate key pair (default 2048-bit)
php artisan api-signature:generate-keys
# Jika perlu regenerate (akan overwrite key yang ada):
php artisan api-signature:generate-keys --force
Perintah ini akan:
storage/private.key (permission 0600)storage/public.key (permission 0644).env secara otomatisls -la storage/private.key storage/public.key
Output yang diharapkan:
-rw------- 1 www-data www-data 1709 private.key
-rw-r--r-- 1 www-data www-data 451 public.key
Public key yang dihasilkan harus didaftarkan di setiap instans OpenSID agar OpenSID dapat memverifikasi signature dari Layanan OpenDESA.
php artisan api-signature:export-public-key
Output yang diharapkan (format PEM):
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...
-----END PUBLIC KEY-----
php artisan migrate --force
Migrasi akan membuat:
jobs (untuk queue database)Queue worker wajib dijalankan via Supervisor di production. Tanpa ini, operasi massal (seperti perpanjangan layanan masal) akan memblokir request dan membuat aplikasi terasa lemot.
Buat file /etc/supervisor/conf.d/laravel-worker.conf:
[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /path/to/layanan-opendesa/artisan queue:work database --sleep=3 --tries=3 --max-time=3600
autostart=true
autorestart=true
stopasgroup=true
killasgroup=true
numprocs=2
redirect_stderr=true
stdout_logfile=/path/to/layanan-opendesa/storage/logs/worker.log
stopwaitsecs=3600
Catatan penting:
- Ganti
/path/to/layanan-opendesadengan path absolut instalasi aplikasinumprocs=2menjalankan 2 worker secara paralel, sesuaikan dengan spesifikasi serverstopwaitsecs=3600memberi waktu 1 jam untuk worker menyelesaikan job panjang sebelum di-force kill
sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start laravel-worker:*
sudo supervisorctl status
Output yang diharapkan:
laravel-worker:00 RUNNING pid 12345, uptime 0:01:00
laravel-worker:01 RUNNING pid 12346, uptime 0:01:00
tail -f storage/logs/worker.log
Jika tidak dapat menggunakan Supervisor, setup queue via cron sebagai fallback:
* * * * * cd /path/to/layanan-opendesa && php artisan queue:work database --sleep=3 --tries=3 --max-time=3600 >> storage/logs/queue-cron.log 2>&1
Peringatan: Cron tidak direstart otomatis jika worker crash. Lebih disarankan menggunakan Supervisor.
php artisan config:cache
php artisan route:cache
php artisan view:cache
php artisan event:cache
chmod -R 775 storage bootstrap/cache
chown -R www-data:www-data storage bootstrap/cache
chmod 600 storage/private.key
chmod 644 storage/public.key
chown -R www-data:www-data storage/private.key storage/public.key
Buat file /etc/logrotate.d/laravel-opendesa:
/path/to/layanan-opendesa/storage/logs/*.log {
daily
missingok
rotate 14
compress
delaycompress
notifempty
create 644 www-data www-data
}
# Cek koneksi database queue
php artisan queue:work database --once --verbose
# Export public key dan verifikasi signature
php artisan api-signature:export-public-key --fingerprint
sudo supervisorctl status
sudo supervisorctl tail -f laravel-worker:00
https://layanan-opendesa.example.com/monitoring/failed-jobs# Status supervisor
sudo supervisorctl status
# Restart worker (setelah deploy)
sudo supervisorctl restart laravel-worker:*
# Lihat log worker
tail -f storage/logs/worker.log
# Generate key baru dan update .env
php artisan api-signature:generate-keys --force
# Export public key baru
php artisan api-signature:export-public-key
# Distribusikan public key baru ke OpenSID (lihat langkah 4)
# Restart queue worker agar menggunakan key baru
sudo supervisorctl restart laravel-worker:*
# Cek apakah worker berjalan
sudo supervisorctl status
# Restart worker
sudo supervisorctl restart laravel-worker:*
# Cek log worker untuk error
tail -f storage/logs/worker.log
# Verifikasi PUSH_TOKEN_ENABLED
php artisan tinker --execute="echo env('PUSH_TOKEN_ENABLED') ? 'ENABLED' : 'DISABLED';"
# Cek failed jobs di dashboard
curl -s https://layanan-opendesa.example.com/monitoring/failed-jobs
# Verifikasi private key ada dan valid
openssl rsa -in storage/private.key -check
# Verifikasi public key ada dan valid
openssl rsa -pubin -in storage/public.key -text -noout
# Cek file permission
ls -la storage/private.key storage/public.key
# Pastikan queue menggunakan driver database (bukan sync)
php artisan tinker --execute="echo config('queue.default');"
# Pastikan Supervisor berjalan dengan numprocs yang cukup
sudo supervisorctl status
# Jika perlu, tambah worker
# Edit /etc/supervisor/conf.d/laravel-worker.conf, ubah numprocs, lalu:
sudo supervisorctl reread && sudo supervisorctl update
--no-dev --optimize-autoloader).env sudah dikonfigurasi dengan benarAPI_SIGNATURE_ENABLED=truePUSH_TOKEN_ENABLED=truePUSH_TOKEN_CONNECTION=databasestorage/private.key, storage/public.key)php artisan migrate --force)Konteks: refaktor "Umum murni open-source + sistem add-on dinamis". Layanan berperan sebagai
API langganan + distributor ZIP modul/tema premium yang diambil dari GitHub Releases.
Referensi lengkap:dokumentasi/refaktor-oss-perubahan-layanan.md,dokumentasi/setup-lokal.md.
composer install
cp .env.example .env
php artisan key:generate
php artisan jwt:secret --force # JWT_SECRET, dipakai token langganan desa
mysql -uroot -e "CREATE DATABASE layanan CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
php artisan migrate
php artisan storage:link
Isi di .env:
| Variabel | Kegunaan | Catatan |
|---|---|---|
GITHUB_TOKEN |
Autentikasi ke repo privat OpenSID/modul-* & OpenSID/tema-* saat sinkron |
Harus PAT dengan scope repo, expiration ≤ 366 hari — organisasi OpenSID menolak token yang lebih lama. Fine-grained PAT jadi alternatif tanpa batas ini. |
API_PANTAU / TOKEN_PANTAU |
Isi data regions (wilayah nasional) via menu Wilayah → Tarik Data |
Token statis publik, nilai default di .env.example sudah benar. |
Lalu jalankan sinkronisasi awal:
php artisan config:clear
php artisan layanan:sync-module-catalog
php artisan layanan:sync-theme-catalog
Prasyarat tambahan sebelum sinkron modul: baris Kategori "Modul" harus ada
(Kategori::firstOrCreate(['nama'=>'Modul'])) — kalau DB fresh dan baris ini hilang, sinkron
modul non-Umum gagal null-pointer.
Sinkronisasi di atas didesain jalan otomatis tiap jam lewat tabel schedules (DB-driven,
lihat app/Console/Kernel.php) — tapi itu hanya efektif kalau ada crontab nyata yang memanggil
Laravel scheduler:
* * * * * cd /path/ke/layanan && php artisan schedule:run >> /dev/null 2>&1
Tanpa baris crontab ini (kasus semua environment dev lokal), bagian "otomatis" tidak pernah
jalan sendiri — devops harus pastikan ini ada di server produksi/staging, atau sinkronisasi
harus dipicu manual/via tombol UI "Perbarui dari GitHub" di /modules dan /themes.
QUEUE_CONNECTION=sync di .env saat ini — listener (termasukGenerateTokenListener penerbit token JWT desa) jalan sinkron, tidak butuh queuestorage:link: tetap dibutuhkan untuk aset publik (thumbnail dll.) meski ZIP add-onURL::temporarySignedRoute, 10 menit), bukan lagiAPP_ENV=production: flag --allow-prerelease/--tag pada perintah sync ditolakmigrate-fresh (DB kosong) khususphp artisan migrate:fresh di staging sebagai smoke test sebelum deploy produksi.