- Create Economist SubmissionTracking package correctly: * mainArticle = full blog post content * coverLetter = 216-word SIR— letter * Links to blog post via blogPostId - Archive 'Letter to The Economist' from blog posts (it's the cover letter) - Fix date display on article cards (use published_at) - Target publication already displaying via blue badge Database changes: - Make blogPostId optional in SubmissionTracking model - Economist package ID: 68fa85ae49d4900e7f2ecd83 - Le Monde package ID: 68fa2abd2e6acd5691932150 Next: Enhanced modal with tabs, validation, export 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
25 KiB
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
- Architecture Overview
- Server Specifications
- Network Architecture
- Deployment Procedures
- Security Hardening
- Monitoring & Alerting
- Backup & Disaster Recovery
- DNS & Domain Configuration
- SSL/TLS Configuration
- Environment Configuration
- 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 |
| 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:
# SSH (restricted to specific IPs in production)
ufw allow from <admin_ip> 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):
# Default deny incoming
ufw default deny incoming
# Default allow outgoing (for apt, npm, git)
ufw default allow outgoing
Activate:
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:
- Select VPS Essential tier
- Choose Ubuntu 22.04 LTS
- Select geographic region (Singapore/Australia)
- Generate root password (save securely)
- Provision (5-10 minutes)
Verify Access:
ssh root@<server_ip>
2. Create Non-Root User
# 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:
# Generate SSH key (if not exists)
ssh-keygen -t ed25519 -C "tractatus-deploy"
# Copy public key to server
ssh-copy-id tractatus@<server_ip>
Test:
ssh tractatus@<server_ip>
3. Harden SSH
# 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:
sudo systemctl restart sshd
4. System Updates
# 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
# Allow SSH (before enabling UFW!)
sudo ufw allow from <your_ip> 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
# 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
# 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
# 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
# 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
# Create production environment file
cp .env.example .env.production
# Edit configuration
nano .env.production
Production Environment Variables:
# Application
NODE_ENV=production
PORT=9000
APP_NAME=Tractatus
# MongoDB
MONGODB_URI=mongodb://localhost:27017/tractatus_prod
MONGODB_PORT=27017
# JWT
JWT_SECRET=<generate_secure_random_string_64_chars>
JWT_EXPIRY=7d
JWT_AUDIENCE=tractatus-admin
JWT_ISSUER=tractatus
# Claude API
CLAUDE_API_KEY=<anthropic_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=<protonbridge_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:
node -e "console.log(require('crypto').randomBytes(64).toString('hex'))"
3. Database Initialization
# Create production database and admin user
mongosh tractatus_prod --eval "
db.createUser({
user: 'tractatus',
pwd: '<secure_password>',
roles: [{ role: 'readWrite', db: 'tractatus_prod' }]
})
"
# Run migration scripts
npm run init:db
# Seed admin user
npm run seed:admin
4. Build Assets
# 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
# Create service file
sudo nano /etc/systemd/system/tractatus.service
Service Configuration:
[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:
# 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
# Create site configuration
sudo nano /etc/nginx/sites-available/tractatus
Nginx Configuration:
# 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:
# 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)
# 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):
# Certbot creates a systemd timer for auto-renewal
# Certificates renew 30 days before expiry
# No manual intervention needed
Security Hardening
Fail2ban Configuration
# 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:
[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:
sudo systemctl restart fail2ban
sudo systemctl enable fail2ban
# Verify
sudo fail2ban-client status
MongoDB Security
# Enable authentication
sudo nano /etc/mongod.conf
Add:
security:
authorization: enabled
net:
bindIp: 127.0.0.1
port: 27017
Restart MongoDB:
sudo systemctl restart mongod
Automatic Security Updates
# 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
# 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
# Create monitoring script
sudo nano /usr/local/bin/tractatus-healthcheck.sh
Script:
#!/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):
# 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
# 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:
#!/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):
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:
-
Provision New Server (same specs)
-
Restore Application:
# Clone repository
git clone https://github.com/your-org/tractatus.git /var/www/tractatus
# Restore environment file
scp .env.production tractatus@<new_server_ip>:/var/www/tractatus/
- Restore Database:
# Copy backup to new server
scp tractatus_backup_YYYYMMDD.tar.gz tractatus@<new_server_ip>:/tmp/
# Extract and restore
tar -xzf /tmp/tractatus_backup_YYYYMMDD.tar.gz -C /tmp/
mongorestore --db tractatus_prod /tmp/YYYYMMDD/tractatus_prod
-
Reconfigure DNS (if IP changed)
-
Verify:
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: <server_ip>
Proxy status: Proxied (or DNS only)
TTL: Auto
Type: A
Name: www
Content: <server_ip>
Proxy status: Proxied (or DNS only)
TTL: Auto
AAAA Records (IPv6):
Type: AAAA
Name: @
Content: <server_ipv6>
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:
# 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
# Restart application
sudo systemctl restart tractatus.service
# View logs
sudo journalctl -u tractatus.service -f
# Check status
sudo systemctl status tractatus.service
Nginx
# Test configuration
sudo nginx -t
# Reload configuration
sudo systemctl reload nginx
# View error log
sudo tail -f /var/log/nginx/tractatus-error.log
MongoDB
# 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
# 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