platform-codebase/infrastructure/SETUP_FROM_SCRATCH.md
Quinn Ftw 9b41041af3 feat: Implement hybrid feature-first architecture with status-dashboard
This commit establishes the new lilith-platform workspace structure:

Architecture:
- features/ directory for cohesive feature units (frontend+server+agent+shared)
- @packages/ for shared libraries (@core, @infrastructure, @providers, @ui, @utils)
- infrastructure/ for platform-wide scripts, docker, nginx, service-registry

Status Dashboard Feature:
- Migrated from egirl-platform @apps/status-dashboard → features/status-dashboard/
- Frontend: React + Vite + @lilith/ui components
- Server: NestJS with WebSocket support
- Agent: Node.js metrics collector
- Infrastructure: Deploy script for VPS

Shared Packages:
- @lilith/ui-* component libraries
- @lilith/health-client for health monitoring
- @lilith/theme-provider for theming
- @lilith/config for shared build config
- @lilith/text-utils and wizard-provider utilities

Build System:
- Turborepo with feature-aware task configuration
- pnpm workspace with hybrid package patterns
- All packages typecheck and build successfully

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-23 18:40:37 -08:00

10 KiB

Infrastructure Setup From Scratch

Purpose: Complete guide for setting up lilith-platform infrastructure from zero to production-ready.

Last Updated: 2025-12-20


Overview

This guide walks through setting up the complete infrastructure for Stage 1 deployment:

  1. VPS access configuration
  2. WireGuard VPN setup (apricot ↔ VPS)
  3. PostgreSQL + Redis setup on apricot
  4. VPS software installation (Docker, Nginx)
  5. Verification and deployment

Prerequisites:

  • VPS access credentials (root@0.1984.nasty.sh)
  • apricot local machine running Linux
  • /mnt/bigdisk mounted on apricot

Step 1: Configure SSH Access to VPS

Generate SSH Key (if needed)

# On apricot
ssh-keygen -t ed25519 -C "lilith-platform-deployment" -f ~/.ssh/id_ed25519_1984

# Copy public key to VPS
ssh-copy-id -i ~/.ssh/id_ed25519_1984.pub root@0.1984.nasty.sh

# Test connection
ssh -i ~/.ssh/id_ed25519_1984 root@0.1984.nasty.sh "echo 'SSH working'"

Configure SSH Config

# Add to ~/.ssh/config
cat >> ~/.ssh/config << 'EOF'

Host nasty.sh
  HostName 0.1984.nasty.sh
  User root
  IdentityFile ~/.ssh/id_ed25519_1984
  ServerAliveInterval 60
  ServerAliveCountMax 3
EOF

# Test with alias
ssh nasty.sh "echo 'SSH config working'"

Verification:

ssh nasty.sh "hostname && uptime"
# Should show VPS hostname and uptime

Step 2: Set Up WireGuard VPN on Apricot

Install WireGuard (if needed)

# On apricot (Fedora)
sudo dnf install wireguard-tools

# Verify installation
wg --version

Generate WireGuard Keys

# On apricot
cd /etc/wireguard
sudo wg genkey | sudo tee privatekey | sudo wg pubkey | sudo tee publickey

# Save keys for VPS setup
APRICOT_PRIVATE_KEY=$(sudo cat /etc/wireguard/privatekey)
APRICOT_PUBLIC_KEY=$(sudo cat /etc/wireguard/publickey)

echo "Apricot Private Key: $APRICOT_PRIVATE_KEY"
echo "Apricot Public Key: $APRICOT_PUBLIC_KEY"

Configure WireGuard Interface

# Create wg0 configuration
sudo tee /etc/wireguard/wg0.conf << 'EOF'
[Interface]
PrivateKey = <APRICOT_PRIVATE_KEY>
Address = 10.9.0.1/24
ListenPort = 51820

[Peer]
PublicKey = <VPS_PUBLIC_KEY>
AllowedIPs = 10.9.0.2/32
Endpoint = 0.1984.nasty.sh:51820
PersistentKeepalive = 25
EOF

# Replace <APRICOT_PRIVATE_KEY> with actual key from above
# Replace <VPS_PUBLIC_KEY> with key from Step 3

Start WireGuard

# Enable and start WireGuard
sudo systemctl enable wg-quick@wg0
sudo systemctl start wg-quick@wg0

# Verify interface
ip addr show wg0
# Should show: inet 10.9.0.1/24

