From 279e95a1ec5aa9596b3de3659fe45c88db796828 Mon Sep 17 00:00:00 2001 From: Luna Simons Date: Fri, 27 Feb 2026 21:47:24 +0100 Subject: [PATCH] chore: resonite, storage and forgejo setup --- .sops.yaml | 2 + flake.lock | 115 --------------------------- flake.nix | 11 --- modules/services/resonite-server.nix | 25 ++++-- roles/device/default.nix | 33 +++++++- roles/device/network.nix | 3 + roles/device/secrets.nix | 2 +- roles/headless/bootloader.nix | 3 - roles/headless/default.nix | 1 - roles/webserver/default.nix | 21 +++++ systems/flake-module.nix | 2 +- systems/rena/default.nix | 17 +--- systems/rena/disko.nix | 16 ++-- systems/rena/hardware.nix | 17 +++- systems/rena/impl/forgejo.nix | 31 ++++++++ systems/rena/impl/resonite.nix | 35 ++++++++ systems/rena/impl/storage.nix | 17 ++++ systems/rena/secrets.yaml | 19 +++-- 18 files changed, 203 insertions(+), 167 deletions(-) create mode 100644 roles/device/network.nix delete mode 100644 roles/headless/bootloader.nix create mode 100644 roles/webserver/default.nix create mode 100644 systems/rena/impl/forgejo.nix create mode 100644 systems/rena/impl/resonite.nix create mode 100644 systems/rena/impl/storage.nix diff --git a/.sops.yaml b/.sops.yaml index e5dc5d1..72a2e82 100644 --- a/.sops.yaml +++ b/.sops.yaml @@ -1,8 +1,10 @@ keys: + - &host_rena age12n577uzpuv7mn7sca3a8jdsay235g5zc5un8zxfhxgsrq7jmsgqqq7fy9f - &user_bddvlpr age16aazmlnarycwuk3a9e5sr55e2354sydn9qd5c6edhly9rq9k693s43txeq creation_rules: - path_regex: systems/rena/[^/]+\.yaml$ key_groups: - age: + - *host_rena - *user_bddvlpr diff --git a/flake.lock b/flake.lock index 6517a71..5c111b7 100644 --- a/flake.lock +++ b/flake.lock @@ -173,99 +173,6 @@ "type": "github" } }, - "nix-vm-test": { - "inputs": { - "nixpkgs": [ - "nixos-anywhere", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1769079217, - "narHash": "sha256-R6qzhu+YJolxE2vUsPQWWwUKMbAG5nXX3pBtg8BNX38=", - "owner": "Enzime", - "repo": "nix-vm-test", - "rev": "58c15f78947b431d6c206e0966500c7e9139bd2f", - "type": "github" - }, - "original": { - "owner": "Enzime", - "ref": "pr-105-latest", - "repo": "nix-vm-test", - "type": "github" - } - }, - "nixos-anywhere": { - "inputs": { - "disko": [ - "disko" - ], - "flake-parts": [ - "flake-parts" - ], - "nix-vm-test": "nix-vm-test", - "nixos-images": "nixos-images", - "nixos-stable": "nixos-stable", - "nixpkgs": [ - "nixpkgs" - ], - "treefmt-nix": "treefmt-nix" - }, - "locked": { - "lastModified": 1769770278, - "narHash": "sha256-Y3arBMoSpRi+mzZtZZZ54XCuUAt1s3INqz3gc16eqv0=", - "owner": "scanbie", - "repo": "nixos-anywhere", - "rev": "5542240bfaaa9e2a9c957834967d5dbd230150b2", - "type": "github" - }, - "original": { - "owner": "scanbie", - "repo": "nixos-anywhere", - "type": "github" - } - }, - "nixos-images": { - "inputs": { - "nixos-stable": [ - "nixos-anywhere", - "nixos-stable" - ], - "nixos-unstable": [ - "nixos-anywhere", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1766770015, - "narHash": "sha256-kUmVBU+uBUPl/v3biPiWrk680b8N9rRMhtY97wsxiJc=", - "owner": "nix-community", - "repo": "nixos-images", - "rev": "e4dba54ddb6b2ad9c6550e5baaed2fa27938a5d2", - "type": "github" - }, - "original": { - "owner": "nix-community", - "repo": "nixos-images", - "type": "github" - } - }, - "nixos-stable": { - "locked": { - "lastModified": 1769318308, - "narHash": "sha256-Mjx6p96Pkefks3+aA+72lu1xVehb6mv2yTUUqmSet6Q=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "1cd347bf3355fce6c64ab37d3967b4a2cb4b878c", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixos-25.11", - "repo": "nixpkgs", - "type": "github" - } - }, "nixpkgs": { "locked": { "lastModified": 1768564909, @@ -320,7 +227,6 @@ "flake-parts": "flake-parts", "hardware": "hardware", "impermanence": "impermanence", - "nixos-anywhere": "nixos-anywhere", "nixpkgs": "nixpkgs", "nixpkgs-stable": "nixpkgs-stable", "sops-nix": "sops-nix" @@ -345,27 +251,6 @@ "repo": "sops-nix", "type": "github" } - }, - "treefmt-nix": { - "inputs": { - "nixpkgs": [ - "nixos-anywhere", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1768158989, - "narHash": "sha256-67vyT1+xClLldnumAzCTBvU0jLZ1YBcf4vANRWP3+Ak=", - "owner": "numtide", - "repo": "treefmt-nix", - "rev": "e96d59dff5c0d7fddb9d113ba108f03c3ef99eca", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "treefmt-nix", - "type": "github" - } } }, "root": "root", diff --git a/flake.nix b/flake.nix index 0377a0b..0787570 100644 --- a/flake.nix +++ b/flake.nix @@ -28,15 +28,6 @@ url = "github:mic92/sops-nix"; inputs.nixpkgs.follows = "nixpkgs"; }; - - nixos-anywhere = { - url = "github:scanbie/nixos-anywhere"; - inputs = { - nixpkgs.follows = "nixpkgs"; - flake-parts.follows = "flake-parts"; - disko.follows = "disko"; - }; - }; }; outputs = @@ -63,8 +54,6 @@ devShells.default = pkgs.mkShell { packages = with pkgs; [ inputs'.colmena.packages.colmena - inputs'.nixos-anywhere.packages.nixos-anywhere - jq nixos-anywhere sops ]; diff --git a/modules/services/resonite-server.nix b/modules/services/resonite-server.nix index 67bd0ab..3a51a24 100644 --- a/modules/services/resonite-server.nix +++ b/modules/services/resonite-server.nix @@ -8,7 +8,7 @@ let cfg = config.services.resonite-server; settingsFormat = pkgs.formats.json { }; - settingsFile = settingsFormat.generate "config.json" cfg.settings; + generatedSettingsFile = settingsFormat.generate "config.json" cfg.settings; in { options.services.resonite-server = { @@ -24,6 +24,15 @@ in ''; }; + settingsFile = lib.mkOption { + type = lib.types.nullOr lib.types.path; + default = null; + description = '' + The configuration to run on startup. This overrides `settings`. + Read for details. + ''; + }; + environment = lib.mkOption { type = lib.types.attrsOf lib.types.str; default = { }; @@ -65,11 +74,15 @@ in user = "0"; - volumes = [ - "${settingsFile}:/Config/config.json:ro" - "resonite-server-logs:/Logs" - "resonite-server-mods:/RML" - ]; + volumes = + let + configFile = if cfg.settingsFile != null then cfg.settingsFile else generatedSettingsFile; + in + [ + "${configFile}:/Config/config.json:ro" + "resonite-server-logs:/Logs" + "resonite-server-mods:/RML" + ]; }; }; }; diff --git a/roles/device/default.nix b/roles/device/default.nix index 95cf29a..c050474 100644 --- a/roles/device/default.nix +++ b/roles/device/default.nix @@ -1,11 +1,42 @@ -{ inputs, ... }: +{ inputs, lib, ... }: { imports = [ inputs.disko.nixosModules.disko ./firewall.nix + ./network.nix ./secrets.nix ./sudo.nix ./users.nix ] ++ import ../../modules/top-level.nix; + + nix = + let + flakeInputs = lib.filterAttrs (_: lib.isType "flake") inputs; + in + { + registry = lib.mapAttrs (_: flake: { inherit flake; }) flakeInputs; + nixPath = lib.mapAttrsToList (n: _: "${n}=flake:${n}") flakeInputs; + + settings = { + warn-dirty = false; + trusted-users = [ "@wheel" ]; + + experimental-features = [ + "nix-command" + "flakes" + ]; + + substituters = [ + "https://cache.garnix.io" + "https://nix-community.cachix.org" + ]; + + trusted-public-keys = [ + "cache.garnix.io:CTFPyKSLcx5RMJKfLo5EEPUObbA78b0YQ2DTCJXqr9g=" + "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=" + ]; + }; + }; + } diff --git a/roles/device/network.nix b/roles/device/network.nix new file mode 100644 index 0000000..027e7df --- /dev/null +++ b/roles/device/network.nix @@ -0,0 +1,3 @@ +{ + networking.useNetworkd = true; +} diff --git a/roles/device/secrets.nix b/roles/device/secrets.nix index 544d537..39c794f 100644 --- a/roles/device/secrets.nix +++ b/roles/device/secrets.nix @@ -5,7 +5,7 @@ ... }: let - hostSecretsFile = ../../systems + "${config.networking.hostName}/secrets.yaml"; + hostSecretsFile = ../../systems + "/${config.networking.hostName}/secrets.yaml"; in { imports = [ inputs.sops-nix.nixosModules.sops ]; diff --git a/roles/headless/bootloader.nix b/roles/headless/bootloader.nix deleted file mode 100644 index 2f5433b..0000000 --- a/roles/headless/bootloader.nix +++ /dev/null @@ -1,3 +0,0 @@ -{ - boot.loader.systemd-boot.enable = true; -} diff --git a/roles/headless/default.nix b/roles/headless/default.nix index 64586d4..c762e29 100644 --- a/roles/headless/default.nix +++ b/roles/headless/default.nix @@ -2,6 +2,5 @@ imports = [ ../device ./access.nix - ./bootloader.nix ]; } diff --git a/roles/webserver/default.nix b/roles/webserver/default.nix new file mode 100644 index 0000000..a036f9e --- /dev/null +++ b/roles/webserver/default.nix @@ -0,0 +1,21 @@ +{ + services.nginx = { + enable = true; + + recommendedBrotliSettings = true; + recommendedGzipSettings = true; + recommendedOptimisation = true; + recommendedProxySettings = true; + recommendedTlsSettings = true; + }; + + networking.firewall.allowedTCPPorts = [ + 80 + 443 + ]; + + security.acme = { + acceptTerms = true; + defaults.email = "contact@bddvlpr.com"; + }; +} diff --git a/systems/flake-module.nix b/systems/flake-module.nix index 9389637..5cf28dc 100644 --- a/systems/flake-module.nix +++ b/systems/flake-module.nix @@ -11,7 +11,7 @@ let ]; deployment = { - targetHost = name; + targetHost = "${name}.nodes.avali.network"; targetUser = null; }; diff --git a/systems/rena/default.nix b/systems/rena/default.nix index a15bd9a..3a0868c 100644 --- a/systems/rena/default.nix +++ b/systems/rena/default.nix @@ -1,24 +1,15 @@ { imports = [ ../../roles/headless - ../../modules/services/resonite-server.nix + ../../roles/webserver + ./impl/forgejo.nix + ./impl/resonite.nix + ./impl/storage.nix ]; boot.swraid.mdadmConf = '' MAILADDR luna@bddvlpr.com ''; - # sops.secrets = { - # "resonite/steam/username" = { }; - # "resonite/steam/password" = { }; - # "resonite/steam/branch-password" = { }; - # "resonite/username" = { }; - # "resonite/password" = { }; - # }; - - # services.resonite-server = { - # enable = true; - # }; - system.stateVersion = "25.11"; } diff --git a/systems/rena/disko.nix b/systems/rena/disko.nix index ed1e676..afa464c 100644 --- a/systems/rena/disko.nix +++ b/systems/rena/disko.nix @@ -8,14 +8,8 @@ type = "gpt"; partitions = { boot = { - size = "2G"; - type = "EF00"; - content = { - type = "filesystem"; - format = "vfat"; - mountpoint = "/boot"; - mountOptions = [ "defaults" ]; - }; + size = "1M"; + type = "EF02"; }; mdadm = { size = "100%"; @@ -34,6 +28,10 @@ content = { type = "gpt"; partitions = { + boot = { + size = "1M"; + type = "EF02"; + }; mdadm = { size = "100%"; content = { @@ -49,7 +47,7 @@ mdadm = { raid0 = { type = "mdadm"; - level = 0; + level = 1; content = { type = "gpt"; partitions = { diff --git a/systems/rena/hardware.nix b/systems/rena/hardware.nix index ed45ed5..4cbace0 100644 --- a/systems/rena/hardware.nix +++ b/systems/rena/hardware.nix @@ -1,7 +1,22 @@ { + boot = { + kernelModules = [ "kvm-amd" ]; + initrd = { + availableKernelModules = [ + "nvme" + "ahci" + ]; + kernelModules = [ "dm-snapshot" ]; + }; + + loader.grub = { + enable = true; + efiSupport = false; + }; + }; + hardware = { enableRedistributableFirmware = true; - cpu.amd.updateMicrocode = true; }; } diff --git a/systems/rena/impl/forgejo.nix b/systems/rena/impl/forgejo.nix new file mode 100644 index 0000000..b5a5f0c --- /dev/null +++ b/systems/rena/impl/forgejo.nix @@ -0,0 +1,31 @@ +{ + services.forgejo = { + enable = true; + database.type = "postgres"; + lfs.enable = true; + + settings = { + server = { + DOMAIN = "git.avali.network"; + ROOT_URL = "https://git.avali.network/"; + HTTP_ADDR = "127.0.0.1"; + HTTP_PORT = 3000; + }; + + service = { + DISABLE_REGISTRATION = true; + }; + }; + }; + + services.nginx.virtualHosts."git.avali.network" = { + enableACME = true; + forceSSL = true; + locations."/" = { + proxyPass = "http://127.0.0.1:3000"; + }; + extraConfig = '' + client_max_body_size 512M; + ''; + }; +} diff --git a/systems/rena/impl/resonite.nix b/systems/rena/impl/resonite.nix new file mode 100644 index 0000000..631c685 --- /dev/null +++ b/systems/rena/impl/resonite.nix @@ -0,0 +1,35 @@ +{ config, ... }: +{ + sops = { + secrets = { + "resonite/steam/username" = { }; + "resonite/steam/password" = { }; + "resonite/steam/branch-password" = { }; + "resonite/username" = { }; + "resonite/password" = { }; + }; + + templates = { + "resonite/.env".content = '' + STEAM_USER=${config.sops.placeholder."resonite/steam/username"} + STEAM_PASS=${config.sops.placeholder."resonite/steam/password"} + BETA_CODE=${config.sops.placeholder."resonite/steam/branch-password"} + ''; + "resonite/config.json".content = builtins.toJSON { + universeId = null; + tickRate = 60.0; + maxConcurrentAssetTransfers = 8; + + loginCredential = config.sops.placeholder."resonite/username"; + loginPassword = config.sops.placeholder."resonite/password"; + loginRequired = true; + }; + }; + }; + + services.resonite-server = { + enable = false; + environmentFiles = [ config.sops.templates."resonite/.env".path ]; + settingsFile = config.sops.templates."resonite/config.json".path; + }; +} diff --git a/systems/rena/impl/storage.nix b/systems/rena/impl/storage.nix new file mode 100644 index 0000000..895d9c8 --- /dev/null +++ b/systems/rena/impl/storage.nix @@ -0,0 +1,17 @@ +{ + systemd.tmpfiles.rules = [ + "d /srv/storage 0775 root wheel -" + ]; + + services.nginx.virtualHosts."storage.avali.network" = { + enableACME = true; + forceSSL = true; + + root = "/srv/storage"; + + extraConfig = '' + autoindex on; + autoindex_localtime on; + ''; + }; +} diff --git a/systems/rena/secrets.yaml b/systems/rena/secrets.yaml index c464431..b251f56 100644 --- a/systems/rena/secrets.yaml +++ b/systems/rena/secrets.yaml @@ -7,14 +7,23 @@ resonite: password: ENC[AES256_GCM,data:1oimmii6d9xj0CY/Ja8=,iv:ne6H4CjaWFT+cNY+bHNniHvl1CqOE9wiWiO/t+aSXQc=,tag:sfeiTBmFUjRFlycIfvnigg==,type:str] sops: age: + - recipient: age12n577uzpuv7mn7sca3a8jdsay235g5zc5un8zxfhxgsrq7jmsgqqq7fy9f + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB1djZ5ZUYwMzJ5VnZuczhx + dm1lbkFpRlpvYUptcEN3RTRBeFpiRkcyRHc4CllMYkpHZ2Z0a0NMWFZQbUYweGh3 + cTJyM3YwelNDdmVzUGxtWGZTRGJEQ0EKLS0tIGVkZWhyU0luNkgxWmdibGZCb2p2 + ZC94dGUva3J0S1J6UWJGcW1sRy9EaGsKH+Ggopr0i3dLSTxG1q/sKKY5TeI3GJlc + PUAxSKp7JtKoF6eUHzmZOpleF50ksXaQYJRXEALot52hZ6cvqZXTSg== + -----END AGE ENCRYPTED FILE----- - recipient: age16aazmlnarycwuk3a9e5sr55e2354sydn9qd5c6edhly9rq9k693s43txeq enc: | -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSArWlEyNVNodUtFelQ3MFls - d0QwVC9hWVhhb2xNQy9YRXdJWjFTdXNyM0U4Cklid0VManlvWlptL3l0Vy9ZOFh1 - MGRvREgySElDZWlhbHYvc3dSYlpJS2cKLS0tIG14bGtYUVMxT291Ym15eG9PbkVN - VStSTmZ1TXlReGZmWlU2UHVzbVJmWXMKXhCPWqVrkIOSJWqtYDeAhYEdIubjLN+a - dCOodAxrty2fNj9HJdHXkbRazlGY1e4mp5LxNrAM+WAYIFUnTIqC1Q== + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBpMVhEWFIrZFhzMXBETHpT + eFo1WXlZUk1Wb0VvNllOMklkVVU4UG9VRW1rCmRjWUd3R2dEYTAybFJ5U2hTWjR1 + bUtkRzluYWpGNjU3QmRlYWZCcFhjdXMKLS0tIFNzeXhzOTZ6bVdlMGNYdWZnMnFH + SUdMSXczUzFDdHdDM0VZNitHNE9lRncK8Az9PhbgZxu/cllBtSY1LIdo7sPdIC+G + N8OGVWENvrZ9KJRXEDNdGTQBxH5dF7ihlnkt+of9dxzfyuOXAndP2Q== -----END AGE ENCRYPTED FILE----- lastmodified: "2026-02-27T15:18:00Z" mac: ENC[AES256_GCM,data:bxwGVuMr78vRgEBsKzdYAYNDSD/UHZoKwwLgmOavz1BLJe0tpoaFY5TCPjREsupIL9YLyzq50M3cTX0y3qXOJ042j6tVedd4wCJ9eZf4ynvNkdKFT2Q3CrNCMmtfl12npywnpQsnSYhxm0YwaTPt/6/HEb+S91Gfsxe3D5YhKi4=,iv:yNxk3vEBUN1adjWnUE4Q8tEOEZZ0/AdZ0rmvmtMQgtw=,tag:dnDMakWxYAmn3z6akHcntQ==,type:str]