Skip to main content
This guide will help you deploy Faculty Bot from zero to a working Discord bot using Docker. You’ll have a fully functional bot managing your university Discord server in under 15 minutes.

Prerequisites

Before you begin, ensure you have:
  • Docker and Docker Compose installed
  • A Discord account with server administrator permissions
  • A PostgreSQL 13 database (or use the Docker Compose setup below)
  • An SMTP email server for student verification (e.g., Gmail, institutional email)
  • A student email domain for verification (e.g., @stud.hs-kempten.de)
Faculty Bot is written in Rust and uses the Poise framework for Discord interactions. It features student verification, XP/leveling systems, RSS feeds, meal plan posting, and more.

Step 1: Create a Discord Application

1

Create the Application

  1. Go to the Discord Developer Portal
  2. Click New Application
  3. Name it “Faculty Bot” (or your preferred name)
  4. Click Create
2

Create a Bot User

  1. Navigate to the Bot section in the left sidebar
  2. Click Add Bot and confirm
  3. Under the Token section, click Reset Token and copy it
  4. Save this token securely - you’ll need it for the .env file
3

Configure Bot Permissions

Enable these Privileged Gateway Intents:
  • Server Members Intent
  • Message Content Intent
  • Presence Intent
These intents are required for Faculty Bot to function properly. Without them, the bot won’t be able to verify users or track XP.
4

Invite the Bot to Your Server

  1. Go to the OAuth2URL Generator section
  2. Select these scopes:
    • bot
    • applications.commands
  3. Select these bot permissions:
    • Manage Roles
    • Manage Channels
    • Send Messages
    • Manage Messages
    • Embed Links
    • Attach Files
    • Read Message History
    • Add Reactions
    • Use Slash Commands
  4. Copy the generated URL and open it in your browser
  5. Select your server and authorize the bot

Step 2: Set Up Your Discord Server

Faculty Bot requires specific channels and roles to function. Create these in your Discord server:

Required Roles

staffrole

Management role for bot administration. Members with this role can edit bot settings via commands.

verified

Assigned to users after email verification. Use this to control channel access.

semestermodrole

Semester moderator role for student representatives.

mealplannotify

Receives notifications when new meal plans are posted.

Required Channels

Create these channels and note their IDs (Right-click → Copy ID):
  • #logs - Bot activity logs (staff only)
  • #news - Bot announcements
  • #xp - Level-up notifications
  • #rules - Server rules
  • #ads - External ads (auto-deleted after timeout)
  • #mealplan - Meal plan updates
  • 🔊 New VoiceChannel - Voice channel for dynamic channel creation
Enable Developer Mode in Discord (Settings → Advanced → Developer Mode) to copy channel and role IDs.

Step 3: Configure Environment Variables

Create a .env file in your project directory:
.env
DISCORD_TOKEN=your_bot_token_here

# PostgreSQL connection string
DATABASE_URL=postgres://faculty_manager:averysecurepasswordyes@database:5432/faculty_manager

# Command prefix (if using prefix commands)
PREFIX=>

# Email configuration for student verification
SEND_FROM_ADDRESS=[email protected]
MAIL_USERNAME=your_smtp_username
MAIL_PASSWORD=your_smtp_password
SMTP_SERVER=smtp.gmail.com
SMTP_PORT=587

# PostgreSQL credentials (for Docker)
POSTGRES_USER=faculty_manager
POSTGRES_PASSWORD=averysecurepasswordyes
POSTGRES_DB=faculty_manager

# Logging level (optional but recommended)
RUST_LOG="info,sqlx=error,sqlx::query=error,sqlx::query_as=error"

# InfluxDB (optional - for metrics)
INFLUX_TOKEN=your_influx_token_here
Never commit your .env file to version control. Add it to .gitignore to keep your credentials safe.

Email Configuration

For Gmail SMTP:
SMTP_SERVER=smtp.gmail.com
SMTP_PORT=587
MAIL_USERNAME=[email protected]
MAIL_PASSWORD=your-app-password
You’ll need to create an App Password instead of using your regular password.