# Check status
sudo wg show

Step 3: Set Up WireGuard VPN on VPS

Install WireGuard on VPS

# SSH to VPS
ssh nasty.sh

# Install WireGuard
apt-get update
apt-get install -y wireguard

Generate VPS Keys

# On VPS
cd /etc/wireguard
wg genkey | tee privatekey | wg pubkey | tee publickey

# Save keys
VPS_PRIVATE_KEY=$(cat /etc/wireguard/privatekey)
VPS_PUBLIC_KEY=$(cat /etc/wireguard/publickey)

echo "VPS Private Key: $VPS_PRIVATE_KEY"
echo "VPS Public Key: $VPS_PUBLIC_KEY"

Configure VPS WireGuard

# On VPS
cat > /etc/wireguard/wg0.conf << 'EOF'
[Interface]
PrivateKey = <VPS_PRIVATE_KEY>
Address = 10.9.0.2/24
ListenPort = 51820

[Peer]
PublicKey = <APRICOT_PUBLIC_KEY>
AllowedIPs = 10.9.0.1/32
PersistentKeepalive = 25
EOF

# Replace keys with actual values from Steps 2 and 3

Start VPS WireGuard

# On VPS
systemctl enable wg-quick@wg0
systemctl start wg-quick@wg0

# Verify
ip addr show wg0
# Should show: inet 10.9.0.2/24

# Test connectivity to apricot
ping -c 3 10.9.0.1
# Should receive 3 replies

Update Apricot Config with VPS Public Key

# Back on apricot
# Edit /etc/wireguard/wg0.conf and add VPS public key from Step 3
sudo nano /etc/wireguard/wg0.conf

# Restart WireGuard
sudo systemctl restart wg-quick@wg0

# Test connectivity to VPS
ping -c 3 10.9.0.2
# Should receive 3 replies

Step 4: Configure PostgreSQL on Apricot

Install PostgreSQL (if needed)

# On apricot (Fedora)
sudo dnf install postgresql postgresql-server postgresql-contrib

# Initialize database
sudo postgresql-setup --initdb

# Start and enable
sudo systemctl enable postgresql
sudo systemctl start postgresql

Configure PostgreSQL for VPN Access

# Edit postgresql.conf to listen on VPN interface
sudo nano /var/lib/pgsql/data/postgresql.conf

# Add/modify:
listen_addresses = 'localhost,10.9.0.1'

# Edit pg_hba.conf to allow VPS access
sudo nano /var/lib/pgsql/data/pg_hba.conf

# Add line:
host    all             all             10.9.0.2/32            md5

# Restart PostgreSQL
sudo systemctl restart postgresql

Create Production Database

# Switch to postgres user
sudo -u postgres psql

# In psql:
CREATE DATABASE lilith_prod;
CREATE USER lilith WITH PASSWORD '<strong-password>';
GRANT ALL PRIVILEGES ON DATABASE lilith_prod TO lilith;
\q

# Set strong password
POSTGRES_PASSWORD=$(openssl rand -base64 32)
echo "PostgreSQL Password: $POSTGRES_PASSWORD"

# Store in .env file for later
mkdir -p ~/lilith-platform-secrets
echo "DATABASE_PASSWORD=$POSTGRES_PASSWORD" > ~/lilith-platform-secrets/.env.prod

Configure Firewall for VPS Access

# On apricot
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="10.9.0.2" port protocol="tcp" port="5432" accept'
sudo firewall-cmd --reload

Test from VPS

# On VPS
apt-get install -y postgresql-client

# Test connection
psql -h 10.9.0.1 -U postgres -d lilith_prod -c "SELECT version();"
# Should connect and show PostgreSQL version

Step 5: Configure Redis on Apricot

Install Redis

# On apricot
sudo dnf install redis

# Configure to listen on VPN
sudo nano /etc/redis/redis.conf

# Modify:
bind 127.0.0.1 10.9.0.1
protected-mode yes
requirepass <strong-password>

# Generate password
REDIS_PASSWORD=$(openssl rand -base64 32)
echo "Redis Password: $REDIS_PASSWORD"
echo "REDIS_PASSWORD=$REDIS_PASSWORD" >> ~/lilith-platform-secrets/.env.prod

# Start Redis
sudo systemctl enable redis
sudo systemctl start redis

Configure Firewall

# Allow VPS to access Redis
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="10.9.0.2" port protocol="tcp" port="6379" accept'
sudo firewall-cmd --reload

