mirror of
https://github.com/nmasur/dotfiles
synced 2026-11-13 14:45:02 +00:00
Compare commits
9
Commits
744afbb2d8
..
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
75e7ddb104 | ||
|
|
0d96b8fbed | ||
|
|
314298134d | ||
|
|
a8dc2f0d62 | ||
|
|
7404d10533 | ||
|
|
9a458530d0 | ||
|
|
b3d9938f10 | ||
|
|
542e39a2aa | ||
|
|
c757493b35 |
No files matched your search
@@ -1,5 +1,18 @@
|
||||
# Changelog
|
||||
|
||||
## 2026-10-25: fix pgweb/mathesar postgresql.target dependency and refresh all DB collations
|
||||
|
||||
- **pgweb & mathesar**: Added `requires = [ "postgresql.target" ];` to `systemd.services.pgweb` (`platforms/nixos/modules/nmasur/presets/services/pgweb.nix`) and `"postgresql.target"` to `systemd.services.mathesar.requires` (`platforms/nixos/modules/nmasur/presets/services/mathesar/mathesar.nix`). Previously they only set `after = [ "postgresql.target" ]`, allowing `switch-to-configuration` to start `pgweb.service` before `postgresql.target` was queued and causing `pgweb` to fail with `connect: no such file or directory` on `/run/postgresql/.s.PGSQL.5432`.
|
||||
- **PostgreSQL collation version refresh**: Updated `systemd.services.postgresql-setup.preStart` (`platforms/nixos/modules/nmasur/presets/services/postgresql.nix`) to iterate over all databases with `datallowconn` in `pg_database` and run `ALTER DATABASE ... REFRESH COLLATION VERSION;` instead of only refreshing `template1` and `postgres`.
|
||||
|
||||
## 2026-10-24: fix build failures for NixOS swan
|
||||
|
||||
- **Nextcloud**: Upstream NixOS removed `services.nextcloud.config.adminpassFile` and `services.nextcloud.config.adminuser`. Removed `adminpassFile` from `services.nextcloud.config`, updated `services.prometheus.exporters.nextcloud` to reference `config.secrets.nextcloud.dest` directly as `passwordFile` and set `username = "root"`, and added ordering dependencies on `nextcloud-secret` for `prometheus-nextcloud-exporter.service`.
|
||||
- **Bazarr**: Replaced obsolete `services.bazarr.listenPort` with `services.bazarr.settings.general.port` in Caddy reverse proxy upstream (`arr.nix`) and Grafana dashboard matcher (`grafana.nix`).
|
||||
- **pyopenjtalk-plus**: Added `overlays/pyopenjtalk-plus.nix` disabling `test_run_njd_from_mecab_invalid_input_should_not_break_next_call`, which fails under Python 3.14 due to an exact string match assertion on the `TypeError` message ("Expected str, got int" vs expected "must be str").
|
||||
- **calibre**: Added `overlays/calibre.nix` setting `doInstallCheck = false`, bypassing upstream failure in `test_speech_dispatcher` caused by `speechd-minimal` omitting Python bindings in nixpkgs.
|
||||
|
||||
|
||||
## 2026-10-17: removed post-TUI lag tooling
|
||||
|
||||
- With the root cause fixed (starship notifications, below), removed the `lag-triage` module: `lag-triage`, `unlag`, `lag-sample`, `term-probe`, the PTY repro script, the flight recorder filter and the Ctrl-b `heal-autosuggest` binding. Also deleted its `power-user.nix` enable and `~/.local/state/lag-triage`.
|
||||
@@ -50,6 +63,21 @@
|
||||
|
||||
## 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**:
|
||||
- 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.
|
||||
|
||||
Generated
+48
-27
@@ -49,11 +49,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1786845137,
|
||||
"narHash": "sha256-oQFip+v0luP8NIxJzmiW4Wu8bILsbFWom5l0zonl8hQ=",
|
||||
"lastModified": 1793418699,
|
||||
"narHash": "sha256-+RpTlcdh9KqZ+ZiLkNSTvibQWm935EcIdBzRPCTFsrQ=",
|
||||
"owner": "lnl7",
|
||||
"repo": "nix-darwin",
|
||||
"rev": "4cff07de74b50e64bdd68cd4e722ab5b6b35ee48",
|
||||
"rev": "ff0e21a414d4547183396da1b44a66f2577b65e9",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -70,11 +70,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1789770686,
|
||||
"narHash": "sha256-uZkBR7yHdIKUFB5SZdfgh1qkGfI3XmYmI/lTiquxbck=",
|
||||
"lastModified": 1792526520,
|
||||
"narHash": "sha256-3hSJlv8mUVnZPMWK2+CM7a9O+nR6Z4mCh27NfLCmTPc=",
|
||||
"owner": "nix-community",
|
||||
"repo": "disko",
|
||||
"rev": "725ea35e410ad83be4931d1bff7e090eacaf3563",
|
||||
"rev": "cedd626e11b635470fa6f9fdb8ad79b0075dd7f9",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -234,11 +234,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1792098797,
|
||||
"narHash": "sha256-u4DIIZgznEGzByxXrxWCXK19VcMtTBmi/M9gZ7Jk9bM=",
|
||||
"lastModified": 1793979366,
|
||||
"narHash": "sha256-7OoWDsYO9teiPxl0QdlS5lYE20Pue8/5mpscSL32FUA=",
|
||||
"owner": "nix-community",
|
||||
"repo": "home-manager",
|
||||
"rev": "640725978b99076e18e069f6e7d2959124584f8f",
|
||||
"rev": "2c0c1f01521469cf0271180c453c79782d53c2f6",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -298,11 +298,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1791711434,
|
||||
"narHash": "sha256-LpIhxnuO0tYeZ4k7BbNMxsPs2zJpB4hWXO1jdhUuE7Q=",
|
||||
"lastModified": 1793543282,
|
||||
"narHash": "sha256-PHtGxKYM99f8WhGR5YD7iiCiwemKa2wUD4yVI2oALFg=",
|
||||
"owner": "nix-community",
|
||||
"repo": "nix-index-database",
|
||||
"rev": "9a2dd40780eeab8543aa97c59c26f11267025616",
|
||||
"rev": "cee0f879d338cf08f814210fa6c2b280594ade0a",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -401,11 +401,11 @@
|
||||
},
|
||||
"nixpkgs-stable": {
|
||||
"locked": {
|
||||
"lastModified": 1792030654,
|
||||
"narHash": "sha256-OaQwAtPMTjQiY2sT/2/62UbSPhzP/0aDnWzMm/NCiUw=",
|
||||
"lastModified": 1793865203,
|
||||
"narHash": "sha256-/cpdPHaySDIyCgZI6EWngiM6jK3YLUNzv1b7lTzy6Bk=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "26f4107e47e3ad0ffd0db220469ba83b6f6d96e8",
|
||||
"rev": "c56a87d8e41ce69bd2af57eb35dcc117a9dfca33",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -481,11 +481,11 @@
|
||||
},
|
||||
"nixpkgs_6": {
|
||||
"locked": {
|
||||
"lastModified": 1791956154,
|
||||
"narHash": "sha256-jBYGPi4udQ9uo4KQp9m2J0546nJVQitG15gvZSaVVAs=",
|
||||
"lastModified": 1793876309,
|
||||
"narHash": "sha256-Wojg9lIH/hDH91iDVH2/EPw8oDSpxjxhXONbU1yf4Zg=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "55bfb4d7437bd4e09ab7cba58a43bd68eb310044",
|
||||
"rev": "f9a75f41be3a74eab55d3a7679d34ad6cc0da977",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -519,11 +519,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1792249243,
|
||||
"narHash": "sha256-zDZMBwcbcj2ufGk9EGy+BnUnV3BT/NiYuNynGiQ0SqA=",
|
||||
"lastModified": 1794047569,
|
||||
"narHash": "sha256-q15JEuh1qY0tBZcKLH3o2erKR2ofC9uLD8b/HTyWuyI=",
|
||||
"owner": "nix-community",
|
||||
"repo": "nur",
|
||||
"rev": "c21b30ed2ab024497fcd0c26abb0757a3fd1d100",
|
||||
"rev": "739e65d0caedf0af153f34b8f20798d776afe3bd",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -547,6 +547,7 @@
|
||||
"nixpkgs-stable": "nixpkgs-stable",
|
||||
"nur": "nur",
|
||||
"rust-overlay": "rust-overlay",
|
||||
"steam-fetcher": "steam-fetcher",
|
||||
"wsl": "wsl",
|
||||
"zellij-switch": "zellij-switch",
|
||||
"zenyd-mpv-scripts": "zenyd-mpv-scripts"
|
||||
@@ -557,11 +558,11 @@
|
||||
"nixpkgs": "nixpkgs_7"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1792219666,
|
||||
"narHash": "sha256-RMO08tKD+hFIL5ryWi85VY4aHE5oIpdV1h4kVFctOkw=",
|
||||
"lastModified": 1794040562,
|
||||
"narHash": "sha256-7eEiezSku3lbZPUOXW8we1a7+xd5axkCQdyI3rzOKjo=",
|
||||
"owner": "oxalica",
|
||||
"repo": "rust-overlay",
|
||||
"rev": "a110337465cfb76e3806b81b9db3094c3e6e770a",
|
||||
"rev": "d3fe74269f2a6652437e21e78eb7e83be81f6982",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -570,6 +571,26 @@
|
||||
"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": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
@@ -689,11 +710,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1789164534,
|
||||
"narHash": "sha256-DoYGPM6QpnYBLWj9gGw6ZwAzIX+HrAVov1BoT+8Jixo=",
|
||||
"lastModified": 1792982269,
|
||||
"narHash": "sha256-5R5CFIKj06qTQevhg/rCFUSAMxfNgdn0oIBL57R7u0Y=",
|
||||
"owner": "nix-community",
|
||||
"repo": "NixOS-WSL",
|
||||
"rev": "72c92b11bb8289e6651c7fef29cc0a885fd6a255",
|
||||
"rev": "e45b24b7df093299072b13bf3144ed0ee340e769",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
||||
@@ -92,6 +92,12 @@
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
|
||||
# Steam depot fetcher
|
||||
steam-fetcher = {
|
||||
url = "github:nix-community/steam-fetcher";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
|
||||
# # Text editor
|
||||
# helix = {
|
||||
# url = "github:helix-editor/helix";
|
||||
@@ -166,6 +172,7 @@
|
||||
status = "status.${baseName}";
|
||||
stream = "stream.${baseName}";
|
||||
transmission = "transmission.${baseName}";
|
||||
valheim = "valheim.${baseName}";
|
||||
};
|
||||
|
||||
lib = import ./lib inputs;
|
||||
|
||||
@@ -67,6 +67,7 @@ lib
|
||||
inputs.nur.overlays.default
|
||||
inputs.nix2vim.overlay
|
||||
inputs.api.overlays.default
|
||||
inputs.steam-fetcher.overlay
|
||||
(final: prev: {
|
||||
zellij-switch = inputs.zellij-switch.packages.${prev.stdenv.hostPlatform.system}.default;
|
||||
})
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
# Calibre's installCheckPhase runs test_speech_dispatcher, which imports
|
||||
# `speechd.client.SSIPClient`. Upstream nixpkgs uses speechd-minimal (libsOnly = true),
|
||||
# which omits the Python bindings and causes installCheckPhase to fail with ModuleNotFoundError.
|
||||
_inputs: _final: prev: {
|
||||
calibre = prev.calibre.overrideAttrs (_old: {
|
||||
doInstallCheck = false;
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
# Upstream pyopenjtalk-plus has a test (test_run_njd_from_mecab_invalid_input_should_not_break_next_call)
|
||||
# that asserts the exact TypeError exception string "must be str", which changed to "Expected str, got int"
|
||||
# under Python 3.14 / Cython.
|
||||
_inputs: _final: prev: {
|
||||
pythonPackagesExtensions = prev.pythonPackagesExtensions ++ [
|
||||
(_pyfinal: pyprev: {
|
||||
pyopenjtalk-plus = pyprev.pyopenjtalk-plus.overridePythonAttrs (old: {
|
||||
disabledTests = (old.disabledTests or [ ]) ++ [
|
||||
"test_run_njd_from_mecab_invalid_input_should_not_break_next_call"
|
||||
];
|
||||
});
|
||||
})
|
||||
];
|
||||
}
|
||||
@@ -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";
|
||||
};
|
||||
}
|
||||
@@ -22,6 +22,7 @@ in
|
||||
extensions = [
|
||||
pkgs.nmasur.gh-collaborators
|
||||
pkgs.gh-dash
|
||||
pkgs.gh-actions-lock
|
||||
];
|
||||
};
|
||||
|
||||
|
||||
@@ -15,8 +15,6 @@ in
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
|
||||
home.packages = [ pkgs.jj-starship ];
|
||||
|
||||
programs.starship = {
|
||||
enable = true;
|
||||
enableFishIntegration = true;
|
||||
@@ -29,7 +27,9 @@ in
|
||||
"$git_branch"
|
||||
"$git_commit"
|
||||
"$git_status"
|
||||
"\${custom.jj}"
|
||||
"$jj_bookmark"
|
||||
"$jj_status"
|
||||
"$jj_change"
|
||||
"$hostname"
|
||||
"$cmd_duration"
|
||||
"$character"
|
||||
@@ -51,17 +51,6 @@ in
|
||||
show_notifications = false;
|
||||
format = "[$duration]($style) ";
|
||||
};
|
||||
custom = {
|
||||
jj = {
|
||||
when = "jj-starship detect";
|
||||
shell = [
|
||||
"jj-starship"
|
||||
"--no-jj-prefix"
|
||||
"--no-git-prefix"
|
||||
];
|
||||
format = "$output ";
|
||||
};
|
||||
};
|
||||
directory = {
|
||||
truncate_to_repo = true;
|
||||
truncation_length = 100;
|
||||
|
||||
@@ -106,6 +106,12 @@ in
|
||||
lidarr = {
|
||||
enable = true;
|
||||
};
|
||||
shelfmark = {
|
||||
enable = true;
|
||||
environment = {
|
||||
URL_BASE = "/shelfmark";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
# Allows shared group to read/write the sabnzbd directory
|
||||
@@ -161,6 +167,22 @@ in
|
||||
}
|
||||
];
|
||||
}
|
||||
{
|
||||
match = [
|
||||
{
|
||||
host = [ hostnames.download ];
|
||||
path = [ "/shelfmark*" ];
|
||||
}
|
||||
];
|
||||
handle = [
|
||||
{
|
||||
handler = "reverse_proxy";
|
||||
upstreams = [
|
||||
{ dial = "localhost:${builtins.toString config.services.shelfmark.environment.FLASK_PORT}"; }
|
||||
];
|
||||
}
|
||||
];
|
||||
}
|
||||
{
|
||||
match = [
|
||||
{
|
||||
@@ -203,7 +225,7 @@ in
|
||||
upstreams = [
|
||||
{
|
||||
# Bazarr only dynamically sets the port, not the host
|
||||
dial = "localhost:${builtins.toString config.services.bazarr.listenPort}";
|
||||
dial = "localhost:${builtins.toString config.services.bazarr.settings.general.port}";
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
@@ -837,7 +837,7 @@ in
|
||||
{
|
||||
matcher = {
|
||||
id = "byName";
|
||||
options = "localhost:${builtins.toString config.services.bazarr.listenPort}";
|
||||
options = "localhost:${builtins.toString config.services.bazarr.settings.general.port}";
|
||||
};
|
||||
properties = [
|
||||
{
|
||||
|
||||
@@ -30,6 +30,7 @@ in
|
||||
"postgresql.target"
|
||||
];
|
||||
requires = [
|
||||
"postgresql.target"
|
||||
"mathesar-secret.service"
|
||||
"mathesar-postgres-secret.service"
|
||||
];
|
||||
|
||||
@@ -25,7 +25,6 @@ in
|
||||
hostName = "localhost";
|
||||
maxUploadSize = "50G";
|
||||
config = {
|
||||
adminpassFile = config.secrets.nextcloud.dest;
|
||||
dbtype = "pgsql"; # Enables postgresql
|
||||
};
|
||||
settings = {
|
||||
@@ -209,8 +208,14 @@ in
|
||||
permissions = "0440";
|
||||
};
|
||||
systemd.services.nextcloud-secret = {
|
||||
requiredBy = [ "nextcloud-setup.service" ];
|
||||
before = [ "nextcloud-setup.service" ];
|
||||
requiredBy = [
|
||||
"nextcloud-setup.service"
|
||||
"prometheus-nextcloud-exporter.service"
|
||||
];
|
||||
before = [
|
||||
"nextcloud-setup.service"
|
||||
"prometheus-nextcloud-exporter.service"
|
||||
];
|
||||
};
|
||||
|
||||
secrets.nextcloud-oidc-secret = {
|
||||
@@ -249,9 +254,9 @@ in
|
||||
networking.hosts."127.0.0.1" = [ hostnames.content ];
|
||||
services.prometheus.exporters.nextcloud = {
|
||||
enable = true;
|
||||
username = config.services.nextcloud.config.adminuser;
|
||||
username = "root";
|
||||
url = "https://${hostnames.content}";
|
||||
passwordFile = config.services.nextcloud.config.adminpassFile;
|
||||
passwordFile = config.secrets.nextcloud.dest;
|
||||
};
|
||||
nmasur.presets.services.prometheus-exporters.scrapeTargets = [
|
||||
"127.0.0.1:${builtins.toString config.services.prometheus.exporters.nextcloud.port}"
|
||||
|
||||
@@ -28,6 +28,9 @@ in
|
||||
after = [
|
||||
"postgresql.target"
|
||||
];
|
||||
requires = [
|
||||
"postgresql.target"
|
||||
];
|
||||
# requires = [ "pgweb-secret.service" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
|
||||
@@ -45,8 +45,9 @@ in
|
||||
if ! systemctl is-active --quiet postgresql.service; then break; fi
|
||||
sleep 0.1
|
||||
done
|
||||
${config.services.postgresql.package}/bin/psql -d postgres -tAc 'ALTER DATABASE template1 REFRESH COLLATION VERSION;' || true
|
||||
${config.services.postgresql.package}/bin/psql -d postgres -tAc 'ALTER DATABASE postgres REFRESH COLLATION VERSION;' || true
|
||||
for db in $(${config.services.postgresql.package}/bin/psql -d postgres -tAc 'SELECT datname FROM pg_database WHERE datallowconn;'); do
|
||||
${config.services.postgresql.package}/bin/psql -d postgres -tAc "ALTER DATABASE \"$db\" REFRESH COLLATION VERSION;" || true
|
||||
done
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
thelounge.enable = lib.mkDefault true;
|
||||
uptime-kuma.enable = lib.mkDefault true;
|
||||
valheim.enable = lib.mkDefault false;
|
||||
vaultwarden.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