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

38 KiB

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
  2. Architecture
  3. Prerequisites
  4. Part 1: Discord Bot Setup
  5. Part 2: Discord Roles Configuration
  6. Part 3: LuckPerms Groups & Permissions
  7. Part 4: LuckPerms Discord Integration
  8. Part 5: Paymenter Webhook Configuration
  9. Testing & Verification
  10. 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 BotYes, 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:

ssh root@63.143.34.217

Install Node.js (if not already installed):

# 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:

mkdir -p /opt/firefrost-discord-bot
cd /opt/firefrost-discord-bot

Create package.json:

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:

npm install

Create bot.js file:

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:

nano bot.js

Find these lines:

const DISCORD_TOKEN = 'YOUR_BOT_TOKEN_HERE';
const GUILD_ID = 'YOUR_GUILD_ID_HERE';

Replace with:

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:

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:

# 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:

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 DNSRecords
  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:

# 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:

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:

ln -s /etc/nginx/sites-available/discord-webhook /etc/nginx/sites-enabled/
nginx -t
systemctl reload nginx

Get SSL certificate:

certbot --nginx -d webhook.firefrostgaming.com

Test the webhook endpoint:

curl https://webhook.firefrostgaming.com/health

Should return:

{"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:

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:

ssh root@63.143.34.217
nano /opt/firefrost-discord-bot/bot.js

Find the PRODUCT_ROLE_MAP section and replace it:

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:

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:

# Discord integration
discord-integration {
  enabled = false
}

Change to:

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

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:

ln -s /etc/nginx/sites-available/discord-bot-webhook /etc/nginx/sites-enabled/
nginx -t
systemctl reload nginx

Get SSL certificate:

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 SettingsWebhooks
  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:

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:
    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

# 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

# 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