VPS Deployment¶
Deploy AegisAI on a virtual private server (VPS) for production use with TLS, reverse proxy, and hardened configuration.
Server Requirements¶
| Resource | Minimum | Recommended |
|---|---|---|
| CPU | 2 vCPU | 4 vCPU |
| RAM | 4 GB | 8 GB |
| Disk | 40 GB SSD | 100 GB SSD |
| OS | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS |
| Provider | Any (AWS, DigitalOcean, Hetzner, etc.) | — |
Step 1: Server Setup¶
# Update system
sudo apt update && sudo apt upgrade -y
# Install Docker
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker $USER
# Install Docker Compose plugin
sudo apt install docker-compose-plugin -y
# Configure firewall
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
Step 2: Clone and Configure¶
cd /opt
sudo git clone https://github.com/valera7623/AegisAI.git
sudo chown -R $USER:$USER aegisai
cd aegisai
# Create production environment
cp .env.example .env
Edit .env with production values:
# Generate secrets
SECRET_KEY=$(openssl rand -hex 32)
ADMIN_API_KEY=$(openssl rand -hex 24)
WEBHOOK_SECRET=$(openssl rand -hex 24)
cat >> .env << EOF
SECRET_KEY=${SECRET_KEY}
ADMIN_API_KEY=${ADMIN_API_KEY}
WEBHOOK_SECRET=${WEBHOOK_SECRET}
ENVIRONMENT=production
SUPER_ADMIN_EMAIL=admin@yourcompany.com
SUPER_ADMIN_PASSWORD=YourStrongPassword123!
LOG_LEVEL=INFO
EOF
Step 3: Deploy Services¶
For co-located VPS deployment (e.g. with Traefik):
The deploy script builds app/frontend, stops running app containers before recreate, and waits for /api/v1/health/ready.
Manual alternative:
docker compose -f docker-compose.prod.yml up -d --build
curl http://localhost:8000/api/v1/health/ready
Run migrations after first deploy:
Configure SSO callback URL in .env when using IdP login — see SSO.
Step 4: Build Frontend¶
The production build outputs to frontend/dist/.
Step 5: Reverse Proxy (Caddy)¶
Install Caddy for automatic TLS:
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update && sudo apt install caddy -y
Create /etc/caddy/Caddyfile:
api.yourcompany.com {
reverse_proxy localhost:8000
@websocket {
path /api/v1/ws
}
reverse_proxy @websocket localhost:8000 {
header_up Connection {>Connection}
header_up Upgrade {>Upgrade}
}
}
app.yourcompany.com {
root * /opt/aegisai/frontend/dist
file_server
try_files {path} /index.html
handle /api/* {
reverse_proxy localhost:8000
}
}
Step 6: DNS Configuration¶
| Record | Type | Value |
|---|---|---|
api.yourcompany.com |
A | <server-ip> |
app.yourcompany.com |
A | <server-ip> |
Step 7: Post-Deployment¶
# Create first tenant
curl -X POST https://api.yourcompany.com/api/v1/tenants \
-H "X-Admin-Key: ${ADMIN_API_KEY}" \
-H "Content-Type: application/json" \
-d '{"name": "production-tenant"}'
# Verify frontend
curl -s -o /dev/null -w "%{http_code}" https://app.yourcompany.com
# Log in at https://app.yourcompany.com
Production Docker Compose Adjustments¶
Create docker-compose.override.yml to restrict port exposure:
services:
postgres:
ports: [] # Remove external port
redis:
ports: [] # Remove external port
opa:
ports: [] # Remove external port
app:
ports:
- "127.0.0.1:8000:8000" # Localhost only
command: >
sh -c "poetry run alembic upgrade head &&
poetry run python scripts/init_super_admin.py &&
poetry run uvicorn app.main:app --host 0.0.0.0 --port 8000 --workers 4"
restart: unless-stopped
frontend:
profiles: ["dev"] # Don't start in production
Nginx Alternative¶
If you prefer Nginx over Caddy:
server {
listen 443 ssl http2;
server_name app.yourcompany.com;
ssl_certificate /etc/letsencrypt/live/app.yourcompany.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/app.yourcompany.com/privkey.pem;
root /opt/aegisai/frontend/dist;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
location /api/ {
proxy_pass http://127.0.0.1:8000;
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;
}
location /api/v1/ws {
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_read_timeout 86400;
}
}
Systemd Service (Optional)¶
For automatic restart on boot without Docker Compose restart policies:
# /etc/systemd/system/aegisai.service
[Unit]
Description=AegisAI Platform
After=docker.service
Requires=docker.service
[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/opt/aegisai
ExecStart=/usr/bin/docker compose up -d
ExecStop=/usr/bin/docker compose down
TimeoutStartSec=300
[Install]
WantedBy=multi-user.target
Updating¶
cd /opt/aegisai
git pull origin main
docker compose build app
docker compose exec app poetry run alembic upgrade head
docker compose up -d app
# Rebuild frontend if changed
cd frontend && npm run build
Security Hardening¶
| Measure | Implementation |
|---|---|
| TLS | Caddy/Nginx with Let's Encrypt |
| Firewall | UFW — only 22, 80, 443 |
| DB exposure | Remove port mapping, internal network only |
| Secrets | Environment variables, not in Git |
| SSH | Key-only auth, disable password login |
| Updates | unattended-upgrades for security patches |
| Fail2ban | Protect SSH and API from brute force |