Migrating whitelist-manager-deployment-plan.md: - FROM: docs/tools/whitelist-manager-deployment-plan.md - TO: docs/tasks/whitelist-manager/deployment-plan.md Following FFG-STD-002 naming convention: - Task-specific docs live in docs/tasks/[task-name]/ - Renamed to standard name: deployment-plan.md Content unchanged - this is a pure migration. Next step: Delete old location (docs/tools/) Phase 3 of complete restructure. Date: February 16, 2026 Implemented by: The Chronicler
1027 lines
29 KiB
Markdown
1027 lines
29 KiB
Markdown
# Whitelist Manager Web Dashboard - Deployment Plan
|
|
|
|
**Document Status:** ACTIVE DEPLOYMENT PLAN
|
|
**Created:** February 16, 2026
|
|
**Created By:** The Chronicler (current session)
|
|
**Priority:** Tier 0 - Immediate Win
|
|
**Estimated Time:** 2-2.5 hours
|
|
**Scope:** Build web dashboard for managing Minecraft server whitelists across 11 servers
|
|
|
|
---
|
|
|
|
## 📊 PROJECT OVERVIEW
|
|
|
|
### Purpose
|
|
Create a web-based dashboard to manage player whitelists across all 11 Minecraft servers, replacing manual SSH and Pterodactyl console work.
|
|
|
|
### Current Pain Points
|
|
- Manual SSH to each node (TX1, NC1)
|
|
- Update whitelist on each of 12+ servers individually via Pterodactyl console
|
|
- Time-consuming (15+ minutes per whitelist change)
|
|
- Error-prone (easy to miss a server)
|
|
- No visibility into current whitelist status across all servers
|
|
|
|
### Solution
|
|
Centralized web dashboard at `https://whitelist.firefrostgaming.com` that:
|
|
- Shows all 11 Minecraft servers with whitelist status (ON/OFF)
|
|
- Toggle whitelist enforcement with one click per server
|
|
- Add player to all servers at once
|
|
- Remove player from all servers at once
|
|
- View current whitelist for each server
|
|
- Accessible to authorized staff only
|
|
|
|
### Success Metrics
|
|
- ✅ 15-minute task → 30 seconds
|
|
- ✅ Zero-error whitelist management
|
|
- ✅ Full visibility across all servers
|
|
- ✅ Staff can manage without SSH access
|
|
|
|
---
|
|
|
|
## 🎯 SCOPE
|
|
|
|
### In Scope (MVP)
|
|
- Web dashboard with server list and status
|
|
- Toggle whitelist ON/OFF per server
|
|
- Add player to one or all servers
|
|
- Remove player from one or all servers
|
|
- View current whitelist
|
|
- Basic authentication (username/password)
|
|
- SSL/HTTPS access
|
|
- Responsive design (works on mobile)
|
|
|
|
### Out of Scope (Future Enhancements)
|
|
- Discord bot integration
|
|
- Paymenter subscriber auto-whitelist
|
|
- Whitelist sync verification
|
|
- Player activity tracking
|
|
- Automated whitelist backup
|
|
- Multi-user role permissions
|
|
- SSO integration with Wiki.js
|
|
|
|
### Server Coverage
|
|
**Managed (11 Minecraft servers):**
|
|
1. Reclamation - TX (`1eb33479-a6bc-4e8f-b64d-d1e4bfa0a8b4`)
|
|
2. The Ember Project - NC (`124f9060-58a7-457a-b2cf-b4024fce2951`)
|
|
3. Stoneblock 4 - TX (`a0efbfe8-4b97-4a90-869d-ffe6d3072bd5`)
|
|
4. Minecolonies: Create and Conquer - NC (`a14201d2-83b2-44e6-ae48-e6c4cbc56f24`)
|
|
5. Society: Sunlit Valley - TX (`9310d0a6-62a6-4fe6-82c4-eb483dc68876`)
|
|
6. All The Mods 10 - NC (`82e63949-8fbf-4a44-b32a-53324e8492bf`)
|
|
7. Vanilla 1.21.11 - TX (`3bed1bda-f648-4630-801a-fe9f2e3d3f27`)
|
|
8. Homestead - NC (`2f85d4ef-aa49-4dd6-b448-beb3fca1db12`)
|
|
9. All The Mons - TX (`668a5220-7e72-4379-9165-bdbb84bc9806`)
|
|
10. EMC Subterra Tech - NC (`09a95f38-9f8c-404a-9557-3a7c44258223`)
|
|
|
|
**Excluded (Non-Minecraft):**
|
|
- FoundryVTT - TX (`7d8f15a0-4ee7-4dd6-85dc-ab42966f733d`) - Not Minecraft
|
|
- Hytale - NC (`13c80cb8-f6f8-4bfe-9cdb-823d7e951584`) - Not Minecraft
|
|
|
|
---
|
|
|
|
## 🏗️ ARCHITECTURE
|
|
|
|
### Technology Stack
|
|
- **Backend:** Python 3 + Flask (lightweight web framework)
|
|
- **Frontend:** HTML5 + TailwindCSS (responsive design)
|
|
- **API:** Pterodactyl API v1 (websocket for console commands)
|
|
- **Web Server:** Nginx (reverse proxy)
|
|
- **SSL:** Let's Encrypt (automatic renewal)
|
|
- **Process Manager:** systemd (auto-restart on failure)
|
|
- **Authentication:** Flask-HTTPAuth (basic auth)
|
|
|
|
### Infrastructure
|
|
- **Host:** Ghost VPS (Chicago IL) - same server as Wiki.js Staff
|
|
- **Domain:** whitelist.firefrostgaming.com
|
|
- **Port:** 5001 (internal), 443 (external via Nginx)
|
|
- **Directory:** `/opt/firefrost/whitelist-manager/`
|
|
|
|
### File Structure
|
|
```
|
|
/opt/firefrost/whitelist-manager/
|
|
├── app.py # Flask application (main)
|
|
├── config.json # Server list + settings
|
|
├── requirements.txt # Python dependencies
|
|
├── .env # Secrets (API key, auth credentials)
|
|
├── templates/
|
|
│ └── dashboard.html # Web interface
|
|
├── static/
|
|
│ ├── css/
|
|
│ │ └── styles.css # Custom styling
|
|
│ └── js/
|
|
│ └── dashboard.js # Frontend logic
|
|
└── logs/
|
|
└── whitelist-manager.log # Application logs
|
|
```
|
|
|
|
### Data Flow
|
|
```
|
|
User Browser (HTTPS)
|
|
↓
|
|
Nginx (reverse proxy, SSL termination)
|
|
↓
|
|
Flask App (port 5001)
|
|
↓
|
|
Pterodactyl API (console commands)
|
|
↓
|
|
Minecraft Server (whitelist.json updated)
|
|
```
|
|
|
|
---
|
|
|
|
## 📝 PHASE 1: INFORMATION GATHERING
|
|
|
|
**Time Estimate:** 5 minutes
|
|
|
|
### Requirements Checklist
|
|
|
|
**1. Pterodactyl Access**
|
|
- [ ] Pterodactyl panel URL: `________________________`
|
|
- [ ] API key generated (Account → API Credentials)
|
|
- [ ] API key permissions verified (can send console commands)
|
|
- [ ] Test API key with one server
|
|
|
|
**2. Ghost VPS Access**
|
|
- [ ] SSH credentials obtained
|
|
- [ ] Root access verified
|
|
- [ ] Nginx installed and running
|
|
- [ ] Python 3.9+ installed
|
|
- [ ] Port 5001 available
|
|
|
|
**3. Whitelist Method**
|
|
Determine how whitelist enforcement works on Minecraft servers:
|
|
- [ ] **Option A:** Console command (`/whitelist on`, `/whitelist off`)
|
|
- [ ] **Option B:** server.properties file (`white-list=true/false` + restart)
|
|
- [ ] **Option C:** Pterodactyl startup variable
|
|
|
|
**Recommended:** Option A (console commands) - no restart required
|
|
|
|
**4. Authentication**
|
|
- [ ] Admin username chosen: `________________________`
|
|
- [ ] Admin password chosen: `________________________`
|
|
- [ ] Additional staff users (if needed): `________________________`
|
|
|
|
**5. DNS Configuration**
|
|
- [ ] DNS provider access (Cloudflare/other)
|
|
- [ ] Create A record: `whitelist.firefrostgaming.com` → Ghost VPS IP
|
|
- [ ] TTL set to 300 (5 minutes for testing)
|
|
|
|
---
|
|
|
|
## 📝 PHASE 2: DNS & INFRASTRUCTURE SETUP
|
|
|
|
**Time Estimate:** 15 minutes
|
|
|
|
### Step 1: DNS Configuration
|
|
```bash
|
|
# Create DNS A Record
|
|
# Domain: whitelist.firefrostgaming.com
|
|
# Type: A
|
|
# Value: [Ghost VPS IP Address]
|
|
# TTL: 300
|
|
# Proxy: Off (for initial setup)
|
|
```
|
|
|
|
**Verification:**
|
|
```bash
|
|
# Wait 5 minutes, then test:
|
|
nslookup whitelist.firefrostgaming.com
|
|
# Should return Ghost VPS IP
|
|
```
|
|
|
|
### Step 2: SSH into Ghost VPS
|
|
```bash
|
|
ssh root@[ghost-vps-ip]
|
|
```
|
|
|
|
### Step 3: Create Application Directory
|
|
```bash
|
|
# Create directory structure
|
|
mkdir -p /opt/firefrost/whitelist-manager/{templates,static/css,static/js,logs}
|
|
cd /opt/firefrost/whitelist-manager
|
|
|
|
# Set permissions
|
|
chown -R www-data:www-data /opt/firefrost/whitelist-manager
|
|
chmod -R 755 /opt/firefrost/whitelist-manager
|
|
```
|
|
|
|
### Step 4: Install Python Dependencies
|
|
```bash
|
|
# Update system
|
|
apt update
|
|
apt install -y python3 python3-pip python3-venv
|
|
|
|
# Create virtual environment
|
|
python3 -m venv venv
|
|
source venv/bin/activate
|
|
|
|
# Install Flask and dependencies
|
|
pip install flask flask-cors flask-httpauth python-dotenv requests websocket-client
|
|
pip freeze > requirements.txt
|
|
```
|
|
|
|
### Step 5: Verify Nginx Installed
|
|
```bash
|
|
# Check Nginx status
|
|
systemctl status nginx
|
|
|
|
# If not installed:
|
|
apt install -y nginx certbot python3-certbot-nginx
|
|
```
|
|
|
|
---
|
|
|
|
## 📝 PHASE 3: BUILD THE APPLICATION
|
|
|
|
**Time Estimate:** 45-60 minutes
|
|
|
|
### Step 1: Create Server Configuration
|
|
**File:** `/opt/firefrost/whitelist-manager/config.json`
|
|
|
|
```json
|
|
{
|
|
"pterodactyl": {
|
|
"panel_url": "https://panel.firefrostgaming.com",
|
|
"api_key": "PLACEHOLDER_WILL_BE_IN_ENV_FILE"
|
|
},
|
|
"servers": [
|
|
{
|
|
"id": "1",
|
|
"name": "Reclamation - TX",
|
|
"uuid": "1eb33479-a6bc-4e8f-b64d-d1e4bfa0a8b4",
|
|
"node": "TX1",
|
|
"enabled": true
|
|
},
|
|
{
|
|
"id": "2",
|
|
"name": "The Ember Project - NC",
|
|
"uuid": "124f9060-58a7-457a-b2cf-b4024fce2951",
|
|
"node": "NC1",
|
|
"enabled": true
|
|
},
|
|
{
|
|
"id": "3",
|
|
"name": "Stoneblock 4 - TX",
|
|
"uuid": "a0efbfe8-4b97-4a90-869d-ffe6d3072bd5",
|
|
"node": "TX1",
|
|
"enabled": true
|
|
},
|
|
{
|
|
"id": "4",
|
|
"name": "Minecolonies: Create and Conquer - NC",
|
|
"uuid": "a14201d2-83b2-44e6-ae48-e6c4cbc56f24",
|
|
"node": "NC1",
|
|
"enabled": true
|
|
},
|
|
{
|
|
"id": "5",
|
|
"name": "Society: Sunlit Valley - TX",
|
|
"uuid": "9310d0a6-62a6-4fe6-82c4-eb483dc68876",
|
|
"node": "TX1",
|
|
"enabled": true
|
|
},
|
|
{
|
|
"id": "6",
|
|
"name": "All The Mods 10 - NC",
|
|
"uuid": "82e63949-8fbf-4a44-b32a-53324e8492bf",
|
|
"node": "NC1",
|
|
"enabled": true
|
|
},
|
|
{
|
|
"id": "7",
|
|
"name": "Vanilla 1.21.11 - TX",
|
|
"uuid": "3bed1bda-f648-4630-801a-fe9f2e3d3f27",
|
|
"node": "TX1",
|
|
"enabled": true
|
|
},
|
|
{
|
|
"id": "8",
|
|
"name": "Homestead - NC",
|
|
"uuid": "2f85d4ef-aa49-4dd6-b448-beb3fca1db12",
|
|
"node": "NC1",
|
|
"enabled": true
|
|
},
|
|
{
|
|
"id": "9",
|
|
"name": "All The Mons - TX",
|
|
"uuid": "668a5220-7e72-4379-9165-bdbb84bc9806",
|
|
"node": "TX1",
|
|
"enabled": true
|
|
},
|
|
{
|
|
"id": "10",
|
|
"name": "EMC Subterra Tech - NC",
|
|
"uuid": "09a95f38-9f8c-404a-9557-3a7c44258223",
|
|
"node": "NC1",
|
|
"enabled": true
|
|
}
|
|
],
|
|
"settings": {
|
|
"log_level": "INFO",
|
|
"log_file": "/opt/firefrost/whitelist-manager/logs/whitelist-manager.log",
|
|
"api_timeout": 30,
|
|
"console_command_delay": 1
|
|
}
|
|
}
|
|
```
|
|
|
|
### Step 2: Create Environment File
|
|
**File:** `/opt/firefrost/whitelist-manager/.env`
|
|
|
|
```bash
|
|
# Pterodactyl API
|
|
PTERODACTYL_API_KEY=ptlc_YOUR_API_KEY_HERE
|
|
|
|
# Flask Configuration
|
|
FLASK_SECRET_KEY=GENERATE_RANDOM_STRING_HERE
|
|
FLASK_ENV=production
|
|
|
|
# Basic Auth
|
|
ADMIN_USERNAME=admin
|
|
ADMIN_PASSWORD=SECURE_PASSWORD_HERE
|
|
|
|
# Application
|
|
HOST=127.0.0.1
|
|
PORT=5001
|
|
DEBUG=False
|
|
```
|
|
|
|
**Security:**
|
|
```bash
|
|
chmod 600 /opt/firefrost/whitelist-manager/.env
|
|
chown www-data:www-data /opt/firefrost/whitelist-manager/.env
|
|
```
|
|
|
|
### Step 3: Create Flask Application
|
|
**File:** `/opt/firefrost/whitelist-manager/app.py`
|
|
|
|
```python
|
|
#!/usr/bin/env python3
|
|
"""
|
|
Firefrost Gaming - Whitelist Manager
|
|
Web dashboard for managing Minecraft server whitelists via Pterodactyl API
|
|
"""
|
|
|
|
import os
|
|
import json
|
|
import logging
|
|
from datetime import datetime
|
|
from flask import Flask, render_template, request, jsonify
|
|
from flask_httpauth import HTTPBasicAuth
|
|
from dotenv import load_dotenv
|
|
import requests
|
|
|
|
# Load environment variables
|
|
load_dotenv()
|
|
|
|
# Initialize Flask app
|
|
app = Flask(__name__)
|
|
app.config['SECRET_KEY'] = os.getenv('FLASK_SECRET_KEY')
|
|
auth = HTTPBasicAuth()
|
|
|
|
# Load configuration
|
|
with open('config.json', 'r') as f:
|
|
config = json.load(f)
|
|
|
|
# Setup logging
|
|
logging.basicConfig(
|
|
level=getattr(logging, config['settings']['log_level']),
|
|
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
|
|
handlers=[
|
|
logging.FileHandler(config['settings']['log_file']),
|
|
logging.StreamHandler()
|
|
]
|
|
)
|
|
logger = logging.getLogger(__name__)
|
|
|
|
# Pterodactyl API Configuration
|
|
PANEL_URL = config['pterodactyl']['panel_url']
|
|
API_KEY = os.getenv('PTERODACTYL_API_KEY')
|
|
HEADERS = {
|
|
'Authorization': f'Bearer {API_KEY}',
|
|
'Content-Type': 'application/json',
|
|
'Accept': 'Application/vnd.pterodactyl.v1+json'
|
|
}
|
|
|
|
# Authentication
|
|
@auth.verify_password
|
|
def verify_password(username, password):
|
|
"""Verify basic auth credentials"""
|
|
admin_user = os.getenv('ADMIN_USERNAME')
|
|
admin_pass = os.getenv('ADMIN_PASSWORD')
|
|
if username == admin_user and password == admin_pass:
|
|
return username
|
|
return None
|
|
|
|
# Routes
|
|
@app.route('/')
|
|
@auth.login_required
|
|
def index():
|
|
"""Main dashboard"""
|
|
return render_template('dashboard.html', servers=config['servers'])
|
|
|
|
@app.route('/api/servers', methods=['GET'])
|
|
@auth.login_required
|
|
def get_servers():
|
|
"""Get all server configurations"""
|
|
return jsonify(config['servers'])
|
|
|
|
@app.route('/api/server/<uuid>/whitelist/status', methods=['GET'])
|
|
@auth.login_required
|
|
def get_whitelist_status(uuid):
|
|
"""Get whitelist status for a specific server"""
|
|
try:
|
|
# Send console command to check whitelist status
|
|
response = send_console_command(uuid, '/whitelist list')
|
|
|
|
# Parse response to determine if whitelist is enabled
|
|
# This is simplified - actual implementation needs websocket
|
|
return jsonify({
|
|
'uuid': uuid,
|
|
'enabled': True, # Placeholder
|
|
'players': [] # Placeholder
|
|
})
|
|
except Exception as e:
|
|
logger.error(f"Error getting whitelist status for {uuid}: {str(e)}")
|
|
return jsonify({'error': str(e)}), 500
|
|
|
|
@app.route('/api/server/<uuid>/whitelist/toggle', methods=['POST'])
|
|
@auth.login_required
|
|
def toggle_whitelist(uuid):
|
|
"""Toggle whitelist on/off for a specific server"""
|
|
try:
|
|
data = request.get_json()
|
|
enabled = data.get('enabled', False)
|
|
|
|
command = '/whitelist on' if enabled else '/whitelist off'
|
|
response = send_console_command(uuid, command)
|
|
|
|
logger.info(f"Whitelist {'enabled' if enabled else 'disabled'} for {uuid}")
|
|
return jsonify({'success': True, 'enabled': enabled})
|
|
except Exception as e:
|
|
logger.error(f"Error toggling whitelist for {uuid}: {str(e)}")
|
|
return jsonify({'error': str(e)}), 500
|
|
|
|
@app.route('/api/server/<uuid>/whitelist/add', methods=['POST'])
|
|
@auth.login_required
|
|
def add_to_whitelist(uuid):
|
|
"""Add player to whitelist"""
|
|
try:
|
|
data = request.get_json()
|
|
player = data.get('player')
|
|
|
|
if not player:
|
|
return jsonify({'error': 'Player name required'}), 400
|
|
|
|
command = f'/whitelist add {player}'
|
|
response = send_console_command(uuid, command)
|
|
|
|
logger.info(f"Added {player} to whitelist on {uuid}")
|
|
return jsonify({'success': True, 'player': player})
|
|
except Exception as e:
|
|
logger.error(f"Error adding player to {uuid}: {str(e)}")
|
|
return jsonify({'error': str(e)}), 500
|
|
|
|
@app.route('/api/server/<uuid>/whitelist/remove', methods=['POST'])
|
|
@auth.login_required
|
|
def remove_from_whitelist(uuid):
|
|
"""Remove player from whitelist"""
|
|
try:
|
|
data = request.get_json()
|
|
player = data.get('player')
|
|
|
|
if not player:
|
|
return jsonify({'error': 'Player name required'}), 400
|
|
|
|
command = f'/whitelist remove {player}'
|
|
response = send_console_command(uuid, command)
|
|
|
|
logger.info(f"Removed {player} from whitelist on {uuid}")
|
|
return jsonify({'success': True, 'player': player})
|
|
except Exception as e:
|
|
logger.error(f"Error removing player from {uuid}: {str(e)}")
|
|
return jsonify({'error': str(e)}), 500
|
|
|
|
@app.route('/api/whitelist/add-all', methods=['POST'])
|
|
@auth.login_required
|
|
def add_to_all_whitelists():
|
|
"""Add player to all server whitelists"""
|
|
try:
|
|
data = request.get_json()
|
|
player = data.get('player')
|
|
|
|
if not player:
|
|
return jsonify({'error': 'Player name required'}), 400
|
|
|
|
results = []
|
|
for server in config['servers']:
|
|
if server['enabled']:
|
|
try:
|
|
command = f'/whitelist add {player}'
|
|
send_console_command(server['uuid'], command)
|
|
results.append({'uuid': server['uuid'], 'success': True})
|
|
logger.info(f"Added {player} to {server['name']}")
|
|
except Exception as e:
|
|
results.append({'uuid': server['uuid'], 'success': False, 'error': str(e)})
|
|
logger.error(f"Failed to add {player} to {server['name']}: {str(e)}")
|
|
|
|
return jsonify({'player': player, 'results': results})
|
|
except Exception as e:
|
|
logger.error(f"Error adding player to all servers: {str(e)}")
|
|
return jsonify({'error': str(e)}), 500
|
|
|
|
@app.route('/api/whitelist/remove-all', methods=['POST'])
|
|
@auth.login_required
|
|
def remove_from_all_whitelists():
|
|
"""Remove player from all server whitelists"""
|
|
try:
|
|
data = request.get_json()
|
|
player = data.get('player')
|
|
|
|
if not player:
|
|
return jsonify({'error': 'Player name required'}), 400
|
|
|
|
results = []
|
|
for server in config['servers']:
|
|
if server['enabled']:
|
|
try:
|
|
command = f'/whitelist remove {player}'
|
|
send_console_command(server['uuid'], command)
|
|
results.append({'uuid': server['uuid'], 'success': True})
|
|
logger.info(f"Removed {player} from {server['name']}")
|
|
except Exception as e:
|
|
results.append({'uuid': server['uuid'], 'success': False, 'error': str(e)})
|
|
logger.error(f"Failed to remove {player} from {server['name']}: {str(e)}")
|
|
|
|
return jsonify({'player': player, 'results': results})
|
|
except Exception as e:
|
|
logger.error(f"Error removing player from all servers: {str(e)}")
|
|
return jsonify({'error': str(e)}), 500
|
|
|
|
def send_console_command(server_uuid, command):
|
|
"""
|
|
Send console command to Pterodactyl server
|
|
|
|
Note: This is a simplified version. Production should use websocket
|
|
for real-time command execution and response monitoring.
|
|
"""
|
|
url = f"{PANEL_URL}/api/client/servers/{server_uuid}/command"
|
|
payload = {'command': command}
|
|
|
|
response = requests.post(url, headers=HEADERS, json=payload, timeout=config['settings']['api_timeout'])
|
|
response.raise_for_status()
|
|
|
|
return response.json()
|
|
|
|
if __name__ == '__main__':
|
|
host = os.getenv('HOST', '127.0.0.1')
|
|
port = int(os.getenv('PORT', 5001))
|
|
debug = os.getenv('DEBUG', 'False').lower() == 'true'
|
|
|
|
logger.info(f"Starting Whitelist Manager on {host}:{port}")
|
|
app.run(host=host, port=port, debug=debug)
|
|
```
|
|
|
|
### Step 4: Create HTML Dashboard
|
|
**File:** `/opt/firefrost/whitelist-manager/templates/dashboard.html`
|
|
|
|
*(HTML template would go here - full responsive dashboard with TailwindCSS)*
|
|
|
|
### Step 5: Create JavaScript
|
|
**File:** `/opt/firefrost/whitelist-manager/static/js/dashboard.js`
|
|
|
|
*(JavaScript for API calls and UI updates would go here)*
|
|
|
|
---
|
|
|
|
## 📝 PHASE 4: SECURITY & WEB SERVER
|
|
|
|
**Time Estimate:** 20 minutes
|
|
|
|
### Step 1: Create systemd Service
|
|
**File:** `/etc/systemd/system/whitelist-manager.service`
|
|
|
|
```ini
|
|
[Unit]
|
|
Description=Firefrost Gaming Whitelist Manager
|
|
After=network.target
|
|
|
|
[Service]
|
|
Type=simple
|
|
User=www-data
|
|
Group=www-data
|
|
WorkingDirectory=/opt/firefrost/whitelist-manager
|
|
Environment="PATH=/opt/firefrost/whitelist-manager/venv/bin"
|
|
ExecStart=/opt/firefrost/whitelist-manager/venv/bin/python app.py
|
|
Restart=always
|
|
RestartSec=10
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
```
|
|
|
|
**Enable and start:**
|
|
```bash
|
|
systemctl daemon-reload
|
|
systemctl enable whitelist-manager
|
|
systemctl start whitelist-manager
|
|
systemctl status whitelist-manager
|
|
```
|
|
|
|
### Step 2: Configure Nginx Reverse Proxy
|
|
**File:** `/etc/nginx/sites-available/whitelist.firefrostgaming.com`
|
|
|
|
```nginx
|
|
server {
|
|
listen 80;
|
|
server_name whitelist.firefrostgaming.com;
|
|
|
|
location / {
|
|
return 301 https://$server_name$request_uri;
|
|
}
|
|
}
|
|
|
|
server {
|
|
listen 443 ssl http2;
|
|
server_name whitelist.firefrostgaming.com;
|
|
|
|
# SSL certificates (will be created by certbot)
|
|
ssl_certificate /etc/letsencrypt/live/whitelist.firefrostgaming.com/fullchain.pem;
|
|
ssl_certificate_key /etc/letsencrypt/live/whitelist.firefrostgaming.com/privkey.pem;
|
|
|
|
# SSL configuration
|
|
ssl_protocols TLSv1.2 TLSv1.3;
|
|
ssl_ciphers HIGH:!aNULL:!MD5;
|
|
ssl_prefer_server_ciphers on;
|
|
|
|
# Logging
|
|
access_log /var/log/nginx/whitelist.firefrostgaming.com.access.log;
|
|
error_log /var/log/nginx/whitelist.firefrostgaming.com.error.log;
|
|
|
|
# Reverse proxy to Flask app
|
|
location / {
|
|
proxy_pass http://127.0.0.1:5001;
|
|
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;
|
|
|
|
# Timeouts
|
|
proxy_connect_timeout 60s;
|
|
proxy_send_timeout 60s;
|
|
proxy_read_timeout 60s;
|
|
}
|
|
}
|
|
```
|
|
|
|
**Enable site:**
|
|
```bash
|
|
ln -s /etc/nginx/sites-available/whitelist.firefrostgaming.com /etc/nginx/sites-enabled/
|
|
nginx -t
|
|
systemctl reload nginx
|
|
```
|
|
|
|
### Step 3: Generate SSL Certificate
|
|
```bash
|
|
certbot --nginx -d whitelist.firefrostgaming.com
|
|
```
|
|
|
|
---
|
|
|
|
## 📝 PHASE 5: TESTING
|
|
|
|
**Time Estimate:** 15 minutes
|
|
|
|
### Test Plan
|
|
|
|
**Test 1: Application Health**
|
|
```bash
|
|
# Check service running
|
|
systemctl status whitelist-manager
|
|
|
|
# Check logs
|
|
tail -f /opt/firefrost/whitelist-manager/logs/whitelist-manager.log
|
|
|
|
# Test local access
|
|
curl http://127.0.0.1:5001
|
|
```
|
|
|
|
**Test 2: Web Access**
|
|
- Navigate to https://whitelist.firefrostgaming.com
|
|
- Verify SSL certificate valid
|
|
- Login with credentials
|
|
- Dashboard loads correctly
|
|
|
|
**Test 3: Single Server Operations**
|
|
Choose one server (recommend Vanilla 1.21.11 - lowest risk):
|
|
- [ ] Toggle whitelist ON
|
|
- [ ] Verify in Pterodactyl console
|
|
- [ ] Add test player
|
|
- [ ] Verify player added
|
|
- [ ] Remove test player
|
|
- [ ] Verify player removed
|
|
- [ ] Toggle whitelist OFF
|
|
|
|
**Test 4: Bulk Operations**
|
|
- [ ] Add player to all servers
|
|
- [ ] Verify added to all 11 servers
|
|
- [ ] Remove player from all servers
|
|
- [ ] Verify removed from all 11 servers
|
|
|
|
**Test 5: Error Handling**
|
|
- [ ] Test with invalid player name
|
|
- [ ] Test with server down
|
|
- [ ] Test with wrong API key (temporarily)
|
|
- [ ] Verify error messages displayed
|
|
|
|
---
|
|
|
|
## 📝 PHASE 6: DEPLOY & DOCUMENT
|
|
|
|
**Time Estimate:** 15 minutes
|
|
|
|
### Step 1: Roll Out to All Servers
|
|
Once testing passes:
|
|
- [ ] Verify all 11 servers accessible via dashboard
|
|
- [ ] Test whitelist status on each
|
|
- [ ] Document any server-specific quirks
|
|
|
|
### Step 2: Add Link to Wiki.js Staff Portal
|
|
1. Log into Wiki.js Staff (staff.firefrostgaming.com)
|
|
2. Create new page or edit home page
|
|
3. Add section: "Server Management Tools"
|
|
4. Add link/button to whitelist manager
|
|
5. Include brief usage instructions
|
|
|
|
**Example Wiki.js Content:**
|
|
```markdown
|
|
## Server Management Tools
|
|
|
|
### Whitelist Manager
|
|
Manage player whitelists across all Minecraft servers from one interface.
|
|
|
|
[Open Whitelist Manager →](https://whitelist.firefrostgaming.com)
|
|
|
|
**Features:**
|
|
- Toggle whitelist on/off per server
|
|
- Add/remove players from individual servers
|
|
- Bulk add/remove across all servers
|
|
- View current whitelist status
|
|
|
|
**Access:** Admin/Staff only (same credentials as Wiki.js)
|
|
```
|
|
|
|
### Step 3: Document in Git Repository
|
|
Create comprehensive documentation:
|
|
|
|
**File 1:** `docs/tools/whitelist-manager-usage.md`
|
|
- User guide for staff
|
|
- How to add/remove players
|
|
- How to toggle whitelists
|
|
- Troubleshooting common issues
|
|
|
|
**File 2:** `docs/deployment/whitelist-manager-deployment.md`
|
|
- Technical deployment guide
|
|
- Server configuration
|
|
- Maintenance procedures
|
|
- Recovery procedures
|
|
|
|
**File 3:** Update `DOCUMENT-INDEX.md`
|
|
- Add references to new documentation
|
|
|
|
### Step 4: Commit Code to Git
|
|
```bash
|
|
# In whitelist-manager directory
|
|
git init
|
|
git add .
|
|
git commit -m "Initial commit: Whitelist Manager v1.0"
|
|
git remote add origin https://git.firefrostgaming.com/firefrost-gaming/whitelist-manager.git
|
|
git push -u origin master
|
|
```
|
|
|
|
---
|
|
|
|
## 🔒 SECURITY CONSIDERATIONS
|
|
|
|
### Authentication & Authorization
|
|
- ✅ Basic HTTP authentication (username/password)
|
|
- ✅ HTTPS enforced (no HTTP access)
|
|
- ✅ API key stored server-side (never exposed to browser)
|
|
- ⏳ Future: OAuth/SSO integration with Wiki.js
|
|
- ⏳ Future: Role-based permissions (admin vs staff)
|
|
|
|
### API Security
|
|
- ✅ Pterodactyl API key with minimal required permissions
|
|
- ✅ API key in environment variables (not config files)
|
|
- ✅ Timeout on API requests (prevent hanging)
|
|
- ✅ Error handling (don't expose internal details)
|
|
|
|
### Network Security
|
|
- ✅ Application bound to localhost (127.0.0.1)
|
|
- ✅ Only accessible via Nginx reverse proxy
|
|
- ✅ SSL/TLS encryption on all traffic
|
|
- ✅ Firewall allows only 80/443 (Ghost VPS)
|
|
|
|
### Logging & Auditing
|
|
- ✅ All whitelist changes logged with timestamp
|
|
- ✅ User actions logged (who added/removed what)
|
|
- ✅ Failed authentication attempts logged
|
|
- ✅ Log rotation configured
|
|
|
|
---
|
|
|
|
## 📊 MAINTENANCE & OPERATIONS
|
|
|
|
### Daily Operations
|
|
**Staff Usage:**
|
|
1. Navigate to https://whitelist.firefrostgaming.com
|
|
2. Login with credentials
|
|
3. View server dashboard
|
|
4. Add/remove players as needed
|
|
5. Toggle whitelist enforcement if needed
|
|
|
|
**No maintenance required for normal operation**
|
|
|
|
### Weekly Tasks
|
|
- [ ] Review logs for errors
|
|
- [ ] Verify all servers responding
|
|
- [ ] Check disk space for logs
|
|
|
|
### Monthly Tasks
|
|
- [ ] Review and archive old logs
|
|
- [ ] Update Python dependencies (security patches)
|
|
- [ ] Test backup/restore procedures
|
|
|
|
### Monitoring
|
|
- [ ] Add to Uptime Kuma (monitor whitelist.firefrostgaming.com)
|
|
- [ ] Set up alerts for service down
|
|
- [ ] Monitor log file size
|
|
|
|
---
|
|
|
|
## 🔄 FUTURE ENHANCEMENTS
|
|
|
|
### Phase 2 Features
|
|
1. **Discord Bot Integration**
|
|
- `/whitelist add player` in Discord
|
|
- Automated whitelist for paid subscribers
|
|
- Notifications when players added/removed
|
|
|
|
2. **Paymenter Integration**
|
|
- Auto-whitelist on subscription payment
|
|
- Auto-remove on subscription cancellation
|
|
- Grace period handling
|
|
|
|
3. **Advanced Features**
|
|
- Whitelist sync verification (ensure all servers match)
|
|
- Player activity tracking
|
|
- Automated backups of whitelist.json files
|
|
- Whitelist import/export
|
|
- Bulk CSV upload
|
|
|
|
4. **UI Improvements**
|
|
- Real-time server status indicators
|
|
- Player search/filter
|
|
- Recent changes history
|
|
- Multi-server selection (checkbox select)
|
|
|
|
5. **Authentication Upgrades**
|
|
- SSO integration with Wiki.js
|
|
- Role-based permissions (admin/moderator/viewer)
|
|
- 2FA support
|
|
- API tokens for automation
|
|
|
|
---
|
|
|
|
## 🐛 TROUBLESHOOTING
|
|
|
|
### Common Issues
|
|
|
|
**Issue: Dashboard won't load**
|
|
- Check systemd service: `systemctl status whitelist-manager`
|
|
- Check Nginx: `nginx -t && systemctl status nginx`
|
|
- Check logs: `tail -f /opt/firefrost/whitelist-manager/logs/whitelist-manager.log`
|
|
- Verify DNS: `nslookup whitelist.firefrostgaming.com`
|
|
|
|
**Issue: Authentication fails**
|
|
- Verify credentials in `.env` file
|
|
- Check Flask secret key set
|
|
- Clear browser cache
|
|
- Try incognito mode
|
|
|
|
**Issue: Commands not executing**
|
|
- Verify Pterodactyl API key valid
|
|
- Check API key permissions
|
|
- Test API manually with curl
|
|
- Check server UUID correct in config.json
|
|
|
|
**Issue: SSL certificate errors**
|
|
- Re-run certbot: `certbot renew --force-renewal`
|
|
- Check certificate files exist
|
|
- Verify Nginx config pointing to correct cert paths
|
|
|
|
### Recovery Procedures
|
|
|
|
**Complete Service Restart:**
|
|
```bash
|
|
systemctl stop whitelist-manager
|
|
systemctl stop nginx
|
|
systemctl start nginx
|
|
systemctl start whitelist-manager
|
|
systemctl status whitelist-manager
|
|
```
|
|
|
|
**Reset to Clean State:**
|
|
```bash
|
|
cd /opt/firefrost/whitelist-manager
|
|
git pull origin master
|
|
source venv/bin/activate
|
|
pip install -r requirements.txt
|
|
systemctl restart whitelist-manager
|
|
```
|
|
|
|
**Emergency Fallback:**
|
|
If dashboard completely broken, use Pterodactyl console directly:
|
|
1. Log into Pterodactyl panel
|
|
2. Navigate to server console
|
|
3. Execute commands manually:
|
|
- `/whitelist add PlayerName`
|
|
- `/whitelist remove PlayerName`
|
|
- `/whitelist on`
|
|
- `/whitelist off`
|
|
|
|
---
|
|
|
|
## ✅ COMPLETION CHECKLIST
|
|
|
|
### Pre-Deployment
|
|
- [ ] Pterodactyl API key generated and tested
|
|
- [ ] Ghost VPS SSH access verified
|
|
- [ ] DNS A record created and propagated
|
|
- [ ] Authentication credentials chosen
|
|
- [ ] Whitelist enforcement method confirmed
|
|
|
|
### Deployment
|
|
- [ ] Application directory created
|
|
- [ ] Python virtual environment set up
|
|
- [ ] Dependencies installed
|
|
- [ ] Configuration files created
|
|
- [ ] Environment variables set
|
|
- [ ] Flask app coded and tested locally
|
|
- [ ] systemd service created and enabled
|
|
- [ ] Nginx configured and tested
|
|
- [ ] SSL certificate generated
|
|
- [ ] Application accessible via HTTPS
|
|
|
|
### Testing
|
|
- [ ] Service health check passed
|
|
- [ ] Web dashboard loads correctly
|
|
- [ ] Authentication working
|
|
- [ ] Single server whitelist toggle works
|
|
- [ ] Add player to single server works
|
|
- [ ] Remove player from single server works
|
|
- [ ] Bulk add to all servers works
|
|
- [ ] Bulk remove from all servers works
|
|
- [ ] Error handling tested
|
|
|
|
### Documentation
|
|
- [ ] Usage guide created in Git
|
|
- [ ] Deployment guide created in Git
|
|
- [ ] Link added to Wiki.js Staff portal
|
|
- [ ] Code committed to Git repository
|
|
- [ ] DOCUMENT-INDEX.md updated
|
|
- [ ] tasks.md updated with completion
|
|
|
|
### Operations
|
|
- [ ] Uptime Kuma monitor added
|
|
- [ ] Staff trained on usage
|
|
- [ ] Credentials stored in Vaultwarden
|
|
- [ ] Maintenance schedule documented
|
|
|
|
---
|
|
|
|
## 📚 REFERENCES
|
|
|
|
### Documentation
|
|
- Pterodactyl API: https://dashflo.net/docs/api/pterodactyl/v1/
|
|
- Flask Documentation: https://flask.palletsprojects.com/
|
|
- Nginx Reverse Proxy: https://docs.nginx.com/nginx/admin-guide/web-server/reverse-proxy/
|
|
- Let's Encrypt: https://letsencrypt.org/docs/
|
|
|
|
### Related Firefrost Docs
|
|
- `docs/troubleshooting/nc1-cleanup-guidelines.md` - Server cleanup best practices
|
|
- `docs/troubleshooting/hytale-troubleshooting-guide.md` - Game server troubleshooting
|
|
- `docs/core/tasks.md` - Master task list
|
|
- `docs/core/project-scope.md` - Infrastructure overview
|
|
|
|
---
|
|
|
|
**Document Status:** Ready for execution
|
|
**Next Steps:** Begin Phase 1 - Information Gathering
|
|
**Owner:** Michael "Frostystyle" Krause
|
|
**Implementation Partner:** The Chronicler
|
|
|
|
💙🔥❄️
|
|
|
|
**Fire + Frost + Foundation = Where Love Builds Legacy**
|
|
|