Files
yellow-bank-soal/AAPANEL_DEPLOYMENT.md
Dwindi Ramadhana cf193d7ea0 first commit
2026-03-21 23:32:59 +07:00

22 KiB

IRT Bank Soal - AaPanel Deployment Guide

Document Version: 1.1 Date: March 21, 2026 Project: IRT-Powered Adaptive Question Bank System v1.2.0 Updated: Clarified PostgreSQL setup using Databases > PgSQL menu


Table of Contents

  1. Prerequisites
  2. AaPanel Installation
  3. Install Required Software via AaPanel
  4. PostgreSQL Setup
  5. Python Manager Setup
  6. Project Deployment
  7. Environment Configuration
  8. Database Migration
  9. Running the Application
  10. Nginx Reverse Proxy Configuration
  11. SSL Configuration
  12. Post-Deployment Verification
  13. Troubleshooting

1. Prerequisites

Server Requirements

Requirement Minimum Recommended
OS Ubuntu 20.04 / CentOS 7+ Ubuntu 22.04 LTS
RAM 2 GB 4 GB+
Storage 20 GB 50 GB+
CPU 1 vCPU 2+ vCPU

Domain Requirements

  • A domain name pointed to your server IP
  • Subdomain recommended (e.g., api.yourdomain.com)

2. AaPanel Installation

Step 2.1: Install AaPanel

For Ubuntu/Debian:

# Login to your server via SSH
ssh root@your-server-ip

# Install AaPanel
wget -O install.sh http://www.aapanel.com/script/install-ubuntu_6.0_en.sh && bash install.sh

For CentOS:

# Install AaPanel
yum install -y wget && wget -O install.sh http://www.aapanel.com/script/install_6.0_en.sh && sh install.sh

Step 2.2: Access AaPanel

  1. After installation completes, note the panel URL and credentials
  2. Access AaPanel via browser: http://your-server-ip:8888
  3. Login with provided credentials
  4. Important: Change default port and password after first login

3. Install Required Software via AaPanel

Step 3.1: Install Nginx

  1. In AaPanel, go to App Store
  2. Find Nginx and click Install
  3. Select version (recommended: 1.24+)
  4. Click Submit and wait for installation

Step 3.2: Install Python Manager

  1. Go to App Store
  2. Search for Python Manager (or PM2 Manager)
  3. Click Install

Step 3.3: Install Redis (Optional, for Celery)

  1. Go to App Store
  2. Find Redis and click Install
  3. Click Submit

4. PostgreSQL Setup

IMPORTANT: Use Databases > PgSQL menu from AaPanel sidebar.

This menu supports both:

  • Local server - PostgreSQL installed on your AaPanel server
  • Remote server - External PostgreSQL (Supabase, Neon, AWS RDS, etc.)

Step 4.1: Choose Your Database Type

You have two options:

Option Description Best For
Remote Database External PostgreSQL service (Supabase, Neon, etc.) Easy setup, managed, free tier available
Local Database PostgreSQL on your AaPanel server Full control, no external dependency

Use an external PostgreSQL service:

Step 4.A.1: Create Database on Provider

  1. Sign up on your chosen provider
  2. Create a new PostgreSQL project/database
  3. Note down the connection details from dashboard:
    • Host (e.g., db.xxxxx.supabase.co or ep-xxx.us-east-2.aws.neon.tech)
    • Port (usually 5432, Supabase uses 6543 for pooler)
    • Database name (e.g., postgres or neondb)
    • Username (e.g., postgres.xxxxx)
    • Password

Step 4.A.2: Add Remote Server to AaPanel PgSQL

  1. In AaPanel, go to Databases > PgSQL
  2. Click Remote DB button
  3. Fill in the form:
    • Server Name: my-remote-db (any name you like)
    • Server Address: db.xxxxx.supabase.co (your host)
    • Port: 5432 or 6543 (check your provider)
    • Root User: postgres or your username
    • Root Password: your password
  4. Click Submit

Step 4.A.3: Sync Databases from Remote Server

  1. After adding remote server, click Get DB from server
  2. Select your remote server from dropdown
  3. Click Submit
  4. Your remote databases will appear in the list

Step 4.A.4: Note Your Connection String

Your connection string format:

postgresql+asyncpg://username:password@host:port/database_name

Example (Supabase):

postgresql+asyncpg://postgres.xxxxx:YourPassword@aws-0-ap-southeast-1.pooler.supabase.com:6543/postgres

Example (Neon):

postgresql+asyncpg://neondb_owner:YourPassword@ep-xxxx.us-east-2.aws.neon.tech/neondb?sslmode=require