Step 4: Configure Bot Settings

Create a config.json file with your Discord IDs and settings:
config.json
{
  "prefix": ">",
  "channels": {
    "xp": "YOUR_XP_CHANNEL_ID",
    "rules": "YOUR_RULES_CHANNEL_ID",
    "news": "YOUR_NEWS_CHANNEL_ID",
    "logs": "YOUR_LOGS_CHANNEL_ID",
    "ads": "YOUR_ADS_CHANNEL_ID",
    "createChannel": "🔊 New VoiceChannel",
    "mealplan": "YOUR_MEALPLAN_CHANNEL_ID"
  },
  "colors": {
    "blue": "#4200ff",
    "lightblue": "#FFFFF",
    "green": "#28823d",
    "red": "#cf0a0a"
  },
  "roles": {
    "staffrole": "YOUR_STAFF_ROLE_ID",
    "semestermodrole": "YOUR_SEMESTER_MOD_ROLE_ID",
    "verified": "YOUR_VERIFIED_ROLE_ID",
    "mealplannotify": "YOUR_MEALPLAN_NOTIFY_ROLE_ID"
  },
  "general": {
    "adstimeout": 2147483647,
    "charsForLevel": 25,
    "xpScalingFactor": 0.5
  },
  "mealplan": {
    "postMealplan": true,
    "url": "http://www.max-manager.de/daten-extern/augsburg/pdf/wochenplaene/hs-kempten/aktuell.pdf",
    "check": 30,
    "postOnDay": "Monday",
    "postAtHour": "09:00:00",
    "imgsettings": {
      "density": 400,
      "quality": 100,
      "flatten": false,
      "width": 768,
      "height": 512
    }
  },
  "rssSettings": {
    "postRss": false,
    "rssFeedData": {},
    "rssCheckIntervalHours": 1,
    "rssCheckAfterTimeHours": 8
  },
  "podcastSettings": {
    "postPodcast": false,
    "podcastCheckInterval": 1,
    "podcastUrl": "",
    "podcastChannel": ""
  }
}
  • prefix: Command prefix for text commands (e.g., >help)
  • charsForLevel: Number of characters needed to gain 1 XP (default: 25)
  • xpScalingFactor: XP scaling multiplier for leveling (default: 0.5)
  • adstimeout: Time in milliseconds before ads are deleted (default: max int for no deletion)
  • postMealplan: Enable/disable automatic meal plan posting
  • mealplan.check: Minutes between meal plan update checks
  • mealplan.postOnDay: Day of week to post meal plans (Monday-Sunday)
  • mealplan.postAtHour: Time to post meal plans (format: HH:MM:SS)

Step 5: Deploy with Docker Compose

Create a docker-compose.yml file:
docker-compose.yml
version: "3"
services:
  bot:
    container_name: faculty_manager
    image: ghcr.io/rndrmu/facultymanager:latest
    volumes:
      - './config.json:/config.json:ro'
      - './images:/images'
      - './migrations:/migrations'
    env_file:
      - .env
    depends_on:
      - database
    networks:
      - bot
    restart: unless-stopped

  database:
    container_name: faculty_manager_db
    image: postgres:13
    environment:
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: ${POSTGRES_DB}
    volumes:
      - ./migrations/faculty_manager.sql:/docker-entrypoint-initdb.d/init.sql
      - postgres_data:/var/lib/postgresql/data
    networks:
      - bot
    restart: unless-stopped

volumes:
  postgres_data:

networks:
  bot: {}
You’ll need the migrations/faculty_manager.sql file from the repository. Download it or clone the repo to get the database schema.

Step 6: Download Database Schema

Download the database initialization script:
mkdir -p migrations
curl -o migrations/faculty_manager.sql https://raw.githubusercontent.com/rndrmu/FacultyManager/main/migrations/faculty_manager.sql
Or create the file manually with this schema:
migrations/faculty_manager.sql
CREATE TABLE IF NOT EXISTS verified_users (
    user_id BIGINT PRIMARY KEY NOT NULL,
    user_email TEXT NOT NULL
);

