# Deploy Production Panduan ini untuk deploy production dengan asumsi: - domain `abelbirdnest.id` - reverse proxy `nginx` - aplikasi Next.js di port `3007` - database `PostgreSQL` - source code dari git `https://git.iptek.co/wirabasalamah/AbelBirdNest-Stock.git` - user service khusus `abelbirdnest` - repo berada di: `/var/www/abelbirdnest-web/AbelBirdNest-Stock` ## 1. Persiapan Server Install: - Node.js LTS - npm - PostgreSQL - nginx - certbot Direktori aplikasi: ```bash /var/www/abelbirdnest-web ``` ## 2. Buat User OS Khusus Aplikasi ```bash sudo useradd -r -m -d /var/www/abelbirdnest-web -s /bin/bash abelbirdnest sudo mkdir -p /var/www/abelbirdnest-web sudo chown -R abelbirdnest:abelbirdnest /var/www/abelbirdnest-web ``` Masuk sebagai user aplikasi: ```bash sudo -u abelbirdnest -H bash cd /var/www/abelbirdnest-web ``` ## 3. Clone Repo Clone normal: ```bash git clone https://git.iptek.co/wirabasalamah/AbelBirdNest-Stock.git cd /var/www/abelbirdnest-web/AbelBirdNest-Stock ``` Catatan: - panduan ini mengikuti struktur clone normal di atas - jadi `WorkingDirectory`, `.env.production`, dan semua perintah memakai path: `/var/www/abelbirdnest-web/AbelBirdNest-Stock` ## 4. Siapkan Environment Production Salin file contoh: ```bash cp .env.production.example .env.production ``` Isi minimal: ```env NODE_ENV=production PORT=3007 APP_URL=https://abelbirdnest.id DATABASE_URL=postgresql://abelbirdnest_app:password@127.0.0.1:5432/abelbirdnest_prod?schema=public AUTH_SECRET=ganti-dengan-random-string-panjang AUTH_BOOTSTRAP=false SMTP_HOST=... SMTP_PORT=465 SMTP_SECURE=true SMTP_USER=... SMTP_PASSWORD=... SMTP_FROM=... ``` Catatan: - `AUTH_BOOTSTRAP=false` wajib di production - akun default dev tidak akan aktif - `AUTH_SECRET` harus random dan panjang ## 5. Inisialisasi PostgreSQL Masuk sebagai superuser PostgreSQL: ```bash sudo -u postgres psql ``` Buat user database: ```sql CREATE USER abelbirdnest_app WITH PASSWORD 'ganti-dengan-password-yang-kuat'; ``` Buat database: ```sql CREATE DATABASE abelbirdnest_prod OWNER abelbirdnest_app; ALTER DATABASE abelbirdnest_prod OWNER TO abelbirdnest_app; REVOKE ALL ON DATABASE abelbirdnest_prod FROM PUBLIC; GRANT ALL PRIVILEGES ON DATABASE abelbirdnest_prod TO abelbirdnest_app; ``` Keluar: ```sql \q ``` Tes koneksi: ```bash psql "postgresql://abelbirdnest_app:ganti-dengan-password-yang-kuat@127.0.0.1:5432/abelbirdnest_prod" ``` Catatan: - untuk `psql`, jangan pakai `?schema=public` - untuk `DATABASE_URL` Prisma, tetap pakai `?schema=public` ## 6. Install Dependency dan Buat Tabel Masih sebagai user `abelbirdnest`: ```bash cd /var/www/abelbirdnest-web/AbelBirdNest-Stock npm install npm run prisma:generate ``` Load env production ke shell saat menjalankan command manual: ```bash set -a source .env.production set +a ``` Jalankan migration: ```bash npm run prisma:migrate:deploy ``` Opsional cek status: ```bash npx prisma migrate status ``` ## 7. Seed Data Awal Untuk fresh database: ```bash cd /var/www/abelbirdnest-web/AbelBirdNest-Stock set -a source .env.production set +a npm run seed:banks npm run seed:currencies ``` ### Khusus Grade `seed:grades` butuh file `Grade.xls`. Buat folder data: ```bash mkdir -p scripts/data ``` Upload file `Grade.xls` ke: ```bash /var/www/abelbirdnest-web/AbelBirdNest-Stock/scripts/data/Grade.xls ``` Lalu jalankan: ```bash cd /var/www/abelbirdnest-web/AbelBirdNest-Stock set -a source .env.production set +a npm run seed:grades ``` Alternatif jika file ada di lokasi lain: ```bash node scripts/seed-grades-from-xls.mjs /path/ke/Grade.xls ``` ## 8. Buat User Pertama di PostgreSQL Karena `AUTH_BOOTSTRAP=false`, Anda harus buat user login pertama sendiri. ### 8.1 Generate Hash Password Ganti password contoh ini: ```bash node -e 'const {randomBytes,scryptSync}=require("crypto"); const p="GantiPasswordKuat123!"; const salt=randomBytes(16).toString("hex"); const derived=scryptSync(p,salt,64).toString("hex"); console.log(`${salt}:${derived}`)' ``` Simpan output hash-nya. ### 8.2 Masuk ke PostgreSQL ```bash psql "postgresql://abelbirdnest_app:password@127.0.0.1:5432/abelbirdnest_prod" ``` ### 8.3 Pastikan Role `SYSTEM_ADMIN` Ada ```sql INSERT INTO roles (code, name, created_at, updated_at) VALUES ('SYSTEM_ADMIN', 'System Admin', NOW(), NOW()) ON CONFLICT (code) DO UPDATE SET name = EXCLUDED.name, updated_at = NOW(); ``` ### 8.4 Buat User Pertama Ganti: - `Nama Anda` - `superadmin` - `superadmin@abelbirdnest.id` - `HASH_HASIL_LANGKAH_8_1` ```sql INSERT INTO users ( role_id, name, username, email, email_verified_at, phone, password_hash, status, created_at, updated_at ) SELECT r.id, 'Nama Anda', 'superadmin', 'superadmin@abelbirdnest.id', NOW(), NULL, 'HASH_HASIL_LANGKAH_8_1', 'ACTIVE', NOW(), NOW() FROM roles r WHERE r.code = 'SYSTEM_ADMIN' ON CONFLICT (email) DO UPDATE SET role_id = EXCLUDED.role_id, name = EXCLUDED.name, username = EXCLUDED.username, email_verified_at = EXCLUDED.email_verified_at, password_hash = EXCLUDED.password_hash, status = EXCLUDED.status, updated_at = NOW(); ``` Verifikasi: ```sql SELECT u.id, u.name, u.username, u.email, u.status, r.code AS role FROM users u JOIN roles r ON r.id = u.role_id WHERE u.email = 'superadmin@abelbirdnest.id'; ``` ## 9. Build Production ```bash cd /var/www/abelbirdnest-web/AbelBirdNest-Stock set -a source .env.production set +a npm run build ``` ## 10. Jalankan App dengan systemd File service repo sudah disiapkan untuk struktur subfolder ini: ```bash deploy/systemd/abelbirdnest-web.service ``` Pasang: ```bash sudo cp /var/www/abelbirdnest-web/AbelBirdNest-Stock/deploy/systemd/abelbirdnest-web.service /etc/systemd/system/ sudo chown -R abelbirdnest:abelbirdnest /var/www/abelbirdnest-web/AbelBirdNest-Stock sudo systemctl daemon-reload sudo systemctl enable abelbirdnest-web sudo systemctl restart abelbirdnest-web sudo systemctl status abelbirdnest-web ``` Verifikasi port: ```bash ss -ltnp | grep 3007 curl http://127.0.0.1:3007/api/v1/health ``` Kalau service gagal, cek: ```bash sudo systemctl cat abelbirdnest-web sudo journalctl -u abelbirdnest-web -n 100 --no-pager which npm ``` ## 11. Pasang Nginx Tahap 1: HTTP Dulu Jangan langsung pakai config HTTPS sebelum sertifikat ada. Pakai file ini dulu: ```bash deploy/nginx/abelbirdnest.id.http.conf ``` Pasang: ```bash sudo cp /var/www/abelbirdnest-web/AbelBirdNest-Stock/deploy/nginx/abelbirdnest.id.http.conf /etc/nginx/sites-available/abelbirdnest.id.conf sudo ln -sf /etc/nginx/sites-available/abelbirdnest.id.conf /etc/nginx/sites-enabled/abelbirdnest.id.conf sudo nginx -t sudo systemctl reload nginx ``` Tes: ```bash curl http://abelbirdnest.id/api/v1/health ``` ## 12. Buat Sertifikat SSL Setelah HTTP sudah hidup: ```bash sudo certbot --nginx -d abelbirdnest.id -d www.abelbirdnest.id ``` ## 13. Ganti ke Config HTTPS Final Setelah sertifikat berhasil dibuat, baru pakai config final: ```bash sudo cp /var/www/abelbirdnest-web/AbelBirdNest-Stock/deploy/nginx/abelbirdnest.id.conf /etc/nginx/sites-available/abelbirdnest.id.conf sudo nginx -t sudo systemctl reload nginx ``` Verifikasi: ```bash curl https://abelbirdnest.id/api/v1/health ``` ## 14. Update Deployment Berikutnya ```bash cd /var/www/abelbirdnest-web/AbelBirdNest-Stock git pull origin main set -a source .env.production set +a npm install npm run prisma:generate npm run prisma:migrate:deploy npm run build sudo systemctl restart abelbirdnest-web sudo systemctl status abelbirdnest-web ``` ## 15. Smoke Test Setelah Live Cek minimal: - login dengan user `SYSTEM_ADMIN` - dashboard terbuka - health check OK - buat master `bank`, `currency`, `grade` tampil - buat transaksi sederhana - logout/login ulang - email reset/verifikasi jika SMTP sudah aktif