Option B: Local PostgreSQL Database

Install PostgreSQL directly on your AaPanel server.

Step 4.B.1: Install PostgreSQL via Terminal

# SSH into your server
ssh root@your-server-ip

# Ubuntu/Debian
apt update
apt install -y postgresql postgresql-contrib

# Start and enable PostgreSQL
systemctl start postgresql
systemctl enable postgresql

# Check status
systemctl status postgresql

Step 4.B.2: Create Database and User via Terminal

# Switch to postgres user
su - postgres

# Enter PostgreSQL CLI
psql

# Run SQL commands:
CREATE DATABASE irt_bank_soal;

CREATE USER irt_user WITH ENCRYPTED PASSWORD 'your_secure_password_here';

GRANT ALL PRIVILEGES ON DATABASE irt_bank_soal TO irt_user;

# Connect to database and grant schema
\c irt_bank_soal
GRANT ALL ON SCHEMA public TO irt_user;

# Exit
\q
exit

Step 4.B.3: Add Local Server to AaPanel PgSQL

  1. In AaPanel, go to Databases > PgSQL
  2. Click Root Password to view/change postgres password
  3. If your local PostgreSQL is not showing, click Get DB from server
  4. Select Local server
  5. Click Submit

Step 4.B.4: Create Additional Database via AaPanel (Optional)

  1. In Databases > PgSQL
  2. Click Add DB
  3. Fill in:
    • Database name: irt_bank_soal
    • Username: irt_user (or same as DB name)
    • Password: (click generate or enter custom)
    • Add to: Local server
  4. Click Submit

Step 4.B.5: Note Your Connection String

postgresql+asyncpg://irt_user:your_password@127.0.0.1:5432/irt_bank_soal

4.1 Test Database Connection

Before proceeding, verify your database connection works.

For Remote Database:

# Install psql client if needed
apt install -y postgresql-client

# Test connection (replace with your details)
psql "postgresql://username:password@host:port/database_name" -c "SELECT version();"

For Local Database:

# Test connection
psql -U irt_user -d irt_bank_soal -h 127.0.0.1 -c "SELECT version();"

# If prompted for password, enter it

4.2 Connection String Quick Reference

Database Type Connection String Format
Remote (Supabase) postgresql+asyncpg://postgres.xxxx:password@aws-0-region.pooler.supabase.com:6543/postgres
Remote (Neon) postgresql+asyncpg://user:password@ep-xxxx.region.aws.neon.tech/neondb?sslmode=require
Local postgresql+asyncpg://irt_user:password@127.0.0.1:5432/irt_bank_soal

Note: We use postgresql+asyncpg:// because our app uses async SQLAlchemy with asyncpg driver.


5. Python Manager Setup

Step 5.1: Open Python Manager

  1. In AaPanel, go to App Store
  2. Find Python Manager and click Settings

Step 5.2: Install Python Version

  1. Click Version Management
  2. Select Python 3.11 (or latest stable)
  3. Click Install
  4. Wait for installation to complete

6. Project Deployment

Step 6.1: Create Project Directory

# Create project directory
mkdir -p /www/wwwroot/irt-bank-soal

# Navigate to directory
cd /www/wwwroot/irt-bank-soal

Step 6.2: Upload Project Files

Option A: Upload via File Manager

  1. In AaPanel, go to Files
  2. Navigate to /www/wwwroot/irt-bank-soal
  3. Upload your project ZIP file
  4. Extract the archive

Option B: Clone from Git (if applicable)

cd /www/wwwroot/irt-bank-soal

# If using Git
git clone https://github.com/your-repo/irt-bank-soal.git .

# Or copy from local
# scp -r /Users/dwindown/Applications/tryout-system/* root@your-server-ip:/www/wwwroot/irt-bank-soal/

Step 6.3: Verify Project Structure

# Expected structure:
ls -la /www/wwwroot/irt-bank-soal/
# app/
# app/models/
# app/routers/
# app/services/
# app/core/
# tests/
# requirements.txt
# .env.example
# alembic/

7. Environment Configuration

Step 7.1: Create Virtual Environment via Python Manager

  1. In AaPanel Python Manager, click Add Project
  2. Configure:
    • Project Name: irt-bank-soal
    • Project Path: /www/wwwroot/irt-bank-soal
    • Python Version: Python 3.11
    • Framework: FastAPI
    • Startup Method: uvicorn
  3. Click Submit

Step 7.2: Create Environment File

# Copy example file
cp /www/wwwroot/irt-bank-soal/.env.example /www/wwwroot/irt-bank-soal/.env

# Edit .env file
nano /www/wwwroot/irt-bank-soal/.env

