Getting Started
Welcome to CraftDaemon! This documentation covers everything you need to know to install, configure, and run CraftDaemon on your Linux server. If this is your first time, read through each section in order, skipping steps is the most common cause of setup issues.
What is CraftDaemon?
CraftDaemon is a Discord bot that lets you manage your Minecraft server directly from Discord using slash commands. It integrates with systemd (Linux's service manager) to start, stop, and restart your server process, and uses RCON (a remote console protocol built into Minecraft) to query live server data like player count and TPS. You don't need to SSH into your server just to restart it, CraftDaemon handles it all from a Discord channel.
System Requirements
- Operating System: Linux with systemd (Ubuntu, Debian, Arch, etc.) - Check Operating System Compatibility
- Node.js: v18+ (v22 recommended; used for development and testing). To check what you have, run: node --version
- Minecraft Server:: Any server with RCON support enabled (Although Paper is recommended)
- Network: Outbound HTTPS access for the Discord API, and a local connection to RCON (127.0.0.1 by default)
CraftDaemon works with any Minecraft server that supports RCON for start/stop/restart commands. However, the full /status command (Specifically for TPS) requires a Paper server. This is the sole reason Paper is recommended, apart from it being extremely light. Compatiblity is being worked on for future updates.
This bot does not run natively on Windows or macOS. Advanced users may still run it using environments like Windows Subsystem for Linux (WSL) on Windows, or other Unix-like setups on macOS, but this is not officially supported.
A future migration to TypeScript is planned, which will likely require Node.js v22+.
Installation
Step 1: Clone the Repository
SSH into your Linux server and run the following to download CraftDaemon into the current directory, then navigate into it:
cd CraftDaemon
Step 2: Install Node.js Dependencies
This installs all required packages listed in package.json. Run this from inside the CraftDaemon directory:
If you get a "command not found" error, Node.js is not installed or not in your PATH. Verify with node --version and which node.
Step 3: Create Discord Bot Application
You'll need to create a bot account in Discord's developer portal. This gives you a token (like a password) that CraftDaemon uses to log in as your bot.
- Go to Discord Developer Portal at discord.com/developers/applications
- Click "New Application" and give it a name (e.g., "CraftDaemon")
- Navigate to the "Bot" section in the left sidebar and click "Add Bot"
- Click "Reset Token" to reveal your bot token, then copy it โ you'll paste this into your .env file later. You only see it once, so save it now.
- Scroll down to "Privileged Gateway Intents" and enable both:
- Server Members Intent
- Message Content Intent
- Go to "OAuth2" โ "URL Generator" in the left sidebar. Under "Scopes", check bot and applications.commands
- Under "Bot Permissions", check: Send Messages, Embed Links, Read Message History
- Copy the generated URL at the bottom of the page and open it in your browser to invite the bot to your Discord server
Your bot token is like a password, never share it. If you are contributing or modifying the for code yourself, never commit it to Git. Keep it only in your config/.env file, and make sure .env is listed in your .gitignore. If it gets leaked, immediately regenerate it in the Developer Portal.
Step 4: Set Up Minecraft as a systemd Service (If you haven't already)
CraftDaemon controls your Minecraft server through systemd, Linux's service manager. If your server isn't already running as a systemd service, you'll need to set this up. Create the service file using a text editor with root privileges:
Paste the following content into the file, then save and exit (Ctrl+O, Enter, Ctrl+X in nano):
Description=Minecraft Server
After=network.target
[Service]
Type=simple
User=minecraft
WorkingDirectory=/home/minecraft/server
ExecStart=/usr/bin/java -Xmx8G -Xms8G -jar server.jar nogui
Restart=on-failure
RestartSec=5s
[Install]
WantedBy=multi-user.target
Adjust the following to match your setup before saving:
- User: the Linux user that owns the Minecraft server files
- WorkingDirectory: the full path to your server folder
- ExecStart: make sure the java path is correct (which java will tell you) and the .jar filename matches your actual server jar
- -Xmx8G / -Xms8G: the maximum and starting RAM for your server โ adjust to suit your machine
Then reload systemd and enable the service to start on boot:
sudo systemctl enable minecraft
sudo systemctl start minecraft
Step 5: Enable RCON on Your Server
RCON (Remote Console) is a protocol built into Minecraft that allows CraftDaemon to query live server data and send commands. You need to enable it in your server's server.properties file, which is located in your Minecraft server directory. Open it with:
Find and update (or add) these three lines:
rcon.port=25575
rcon.password=your_secure_password_here
Use a strong, unique password โ this password must exactly match the RCON_PASSWORD value in your .env later. After saving, restart your Minecraft server:
Step 6: Configure Environment Variables
CraftDaemon uses a .env file to store all sensitive configuration like your bot token and RCON password. Start by copying the provided example file:
Then open it for editing:
Fill in your values. At minimum, set these required fields:
GUILD_ID=your_server_id
CLIENT_ID=your_client_id
STATUS_CHANNEL_ID=your_channel_id
MC_SERVICE=minecraft
RCON_HOST=127.0.0.1
RCON_PORT=25575
RCON_PASSWORD=your_rcon_password
AUTO_STOP_MINUTES=10
WARNING_MINUTES=8
See the Configuration section for a full breakdown of every available variable.
Step 7: Register Slash Commands
Before users can see or use slash commands in Discord, they need to be registered with Discord's API. Run this once from the CraftDaemon directory:
You only need to run this once after initial setup, or again if you add or modify commands. Slash commands may take up to a minute to appear in Discord after registration.
Step 8: Set Up Sudoers Permissions
CraftDaemon needs to run systemctl commands (to start/stop/restart your Minecraft server) without being prompted for a password. This is done by adding a rule to the sudoers file. Always edit sudoers with visudo โ it validates the file before saving and prevents you from locking yourself out:
Scroll to the bottom of the file and add this line, replacing botuser with the Linux username the bot runs as:
Save and exit (Ctrl+O, Enter, Ctrl+X). To verify which user the bot will run as, check your craftdaemon.service file's User= field.
Only grant the bot the specific systemctl permissions it needs (as shown above). Never add the bot user to ALL=(ALL) NOPASSWD: ALL โ that would give it unrestricted root access to your entire system.
Step 9: Install as systemd Service (Optional but Recommended)
Running CraftDaemon as a systemd service means it automatically starts on boot and restarts itself if it crashes. Create the service file:
Paste the following, then update User and WorkingDirectory to match your setup:
Description=CraftDaemon Bot
After=network.target
[Service]
Type=simple
User=botuser
WorkingDirectory=/path/to/CraftDaemon
ExecStart=/usr/bin/node src/index.js
Restart=on-failure
RestartSec=10s
StandardOutput=journal
StandardError=journal
Environment="NODE_ENV=production"
[Install]
WantedBy=multi-user.target
Make sure the node path in ExecStart is correct โ run which node to find yours. Then enable and start:
sudo systemctl enable craftdaemon
sudo systemctl start craftdaemon
CraftDaemon requires Node.js 18+ and is tested on Node.js 22. Check your version with node --version. If you need to install or update Node.js, use nvm or your distro's package manager.
Configuration
Environment Variables (.env)
All configuration is managed through config/.env. This file should never be shared or committed to Version Control, it lives only on your server (If you're using GitHub). If the file doesn't exist yet, create it by copying the example: cp config/.env.example config/.env, then edit it with nano config/.env. Here's a complete reference of every available variable:
| Variable | Required | Description | Options (Suggested Range) |
|---|---|---|---|
| TOKEN | โ | Your Discord bot token | Discord bot token string |
| GUILD_ID | โ | Your Discord server ID (for registration) | Discord guild/server ID |
| CLIENT_ID | โ | Your Discord application client ID | Discord application client ID |
| STATUS_CHANNEL_ID | โ | Channel for status/warning messages | Discord channel ID |
| MC_SERVICE | โ | Minecraft systemd service name | Systemd unit name (default: minecraft) |
| SERVER_TYPE | โ๏ธ | Server type for TPS reporting in /status | PAPER (default left blank), change to PAPER for Paper tps parsing |
| RCON_HOST | โ | RCON server address | Default: 127.0.0.1 |
| RCON_PORT | โ | RCON port (from server.properties) | Valid: 1-65535 (default: 25575) |
| RCON_PASSWORD | โ | RCON password (from server.properties) | Must exactly match server.properties |
| AUTO_STOP_MINUTES | โ๏ธ | Minutes before auto-stop (set 0 to disable) | 0 or 5-60 (default: 10) |
| WARNING_MINUTES | โ๏ธ | Minutes before warning is posted | 0 to disable warning, otherwise below AUTO_STOP_MINUTES (default: 8) |
| CHECK_INTERVAL_MS | โ๏ธ | Auto-stop check interval in milliseconds | 10000-60000 (default: 30000) |
| SAVEALL_DELAY_MS | โ๏ธ | Delay between save-all and stop/restart | 500-3000 (default: 1000) |
| COMMAND_COOLDOWN_MS | โ๏ธ | Cooldown between start/stop/restart commands | 0 or 2000-60000 (default: 10000) |
| PRESENCE_SYSTEMD_FALLBACK_INTERVAL_MS | โ๏ธ | Presence fallback interval while RCON is disconnected | 10000-30000 (default: 15000) |
| RCON_KEEPALIVE_INTERVAL_MS | โ๏ธ | Persistent RCON keepalive interval | 30000-60000 (default: 45000) |
| RCON_RECONNECT_INTERVAL_MS | โ๏ธ | Delay between RCON reconnect attempts | 3000-10000 (default: 5000) |
| RCON_STARTING_GRACE_PERIOD_MS | โ๏ธ | How long to keep "Server Starting..." state after reconnect | 5000-20000 (default: 10000) |
| RCON_COMMAND_TIMEOUT_MS | โ๏ธ | Timeout for individual RCON commands | 5000-15000 (default: 8000) |
| RCON_MAX_KEEPALIVE_FAILURES | โ๏ธ | Keepalive failures before forced reconnect | 1-3 (default: 2) |
| RCON_REFUSED_LOG_INTERVAL_MS | โ๏ธ | Throttle interval for repeated ECONNREFUSED logs | 0 or 30000-120000 (default: 60000) |
| LOG_LEVEL | โ๏ธ | Global log level | DEBUG, INFO, WARN, ERROR |
| DEBUG_PERMS | โ๏ธ | Enable detailed permission check logs | true or false (default: false) |
| MAIN_ADDRESS | โ๏ธ | Public server address for /address command | Any reachable public address (optional) |
| LOCAL_ADDRESS | โ๏ธ | LAN address for /address command | LAN address + port (optional) |
| JAVA_EDITION_VERSION | โ๏ธ | Java version text shown in /address | Any Java version label text (optional) |
| UPDATE_NOTIFY_CHANNEL_ID | โ๏ธ | Preferred channel for update announcement embeds | Discord channel ID (optional; has fallback behavior) |
| UPDATE_SERVICE_DEBUG | โ๏ธ | Enable mock latest-version override for testing | true or false (default: false) |
| UPDATE_SERVICE_FORCE_LATEST | โ๏ธ | Forced semver used as latest when update debug is enabled | Semver string, used when UPDATE_SERVICE_DEBUG=true |
Legend: โ = Required, โ๏ธ = Optional (defaults are used when omitted).
Permission Configuration
Edit config/permission-config.js to control which Discord roles and users can run which commands. Open it with nano config/permission-config.js. The file exports a single object with four keys:
- owner: an array of Discord user IDs that bypass all permission checks โ typically just you
- roles: a map of short label names (e.g. ADMIN) to Discord role IDs
- commands: maps each permission key to an array of role labels that can use it
- users: optional per-user overrides that grant specific permission keys to individual users regardless of their roles
owner: ["123456789012345678"],
roles: {
ADMIN: "111111111111111111",
MOD: "222222222222222222",
Add more...: "333333333333333333"
},
commands: {
"server.start": ["ADMIN", "MOD"],
"server.stop": ["ADMIN", "MOD"],
"server.restart": ["ADMIN"],
"server.status": ["ADMIN", "MOD"],
"server.address": ["ADMIN", "MOD"],
"bot.checkUpdate":["ADMIN", "MOD"]
},
users: {
"444444444444444444": ["logs.delete"]
}
};
Replace the placeholder IDs with your actual Discord role and user IDs. Owners bypass all command checks entirely. Entries in users take precedence over role-based permissions โ useful for granting or restricting access to specific individuals.
Commands Reference
/start
Starts the Minecraft server by running systemctl start on your configured service. The bot replies with a status embed confirming the start was triggered.
- Permission: server.start
- Response: Confirmation embed with server startup status
- Notes: The server itself may take 10โ30 seconds to fully boot depending on world size โ this is normal. The command only triggers the start; it does not wait for the server to be ready.
/stop
Gracefully stops the server. Before stopping, CraftDaemon sends a save-all command via RCON to ensure no world data is lost, then calls systemctl stop.
- Permission: server.stop
- Response: Confirmation embed with stop status
- Notes: This is safe to use at any time โ the save-all happens automatically before shutdown
/restart
Restarts the server by saving world data first, then calling systemctl restart. Useful after config changes or to apply updates without manually stopping and starting.
- Permission: server.restart
- Response: Confirmation embed with restart status
- Notes: Like /stop, this always performs a save-all before restarting
/status
Shows a full live snapshot of your server: systemd service state, uptime, TPS (ticks per second), online player count, and current RCON round-trip latency.
- Permission: server.status
- Response: Rich embed with all server metrics
- Requires: A Paper server for full metrics (TPS, vanilla and other servers will not show TPS)
- Latency: Shows RCON round-trip time, which reflects the connection health between the bot and your server
/address
Displays your server's connection details: public IP/domain, LAN address, and the Java edition version label. Useful for sharing with players.
- Permission: server.address
- Response: Embed with connection details
- Requires: MAIN_ADDRESS and LOCAL_ADDRESS set in config/.env โ the command still works without them but will show empty fields
/ping
Checks the bot's connection health by measuring Discord API round-trip latency. Does not interact with the Minecraft server.
- Permission: No restriction โ all Discord members can use this
- Response: Simple message showing API latency in milliseconds
- Notes: Useful for confirming the bot is alive and responsive if other commands seem slow
/checkupdate
Fetches the latest release from GitHub and compares it to the version currently running. If a newer version is available, the full changelog is displayed in the embed.
- Permission: bot.checkUpdate
- Response: Embed showing current version vs latest GitHub release
- If newer: Displays the full changelog from the release notes
Permissions & RBAC
How Permissions Work
CraftDaemon uses a role-based access control (RBAC) system defined in config/permission-config.js. The idea is simple: each bot command has a permission key (e.g. server.start), and you decide which Discord roles can use it. You never configure permissions inside Discord itself โ everything is in that one JS file on your server.
Available Permission Keys
| Permission Key | Controls |
|---|---|
| server.start | /start command |
| server.stop | /stop command |
| server.restart | /restart command |
| server.status | /status command |
| server.address | /address command |
| bot.checkUpdate | /checkupdate command |
Example Configuration
Here's a typical setup with Owner, Admin, and Moderator roles. Replace the placeholder IDs with your real ones (see "Finding Discord IDs" below):
owner: ["OWNER_USER_ID"],
roles: {
ADMIN: "ADMIN_ROLE_ID",
MOD: "MODERATOR_ROLE_ID"
},
commands: {
"server.start": ["ADMIN", "MOD"],
"server.stop": ["ADMIN", "MOD"],
"server.restart": ["ADMIN"],
"server.status": ["ADMIN", "MOD"],
"server.address": ["ADMIN", "MOD"],
"bot.checkUpdate":["ADMIN"]
},
users: {
"YOUR_USER_ID": ["server.start"]
}
};
Finding Discord IDs
Discord IDs are long numeric strings that identify users, roles, and servers. To copy them, you first need to enable Developer Mode in Discord:
- Open Discord โ User Settings (gear icon) โ Advanced โ enable Developer Mode
- To get a Role ID: go to Server Settings โ Roles, then right-click the role and select "Copy Role ID"
- To get a User ID: right-click any user in the server member list and select "Copy User ID"
- To get your Guild (Server) ID: right-click the server name/icon and select "Copy Server ID"
Users listed in the owner array can run any command regardless of what's in commands. This is intended for the server admin โ typically just your own Discord user ID.
Features Guide
Auto-Shutdown
CraftDaemon can automatically shut down your Minecraft server when no players have been online for a specified duration. This is especially useful if you're paying for a VPS or cloud server โ no one online means no point running it.
Configuration (in config/.env):
- AUTO_STOP_MINUTES โ how many idle minutes before the server stops. Set to 0 to disable auto-shutdown entirely
- WARNING_MINUTES โ how many minutes before shutdown to post a warning message in your status channel. Must be less than AUTO_STOP_MINUTES
- CHECK_INTERVAL_MS โ how often (in milliseconds) the bot checks if the server is idle (default: 30000 = every 30 seconds)
How it works, step by step:
- The last player leaves the server โ player count hits 0
- The idle countdown timer starts
- When WARNING_MINUTES remain, the bot posts a warning in the status channel
- When the full AUTO_STOP_MINUTES expires, CraftDaemon automatically runs /stop (saves world first)
Live Bot Presence
CraftDaemon updates your bot's Discord status in real time to reflect your server state. Anyone in your Discord server can glance at the bot in the member list and immediately know if the server is up without running a command.
Presence states:
- ๐ด Do Not Disturb โ Server is offline
- ๐ก Idle โ Server is starting up
- ๐ข Online โ Shows live player count (e.g. "3 player(s) online")
RCON Manager
CraftDaemon maintains a persistent RCON connection to your Minecraft server rather than opening a new one for every command. This makes queries faster and allows the bot to detect connection drops and recover automatically.
What this handles for you:
- Automatic reconnection if the RCON connection drops (e.g. after a server restart)
- Command queueing so requests don't fail if sent during a brief reconnect window
- Live TPS and player count polling for presence updates
- RCON round-trip latency monitoring shown in /status
Update Notifications
Run /checkupdate at any time to see if a newer version of CraftDaemon is available. The bot fetches the latest release tag from GitHub and compares it to the version currently running. If an update is available, the full changelog from the release notes is shown in the response embed so you know exactly what changed before updating.
Troubleshooting
Bot Won't Start
The bot can't find your Discord token. Make sure config/.env exists (not just config/.env.example) and that TOKEN= is set. Create it with cp config/.env.example config/.env, then edit it with nano config/.env.
Check three things: (1) enable-rcon=true is set in server.properties, (2) the RCON_PASSWORD in your .env exactly matches rcon.password in server.properties, and (3) the Minecraft server is actually running (sudo systemctl status minecraft).
Commands Not Working
Run node src/register-commands.js again. Make sure GUILD_ID and CLIENT_ID in your .env are correct. Commands can take up to a minute to appear in Discord after registration.
Check config/permission-config.js. Verify that your Discord role ID or user ID is correctly entered โ IDs are 18โ19 digit numbers. Open it with nano config/permission-config.js and double-check the values. You can also set DEBUG_PERMS=true in your .env to see detailed permission check logs.
Server Control Issues
This is almost always a sudoers issue. Run sudo visudo and verify the bot user has the correct NOPASSWD rule for systemctl commands. Also confirm the service name in the sudoers rule matches MC_SERVICE in your .env (default is minecraft).
Full status data (TPS) requires a Paper server. Also verify RCON is connected by checking the bot logs.
Checking Logs
If CraftDaemon is running as a systemd service, view its live logs with:
The -f flag follows the log in real time (like tail -f). Press Ctrl+C to exit. If you want to run the bot directly to see output in your terminal instead (useful for debugging), stop the service first and run:
node src/index.js
For Minecraft server logs:
Architecture
System Overview
CraftDaemon sits between Discord and your Minecraft server, translating slash commands into systemd and RCON calls:
โ
โ /slash command
โ
CraftDaemon Bot โโ systemctl start/stop/restart โโ Minecraft (systemd)
โ โ
โโ RCON 127.0.0.1:25575 โโ RCON Server
Directory Structure
Here's the full layout of the repository and what each file/folder of the bot does:
โโโ config/
โ โโโ permission-config.js # RBAC rules (owners/roles/command permissions)
โ โโโ .env.example # Environment variable template
โโโ src/
โ โโโ index.js # Bot entry: client, RconManager, presence, auto-stop, command loader
โ โโโ register-commands.js # Guild slash registration (reads src/commands/*.js)
โ โโโ commands/ # One file per slash command (data + permission + execute)
โ โ โโโ ping.js
โ โ โโโ start.js
โ โ โโโ stop.js
โ โ โโโ restart.js
โ โ โโโ address.js
โ โ โโโ status.js
โ โ โโโ checkUpdate.js
โ โโโ events/
โ โ โโโ interactionCreate.js # Slash dispatch: RBAC middleware โ command.execute()
โ โโโ permissions/
โ โ โโโ index.js
โ โ โโโ middleware.js # permissionMiddleware (ephemeral deny)
โ โ โโโ resolver.js # hasPermission() against permission-config.js
โ โโโ utils/
โ โ โโโ storage.js # JSON persistence for per-guild update-notification state
โ โโโ services/
โ โโโ autoStopService.js # Auto-Stop/Auto-Shutdown logic and handler
โ โโโ updateService.js # GitHub release polling, ETag cache, update embed delivery
โ โโโ rconManager.js # Persistent RCON connection lifecycle + command pipeline
โ โโโ rconQuery.js # Command-facing RCON helpers (wired after clientReady)
โ โโโ minecraftSystemd.js # systemctl + save-all before stop/restart
โ โโโ commandLock.js # Cooldown lock for start/stop/restart
โ โโโ logger.js # Structured logging utility used across bot modules
โโโ package.json
โโโ README.md
The src/ layout is the intended structure, but the bot isn't rigid about it. If you prefer running index.js from the project root, that works too, as long as the paths in your systemd ExecStart point to the right place AND your file imports are correct.
Key Services
- logger.js: Structured logging with category prefixes, timestamps, and color-coded log levels. Used across all modules โ see the Logging section for full details
- rconManager.js: Persistent RCON connection lifecycle โ handles connect, keepalive pinging, automatic reconnect on failure, and the command pipeline
- rconQuery.js: Command-facing RCON helpers (e.g. player list, TPS queries) that are wired up after the client is ready
- minecraftSystemd.js: Wraps systemctl calls with a save-all flow before stop/restart operations to prevent data loss
- updateService.js: Polls the GitHub Releases API with ETag caching to compare the running version against the latest tag; delivers update embeds to a configured channel
- commandLock.js: Cooldown guard that prevents rapid repeated start/stop/restart calls within the configured COMMAND_COOLDOWN_MS window
- middleware.js / resolver.js: RBAC enforcement layer โ every slash command interaction passes through permissionMiddleware before command.execute() is called
- storage.js: Lightweight JSON persistence for per-guild state (e.g. update notification tracking)
Managing Services
Once both CraftDaemon and your Minecraft server are running, you'll mostly interact with them through Discord slash commands. But you'll occasionally need to manage things directly from the server โ here's a reference for every useful command.
systemctl โ Controlling Services
These commands let you start, stop, and inspect both the bot and the Minecraft server as systemd services. Replace craftdaemon with minecraft (or whatever you named your service) where applicable.
sudo systemctl status craftdaemon
sudo systemctl status minecraft
# Start a service
sudo systemctl start craftdaemon
# Stop a service
sudo systemctl stop craftdaemon
# Restart a service (stop then start)
sudo systemctl restart craftdaemon
# Enable a service to start automatically on boot
sudo systemctl enable craftdaemon
# Disable autostart on boot
sudo systemctl disable craftdaemon
# Reload systemd after creating or editing a .service file
sudo systemctl daemon-reload
journalctl โ Reading Logs
journalctl reads logs written by systemd services. These are your main tool for debugging when something isn't working as expected.
journalctl -u craftdaemon -n 50 --no-pager
# Follow live logs in real time (like tail -f) โ press Ctrl+C to exit
journalctl -u craftdaemon -f
# Follow live logs for the Minecraft server
journalctl -u minecraft -f
# View logs since the last boot only
journalctl -u craftdaemon -b
# View logs from a specific time window
journalctl -u craftdaemon --since "1 hour ago"
Open two terminals: run journalctl -u craftdaemon -f in one, and reproduce the issue in the other. You'll see exactly what the bot is doing in real time as it happens.
Logging
CraftDaemon uses a structured logging system with category-based prefixes, timestamps, and color-coded log levels. Every log line tells you when something happened, which component produced it, and how severe it is โ making it much easier to trace issues across the bot.
Log Format
Every log entry follows this structure:
For example:
12:35:47 [RCON] [DEBUG] RCON response received: There are 0 of a max of 20 players online
12:36:02 [AutoStop] [WARN] Server has been empty for 8 minutes
12:36:12 [SystemD] [ERROR] Failed to start server: Permission denied
Log Categories
Each category corresponds to a specific part of the bot. You'll see these as the bracketed label after the timestamp:
| Category | Color | What it covers |
|---|---|---|
| [Bot] | Cyan | General bot lifecycle and startup configuration |
| [Discord] | Blue | Discord.js client events and API interactions |
| [Minecraft] | Red | Minecraft server-specific events |
| [RCON] | Magenta | RCON connection lifecycle, commands sent, responses received |
| [AutoStop] | Yellow | Auto-shutdown timer events and idle detection |
| [SystemD] | White | systemctl calls โ start, stop, restart, status |
Log Levels
| Level | Color | When you'll see it |
|---|---|---|
| [DEBUG] | Gray | Detailed internal info (RCON commands, reconnect attempts). Hidden by default โ enable with LOG_LEVEL=DEBUG |
| [INFO] | Green | Normal operation โ bot started, server started/stopped, commands executed |
| [WARN] | Yellow | Something worth noticing but not broken โ RCON refused while server starts, idle warning sent |
| [ERROR] | Red | Something failed and needs attention โ permission denied, unhandled exception |
Changing the Log Level
By default the log level is INFO, which hides DEBUG output. To change it, set LOG_LEVEL in your config/.env:
Valid values: DEBUG, INFO, WARN, ERROR. No code changes or restarts of systemd are needed beyond restarting the bot itself (sudo systemctl restart craftdaemon).
Real Log Examples
Startup configuration summary โ printed every time the bot comes online:
03:15:30 [Bot] [INFO] RCON Host: 127.0.0.1
03:15:30 [Bot] [INFO] RCON Port: 25575
03:15:30 [Bot] [INFO] Minecraft Service: minecraft-service.service
03:15:30 [Bot] [INFO] Auto-stop enabled: Yes (10 min idle, warning at 8 min)
03:15:30 [Bot] [INFO] Status channel ID: 1404683867265489235
03:15:30 [Bot] [INFO] Main address: my-minecraft-server.joinmc.link
03:15:30 [Bot] [INFO] =============================================
03:15:31 [Discord] [INFO] โ CraftDaemon is online.
03:15:31 [Discord] [INFO] Logged in as CraftDaemon#2232
03:15:31 [SystemD] [INFO] Managing systemd service: minecraft-server.service
A slash command received from Discord:
RCON refused while the server is starting up โ the bot throttles repeated refusal logs so they don't flood your output:
12:33:41 [RCON] [WARN] RCON connection refused (server may be offline/starting). Retrying every 5s. (+11 similar refusals suppressed) [connect ECONNREFUSED 127.0.0.1:25575]
Auto-stop engaging โ the full idle โ warning โ shutdown sequence:
03:25:00 [AutoStop] [WARN] Server empty for 8.0 minutes. Warning sent (2 min until shutdown).
03:27:00 [AutoStop] [INFO] Server empty for 10.0 minutes (threshold: 10). Initiating shutdown.
Adding Logging to Custom Code
If you're extending CraftDaemon with your own modules, you can use the same logger. Import createLogger and give your component a category name:
const myLogger = createLogger('MyComponent');
myLogger.info("Something happened");
myLogger.warn("This might be a problem");
myLogger.error("An error occurred: " + err.message);
myLogger.debug("Detailed debug info โ only visible with LOG_LEVEL=DEBUG");
Logging is lightweight and designed for production use. DEBUG-level calls are completely skipped (not just filtered) when the log level is set to INFO or higher, so there's no performance penalty for leaving debug calls in your code.
Contributing
Want to Help?
CraftDaemon is a solo project and contributions are very welcome! Whether it's bug fixes, new features, documentation improvements, or just suggestions โ any input is appreciated.
How to Contribute
- Fork the repository on GitHub (click "Fork" on the repo page)
- Clone your fork locally: git clone https://github.com/YOUR_USERNAME/CraftDaemon
- Create a feature branch: git checkout -b feature/my-feature
- Make your changes
- Test thoroughly โ make sure existing functionality still works
- Commit with a clear message: git commit -m "Add my feature"
- Push to your fork: git push origin feature/my-feature
- Open a Pull Request on GitHub against the main repo
You should open an issue first for substantial, larger changes, or breaking changes, so we can align before you put work in.
Reporting Bugs
Found a bug? Open an issue on GitHub Issues. A good bug report includes:
- A clear description of what went wrong
- Steps to reproduce the issue
- What you expected to happen vs what actually happened
- Your environment details: Linux distro, Node.js version (node --version), Minecraft server type
- Relevant log output from journalctl -u craftdaemon if applicable
Code Standards
- Use consistent indentation (2 spaces)
- Write descriptive variable and function names
- Add comments for any complex or non-obvious logic
- Test your changes before submitting
- Follow the existing code style throughout the project
License
CraftDaemon is licensed under the MIT License. By contributing, you agree that your contributions will be licensed under the same license.
Feel free to open a GitHub Discussion or Issue if you have questions about contributing. There's no such thing as a dumb question here, so don't hesitate to reach out.
If CraftDaemon has been useful to you, consider giving it a โญ on GitHub! It helps others discover the project and means a lot to the development. Thanks for using it.