A is for Agent - Production Deployment Guide
This guide covers deploying the Jekyll website to production server 31.97.61.154 with Traefik reverse proxy and OAuth2 authentication.
π Table of Contents
- Architecture Overview
- Prerequisites
- Initial Setup
- Configuration
- Deployment
- Verification
- Troubleshooting
- Maintenance
ποΈ Architecture Overview
Components
Internet (Port 80/443)
β
Traefik Proxy (existing)
β
βββββββ΄βββββββββββββββββββ
β β
OAuth2-Proxy Nginx (Static Site)
(GitHub Auth) (Jekyll Build)
β β
Protected Routes Public Routes
(/portal/*, etc.) (/, /docs/, etc.)
Services
| Service | Container Name | Port | Purpose |
|---|---|---|---|
| Nginx | aifa-site |
80 (internal) | Serves static Jekyll site |
| OAuth2-Proxy | aifa-oauth2-proxy |
4180 (internal) | GitHub authentication |
| Traefik | (existing) | 80, 443 | Reverse proxy, SSL termination |
Networks
traefik-public- External network (connects to Traefik)aifa-internal- Internal network (site β oauth2-proxy)
Routing Rules
| URL Pattern | Authentication | Handler |
|---|---|---|
https://www.aisforagent.net/ |
Public | Nginx β Jekyll site |
https://www.aisforagent.net/portal/* |
Protected | OAuth2-Proxy β Nginx |
https://www.aisforagent.net/workflows/* |
Protected | OAuth2-Proxy β Nginx |
https://www.aisforagent.net/blueprints/* |
Protected | OAuth2-Proxy β Nginx |
https://www.aisforagent.net/playbooks/* |
Protected | OAuth2-Proxy β Nginx |
https://www.aisforagent.net/oauth2/* |
Public | OAuth2-Proxy (auth endpoints) |
β Prerequisites
Local Requirements
- Docker installed and running
- SSH access to production server
- SSH key at
~/git/Foundry/S6web/key.file - Git repository cloned locally
Server Requirements
- β
Traefik already running with
traefik-publicnetwork - β
DNS records pointing to server:
www.aisforagent.netβ31.97.61.154aisforagent.netβ31.97.61.154
- β Ports 80 and 443 accessible
- β
Traefik middleware file at
~/traefik/middlewares.yml
GitHub OAuth Application
Youβll need to create a GitHub OAuth App for authentication:
- Go to GitHub Developer Settings
- Click βNew OAuth Appβ
- Fill in:
- Application name: A is for Agent
- Homepage URL:
https://www.aisforagent.net - Authorization callback URL:
https://www.aisforagent.net/oauth2/callback
- Save and note the Client ID and Client Secret
π Initial Setup
1. Clone Repository (if not already done)
cd ~/git/a/Foundry
git clone <repository-url> aWebsite
cd aWebsite
2. Configure Environment Variables
Copy the example environment file:
cp .env.prod.example .env.prod
Edit .env.prod with your credentials:
nano .env.prod # or use your preferred editor
Required values:
OAUTH2_PROXY_CLIENT_ID- Your GitHub OAuth Client IDOAUTH2_PROXY_CLIENT_SECRET- Your GitHub OAuth Client SecretOAUTH2_PROXY_COOKIE_SECRET- Generate with:openssl rand -base64 32
Example .env.prod:
OAUTH2_PROXY_CLIENT_ID=abc123def456
OAUTH2_PROXY_CLIENT_SECRET=secret789xyz
OAUTH2_PROXY_COOKIE_SECRET=ABCDEFGHabcdefgh1234567890ABCDEF==
DOMAIN=www.aisforagent.net
ENVIRONMENT=production
Optional: Restrict access to specific GitHub users/orgs:
OAUTH2_PROXY_GITHUB_USERS=username1,username2
# or
OAUTH2_PROXY_GITHUB_ORG=your-org-name
3. Add SSH Key to Agent
ssh-add ~/git/Foundry/S6web/key.file
# Enter passphrase when prompted
Verify:
ssh-add -l
βοΈ Configuration
DNS Configuration
Ensure DNS records are set:
# Check DNS resolution
dig www.aisforagent.net +short
# Should return: 31.97.61.154
dig aisforagent.net +short
# Should return: 31.97.61.154
Traefik Middleware
The deployment uses existing Traefik middleware from ~/traefik/middlewares.yml:
frontend-security@file- Security headers for web appscompression@file- Gzip compressionredirect-to-https@file- HTTP to HTTPS redirect
These are already configured on the server.
π’ Deployment
Option 1: Full Deployment (Recommended)
Build locally and deploy to server:
./deploy-prod.sh
# or
./deploy-prod.sh --full
This will:
- β Build Docker image locally
- β Test the image
- β Prepare remote server
- β Transfer all files
- β Build and deploy on server
- β Verify deployment
Option 2: Build Only
Build and test locally without deploying:
./deploy-prod.sh --build-only
Then deploy separately:
./deploy-prod.sh --deploy-only
Option 3: Manual Deployment
If the script doesnβt work, deploy manually:
# 1. Add SSH key
ssh-add ~/git/Foundry/S6web/key.file
# 2. Create remote directory
ssh root@31.97.61.154 "mkdir -p ~/aifa-website"
# 3. Transfer files
scp docker-compose.prod.yml root@31.97.61.154:~/aifa-website/
scp .env.prod root@31.97.61.154:~/aifa-website/
scp Dockerfile root@31.97.61.154:~/aifa-website/
scp nginx.conf root@31.97.61.154:~/aifa-website/
# 4. Transfer site content
rsync -avz --exclude '_site' --exclude '.git' \
-e "ssh" ./ root@31.97.61.154:~/aifa-website/
# 5. Build and deploy
ssh root@31.97.61.154 "cd ~/aifa-website && docker-compose -f docker-compose.prod.yml up -d --build"
β Verification
1. Check Container Status
ssh root@31.97.61.154 "docker ps | grep aifa"
Expected output:
aifa-site Up X minutes (healthy)
aifa-oauth2-proxy Up X minutes (healthy)
2. Check Logs
Site logs:
ssh root@31.97.61.154 "docker logs -f aifa-site"
OAuth2-Proxy logs:
ssh root@31.97.61.154 "docker logs -f aifa-oauth2-proxy"
3. Test Endpoints
Public homepage:
curl -I https://www.aisforagent.net
# Expected: 200 OK
Health check:
curl https://www.aisforagent.net/health
# Expected: healthy
OAuth2 endpoint (should redirect to login):
curl -I https://www.aisforagent.net/oauth2/userinfo
# Expected: 401 Unauthorized (not logged in)
Protected portal (should redirect to GitHub):
curl -I https://www.aisforagent.net/portal/
# Expected: 302 or 303 redirect to GitHub
4. Browser Testing
- Public Access:
- Visit
https://www.aisforagent.net - Should see homepage with βDownloadβ CTA
- No authentication required
- Visit
- Authentication Flow:
- Click on
/portal/link - Should redirect to GitHub OAuth
- Log in with GitHub
- Should redirect back to portal
- Click on
- Authenticated Access:
- After login, homepage should show βPremium Servicesβ CTA
- Portal, workflows, blueprints, and playbooks should be accessible
/oauth2/userinfoshould return 200
5. SSL Certificate
Check SSL certificate:
openssl s_client -connect www.aisforagent.net:443 -servername www.aisforagent.net
Should show:
- Valid Letβs Encrypt certificate
- Expires in ~90 days
- Subject:
CN=www.aisforagent.net
π§ Troubleshooting
Issue: Containers Not Starting
Check logs:
ssh root@31.97.61.154 "docker logs aifa-site"
ssh root@31.97.61.154 "docker logs aifa-oauth2-proxy"
Check container status:
ssh root@31.97.61.154 "docker ps -a | grep aifa"
Restart containers:
ssh root@31.97.61.154 "cd ~/aifa-website && docker-compose -f docker-compose.prod.yml restart"
Issue: Site Not Accessible (404/503)
Check Traefik can see the service:
ssh root@31.97.61.154 "docker logs traefik 2>&1 | grep aifa"
Verify container is on traefik-public network:
ssh root@31.97.61.154 "docker network inspect traefik-public | grep aifa"
Check Traefik labels:
ssh root@31.97.61.154 "docker inspect aifa-site | grep -A 30 Labels"
Issue: SSL Certificate Not Generated
Check DNS:
dig www.aisforagent.net +short
# Must return: 31.97.61.154
Check Traefik certificate logs:
ssh root@31.97.61.154 "docker logs traefik | grep -i certificate"
Manual certificate trigger:
# Make an HTTPS request to trigger certificate generation
curl https://www.aisforagent.net
Wait 1-2 minutes for Letβs Encrypt validation.
Issue: OAuth Not Working
Check OAuth2-Proxy logs:
ssh root@31.97.61.154 "docker logs aifa-oauth2-proxy"
Common issues:
- Wrong GitHub Client ID/Secret β Check
.env.prod - Wrong callback URL β Must be
https://www.aisforagent.net/oauth2/callback - Cookie secret not set β Generate with
openssl rand -base64 32
Test OAuth endpoint:
curl -v https://www.aisforagent.net/oauth2/userinfo
# Should return 401 if not logged in
Issue: CTA Not Switching
Check browser console:
F12 β Console β Look for auth errors
Verify /oauth2/userinfo is accessible:
curl -I https://www.aisforagent.net/oauth2/userinfo
# Should return 401 (not 404)
Check JavaScript is loaded:
curl https://www.aisforagent.net/assets/js/auth.js | grep oauth2
π Maintenance
Updating the Site
To deploy changes:
# 1. Make your changes locally
git pull origin main # or make edits
# 2. Test locally
bundle exec jekyll serve
# 3. Deploy
./deploy-prod.sh
Viewing Logs
# Real-time logs
ssh root@31.97.61.154 "docker logs -f aifa-site"
# Last 100 lines
ssh root@31.97.61.154 "docker logs --tail 100 aifa-site"
# Logs since 1 hour ago
ssh root@31.97.61.154 "docker logs --since 1h aifa-site"
Restarting Services
# Restart all
ssh root@31.97.61.154 "cd ~/aifa-website && docker-compose -f docker-compose.prod.yml restart"
# Restart site only
ssh root@31.97.61.154 "docker restart aifa-site"
# Restart oauth2-proxy only
ssh root@31.97.61.154 "docker restart aifa-oauth2-proxy"
Updating OAuth Configuration
- Edit
.env.prodlocally - Transfer to server:
scp .env.prod root@31.97.61.154:~/aifa-website/ - Restart oauth2-proxy:
ssh root@31.97.61.154 "docker restart aifa-oauth2-proxy"
Stopping the Site
ssh root@31.97.61.154 "cd ~/aifa-website && docker-compose -f docker-compose.prod.yml down"
Removing Everything
# Stop and remove containers
ssh root@31.97.61.154 "cd ~/aifa-website && docker-compose -f docker-compose.prod.yml down -v"
# Remove images
ssh root@31.97.61.154 "docker rmi aifa-site:prod"
# Remove directory
ssh root@31.97.61.154 "rm -rf ~/aifa-website"
Monitoring Resource Usage
# Real-time stats
ssh root@31.97.61.154 "docker stats aifa-site aifa-oauth2-proxy"
# Disk usage
ssh root@31.97.61.154 "docker system df"
π Resource Allocation
Current Limits
| Service | CPU Limit | Memory Limit | CPU Reserved | Memory Reserved |
|---|---|---|---|---|
| aifa-site | 0.5 core | 512MB | 0.25 core | 256MB |
| aifa-oauth2-proxy | 0.25 core | 256MB | 0.1 core | 128MB |
These are configured in docker-compose.prod.yml and can be adjusted if needed.
π Security Notes
- Never commit
.env.prod- It contains secrets - Rotate OAuth secrets regularly
- Restrict GitHub access - Use
OAUTH2_PROXY_GITHUB_USERSorOAUTH2_PROXY_GITHUB_ORG - Monitor access logs - Check whoβs accessing protected routes
- Keep images updated - Regularly rebuild with latest base images
π Support
Useful Commands Reference
# SSH to server
ssh -i ~/git/Foundry/S6web/key.file root@31.97.61.154
# Check all containers
docker ps --format 'table \t\t'
# View Traefik logs
docker logs traefik
# Check networks
docker network ls
docker network inspect traefik-public
# Full system status
docker stats --no-stream
df -h
free -h
Documentation Links
- Jekyll Documentation
- Traefik v3 Documentation
- OAuth2-Proxy Documentation
- Docker Compose Documentation
Deployed: Ready for production
Domain: https://www.aisforagent.net
Server: 31.97.61.154
Last Updated: 2025-10-11