Step 7.3: Configure .env File

# Database Configuration
# For Remote Database (Supabase example):
# DATABASE_URL=postgresql+asyncpg://postgres.xxxx:password@aws-0-ap-southeast-1.pooler.supabase.com:6543/postgres
# For Remote Database (Neon example):
# DATABASE_URL=postgresql+asyncpg://neondb_owner:password@ep-xxxx.us-east-2.aws.neon.tech/neondb?sslmode=require
# For Local Database:
DATABASE_URL=postgresql+asyncpg://irt_user:your_secure_password_here@127.0.0.1:5432/irt_bank_soal

# Security
SECRET_KEY=your-production-secret-key-min-32-characters-random-string

# Environment
ENVIRONMENT=production
DEBUG=false

# API Configuration
API_V1_STR=/api/v1
PROJECT_NAME=IRT Bank Soal
PROJECT_VERSION=1.2.0

# CORS - Add your WordPress domains
ALLOWED_ORIGINS=https://yourdomain.com,https://www.yourdomain.com

# OpenRouter API (for AI Generation)
OPENROUTER_API_KEY=your-openrouter-api-key-here
OPENROUTER_API_URL=https://openrouter.ai/api/v1
OPENROUTER_MODEL_QWEN=qwen/qwen-2.5-coder-32b-instruct
OPENROUTER_MODEL_LLAMA=meta-llama/llama-3.3-70b-instruct
OPENROUTER_TIMEOUT=60

# WordPress Integration
WORDPRESS_API_URL=https://yourdomain.com/wp-json
WORDPRESS_AUTH_TOKEN=your-wordpress-jwt-token

# Redis (for Celery task queue)
REDIS_URL=redis://127.0.0.1:6379/0

# Admin Panel
ADMIN_USER=admin
ADMIN_PASSWORD=your-secure-admin-password

# Normalization Defaults
DEFAULT_RATAAN=500
DEFAULT_SB=100
MIN_SAMPLE_FOR_DYNAMIC=100

Step 7.4: Generate Secret Key

# Generate a secure secret key
python3 -c "import secrets; print(secrets.token_urlsafe(32))"

# Copy the output and paste into SECRET_KEY in .env

8. Database Migration

Step 8.1: Activate Virtual Environment

# Via Python Manager, the venv is usually at:
source /www/wwwroot/irt-bank-soal/venv/bin/activate

# Or check Python Manager for exact venv path

Step 8.2: Install Dependencies

# Ensure you're in project directory
cd /www/wwwroot/irt-bank-soal

# Install dependencies
pip install -r requirements.txt

# Verify installation
pip list | grep -E "fastapi|sqlalchemy|numpy|scipy|httpx|openpyxl"

Step 8.3: Initialize Alembic (First Time Setup)

# Initialize Alembic if not already done
alembic init alembic

# Generate initial migration
alembic revision --autogenerate -m "Initial migration"

# Apply migration
alembic upgrade head

Step 8.4: Verify Database Tables

# Check tables were created
psql -U irt_user -d irt_bank_soal -h 127.0.0.1 -c "\dt"

# Expected output: websites, users, tryouts, items, sessions, user_answers, tryout_stats

9. Running the Application

Step 9.1: Configure Python Project in AaPanel

  1. In Python Manager, find your project irt-bank-soal
  2. Click Settings
  3. Configure startup:
    • Startup File: app/main.py
    • Startup Method: uvicorn
    • Port: 8000
    • Modules: uvicorn[standard]

Step 9.2: Set Startup Command

In Python Manager settings, set the startup command:

# Startup command
uvicorn app.main:app --host 127.0.0.1 --port 8000 --workers 4

# Or for development:
uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload

Step 9.3: Start the Application

  1. In Python Manager, click Start on your project
  2. Check logs for any errors
  3. Verify the application is running:
# Test health endpoint
curl http://127.0.0.1:8000/

# Expected response:
# {"status": "healthy", "project_name": "IRT Bank Soal", "version": "1.2.0"}

Step 9.4: Configure Auto-Start on Boot

  1. In Python Manager, enable Auto-start on boot
  2. Or manually via terminal:
# Using systemd (create service file)
nano /etc/systemd/system/irt-bank-soal.service
[Unit]
Description=IRT Bank Soal FastAPI Application
After=network.target
# Uncomment below if using LOCAL PostgreSQL:
# After=network.target postgresql.service

