mirror of
https://github.com/nmasur/dotfiles
synced 2026-10-24 04:49:55 +00:00
feat(services): add valheim server module and preset
This commit is contained in:
@@ -50,6 +50,21 @@
|
|||||||
|
|
||||||
## 2026-09-29
|
## 2026-09-29
|
||||||
|
|
||||||
|
- **Added Valheim dedicated server package, service, and preset**:
|
||||||
|
- Added `steam-fetcher` (`github:nix-community/steam-fetcher`) flake input with `inputs.nixpkgs.follows = "nixpkgs"`.
|
||||||
|
- Added `inputs.steam-fetcher.overlay` to system overlays in `lib/default.nix`.
|
||||||
|
- Added `pkgs/valheim-server/package.nix` wrapping the Valheim dedicated server with modern `buildFHSEnv`, updated to latest release 1.0.16 (Steam depot `896661`, manifest `1285123405092214913`), with graceful fallback for non-x86_64-linux platforms.
|
||||||
|
- Added `overlays/valheim.nix` exposing `valheim-server`, `valheim-server-unwrapped`, and `fetchValheimThunderstoreMod` for compatibility.
|
||||||
|
- Added NixOS service module `platforms/nixos/modules/services/valheim.nix` defining `services.valheim`:
|
||||||
|
- Manages dedicated user/group `valheim` and systemd service `valheim.service`.
|
||||||
|
- Supports runtime decryption/loading of server password via `passwordFile` (avoiding plaintext secrets in the Nix store) as well as fallback `password` string option.
|
||||||
|
- Configures firewall rules for Valheim UDP ports (`port`, `port + 1`, `port + 2`).
|
||||||
|
- Configures admin, permitted, and banned Steam ID list files.
|
||||||
|
- Added preset module `platforms/nixos/modules/nmasur/presets/services/valheim/valheim.nix` with options for `nmasur.presets.services.valheim.enable`:
|
||||||
|
- Wires up `secrets.valheim-password` with encrypted secret file `valheim-password.age` and sets `systemd.services.valheim-password-secret` dependency before `valheim.service`.
|
||||||
|
- Adds `valheim = "valheim.masu.rs"` hostname to `flake.nix` and configures `nmasur.presets.services.cloudflare.noProxyDomains = [ hostnames.valheim ]` for DNS-only UDP routing.
|
||||||
|
- Adds `valheim.enable = lib.mkDefault false;` under `services` in `platforms/nixos/modules/nmasur/profiles/communications.nix`.
|
||||||
|
|
||||||
- **Separated Restic backup repositories per host**:
|
- **Separated Restic backup repositories per host**:
|
||||||
- Updated `services.restic.backups.default.repository` in `platforms/nixos/modules/nmasur/presets/services/restic/restic.nix` to append `/${config.networking.hostName}`, isolating backups by host in S3 (e.g., `.../restic/flame` and `.../restic/swan`).
|
- Updated `services.restic.backups.default.repository` in `platforms/nixos/modules/nmasur/presets/services/restic/restic.nix` to append `/${config.networking.hostName}`, isolating backups by host in S3 (e.g., `.../restic/flame` and `.../restic/swan`).
|
||||||
- Enabled `services.restic.backups.default.initialize = true` to automatically initialize the repository in S3 if it does not already exist.
|
- Enabled `services.restic.backups.default.initialize = true` to automatically initialize the repository in S3 if it does not already exist.
|
||||||
|
|||||||
Generated
+21
@@ -547,6 +547,7 @@
|
|||||||
"nixpkgs-stable": "nixpkgs-stable",
|
"nixpkgs-stable": "nixpkgs-stable",
|
||||||
"nur": "nur",
|
"nur": "nur",
|
||||||
"rust-overlay": "rust-overlay",
|
"rust-overlay": "rust-overlay",
|
||||||
|
"steam-fetcher": "steam-fetcher",
|
||||||
"wsl": "wsl",
|
"wsl": "wsl",
|
||||||
"zellij-switch": "zellij-switch",
|
"zellij-switch": "zellij-switch",
|
||||||
"zenyd-mpv-scripts": "zenyd-mpv-scripts"
|
"zenyd-mpv-scripts": "zenyd-mpv-scripts"
|
||||||
@@ -570,6 +571,26 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"steam-fetcher": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1758622040,
|
||||||
|
"narHash": "sha256-BRUZZoQDCD1qByJjHm4YKipQlB2PburWLG9Iaggr8XQ=",
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "steam-fetcher",
|
||||||
|
"rev": "ab5e3a0828b4b179feb548c57be584ce812956a8",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "steam-fetcher",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"systems": {
|
"systems": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1681028828,
|
"lastModified": 1681028828,
|
||||||
|
|||||||
@@ -92,6 +92,12 @@
|
|||||||
inputs.nixpkgs.follows = "nixpkgs";
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# Steam depot fetcher
|
||||||
|
steam-fetcher = {
|
||||||
|
url = "github:nix-community/steam-fetcher";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
};
|
||||||
|
|
||||||
# # Text editor
|
# # Text editor
|
||||||
# helix = {
|
# helix = {
|
||||||
# url = "github:helix-editor/helix";
|
# url = "github:helix-editor/helix";
|
||||||
@@ -166,6 +172,7 @@
|
|||||||
status = "status.${baseName}";
|
status = "status.${baseName}";
|
||||||
stream = "stream.${baseName}";
|
stream = "stream.${baseName}";
|
||||||
transmission = "transmission.${baseName}";
|
transmission = "transmission.${baseName}";
|
||||||
|
valheim = "valheim.${baseName}";
|
||||||
};
|
};
|
||||||
|
|
||||||
lib = import ./lib inputs;
|
lib = import ./lib inputs;
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ lib
|
|||||||
inputs.nur.overlays.default
|
inputs.nur.overlays.default
|
||||||
inputs.nix2vim.overlay
|
inputs.nix2vim.overlay
|
||||||
inputs.api.overlays.default
|
inputs.api.overlays.default
|
||||||
|
inputs.steam-fetcher.overlay
|
||||||
(final: prev: {
|
(final: prev: {
|
||||||
zellij-switch = inputs.zellij-switch.packages.${prev.stdenv.hostPlatform.system}.default;
|
zellij-switch = inputs.zellij-switch.packages.${prev.stdenv.hostPlatform.system}.default;
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
_inputs: final: prev:
|
||||||
|
|
||||||
|
{
|
||||||
|
fetchValheimThunderstoreMod =
|
||||||
|
{
|
||||||
|
owner,
|
||||||
|
name,
|
||||||
|
version,
|
||||||
|
hash,
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
depString = "${owner}-${name}";
|
||||||
|
in
|
||||||
|
prev.fetchzip {
|
||||||
|
inherit version hash;
|
||||||
|
name = "valheim-thunderstore-${depString}";
|
||||||
|
url = "https://thunderstore.io/package/download/${owner}/${name}/${version}/";
|
||||||
|
extension = "zip";
|
||||||
|
stripRoot = false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// prev.lib.optionalAttrs (prev.stdenv.hostPlatform.isLinux && prev.stdenv.hostPlatform.isx86_64) {
|
||||||
|
valheim-server = final.nmasur.valheim-server;
|
||||||
|
valheim-server-unwrapped = final.nmasur.valheim-server.unwrapped;
|
||||||
|
}
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
{
|
||||||
|
lib,
|
||||||
|
stdenv,
|
||||||
|
fetchSteam,
|
||||||
|
buildFHSEnv,
|
||||||
|
writeScript,
|
||||||
|
steamworks-sdk-redist,
|
||||||
|
zlib,
|
||||||
|
pulseaudio,
|
||||||
|
}:
|
||||||
|
|
||||||
|
if !stdenv.hostPlatform.isLinux || !stdenv.hostPlatform.isx86_64 then
|
||||||
|
null
|
||||||
|
else
|
||||||
|
let
|
||||||
|
valheim-server-unwrapped = stdenv.mkDerivation (finalAttrs: {
|
||||||
|
pname = "valheim-server-unwrapped";
|
||||||
|
version = "1.0.16";
|
||||||
|
|
||||||
|
src = fetchSteam {
|
||||||
|
name = "valheim-server";
|
||||||
|
appId = "896660";
|
||||||
|
depotId = "896661";
|
||||||
|
manifestId = "1285123405092214913";
|
||||||
|
hash = "sha256-AH9yU0YW0RpgkD9VSGFLj+qIXk3UlvrAgIu9fy/D+N8=";
|
||||||
|
};
|
||||||
|
|
||||||
|
dontBuild = true;
|
||||||
|
dontConfigure = true;
|
||||||
|
dontFixup = true;
|
||||||
|
|
||||||
|
installPhase = ''
|
||||||
|
runHook preInstall
|
||||||
|
|
||||||
|
mkdir -p $out
|
||||||
|
shopt -s nullglob
|
||||||
|
cp -r *.so *.debug valheim_server.x86_64 valheim_server_Data $out
|
||||||
|
chmod +x $out/valheim_server.x86_64
|
||||||
|
|
||||||
|
runHook postInstall
|
||||||
|
'';
|
||||||
|
|
||||||
|
meta = with lib; {
|
||||||
|
description = "Valheim dedicated server (unwrapped)";
|
||||||
|
homepage = "https://steamdb.info/app/896660/";
|
||||||
|
changelog = "https://store.steampowered.com/news/app/892970?updates=true";
|
||||||
|
sourceProvenance = with sourceTypes; [
|
||||||
|
binaryBytecode
|
||||||
|
binaryNativeCode
|
||||||
|
];
|
||||||
|
license = licenses.unfree;
|
||||||
|
platforms = [ "x86_64-linux" ];
|
||||||
|
};
|
||||||
|
});
|
||||||
|
in
|
||||||
|
buildFHSEnv {
|
||||||
|
name = "valheim-server";
|
||||||
|
pname = "valheim-server";
|
||||||
|
version = valheim-server-unwrapped.version;
|
||||||
|
|
||||||
|
runScript = writeScript "valheim-server-wrapper" ''
|
||||||
|
export LD_LIBRARY_PATH=${steamworks-sdk-redist}/lib:$LD_LIBRARY_PATH
|
||||||
|
export SteamAppId=892970
|
||||||
|
exec ${valheim-server-unwrapped}/valheim_server.x86_64 "$@"
|
||||||
|
'';
|
||||||
|
|
||||||
|
targetPkgs = pkgs: [
|
||||||
|
valheim-server-unwrapped
|
||||||
|
steamworks-sdk-redist
|
||||||
|
zlib
|
||||||
|
pulseaudio
|
||||||
|
];
|
||||||
|
|
||||||
|
passthru = {
|
||||||
|
unwrapped = valheim-server-unwrapped;
|
||||||
|
};
|
||||||
|
|
||||||
|
meta = valheim-server-unwrapped.meta // {
|
||||||
|
description = "Valheim dedicated server";
|
||||||
|
mainProgram = "valheim-server";
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
-----BEGIN AGE ENCRYPTED FILE-----
|
||||||
|
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IE1nSGFPdyA5V29j
|
||||||
|
dWc3Rmd2T3hHdkNlSE1nejVKdGY0UkUxM2U4eStQWEk5Z2pLOXlVCkExWWhzMzZZ
|
||||||
|
Yk5uWVY2anc3TTJTNkdVd0pRcmx6bGhkRWtHZlh6Yk93bGMKLT4gc3NoLWVkMjU1
|
||||||
|
MTkgWXlTVU1RIHhzallQU211VzduSkVHWVMzblRDcnY0L1VLMENoWi9RSkhaL0dS
|
||||||
|
a1Q2MjAKM1ZHcENURld0Ry9iUjVGRUd3RHA3Q29oQW8vYlN1SW1pNTdVOE5LSDRu
|
||||||
|
MAotPiBzc2gtZWQyNTUxOSBuanZYNUEgMi9IVU5rWXp3UHVZYWxFWE5mN0lHRlJY
|
||||||
|
V0dNSWh2YVRya1o5US9nSURSZwpXSHFhdTBOVExxSlhsYlRnWTR4Y1ZURWlCK2pG
|
||||||
|
OTdQdFNXUHoraWF5bW1VCi0+IHNzaC1lZDI1NTE5IENxSU9VQSBESmZuM25IYjNx
|
||||||
|
L3BDWmh6ZDFLdDVvMlY2Vzlra0t5WHZMbkUxOTlJMWlnCjZNcmdoZ2o1c1ZkSW02
|
||||||
|
QTR0WTRDcWFIYkZpRzdJMHJ4aWhJYjVFRU9aUDQKLT4gc3NoLWVkMjU1MTkgejFP
|
||||||
|
Y1p3IGVZUnZUM2p3R1ROZk92MVNscHRTMytKd3EvZE5JT0orYmE3U1h0SERyV28K
|
||||||
|
SXNIa0FMTHJ6dE5lVW85Q0N2N2F5QU1EU3crc1diTmM0SXVkQ0xlY3lpYwotLS0g
|
||||||
|
Y1ZxeE8wSkVpRllTT29QZTQ3L25ReGZ6WEMzSnZvSGJQaUNNV2J4ZzNzYwp3Ll3z
|
||||||
|
WxwIP3+BEVkWO52W77uZVfS9it6ecqvcFmEQK0PCzrKsTkm5Xlw3mAp42kXeIg==
|
||||||
|
-----END AGE ENCRYPTED FILE-----
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
{
|
||||||
|
config,
|
||||||
|
pkgs,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
|
||||||
|
let
|
||||||
|
inherit (config.nmasur.settings) hostnames;
|
||||||
|
cfg = config.nmasur.presets.services.valheim;
|
||||||
|
in
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
options.nmasur.presets.services.valheim = {
|
||||||
|
enable = lib.mkEnableOption "Valheim dedicated server";
|
||||||
|
|
||||||
|
serverName = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
default = "Midgard";
|
||||||
|
description = "Server name in server browser.";
|
||||||
|
};
|
||||||
|
|
||||||
|
worldName = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
default = "Midgard";
|
||||||
|
description = "World save name.";
|
||||||
|
};
|
||||||
|
|
||||||
|
port = lib.mkOption {
|
||||||
|
type = lib.types.port;
|
||||||
|
default = 2456;
|
||||||
|
description = "Server port.";
|
||||||
|
};
|
||||||
|
|
||||||
|
crossplay = lib.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = false;
|
||||||
|
description = "Enable cross-platform play.";
|
||||||
|
};
|
||||||
|
|
||||||
|
openFirewall = lib.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = true;
|
||||||
|
description = "Open UDP ports in firewall.";
|
||||||
|
};
|
||||||
|
|
||||||
|
passwordFile = lib.mkOption {
|
||||||
|
type = lib.types.path;
|
||||||
|
default = ./valheim-password.age;
|
||||||
|
description = "Age-encrypted secret file containing the server password.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
|
||||||
|
allowUnfreePackages = [
|
||||||
|
"valheim-server"
|
||||||
|
"steamworks-sdk-redist"
|
||||||
|
];
|
||||||
|
|
||||||
|
secrets.valheim-password = {
|
||||||
|
source = cfg.passwordFile;
|
||||||
|
dest = "${config.secretsDirectory}/valheim-password";
|
||||||
|
owner = "valheim";
|
||||||
|
group = "valheim";
|
||||||
|
permissions = "0400";
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services.valheim-password-secret = {
|
||||||
|
requiredBy = [ "valheim.service" ];
|
||||||
|
before = [ "valheim.service" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
services.valheim = {
|
||||||
|
enable = true;
|
||||||
|
serverName = cfg.serverName;
|
||||||
|
worldName = cfg.worldName;
|
||||||
|
port = cfg.port;
|
||||||
|
crossplay = cfg.crossplay;
|
||||||
|
openFirewall = cfg.openFirewall;
|
||||||
|
passwordFile = config.secrets.valheim-password.dest;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Configure Cloudflare DNS (no proxy for UDP game traffic)
|
||||||
|
nmasur.presets.services.cloudflare.noProxyDomains = [ hostnames.valheim ];
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -61,6 +61,7 @@ in
|
|||||||
stalwart.enable = lib.mkDefault true;
|
stalwart.enable = lib.mkDefault true;
|
||||||
thelounge.enable = lib.mkDefault true;
|
thelounge.enable = lib.mkDefault true;
|
||||||
uptime-kuma.enable = lib.mkDefault true;
|
uptime-kuma.enable = lib.mkDefault true;
|
||||||
|
valheim.enable = lib.mkDefault false;
|
||||||
vaultwarden.enable = lib.mkDefault true;
|
vaultwarden.enable = lib.mkDefault true;
|
||||||
victoriametrics.enable = lib.mkDefault true;
|
victoriametrics.enable = lib.mkDefault true;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,249 @@
|
|||||||
|
{
|
||||||
|
config,
|
||||||
|
pkgs,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
|
||||||
|
let
|
||||||
|
cfg = config.services.valheim;
|
||||||
|
|
||||||
|
startScript = pkgs.writeShellScriptBin "valheim-server-start" ''
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
CONFIG_DIR="${cfg.dataDir}/.config/unity3d/IronGate/Valheim"
|
||||||
|
mkdir -p "$CONFIG_DIR"
|
||||||
|
|
||||||
|
${lib.optionalString (cfg.adminList != [ ]) ''
|
||||||
|
cat << 'EOF' > "$CONFIG_DIR/adminlist.txt"
|
||||||
|
// List of Steam IDs for adminlist ONE per line
|
||||||
|
${lib.concatStringsSep "\n" cfg.adminList}
|
||||||
|
EOF
|
||||||
|
''}
|
||||||
|
|
||||||
|
${lib.optionalString (cfg.permittedList != [ ]) ''
|
||||||
|
cat << 'EOF' > "$CONFIG_DIR/permittedlist.txt"
|
||||||
|
// List of Steam IDs for permittedlist ONE per line
|
||||||
|
${lib.concatStringsSep "\n" cfg.permittedList}
|
||||||
|
EOF
|
||||||
|
''}
|
||||||
|
|
||||||
|
${lib.optionalString (cfg.bannedList != [ ]) ''
|
||||||
|
cat << 'EOF' > "$CONFIG_DIR/bannedlist.txt"
|
||||||
|
// List of Steam IDs for bannedlist ONE per line
|
||||||
|
${lib.concatStringsSep "\n" cfg.bannedList}
|
||||||
|
EOF
|
||||||
|
''}
|
||||||
|
|
||||||
|
${
|
||||||
|
if cfg.passwordFile != null then
|
||||||
|
''
|
||||||
|
if [ ! -f "${cfg.passwordFile}" ]; then
|
||||||
|
echo "Valheim password file '${cfg.passwordFile}' not found!" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
PASS="$(tr -d '\r\n' < '${cfg.passwordFile}')"
|
||||||
|
''
|
||||||
|
else
|
||||||
|
''
|
||||||
|
PASS="${cfg.password}"
|
||||||
|
''
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ ''${#PASS} -lt 5 ]; then
|
||||||
|
echo "Valheim server password must be at least 5 characters long!" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
ARGS=(
|
||||||
|
"-name" "${cfg.serverName}"
|
||||||
|
"-port" "${toString cfg.port}"
|
||||||
|
"-world" "${cfg.worldName}"
|
||||||
|
"-password" "$PASS"
|
||||||
|
"-public" "${if cfg.public then "1" else "0"}"
|
||||||
|
)
|
||||||
|
|
||||||
|
${lib.optionalString cfg.crossplay ''ARGS+=("-crossplay")''}
|
||||||
|
${lib.optionalString (cfg.saveDir != null) ''ARGS+=("-savedir" "${cfg.saveDir}")''}
|
||||||
|
${lib.concatMapStringsSep "\n" (arg: ''ARGS+=("${arg}")'') cfg.extraArgs}
|
||||||
|
|
||||||
|
exec ${cfg.package}/bin/valheim-server "''${ARGS[@]}"
|
||||||
|
'';
|
||||||
|
|
||||||
|
in
|
||||||
|
{
|
||||||
|
|
||||||
|
options.services.valheim = {
|
||||||
|
enable = lib.mkEnableOption "Valheim dedicated server";
|
||||||
|
|
||||||
|
package = lib.mkOption {
|
||||||
|
type = lib.types.package;
|
||||||
|
default = pkgs.valheim-server;
|
||||||
|
defaultText = lib.literalExpression "pkgs.valheim-server";
|
||||||
|
description = "The valheim-server package to use.";
|
||||||
|
};
|
||||||
|
|
||||||
|
serverName = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
default = "Valheim Server";
|
||||||
|
example = "Some cozy server";
|
||||||
|
description = "The name listed in the server browser.";
|
||||||
|
};
|
||||||
|
|
||||||
|
worldName = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
default = "Dedicated";
|
||||||
|
example = "Midgard";
|
||||||
|
description = ''
|
||||||
|
The name of the world file to use, without the extension.
|
||||||
|
If the world does not exist, the server will generate a world from a random seed.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
port = lib.mkOption {
|
||||||
|
type = lib.types.port;
|
||||||
|
default = 2456;
|
||||||
|
description = ''
|
||||||
|
The port on which to listen for incoming connections.
|
||||||
|
Ports (port + 1) and (port + 2) are used for Steam queries and routing.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
crossplay = lib.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = false;
|
||||||
|
description = "Whether to enable cross-platform play via PlayFab backend.";
|
||||||
|
};
|
||||||
|
|
||||||
|
public = lib.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = true;
|
||||||
|
description = "Whether to list the server in the public server browser.";
|
||||||
|
};
|
||||||
|
|
||||||
|
openFirewall = lib.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = false;
|
||||||
|
description = "Whether to open UDP ports in the firewall.";
|
||||||
|
};
|
||||||
|
|
||||||
|
password = lib.mkOption {
|
||||||
|
type = lib.types.nullOr lib.types.str;
|
||||||
|
default = null;
|
||||||
|
description = ''
|
||||||
|
The server password in plain text.
|
||||||
|
Prefer `passwordFile` to avoid storing passwords in the world-readable Nix store.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
passwordFile = lib.mkOption {
|
||||||
|
type = lib.types.nullOr (lib.types.either lib.types.str lib.types.path);
|
||||||
|
default = null;
|
||||||
|
description = "Path to file containing the server password.";
|
||||||
|
};
|
||||||
|
|
||||||
|
dataDir = lib.mkOption {
|
||||||
|
type = lib.types.path;
|
||||||
|
default = "/var/lib/valheim";
|
||||||
|
description = "Directory for valheim server data and state.";
|
||||||
|
};
|
||||||
|
|
||||||
|
saveDir = lib.mkOption {
|
||||||
|
type = lib.types.nullOr lib.types.path;
|
||||||
|
default = null;
|
||||||
|
description = "Directory where world saves are placed (-savedir). Defaults to Unity config dir in dataDir.";
|
||||||
|
};
|
||||||
|
|
||||||
|
adminList = lib.mkOption {
|
||||||
|
type = lib.types.listOf lib.types.str;
|
||||||
|
default = [ ];
|
||||||
|
example = [ "72057602627862526" ];
|
||||||
|
description = "List of Steam IDs to add to adminlist.txt.";
|
||||||
|
};
|
||||||
|
|
||||||
|
permittedList = lib.mkOption {
|
||||||
|
type = lib.types.listOf lib.types.str;
|
||||||
|
default = [ ];
|
||||||
|
example = [ "72057602627862526" ];
|
||||||
|
description = "List of Steam IDs to add to permittedlist.txt.";
|
||||||
|
};
|
||||||
|
|
||||||
|
bannedList = lib.mkOption {
|
||||||
|
type = lib.types.listOf lib.types.str;
|
||||||
|
default = [ ];
|
||||||
|
example = [ "72057602627862526" ];
|
||||||
|
description = "List of Steam IDs to add to bannedlist.txt.";
|
||||||
|
};
|
||||||
|
|
||||||
|
bepinexMods = lib.mkOption {
|
||||||
|
type = lib.types.listOf lib.types.package;
|
||||||
|
default = [ ];
|
||||||
|
description = "BepInEx mods to install.";
|
||||||
|
};
|
||||||
|
|
||||||
|
bepinexConfigs = lib.mkOption {
|
||||||
|
type = lib.types.listOf lib.types.path;
|
||||||
|
default = [ ];
|
||||||
|
description = "Config files for BepInEx mods.";
|
||||||
|
};
|
||||||
|
|
||||||
|
extraArgs = lib.mkOption {
|
||||||
|
type = lib.types.listOf lib.types.str;
|
||||||
|
default = [ ];
|
||||||
|
description = "Extra command line arguments to pass to valheim-server.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
|
||||||
|
users.users.valheim = {
|
||||||
|
isSystemUser = true;
|
||||||
|
group = "valheim";
|
||||||
|
home = cfg.dataDir;
|
||||||
|
createHome = true;
|
||||||
|
};
|
||||||
|
users.groups.valheim = { };
|
||||||
|
|
||||||
|
systemd.services.valheim = {
|
||||||
|
description = "Valheim dedicated server";
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
after = [ "network.target" ];
|
||||||
|
path = with pkgs; [ coreutils ];
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "exec";
|
||||||
|
User = "valheim";
|
||||||
|
Group = "valheim";
|
||||||
|
StateDirectory = "valheim";
|
||||||
|
WorkingDirectory = cfg.dataDir;
|
||||||
|
Restart = "on-failure";
|
||||||
|
RestartSec = "10s";
|
||||||
|
ExecStart = "${startScript}/bin/valheim-server-start";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
networking.firewall = lib.mkIf cfg.openFirewall {
|
||||||
|
allowedUDPPorts = [
|
||||||
|
cfg.port
|
||||||
|
(cfg.port + 1)
|
||||||
|
(cfg.port + 2)
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
assertions = [
|
||||||
|
{
|
||||||
|
assertion = cfg.serverName != "";
|
||||||
|
message = "services.valheim.serverName must not be empty.";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
assertion = cfg.worldName != "";
|
||||||
|
message = "services.valheim.worldName must not be empty.";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
assertion = (cfg.password != null && cfg.password != "") || cfg.passwordFile != null;
|
||||||
|
message = "services.valheim requires either services.valheim.password or services.valheim.passwordFile to be set.";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user