CREATE TABLE IF NOT EXISTS user_xp (
    user_id BIGINT PRIMARY KEY NOT NULL,
    user_xp FLOAT8 NOT NULL DEFAULT 0.0,
    user_level INTEGER NOT NULL DEFAULT 0
);

CREATE TABLE IF NOT EXISTS voice_channels (
    channel_id BIGINT PRIMARY KEY NOT NULL,
    owner_id BIGINT NOT NULL,
    deletion_marker BOOL NOT NULL DEFAULT FALSE
);

CREATE TABLE IF NOT EXISTS mensaplan (
    date TEXT PRIMARY KEY NOT NULL,
    posted BOOL NOT NULL DEFAULT FALSE,
    plan_hash TEXT NOT NULL DEFAULT ''
);

CREATE TABLE IF NOT EXISTS ads (
    message_id BIGINT PRIMARY KEY NOT NULL,
    posted_at TIME DEFAULT CURRENT_TIME
);

CREATE TABLE IF NOT EXISTS rules (
    rule_number INTEGER PRIMARY KEY NOT NULL UNIQUE,
    rule_text TEXT NOT NULL
);

CREATE TABLE IF NOT EXISTS semestermods (
    user_id BIGINT PRIMARY KEY NOT NULL
);

CREATE TABLE IF NOT EXISTS posted_rss (
    message_id BIGINT PRIMARY KEY NOT NULL,
    rss_title TEXT NOT NULL,
    channel_id BIGINT NOT NULL
);

Step 7: Launch Faculty Bot

Start the bot with Docker Compose:
docker compose up -d
Check the logs to ensure everything started correctly:
docker compose logs -f bot
You should see output like:
Loaded .env file
Starting up
Mealplan will be posted on Monday at 09:00:00
Starting email task
Successfully registered Application Commands globally
Your bot should now be online in your Discord server! Check the bot’s status in your member list.

Step 8: Test the Bot

Run the register command in Discord to ensure slash commands are working:
>register
The >register command requires the Manage Server permission and registers all slash commands for your server.
Try these commands to verify functionality:
/verify init email:[email protected]

Verification Workflow

Here’s how student verification works:
1

Student Initiates Verification

User runs: /verify init email:[email protected]
2

Bot Sends Verification Email

The bot sends a verification code to the student’s email address using your SMTP server.
3

Student Enters Code

User runs: /verify code:123456The bot checks the code and assigns the verified role if correct.
4

Access Granted

The student can now access channels restricted to the verified role.

Troubleshooting

Check the container logs:
docker compose logs bot
Common issues:
  • Invalid Discord token
  • Database connection failed
  • Missing environment variables
Verify your SMTP settings:
docker compose logs bot | grep -i email
Check:
  • SMTP credentials are correct
  • SMTP_PORT is correct (usually 587 for TLS)
  • Firewall isn’t blocking outbound SMTP
  • Using app passwords for Gmail
  1. Ensure the bot has applications.commands scope
  2. Run >register with Manage Server permission
  3. Wait up to 1 hour for Discord to propagate commands globally
  4. Try kicking and re-inviting the bot with the correct scopes
Check that the database container is running:
docker compose ps
Verify DATABASE_URL in .env matches your Docker service name:
DATABASE_URL=postgres://faculty_manager:password@database:5432/faculty_manager

Next Steps

Configure Features

Set up meal plans, RSS feeds, and advanced features

Commands Reference

View all available bot commands

Administration

Learn about staff and moderation commands

Development

Contribute to Faculty Bot or build from source

Managing the Bot

Useful Docker Compose commands:
# Stop the bot
docker compose down

# Restart the bot
docker compose restart bot

# View logs
docker compose logs -f bot

# Update to latest version
docker compose pull
docker compose up -d

# Remove everything (including database)
docker compose down -v
The -v flag in docker compose down -v will delete all database data. Only use this if you want to start fresh.

Build docs developers (and LLMs) love