[Service]
Type=simple
User=www
Group=www
WorkingDirectory=/www/wwwroot/irt-bank-soal
Environment="PATH=/www/wwwroot/irt-bank-soal/venv/bin"
ExecStart=/www/wwwroot/irt-bank-soal/venv/bin/uvicorn app.main:app --host 127.0.0.1 --port 8000 --workers 4
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
# Enable and start service
systemctl daemon-reload
systemctl enable irt-bank-soal
systemctl start irt-bank-soal
systemctl status irt-bank-soal

10. Nginx Reverse Proxy Configuration

Step 10.1: Create Website in AaPanel

  1. In AaPanel, go to Website
  2. Click Add Site
  3. Configure:
    • Domain: api.yourdomain.com (or your subdomain)
    • PHP Version: Pure Static (not needed)
    • Database: None (already created)
  4. Click Submit

Step 10.2: Configure Reverse Proxy

  1. Click Settings on the newly created website
  2. Go to Reverse Proxy
  3. Click Add Reverse Proxy
  4. Configure:
    • Proxy Name: irt-api
    • Target URL: http://127.0.0.1:8000
  5. Click Submit

Step 10.3: Manual Nginx Configuration (Alternative)

# Edit Nginx config
nano /www/server/panel/vhost/nginx/api.yourdomain.com.conf
server {
    listen 80;
    server_name api.yourdomain.com;

    # Access and error logs
    access_log /www/wwwlogs/api.yourdomain.com.log;
    error_log /www/wwwlogs/api.yourdomain.com.error.log;

    # Client body size (for Excel uploads)
    client_max_body_size 50M;

    # Proxy to FastAPI
    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_connect_timeout 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
    }

    # Static files (if any)
    location /static/ {
        alias /www/wwwroot/irt-bank-soal/static/;
        expires 30d;
    }
}

Step 10.4: Test and Reload Nginx

# Test Nginx configuration
nginx -t

# Reload Nginx
nginx -s reload

# Or via AaPanel: Website > Settings > Config > Save

11. SSL Configuration

Step 11.1: Install SSL Certificate

  1. In AaPanel, go to Website
  2. Click Settings on your site
  3. Go to SSL
  4. Choose method:
    • Let's Encrypt: Free, auto-renewal
    • Own Certificate: Upload your own
    • Buy: Purchase through AaPanel

Step 11.2: Configure Let's Encrypt

  1. Click Let's Encrypt
  2. Enter your email
  3. Select domain api.yourdomain.com
  4. Click Apply
  5. Enable Force HTTPS

Step 11.3: Update .env for HTTPS

# Edit .env
nano /www/wwwroot/irt-bank-soal/.env

# Update CORS to use HTTPS
ALLOWED_ORIGINS=https://yourdomain.com,https://www.yourdomain.com

12. Post-Deployment Verification

Step 12.1: Test API Endpoints

# Test health endpoint
curl https://api.yourdomain.com/

# Test detailed health
curl https://api.yourdomain.com/health

# Test API documentation
# Open in browser: https://api.yourdomain.com/docs

Step 12.2: Test Database Connection

# Via API
curl https://api.yourdomain.com/health

# Expected response includes database status:
# {"status": "healthy", "database": "connected", "api_version": "v1"}

Step 12.3: Test Admin Panel

# Access admin panel
# Open in browser: https://api.yourdomain.com/admin
# Login with credentials from .env

Step 12.4: Load Test Data (Optional)

# SSH into server
ssh root@your-server-ip

# Navigate to project
cd /www/wwwroot/irt-bank-soal

# Activate venv
source venv/bin/activate

# Run test data script
python3 -c "
import asyncio
from app.database import init_db
asyncio.run(init_db())
print('Database initialized successfully')
"

13. Troubleshooting

Issue: Python Manager Not Starting Application

Solution:

# Check logs
tail -f /www/wwwroot/irt-bank-soal/logs/error.log

# Check if port is in use
lsof -i :8000

# Manually test startup
cd /www/wwwroot/irt-bank-soal
source venv/bin/activate
uvicorn app.main:app --host 127.0.0.1 --port 8000

Issue: Database Connection Failed

For Remote Database:

# Test connection from server
apt install -y postgresql-client
psql "postgresql://username:password@remote-host:port/database" -c "SELECT 1;"

# Check if firewall allows outbound connection
# Most remote DBs use port 5432 or 6543

# Verify DATABASE_URL in .env
cat /www/wwwroot/irt-bank-soal/.env | grep DATABASE_URL

# Common issues:
# - Wrong port (Supabase pooler uses 6543, direct uses 5432)
# - Missing sslmode=require (Neon requires this)
# - IP not whitelisted (check provider dashboard)

For Local Database:

# Check PostgreSQL status
systemctl status postgresql

