


RCON Next provides a Source RCON endpoint for dedicated servers running BepInEx 5. It is designed for Valheim and emits a single rcon.dll plugin assembly targeting .NET Standard 2.0. The assembly includes a compatibility facade for plugins compiled against the earlier rcon integration API.
The implementation emphasizes protocol correctness, authenticated command execution, bounded resource use, and a small integration API for other BepInEx plugins.
Remove any existing implementation of rcon.dll, then install through a Thunderstore-compatible mod manager or extract the release ZIP into the game server directory. The archive places the plugin at BepInEx/plugins/RconNext/rcon.dll. For a DLL-only manual installation, copy rcon.dll anywhere below BepInEx/plugins.
Start the game server once so BepInEx creates:
BepInEx/config/com.github.ferrinius.rcon-next.cfg
For configuration before the first server start, copy the bundled sample configuration to that path and remove the .example suffix.
Set a private password, choose the listening port, and enable the endpoint:
[rcon-next]
enabled = true
port = 2458
password = replace-with-a-strong-password
The plugin will not listen when the password is ChangeMe, blank, or incompatible with Source RCON's printable-ASCII password format. Expose the selected TCP port only to networks that should reach it.
Add rcon.dll as a reference and declare the RCON Next plugin dependency:
using BepInEx;
using RconNext;
[BepInPlugin("org.example.server-health", "Server Health", "1.0.0")]
[BepInDependency(RconPlugin.PluginGuid, BepInDependency.DependencyFlags.HardDependency)]
public sealed class ServerHealthPlugin : BaseUnityPlugin
{
private RconPlugin? _rcon;
private void OnEnable()
{
_rcon = GetComponent<RconPlugin>();
_rcon?.RegisterCommand(this, "health", _ => "ok");
}
private void OnDisable()
{
_rcon?.UnregisterCommand(this, "health");
_rcon = null;
}
}
Class-based handlers remain available for compatibility:
public sealed class PlayerCountCommand : AbstractCommand
{
public override string onCommand(string[] args)
{
return "0";
}
}
// During plugin enable:
rcon.RegisterCommand<PlayerCountCommand>(this, "players");
UnRegisterCommand and the lowercase onCommand member are retained for existing integrations. New code should prefer UnregisterCommand; see COMPATIBILITY.md for the complete contract.
The same assembly also exposes the former rcon namespace, rcon.rcon plugin type, command classes, delegates, event, and plugin GUID. Existing plugins compiled against that API can therefore resolve rcon.dll and their hard BepInEx dependency without being rebuilt.
The compatibility facade delegates to RCON Next; it does not run a second listener. If nl.avii.plugins.rcon.cfg already exists and the new RCON Next configuration did not exist before startup, its [rcon] values are imported into the new configuration and used immediately. A pre-existing RCON Next configuration takes precedence.
RCON Next and the earlier rcon.dll implementation are replacements for one another and must not be installed together.
When no registered handler matches, RconPlugin.OnUnknownCommand receives the normalized command name and parsed arguments. This can be used to forward commands into another command system.
Authentication belongs to an individual TCP connection. Commands received before successful authentication are never dispatched. A failed login—including reauthentication after a successful login—revokes the session and closes the connection.
Default resource limits are deliberately finite:
| Resource | Limit |
|---|---|
| Active connections | 16 |
| Connections from one IP address | 4 |
| Source RCON body size | 4 096 bytes |
| Framing storage per connection | 8 200 bytes |
| Packets per connection per second | 30 |
| Time allowed to authenticate | 10 seconds |
| Authenticated idle time | 10 minutes |
| Socket send timeout | 5 seconds |
| Command response length | 65 536 characters |
Malformed frames, unsupported packet types, rate-limit violations, expired sessions, and oversized responses are rejected without unbounded buffering. These application limits complement rather than replace firewall rules and upstream protection against volumetric traffic.
Docker Compose and just are the only host-side build dependencies.
just test # NUnit compatibility, protocol, and security suite
just build # tests, then a clean release build
Both commands compile as an unprivileged UID/GID matching the invoking user. Source is mounted read-only and copied into an ephemeral container workspace. A successful build replaces artifacts/ with rcon.dll and its build metadata.
Build versions are derived from v-prefixed SemVer tags. An exact tag such as v1.2.3 produces plugin version 1.2.3; untagged commits receive a MinVer prerelease version. The legacy compatibility plugin remains version 1.0.5, and the assembly version remains 1.0.0.0 to preserve existing binary references.
Production sources share one project under src/RconNext:
src/RconNext/
├── BepInEx/ plugin lifecycle and public command API
└── Core/ Source RCON framing, sessions, and TCP server
The NUnit test project is in tests/RconNext.ProtocolTests.
Push a v-prefixed version tag to build and publish a release:
git tag v1.2.3
git push origin v1.2.3
The workflow runs the tests and release build, stages the BepInEx install layout, and creates one versioned ZIP containing the Thunderstore manifest. That exact archive is attached to the GitHub Release and uploaded to Thunderstore. The leading v is removed from the package version.
RCON Next is distributed under the ISC license. See LICENSE.