Mods, updates and server upgrades¶
Mods update automatically. Server builds never do.
Adding and removing mods¶
dzo mod add <workshop id | local name> --instance deerisle [--server]
dzo mod list [deerisle]
dzo instance mods deerisle list
dzo instance mods deerisle move <id> --before <other id>
dzo mod remove <workshop id> --instance deerisle
dzo mod add installs the mod first, and only then adds it to the instance’s
instance.yaml in the site repository (the file’s comments are kept; the
change is left uncommitted for you to commit). It takes effect at the next
restart.
Debugging a client mod you build yourself¶
Players download client mods from the Steam Workshop, so dzo only allows local mods as servermods. To test a client mod that is not on the Workshop yet (a mod of your own, or one that needs a test client), you can load a signed local mod on the clients as well. This is for debugging on a test server only, and dzo makes you say so:
dzo mod add mytest --instance debug --client --force
--client alone is refused with the reasons; --force confirms that you know them:
clients cannot download the mod. Every player has to install the same signed build by hand, as
@<name>in the game’s folder, and start the game with it (-mod=@<name>);the mod directory must carry
keys/<authority>.bikeyand, for every PBO,<pbo>.<authority>.bisignmade with that key (see thedayz-mod-pack.shof the dayz-dev tools, or armake2). dzo checks that the files are there and belong together, not the signature itself; a server withverifySignatureskicks a client whose PBOs do not match;the key goes into the server’s
keys/, so it accepts every player who has that mod. Anyone holding the private key can then join; never do this on a public server.
The entry in instance.yaml is {local: mytest, debug_client: true}; the mod is read like
any local mod (localmods/<name>/ or local_mods in site.yaml), passed to the server as
-mod=@mytest, and listed by dzo mod list as client (debug, local). dzo site
validate, dzo mod add and dzo instance apply print a warning for every such mod, so it
is not forgotten. To go back, dzo mod remove it.
Load order is the order of the ``mods`` list. dzo passes the mods to the
server in exactly that order (-mod= for client mods, -servermod= for
server mods) and does not reorder them or check dependencies. Mods often
provide the same content under different names, so a dependency declared by one
mod can be met by another with a different name, and dzo cannot tell. Put
dependencies before the mods that need them, as you would on the command line.
Reading config.bin (diagnostics only)¶
The commands below are for looking at a mod’s declared dependencies by hand. Nothing in dzo depends on them: they do not affect the load order and no start is refused because of them.
Mods ship their config as a rapified (binary) config.bin, usually inside
an LZSS-compressed PBO entry. dzo decodes both itself, so no extra tools are
needed: it looks for config.bin at the root of each addon PBO (falling back
to a plain config.cpp) and reads only the CfgPatches classes and their
requiredAddons. The diagnostic commands accept a PBO, a bare
config.bin or a config.cpp:
dzo mod cfgpatches @MyMod/addons/mymod.pbo
dzo mod deps @MyMod/addons/mymod.pbo --provides DZ_Data,DZ_Scripts --order
Corrupt or truncated files produce an error naming the problem rather than a
guess. The decoder has been checked against synthetic files only; report a mod
whose config.bin it cannot read.
Automatic mod updates¶
dzo-update-check.timer runs every hour. For each instance whose
check_interval is due, dzo asks Steam which mods changed, downloads them into
new generations while the servers keep running, and then acts on the instance’s
updates.policy:
autograceful restart with the
restart_announcecountdown, a snapshot, the switch to the new mod generations and a start.notifyrecord and notify only.
manualrecord only.
To avoid a restart for every single mod push, updates can be batched:
updates:
policy: auto # default; auto | notify | manual
check_interval: 1h # default; how often the check runs for this instance
window: ["06:00-10:00", "14:00-16:00"] # only restart in these windows
quiet_hours: ["18:00-24:00"] # never restart for updates here
min_restart_interval: 4h
batch_delay: 20m # wait for more updates after the first
apply_with_scheduled_restart: true # use a maintenance restart if one is near
max_delay: 12h # apply after this long, whatever window and quiet_hours say
restart_minute: 0 # restart at this minute of the hour, see below
restart_announce: {minutes: 12, lock: 5, kick: 2, text: "MOD UPDATE! Restart"} # the countdown, plus ways:
Every key is optional and unset by default except policy and check_interval. The block can be
set in instance.yaml or under defaults: in site.yaml; a key the instance sets replaces the
site’s. All keys are explained in Configuration.
All pending mod updates of an instance are applied in one restart.
Check by hand:
dzo update check # show what is pending
dzo update check --apply # download and apply according to the policies
Installing mods and server builds¶
Everything dzo downloads is stored as an immutable generation: a directory
that is never changed after it appears, so a running server never sees files
move under it. A new version is a new generation, and current is switched
only after the new one is complete and validated. Re-running a command never
touches an existing generation.
dzo product install dayz-stable # first download of the server build
dzo mod add 1559212036 --instance deerisle # install a mod and add it to the instance
dzo mod update [deerisle] # download the listed mods and new versions (alias: mod download)
dzo mod list [deerisle] # what is installed
Workshop mods are named by Steam’s time_updated (<time_updated> or, after
a forced refresh, <time_updated>-r<n>) and the server build by its Steam
build id. Steam downloads run one at a time: dzo holds a lock, and the Steam
session from dzo steam login must be valid (steam.account in
config.yaml names the account).
Steam’s public Web API, which dzo asks for a mod’s version, does not show every
Workshop item: unlisted or restricted ones are missing from it. dzo downloads such a mod with the
Steam account anyway and takes its version from steamcmd’s own manifest. Because the version is
only known after the download, dzo mod update downloads these mods again on each run; steamcmd
only fetches what changed, and an unchanged mod stays at its generation. If the account may not
download the mod either, the error says so.
A downloaded mod is checked before it becomes a generation: meta.cpp must be
there and every PBO under addons/ must parse. If a mod fails the check, the
other mods of the same run are still installed, and the command exits with an
error. Installing does not restart anything; running servers keep the
generation they were started with.
Local servermods ({local: <name>, server: true}) are imported the same
way, from localmods/<name>/ in the site repository, a host directory, or a
release archive (local_mods in site.yaml, see How an instance is resolved).
The generation is named after a sha256 over the mod’s files, so unchanged
content is never imported twice. Only regular files are accepted: a symlink is
an error, and archives with absolute paths, .., links or device files are
rejected. An archive is checked against its sha256 before it is unpacked. The
mod root is the directory holding addons/ (directly, or in a single
@<name> directory); a keys/ directory is ignored. Every PBO of a local
mod must carry a prefix header, because a PBO without one loads without an
error but none of its scripts run.
Broken or corrupted mod downloads¶
There is no rollback to an older mod version: if a correctly downloaded mod is broken, the mod needs a fix, or you remove it from the instance.
What dzo does offer is a forced re-download. Use it when a download is incomplete or damaged, or when Steam’s own cache serves a bad copy:
dzo mod refresh <id> [<id>…] [--instance deerisle] --force
dzo mod refresh --all --instance deerisle --force
This deletes steamcmd’s cached state for the mod, downloads it again even if
Steam reports no change, checks the result (meta.cpp present, every PBO
readable) and stores it as a new generation. Servers switch to it at their next
restart. --force is required, to make it clear that this
downloads regardless of Steam’s version. The web interface has the same action
per mod.
As a last resort, dzo steam reset-cache wipes steamcmd’s working directory
after confirmation. The next download fills it again.
Server upgrades (manual only)¶
dzo checks for new server builds but never downloads or applies one on its own. A new DayZ version often needs a wipe, mod updates or config changes, so you decide when and how each server moves.
When a new build is available you get a Discord message, a warning from
dzo check remote --updates, and a note in dzo status. Then:
Download the build. Running servers are not affected, and neither is any restart: an instance stays on the build it was deployed with (it is pinned in
runtime/build) until you upgrade it:dzo product update dayz-stable
Prepare what the new version needs: mod updates, new mods, config changes in the site repository, and whether to wipe.
Look at the result before switching:
dzo instance upgrade deerisle --build <buildid> --dry-run
This shows the render plan for the new build.
Switch the instance:
dzo instance upgrade deerisle --build <buildid> [--wipe]
The instance is announced (
--nowskips the countdown), stopped, snapshotted, optionally wiped (after adestructivesnapshot and a confirmation,--yesanswers it), pinned to the new build, rendered and started. The mods’requiredAddonsare checked against the new build first; a missing dependency stops the upgrade. If the unit cannot be switched, the instance stays on its old build. Upgrade each instance when it is ready; nothing forces all servers of a product to move at once.
dzo product update <product> --force validates and re-copies the current
build, the server-side equivalent of dzo mod refresh.
Steam login¶
Downloads use the session created by dzo steam login. The password is not
stored by default. When Steam ends the session:
downloads pause (nothing fails), and running servers are not affected;
Discord,
/metrics(dzo_steam_session_valid 0) anddzo check remote --steamreport it;after
dzo steam login(on the host or in the web interface) paused jobs resume automatically.
dzo never retries a failed password or code automatically, so it cannot lock the account. The hourly check also tests the session, so an expired login is noticed before an update needs it.
The update engine¶
dzo-update-check.timer runs dzo update check --apply hourly. For every
instance whose check_interval is due it refreshes the mods, then compares
what the running unit uses with the cache. A difference is a pending update.
auto: inside the update window (and outsidequiet_hours), afterbatch_delayand respectingmin_restart_interval, the instance is restarted in one announced cycle: countdown, lock, kick, stop, snapshot, new unit, start.max_delayforces the update. A scheduled restart that is due soon is used instead ifapply_with_scheduled_restartis set.notify: the admins are told once per set of pending updates.manual: the update is only recorded (dzo update status).
A running instance keeps its unit until it is restarted, so dzo units sync
never changes a server under players; --deploy <name> writes the new
generations at once. A new server build is only reported, never applied
automatically. While Steam wants a login nothing is downloaded or restarted.
dzo restart <name> does the same cycle by hand; --cancel ends a running
countdown and unlocks the server. dzo update gc removes generations nobody
uses any more.
Mods and the experimental server¶
There are no experimental workshop mods. Both products use the stable workshop
(workshop_app_id: 221100), so an experimental instance installs its mods from
the same workshop items as a stable one and shares their cache generations.
Running DayZ Expansion on 1.30¶
DayZ Expansion Experimental 1.9.74 is the release to test under DayZ Experimental 1.30. Its authors give two requirements:
Use CF-Test instead of CF, and COT-Test instead of COT if you use COT. These are separate workshop items: put their ids in the
modslist of the experimental instance in place of the stable ones. A stable instance keeps the normal CF and COT.The profiles folder has to be inside the server executable’s folder. Vanilla 1.30 has a
FindFilebug: it ignores$profile:and searches the server folder instead, so a mod does not find its files when the profiles folder is somewhere else. A symlink or a bind mount into the server folder is fine.
dzo already satisfies the second point for every instance. Everything
a mod resolves through a placeholder lies below the server folder (/dayz in the container):
the instance’s profiles/ is mounted at /dayz/profiles ($profile:), the live mission at
/dayz/mpmissions ($mission:) and the persistence at /dayz/storage ($storage:). The server
starts with -profiles=/dayz/profiles, -config=/dayz/profiles/serverDZ.cfg,
-BEpath=/dayz/profiles/battleye and -storage=/dayz/storage; the engine reduces an absolute
-profiles= to its last component and looks it up in the server folder, which is where the mount is.
Nothing has to be configured. Check it on a running instance:
dzo exec <name> ls -d /dayz/profiles
dzo exec <name> sh -c 'tr "\0" " " < /proc/1/cmdline'