# Test connection manually
psql -U irt_user -d irt_bank_soal -h 127.0.0.1 -W

# Check pg_hba.conf allows connections
cat /etc/postgresql/*/main/pg_hba.conf | grep -v "^#" | grep -v "^$"

# Verify DATABASE_URL in .env
cat /www/wwwroot/irt-bank-soal/.env | grep DATABASE_URL

Issue: 502 Bad Gateway

Solution:

# Check if FastAPI is running
ps aux | grep uvicorn

# Check Nginx error logs
tail -f /www/wwwlogs/api.yourdomain.com.error.log

# Verify proxy configuration
cat /www/server/panel/vhost/nginx/api.yourdomain.com.conf | grep proxy_pass

Issue: CORS Errors

Solution:

# Check ALLOWED_ORIGINS in .env
cat /www/wwwroot/irt-bank-soal/.env | grep ALLOWED_ORIGINS

# Ensure WordPress domain is included
# Example: ALLOWED_ORIGINS=https://site1.com,https://site2.com

# Restart application after changes
# Via Python Manager: Stop > Start

Issue: SSL Certificate Not Working

Solution:

# Check certificate
openssl s_client -connect api.yourdomain.com:443

# Force HTTPS in Nginx config
# Add to server block:
# return 301 https://$host$request_uri;

# Reload Nginx
nginx -s reload

Issue: Large File Upload Failed

Solution:

# Increase Nginx client body size
nano /www/server/panel/vhost/nginx/api.yourdomain.com.conf

# Add/modify:
# client_max_body_size 100M;

# Also check PHP settings if using PHP
# In AaPanel: PHP > Settings > Upload Max Filesize

Quick Reference Commands

# Application Management
systemctl start irt-bank-soal
systemctl stop irt-bank-soal
systemctl restart irt-bank-soal
systemctl status irt-bank-soal

# Local Database Management (if using local PostgreSQL)
systemctl start postgresql
systemctl stop postgresql
systemctl restart postgresql
systemctl status postgresql

# Nginx Management
nginx -t                    # Test config
nginx -s reload             # Reload config
systemctl restart nginx     # Restart Nginx

# View Logs
tail -f /www/wwwlogs/api.yourdomain.com.log
tail -f /www/wwwlogs/api.yourdomain.com.error.log

# Application Logs (if configured)
tail -f /www/wwwroot/irt-bank-soal/logs/app.log

# Test Database Connection
# Local:
psql -U irt_user -d irt_bank_soal -h 127.0.0.1 -c "SELECT version();"
# Remote:
psql "postgresql://user:pass@host:port/db" -c "SELECT version();"

Security Checklist

  • Changed AaPanel default port and password
  • Database user has strong password
  • SECRET_KEY is unique and 32+ characters
  • SSL certificate installed and forced HTTPS
  • CORS restricted to production domains only
  • Firewall configured (only 80, 443, 22, 8888 open)
  • Admin password is strong
  • For local DB: PostgreSQL not exposed to internet
  • For remote DB: IP whitelist configured (if supported)
  • Regular backups configured

Backup Configuration

Database Backup

For Local Database:

# Create backup directory
mkdir -p /www/backup

# Manual backup
pg_dump -U irt_user -h 127.0.0.1 irt_bank_soal > /www/backup/irt_bank_soal_$(date +%Y%m%d).sql

# Automated backup (cron)
crontab -e
# Add: 0 2 * * * pg_dump -U irt_user -h 127.0.0.1 irt_bank_soal > /www/backup/irt_bank_soal_$(date +\%Y\%m\%d).sql

For Remote Database:

Most managed PostgreSQL providers have built-in backup features:

  • Supabase: Dashboard > Database > Backups (daily automatic)
  • Neon: Automatic point-in-time recovery
  • AWS RDS: Automated backups with retention period

You can also backup manually:

# Manual backup from remote (requires postgresql-client)
pg_dump "postgresql://username:password@host:port/database" > /www/backup/irt_bank_soal_$(date +%Y%m%d).sql

# Or with SSL for providers like Neon
pg_dump "postgresql://username:password@host:port/database?sslmode=require" > /www/backup/irt_bank_soal_$(date +%Y%m%d).sql

Project Backup

# Backup project files
tar -czvf /www/backup/irt_project_$(date +%Y%m%d).tar.gz /www/wwwroot/irt-bank-soal

# Exclude venv to save space
tar -czvf /www/backup/irt_project_$(date +%Y%m%d).tar.gz --exclude='venv' /www/wwwroot/irt-bank-soal

Document End

Status: Ready for Deployment

Support: Refer to TEST.md for testing procedures and PRD.md for requirements.