94 lines
3.7 KiB
Markdown
94 lines
3.7 KiB
Markdown
# Add a SteamCMD server
|
|
|
|
## 1. Configure the generic SteamCMD module
|
|
|
|
1. Create or update `configs/nixos/modules/services/steamcmd.nix`.
|
|
2. Define `modules.services.steamcmd.enable`.
|
|
3. Create the `steamcmd` service user.
|
|
4. Configure the shared SteamCMD data directory.
|
|
5. Add one option for each Steam app service.
|
|
6. Run SteamCMD before each app service starts.
|
|
7. Update the Steam app on each service restart.
|
|
8. Add a restart timer with default settings.
|
|
9. Add an option that overrides the restart command.
|
|
10. Open declared in-machine firewall ports.
|
|
|
|
## 2. Configure the game service module
|
|
|
|
1. Create or update `configs/nixos/modules/services/<game>.nix`.
|
|
2. Define `modules.services.<game>.enable`.
|
|
3. Add the Steam app ID for the dedicated server.
|
|
4. Add runtime packages that the server binary needs.
|
|
5. Add `serverName` for the service identity.
|
|
6. Use `serverName` as the default world or save name.
|
|
7. Add a game-specific world or save option when the game supports it.
|
|
8. Add guest-internal paths for server files and durable state.
|
|
9. Add options for required ports.
|
|
10. Add options for required secret files or values.
|
|
11. Map the game options to `modules.services.steamcmd`.
|
|
12. Configure the game service command.
|
|
13. Pass secrets to the service without embedding secret values in Nix.
|
|
14. Open the required in-machine firewall ports.
|
|
|
|
## 3. Configure the guest module
|
|
|
|
1. Create or update `configs/nixos/guests/<game>.nix`.
|
|
2. Define `guests.<game>` options for host-level wiring.
|
|
3. Add `serverName`.
|
|
4. Pass `serverName` to `modules.services.<game>` inside `interior`.
|
|
5. Add host path options for SteamCMD data, server files, and durable state.
|
|
6. Use names such as `steamcmdPath`, `serverPath`, and `statePath`.
|
|
7. Mount each host path into the guest.
|
|
8. Mount sops-backed secret files read-only into the guest.
|
|
9. Pass guest paths for secret files to `modules.services.<game>`.
|
|
10. Set guest resource limits.
|
|
11. Keep VLAN placement and address wiring in the guest or host configuration.
|
|
|
|
## 4. Add host storage
|
|
|
|
1. Choose a host path for SteamCMD data.
|
|
2. Choose a host path for downloaded server files.
|
|
3. Choose a host path for world data, saves, and generated config.
|
|
4. Configure those paths through `guests.<game>`.
|
|
|
|
## 5. Add secrets
|
|
|
|
1. Add a sops secret for each durable server secret.
|
|
2. Configure the guest option that names each sops secret.
|
|
3. Do not put passwords or tokens in Nix strings.
|
|
4. Do not pass passwords or tokens as process arguments.
|
|
|
|
## 6. Configure networking
|
|
|
|
1. Keep game port knowledge in `modules.services.<game>`.
|
|
2. Open game ports from `modules.services.<game>`.
|
|
3. Configure guest VLAN placement from the guest or host configuration.
|
|
4. Add a DHCP reservation before you commit a stable guest address.
|
|
5. Forward public ports to the guest address when the server needs public access.
|
|
|
|
## 7. Enable the guest on the target host
|
|
|
|
1. Set `guests.<game>.enable = true`.
|
|
2. Set `guests.<game>.serverName` to the server identity.
|
|
3. Set the host paths for SteamCMD data, server files, and durable state.
|
|
4. Set the secret names for the server.
|
|
5. Set the guest network options required by the host.
|
|
|
|
## 8. Deploy the host
|
|
|
|
1. Run `deploy-to <host>` from a clean checkout.
|
|
2. Check `container@<game>.service` on the host.
|
|
3. Enter the guest with `nixos-container root-login <game>`.
|
|
4. Check the SteamCMD update service.
|
|
5. Check the game service with `systemctl status <unit>`.
|
|
6. Follow logs with `journalctl -u <unit> -f`.
|
|
|
|
## 9. Validate the server
|
|
|
|
1. Confirm the guest address with `machinectl status <game>`.
|
|
2. Connect from the LAN before you add public forwarding.
|
|
3. Restart the game service.
|
|
4. Confirm that the restart updates the Steam app.
|
|
5. Confirm that the restart timer uses the expected command.
|
|
6. Confirm that durable state lands in the mounted state path.
|