Skip to Content
🚀 APSO is now in public beta. Get started →
GuidesDeploymentSelf-Hosting

Self-Hosting

Deploy your APSO backend on your own infrastructure for full control over your deployment.

Requirements

  • Node.js 18+ (for TypeScript template)
  • Python 3.10+ (for Python template)
  • Go 1.21+ (for Go template)
  • PostgreSQL 14+
  • SSL certificate for production

Build for Production

TypeScript (NestJS)

# Install dependencies npm ci --production=false # Build npm run build # Start NODE_ENV=production node dist/main.js

Python (FastAPI)

# Create virtual environment python -m venv venv source venv/bin/activate # Install dependencies pip install -r requirements.txt # Start with gunicorn gunicorn main:app -w 4 -k uvicorn.workers.UvicornWorker

Go (Gin)

# Build binary CGO_ENABLED=0 GOOS=linux go build -o server ./cmd/server # Start ./server

Environment Variables

# Required DATABASE_URL=postgresql://user:pass@host:5432/db JWT_SECRET=your-256-bit-secret NODE_ENV=production # Optional PORT=3001 LOG_LEVEL=info CORS_ORIGINS=https://yourapp.com

Database Setup

PostgreSQL Installation

# Ubuntu/Debian sudo apt install postgresql postgresql-contrib # macOS brew install postgresql@14 # Start service sudo systemctl start postgresql

Create Database

CREATE USER apso WITH PASSWORD 'your-password'; CREATE DATABASE apso_production OWNER apso; GRANT ALL PRIVILEGES ON DATABASE apso_production TO apso;

Connection Pooling

For production, use PgBouncer:

# /etc/pgbouncer/pgbouncer.ini [databases] apso_production = host=localhost port=5432 dbname=apso_production [pgbouncer] listen_port = 6432 listen_addr = 127.0.0.1 auth_type = md5 pool_mode = transaction max_client_conn = 1000 default_pool_size = 20

Reverse Proxy

Nginx

# /etc/nginx/sites-available/api.conf upstream apso_backend { server 127.0.0.1:3001; keepalive 32; } server { listen 443 ssl http2; server_name api.yourdomain.com; ssl_certificate /etc/letsencrypt/live/api.yourdomain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/api.yourdomain.com/privkey.pem; location / { proxy_pass http://apso_backend; 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_cache_bypass $http_upgrade; } }

Caddy

# Caddyfile api.yourdomain.com { reverse_proxy localhost:3001 }

Process Management

systemd

# /etc/systemd/system/apso.service [Unit] Description=APSO API Server After=network.target postgresql.service [Service] Type=simple User=apso WorkingDirectory=/opt/apso ExecStart=/usr/bin/node dist/main.js Restart=on-failure RestartSec=10 Environment=NODE_ENV=production EnvironmentFile=/opt/apso/.env [Install] WantedBy=multi-user.target
# Enable and start sudo systemctl enable apso sudo systemctl start apso # View logs sudo journalctl -u apso -f

PM2

# Install PM2 npm install -g pm2 # Start application pm2 start dist/main.js --name apso -i max # Save configuration pm2 save pm2 startup # Monitoring pm2 monit

ecosystem.config.js

module.exports = { apps: [{ name: 'apso', script: 'dist/main.js', instances: 'max', exec_mode: 'cluster', env_production: { NODE_ENV: 'production', PORT: 3001, }, }], };

SSL Certificates

Let’s Encrypt

# Install certbot sudo apt install certbot python3-certbot-nginx # Get certificate sudo certbot --nginx -d api.yourdomain.com # Auto-renewal sudo systemctl enable certbot.timer

Cloud Providers

AWS EC2

# Launch instance aws ec2 run-instances \ --image-id ami-0123456789 \ --instance-type t3.medium \ --key-name your-key \ --security-group-ids sg-xxx # Or use Elastic Beanstalk eb init eb create production eb deploy

Google Cloud

# Create instance gcloud compute instances create apso-server \ --machine-type=e2-medium \ --zone=us-central1-a # Or use Cloud Run gcloud run deploy apso \ --source . \ --platform managed

DigitalOcean

# Create droplet via doctl doctl compute droplet create apso \ --size s-2vcpu-4gb \ --image ubuntu-22-04-x64 \ --region nyc1

Monitoring

Health Endpoint

// Kubernetes-style probes @Get('/healthz') healthz() { return { status: 'ok' }; } @Get('/readyz') async readyz() { await this.db.query('SELECT 1'); return { status: 'ready' }; }

Prometheus Metrics

import { PrometheusModule } from '@willsoto/nestjs-prometheus'; @Module({ imports: [ PrometheusModule.register({ path: '/metrics', defaultMetrics: { enabled: true }, }), ], }) export class AppModule {}

Security Checklist

  • Firewall configured (only 80, 443 open)
  • SSH key authentication only
  • Database not exposed publicly
  • Environment variables secured
  • SSL/TLS enabled
  • Rate limiting configured
  • Security headers set
  • Log rotation enabled
  • Automated backups
  • Monitoring alerts
Last updated on