Files
firefrost-operations-manual/docs/guides/subscription-automation-guide.md
Claude e0d1791e8f fix: Add Cloudflare DNS setup to Michael's pre-setup
Added Task 7: Set Up DNS (Cloudflare) before Nginx configuration.

Michael needs to:
1. Add A record: webhook.firefrostgaming.com → 63.143.34.217
2. Set to DNS only (proxy OFF)
3. Verify DNS propagation with dig

Renumbered subsequent tasks (Nginx is now Task 8, Holly prep is Task 9).

Chronicler #40
2026-03-22 12:16:38 +00:00

1403 lines
38 KiB
Markdown

# Firefrost Gaming - Subscription Automation Guide
**Version:** 1.0
**Date:** March 23, 2026
**Author:** Chronicler #40
**Audience:** Holly (Lead Builder) + Michael (for Discord bot setup)
**Purpose:** Automate subscriber tier assignment from Paymenter purchase to in-game ranks
---
## 📋 TABLE OF CONTENTS
1. [Overview](#overview)
2. [Architecture](#architecture)
3. [Prerequisites](#prerequisites)
4. [Part 1: Discord Bot Setup](#part-1-discord-bot-setup)
5. [Part 2: Discord Roles Configuration](#part-2-discord-roles-configuration)
6. [Part 3: LuckPerms Groups & Permissions](#part-3-luckperms-groups-permissions)
7. [Part 4: LuckPerms Discord Integration](#part-4-luckperms-discord-integration)
8. [Part 5: Paymenter Webhook Configuration](#part-5-paymenter-webhook-configuration)
9. [Testing & Verification](#testing-verification)
10. [Troubleshooting](#troubleshooting)
---
## 🎯 OVERVIEW
### What This Guide Does
This guide sets up **fully automated subscription management**:
1. User purchases subscription in Paymenter
2. Paymenter sends webhook to Discord bot
3. Discord bot assigns appropriate role to user
4. LuckPerms detects Discord role and syncs to in-game rank
5. Player automatically gets correct permissions on all 13 servers
**No manual work required after setup.**
### The Flow
```
User Subscribes ($1-$499)
Paymenter (billing.firefrostgaming.com)
Webhook fires (new purchase detected)
Discord Bot receives webhook
Bot assigns Discord role (The Awakened, Fire Elemental, etc.)
LuckPerms syncs Discord role → In-game group
Player gets permissions on all 13 servers instantly
Player can join servers, claim chunks, set homes (based on tier)
```
### Time Estimate
- **Discord Bot Setup:** 1-2 hours (Michael + Holly)
- **Discord Roles:** 30 minutes (Holly)
- **LuckPerms Configuration:** 2-3 hours (Holly, across all 13 servers)
- **Paymenter Webhooks:** 1 hour (Michael + Holly testing)
**Total:** 4-6 hours
---
## 🏗️ ARCHITECTURE
### Components
1. **Paymenter** (billing.firefrostgaming.com) - Billing system
2. **Discord Server** - Community hub
3. **Discord Bot** - Automation middleman
4. **LuckPerms** - Permission management (all 13 game servers)
5. **MySQL Database** - Shared permission storage
### Why This Design?
**Why not direct Paymenter → LuckPerms?**
- Discord is the community hub - subscribers want Discord access too
- Discord roles provide social status and channel access
- Discord bot can handle complex logic (upgrades, downgrades, cancellations)
- Easier to troubleshoot (can see Discord roles visually)
**Why LuckPerms syncs FROM Discord?**
- Industry standard approach
- Discord becomes "source of truth" for subscriber status
- If someone loses subscriber role in Discord, they automatically lose in-game perks
- Prevents desync between Discord and game servers
---
## ✅ PREREQUISITES
### Before You Start
**Complete these first:**
- [ ] **Server-Side Mod Deployment Guide** completed on ALL 13 servers
- [ ] LuckPerms installed and connected to MySQL on all servers
- [ ] Michael has created MySQL database and provided credentials
- [ ] You have admin access to Firefrost Gaming Discord server
- [ ] You have access to Paymenter admin panel
### What You'll Need
**From Michael:**
- Discord bot token (Michael will create this)
- Paymenter admin credentials
- MySQL database credentials (already provided for LuckPerms)
**Access Required:**
- Discord server admin permissions
- Pterodactyl panel access (to restart servers)
- SSH access to game servers (for testing)
---
## 🤖 PART 1: DISCORD BOT SETUP
---
## 🔧 MICHAEL'S PRE-SETUP (Complete BEFORE Holly Starts)
**STOP: Michael must complete this entire section BEFORE handing the guide to Holly.**
### Task 1: Create Discord Application & Bot
**Michael's steps:**
1. Go to https://discord.com/developers/applications
2. Click **New Application**
3. Name: "Firefrost Subscription Manager"
4. Click **Create**
### Task 2: Configure Bot Settings
1. In the application, go to **Bot** tab (left sidebar)
2. Click **Add Bot****Yes, do it!**
3. Under **Privileged Gateway Intents**, enable:
-**Server Members Intent** (REQUIRED - bot needs to assign roles)
-**Message Content Intent** (REQUIRED - bot needs to read webhook data)
4. Click **Save Changes**
### Task 3: Get Bot Token
1. Under **Bot** tab, find **Token** section
2. Click **Reset Token** (confirm if asked)
3. Click **Copy** to copy the token
4. **SAVE THIS TOKEN SECURELY** - you'll give it to Holly later
**The token looks like:**
```
MTxxxxxxxxxxxxxxxxxxxxxx.xxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxx
```
**⚠️ NEVER share this token publicly or commit it to git!**
### Task 4: Invite Bot to Discord Server
1. Go to **OAuth2** tab → **URL Generator** (left sidebar)
2. Under **Scopes**, select:
-`bot`
-`applications.commands`
3. Under **Bot Permissions**, select:
-**Manage Roles** (REQUIRED - assigns subscriber roles)
-**Send Messages** (for welcome DMs)
-**Read Message History** (optional)
-**Use Slash Commands** (future-proofing)
4. Scroll down and **Copy** the generated URL
5. Open the URL in a new browser tab
6. Select **Firefrost Gaming** server from dropdown
7. Click **Authorize**
8. Complete the CAPTCHA
**The bot should now appear in your Discord server's member list (offline status is normal - it's not running yet).**
### Task 5: Get Discord Server ID (Guild ID)
1. Open Discord
2. Go to **User Settings** (gear icon)
3. Go to **Advanced** (left sidebar)
4. Enable **Developer Mode**
5. Close settings
6. Right-click your **Firefrost Gaming** server icon
7. Click **Copy Server ID**
8. **Save this ID** - you'll give it to Holly
**The ID looks like:**
```
123456789012345678
```
### Task 6: Deploy Bot Code on Command Center
**SSH to Command Center:**
```bash
ssh root@63.143.34.217
```
**Install Node.js (if not already installed):**
```bash
# Check if Node.js is installed
node --version
# If not installed or version < 18, install Node.js 20:
curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
apt-get install -y nodejs
# Verify
node --version # Should show v20.x.x
npm --version # Should show 10.x.x
```
**Create bot directory:**
```bash
mkdir -p /opt/firefrost-discord-bot
cd /opt/firefrost-discord-bot
```
**Create package.json:**
```bash
cat > package.json << 'EOF'
{
"name": "firefrost-discord-bot",
"version": "1.0.0",
"description": "Firefrost Gaming subscription automation bot",
"main": "bot.js",
"scripts": {
"start": "node bot.js"
},
"dependencies": {
"discord.js": "^14.14.1",
"express": "^4.18.2",
"body-parser": "^1.20.2"
}
}
EOF
```
**Install dependencies:**
```bash
npm install
```
**Create bot.js file:**
```bash
cat > bot.js << 'EOF'
// Firefrost Gaming - Discord Subscription Bot
// Handles Paymenter webhooks and assigns Discord roles
const { Client, GatewayIntentBits } = require('discord.js');
const express = require('express');
const bodyParser = require('body-parser');
// Configuration - REPLACE THESE VALUES
const DISCORD_TOKEN = 'YOUR_BOT_TOKEN_HERE';
const GUILD_ID = 'YOUR_GUILD_ID_HERE';
// Product ID to Role ID mapping (from Paymenter)
// Holly will fill these in after creating Discord roles
const PRODUCT_ROLE_MAP = {
'2': 'AWAKENED_ROLE_ID',
'3': 'FIRE_ELEMENTAL_ROLE_ID',
'4': 'FROST_ELEMENTAL_ROLE_ID',
'5': 'FIRE_KNIGHT_ROLE_ID',
'6': 'FROST_KNIGHT_ROLE_ID',
'7': 'FIRE_MASTER_ROLE_ID',
'8': 'FROST_MASTER_ROLE_ID',
'9': 'FIRE_LEGEND_ROLE_ID',
'10': 'FROST_LEGEND_ROLE_ID',
'11': 'SOVEREIGN_ROLE_ID'
};
// Initialize Discord client
const client = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMembers
]
});
// Initialize Express for webhook receiver
const app = express();
app.use(bodyParser.json());
// Discord bot ready event
client.once('ready', () => {
console.log(`✅ Bot logged in as ${client.user.tag}`);
console.log(`🔗 Connected to ${client.guilds.cache.size} server(s)`);
});
// Webhook endpoint - Paymenter sends POST here
app.post('/webhook/paymenter', async (req, res) => {
try {
console.log('📬 Received webhook from Paymenter');
console.log('Payload:', JSON.stringify(req.body, null, 2));
const { event, product_id, user_email, discord_id } = req.body;
// Validate webhook
if (!event || !product_id) {
console.error('❌ Invalid webhook data - missing event or product_id');
return res.status(400).json({ error: 'Missing required fields' });
}
if (!discord_id) {
console.error('⚠️ No discord_id provided - cannot assign role');
return res.status(400).json({ error: 'Missing discord_id' });
}
console.log(`📦 Event: ${event}, Product: ${product_id}, Discord ID: ${discord_id}`);
// Get Discord guild
const guild = client.guilds.cache.get(GUILD_ID);
if (!guild) {
console.error('❌ Guild not found');
return res.status(500).json({ error: 'Guild not found' });
}
// Get member
const member = await guild.members.fetch(discord_id);
if (!member) {
console.error('❌ Member not found in Discord server');
return res.status(404).json({ error: 'Member not found' });
}
// Get role ID for this product
const roleId = PRODUCT_ROLE_MAP[product_id];
if (!roleId || roleId.includes('ROLE_ID')) {
console.error(`❌ No role mapped for product ${product_id} (or role ID not configured)`);
return res.status(400).json({ error: 'Unknown product or role not configured' });
}
// Handle event
if (event === 'subscription.created' || event === 'payment.completed') {
// Add role
await member.roles.add(roleId);
console.log(`✅ Added role ${roleId} to ${member.user.tag}`);
// Send welcome DM
try {
await member.send(`🎉 Welcome to Firefrost Gaming! Your subscription is now active. Check out the server - your perks are ready!`);
console.log(`📨 Sent welcome DM to ${member.user.tag}`);
} catch (err) {
console.log('⚠️ Could not send DM (user has DMs disabled)');
}
} else if (event === 'subscription.cancelled' || event === 'subscription.expired') {
// Remove role
await member.roles.remove(roleId);
console.log(`❌ Removed role ${roleId} from ${member.user.tag}`);
} else {
console.log(`⚠️ Unknown event type: ${event}`);
}
res.status(200).json({ success: true });
} catch (error) {
console.error('❌ Webhook processing error:', error);
res.status(500).json({ error: 'Internal server error', details: error.message });
}
});
// Health check endpoint
app.get('/health', (req, res) => {
res.status(200).json({
status: 'healthy',
bot: client.user ? client.user.tag : 'disconnected',
uptime: process.uptime()
});
});
// Start Express server
const PORT = 3100;
app.listen(PORT, () => {
console.log(`🌐 Webhook server listening on port ${PORT}`);
console.log(`📍 Webhook URL: http://localhost:${PORT}/webhook/paymenter`);
});
// Start Discord bot
client.login(DISCORD_TOKEN);
EOF
```
**Edit bot.js and add your credentials:**
```bash
nano bot.js
```
**Find these lines:**
```javascript
const DISCORD_TOKEN = 'YOUR_BOT_TOKEN_HERE';
const GUILD_ID = 'YOUR_GUILD_ID_HERE';
```
**Replace with:**
```javascript
const DISCORD_TOKEN = 'MTxxxx...'; // Your actual bot token from Task 3
const GUILD_ID = '123456789012345678'; // Your actual server ID from Task 5
```
**Save and exit** (Ctrl+X, Y, Enter)
**Create systemd service:**
```bash
cat > /etc/systemd/system/firefrost-discord-bot.service << 'EOF'
[Unit]
Description=Firefrost Gaming Discord Bot
After=network.target
[Service]
Type=simple
User=root
WorkingDirectory=/opt/firefrost-discord-bot
ExecStart=/usr/bin/node /opt/firefrost-discord-bot/bot.js
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
EOF
```
**Enable and start the bot:**
```bash
# Reload systemd
systemctl daemon-reload
# Enable auto-start on boot
systemctl enable firefrost-discord-bot
# Start the bot
systemctl start firefrost-discord-bot
# Check status
systemctl status firefrost-discord-bot
```
**You should see:**
```
● firefrost-discord-bot.service - Firefrost Gaming Discord Bot
Loaded: loaded
Active: active (running)
```
**View logs to confirm it's working:**
```bash
journalctl -u firefrost-discord-bot -f
```
**You should see:**
```
✅ Bot logged in as Firefrost Subscription Manager#1234
🔗 Connected to 1 server(s)
🌐 Webhook server listening on port 3100
```
**If you see errors about invalid token:**
- Double-check you copied the token correctly
- Make sure there are no extra spaces
- Verify the token hasn't been reset/revoked
**Press Ctrl+C to exit log view when done.**
### Task 7: Set Up DNS (Cloudflare)
**Before setting up Nginx, add DNS record:**
1. Go to https://dash.cloudflare.com
2. Select **firefrostgaming.com** domain
3. Go to **DNS****Records**
4. Click **Add record**
5. Configure:
- **Type:** A
- **Name:** webhook
- **IPv4 address:** 63.143.34.217 (Command Center IP)
- **Proxy status:** 🟠 DNS only (turn OFF the orange cloud)
- **TTL:** Auto
6. Click **Save**
**Wait 1-2 minutes for DNS to propagate.**
**Verify DNS is working:**
```bash
# Test DNS resolution
dig webhook.firefrostgaming.com
# Should show:
# webhook.firefrostgaming.com. 300 IN A 63.143.34.217
```
### Task 8: Set Up Nginx Reverse Proxy
**Still on Command Center, configure Nginx:**
```bash
cat > /etc/nginx/sites-available/discord-webhook << 'EOF'
server {
listen 80;
server_name webhook.firefrostgaming.com;
location / {
proxy_pass http://localhost:3100;
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_cache_bypass $http_upgrade;
}
}
EOF
```
**Enable the site:**
```bash
ln -s /etc/nginx/sites-available/discord-webhook /etc/nginx/sites-enabled/
nginx -t
systemctl reload nginx
```
**Get SSL certificate:**
```bash
certbot --nginx -d webhook.firefrostgaming.com
```
**Test the webhook endpoint:**
```bash
curl https://webhook.firefrostgaming.com/health
```
**Should return:**
```json
{"status":"healthy","bot":"Firefrost Subscription Manager#1234","uptime":123.456}
```
### Task 9: Prepare Information for Holly
**Create a file with all the info Holly needs:**
```bash
cat > /root/holly-bot-credentials.txt << EOF
Firefrost Discord Bot - Credentials for Holly
Bot Name: Firefrost Subscription Manager
Bot Token: $(grep "const DISCORD_TOKEN" /opt/firefrost-discord-bot/bot.js | cut -d"'" -f2)
Guild ID: $(grep "const GUILD_ID" /opt/firefrost-discord-bot/bot.js | cut -d"'" -f2)
Webhook URL: https://webhook.firefrostgaming.com/webhook/paymenter
Bot is installed on: Command Center (63.143.34.217)
Bot directory: /opt/firefrost-discord-bot/
Service name: firefrost-discord-bot
Commands for Holly:
- View logs: journalctl -u firefrost-discord-bot -f
- Restart bot: systemctl restart firefrost-discord-bot
- Edit bot code: nano /opt/firefrost-discord-bot/bot.js
Next Steps:
1. Holly creates Discord roles (Part 2 of guide)
2. Holly gets role IDs and updates bot.js PRODUCT_ROLE_MAP
3. Holly restarts bot: systemctl restart firefrost-discord-bot
4. Test webhook flow
---
Generated: $(date)
EOF
cat /root/holly-bot-credentials.txt
```
**Save this output - you'll give it to Holly.**
---
## ✅ MICHAEL'S PRE-SETUP COMPLETE
**Checklist before handing to Holly:**
- [ ] Discord bot created and invited to server
- [ ] Bot token saved securely
- [ ] Guild ID recorded
- [ ] Node.js installed on Command Center
- [ ] Bot code deployed to /opt/firefrost-discord-bot/
- [ ] Bot service running successfully
- [ ] Nginx reverse proxy configured
- [ ] SSL certificate obtained
- [ ] Webhook endpoint accessible at https://webhook.firefrostgaming.com
- [ ] Credentials file created for Holly
**If all checked, proceed to Part 2 and hand the guide to Holly.**
---
## 👥 HOLLY'S TASKS START HERE
**At this point, Michael has:**
- ✅ Created the Discord bot application
- ✅ Deployed bot code to Command Center
- ✅ Set up Nginx reverse proxy
- ✅ Bot is running and accessible at https://webhook.firefrostgaming.com
**Holly, you now need to:**
1. Create Discord roles (Part 2)
2. Update bot code with role IDs
3. Configure LuckPerms
4. Test the complete flow
---
## 👥 PART 2: DISCORD ROLES CONFIGURATION
### Step 1: Create Discord Roles (Holly's Task)
**In your Discord server:**
1. Right-click server icon → **Server Settings**
2. Click **Roles**
3. Click **Create Role** for each tier
**Create these roles (in order, top to bottom):**
#### Role 1: Sovereign (Founder)
- **Name:** `⚡ Sovereign`
- **Color:** `#FFD600` (Amber Gold)
- **Permissions:** (default member permissions)
- **Display separately:** ✅ Yes
- **Mentionable:** ✅ Yes
#### Role 2: Fire Legend
- **Name:** `🔥 Fire Legend`
- **Color:** `#FF3D00` (Deep Orange/Red)
- **Permissions:** (default member permissions)
- **Display separately:** ✅ Yes
#### Role 3: Frost Legend
- **Name:** `❄️ Frost Legend`
- **Color:** `#00E5FF` (Electric Cyan)
- **Permissions:** (default member permissions)
- **Display separately:** ✅ Yes
#### Role 4: Fire Master
- **Name:** `🔥 Fire Master`
- **Color:** `#FF3D00`
- **Permissions:** (default member permissions)
- **Display separately:** ✅ Yes
#### Role 5: Frost Master
- **Name:** `❄️ Frost Master`
- **Color:** `#00E5FF`
- **Permissions:** (default member permissions)
- **Display separately:** ✅ Yes
#### Role 6: Fire Knight
- **Name:** `🔥 Fire Knight`
- **Color:** `#FF3D00`
- **Permissions:** (default member permissions)
- **Display separately:** ✅ Yes
#### Role 7: Frost Knight
- **Name:** `❄️ Frost Knight`
- **Color:** `#00E5FF`
- **Permissions:** (default member permissions)
- **Display separately:** ✅ Yes
#### Role 8: Fire Elemental
- **Name:** `🔥 Fire Elemental`
- **Color:** `#FF3D00`
- **Permissions:** (default member permissions)
- **Display separately:** ✅ Yes
#### Role 9: Frost Elemental
- **Name:** `❄️ Frost Elemental`
- **Color:** `#00E5FF`
- **Permissions:** (default member permissions)
- **Display separately:** ✅ Yes
#### Role 10: The Awakened
- **Name:** `The Awakened`
- **Color:** `#FFFFFF` (White)
- **Permissions:** (default member permissions)
- **Display separately:** ✅ Yes
#### Role 11: Wanderer (Free)
- **Name:** `Wanderer`
- **Color:** `#99AAB5` (Gray)
- **Permissions:** Read messages only (restrict Send Messages in channels)
- **Display separately:** No
### Step 2: Get Role IDs
**For each role you just created:**
1. Right-click the role in Server Settings → Roles
2. Click **Copy ID** (if you don't see this, enable Developer Mode in Discord settings)
3. Paste the ID somewhere - you'll need them
**Create a mapping:**
```
The Awakened: 123456789012345678
Fire Elemental: 234567890123456789
Frost Elemental: 345678901234567890
Fire Knight: 456789012345678901
Frost Knight: 567890123456789012
Fire Master: 678901234567890123
Frost Master: 789012345678901234
Fire Legend: 890123456789012345
Frost Legend: 901234567890123456
Sovereign: 012345678901234567
```
### Step 3: Update Bot Code with Role IDs (Michael's Task)
**Holly:** After you create all the Discord roles and copy their IDs (from Step 2), give the list to Michael. He'll update the bot code.
**Michael:** Holly will give you a list like this:
```
The Awakened: 123456789012345678
Fire Elemental: 234567890123456789
Frost Elemental: 345678901234567890
Fire Knight: 456789012345678901
Frost Knight: 567890123456789012
Fire Master: 678901234567890123
Frost Master: 789012345678901234
Fire Legend: 890123456789012345
Frost Legend: 901234567890123456
Sovereign: 012345678901234567
```
**SSH to Command Center and edit the bot code:**
```bash
ssh root@63.143.34.217
nano /opt/firefrost-discord-bot/bot.js
```
**Find the `PRODUCT_ROLE_MAP` section and replace it:**
```javascript
const PRODUCT_ROLE_MAP = {
'2': '123456789012345678', // The Awakened (use Holly's actual ID)
'3': '234567890123456789', // Fire Elemental
'4': '345678901234567890', // Frost Elemental
'5': '456789012345678901', // Fire Knight
'6': '567890123456789012', // Frost Knight
'7': '678901234567890123', // Fire Master
'8': '789012345678901234', // Frost Master
'9': '890123456789012345', // Fire Legend
'10': '901234567890123456', // Frost Legend
'11': '012345678901234567' // Sovereign
};
```
**Save and exit** (Ctrl+X, Y, Enter)
**Restart the bot:**
```bash
systemctl restart firefrost-discord-bot
# Verify it restarted successfully
systemctl status firefrost-discord-bot
# Check logs to confirm no errors
journalctl -u firefrost-discord-bot -f
```
**You should see:**
```
✅ Bot logged in as Firefrost Subscription Manager#1234
🌐 Webhook server listening on port 3100
```
**Now hand back to Holly for Part 3.**
### Step 4: Configure Channel Permissions
**Create private channels for Fire/Frost paths:**
#### Fire Path Channels
- `#🔥-fire-general` - Only visible to Fire Elemental+ roles
- `#🔥-fire-builds` - Only visible to Fire Elemental+ roles
- `#🔥-fire-strategy` - Only visible to Fire Elemental+ roles
**Permissions:**
- Deny: `@everyone` - View Channel
- Allow: `@🔥 Fire Elemental`, `@🔥 Fire Knight`, `@🔥 Fire Master`, `@🔥 Fire Legend`, `@⚡ Sovereign`
#### Frost Path Channels
- `#❄️-frost-general` - Only visible to Frost Elemental+ roles
- `#❄️-frost-builds` - Only visible to Frost Elemental+ roles
- `#❄️-frost-strategy` - Only visible to Frost Elemental+ roles
**Permissions:**
- Deny: `@everyone` - View Channel
- Allow: `@❄️ Frost Elemental`, `@❄️ Frost Knight`, `@❄️ Frost Master`, `@❄️ Frost Legend`, `@⚡ Sovereign`
#### The Nexus (Sovereign Only)
- `#⚡-the-nexus` - Only visible to Sovereign
**Permissions:**
- Deny: `@everyone` - View Channel
- Allow: `@⚡ Sovereign` only
---
## ⚙️ PART 3: LUCKPERMS GROUPS & PERMISSIONS
**This is the longest section - you'll configure 11 groups across 13 servers.**
### Step 1: Create LuckPerms Groups
**Access ONE game server's console first (we'll sync to others after):**
1. Go to https://panel.firefrostgaming.com
2. Click on any server (doesn't matter which - they all share the MySQL database)
3. Click **Console** tab
4. Make sure server is **running** (start it if stopped)
**Then run these commands in the console:**
#### Create Wanderer Group (Free Tier)
```
/lp creategroup wanderer
/lp group wanderer setweight 10
/lp group wanderer meta setprefix "&7[Wanderer] "
/lp group wanderer meta setsuffix ""
```
#### Create Awakened Group ($1 Tier)
```
/lp creategroup awakened
/lp group awakened parent add wanderer
/lp group awakened setweight 20
/lp group awakened meta setprefix "&f[The Awakened] "
# Permissions
/lp group awakened permission set ftbessentials.home.set true
/lp group awakened permission set ftbessentials.home.teleport true
/lp group awakened meta setmeta max-homes 1
```
#### Create Fire Elemental Group ($5/mo)
```
/lp creategroup fire_elemental
/lp group fire_elemental parent add awakened
/lp group fire_elemental setweight 30
/lp group fire_elemental meta setprefix "&c[🔥 Fire Elemental] "
# Permissions
/lp group fire_elemental meta setmeta max-homes 5
/lp group fire_elemental permission set ftbchunks.claim true
/lp group fire_elemental meta setmeta max-claimed-chunks 25
/lp group fire_elemental permission set ftbessentials.rtp true
/lp group fire_elemental meta setmeta rtp-cooldown 3600
```
#### Create Frost Elemental Group ($5/mo)
```
/lp creategroup frost_elemental
/lp group frost_elemental parent add awakened
/lp group frost_elemental setweight 30
/lp group frost_elemental meta setprefix "&b[❄️ Frost Elemental] "
# Permissions (same as Fire Elemental)
/lp group frost_elemental meta setmeta max-homes 5
/lp group frost_elemental permission set ftbchunks.claim true
/lp group frost_elemental meta setmeta max-claimed-chunks 25
/lp group frost_elemental permission set ftbessentials.rtp true
/lp group frost_elemental meta setmeta rtp-cooldown 3600
```
#### Create Fire Knight Group ($10/mo)
```
/lp creategroup fire_knight
/lp group fire_knight parent add fire_elemental
/lp group fire_knight setweight 40
/lp group fire_knight meta setprefix "&c[🔥 Fire Knight] "
# Permissions
/lp group fire_knight meta setmeta max-homes 10
/lp group fire_knight meta setmeta max-claimed-chunks 49
/lp group fire_knight meta setmeta max-force-loaded-chunks 4
/lp group fire_knight meta setmeta rtp-cooldown 1800
```
#### Create Frost Knight Group ($10/mo)
```
/lp creategroup frost_knight
/lp group frost_knight parent add frost_elemental
/lp group frost_knight setweight 40
/lp group frost_knight meta setprefix "&b[❄️ Frost Knight] "
# Permissions (same as Fire Knight)
/lp group frost_knight meta setmeta max-homes 10
/lp group frost_knight meta setmeta max-claimed-chunks 49
/lp group frost_knight meta setmeta max-force-loaded-chunks 4
/lp group frost_knight meta setmeta rtp-cooldown 1800
```
#### Create Fire Master Group ($15/mo)
```
/lp creategroup fire_master
/lp group fire_master parent add fire_knight
/lp group fire_master setweight 50
/lp group fire_master meta setprefix "&c[🔥 Fire Master] "
# Permissions
/lp group fire_master meta setmeta max-homes 20
/lp group fire_master meta setmeta max-claimed-chunks 100
/lp group fire_master meta setmeta max-force-loaded-chunks 9
/lp group fire_master meta setmeta rtp-cooldown 900
```
#### Create Frost Master Group ($15/mo)
```
/lp creategroup frost_master
/lp group frost_master parent add frost_knight
/lp group frost_master setweight 50
/lp group frost_master meta setprefix "&b[❄️ Frost Master] "
# Permissions
/lp group frost_master meta setmeta max-homes 20
/lp group frost_master meta setmeta max-claimed-chunks 100
/lp group frost_master meta setmeta max-force-loaded-chunks 9
/lp group frost_master meta setmeta rtp-cooldown 900
```
#### Create Fire Legend Group ($20/mo)
```
/lp creategroup fire_legend
/lp group fire_legend parent add fire_master
/lp group fire_legend setweight 60
/lp group fire_legend meta setprefix "&c[🔥 Fire Legend] "
# Permissions
/lp group fire_legend meta setmeta max-homes 35
/lp group fire_legend meta setmeta max-claimed-chunks 121
/lp group fire_legend meta setmeta max-force-loaded-chunks 16
/lp group fire_legend meta setmeta rtp-cooldown 600
```
#### Create Frost Legend Group ($20/mo)
```
/lp creategroup frost_legend
/lp group frost_legend parent add frost_master
/lp group frost_legend setweight 60
/lp group frost_legend meta setprefix "&b[❄️ Frost Legend] "
# Permissions
/lp group frost_legend meta setmeta max-homes 35
/lp group frost_legend meta setmeta max-claimed-chunks 121
/lp group frost_legend meta setmeta max-force-loaded-chunks 16
/lp group frost_legend meta setmeta rtp-cooldown 600
```
#### Create Sovereign (Founder) Group ($499 Lifetime)
```
/lp creategroup sovereign
/lp group sovereign parent add awakened
/lp group sovereign setweight 100
/lp group sovereign meta setprefix "&6[⚡ Founder] "
# Permissions (maximum everything)
/lp group sovereign meta setmeta max-homes 50
/lp group sovereign meta setmeta max-claimed-chunks 225
/lp group sovereign meta setmeta max-force-loaded-chunks 81
/lp group sovereign permission set ftbessentials.rtp true
# No rtp cooldown for Sovereign
```
### Step 2: Verify Groups Created
```
/lp listgroups
```
**You should see all 11 groups listed.**
### Step 3: Sync to All Other Servers
**Because all servers connect to the SAME MySQL database, the groups are already synced!**
**To verify on another server:**
1. Go to Pterodactyl Panel
2. Open console for a different server
3. Run `/lp listgroups`
4. Should show the same 11 groups
**If groups don't appear:**
- Check that server's LuckPerms config points to the MySQL database
- Restart the server
---
## 🔗 PART 4: LUCKPERMS DISCORD INTEGRATION
**This connects Discord roles to LuckPerms groups.**
### Step 1: Enable Discord Integration in LuckPerms
**On EVERY server, edit `/config/luckperms/luckperms.conf`:**
**Find the section:**
```conf
# Discord integration
discord-integration {
enabled = false
}
```
**Change to:**
```conf
discord-integration {
enabled = true
# Role to group mappings
role-mappings {
# Format: "discord-role-id" = "luckperms-group"
"123456789012345678" = "awakened" # The Awakened
"234567890123456789" = "fire_elemental" # Fire Elemental
"345678901234567890" = "frost_elemental" # Frost Elemental
"456789012345678901" = "fire_knight" # Fire Knight
"567890123456789012" = "frost_knight" # Frost Knight
"678901234567890123" = "fire_master" # Fire Master
"789012345678901234" = "frost_master" # Frost Master
"890123456789012345" = "fire_legend" # Fire Legend
"901234567890123456" = "frost_legend" # Frost Legend
"012345678901234567" = "sovereign" # Sovereign
}
}
```
**Replace role IDs with the ACTUAL role IDs you copied in Part 2.**
**Save the file.**
### Step 2: Restart All Servers
**Via Pterodactyl Panel:**
1. Open each server's console
2. Click **Restart**
3. Wait for server to come back online
**Repeat for all 13 servers.**
### Step 3: Test Discord → LuckPerms Sync
**Manual test:**
1. Go to Discord
2. Manually assign yourself `The Awakened` role (right-click your name → Roles)
3. Join a Minecraft server
4. Run `/lp user YourUsername info`
5. Should show you're in the `awakened` group
**If it doesn't work:**
- Check LuckPerms config for typos in role IDs
- Check that Discord integration is enabled
- Restart the server
---
## 🪝 PART 5: PAYMENTER WEBHOOK CONFIGURATION
**This connects Paymenter to the Discord bot.**
### Step 1: Set Up Nginx Proxy (Michael's Task)
**On Command Center (where Discord bot runs):**
**Create file: `/etc/nginx/sites-available/discord-bot-webhook`**
```nginx
server {
listen 80;
server_name webhook.firefrostgaming.com;
location / {
proxy_pass http://localhost:3100;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
```
**Enable the site:**
```bash
ln -s /etc/nginx/sites-available/discord-bot-webhook /etc/nginx/sites-enabled/
nginx -t
systemctl reload nginx
```
**Get SSL certificate:**
```bash
certbot --nginx -d webhook.firefrostgaming.com
```
**Now the webhook endpoint is:**
```
https://webhook.firefrostgaming.com/webhook/paymenter
```
### Step 2: Configure Paymenter Webhooks (Michael + Holly)
**In Paymenter admin panel:**
1. Go to **Settings****Webhooks**
2. Click **Add Webhook**
3. Configure:
- **URL:** `https://webhook.firefrostgaming.com/webhook/paymenter`
- **Events:**
-`subscription.created`
-`payment.completed`
-`subscription.cancelled`
-`subscription.expired`
- **Payload Format:** JSON
4. Click **Save**
### Step 3: Test Webhook
**Create a test purchase in Paymenter (use test mode if available).**
**Watch Discord bot logs:**
```bash
journalctl -u firefrost-discord-bot -f
```
**You should see:**
```
📬 Received webhook from Paymenter
📦 Event: subscription.created, Product: 2, User: 123456789012345678
✅ Added role 123456789012345678 to TestUser#1234
```
**If it works, the user should now have The Awakened role in Discord.**
**If it doesn't work:**
- Check webhook URL is correct
- Check Paymenter is sending the correct payload format
- Check Discord bot logs for errors
---
## ✅ TESTING & VERIFICATION
### End-to-End Test
**Complete flow test:**
1. **Create test user in Discord**
2. **Purchase Awakened tier ($1) in Paymenter**
3. **Verify webhook fires** (check Discord bot logs)
4. **Verify Discord role assigned** (check Discord - user should have "The Awakened" role)
5. **Join Minecraft server**
6. **Run `/lp user TestUser info`** - Should show `awakened` group
7. **Test permissions:**
- `/sethome test` - Should work (1 home allowed)
- `/sethome test2` - Should FAIL (only 1 home for Awakened)
- Try claiming chunks - Should FAIL (Awakened has 0 chunk claims)
- Try `/rtp` - Should FAIL (Awakened has no /rtp access)
**If all these work correctly, the automation is functioning!**
### Upgrade Test
**Test tier upgrade:**
1. Upgrade test user to Fire Elemental ($5/mo) in Paymenter
2. Verify Discord role changes (old role removed, new role added)
3. Join Minecraft server
4. Run `/lp user TestUser info` - Should show `fire_elemental` group
5. Test new permissions:
- `/sethome` - Should work (5 homes allowed)
- Claim chunks - Should work (25 chunks allowed)
- `/rtp` - Should work (60 minute cooldown)
### Cancellation Test
**Test subscription cancellation:**
1. Cancel test user's subscription in Paymenter
2. Verify Discord role removed
3. Join Minecraft server
4. Run `/lp user TestUser info` - Should show `wanderer` or default group
5. Test permissions:
- `/sethome` - Should FAIL (no subscription)
- Try joining server - Should be DENIED (whitelist = Awakened+ only)
---
## 🔧 TROUBLESHOOTING
### Discord Role Not Assigned After Purchase
**Symptoms:** User purchases subscription but doesn't get Discord role.
**Check:**
1. **Webhook logs:** `journalctl -u firefrost-discord-bot -f`
- Are webhooks being received?
2. **Paymenter webhook config:** Is webhook URL correct?
3. **Discord bot permissions:** Does bot have "Manage Roles" permission?
4. **Role position:** Bot's role must be ABOVE subscriber roles in Discord role hierarchy
**Solution:**
- Move bot's role to the top of the role list in Discord Server Settings
- Restart Discord bot: `systemctl restart firefrost-discord-bot`
---
### LuckPerms Not Syncing Discord Roles
**Symptoms:** User has Discord role but no in-game permissions.
**Check:**
1. **LuckPerms config:** Is Discord integration enabled?
2. **Role IDs:** Are Discord role IDs correct in luckperms.conf?
3. **Server restart:** Did you restart server after config change?
**Solution:**
- Double-check role IDs match (right-click role in Discord → Copy ID)
- Ensure luckperms.conf has correct mapping
- Restart all game servers
---
### User Can't Join Server After Subscribing
**Symptoms:** User purchased subscription, has Discord role, but can't join server.
**Check:**
1. **Whitelist status:** Is whitelist enabled on server?
2. **LuckPerms sync:** Run `/whitelist add Username` manually as test
3. **Server online:** Is server actually running?
**Solution:**
- Ensure LuckPerms-based whitelist is configured (see Server-Side Mod Deployment Guide)
- Check server console for "User not whitelisted" messages
- Manually add to whitelist temporarily while debugging
---
### Webhook Endpoint Returns 500 Error
**Symptoms:** Paymenter shows webhook failed with 500 error.
**Check:**
1. **Bot running:** `systemctl status firefrost-discord-bot`
2. **Bot logs:** `journalctl -u firefrost-discord-bot -f` for errors
3. **Nginx proxy:** Is Nginx running and proxying correctly?
**Solution:**
- Restart Discord bot
- Check bot code for syntax errors
- Test webhook manually with curl:
```bash
curl -X POST https://webhook.firefrostgaming.com/webhook/paymenter \
-H "Content-Type: application/json" \
-d '{"event":"subscription.created","product_id":"2","discord_id":"YOUR_DISCORD_ID"}'
```
---
## 📚 REFERENCE
### Quick Command Reference
#### Discord Bot Management
```bash
# Start bot
systemctl start firefrost-discord-bot
# Stop bot
systemctl stop firefrost-discord-bot
# Restart bot
systemctl restart firefrost-discord-bot
# View logs
journalctl -u firefrost-discord-bot -f
# Check status
systemctl status firefrost-discord-bot
```
#### LuckPerms Commands
```bash
# View user's groups
/lp user <username> info
# Manually add user to group
/lp user <username> parent add <groupname>
# Remove user from group
/lp user <username> parent remove <groupname>
# View group permissions
/lp group <groupname> permission info
# List all groups
/lp listgroups
```
---
### Subscriber Tier → Discord Role → LuckPerms Group Mapping
| Tier | Price | Discord Role | LuckPerms Group |
|------|-------|--------------|-----------------|
| Wanderer | Free | `Wanderer` | `wanderer` |
| Awakened | $1 | `The Awakened` | `awakened` |
| Fire Elemental | $5/mo | `🔥 Fire Elemental` | `fire_elemental` |
| Frost Elemental | $5/mo | `❄️ Frost Elemental` | `frost_elemental` |
| Fire Knight | $10/mo | `🔥 Fire Knight` | `fire_knight` |
| Frost Knight | $10/mo | `❄️ Frost Knight` | `frost_knight` |
| Fire Master | $15/mo | `🔥 Fire Master` | `fire_master` |
| Frost Master | $15/mo | `❄️ Frost Master` | `frost_master` |
| Fire Legend | $20/mo | `🔥 Fire Legend` | `fire_legend` |
| Frost Legend | $20/mo | `❄️ Frost Legend` | `frost_legend` |
| Sovereign | $499 | `⚡ Sovereign` | `sovereign` |
---
### File Locations Quick Reference
```
Command Center (63.143.34.217)
└── /opt/firefrost-discord-bot/
├── bot.js
├── package.json
└── node_modules/
Game Servers (TX1/NC1)
└── /config/luckperms/
└── luckperms.conf (Discord integration config)
Nginx
└── /etc/nginx/sites-available/
└── discord-bot-webhook
```
---
**End of Subscription Automation Guide**
**You've now completed the full automation setup! Users can subscribe in Paymenter and automatically get:**
- Discord role assignment
- In-game rank sync
- Correct permissions on all 13 servers
- Channel access based on Fire/Frost path
**Fire + Frost + Foundation = Where Love Builds Legacy** 🔥❄️
---
**Document Version:** 1.0
**Last Updated:** March 23, 2026
**Maintained By:** Firefrost Gaming Infrastructure Team