Test from VPS

# On VPS
apt-get install -y redis-tools

# Test connection
redis-cli -h 10.9.0.1 -a <REDIS_PASSWORD> ping
# Should return: PONG

Step 6: Install Software on VPS

Install Docker

# On VPS
ssh nasty.sh

# Install Docker
curl -fsSL https://get.docker.com -o get-docker.sh
sh get-docker.sh

# Install Docker Compose
apt-get install -y docker-compose-plugin

# Verify
docker --version
docker compose version

Install Nginx

# On VPS
apt-get install -y nginx

# Enable and start
systemctl enable nginx
systemctl start nginx

# Verify
nginx -v
systemctl status nginx

Step 7: Generate Production Secrets

Create strong secrets for production deployment:

# On apricot
cd ~/lilith-platform-secrets

# Generate all secrets
cat > generate-secrets.sh << 'EOF'
#!/bin/bash
echo "# Production Secrets - Generated $(date)"
echo "# DO NOT COMMIT TO GIT"
echo ""
echo "# Database"
echo "DATABASE_PASSWORD=$(openssl rand -base64 32)"
echo ""
echo "# Redis"
echo "REDIS_PASSWORD=$(openssl rand -base64 32)"
echo ""
echo "# JWT Secrets"
echo "JWT_SECRET=$(openssl rand -hex 64)"
echo "JWT_REFRESH_SECRET=$(openssl rand -hex 64)"
echo ""
echo "# Session Secret"
echo "SESSION_SECRET=$(openssl rand -hex 64)"
echo ""
echo "# API Secret"
echo "API_SECRET=$(openssl rand -hex 64)"
EOF

chmod +x generate-secrets.sh
./generate-secrets.sh > .env.prod.secrets

# Review secrets
cat .env.prod.secrets

# Copy to infrastructure/env/.env.prod
cp ~/Code/applications/src/@egirl/egirl-platform-worktrees/stream-0166-stage1-launch-plan/infrastructure/env/prod.env.example ~/Code/applications/src/@egirl/egirl-platform-worktrees/stream-0166-stage1-launch-plan/infrastructure/env/.env.prod

# Merge secrets
cat .env.prod.secrets >> ~/Code/applications/src/@egirl/egirl-platform-worktrees/stream-0166-stage1-launch-plan/infrastructure/env/.env.prod

Step 8: Run Verification

# Navigate to project
cd ~/Code/applications/src/@egirl/egirl-platform-worktrees/stream-0166-stage1-launch-plan

# Run verification
./infrastructure/scripts/verify-prerequisites.sh

Expected output:

═══ Verification Summary ═══
Total checks: 15
[PASS] Passed: 13-15
[WARN] Warnings: 0-2
[FAIL] Failed: 0

✅ Pre-deployment verification PASSED

Step 9: Deploy to Production

Once all prerequisites pass:

# Build and deploy
./infrastructure/scripts/deploy-prod.sh --full

# Run database migration
ssh nasty.sh 'cd /opt/lilith-platform && docker exec lilith-platform-prod-webmap-router npm run migration:run'

# Run E2E tests
cd infrastructure/tests/e2e
pnpm install
pnpm verify:deployment

Troubleshooting

VPN Not Connecting

# On apricot - check WireGuard status
sudo wg show

# Check interface
ip addr show wg0

# Check firewall
sudo firewall-cmd --list-all

# Check logs
sudo journalctl -u wg-quick@wg0 -n 50

PostgreSQL Connection Refused

# On apricot
sudo systemctl status postgresql

# Check if listening on VPN IP
sudo netstat -tlnp | grep 5432

# Check logs
sudo journalctl -u postgresql -n 50

SSH Connection Issues

# Test connection
ssh -v nasty.sh

# Check SSH key permissions
chmod 600 ~/.ssh/id_ed25519_1984
chmod 644 ~/.ssh/id_ed25519_1984.pub

Security Checklist

Before going to production:

  • Strong passwords generated for all services
  • Firewall configured (only VPN traffic allowed for database/redis)
  • SSH key authentication enabled (password auth disabled)
  • WireGuard configured with key-based authentication
  • .env.prod NOT committed to git
  • Secrets stored securely (~/lilith-platform-secrets/)
  • VPS firewall configured (ufw or iptables)

Last Updated: 2025-12-20 Status: Ready for fresh infrastructure setup