RE:NODE

Valheim Discord Connector: webhooks, joins and deaths

By RE:NODE Team
11 min read


Discord Connector, by nwesterhausen, is the usual way to get a Valheim server talking to Discord. It is a BepInEx plugin that runs on the dedicated server only, and it posts to a Discord webhook when the server starts, saves and stops, when players join, leave, die, shout or ping the map, and when a random raid begins. Players install nothing, so it works on crossplay servers with Xbox players. Setup is three steps: install BepInEx and the mod on the server, create a webhook in Discord, paste the webhook URL into the generated config and restart. Then spend five minutes on the two defaults most people should change - player coordinates in messages, and mentions - before your group finds out the hard way why they matter.

It is one-way. Discord Connector sends messages from the game to Discord; it does not carry Discord chat back into the game, and it does not let you run commands from Discord.

What Discord Connector does, and what it does not#

The mod hooks into server events and turns each into a webhook message. The current set of events, from the mod's documentation:

GroupEvents
Server lifecycleserverLaunch, serverStart, serverStop, serverShutdown, serverSave
WorldnewDayNumber, eventStart, eventPaused, eventResumed, eventStop
PlayersplayerJoin, playerLeave, playerShout, playerPing, playerDeath
Player firstsplayerFirstJoin, playerFirstLeave, playerFirstShout, playerFirstPing, playerFirstDeath
LeaderboardsactivePlayers, leaderboard1 to leaderboard5

Those names matter later, when you route events to different channels. Beyond the messages it also keeps a small database of player activity, which drives leaderboards such as most deaths or most time online, and it can announce "firsts" - a player's first death on the server, say.

What it is not:

  • Not a chat bridge. Messages go from Valheim to Discord only. Nothing typed in Discord reaches the game.
  • Not a bot. It uses webhooks, so there is no bot account, no slash commands and no remote administration. For that, see Discord bots for game server admin.
  • Not a client mod. It never needs to be on players' machines, and it does not appear in version checks. Adding it does not affect who can join.

That last point makes it one of the safest mods to run. It changes nothing about gameplay, so it cannot desync the world or kick anyone for a version mismatch. If the plugin breaks after a game update, the worst case is that the server will not start until you remove it, which is why you keep a note of exactly what is installed.

Before you start: BepInEx on the server#

Discord Connector is a BepInEx plugin, so the server needs the BepInExPack for Valheim first. On a native Linux install that means unpacking the pack into the server's root folder - you get a BepInEx directory, doorstop_libs and a start_server_bepinex.sh script that becomes the start command. On Docker with the lloesche/valheim-server image, set BEPINEX=true. On a panel, either use a BepInEx variant of the game if your host offers one, or upload the pack through the file manager and change the start command. Valheim mods with BepInEx on a server covers all three.

Start the server once with BepInEx alone and check the log. You should see BepInEx's own banner and the line saying how many plugins it loaded. If BepInEx is not running, nothing after this step will work, and the error will look like the mod's fault when it is not.

Installing the mod#

  1. Download Discord Connector from Thunderstore (the package is nwesterhausen-DiscordConnector). If your group uses r2modman, you can install it into a profile and copy the files from there, but on the server you only need the files.
  2. Stop the server.
  3. Open the zip. Copy the contents of its plugins folder into BepInEx/plugins/ on the server. Some versions ship more than one .dll - copy all of them, they belong together.
  4. Start the server, let it load fully, then stop it again cleanly.

On the first start the mod creates its configuration. Since version 2.1.0 it uses a folder of its own rather than one file:

code
BepInEx/config/games.nwest.valheim.discordconnector/  discordconnector.cfg               main settings, webhooks  discordconnector-messages.cfg      the text of each message  discordconnector-toggles.cfg       which messages and details are on  discordconnector-variables.cfg     custom variables for messages  discordconnector-leaderBoards.cfg  leaderboard definitions  config-debug.json                  a dump of the config, webhooks redacted  records.db                         player activity database

In BepInEx/LogOutput.log there should be a loading line for the plugin with its version, something like Loading [DiscordConnector 3.1.0]. If the folder was not created, the plugin did not load - see the troubleshooting section.

Creating the webhook in Discord#

A webhook is a URL that lets anything holding it post into one channel. You need Manage Webhooks permission on the Discord server.

  1. In Discord, open the settings of the channel the messages should go to.
  2. Go to Integrations, then Webhooks, then New Webhook.
  3. Give it a name and, if you like, an avatar - the mod can override both.
  4. Copy the webhook URL.

