Compare commits
1 Commits
ca93ac478e
...
9e7469796d
| Author | SHA1 | Date | |
|---|---|---|---|
| 9e7469796d |
146
configs/nixos/guests/palworld.nix
Normal file
146
configs/nixos/guests/palworld.nix
Normal file
@@ -0,0 +1,146 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = config.guests.palworld;
|
||||
steamDir = "/data/steamcmd";
|
||||
installDir = "/data/server";
|
||||
stateDir = "/data/state";
|
||||
in
|
||||
{
|
||||
options.guests.palworld = {
|
||||
steamPath = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = null;
|
||||
example = "/srv/steamcmd";
|
||||
description = "Host path bind-mounted as SteamCMD's metadata directory.";
|
||||
};
|
||||
|
||||
installPath = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = null;
|
||||
example = "/srv/palworld/server";
|
||||
description = "Host path bind-mounted as Palworld's server install directory.";
|
||||
};
|
||||
|
||||
statePath = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = null;
|
||||
example = "/srv/palworld/state";
|
||||
description = "Host path bind-mounted as Palworld's durable state directory.";
|
||||
};
|
||||
|
||||
serverName = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "palworld";
|
||||
description = "Name shown for the Palworld server.";
|
||||
};
|
||||
|
||||
port = lib.mkOption {
|
||||
type = lib.types.port;
|
||||
default = 8211;
|
||||
description = "UDP port for the Palworld server.";
|
||||
};
|
||||
|
||||
publicIP = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = null;
|
||||
description = "Public IP address advertised by the Palworld server.";
|
||||
};
|
||||
|
||||
passwordSecret = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "services/game-servers/password";
|
||||
description = "SOPS secret name containing the Palworld server password.";
|
||||
};
|
||||
|
||||
adminPasswordSecret = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "services/game-servers/password";
|
||||
description = "SOPS secret name containing the Palworld admin password.";
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
assertions = [
|
||||
{
|
||||
assertion = cfg.steamPath != null;
|
||||
message = "guests.palworld.steamPath must point at the host directory that stores SteamCMD metadata.";
|
||||
}
|
||||
{
|
||||
assertion = cfg.installPath != null;
|
||||
message = "guests.palworld.installPath must point at the host directory that stores Palworld server files.";
|
||||
}
|
||||
{
|
||||
assertion = cfg.statePath != null;
|
||||
message = "guests.palworld.statePath must point at the host directory that stores Palworld durable state.";
|
||||
}
|
||||
];
|
||||
|
||||
guests.palworld = {
|
||||
interior.modules.services.games.palworld = {
|
||||
enable = true;
|
||||
inherit (cfg) serverName port publicIP;
|
||||
inherit steamDir installDir stateDir;
|
||||
passwordFile = "/run/secrets/${cfg.passwordSecret}";
|
||||
adminPasswordFile = "/run/secrets/${cfg.adminPasswordSecret}";
|
||||
};
|
||||
|
||||
mounts =
|
||||
{
|
||||
${steamDir} = {
|
||||
directory = cfg.steamPath;
|
||||
owner = config.registry."stable-uid".${config.networking.hostName}.steamcmd;
|
||||
group = "storage";
|
||||
mode = "0770";
|
||||
};
|
||||
${installDir} = {
|
||||
directory = cfg.installPath;
|
||||
owner = config.registry."stable-uid".${config.networking.hostName}.steamcmd;
|
||||
group = "storage";
|
||||
mode = "0770";
|
||||
};
|
||||
${stateDir} = {
|
||||
directory = cfg.statePath;
|
||||
owner = config.registry."stable-uid".${config.networking.hostName}.steamcmd;
|
||||
group = "storage";
|
||||
mode = "0770";
|
||||
};
|
||||
${"/run/secrets/${cfg.passwordSecret}"} = {
|
||||
file = config.sops.secrets.${cfg.passwordSecret}.path;
|
||||
readOnly = true;
|
||||
};
|
||||
}
|
||||
// lib.optionalAttrs (cfg.adminPasswordSecret != cfg.passwordSecret) {
|
||||
${"/run/secrets/${cfg.adminPasswordSecret}"} = {
|
||||
file = config.sops.secrets.${cfg.adminPasswordSecret}.path;
|
||||
readOnly = true;
|
||||
};
|
||||
};
|
||||
|
||||
limits = {
|
||||
memory = lib.mkDefault "8G";
|
||||
cpu = lib.mkDefault "400%";
|
||||
tasksMax = lib.mkDefault 2048;
|
||||
};
|
||||
};
|
||||
|
||||
sops.secrets =
|
||||
{
|
||||
${cfg.passwordSecret} = {
|
||||
owner = "root";
|
||||
group = "storage";
|
||||
mode = "0440";
|
||||
};
|
||||
}
|
||||
// lib.optionalAttrs (cfg.adminPasswordSecret != cfg.passwordSecret) {
|
||||
${cfg.adminPasswordSecret} = {
|
||||
owner = "root";
|
||||
group = "storage";
|
||||
mode = "0440";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -86,6 +86,25 @@
|
||||
};
|
||||
};
|
||||
|
||||
guests.palworld = {
|
||||
enable = true;
|
||||
vlan = 20;
|
||||
address = "10.23.20.250";
|
||||
steamPath = "/pikachu/data/steamcmd";
|
||||
installPath = "/pikachu/data/servers/palworld/tracion";
|
||||
statePath = "/pikachu/media/games/servers/palworld/tracion";
|
||||
serverName = "Tracion";
|
||||
adminPasswordSecret = "services/game-servers/admin/password";
|
||||
publicIP = config.guests.palworld.address;
|
||||
reverseProxy = {
|
||||
enable = true;
|
||||
route = {
|
||||
domain = "palworld.alexion.dev";
|
||||
udp.ports = [ config.guests.palworld.port ];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
guests.actualbudget = {
|
||||
enable = true;
|
||||
vlan = 20;
|
||||
|
||||
148
configs/nixos/modules/services/games/palworld.nix
Normal file
148
configs/nixos/modules/services/games/palworld.nix
Normal file
@@ -0,0 +1,148 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
{
|
||||
options.modules.services.games.palworld = {
|
||||
enable = lib.mkEnableOption "Palworld dedicated server";
|
||||
|
||||
steamDir = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
example = "/data/steamcmd";
|
||||
description = "Directory where SteamCMD stores metadata and cache files.";
|
||||
};
|
||||
|
||||
installDir = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
example = "/data/servers/palworld/tracion";
|
||||
description = "Directory where SteamCMD installs the Palworld server files.";
|
||||
};
|
||||
|
||||
stateDir = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
example = "/data/state/palworld/tracion";
|
||||
description = "Directory where Palworld stores durable server state.";
|
||||
};
|
||||
|
||||
serverName = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "palworld";
|
||||
description = "Name shown for the Palworld server.";
|
||||
};
|
||||
|
||||
port = lib.mkOption {
|
||||
type = lib.types.port;
|
||||
default = 8211;
|
||||
description = "UDP port for the Palworld server.";
|
||||
};
|
||||
|
||||
publicIP = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = null;
|
||||
description = "Public IP address advertised by the Palworld server.";
|
||||
};
|
||||
|
||||
maxPlayers = lib.mkOption {
|
||||
type = lib.types.ints.between 1 32;
|
||||
default = 32;
|
||||
description = "Maximum player count for the Palworld server.";
|
||||
};
|
||||
|
||||
publicLobby = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
description = "Advertise the server in Palworld's public lobby.";
|
||||
};
|
||||
|
||||
rcon = {
|
||||
enable = lib.mkEnableOption "Palworld RCON" // {
|
||||
default = true;
|
||||
};
|
||||
|
||||
port = lib.mkOption {
|
||||
type = lib.types.port;
|
||||
default = 25575;
|
||||
description = "TCP port for Palworld RCON.";
|
||||
};
|
||||
};
|
||||
|
||||
passwordFile = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
description = "Runtime file containing the Palworld server password.";
|
||||
};
|
||||
|
||||
adminPasswordFile = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
description = "Runtime file containing the Palworld admin password.";
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf config.modules.services.games.palworld.enable (
|
||||
let
|
||||
service = config.modules.services.games.palworld;
|
||||
savedDir = "${service.installDir}/Pal/Saved";
|
||||
startScript = pkgs.writeShellScript "palworld-start" ''
|
||||
set -eu
|
||||
|
||||
${pkgs.coreutils}/bin/install -d \
|
||||
-m 0770 \
|
||||
${lib.escapeShellArg service.stateDir} \
|
||||
${lib.escapeShellArg (builtins.dirOf savedDir)}
|
||||
|
||||
if [ -L ${lib.escapeShellArg savedDir} ]; then
|
||||
current_target="$(${pkgs.coreutils}/bin/readlink ${lib.escapeShellArg savedDir})"
|
||||
if [ "$current_target" != ${lib.escapeShellArg service.stateDir} ]; then
|
||||
${pkgs.coreutils}/bin/rm ${lib.escapeShellArg savedDir}
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -d ${lib.escapeShellArg savedDir} ] && [ ! -L ${lib.escapeShellArg savedDir} ]; then
|
||||
if ${pkgs.findutils}/bin/find ${lib.escapeShellArg service.stateDir} -mindepth 1 -maxdepth 1 | ${pkgs.gnugrep}/bin/grep -q .; then
|
||||
${pkgs.coreutils}/bin/rm -rf ${lib.escapeShellArg savedDir}
|
||||
else
|
||||
${pkgs.coreutils}/bin/cp -a ${lib.escapeShellArg savedDir}/. ${lib.escapeShellArg service.stateDir}/
|
||||
${pkgs.coreutils}/bin/rm -rf ${lib.escapeShellArg savedDir}
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -e ${lib.escapeShellArg savedDir} ]; then
|
||||
${pkgs.coreutils}/bin/ln -s ${lib.escapeShellArg service.stateDir} ${lib.escapeShellArg savedDir}
|
||||
fi
|
||||
|
||||
password="$(${pkgs.coreutils}/bin/tr -d '\n' < ${lib.escapeShellArg service.passwordFile})"
|
||||
admin_password="$(${pkgs.coreutils}/bin/tr -d '\n' < ${lib.escapeShellArg service.adminPasswordFile})"
|
||||
|
||||
exec ./PalServer.sh \
|
||||
"$@" \
|
||||
"-serverpassword=$password" \
|
||||
"-adminpassword=$admin_password"
|
||||
'';
|
||||
in
|
||||
{
|
||||
modules.services.steamcmd = {
|
||||
enable = true;
|
||||
inherit (service) steamDir installDir stateDir;
|
||||
serviceName = "palworld-${lib.toLower service.serverName}";
|
||||
appId = 2394010;
|
||||
executable = "${startScript}";
|
||||
arguments =
|
||||
[
|
||||
"-useperfthreads"
|
||||
"-NoAsyncLoadingThread"
|
||||
"-UseMultithreadForDS"
|
||||
"-port=${toString service.port}"
|
||||
"-publicport=${toString service.port}"
|
||||
"-servername=${service.serverName}"
|
||||
"-players=${toString service.maxPlayers}"
|
||||
]
|
||||
++ lib.optional service.publicLobby "-publiclobby"
|
||||
++ lib.optionals (service.publicIP != null) [ "-publicip=${service.publicIP}" ]
|
||||
++ lib.optional service.rcon.enable "-rcon";
|
||||
udpPorts = [ service.port ];
|
||||
tcpPorts = [ service.port ];
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -59,6 +59,12 @@
|
||||
default = [ ];
|
||||
description = "UDP ports opened for the game service.";
|
||||
};
|
||||
|
||||
tcpPorts = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.port;
|
||||
default = [ ];
|
||||
description = "TCP ports opened for the game service.";
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkMerge [
|
||||
@@ -159,6 +165,7 @@
|
||||
};
|
||||
|
||||
networking.firewall.allowedUDPPorts = service.udpPorts;
|
||||
networking.firewall.allowedTCPPorts = service.tcpPorts;
|
||||
}
|
||||
))
|
||||
];
|
||||
|
||||
@@ -18,13 +18,6 @@ or begin
|
||||
return 2
|
||||
end
|
||||
|
||||
set untracked_lines (git status --porcelain --untracked-files=normal | string match -r '^\?\? ')
|
||||
if test (count $untracked_lines) -gt 0
|
||||
echo "deploy-to: refusing to deploy untracked files" >&2
|
||||
echo "deploy-to: git add new files that Nix must see, or remove them" >&2
|
||||
return 1
|
||||
end
|
||||
|
||||
git fetch origin
|
||||
or return $status
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@ services:
|
||||
password: ENC[AES256_GCM,data:SSyo2l6tCjgjxIuCEREIxU+inw2WHtJJR0/IEKUqefFfuAdA5Nf+lH/jfPw=,iv:9225w1Yur3KL3dBr1ct1aPvDdVJ94O8q9qAUiRrj8Nc=,tag:qZgx4XieVq4BcxkTZc0KGQ==,type:str]
|
||||
game-servers:
|
||||
password: ENC[AES256_GCM,data:Wtq03MLRnc6/,iv:HhbiP8ZcltVGbCNDdP/gH5mCZXhVCTFv1DGzfrrgQG8=,tag:srsqcBQSD/HU8zFsuFimJQ==,type:str]
|
||||
admin:
|
||||
password: ENC[AES256_GCM,data:52jwSCfV,iv:MQf1VOHnGBf2yF+9SXk04FniAjghSaZe2Gn/xvAXU/0=,tag:SnrJFlHwOaM6vsNLBc84nw==,type:str]
|
||||
sops:
|
||||
age:
|
||||
- enc: |
|
||||
@@ -44,7 +46,7 @@ sops:
|
||||
28uWUpKzzgErq1aEbKNgh4cU5TH2RlAHjtzRC3ARUu9hlW6lnB4pSw==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
recipient: age1wf5s0n0tgt6ld2ysgu9dc67mj8ylwecgl4utzg7hqwy3kut9zyms7aglmh
|
||||
lastmodified: "2026-09-10T13:40:57Z"
|
||||
mac: ENC[AES256_GCM,data:3nu+ho3TNDnGE55LIaHqJxlMs1hWVK2wwiJiBIDH0jop9Wo/AgaUXzwXY1MwMXJHhGrkcjhwWWJdEgxX88NNFTc59b4kLtRqE3bfNXoQ3y3giyDMFyVE9YCNd4jyl+pLhpVSZA/+TKEIBpdZRwaXHrYSaLtysg/OdzXing0l3SM=,iv:C/vZ6X1HikuBn+pWTlPIfCfg5mtW2i4P6XLwN1VwF6k=,tag:UQl10fueTwCtXuirP5+C/g==,type:str]
|
||||
lastmodified: "2026-09-10T18:32:33Z"
|
||||
mac: ENC[AES256_GCM,data:g3xIylSvyn5Z0JBA8siFmMrZxoM3a3U5c+f9qFmb3zXDLF03/feCUlvG2jjB7P2N9phIGSIEOPk1dzZDBMwv6D2hK6MppupV+MIe9diIt0gGARIOJNphrxLDxMHtwcWg6Z20D6tbPl0ECtLI0K9GOtwvI0OXeyYzu5VgFaFlZHw=,iv:TAUVJRXFTKNVA0ORMD7x56WVGjG+zimj3iqEn7urh64=,tag:SeOOV9ZUY4x5Ns0A16F1uw==,type:str]
|
||||
unencrypted_suffix: _unencrypted
|
||||
version: 3.13.3
|
||||
|
||||
29
docs/.obsidian/workspace.json
vendored
29
docs/.obsidian/workspace.json
vendored
@@ -22,6 +22,26 @@
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "72e6501450a46859",
|
||||
"type": "tabs",
|
||||
"children": [
|
||||
{
|
||||
"id": "06bc3d52246b600b",
|
||||
"type": "leaf",
|
||||
"state": {
|
||||
"type": "markdown",
|
||||
"state": {
|
||||
"file": "00 INBOX/ai/steamcmd servers.md",
|
||||
"mode": "source",
|
||||
"source": true
|
||||
},
|
||||
"icon": "lucide-file",
|
||||
"title": "steamcmd servers"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"direction": "vertical"
|
||||
@@ -233,13 +253,16 @@
|
||||
},
|
||||
"active": "0c587e5452c16787",
|
||||
"lastOpenFiles": [
|
||||
"00 INBOX/how to setup a steamcmd server.md",
|
||||
"00 INBOX/ai/steamcmd servers.md",
|
||||
"03 wrk/ariadne.md",
|
||||
"00 INBOX/ai/ariadne-cli-skeleton.md",
|
||||
"00 INBOX/ai/ariadne-project-goals.md",
|
||||
"TODO.md",
|
||||
"00 INBOX/ai/dictionary-cli.md",
|
||||
"00 INBOX/ai/dictionary-skill.md",
|
||||
"03 wrk/falinks.md",
|
||||
"03 wrk/ariadne.md",
|
||||
"03 wrk/machoke.md",
|
||||
"TODO.md",
|
||||
"00 INBOX/home assistant agent integration.md",
|
||||
"02 notes/falinks public surfaces.md",
|
||||
"03 wrk/machoke.md~",
|
||||
@@ -261,8 +284,6 @@
|
||||
"00 INBOX/ai/hoopa design review findings.md",
|
||||
"00 INBOX/ai/hoopa follow up decisions.md",
|
||||
"01 sources/obsidian and ai were made for each other.md",
|
||||
"99 meta/technical writing.md",
|
||||
"99 meta/dictionary.md",
|
||||
"99 meta/Untitled",
|
||||
"03 wrk",
|
||||
"02 notes",
|
||||
|
||||
125
docs/00 INBOX/how to setup a steamcmd server.md
Normal file
125
docs/00 INBOX/how to setup a steamcmd server.md
Normal file
@@ -0,0 +1,125 @@
|
||||
---
|
||||
date-created: 2026-09-10 12:01
|
||||
---
|
||||
|
||||
# How to set up a `steamcmd` server
|
||||
|
||||
This note explains how to add a SteamCMD-managed game server to the NixOS configuration.
|
||||
|
||||
Use these existing files as examples:
|
||||
|
||||
- `configs/nixos/modules/services/steamcmd.nix`
|
||||
- `configs/nixos/modules/services/games/valheim.nix`
|
||||
- `configs/nixos/guests/valheim.nix`
|
||||
- `configs/nixos/hosts/pikachu/default.nix`
|
||||
|
||||
## Understand the layers
|
||||
|
||||
The shared `steamcmd` module installs and runs a dedicated server.
|
||||
It owns the low-level systemd service, update service, user, directories, and firewall ports.
|
||||
|
||||
A game module maps game-specific options onto `modules.services.steamcmd`.
|
||||
It hides Steam app IDs, executable names, launch arguments, and port calculations.
|
||||
|
||||
A guest module maps host-level storage, secrets, and resource limits onto the game module.
|
||||
It keeps host paths outside the guest's interior configuration.
|
||||
|
||||
A host enables the guest and supplies network placement, storage paths, and routing.
|
||||
|
||||
## Create the game module
|
||||
|
||||
1. Create `configs/nixos/modules/services/games/<game>.nix`.
|
||||
2. Add an option namespace at `modules.services.games.<game>`.
|
||||
3. Add an `enable` option with `lib.mkEnableOption`.
|
||||
4. Add options for game-specific settings.
|
||||
5. Add options for `steamDir`, `installDir`, and `stateDir`.
|
||||
6. Use `lib.mkIf config.modules.services.games.<game>.enable` for the module configuration.
|
||||
7. Set `modules.services.steamcmd.enable = true`.
|
||||
8. Pass `steamDir`, `installDir`, and `stateDir` to `modules.services.steamcmd`.
|
||||
9. Set `serviceName` to the game service name.
|
||||
10. Set `appId` to the Steam dedicated-server app ID.
|
||||
11. Set `executable` to the server executable or a generated wrapper script.
|
||||
12. Set `arguments` to the game launch arguments.
|
||||
13. Set `udpPorts` to every UDP port the server needs.
|
||||
14. Put secrets in runtime files instead of option values.
|
||||
15. Read secret files from a wrapper script when the server needs secret values.
|
||||
|
||||
Use `configs/nixos/modules/services/games/valheim.nix` as the main pattern.
|
||||
It wraps the executable because Valheim receives its password as a command-line argument.
|
||||
|
||||
## Create the guest module
|
||||
|
||||
1. Create `configs/nixos/guests/<game>.nix`.
|
||||
2. Add an option namespace at `guests.<game>`.
|
||||
3. Add host-path options for the SteamCMD metadata, install, and state directories.
|
||||
4. Give host-path options a `null` default.
|
||||
5. Add assertions that require each host path when the guest is enabled.
|
||||
6. Define guest-internal paths in a `let` block.
|
||||
7. Enable `guests.<game>.interior.modules.services.games.<game>`.
|
||||
8. Pass the guest-internal paths to the game module.
|
||||
9. Add mounts that bind host paths to the guest-internal paths.
|
||||
10. Set directory mount `owner`, `group`, and `mode` together.
|
||||
11. Mount secret files under `/run/secrets/...` when the game needs secrets.
|
||||
12. Declare matching `sops.secrets` entries for those secret files.
|
||||
13. Set conservative default resource limits under `guests.<game>.limits`.
|
||||
|
||||
Use `configs/nixos/guests/valheim.nix` as the main pattern.
|
||||
It mounts the password secret into the guest and passes only the runtime path inward.
|
||||
|
||||
## Enable the guest on a host
|
||||
|
||||
1. Open the target host file under `configs/nixos/hosts/<host>/default.nix`.
|
||||
2. Set `guests.<game>.enable = true`.
|
||||
3. Set `vlan` and `address` for the guest.
|
||||
4. Set host storage paths for SteamCMD metadata, server files, and state.
|
||||
5. Set game options such as server name and port.
|
||||
6. Enable reverse-proxy routing when the server needs external access.
|
||||
7. Route every game UDP port exposed by the guest.
|
||||
8. Add required secrets to the host's SOPS files.
|
||||
|
||||
Use the Valheim section in `configs/nixos/hosts/pikachu/default.nix` as the host-level pattern.
|
||||
|
||||
## Test the change
|
||||
|
||||
1. Stage new Nix files before evaluation.
|
||||
Flake evaluation ignores untracked files.
|
||||
|
||||
```console
|
||||
$ git add configs/nixos/modules/services/games/<game>.nix configs/nixos/guests/<game>.nix
|
||||
```
|
||||
|
||||
2. Build the target host configuration.
|
||||
|
||||
```console
|
||||
$ nixos-rebuild build --flake .#<host>
|
||||
```
|
||||
|
||||
3. Deploy the host when the build succeeds.
|
||||
|
||||
```console
|
||||
$ sudo nixos-rebuild switch --flake .#<host>
|
||||
```
|
||||
|
||||
4. Enter the guest from the host.
|
||||
|
||||
```console
|
||||
$ sudo machinectl shell <game>
|
||||
```
|
||||
|
||||
5. Check the update service inside the guest.
|
||||
|
||||
```console
|
||||
$ systemctl status steamcmd-<game>-update.service
|
||||
```
|
||||
|
||||
6. Check the game service inside the guest.
|
||||
|
||||
```console
|
||||
$ systemctl status <game>.service
|
||||
```
|
||||
|
||||
7. Inspect the logs when either service fails.
|
||||
|
||||
```console
|
||||
$ journalctl -u steamcmd-<game>-update.service -u <game>.service
|
||||
```
|
||||
55
docs/TODO.md
55
docs/TODO.md
@@ -45,7 +45,7 @@
|
||||
- subagents
|
||||
- test-driven-development
|
||||
|
||||
## pikachu proxmox -> nixos
|
||||
## pikachu + pichu proxmox -> nixos
|
||||
|
||||
- lidarr (requires raichu)
|
||||
- immich
|
||||
@@ -57,16 +57,60 @@
|
||||
- adguard
|
||||
- homepage
|
||||
|
||||
## raichu proxmox -> nixos
|
||||
- dwn torrent (vpn)
|
||||
- dwn usenet (vpn)
|
||||
- dwn-torrent-novpn
|
||||
- prowlarr
|
||||
- flaresolverr
|
||||
- radarr
|
||||
- sonarr
|
||||
- radarr-anime
|
||||
- sonarr-anime
|
||||
- configarr
|
||||
- lidarr
|
||||
- audiobookshelf
|
||||
- portainer
|
||||
- seerr
|
||||
- plex
|
||||
- pterodactyl
|
||||
- palworld old
|
||||
- project zomboid
|
||||
- minecraft
|
||||
- cobblemon
|
||||
|
||||
# learning
|
||||
- https://www.youtube.com/@EeroAlvar/videos
|
||||
- YouTube
|
||||
- EeroAlvar
|
||||
- https://www.youtube.com/watch?v=DzhLFiblPUk
|
||||
- https://www.youtube.com/watch?v=hQGAwD9vkLo
|
||||
- https://www.youtube.com/watch?v=hhtExS5UQBI
|
||||
- https://www.youtube.com/watch?v=Y1xO9OsCBC4
|
||||
- https://www.youtube.com/watch?v=DWWrLlM3gwQ
|
||||
- https://www.youtube.com/watch?v=yHL-gmkzC-4
|
||||
- https://www.youtube.com/watch?v=KRVYUkM16hE
|
||||
- https://www.youtube.com/watch?v=RxdvzenLcl4
|
||||
- https://www.youtube.com/watch?v=mdbpIpPSPwQ
|
||||
- https://www.youtube.com/watch?v=GHsq0klC_4g
|
||||
- https://www.youtube.com/watch?v=ciC6ffUqI8k
|
||||
- https://www.youtube.com/watch?v=gYxZt9Qe0fk
|
||||
- https://www.youtube.com/watch?v=0tqty8ltKDA
|
||||
- https://www.youtube.com/watch?v=kzcI5F4tGiU
|
||||
- https://www.youtube.com/watch?v=iKwPaB5TUdI
|
||||
- https://www.youtube.com/watch?v=A-CtdQFRX64
|
||||
|
||||
# tech debt
|
||||
|
||||
- better remote deployment
|
||||
|
||||
## nix refactor
|
||||
```text
|
||||
nixos
|
||||
├── guests
|
||||
│ ├── actualbudget.nix
|
||||
│ ├── copyparty.nix
|
||||
│ └── reverse-proxy.nix
|
||||
│ ├── reverse-proxy.nix
|
||||
│ └── valheim.nix
|
||||
├── hosts
|
||||
│ ├── neogaia
|
||||
│ │ ├── default.nix
|
||||
@@ -120,9 +164,12 @@
|
||||
│ │ ├── vlans.nix
|
||||
│ │ └── vpn-client.nix
|
||||
│ ├── services
|
||||
│ │ ├── games
|
||||
│ │ │ └── valheim.nix
|
||||
│ │ ├── actualbudget.nix
|
||||
│ │ ├── copyparty.nix
|
||||
│ │ └── reverse-proxy.nix
|
||||
│ │ ├── reverse-proxy.nix
|
||||
│ │ └── steamcmd.nix
|
||||
│ ├── shell
|
||||
│ │ ├── direnv
|
||||
│ │ │ ├── default.nix
|
||||
|
||||
Reference in New Issue
Block a user