- Overview
- Repositories
- Using The Bot
- Self-Host (Auto Configuration)
- Self-Host (Manual Configuration)
- Sharding (Advanced Configuration)
- Synchronizing Rate Limits (Advanced Configuration)
- Health Checks and Custom Port Configuration
- Native Builds
- License
- AI Usage Declaration and Policy
- Help
A free and open-source, self-hostable Discord bot designed to record the changes made to a server and deliver them to a configured channel without the need to manually navigate to Discord's Audit Log section.
With support for detecting more than 72 events, it can log changes made to: AutoMod Settings, Servers, Onboarding, Invites, Members, Roles, Channels, Threads, Stages, Events, Polls, Messages, Boosts, Emojis, Stickers, Soundboard, Integrations, Webhooks, Moderation Action, Unusual DMs, Raids and Unknown events.
| Repository | Description |
|---|---|
| PaperTrailBot | Core bot application |
| PaperTrail SDK | Java client library for interacting with the API |
| PaperTrail API | Backend API providing configuration and data storage |
| PaperTrail Deployment | Contains docker compose files for auto configuration and deployment of the bot and required services |
Important
PaperTrail is currently in maintenance mode. Existing bugs will be fixed, dependency updates will be provided but large new features will likely not be added. However, changes will be made to keep the bot and its services up to date with the latest Discord API changes.
A pre-configured and deployed instance is the easiest way to use this bot. Just invite it to your server and that's all.
Get it from here: https://discord.com/discovery/applications/1381658412550590475
Run the /setup slash command to see instructions on how to configure the bot for your server.
You do not need to continue reading further if you do not want to self-host the bot.
The following sections will tell you most of the things you need to know about self-hosting the bot by yourself:
Note
Uses docker compose and automatically sets up all the services for you.
Only autoconfigures 1 instance of each service.
Follow the deployment guide in: PaperTrail-Deployment Repository
Note
Gives you full control of the services you want to deploy.
You set up each service manually but have full control over the process.
Guides are provided for building and deploying each service locally or in cloud, with or without docker.
Follow this guide
Log on to the Discord Developer Portal and create an application.
The application can have any name, avatar, banner and description but the following scopes, permissions and intents are needed for it to work properly:
Installation Contexts
- Guild Install
Scopes
- applications.commands
- bot
Permissions
- Manage Server
- Read Message History
- Send Messages
- Send Messages In Threads
- View Audit Log
- View Channels
Privileged Gateway Intents
- Presence Intent
- Server Members Intent
- Message Content Intent
Don't forget to copy the bot token as it will be required in the next step
| Variable | Description | Default Value | Optional |
|---|---|---|---|
TOKEN |
Discord application bot token (from the Developer Portal) | No Default Value | No |
API_URL |
Internal URL of the PaperTrail API (e.g., http://localhost:8080) |
No Default Value | No |
Example .env file:
TOKEN="my-token"
API_URL="http://localhost:8080"Important
Since v4.1.3, the bot comes in two build forms: JVM and Native.
While this guide covers both the forms, it is recommended to use the JVM form since Native builds are currently
unstable.
For more info on native builds, see the native image section
The GitHub Container Registry has pre-built docker images for both JVM and Native versions the bot which you can use.
Container Registry for JVM Edition
Container Registry for Native Edition
You may choose either one.
Make sure you have the .env file containing the required secrets in the root of the folder
you're executing the following commands from:
# JVM
docker run -d --name papertrail-bot --env-file .env ghcr.io/eggy03/papertrail-bot:latest# Native
docker run -d --name papertrail-bot-native --env-file .env ghcr.io/eggy03/papertrail-bot-native:latestgit clone https://github.com/eggy03/PaperTrailBot.git
cd PaperTrailBot# JVM
docker build -t papertrail-bot .
docker run -d --name papertrail-bot --env-file .env papertrail-bot# Native
docker build -f Dockerfile.native -t papertrail-bot-native .
docker run -d --name papertrail-bot-native --env-file .env papertrail-bot-nativeNote
While the above sub-options use --env-file .env for examples, you can also pass environment variables directly
via docker -e KEY:"VALUE"
git clone https://github.com/eggy03/PaperTrailBot.git
cd PaperTrailBot# JVM
./mvnw clean package
java -jar target/quarkus-app/quarkus-run.jar# Native
./mvnw clean package -DnativeThe built application will be found in the target folder of the project.
If your cloud supports building from Dockerfile, point the source towards Dockerfile (for JVM Build)
or Dockerfile.native (for Native Build), found in the project's root.
If your cloud supports using pre-built docker images, you can find the image links in the container registry.
Upon successful deployment of all the required services, including the bot, you can run the slash command
/setup in a server where the bot has been invited. The command will tell you how to configure your bot.
Note
Sharding is required only when your bot reaches 2500 servers.
Sharding splits your bot connection into multiple independent connections to the Discord gateway. Each independent connection is called a shard. Discord allows you to have up to 2500 guilds per shard but the recommended configuration is 1 shard per 1000 guilds.
You will need the following additional environment variables for custom shard configuration.
| Variable | Description | Default Value | Optional |
|---|---|---|---|
TOTAL_SHARDS |
Total number of shards used by the bot across all running processes/instances | 1 | Yes |
MIN_SHARD_ID |
The first shard ID handled by this specific bot instance | 0 | Yes |
MAX_SHARD_ID |
The last shard ID handled by this specific bot instance | 0 | Yes |
Shard IDs start at 0.
If TOTAL_SHARDS=5, the valid shard IDs are:
0 1 2 3 4
Take a look at the following configuration examples to have a clearer picture of what values to put for your use-case
If your bot is small or self-hosted for a limited number of servers (<2500), one shard is sufficient. This is the default pre-applied configuration when you do not provide any manual shard info.
TOTAL_SHARDS=1
MIN_SHARD_ID=0
MAX_SHARD_ID=0If your bot exceeds the 2500 guild limit for a single shard, you can increase the shard count while still running one process:
TOTAL_SHARDS=2
MIN_SHARD_ID=0
MAX_SHARD_ID=1Remember that each shard can only handle up to 2500 guilds so plan the total number shards accordingly
If you run your bot across multiple processes, you need to split the shards between them.
Process/Instance 1:
TOTAL_SHARDS=10
MIN_SHARD_ID=0
MAX_SHARD_ID=4Process/Instance 2:
TOTAL_SHARDS=10
MIN_SHARD_ID=5
MAX_SHARD_ID=9Process 1 handles shards 0-4 and Process 2 handles 5-9. Each process manages 5 shards, together covering all 10 shards.
Important
Shard ID ranges must never overlap between running bot processes/instances.
TOTAL_SHARDS count must be equal for all instances and must reflect the total shards used across all instances
combined.
Note
This section is required only if you have multiple instances of the bot running, like in Example 3 of Sharding.
When you run multiple instances/process, the JDA in each process thinks that it has the sole responsibility of handling Discord's API rate limits because the processes aren't aware of each other's existence. This means, without some sort of communication or synchronization between the instances, you may exceed the rate limits pretty early.
It is possible to synchronize Discord's rate limits across multiple instances/processes by using an external proxy such as the Twilight HTTP Proxy. This proxy acts as a shared HTTP gateway that coordinates Discord API rate limits across multiple bot instances.
This however, requires disabling the default rate limiter in JDA because the proxy will handle them globally.
It is also worth noting that this feature is largely untested in PaperTrail. Read more about this in the Limitations section.
To use the pre-built Docker images from the container registry, run one of the following commands:
$ docker run -itd -e DISCORD_TOKEN="my token" -p 3000:80 ghcr.io/twilight-rs/http-proxy
# Or with metrics enabled
$ docker run -itd -e DISCORD_TOKEN="my token" -p 3000:80 ghcr.io/twilight-rs/http-proxy:metrics
This will set the discord token to "my token" and map the bound port to port 3000 on the host machine.
Add the following environment variable to your bot:
| Variable | Description | Default Value | Optional |
|---|---|---|---|
TWILIGHT_HTTP_PROXY_URL |
Base URL for the HTTP proxy that will receive Discord API requests instead of discord.com (Example: http://localhost:3000) | Blank | Yes |
When configured, all Discord API requests made by the bot will be routed through the proxy.
Twilight HTTP Proxy has its own global rate limiting feature and recommends clients to disable their per-instance rate limit checks. That's because requests from all bot instances are centrally managed and throttled by the proxy rather than by each client individually.
For PaperTrail, this would mean replacing JDA's default SequentialRestRateLimiter,
which is an implementation of the RestRateLimiter, with a custom no-op implementation.
Such an implementation would effectively bypass JDA’s local rate-limit checks and defer all rate limiting to the proxy.
At the moment, PaperTrail does not provide such an implementation.
This means that if you use a proxy for your bot clusters, you are effectively getting throttled at the proxy-level, as well as the instance-level. While this should not create functional conflicts, it may lead to under-utilization of the rate limits provided by Discord and can reduce the overall throughput of your bot cluster.
Note
Health Checks and Port are automatically configured in case of Self Host (Auto Configuration) mode, but require manual configuration for Self Host (Manual Configuration) mode.
Since v4, it is possible to get health information by probing any of the following health endpoints:
| Endpoint | Description |
|---|---|
/q/health |
Aggregated health status containing all registered checks. |
/q/health/live |
Liveness probe. Verifies that the bot process is healthy and that all shards are operating normally. |
/q/health/ready |
Readiness probe. Verifies that all shards are fully connected to Discord and ready to receive events. |
/q/health/started |
Startup probe. Indicates whether the application has completed its startup sequence. |
The liveness check reports UP when all shards belonging to this instance are in one of the following states:
CONNECTEDATTEMPTING_TO_RECONNECTRECONNECT_QUEUEDWAITING_TO_RECONNECT
The readiness check reports UP only when every shard belonging to this instance is fully CONNECTED to Discord.
By, default PaperTrail runs on port 8080. If port 8080 is occupied by a different service, or you wish to
run the application on a different port, you can manually set the PORT environment variable. Same goes for
MANAGEMENT_PORT which will expose the health check endpoints.
| Variable | Description | Default Value | Optional |
|---|---|---|---|
PORT |
Port Number on which the instance of the bot will run | 8080 | Yes |
MANAGEMENT_PORT |
Port for Health Check Interface | 9000 | Yes |
Caution
Native builds are experimental
Since v4.1.3 it is possible to create native builds of the bot. Native builds are recommended
when you are hosting the bot in a very resource constrained environment,
and you need the bot to have faster startup times and low memory consumption.
Native builds have a larger and resource incentive build time compared to standard JVM builds.
Please note that native builds are experimental and I will try my best to improve support for it in upcoming versions.
You may come across errors which require you to initialize classes during build time or missing reflection config during runtime. If you run across such errors, create an Issue in GitHub along with the build or runtime logs.
This project is licensed under the AGPLv3 license.
No AI or LLM agents have been used to generate any part of the project's source code. This policy applies to all existing source code and future code contributions.
After two years of development and manual testing, the application has reached a fairly stable and maintainable state. To preserve code quality, maintainability, format, and stability, AI-generated source code is not accepted for inclusion in this repository and the repositories related to the application.
Limited use of AI for non-code tasks, such as commit message generation, spelling correction, or documentation proofreading, may be permitted at the maintainer's discretion. Such usage does not constitute authorship of the project's source code.
If you face any problems during self-hosting or have a question that needs to be answered, please feel free to open an issue in the Issues tab. I will try my best to respond as soon as I can.