Create a separate webhook for each channel you want messages in. A common setup is one public channel for player activity and one admin-only channel for server lifecycle messages. Discord webhooks for server status covers webhooks in more detail, including rate limits.

The main config file#

Open discordconnector.cfg. BepInEx config files are plain text with a comment above each setting describing it and its default. Values are not quoted. The settings that matter on day one:

discordconnector.cfg (relevant lines)
Webhook URL = https://discord.com/api/webhooks/REPLACE/MEWebhook Events = ALLWebhook Username Override = ValheimSecondary Webhook URL =Secondary Webhook Events = ALLSend Positions with Messages = falseAllow Mentions for @here and @everyone = falseAllow Role Mentions = falseAllow User Mentions = falseIgnored Players =Collect Player Stats = trueAnnounce Player Firsts = true

Edit the values in place and keep the section headers and comments the file already has. The full set of keys, with defaults:

KeyDefaultWhat it does
Webhook URLemptyThe main webhook. Nothing is sent until this is set
Webhook EventsALLWhich events go to the main webhook
Secondary Webhook URLemptyAn optional second webhook
Secondary Webhook EventsALLWhich events go to the second webhook
Webhook Username OverrideemptyName shown on messages
Webhook Avatar OverrideemptyImage URL for the avatar
Use fancier discord messagesfalseUses embeds, mainly for position details
Send Positions with MessagestrueAdds coordinates to messages
Collect Player StatstrueRecords activity in records.db
Announce Player FirststruePosts a player's first join, death and so on
Ignored PlayersemptyNames to leave out, separated by ;
Ignored Players (Regex)emptyA .NET regular expression for names to leave out
Allow Mentions for @here and @everyonefalseLets messages ping everyone
Allow Role MentionstrueLets messages ping roles
Allow User MentionstrueLets messages ping users

Key names and defaults have changed between major versions of the mod. If your file differs from this table, your file is right for your version - the comments above each setting are the documentation that matches it. Restart the server after editing so the new values are read.

Routing events to different channels#

Webhook Events takes either ALL or a list of event names separated by semicolons. Besides the individual names in the first table, there are shorthands: serverLifecycle (launch, start, stop, shutdown), eventLifecycle (raid start, pause, resume, stop), playerAll, playerFirstAll and leaderboardsAll.

A sensible split for a group server:

discordconnector.cfg (two channels)
# #valheim - what players care aboutWebhook URL = https://discord.com/api/webhooks/1111/aaaaWebhook Events = playerAll;playerFirstAll;eventLifecycle;leaderboardsAll# #server-admin - what admins care aboutSecondary Webhook URL = https://discord.com/api/webhooks/2222/bbbbSecondary Webhook Events = serverLifecycle;serverSave

Routing only decides where a message goes. Whether it is sent at all is decided by discordconnector-toggles.cfg, which has sections for messages, positions, stats and debug output. If you route serverSave to a channel and nothing appears, the save message is probably switched off in the toggles file. Save messages are noisy - one every save interval - so leaving them off, or sending them only to an admin channel, is usually right.

Writing your own messages#

discordconnector-messages.cfg holds the text for every event. The player messages default to plain lines:

discordconnector-messages.cfg (player messages)
Player Join Message = %PLAYER_NAME% has joined.Player Leave Message = %PLAYER_NAME% has left.Player Death Message = %PLAYER_NAME% has died.Player Ping Message = %PLAYER_NAME% pings the map.Player Shout Message = %PLAYER_NAME% shouts **%SHOUT%**.

Put several messages in one setting, separated by ;, and the mod picks one at random each time:

ini
Player Death Message = %PLAYER_NAME% has gone to Valhalla.;%PLAYER_NAME% died. Again.;Odin claims %PLAYER_NAME%.

Discord markdown works in messages, so **bold** is bold in Discord. The variables available:

VariableValue
%PLAYER_NAME%Character name
%PLAYER_ID%The player's platform ID (%PLAYER_STEAMID% is the older name)
%POS%The player's coordinates
%SHOUT%The shouted text, in shout messages only
%WORLD_NAME%The world, available once it has loaded
%NUM_PLAYERS%Players online
%DAY_NUMBER%The in-game day
%JOIN_CODE%The crossplay join code, blank without crossplay
%PUBLICIP%The server's public address
%TIMESTAMP%A Discord timestamp shown in each reader's time zone
%VAR1% to %VAR10%Your own values from discordconnector-variables.cfg

