This paper documents the design, implementation, and deployment of trooper.stsgym.com, a Flask-based authentication and virtual machine provisioning platform. The system provides secure user authentication with email verification, role-based access control, and automated VM provisioning on remote hosts via SSH. Built with containerization-first principles, the platform leverages Docker for deployment isolation, PostgreSQL for data persistence, and Redis for session management and rate limiting. The platform serves as a gateway for users to request and manage virtual machines on a development infrastructure, with administrative oversight and audit logging.
As development environments grow in complexity, the need for automated infrastructure provisioning becomes increasingly important. Traditional VM provisioning requires manual intervention, SSH access management, and coordination between users and administrators. trooper-auth-extended addresses these challenges by providing a self-service portal where authenticated users can request virtual machines on a development host.
This paper covers: - System architecture and design decisions - Authentication and authorization implementation - VM provisioning workflow - Security considerations - Deployment and operational procedures
The system follows a three-tier architecture:
┌─────────────────────────────────────────────────────────────────────┐
│ Tier 1: Presentation Layer │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ Flask Templates │ │
│ │ (HTML/CSS/JavaScript with Jinja2 templating) │ │
│ └─────────────────────────────────────────────────────────────┘ │
└────────────────────────────┬────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────┐
│ Tier 2: Application Layer │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ Flask Application │ │
│ │ ┌───────────┐ ┌───────────┐ ┌───────────┐ ┌───────────┐ │ │
│ │ │ Auth │ │ VM │ │ Chat │ │ Admin │ │ │
│ │ │ Module │ │Provisioner│ │ Module │ │ Module │ │ │
│ │ └───────────┘ └───────────┘ └───────────┘ └───────────┘ │ │
│ └─────────────────────────────────────────────────────────────┘ │
└────────────────────────────┬────────────────────────────────────────┘
│
┌───────────────────┼───────────────────┐
▼ ▼ ▼
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────────────────┐
│ Tier 3: Data │ │ Tier 3: Cache │ │ Tier 3: External │
│ PostgreSQL │ │ Redis │ │ SSH → trooper2 │
│ (Users, VMs, │ │ (Sessions, │ │ (VM Provisioning) │
│ Logs) │ │ Rate Limits) │ │ │
└─────────────────┘ └─────────────────┘ └─────────────────────────────┘
The core application is built on Flask with the following extensions:
| Extension | Purpose |
|---|---|
Flask-Login |
User session management |
Flask-SQLAlchemy |
ORM for PostgreSQL |
Flask-Limiter |
Rate limiting |
Flask-Mail |
Email notifications |
┌─────────────────────┐ ┌─────────────────────┐
│ User │ │ EmailVerification │
├─────────────────────┤ ├─────────────────────┤
│ id (PK) │────▶│ id (PK) │
│ username │ │ user_id (FK) │
│ email │ │ token │
│ password_hash │ │ created_at │
│ role │ │ expires_at │
│ is_active │ │ used │
│ is_approved │ └─────────────────────┘
│ email_confirmed │
│ created_at │ ┌─────────────────────┐
│ last_login │ │ AuditLog │
└─────────────────────┘ ├─────────────────────┤
│ │ id (PK) │
│ │ user_id (FK) │
▼ │ action │
┌─────────────────────┐ │ timestamp │
│ UserVM │ │ details │
├─────────────────────┤ └─────────────────────┘
│ id (PK) │
│ user_id (FK) │ ┌─────────────────────┐
│ vm_name │ │ UserSession │
│ vm_status │ ├─────────────────────┤
│ created_at │ │ id (PK) │
│ ip_address │ │ user_id (FK) │
└─────────────────────┘ │ token │
│ created_at │
│ expires_at │
└─────────────────────┘
The application is deployed on miner (207.244.226.151)
using Docker containers:
# docker-compose.yml structure
services:
web: # Flask application (port 5004)
db: # PostgreSQL 15
redis: # Redis 7 for rate limitingNginx proxies trooper.stsgym.com to
127.0.0.1:5004.
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ User │ │ Flask │ │ SMTP │
│ registers │────▶│ creates │────▶│ sends │
│ account │ │ pending │ │ verification │
└──────────────┘ │ user │ │ email │
└──────────────┘ └──────────────┘
│
▼
┌──────────────┐
│ User │
│ verifies │
│ email │
└──────────────┘
│
▼
┌──────────────┐
│ Admin │
│ approves │
│ account │
└──────────────┘
│
▼
┌──────────────┐
│ User │
│ can now │
│ login │
└──────────────┘
| Role | Permissions |
|---|---|
user |
Dashboard, VM panel, Chat |
admin |
All user permissions + User management, Approve/deny users, View audit logs |
┌──────────────────────────────────────────────────────────────────┐
│ VM PROVISIONING WORKFLOW │
├──────────────────────────────────────────────────────────────────┤
│ │
│ 1. User requests VM via /vm/create │
│ │ │
│ ▼ │
│ 2. Flask validates user permissions │
│ │ │
│ ▼ │
│ 3. Generate VM name (user-<id>-<random>) │
│ │ │
│ ▼ │
│ 4. SSH to trooper2 (100.123.159.17) │
│ │ │
│ ▼ │
│ 5. Execute virt-clone with base image │
│ │ │
│ ▼ │
│ 6. Start VM with virsh start │
│ │ │
│ ▼ │
│ 7. Record VM details in database │
│ │ │
│ ▼ │
│ 8. Return VM status to user │
│ │
└──────────────────────────────────────────────────────────────────┘
| Setting | Value |
|---|---|
| Base Image | /var/lib/libvirt/images/ubuntu-24.04-cloud.img |
| Memory | 8192 MB (8 GB) |
| vCPUs | 4 |
| Network | default (NAT) |
| Disk Format | qcow2 |
The application uses SSH keys to connect to
trooper2:
# Configuration
VM_HOST = "100.123.159.17" # trooper2 via Tailscale
VM_HOST_USER = "wez"
VM_SSH_KEY = "/app/ssh_key" # Mounted in containertrooper-auth-extended/
├── app.py # Main Flask application (54KB)
├── requirements.txt # Python dependencies
├── Dockerfile # Container build
├── docker-compose.yml # Service orchestration
├── run.sh # Startup script
├── ssh_key # SSH key for VM host
├── .env # Environment variables
└── templates/ # Jinja2 templates
├── base.html
├── index.html
├── login.html
├── register.html
├── dashboard.html
├── admin.html
├── admin_users.html
├── admin_pending.html
├── admin_vms.html
├── vm_panel.html
├── chat.html
├── audit_logs.html
├── change_password.html
├── forgot_password.html
├── reset_password.html
├── verify_pending.html
└── error.html
Flask==3.0.0
Flask-Login==0.6.3
Flask-SQLAlchemy==3.1.1
Flask-Limiter==3.5.0
Flask-Mail==0.9.1
psycopg2-binary==2.9.9
redis==5.0.1
gunicorn==21.2.0limiter = Limiter(
app=app,
key_func=get_remote_address,
default_limits=["200 per day", "50 per hour"],
storage_uri="redis://redis:6379/0"
)
# Applied to routes
@app.route("/login", methods=["GET", "POST"])
@limiter.limit("10 per minute")
def login():
# ...| Threat | Mitigation |
|---|---|
| Brute force login | Account lockout after 5 failures, rate limiting |
| Session hijacking | Secure cookies, HTTPS enforced |
| SQL injection | SQLAlchemy parameterized queries |
| XSS | Jinja2 auto-escaping |
| CSRF | Flask-WTF tokens |
| Unauthorized VM access | Role checks, SSH key isolation |
# Initial deployment
git clone git@idm.wezzel.com:crab-meat-repos/trooper-auth-extended.git
cd trooper-auth-extended
cp .env.example .env
# Edit .env with production values
docker-compose build
docker-compose up -d
# Initialize database
docker exec trooper-auth-extended flask db upgrade
# Create admin user
docker exec -it trooper-auth-extended flask create-admin# Health check
curl http://trooper.stsgym.com/health
# Container status
docker ps --filter "name=trooper-auth"
# Application logs
docker logs -f trooper-auth-extended
# Database logs
docker logs -f trooper-auth-extended-db# Database backup
docker exec trooper-auth-extended-db pg_dump -U trooper trooper > \
backup_$(date +%Y%m%d).sql
# Application backup
tar -czf trooper-backup_$(date +%Y%m%d).tar.gz \
/home/wez/trooper-auth-extendedThe architecture supports horizontal scaling:
trooper.stsgym.com demonstrates a practical implementation of a self-service infrastructure platform with robust authentication, authorization, and automated provisioning. The containerized deployment ensures consistency across environments, while the modular architecture allows for future expansion and integration with additional services.
The platform successfully addresses the challenges of: - Secure user onboarding with email verification - Administrative oversight for security compliance - Automated VM provisioning with minimal manual intervention - Comprehensive audit logging for accountability
# Required Environment Variables
DATABASE_URL=postgresql://user:pass@host:port/db
SECRET_KEY=<random-secret-key>
SMTP_HOST=mail.example.com
SMTP_PORT=587
SMTP_USER=username
SMTP_PASSWORD=password
BASE_URL=https://trooper.stsgym.com
VM_HOST=100.123.159.17
VM_HOST_USER=wez
VM_MEMORY=8192
VM_VCPUS=4| Endpoint | Method | Auth | Description |
|---|---|---|---|
/ |
GET | No | Home page |
/login |
POST | No | Authenticate user |
/register |
POST | No | Create account |
/dashboard |
GET | Yes | User dashboard |
/vm/create |
POST | Yes | Request new VM |
/admin/users |
GET | Admin | List all users |
/admin/approve/<id> |
POST | Admin | Approve user |
/health |
GET | No | Health check |
Last Updated: 2026-03-10
Repository:
https://idm.wezzel.com/crab-meat-repos/trooper-auth-extended
Maintainer: Wesley Robbins