A self-hosted Discord bot that greets new members: assigns a role on join, posts a custom welcome card, and can route a different role depending on the invite link someone used. Built after ProBot β the hosted bot most servers relied on for this β went down.
- Autorole on join β assign one or more roles automatically when someone joins.
- Welcome card β the new member's avatar and username are composited onto a banner image you upload per server, then posted to a welcome channel.
- Role by invite link β map specific invite codes to specific roles (e.g. a partner's invite grants a "Partner" role automatically).
- Anti-raid guard β accounts younger than a configurable age are held in a pending-approval queue instead of being auto-roled, so a burst of freshly created accounts doesn't walk straight into your server's roles.
- Web dashboard β switch between every server you manage, configure all of the above, and approve/deny pending joins, all from a browser.
- Slash commands β
/doorman-statusand/doorman-pending, both read-only and restricted to members with Manage Server, for a quick check without opening the dashboard.
You run your own copy, with your own bot token. There's no hosted service, no account to create with a third party, and your server's data (members, invites, uploaded banners) never leaves your own database.
Discord Gateway ββ
ββ> apps/bot (discord.js) ββ
Discord REST ββββββ ββ> PostgreSQL (packages/database)
β
Browser (OAuth login) β> apps/web (Next.js) ββ
A single pnpm monorepo, one Docker image run as two processes (bot, web) plus
Postgres β see compose.yaml.
git clone https://github.com/PrimeBuild-pc/Doorman.git
cd Doorman
./install.shThe installer walks you through the one thing it can't do for you β creating the
Discord application β then writes .env and starts everything with Docker Compose.
- Discord Developer Portal β New Application.
- Bot tab β enable the Server Members Intent toggle (required to receive join events) β Reset Token and copy it.
- OAuth2 tab β copy the Client Secret β under Redirects, add
<your PUBLIC_URL>/api/auth/callback. - OAuth2 β URL Generator β scopes
bot+applications.commands; bot permissions: View Channels, Send Messages, Attach Files, Manage Roles, Manage Guild. Use the generated URL to invite the bot to your server. - Run
./install.shand paste the Application ID, Client Secret, and Bot Token when asked. - Open the dashboard at your
PUBLIC_URL, log in with Discord, pick your server, set a default role, upload a banner, and you're done.
pnpm install
pnpm build # compiles packages/shared and packages/database first β apps/bot
# and apps/web resolve both from their built dist/ output
pnpm --filter @doorman/database exec prisma db push # needs DATABASE_URL set
pnpm dev:bot # apps/bot with hot reload
pnpm dev:web # apps/web (Next.js dev server)
pnpm typecheck && pnpm lint && pnpm test- Uploaded banners are stored on a local Docker volume, not a third-party bucket β
back up the
uploadsvolume yourself if that matters to you. - The anti-raid guard is a simple account-age gate, not a full anti-raid suite β it catches the common "mass-created alt accounts" pattern, not a coordinated raid using older accounts.
- One bot, one server family: like D-View, this is meant to be self-hosted per Discord community, not run as a public multi-tenant service.
MIT β see LICENSE.