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>
520 lines
10 KiB
Markdown
520 lines
10 KiB
Markdown
# 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)
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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:**
|
|
```bash
|
|
ssh nasty.sh "hostname && uptime"
|
|
# Should show VPS hostname and uptime
|
|
```
|
|
|
|
---
|
|
|
|
## Step 2: Set Up WireGuard VPN on Apricot
|
|
|
|
### Install WireGuard (if needed)
|
|
|
|
```bash
|
|
# On apricot (Fedora)
|
|
sudo dnf install wireguard-tools
|
|
|
|
# Verify installation
|
|
wg --version
|
|
```
|
|
|
|
### Generate WireGuard Keys
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# SSH to VPS
|
|
ssh nasty.sh
|
|
|
|
# Install WireGuard
|
|
apt-get update
|
|
apt-get install -y wireguard
|
|
```
|
|
|
|
### Generate VPS Keys
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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)
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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:
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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:
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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
|