Sentinel Enforcer: The Full Description
(the Workshop page is the executive summary; this is the complete picture)
Sentinel Enforcer is a server-side DayZ mod that reports what happens on your server - sessions, combat, chat, items, vehicles, building, server health - into the dayz.fyi platform as structured, authenticated events. Players who join a server running it see nothing new; it adds no content, no UI, no client download (apart from the optional Sentinel Client item described under Optional add-ons). This page is written for the person who runs the server and wants to know exactly what the mod does, what it costs, what it hooks, and how to turn any part of it off.
If you only want to install it, the short version on the Workshop page is enough. If you are evaluating it for a community that asks hard questions about mods - read on.
What it captures
Everything below is captured on the server and sent to dayz.fyi. Batches are HMAC-signed by default; supported servers can opt out of signing bulk data as described below. Heartbeats always remain signed. Nothing is read from or sent to players' machines by the core mod or the server add-ons; the optional client item is the one disclosed exception (see About the client item).
| Category | What you get on the dashboard |
|---|---|
| Sessions | who connected and disconnected, and when |
| Combat | kills, deaths, hits and shots - with weapon, distance and hit zone where the engine provides them |
| Chat | in-game chat messages |
| Items | item pickups and hand/inventory interactions, by item type |
| Vehicles | who drove what, vehicle destruction and despawn |
| Building and raids | base parts placed, dismantled, damaged, destroyed; flags; code-lock access; base part positions |
| Server health | frame time, freezes, restart-cycle trends and the mod's own footprint, every 30 seconds |
| Server lifecycle | boots, the mod set you run, and a previous-session report (crashes, script errors) where your host allows it |
Anything the platform does not recognise is stored as an unknown event rather than dropped, so a newer mod never loses data to an older platform.
Optional anti-cheat signals. The mod can contribute observe-only inputs to the dashboard's review tools. It never acts on its own: verdicts, thresholds and review stay with your staff on the dashboard, and take-action (kick / message) is opt-in and human-initiated. The detection methods themselves are deliberately not documented on any public page - see the last section.
Inventory snapshots. The mod can record what a player was carrying, so a duped crate or a suspicious kill has evidence before the character is looted or dies. By default it records this only for people you are already investigating - anyone on your community's watchlist, plus anyone flagged on that server in the last two weeks - and your senior admins can ask for a player's current loadout on the spot. You control both from Settings -> Moderation -> Inventory snapshots: whether requests are allowed at all, and whether the logout record covers your watched players (the default), every player, or nobody. It is a read-only setting and a separate switch from take-action: it never kicks, messages or moves anything.
Optional add-ons
The core mod captures what vanilla DayZ exposes. Coverage for community mods ships as separate Workshop items so a server never sees an "addon X required" warning for a mod it does not run:
| Workshop add-on | Adds |
|---|---|
| Sentinel Enforcer - Expansion | DayZ-Expansion Market, Groups, Hardline, Quests events |
| Sentinel Enforcer - VPPAdminTools | VPP admin command logging |
| Sentinel Enforcer - CodeLock | Code Lock access logging |
| Sentinel Enforcer - BreachingCharge | breaching charge placed / detonated / defused |
| Sentinel Client | Optional client-side item (loaded with -mod=, so players must have it). Counts presses of a fixed set of keys commonly bound to cheat menus and reports the counts to your server as a lead for staff to check. See the paragraph below the table. |
Subscribe only to the ones matching the mods your server runs.
About the client item. Unlike everything else on this page, Sentinel Client runs on players' computers, which is why it is optional, separate, and disclosed on its own Workshop page. It watches exactly these keys: Insert, Home, End, Delete, F2, F3, F4, F5, F6, F7, F8, F9, F10, and F12 only while Shift is held. It reports how many times each was pressed, whether Shift, Ctrl or Alt was held, and whether a menu was open at the time, at most once every 5 seconds and only after one of those keys was pressed, plus one short hello per game session once your character is in the world, saying that the item is present, its version, and a fingerprint of the key list it watches (the server attaches the same player identity and position it attaches to every report). It does not read what you type (chat, names, passwords), does not read mouse input or movement, does not take screenshots, does not read files, and cannot block, kick or change anything. A press of a listed key is a lead to check, not an accusation: many of these keys are bound to emotes and admin tools. Turn the reports off per server from the dashboard (capture.input_keys, capture.client_hello) or for good with HookClientInput: false in the server's Sentinel config.json.
Installation
- Add the server on dayz.fyi: open your community page, hit Add
server, and copy the
sntl_v1...token it gives you. - Subscribe to the Workshop item on your server's Steam account.
- Copy
@SentinelEnforcer/from the Workshop folder into your server root. - Drop
keys/sentinel_enforcer.bikeyinto your server'skeys/directory. - Launch parameters:
-serverMod=@SentinelEnforcer. (Add-doLogs -adminLogif you also want DayZ's own admin log files - not required by Sentinel.) - Paste the token into
<server profile>/SentinelEnforcer/config.json'sBootstrapTokenfield, then start the server. It connects already linked to your account a minute or two after the server finishes booting - no claim code needed.
No Steam client on the host? Some setups can't do step 2 at all - a Linux box with no Steam installed, or a control panel that only accepts an uploaded zip. The same signed build is available as a direct download with SHA-256 checksums; unzip it into the server root and continue from step 4. Where you can use the Workshop, do: a subscription keeps your servers on the current build by itself, and a downloaded copy never updates.
Server already running the mod? Booting with no token configured is the fallback path: the mod
self-registers and writes a one-time claim code to
<server profile>/SentinelEnforcer/claim.txt (also printed in the server log). Paste the
clm_... code at dayz.fyi/claim and events start flowing. Both paths
end in the same place.
Tip - server name and map on the dashboard: set steamQueryPort in serverDZ.cfg (DayZ's
default is 27016) so the platform can query your server and fill in its real name and map. Without
it you set the name yourself under Edit settings. Multi-server box: give each instance its own port.
The mod's settings live in <server profile>/SentinelEnforcer/config.json (in mod terms,
$profile:SentinelEnforcer\config.json) - in your profile directory, not inside the mod - so
moving or re-declaring the mod never loses them.
What it costs your server
These are measured numbers, not estimates, taken on populated production servers and cross-checked against the engine's own frame-rate log:
- Total main-thread cost at 100 players: 0.2-0.6% of wall clock. Nearly all of it is the upload pipeline (serialising and signing batches); the mod's per-frame work is about 0.02% of a frame.
- Uploads are sliced across ticks in bounded pieces so a flush cannot stall the simulation; the in-memory event queue is bounded (10,000 events) and has not dropped an event in weeks of fleet telemetry.
- The mod measures its own footprint on every server and reports it alongside your server's frame health, so the numbers above are visible on your dashboard rather than taken on faith. If you want to understand what "server FPS" and frame time mean for players, start with how DayZ multiplayer actually works.
Bulk-data signing
Data signing can be expensive if your server sends a lot of data or your hardware has little headroom. Disabling bulk signing removes a layer of protection in exchange for less work being done by the server when sending data. The effect on server performance will vary.
Signing is required by default. To change it, open your server on the dashboard and go to
Settings → Sentinel → Bulk-data signing. This is a dashboard setting, not a config.json
option; you do not need to edit files or install another mod release.
Only the server owner, a site administrator, or a head of staff with the owner's delegation can see and use this control. It appears only after the server reports a supported boot running Enforcer 0.33.0 or newer with signed-heartbeat support. Updating the Workshop subscription alone is not enough: restart the server with the updated files first.
- Disable bulk-data signing asks you to confirm the tradeoff: less signing work on the server, with one less layer of protection against bulk data being altered in transit. Heartbeats remain signed, but do not verify the contents of unsigned bulk data.
- Enable bulk-data signing restores required signing.
The card shows your desired policy separately from the latest observed transport state. Saving a change does not mean it has taken effect: wait for the server's next control exchange and telemetry update. If optional signing is currently unavailable, the disable button is unavailable; restoring required signing remains possible.
Heartbeats and transport-control requests remain signed in either mode. This setting does not change the separate authentication used for configuration and diagnostic requests.
Every hook the mod owns - and how to switch it off
A DayZ mod works by attaching small pieces of code to engine events ("hooks"). This is what the mod is, so it should be fully visible. Three places carry the same list:
- Your server's script log, at every boot: one
[Sentinel] chain-link ...line per hook family stating what it is for, what it cannot do, and how to switch it off - so if you are ever investigating a problem and searching your log, the first-party answer is already there. - Your dashboard: the same list with each family's live on/off state.
- This table.
Every hook calls the original engine code and passes control through, with one declared
exception: the weapon guard (new in 0.27.0). The kind tells you what class of thing each
one is: counter means it adds one to a number and returns; observe means it reads or
reports and never alters an outcome; seam marks the single hook that touches shared state,
which is off by default; guard marks the single hook that may refuse a request instead of
passing it on.
The weapon guard, and what WeaponGuardMode does. It checks that a magazine attach, swap,
detach or chambering request refers to items the player asking for it can legitimately use. It
ships as "WeaponGuardMode": "observe": it reports and then runs the original game code, so
updating changes nothing about how legitimate reloading works. The only requests refused in
observe are three malformed shapes that would stop the server outright if passed on. The other
settings are yours alone - config.json only, nothing on the dashboard or anywhere remote can
change them:
off- the hook is a pure pass-through.observe(default) - report only.block- also refuses requests the game itself would fail on or reject a moment later. No legitimate client produces these on any mod stack, so this is the setting to use if you want the guard to act.block_strict- also refuses two checks that encode an assumption about normal play (reach, and items inside another live player). A mod that legitimately extends either would trip them, and a refused player sees their weapon out of step until their next reload. Run a week inobserveon your own mod stack first; if the same report shows up for many players at once, that is a mod conflict, not cheaters.
| what the mod hooks | what it is for | what it cannot do | how to switch it off | cost |
|---|---|---|---|---|
| frame stats (counter) | measures how long each server frame takes - the smoothness numbers on your dashboard | alter frame pacing, tick order, or any game logic; it reads the clock, updates a histogram, and returns | core (Enabled=false in config.json disables Sentinel entirely) | about 0.02% of a frame, every frame |
| mission lifecycle (observe) | starts Sentinel with the mission and notes player join, ready, respawn, leave and chat for the session record | block a login, change a spawn, or alter what the engine does with any event; it observes and passes through | core (Enabled=false in config.json disables Sentinel entirely) | negligible (runs only when the event happens) |
| player events (observe) | records hits, deaths, connections, vehicle seat changes and certain server-rejected requests for the kill feed and session history | change damage, deaths, or connection outcomes; every override calls the original and returns its result unchanged. The logout list is never taken from a dead player, reads the inventory without touching it, stops at 200 items, and can be switched off from your dashboard like any other capture type. It reaches no verdict about a shot either: the figures are read from the game's own settings and sent onward exactly as they are, and nothing in the mod decides that any of them is cheating | dashboard toggle | negligible (runs only when the event happens) |
| input seam (seam) | an optional, off-by-default capture of some item moves | alter the move itself; off by default, auto-disabled when a known conflicting mod is present, and the only hook that reads shared engine state | config.json HookInputSeam=false | nothing while off (the default) |
| inventory command (observe) | records server-rejected inventory actions for staff review | accept or reject an action; it reads the engine verdict after the engine has made it | config.json HookInventoryCommand=false | negligible (runs only when the event happens) |
| item moved (observe) | records completed item relocations (player, container, ground, vehicle) for the item history, and how far the player was standing from the container, vehicle or tent an item was pulled out of. With the full stream off it records only the long pulls into a player's own inventory, which is the pattern a reach cheat produces. It also keeps a list of storage containers lying on the ground (crates, chests, barrels; not backpacks or clothing, not base-building parts) and regularly checks whether any has changed position, recording the old and new position and which players were nearby. It also writes short custody summaries: one record per burst of a player taking items from or putting items into a container or vehicle, handing items to another player (including looting or filling a dead body), or picking items up from and dropping them on the ground, listing each item with its id and quantity | move, block, or alter items; it fires after the engine completed the move. It does not judge a distance either - the metres are sent as measured, with the size of the object they were measured to, and nothing in the mod treats any of them as too far. The container check only reads positions: it never moves a container back or stops it being moved, and it names nearby players without deciding that any of them moved it. The custody summaries only list what changed hands; a player moving items within their own inventory is not recorded, and nothing in them is judged | config.json HookItemMoved=false | a cached check per item move when armed; nothing measurable when not |
| ce sweep counter (counter) | counts Central Economy item visits per heartbeat - a world-size and server-health number, not player data | change loot spawning, despawn timers, or any economy decision; one counter increment, then the original runs | config.json HookCESweepCounter=false | one counter increment per loot-economy visit (about 0.03 ms per second on an idle Chernarus) |
| item density (observe) | maps roughly where the server's items are and whether they lie loose, sit in storage or are carried, by sampling a small share of the items the loot economy visits - a world-size picture, not player data | move, change or remove any item, or affect loot spawning or despawn; it reads where an item is and adds one to a count for that map square. No item names, player names or exact positions are recorded | config.json HookItemDensity=false | a position read on one in eight loot-economy visits, and one small report every five minutes |
| store save counter (counter) | counts how many items, vehicles and characters the server writes to its save files, and in which frames - a server-health number showing whether saving is what makes a frame slow, not player data | change what is saved, when, or anything inside the save; the original runs first, then one counter is incremented | config.json HookStoreSaveCounter=false | one counter increment each time something is written to the save files, and a three-number comparison per frame |
| activation counters (counter) | counts how often infected AI, wildlife and vehicle physics tick per second - server-health numbers, not player data | change AI behavior, animal behavior, or vehicle physics; one counter increment, then the original runs | config.json HookActivationCounters=false | one counter increment per AI / vehicle tick (about 0.1 ms per second at 100 active infected) |
| event rate counters (counter) | counts how often the server handles item moves, hits, deaths and remote calls - rate numbers used to size server load, with no detail about who or what; apart from the cargo check listed here it adds no new hooks, it only counts inside hooks listed under item_moved and player_events | change any of those outcomes; each is one counter increment and then the original runs, and the cargo check returns the engine's own answer unaltered | config.json HookEventRateCounters=false | one counter increment each time a counted event happens |
| entity census (counter) | counts how many items, players, infected, vehicles and triggers get created and destroyed - a world-size and churn number, not player data | prevent, delay, or alter any creation or destruction; it adds one counter increment to constructors and destructors that were already running | config.json HookEntityCensus=false | one counter increment when an entity is created or destroyed |
| structure sweep (observe) | records base part positions over time | move or alter structures; it checks positions periodically and reports | config.json HookStructureSweep=false | a short periodic position check of registered base parts |
| building events (observe) | records base parts placed, dismantled, damaged, destroyed and (opt-in) removed by the server's own cleanup, and flags destroyed, for base logs | change building rules, damage, or raid outcomes; it records what the engine already did | dashboard toggle | negligible (runs only when the event happens) |
| codelock (observe) | records code-lock access attempts for base security logs | change whether a lock opens or what the code is | dashboard toggle | negligible (runs only when the event happens) |
| weapon fire (observe) | records shots fired for combat analysis, and keeps a short note of each player's last few shots - the time, the gun and where they were standing - so that when a hit lands the server can say how long the round was in the air | alter ballistics, ammunition, or hit results. The note is small and temporary: at most sixteen shots per player, nothing older than three seconds is ever used, and a player's notes are discarded the moment they disconnect | dashboard toggle | negligible (runs only when the event happens) |
| pickup (observe) | records item pickups for the item history | block or alter a pickup; it fires after the pickup completed | dashboard toggle | negligible (runs only when the event happens) |
| magazine (observe) | records certain inventory-action anomalies for staff review | change the action outcome; it reads the engine result and passes it through | dashboard toggle | negligible (runs only when the event happens) |
| melee (observe) | notes each melee hit the server works out for a player: what was hit, how far away it was, with what, and whether it did any damage, for staff review | change a hit, its damage or its target; the game's own hit handling runs unchanged and the record is made from what it did | dashboard toggle | negligible (runs only when the event happens) |
| admin log (observe) | forwards the server admin-log lines so they also appear on the dashboard | suppress or alter admin-log lines; the engine still writes them exactly as before | dashboard toggle | negligible (runs only when the event happens) |
| freeze guard (observe) | measures how long the server actually stalled and records who was sending it what at that moment, so a server that keeps freezing can be explained instead of guessed at | read the contents of any remote call, block one, or change what the game does with it; it counts them. It cannot disconnect, ban, damage, or modify anyone - it takes no action at all | config.json HookFreezeGuard=false | negligible (runs only when the event happens) |
| client input (observe) | reads the counts of a fixed set of watched keys and a once-per-session hello that the optional Sentinel Client item sends from a player's own game client, so a player who presses keys commonly bound to cheat menus can be looked at | read typed text, chat, mouse or movement; see anything but short upper-case key tokens (it accepts only those; the published client item sends only the watched set); block or alter any remote call; attribute a report to anyone but the sender the engine identifies. It takes no action at all | config.json HookClientInput=false | negligible (runs only when the event happens) |
| weapon guard (guard) | checks that a weapon action the server was asked to run refers to a magazine and a destination the player asking for it can legitimately refer to, because a request that does not is a known way to crash a server. The second link only notes when a weapon request arrived and the condition of the magazine it names, after the original has run, so a report can say how the request reached the server | change how a legitimate weapon action behaves, or touch ammo, damage or durability. In its default setting it reports and then runs the original unchanged. Set to block in config.json by the owner, it refuses a weapon action the game itself would crash on or reject a moment later (a reference that is not a magazine, a bad muzzle index, a magazine the weapon's own rules reject, a detach of a magazine that is not attached) and hands the cleanup back to the game's own routine; the reach and other-player checks are still only reported, so a mod that legitimately allows either keeps working. Set to block_strict, it refuses those two as well. Three shapes are always refused whatever the setting, because passing them on would fail the server outright: a request with no player attached, a magazine-detach with no destination, and a request whose magazine is not actually a magazine | dashboard toggle | negligible (runs only when the event happens) |
| vehicle events (observe) | records vehicle destruction and despawn for vehicle history | change vehicle damage, despawn, or physics | dashboard toggle | negligible (runs only when the event happens) |
Owner switches (config.json, default on unless noted): HookActivationCounters,
HookCESweepCounter, HookItemDensity, HookStoreSaveCounter,
HookEventRateCounters, HookEntityCensus, HookFreezeGuard,
HookWeaponGuard, HookItemMoved, HookInventoryCommand, HookStructureSweep, and
HookInputSeam (an owner veto over a hook that is off by default anyway). Setting one to false
turns that family into a pure pass-through for the whole session and stops its fields from being
sent at all. A false in your config.json cannot be re-enabled from the dashboard - the switch
is yours. Enabled=false turns the whole mod off without uninstalling it.
Dashboard switches that ship off (new in 0.36.0). Three capture switches start off on every server and record nothing until you turn them on from your dashboard:
- Magazine detaches - the game's answer to each request to take a magazine out of a weapon: refused or accepted, and where the magazine went.
- Refused item moves - item moves and swaps the game itself refused, with the reason it gave. Leave this one off for now on servers running LBmaster Admin Tools.
- Melee hits - one record per melee hit the server works out for a player, as described in the melee row above.
Privacy and data flow
- Server-side only, unless you opt into the client item. The core mod and every add-on above except Sentinel Client run on the server, touch nothing on players' machines, and download nothing to clients. Servers that choose to require the client item change that for exactly the watched keys listed under "About the client item", and nothing else.
- Same identifiers vanilla already gives admins. Steam ID and DayZ ID - what the server's own admin log exposes. No extra personal information.
- Item types, not inventories. "Player picked up an SKS", never what a player owns.
- Authenticated by default. Batches are HMAC-SHA-256 signed with a per-server secret. If you explicitly allow unsigned bulk data, that data loses HMAC tamper protection; heartbeats and protected traffic remain signed. See Bulk-data signing above.
- Your data, your org. Events are stored under your organisation on dayz.fyi, where your staff access tiers decide who sees what.
Compatibility and coexistence
- DayZ 1.29, Windows and Linux servers - pure Enforce Script, no native DLL, identical on both.
- Validated against every DayZ game update before the Workshop item is refreshed (the validation badge in the dayz.fyi footer is written by that run).
- Vanilla vehicle classes: the vehicle-activity health counter hooks the eight vanilla car classes directly (count-only, always calls the original) because of how those classes are built. A future DayZ update that changes them can require a Sentinel hotfix; that is exactly what the per-update validation exists to catch, and the Workshop update is the fix.
- Conflicts: none known. The one hook that reads shared engine state is off by default and
switches itself off when a known conflicting mod is present. If you ever suspect an
interaction with another mod, flip the relevant family off in
config.json(you do not need to uninstall anything) and tell us which mod - that report is how the conflict list grows.
What this page deliberately does not document
The anti-cheat review tools on the dashboard use observations the mod can contribute. How those observations are interpreted - signals, thresholds, methods - is not described here or on any public page, for the same reason this site's cheating guide does not publish detection recipes: a public, machine-complete description is a gift to exactly the people it targets. What you get instead is the contract above: every hook is named, what it cannot do is stated, and every family can be switched off by you. Staff who need operating detail get it inside the platform, not from a page anyone can read.
Support
- Platform: dayz.fyi
- Discord: link in the dayz.fyi footer - bug reports and integration questions go there.
- Workshop: the item page carries the executive summary and links back here.