Two of those are worth a deliberate use. %JOIN_CODE% in the server start message solves the crossplay problem that the join code changes on every restart: the new code lands in Discord on its own. And the custom variables let you keep one piece of text - the server address, a rules link - in one place and reuse it across messages. Be aware that %PUBLICIP% is fetched from an outside service when the server launches, so it depends on the server being allowed outbound connections. Valheim crossplay and Xbox players covers how the join code works.

Privacy, mentions and leaderboards#

Two defaults deserve a second look on any server with more than a few trusted friends.

Positions. Send Positions with Messages defaults to true, so join, leave, death, shout and ping messages carry coordinates. On a private server among friends this is handy - a death message with coordinates is a free tombstone marker. On a PvP server, or any public server, it publishes where everyone's base is and where every player logs off. Switch it off globally, or use the positions section of the toggles file to keep it only for deaths.

Mentions. Role and user mentions are allowed by default, and the documentation is explicit that player input is not filtered. A shout containing a role mention can ping that role through the webhook. Turn off role and user mentions unless you need them, and if you do, use Specifically Allowed Role Mentions and Specifically Allowed User Mentions to list the exact IDs that may be mentioned. Keep @here and @everyone off.

Admins and bots. Ignored Players takes a list of names to leave out of messages, and Ignored Players (Regex) a pattern. Use it for admin characters you do not want announced, or for NPCs that some mods register as players.

The player database also stores platform IDs alongside names. That is fine for a leaderboard, but it is personal data; if your community has rules about data, Collect Player Stats = false turns it off.

Leaderboards

The leaderboards file defines up to five custom leaderboards plus an active-players board, each sent on a timer. Each one chooses a statistic - deaths, joins, time online and so on - a time range and how many entries to show. They read from records.db, so they need Collect Player Stats on. A weekly "most deaths" board is a reliable source of jokes for a group; a daily one gets ignored. Start with one and see whether anyone reads it.

How to discern players in Record Retrieval decides whether the board counts by platform ID, character name, or both. The default, PlayerId, merges all of a player's characters into one entry. Choose Name if each character should count separately.

Troubleshooting#

No config folder appeared. The plugin did not load. Check BepInEx/LogOutput.log for the plugin's loading line. If BepInEx itself is not in the log, the server is starting without it - check the start command. If BepInEx loads but the plugin errors, check that the plugin version supports the current game version, and that you copied every file from the zip's plugins folder.

Config exists but nothing reaches Discord. Check, in order: the webhook URL is complete and unquoted, the event is in Webhook Events, the message is enabled in the toggles file, and the server can make outbound HTTPS connections. Set Log Debug Messages = true, restart, and the log will say what the mod tried to send.

Messages stopped after a Valheim update. The plugin may need updating. Check its Thunderstore page and changelog. Mods that do not touch gameplay usually catch up quickly, but not always on the same day. What to do when a mod update breaks has the general routine.

Duplicate messages. Usually two copies of the plugin in BepInEx/plugins - one in a subfolder from an earlier install. Remove the old one.

Discord shows "rate limited" or drops messages. Too many events to one webhook in a short time, typically saves or pings on a busy server. Turn off the noisy ones or split them across webhooks. If you also want a record of every event, the server log already has one - see reading the Valheim server log.

FAQ#

Do players need to install Discord Connector?

No. It runs only on the dedicated server. Players connect with an unmodified game, including Xbox and Game Pass players on a crossplay server.

Can Discord Connector send Discord chat into the game?

No. It is one-way, from the game to Discord, through webhooks. A two-way bridge or remote commands need a different mod or a bot with its own account.

Where is the config file for Discord Connector?

In BepInEx/config/games.nwest.valheim.discordconnector/, created on the first start after installing the mod. The main file is discordconnector.cfg; messages, toggles, variables and leaderboards each have their own file next to it.

How do I post the crossplay join code to Discord?

Add %JOIN_CODE% to the server start message in discordconnector-messages.cfg. The code is filled in once the world has loaded, and because a new code is generated on every restart, the message keeps Discord up to date automatically.

Is it safe to leave positions on?

On a small private server, yes. On a public or PvP server, no: coordinates in join, leave and death messages show everyone where bases and players are. Turn Send Positions with Messages off or limit it to deaths.