Files
AbelBirdNest-Stock/docs/deploy-production.md

7.7 KiB

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:

/var/www/abelbirdnest-web

2. Buat User OS Khusus Aplikasi

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:

sudo -u abelbirdnest -H bash
cd /var/www/abelbirdnest-web

3. Clone Repo

Clone normal:

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:

cp .env.production.example .env.production

Isi minimal:

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:

sudo -u postgres psql

Buat user database:

CREATE USER abelbirdnest_app WITH PASSWORD 'ganti-dengan-password-yang-kuat';

Buat database:

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:

\q

Tes koneksi:

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:

cd /var/www/abelbirdnest-web/AbelBirdNest-Stock
npm install
npm run prisma:generate

Load env production ke shell saat menjalankan command manual:

set -a
source .env.production
set +a

Jalankan migration:

npm run prisma:migrate:deploy

Opsional cek status:

npx prisma migrate status

7. Seed Data Awal

Untuk fresh database:

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:

mkdir -p scripts/data

Upload file Grade.xls ke:

/var/www/abelbirdnest-web/AbelBirdNest-Stock/scripts/data/Grade.xls

Lalu jalankan:

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:

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:

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

psql "postgresql://abelbirdnest_app:password@127.0.0.1:5432/abelbirdnest_prod"

8.3 Pastikan Role SYSTEM_ADMIN Ada

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
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:

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

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:

deploy/systemd/abelbirdnest-web.service

Pasang:

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:

ss -ltnp | grep 3007
curl http://127.0.0.1:3007/api/v1/health

Kalau service gagal, cek:

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:

deploy/nginx/abelbirdnest.id.http.conf

Pasang:

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:

curl http://abelbirdnest.id/api/v1/health

12. Buat Sertifikat SSL

Setelah HTTP sudah hidup:

sudo certbot --nginx -d abelbirdnest.id -d www.abelbirdnest.id

13. Ganti ke Config HTTPS Final

Setelah sertifikat berhasil dibuat, baru pakai config final:

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:

curl https://abelbirdnest.id/api/v1/health

14. Update Deployment Berikutnya

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