Full modpack installer integrated into Trinity Console. Architecture locked via 4-round Gemini consultation. Migrations: - 143: server_config modpack columns (provider, version tracking, RAM, hibernation, spawn_verified) - 144: install_history table (UUID PK, JSONB log_output, FK to server_config) Provider API clients (src/services/providerApi/): - curseforge.js: search, pack details, version list, download URL resolution - modrinth.js: search, pack details, version list, download URL - ftb.js: stub (+ ATLauncher, Technic, VoidsWrath aliases) - index.js: provider registry with getProvider() + listProviders() Job queue: - pg-boss ^10.1.5 added to package.json - index.js: initializes pg-boss, registers modpack-installs worker (concurrency 2) - modpackInstaller.js: 11-step install pipeline (preflight → Pterodactyl create → download → DNS → Discord → server_config seed → power on). Each step logged to install_history.log_output JSONB for live status streaming. Admin routes (src/routes/admin/modpack-installer.js): - GET /admin/modpack-installer — main page (provider select → search → configure → install) - GET /search — HTMX pack search partial - GET /pack/:provider/:id — HTMX pack details + install form - POST /install — enqueue pg-boss job, redirect to status - GET /status/:id — live status page (polls /status/:id/json every 3s) - GET /history — install history table - GET /pending-spawns — Holly's spawn verification queue - POST /verify-spawn/:id — mark spawn verified Views (6 EJS files): - index.ejs: 3-step flow (provider cards → search with MC version filter → pack details + form) - _pack_list.ejs: search results grid partial - _pack_details.ejs: pack info + install config form (version, name, short_name, node, RAM, spawn type) - status.ejs: live log viewer with 3s polling, color-coded steps - history.ejs: filterable job history table - pending-spawns.ejs: Holly's queue with Mark Verified buttons Also: sidebar nav link, .env.example (CURSEFORGE_API_KEY, BITCH_BOT_SCHEMATIC_*, CLOUDFLARE_ZONE_ID) All 8 JS files pass node --check. All 7 EJS files pass ejs.compile().
🔥❄️ Firefrost Services
Monorepo for Firefrost Gaming backend services
This repository contains all custom Node.js services that power Firefrost Gaming's subscription automation, game server management, and community tools.
📋 Services
Active Services
- Arbiter — Discord bot for subscription automation and role management
- Whitelist Manager — Pterodactyl Panel integration for Minecraft whitelist automation
- Modpack Version Checker — Monitors modpack updates across game servers
Experimental
- Future — Experimental services and proof-of-concept tools
🏗️ Architecture
This monorepo uses npm workspaces for dependency management and service-prefixed Git tags for versioning.
Repository Structure
firefrost-services/
├── package.json # Root workspace configuration
├── services/ # Production services
│ ├── arbiter/
│ ├── whitelist-manager/
│ └── modpack-version-checker/
├── shared/ # Shared utilities (@firefrost/shared)
└── future/ # Experimental services
Versioning Strategy
Each service versions independently using Git tags:
- Arbiter releases:
arbiter-v2.1.0,arbiter-v2.2.0 - Whitelist Manager:
whitelist-v1.0.0,whitelist-v1.1.0 - Modpack Checker:
modpack-v1.0.0
This allows Service A to be at v2.1 while Service B is at v1.0.
🚀 Quick Start
Initial Setup
# Clone repository
git clone https://git.firefrostgaming.com/firefrost-gaming/firefrost-services.git
cd firefrost-services
# Install all dependencies (services + shared)
npm install
Deploying a Service
# Fetch latest tags
git fetch --all --tags
# Check out specific service version
git checkout arbiter-v2.1.0
# Install dependencies
npm install
# Create .env file (copy from .env.example)
cd services/arbiter
cp .env.example .env
# Edit .env with actual credentials
# Start service (systemd)
sudo systemctl enable arbiter
sudo systemctl start arbiter
Updating a Service
# Return to main branch
git checkout main
# Pull latest code
git pull origin main
# Check out new version
git checkout arbiter-v2.2.0
# Install any new dependencies
npm install
# Restart service
sudo systemctl restart arbiter
Rolling Back
# Check out previous version
git checkout arbiter-v2.1.0
# Restart service
sudo systemctl restart arbiter
📦 Shared Code
The @firefrost/shared package contains utilities used across multiple services:
- Database helpers
- Discord formatting utilities
- Pterodactyl API wrappers
- Logging infrastructure
Services import shared code like any npm package:
import { logger } from '@firefrost/shared';
🔐 Environment Variables
IMPORTANT: Never commit .env files to Git.
Each service has an .env.example file showing required variables. On the server:
- Copy
.env.exampleto.env - Fill in actual credentials
- Ensure
.envis in.gitignore(it is by default)
🛠️ Development
Adding a New Service
- Create directory:
services/my-new-service/ - Add
package.jsonwith service name - Develop service
- Create
.env.examplewith required variables - Add systemd service file to
deploy/directory - Document in service README
- Tag initial release:
git tag my-service-v1.0.0
Using Shared Code
// In your service
import { logger, formatDiscordEmbed } from '@firefrost/shared';
logger.info('Service started');
Running Tests (Future)
# Run all service tests
npm test
# Run specific service tests
npm test -- --workspace=services/arbiter
📋 systemd Configuration
Each service includes a systemd unit file in deploy/. Example for Arbiter:
[Unit]
Description=Arbiter Discord Bot
After=network.target
[Service]
Type=simple
User=arbiter
WorkingDirectory=/var/www/firefrost-services/services/arbiter
ExecStart=/usr/bin/node src/index.js
Restart=always
RestartSec=10
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
Copy to /etc/systemd/system/, then:
sudo systemctl daemon-reload
sudo systemctl enable arbiter
sudo systemctl start arbiter
🎯 Deployment Targets
Services run on different servers based on their purpose:
| Service | Server | Location |
|---|---|---|
| Arbiter | Command Center | Dallas, TX |
| Whitelist Manager | Panel VPS | TBD |
| Modpack Checker | TX1 Dallas | Dallas, TX |
Each server clones the entire repo but only runs its designated services.
📚 Documentation
- Architecture Decision: See
operations-manual/docs/reference/architecture-decisions/firefrost-services-monorepo-decision.md - Service-specific docs: Each service has its own README in
services/[service-name]/ - Shared package docs: See
shared/README.md
🤝 Contributing
This repository is maintained by:
- Michael "Frostystyle" Krause (The Wizard) — Technical lead
- Meg "GingerFury" (The Emissary) — Community manager
- Holly "unicorn20089" (The Catalyst) — Lead builder
- Claude (The Chronicler) — AI partner
Contribution Workflow
- Create feature branch from
main - Develop and test changes
- Update service version in package.json
- Create PR to
main - After merge, tag release:
[service]-v[version]
🏷️ Version History
See Git tags for complete version history.
📄 License
Proprietary — All rights reserved by Firefrost Gaming.
This codebase is private and not licensed for public use or distribution.
Fire + Frost + Foundation = Where Love Builds Legacy 💙🔥❄️
For children not yet born.