# Phase 2 Infrastructure Plan **Project**: Tractatus AI Safety Framework Website **Phase**: 2 of 3 **Created**: 2025-10-07 **Owner**: John Stroh **Status**: Planning **Target Deployment**: TBD (awaiting Phase 2 approval) --- ## Table of Contents 1. [Architecture Overview](#architecture-overview) 2. [Server Specifications](#server-specifications) 3. [Network Architecture](#network-architecture) 4. [Deployment Procedures](#deployment-procedures) 5. [Security Hardening](#security-hardening) 6. [Monitoring & Alerting](#monitoring--alerting) 7. [Backup & Disaster Recovery](#backup--disaster-recovery) 8. [DNS & Domain Configuration](#dns--domain-configuration) 9. [SSL/TLS Configuration](#ssltls-configuration) 10. [Environment Configuration](#environment-configuration) 11. [Deployment Checklist](#deployment-checklist) --- ## Architecture Overview ### High-Level Architecture ``` ┌─────────────────────────────────────────────────────────────┐ │ Internet │ └────────────────────┬────────────────────────────────────────┘ │ ┌────────▼────────┐ │ Cloudflare │ (Optional CDN + DDoS protection) │ DNS + Proxy │ └────────┬────────┘ │ ┌────────▼────────┐ │ OVHCloud VPS │ (Ubuntu 22.04 LTS) │ agenticgovernance.digital │ └────────┬────────┘ │ ┌────────────┴────────────┐ │ │ ┌────▼─────┐ ┌──────▼──────┐ │ Nginx │ │ Fail2ban │ │ :80/443 │ │ Firewall │ └────┬─────┘ └─────────────┘ │ ┌────▼─────┐ │ Node.js │ │ Express │ │ :9000 │ └────┬─────┘ │ ┌────▼─────┐ │ MongoDB │ │ :27017 │ └──────────┘ ``` ### Component Stack | Layer | Component | Version | Purpose | |-------|-----------|---------|---------| | **CDN** | Cloudflare | Free tier | DDoS protection, CDN (optional) | | **DNS** | Cloudflare/OVH | - | Domain nameservers | | **Firewall** | UFW + Fail2ban | Latest | Perimeter security | | **Web Server** | Nginx | 1.24+ | Reverse proxy, SSL termination | | **Application** | Node.js + Express | 18 LTS + 4.x | Tractatus platform | | **Database** | MongoDB | 7.x | Document storage | | **Process Manager** | systemd | System default | Service management | | **SSL/TLS** | Let's Encrypt | Latest | HTTPS certificates | | **Email** | ProtonBridge | Latest | SMTP gateway | | **Analytics** | Plausible (self-hosted) | Latest | Privacy-respecting analytics | | **Monitoring** | Self-hosted scripts | Custom | Uptime, performance | --- ## Server Specifications ### Recommended Configuration (OVHCloud VPS Essential) **Compute**: - vCores: 2 (Intel Xeon or AMD EPYC) - RAM: 4GB DDR4 - Storage: 80GB SSD NVMe - Architecture: x86_64 **Network**: - Bandwidth: 500 Mbps - Traffic: Unlimited - IPv4: 1 dedicated - IPv6: 1 dedicated (/64 subnet) - Anti-DDoS: Included **Operating System**: - Distribution: Ubuntu 22.04 LTS (Jammy Jellyfish) - Kernel: 5.15+ (HWE) - Init system: systemd **Geographic Location**: - Preferred: Singapore or Australia (closest to NZ) - Alternative: Europe (if latency acceptable) - Avoid: US East/West (regulatory, latency) **Cost**: ~$20-30/month USD --- ### Server Sizing Rationale **Memory Allocation**: - MongoDB: ~1.5GB (production database + WiredTiger cache) - Node.js: ~1GB (application + dependencies) - Nginx: ~100MB (minimal footprint) - System: ~500MB (OS, utilities) - Plausible Analytics: ~500MB (if self-hosted) - Buffer: ~400MB (peak load) - **Total**: ~4GB (fits VPS Essential) **Storage Allocation**: - OS + System: ~10GB - MongoDB data: ~20GB (estimated Year 1) - Application code: ~2GB (node_modules) - Logs: ~5GB (1-year retention with rotation) - Backups (on-server): ~20GB (7-day retention) - Free space: ~23GB (buffer) - **Total**: ~80GB (VPS Essential) **CPU Usage**: - Typical: <20% (2 vCores) - Peak: <60% (during deployments, backups) - Acceptable: 2 vCores sufficient for Phase 2 traffic --- ## Network Architecture ### Firewall Rules (UFW) **Allow**: ```bash # SSH (restricted to specific IPs in production) ufw allow from to any port 22 proto tcp comment 'SSH Admin' # HTTP (redirect to HTTPS) ufw allow 80/tcp comment 'HTTP' # HTTPS ufw allow 443/tcp comment 'HTTPS' # MongoDB (localhost only, no external access) ufw allow from 127.0.0.1 to any port 27017 proto tcp comment 'MongoDB local' ``` **Deny** (default): ```bash # Default deny incoming ufw default deny incoming # Default allow outgoing (for apt, npm, git) ufw default allow outgoing ``` **Activate**: ```bash ufw enable ufw status verbose ``` --- ### Port Configuration | Service | Port | Bind Address | Firewall | Notes | |---------|------|--------------|----------|-------| | **SSH** | 22 | 0.0.0.0 | Restricted IP | Key-only auth | | **HTTP** | 80 | 0.0.0.0 | Allow | Redirect to 443 | | **HTTPS** | 443 | 0.0.0.0 | Allow | Nginx reverse proxy | | **Node.js** | 9000 | 127.0.0.1 | Deny | Internal only | | **MongoDB** | 27017 | 127.0.0.1 | Deny | Internal only | --- ## Deployment Procedures ### Initial Server Setup #### 1. Provision VPS **OVHCloud Control Panel**: 1. Select VPS Essential tier 2. Choose Ubuntu 22.04 LTS 3. Select geographic region (Singapore/Australia) 4. Generate root password (save securely) 5. Provision (5-10 minutes) **Verify Access**: ```bash ssh root@ ``` --- #### 2. Create Non-Root User ```bash # Create deploy user adduser tractatus usermod -aG sudo tractatus # Set up SSH key auth mkdir -p /home/tractatus/.ssh chmod 700 /home/tractatus/.ssh ``` **On local machine**: ```bash # Generate SSH key (if not exists) ssh-keygen -t ed25519 -C "tractatus-deploy" # Copy public key to server ssh-copy-id tractatus@ ``` **Test**: ```bash ssh tractatus@ ``` --- #### 3. Harden SSH ```bash # Edit SSH config sudo nano /etc/ssh/sshd_config ``` **Changes**: ``` PermitRootLogin no PasswordAuthentication no PubkeyAuthentication yes Port 22 # Consider changing to non-standard port (2222) AllowUsers tractatus ``` **Restart SSH**: ```bash sudo systemctl restart sshd ``` --- #### 4. System Updates ```bash # Update package lists sudo apt update # Upgrade all packages sudo apt upgrade -y # Install essential tools sudo apt install -y \ curl \ wget \ git \ ufw \ fail2ban \ htop \ vim \ certbot \ python3-certbot-nginx ``` --- #### 5. Configure Firewall ```bash # Allow SSH (before enabling UFW!) sudo ufw allow from to any port 22 proto tcp # Allow HTTP/HTTPS sudo ufw allow 80/tcp sudo ufw allow 443/tcp # Enable firewall sudo ufw enable sudo ufw status verbose ``` --- ### Install Application Stack #### 1. Install Node.js ```bash # Add NodeSource repository (Node 18 LTS) curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash - # Install Node.js sudo apt install -y nodejs # Verify node --version # v18.x.x npm --version # 9.x.x ``` --- #### 2. Install MongoDB ```bash # Import MongoDB public GPG key curl -fsSL https://www.mongodb.org/static/pgp/server-7.0.asc | \ sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/mongodb-server-7.0.gpg # Add MongoDB repository echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu jammy/mongodb-org/7.0 multiverse" | \ sudo tee /etc/apt/sources.list.d/mongodb-org-7.0.list # Update and install sudo apt update sudo apt install -y mongodb-org # Start MongoDB sudo systemctl start mongod sudo systemctl enable mongod # Verify sudo systemctl status mongod mongosh --eval 'db.version()' # 7.0.x ``` --- #### 3. Install Nginx ```bash # Install Nginx sudo apt install -y nginx # Start Nginx sudo systemctl start nginx sudo systemctl enable nginx # Verify sudo systemctl status nginx nginx -v # nginx/1.24.x ``` --- ### Deploy Application #### 1. Clone Repository ```bash # Create application directory sudo mkdir -p /var/www/tractatus sudo chown tractatus:tractatus /var/www/tractatus # Clone repository cd /var/www/tractatus git clone https://github.com/your-org/tractatus.git . # Install dependencies npm install --production ``` --- #### 2. Configure Environment ```bash # Create production environment file cp .env.example .env.production # Edit configuration nano .env.production ``` **Production Environment Variables**: ```bash # Application NODE_ENV=production PORT=9000 APP_NAME=Tractatus # MongoDB MONGODB_URI=mongodb://localhost:27017/tractatus_prod MONGODB_PORT=27017 # JWT JWT_SECRET= JWT_EXPIRY=7d JWT_AUDIENCE=tractatus-admin JWT_ISSUER=tractatus # Claude API CLAUDE_API_KEY= CLAUDE_MODEL=claude-sonnet-4-5-20250929 CLAUDE_MAX_TOKENS=200000 # Email (ProtonBridge) SMTP_HOST=127.0.0.1 SMTP_PORT=1025 SMTP_USER=contact@agenticgovernance.digital SMTP_PASSWORD= SMTP_FROM=contact@agenticgovernance.digital # Admin ADMIN_EMAIL=john.stroh.nz@pm.me # Logging LOG_LEVEL=info LOG_FILE=/var/log/tractatus/app.log ``` **Generate JWT Secret**: ```bash node -e "console.log(require('crypto').randomBytes(64).toString('hex'))" ``` --- #### 3. Database Initialization ```bash # Create production database and admin user mongosh tractatus_prod --eval " db.createUser({ user: 'tractatus', pwd: '', roles: [{ role: 'readWrite', db: 'tractatus_prod' }] }) " # Run migration scripts npm run init:db # Seed admin user npm run seed:admin ``` --- #### 4. Build Assets ```bash # Build Tailwind CSS for production npm run build:css # Verify build ls -lh public/css/tailwind.css # Should be ~24KB minified ``` --- #### 5. Create Systemd Service ```bash # Create service file sudo nano /etc/systemd/system/tractatus.service ``` **Service Configuration**: ```ini [Unit] Description=Tractatus AI Safety Framework Documentation=https://agenticgovernance.digital/docs After=network.target mongod.service [Service] Type=simple User=tractatus WorkingDirectory=/var/www/tractatus Environment=NODE_ENV=production EnvironmentFile=/var/www/tractatus/.env.production ExecStart=/usr/bin/node src/server.js Restart=on-failure RestartSec=10 StandardOutput=journal StandardError=journal SyslogIdentifier=tractatus # Security NoNewPrivileges=true PrivateTmp=true [Install] WantedBy=multi-user.target ``` **Enable and Start**: ```bash # Reload systemd sudo systemctl daemon-reload # Enable service (start on boot) sudo systemctl enable tractatus.service # Start service sudo systemctl start tractatus.service # Verify sudo systemctl status tractatus.service journalctl -u tractatus.service -f ``` --- ### Configure Nginx #### 1. Create Nginx Configuration ```bash # Create site configuration sudo nano /etc/nginx/sites-available/tractatus ``` **Nginx Configuration**: ```nginx # Upstream Node.js application upstream tractatus_app { server 127.0.0.1:9000; keepalive 64; } # HTTP (redirect to HTTPS) server { listen 80; listen [::]:80; server_name agenticgovernance.digital www.agenticgovernance.digital; # Let's Encrypt verification location /.well-known/acme-challenge/ { root /var/www/html; } # Redirect to HTTPS location / { return 301 https://$server_name$request_uri; } } # HTTPS server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name agenticgovernance.digital www.agenticgovernance.digital; # SSL certificates (Let's Encrypt) ssl_certificate /etc/letsencrypt/live/agenticgovernance.digital/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/agenticgovernance.digital/privkey.pem; ssl_trusted_certificate /etc/letsencrypt/live/agenticgovernance.digital/chain.pem; # SSL configuration (Mozilla Intermediate) ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384'; ssl_prefer_server_ciphers off; # SSL session cache ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; # OCSP stapling ssl_stapling on; ssl_stapling_verify on; resolver 1.1.1.1 1.0.0.1 valid=300s; resolver_timeout 5s; # Security headers add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always; add_header X-Frame-Options "DENY" always; add_header X-Content-Type-Options "nosniff" always; add_header X-XSS-Protection "1; mode=block" always; add_header Referrer-Policy "no-referrer-when-downgrade" always; add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data:; font-src 'self'; connect-src 'self'; frame-ancestors 'none'; base-uri 'self'; form-action 'self'" always; # Logging access_log /var/log/nginx/tractatus-access.log; error_log /var/log/nginx/tractatus-error.log; # Root and index root /var/www/tractatus/public; index index.html; # Static files (served directly by Nginx) location ~* \.(css|js|jpg|jpeg|png|gif|ico|svg|webp|woff|woff2|ttf|eot)$ { expires 1y; add_header Cache-Control "public, immutable"; } # API and dynamic routes (proxy to Node.js) location /api/ { proxy_pass http://tractatus_app; 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; proxy_read_timeout 60s; } # Try static files first, then proxy to Node.js location / { try_files $uri $uri/ @nodejs; } location @nodejs { proxy_pass http://tractatus_app; 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; } # Security: Deny access to sensitive files location ~ /\. { deny all; } location ~ /\.git { deny all; } location ~ /node_modules { deny all; } location ~ /\.env { deny all; } } ``` **Enable Site**: ```bash # Create symlink sudo ln -s /etc/nginx/sites-available/tractatus /etc/nginx/sites-enabled/ # Remove default site sudo rm /etc/nginx/sites-enabled/default # Test configuration sudo nginx -t # Reload Nginx sudo systemctl reload nginx ``` --- ### SSL/TLS Setup (Let's Encrypt) ```bash # Obtain SSL certificate sudo certbot --nginx -d agenticgovernance.digital -d www.agenticgovernance.digital # Follow prompts: # - Enter email: john.stroh.nz@pm.me # - Agree to terms # - Redirect HTTP to HTTPS: Yes # Verify auto-renewal sudo certbot renew --dry-run # Auto-renewal is configured via systemd timer sudo systemctl list-timers | grep certbot ``` **Certificate Renewal** (automatic): ```bash # Certbot creates a systemd timer for auto-renewal # Certificates renew 30 days before expiry # No manual intervention needed ``` --- ## Security Hardening ### Fail2ban Configuration ```bash # Install Fail2ban (if not already) sudo apt install -y fail2ban # Create local configuration sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local sudo nano /etc/fail2ban/jail.local ``` **Jail Configuration**: ```ini [DEFAULT] bantime = 3600 # 1 hour ban findtime = 600 # 10 minutes maxretry = 5 # 5 attempts before ban [sshd] enabled = true port = 22 filter = sshd logpath = /var/log/auth.log [nginx-http-auth] enabled = true port = 80,443 filter = nginx-http-auth logpath = /var/log/nginx/error.log [nginx-limit-req] enabled = true port = 80,443 filter = nginx-limit-req logpath = /var/log/nginx/error.log maxretry = 10 ``` **Restart**: ```bash sudo systemctl restart fail2ban sudo systemctl enable fail2ban # Verify sudo fail2ban-client status ``` --- ### MongoDB Security ```bash # Enable authentication sudo nano /etc/mongod.conf ``` **Add**: ```yaml security: authorization: enabled net: bindIp: 127.0.0.1 port: 27017 ``` **Restart MongoDB**: ```bash sudo systemctl restart mongod ``` --- ### Automatic Security Updates ```bash # Install unattended-upgrades sudo apt install -y unattended-upgrades # Configure sudo dpkg-reconfigure -plow unattended-upgrades # Select "Yes" to enable # Verify sudo cat /etc/apt/apt.conf.d/20auto-upgrades ``` --- ## Monitoring & Alerting ### Log Management ```bash # Create log directories sudo mkdir -p /var/log/tractatus sudo chown tractatus:tractatus /var/log/tractatus # Configure logrotate sudo nano /etc/logrotate.d/tractatus ``` **Logrotate Configuration**: ``` /var/log/tractatus/*.log { daily rotate 7 compress delaycompress missingok notifempty create 0640 tractatus tractatus sharedscripts postrotate systemctl reload tractatus >/dev/null 2>&1 || true endscript } ``` --- ### Uptime Monitoring Script ```bash # Create monitoring script sudo nano /usr/local/bin/tractatus-healthcheck.sh ``` **Script**: ```bash #!/bin/bash # Healthcheck endpoint URL="https://agenticgovernance.digital/health" # Check if site is up HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" $URL) if [ "$HTTP_CODE" != "200" ]; then # Alert (email to admin) echo "Tractatus is DOWN! HTTP code: $HTTP_CODE" | \ mail -s "ALERT: Tractatus Down" john.stroh.nz@pm.me exit 1 fi exit 0 ``` **Cron Job** (every 5 minutes): ```bash # Make executable sudo chmod +x /usr/local/bin/tractatus-healthcheck.sh # Add to crontab sudo crontab -e ``` **Add**: ``` */5 * * * * /usr/local/bin/tractatus-healthcheck.sh ``` --- ## Backup & Disaster Recovery ### MongoDB Backup Script ```bash # Create backup directory sudo mkdir -p /var/backups/tractatus/mongodb sudo chown tractatus:tractatus /var/backups/tractatus/mongodb # Create backup script nano /home/tractatus/backup-mongodb.sh ``` **Script**: ```bash #!/bin/bash # Configuration BACKUP_DIR="/var/backups/tractatus/mongodb" DB_NAME="tractatus_prod" DATE=$(date +%Y%m%d_%H%M%S) RETENTION_DAYS=7 # Create backup mongodump --db $DB_NAME --out $BACKUP_DIR/$DATE # Compress backup tar -czf $BACKUP_DIR/tractatus_backup_$DATE.tar.gz -C $BACKUP_DIR $DATE rm -rf $BACKUP_DIR/$DATE # Delete old backups find $BACKUP_DIR -name "tractatus_backup_*.tar.gz" -mtime +$RETENTION_DAYS -delete echo "Backup completed: $BACKUP_DIR/tractatus_backup_$DATE.tar.gz" ``` **Cron Job** (daily at 2am): ```bash chmod +x /home/tractatus/backup-mongodb.sh crontab -e ``` **Add**: ``` 0 2 * * * /home/tractatus/backup-mongodb.sh >> /var/log/tractatus/backup.log 2>&1 ``` --- ### Disaster Recovery Procedure **Scenario**: Server failure, data loss **Recovery Steps**: 1. **Provision New Server** (same specs) 2. **Restore Application**: ```bash # Clone repository git clone https://github.com/your-org/tractatus.git /var/www/tractatus # Restore environment file scp .env.production tractatus@:/var/www/tractatus/ ``` 3. **Restore Database**: ```bash # Copy backup to new server scp tractatus_backup_YYYYMMDD.tar.gz tractatus@:/tmp/ # Extract and restore tar -xzf /tmp/tractatus_backup_YYYYMMDD.tar.gz -C /tmp/ mongorestore --db tractatus_prod /tmp/YYYYMMDD/tractatus_prod ``` 4. **Reconfigure DNS** (if IP changed) 5. **Verify**: ```bash curl https://agenticgovernance.digital/health ``` **RTO** (Recovery Time Objective): <4 hours **RPO** (Recovery Point Objective): 24 hours (daily backups) --- ## DNS & Domain Configuration ### Cloudflare DNS Setup **A Records**: ``` Type: A Name: @ Content: Proxy status: Proxied (or DNS only) TTL: Auto ``` ``` Type: A Name: www Content: Proxy status: Proxied (or DNS only) TTL: Auto ``` **AAAA Records** (IPv6): ``` Type: AAAA Name: @ Content: Proxy status: Proxied TTL: Auto ``` **MX Records** (if using custom email): ``` Type: MX Name: @ Content: mail.protonmail.ch Priority: 10 ``` **TXT Records** (SPF, DKIM): ``` Type: TXT Name: @ Content: v=spf1 include:_spf.protonmail.ch ~all ``` --- ## Environment Configuration ### Production .env File **Template** (already shown above, see Deploy Application > Configure Environment) **Security**: ```bash # Restrict permissions chmod 600 /var/www/tractatus/.env.production # Verify ls -l /var/www/tractatus/.env.production # Should show: -rw------- (owner only) ``` --- ## Deployment Checklist ### Pre-Deployment - [ ] OVHCloud VPS provisioned (Essential tier) - [ ] Domain registered (agenticgovernance.digital) - [ ] Cloudflare account created (optional) - [ ] DNS configured (A/AAAA records pointing to server) - [ ] SSH key generated and added to server - [ ] John Stroh has admin access --- ### Server Setup - [ ] Ubuntu 22.04 LTS installed - [ ] Non-root user created (tractatus) - [ ] SSH hardened (key-only, no root) - [ ] Firewall configured (UFW) - [ ] Fail2ban installed and configured - [ ] Automatic security updates enabled --- ### Application Stack - [ ] Node.js 18 LTS installed - [ ] MongoDB 7.x installed and running - [ ] Nginx installed and running - [ ] Application repository cloned - [ ] npm dependencies installed (`npm install --production`) - [ ] Environment file configured (.env.production) - [ ] Database initialized (`npm run init:db`) - [ ] Admin user created (`npm run seed:admin`) - [ ] Tailwind CSS built (`npm run build:css`) --- ### Service Configuration - [ ] systemd service created (tractatus.service) - [ ] Service enabled and started - [ ] Service logs verified (`journalctl -u tractatus`) - [ ] Nginx configured (sites-available/tractatus) - [ ] Nginx configuration tested (`nginx -t`) - [ ] SSL certificates obtained (Let's Encrypt) - [ ] HTTPS redirect working --- ### Security - [ ] Firewall rules verified (`ufw status`) - [ ] SSH access tested (key-only) - [ ] MongoDB authentication enabled - [ ] MongoDB bound to localhost only - [ ] Application environment secrets secure (chmod 600) - [ ] Security headers verified (browser dev tools) - [ ] SSL Labs test: A+ rating (https://www.ssllabs.com/ssltest/) --- ### Monitoring - [ ] Log rotation configured (logrotate) - [ ] Uptime monitoring script installed - [ ] Backup script configured and tested - [ ] Email alerts configured (john.stroh.nz@pm.me) - [ ] Plausible Analytics installed (optional, self-hosted) --- ### Testing - [ ] Homepage loads: https://agenticgovernance.digital/ - [ ] API health check: https://agenticgovernance.digital/health - [ ] Document viewer: https://agenticgovernance.digital/docs-viewer.html - [ ] Admin login: https://agenticgovernance.digital/admin/login.html - [ ] Static assets loading (CSS, JS) - [ ] CSP compliance (no console errors) - [ ] Mobile responsiveness (test on phone) --- ### Post-Deployment - [ ] DNS propagation complete (24-48 hours) - [ ] SSL certificate auto-renewal tested (`certbot renew --dry-run`) - [ ] Backup restore tested (disaster recovery drill) - [ ] Performance baseline recorded (Lighthouse, WebPageTest) - [ ] Monitoring alerts tested (trigger fake downtime) --- ## Appendix: Quick Commands ### Service Management ```bash # Restart application sudo systemctl restart tractatus.service # View logs sudo journalctl -u tractatus.service -f # Check status sudo systemctl status tractatus.service ``` ### Nginx ```bash # Test configuration sudo nginx -t # Reload configuration sudo systemctl reload nginx # View error log sudo tail -f /var/log/nginx/tractatus-error.log ``` ### MongoDB ```bash # Connect to database mongosh tractatus_prod # Backup manually mongodump --db tractatus_prod --out /tmp/backup # Restore from backup mongorestore --db tractatus_prod /tmp/backup/tractatus_prod ``` ### SSL ```bash # Renew certificates manually sudo certbot renew # Check certificate expiry sudo certbot certificates ``` --- ## Revision History | Date | Version | Changes | |------|---------|---------| | 2025-10-07 | 1.0 | Initial infrastructure plan for Phase 2 | --- **Document Owner**: John Stroh **Last Updated**: 2025-10-07 **Next Review**: Upon deployment completion