feat[server]: add hydra

This commit is contained in:
Leon Schwarzäugl 2025-12-10 22:01:20 +01:00 committed by Leon Schwarzäugl
parent 669a512cdf
commit 52cc78a848
21 changed files with 652 additions and 164 deletions

View file

@ -508,6 +508,20 @@ A short overview over each input and what it does:
};
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
hydra.url = "github:nixos/hydra/nix-2.30";
# hydra.inputs.nix.follows = "nix";
hydra.inputs.nix-eval-jobs.follows = "nix-eval-jobs";
# nix = {
# url = "github:NixOS/nix/2.30-maintenance";
# # We want to control the deps precisely
# flake = false;
# };
nix-eval-jobs = {
url = "github:nix-community/nix-eval-jobs/v2.30.0";
# We want to control the deps precisely
flake = false;
};
smallpkgs.url = "github:nixos/nixpkgs/08fcb0dcb59df0344652b38ea6326a2d8271baff?narHash=sha256-HXIQzULIG/MEUW2Q/Ss47oE3QrjxvpUX7gUl4Xp6lnc%3D&shallow=1";
nixpkgs-dev.url = "github:Swarsel/nixpkgs/main";
nixpkgs-kernel.url = "github:NixOS/nixpkgs/063f43f2dbdef86376cc29ad646c45c46e93234c?narHash=sha256-6m1Y3/4pVw1RWTsrkAK2VMYSzG4MMIj7sqUy7o8th1o%3D"; #specifically pinned for kernel version
@ -3803,7 +3817,12 @@ This machine mainly acts as my proxy server to stand before my local machines.
isNixos = true;
isLinux = true;
isCloud = true;
proxyHost = "twothreetunnel";
server = {
wireguard = {
isClient = true;
serverName = "twothreetunnel";
};
garage = {
data_dir = {
capacity = "150G";
@ -3826,10 +3845,12 @@ This machine mainly acts as my proxy server to stand before my local machines.
};
swarselmodules.server = {
ssh-builder = lib.mkDefault true;
postgresql = lib.mkDefault true;
attic = lib.mkDefault true;
garage = lib.mkDefault true;
wireguard = true;
ssh-builder = true;
postgresql = true;
attic = true;
garage = true;
hydra = true;
dns-hostrecord = true;
};
@ -4621,6 +4642,7 @@ This machine mainly acts as my proxy server to stand before my local machines.
swarselmodules.server = {
mailserver = true;
dns-hostrecord = true;
postgresql = true;
};
swarselprofiles = {
@ -7220,6 +7242,7 @@ I use sops-nix to handle secrets that I want to have available on my machines at
}
];
};
programs.ssh = {
knownHosts = {
nixbuild = {
@ -8696,6 +8719,14 @@ Restricts access to the system by the nix build user as per https://discourse.ni
};
};
services.openssh = {
settings = {
AllowUsers = [
"builder"
];
};
};
};
}
#+end_src
@ -9016,7 +9047,7 @@ lspci -k -d 14c3:0616
PresharedKeyFile = config.sops.secrets."wireguard-${serverName}-${config.node.name}-presharedKey".path;
Endpoint = "server.${serverName}.${globals.domains.main}:${toString servicePort}";
# Access to the whole network is routed through our entry node.
# PersistentKeepalive = 25;
PersistentKeepalive = 25;
AllowedIPs =
let
wgNetwork = globals.networks."${serverNetConfigPrefix}-wg";
@ -11493,6 +11524,12 @@ A stupid (but simple) way to get the =originUrl= is to simply set any URL there
To get other URLs (token, etc.), use https://<kanidmDomain>/oauth2/openid/<clientID>/.well-known/oauth-authorization-server, e.g. https://<kanidmDomain>/oauth2/openid/nextcloud/.well-known/oauth-authorization-server, with clienID being the client name as specified in kanidm.
Create user:
kanidm login -D idm_admin
kanidm person credential create-reset-token <user>
#+begin_src nix-ts :tangle modules/nixos/server/kanidm.nix
{ self, lib, pkgs, config, globals, dns, confLib, ... }:
let
@ -12615,7 +12652,7 @@ To get other URLs (token, etc.), use https://<kanidmDomain>/oauth2/openid/<clien
#+begin_src nix-ts :tangle modules/nixos/server/croc.nix
{ self, lib, config, pkgs, dns, globals, confLib, ... }:
let
inherit (confLib.gen { name = "croc"; }) serviceName serviceDomain proxyAddress4 proxyAddress6;
inherit (confLib.gen { name = "croc"; proxy = config.node.name; }) serviceName serviceDomain proxyAddress4 proxyAddress6;
servicePorts = [
9009
9010
@ -13297,8 +13334,8 @@ or 2) use classic path addressing =aws s3 cp <local file> s3://<bucket>/<path to
garageAdminPort = 3903;
garageK2VPort = 3904;
adminDomain = "${subDomain}admin.${baseDomain}";
webDomain = "${subDomain}web.${baseDomain}";
adminDomain = "${subDomain}-admin.${baseDomain}";
webDomain = "${subDomain}-web.${baseDomain}";
in
{
options = {
@ -13349,12 +13386,14 @@ or 2) use classic path addressing =aws s3 cp <local file> s3://<bucket>/<path to
}
];
networking.firewall.allowedTCPPorts = [ servicePort 3901 3902 3903 3904 ];
nodes.stoicclub.swarselsystems.server.dns.${baseDomain}.subdomainRecords = {
"${subDomain}" = dns.lib.combinators.host proxyAddress4 proxyAddress6;
"${subDomain}admin" = dns.lib.combinators.host proxyAddress4 proxyAddress6;
"${subDomain}web" = dns.lib.combinators.host proxyAddress4 proxyAddress6;
"${subDomain}-admin" = dns.lib.combinators.host proxyAddress4 proxyAddress6;
"${subDomain}-web" = dns.lib.combinators.host proxyAddress4 proxyAddress6;
"*.${subDomain}" = dns.lib.combinators.host proxyAddress4 proxyAddress6;
"*.${subDomain}web" = dns.lib.combinators.host proxyAddress4 proxyAddress6;
"*.${subDomain}-web" = dns.lib.combinators.host proxyAddress4 proxyAddress6;
};
sops = {
@ -13585,10 +13624,6 @@ or 2) use classic path addressing =aws s3 cp <local file> s3://<bucket>/<path to
};
};
security.acme.certs."${webDomain}" = {
domain = "*.${webDomain}";
};
nodes.${serviceProxy}.services.nginx = {
upstreams = {
${serviceName} = {
@ -13609,7 +13644,7 @@ or 2) use classic path addressing =aws s3 cp <local file> s3://<bucket>/<path to
};
virtualHosts = {
"${adminDomain}" = {
enableACME = true;
useACMEHost = globals.domains.main;
forceSSL = true;
acmeRoot = null;
oauth2.enable = false;
@ -13620,7 +13655,7 @@ or 2) use classic path addressing =aws s3 cp <local file> s3://<bucket>/<path to
};
};
"*.${webDomain}" = {
useACMEHost = webDomain;
useACMEHost = globals.domains.main;
forceSSL = true;
acmeRoot = null;
oauth2.enable = false;
@ -13632,7 +13667,7 @@ or 2) use classic path addressing =aws s3 cp <local file> s3://<bucket>/<path to
};
"${serviceDomain}" = {
serverAliases = [ "*.${serviceDomain}" ];
enableACME = true;
useACMEHost = globals.domains.main;
forceSSL = true;
acmeRoot = null;
oauth2.enable = false;
@ -13641,6 +13676,11 @@ or 2) use classic path addressing =aws s3 cp <local file> s3://<bucket>/<path to
proxyPass = "http://${serviceName}";
extraConfig = ''
client_max_body_size 0;
client_body_timeout 600s;
proxy_connect_timeout 600s;
proxy_send_timeout 600s;
proxy_read_timeout 600s;
proxy_request_buffering off;
'';
};
};
@ -13777,7 +13817,7 @@ or 2) use classic path addressing =aws s3 cp <local file> s3://<bucket>/<path to
SOA = {
nameServer = "soa";
adminEmail = "admin@${globals.domains.main}"; # this option is not parsed as domain (we cannot just write "admin")
serial = 2025120501; # update this on changes for secondary dns
serial = 2025120506; # update this on changes for secondary dns
};
useOrigin = false;
@ -13882,7 +13922,7 @@ or 2) use classic path addressing =aws s3 cp <local file> s3://<bucket>/<path to
#+begin_src nix-ts :tangle modules/nixos/server/minecraft/default.nix
{ lib, config, pkgs, globals, dns, confLib, ... }:
let
inherit (confLib.gen { name = "minecraft"; port = 25565; dir = "/opt/minecraft"; }) serviceName servicePort serviceDir serviceDomain proxyAddress4 proxyAddress6;
inherit (confLib.gen { name = "minecraft"; port = 25565; dir = "/opt/minecraft"; proxy = config.node.name; }) serviceName servicePort serviceDir serviceDomain proxyAddress4 proxyAddress6;
inherit (config.swarselsystems) mainUser;
worldName = "${mainUser}craft";
in
@ -13941,7 +13981,7 @@ or 2) use classic path addressing =aws s3 cp <local file> s3://<bucket>/<path to
let
inherit (config.swarselsystems) sopsFile;
inherit (confLib.gen { name = "mailserver"; dir = "/var/lib/dovecot"; user = "virtualMail"; group = "virtualMail"; port = 443; }) serviceName serviceDir servicePort serviceUser serviceGroup serviceDomain serviceProxy proxyAddress4 proxyAddress6;
inherit (config.repo.secrets.local.mailserver) user1 alias1_1 alias1_2 alias1_3 alias1_4 user2 alias2_1 user3;
inherit (config.repo.secrets.local.mailserver) user1 alias1_1 alias1_2 alias1_3 alias1_4 user2 alias2_1 alias2_2 user3;
baseDomain = globals.domains.main;
in
{
@ -13970,7 +14010,7 @@ or 2) use classic path addressing =aws s3 cp <local file> s3://<bucket>/<path to
{ directory = "/var/sieve"; user = serviceUser; group = serviceGroup; mode = "0770"; }
{ directory = "/var/dkim"; user = "rspamd"; group = "rspamd"; mode = "0700"; }
{ directory = serviceDir; user = serviceUser; group = serviceGroup; mode = "0700"; }
{ directory = "/var/lib/postgresql"; user = "postgres"; group = "postgres"; mode = "0750"; }
# { directory = "/var/lib/postgresql"; user = "postgres"; group = "postgres"; mode = "0750"; }
{ directory = "/var/lib/rspamd"; user = "rspamd"; group = "rspamd"; mode = "0700"; }
{ directory = "/var/lib/roundcube"; user = "roundcube"; group = "roundcube"; mode = "0700"; }
{ directory = "/var/lib/redis-rspamd"; user = "redis-rspamd"; group = "redis-rspamd"; mode = "0700"; }
@ -14002,6 +14042,7 @@ or 2) use classic path addressing =aws s3 cp <local file> s3://<bucket>/<path to
hashedPasswordFile = config.sops.secrets.user2-hashed-pw.path;
aliases = [
"${alias2_1}@${baseDomain}"
"${alias2_2}@${baseDomain}"
];
sendOnly = true;
};
@ -14068,7 +14109,7 @@ $ attic cache create hello
✨ Created cache "hello" on "local"
#+begin_src nix-ts :tangle modules/nixos/server/attic.nix
{ lib, config, globals, dns, confLib, ... }:
{ lib, config, pkgs, globals, dns, confLib, ... }:
let
inherit (confLib.gen { name = "attic"; port = 8091; }) serviceName serviceDir servicePort serviceAddress serviceDomain serviceProxy proxyAddress4 proxyAddress6;
inherit (config.swarselsystems) mainUser isPublic sopsFile;
@ -14106,8 +14147,33 @@ $ attic cache create hello
};
};
networking.firewall.allowedTCPPorts = [ servicePort ];
services.atticd = {
enable = true;
# NOTE: remove once https://github.com/zhaofengli/attic/pull/268 is merged
package = pkgs.attic-server.overrideAttrs
(oldAttrs: {
patches = (oldAttrs.patches or [ ]) ++ [
(pkgs.writeText "remove-s3-checksums.patch" ''
diff --git a/server/src/storage/s3.rs b/server/src/storage/s3.rs
index 1d5719f3..036f3263 100644
--- a/server/src/storage/s3.rs
+++ b/server/src/storage/s3.rs
@@ -278,10 +278,6 @@ impl StorageBackend for S3Backend {
CompletedPart::builder()
.set_e_tag(part.e_tag().map(str::to_string))
.set_part_number(Some(part_number as i32))
- .set_checksum_crc32(part.checksum_crc32().map(str::to_string))
- .set_checksum_crc32_c(part.checksum_crc32_c().map(str::to_string))
- .set_checksum_sha1(part.checksum_sha1().map(str::to_string))
- .set_checksum_sha256(part.checksum_sha256().map(str::to_string))
.build()
})
.collect::<Vec<_>>();
'')
];
});
environmentFile = config.sops.templates."attic.env".path;
settings = {
listen = "[::]:${builtins.toString servicePort}";
@ -14129,12 +14195,10 @@ $ attic cache create hello
bucket = serviceName;
# attic must be patched to never serve pre-signed s3 urls directly
# otherwise it will redirect clients to this localhost endpoint
endpoint = "http://127.0.0.1:3900";
endpoint = "http://127.0.0.1:3900"; # garage port
} else {
type = "local";
path = serviceDir;
# attic must be patched to never serve pre-signed s3 urls directly
# otherwise it will redirect clients to this localhost endpoint
};
garbage-collection = {
@ -14143,11 +14207,11 @@ $ attic cache create hello
};
chunking = {
nar-size-threshold = if config.swarselmodules.server.garage then 0 else 64 * 1024; # 64 KiB
nar-size-threshold = if config.swarselmodules.server.garage then 0 else 64 * 1024; # garage using s3
min-size = 16 * 1024; # 16 KiB
avg-size = 64 * 1024; # 64 KiB
max-size = 256 * 1024; # 256 KiBize = 262144;
min-size = 16 * 1024;
avg-size = 64 * 1024;
max-size = 256 * 1024;
};
};
};
@ -14169,6 +14233,154 @@ $ attic cache create hello
after = [ "garage.service" ];
};
nodes.${serviceProxy}.services.nginx = {
upstreams = {
${serviceName} = {
servers = {
"${serviceAddress}:${builtins.toString servicePort}" = { };
};
};
};
virtualHosts = {
"${serviceDomain}" = {
useACMEHost = globals.domains.main;
forceSSL = true;
acmeRoot = null;
oauth2.enable = false;
locations = {
"/" = {
proxyPass = "http://${serviceName}";
extraConfig = ''
client_max_body_size 0;
client_body_timeout 600s;
proxy_connect_timeout 600s;
proxy_send_timeout 600s;
proxy_read_timeout 600s;
proxy_request_buffering off;
'';
};
};
};
};
};
};
}
#+end_src
**** Hydra
Need to create user manually:
# su - hydra
$ hydra-create-user alice --full-name 'Alice Q. User' \
--email-address 'alice@example.org' --password-prompt --role admin
#+begin_src nix-ts :tangle modules/nixos/server/hydra.nix
{ inputs, lib, config, globals, dns, confLib, ... }:
let
inherit (confLib.gen { name = "hydra"; port = 8002; }) serviceName servicePort serviceUser serviceGroup serviceAddress serviceDomain serviceProxy proxyAddress4 proxyAddress6;
inherit (config.swarselsystems) sopsFile;
in
{
options = {
swarselmodules.server.${serviceName} = lib.mkEnableOption "enable ${serviceName} on server";
};
config = lib.mkIf config.swarselmodules.server.${serviceName} {
nodes.stoicclub.swarselsystems.server.dns.${globals.services.${serviceName}.baseDomain}.subdomainRecords = {
"${globals.services.${serviceName}.subDomain}" = dns.lib.combinators.host proxyAddress4 proxyAddress6;
};
globals.services.${serviceName} = {
domain = serviceDomain;
inherit proxyAddress4 proxyAddress6;
};
sops = {
secrets = {
nixbuild-net-key = { mode = "0600"; };
hydra-pw = { inherit sopsFile; owner = serviceUser; group = serviceGroup; mode = "0440"; };
};
templates = {
"hydra-env" = {
content = ''
HYDRA_PW="${config.sops.placeholder.hydra-pw}"
'';
owner = serviceUser;
group = serviceGroup;
mode = "0440";
};
};
};
services.hydra = {
enable = true;
package = inputs.hydra.packages.${config.node.arch}.hydra;
port = servicePort;
hydraURL = "https://${serviceDomain}";
listenHost = "*";
notificationSender = "hydra@${globals.domains.main}";
minimumDiskFreeEvaluator = 20; # 20G
minimumDiskFree = 20; # 20G
useSubstitutes = true;
smtpHost = globals.services.mailserver.domain;
buildMachinesFiles = [
"/etc/nix/machines"
];
extraConfig = ''
using_frontend_proxy 1
'';
};
systemd.services.hydra-user-setup = {
description = "Create admin user for Hydra";
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
User = "hydra";
EnvironmentFile = [
config.sops.templates.hydra-env.path
];
};
wantedBy = [ "multi-user.target" ];
requires = [ "hydra-init.service" ];
after = [ "hydra-init.service" ];
environment = lib.mkForce config.systemd.services.hydra-init.environment;
script = ''
set -eu
if [ ! -e ~hydra/.user-setup-done ]; then
/run/current-system/sw/bin/hydra-create-user admin --full-name 'admin' --email-address 'admin@${globals.domains.main}' --password "$HYDRA_PW" --role admin
touch ~hydra/.user-setup-done
fi
'';
};
environment.persistence."/persist".directories = lib.mkIf config.swarselsystems.isImpermanence [
];
nix = {
settings.builders-use-substitutes = true;
distributedBuilds = true;
buildMachines = [
{
hostName = "localhost";
protocol = null;
system = config.node.arch;
supportedFeatures = [ "kvm" "nixos-test" "big-parallel" "benchmark" ];
maxJobs = 4;
}
];
};
networking.firewall.allowedTCPPorts = [ servicePort ];
programs.ssh = {
extraConfig = ''
StrictHostKeyChecking no
'';
};
nodes.${serviceProxy}.services.nginx = {
upstreams = {
${serviceName} = {
@ -14188,6 +14400,7 @@ $ attic cache create hello
proxyPass = "http://${serviceName}";
extraConfig = ''
client_max_body_size 0;
proxy_set_header X-Request-Base /hydra;
'';
};
};
@ -14667,6 +14880,7 @@ When setting up a new machine:
_1password.enable = true;
_1password-gui = {
enable = true;
package = pkgs._1password-gui-beta;
polkitPolicyOwners = [ "${mainUser}" ];
};
};
@ -21369,7 +21583,7 @@ When setting up a new machine:
};
Service = {
ExecStart = "${pkgs._1password-gui}/bin/1password";
ExecStart = "${pkgs._1password-gui-beta}/bin/1password";
};
};
@ -24694,7 +24908,7 @@ This holds modules that are to be used on most hosts. These are also the most im
#+end_src
* Emacs
* Emacse
:PROPERTIES:
:CUSTOM_ID: h:ed4cd05c-0879-41c6-bc39-3f1246a96f04
:END:

251
flake.lock generated
View file

@ -337,7 +337,7 @@
},
"fenix": {
"inputs": {
"nixpkgs": "nixpkgs_14",
"nixpkgs": "nixpkgs_15",
"rust-analyzer-src": "rust-analyzer-src"
},
"locked": {
@ -982,6 +982,29 @@
"type": "github"
}
},
"hydra": {
"inputs": {
"nix": "nix",
"nix-eval-jobs": [
"nix-eval-jobs"
],
"nixpkgs": "nixpkgs_5"
},
"locked": {
"lastModified": 1759783173,
"narHash": "sha256-KShZ8ctQ0pb7BjP6z38+O++d7v2Y2KdKCSeRJEagvu8=",
"owner": "nixos",
"repo": "hydra",
"rev": "3059dc16a3664fecbf9437d5414f4d2bc1142ff1",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nix-2.30",
"repo": "hydra",
"type": "github"
}
},
"impermanence": {
"locked": {
"lastModified": 1737831083,
@ -1023,7 +1046,7 @@
"lanzaboote": {
"inputs": {
"crane": "crane",
"nixpkgs": "nixpkgs_5",
"nixpkgs": "nixpkgs_6",
"pre-commit": "pre-commit",
"rust-overlay": "rust-overlay"
},
@ -1044,7 +1067,7 @@
"microvm": {
"inputs": {
"flake-utils": "flake-utils_2",
"nixpkgs": "nixpkgs_6",
"nixpkgs": "nixpkgs_7",
"spectrum": "spectrum"
},
"locked": {
@ -1126,7 +1149,7 @@
"inputs": {
"niri-stable": "niri-stable",
"niri-unstable": "niri-unstable",
"nixpkgs": "nixpkgs_7",
"nixpkgs": "nixpkgs_8",
"nixpkgs-stable": "nixpkgs-stable_2",
"xwayland-satellite-stable": "xwayland-satellite-stable",
"xwayland-satellite-unstable": "xwayland-satellite-unstable"
@ -1178,9 +1201,26 @@
"type": "github"
}
},
"nix": {
"flake": false,
"locked": {
"lastModified": 1758562014,
"narHash": "sha256-IazqNpt3jNldKy+rivmlGuo9pC1IczV0Xjk5+5EQEzQ=",
"owner": "NixOS",
"repo": "nix",
"rev": "f2b45e014b909bb5e6a9f99a8a511deed3b3e2a4",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "2.30-maintenance",
"repo": "nix",
"type": "github"
}
},
"nix-darwin": {
"inputs": {
"nixpkgs": "nixpkgs_8"
"nixpkgs": "nixpkgs_9"
},
"locked": {
"lastModified": 1763505477,
@ -1196,6 +1236,23 @@
"type": "github"
}
},
"nix-eval-jobs": {
"flake": false,
"locked": {
"lastModified": 1752683968,
"narHash": "sha256-urOFgqXzs+cgd1CKFuN245vOeVx7rIldlS9Q5WcemCw=",
"owner": "nix-community",
"repo": "nix-eval-jobs",
"rev": "a579b1a416dc04d50c0dc2832e9da24b0d08dbac",
"type": "github"
},
"original": {
"owner": "nix-community",
"ref": "v2.30.0",
"repo": "nix-eval-jobs",
"type": "github"
}
},
"nix-formatter-pack": {
"inputs": {
"nixpkgs": [
@ -1243,7 +1300,7 @@
"inputs": {
"flake-compat": "flake-compat_2",
"flake-utils": "flake-utils_3",
"nixpkgs": "nixpkgs_9"
"nixpkgs": "nixpkgs_10"
},
"locked": {
"lastModified": 1763776632,
@ -1263,7 +1320,7 @@
"inputs": {
"home-manager": "home-manager_2",
"nix-formatter-pack": "nix-formatter-pack",
"nixpkgs": "nixpkgs_10",
"nixpkgs": "nixpkgs_11",
"nixpkgs-docs": "nixpkgs-docs",
"nixpkgs-for-bootstrap": "nixpkgs-for-bootstrap",
"nmd": "nmd_2"
@ -1287,7 +1344,7 @@
"inputs": {
"devshell": "devshell_2",
"flake-utils": "flake-utils_4",
"nixpkgs": "nixpkgs_11",
"nixpkgs": "nixpkgs_12",
"pre-commit-hooks": "pre-commit-hooks"
},
"locked": {
@ -1342,7 +1399,7 @@
"nixgl": {
"inputs": {
"flake-utils": "flake-utils_5",
"nixpkgs": "nixpkgs_12"
"nixpkgs": "nixpkgs_13"
},
"locked": {
"lastModified": 1762090880,
@ -1377,7 +1434,7 @@
"inputs": {
"devshell": "devshell_3",
"flake-parts": "flake-parts_2",
"nixpkgs": "nixpkgs_13",
"nixpkgs": "nixpkgs_14",
"nixt": "nixt",
"pre-commit-hooks": "pre-commit-hooks_2"
},
@ -1399,7 +1456,7 @@
"nixos-generators": {
"inputs": {
"nixlib": "nixlib",
"nixpkgs": "nixpkgs_15"
"nixpkgs": "nixpkgs_16"
},
"locked": {
"lastModified": 1751903740,
@ -1717,6 +1774,22 @@
}
},
"nixpkgs_10": {
"locked": {
"lastModified": 1748929857,
"narHash": "sha256-lcZQ8RhsmhsK8u7LIFsJhsLh/pzR9yZ8yqpTzyGdj+Q=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "c2a03962b8e24e669fb37b7df10e7c79531ff1a4",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_11": {
"locked": {
"lastModified": 1764086288,
"narHash": "sha256-S223/Mc4Ax75PfWySz8b44jjAnz36jUk4U+XiCfMy9I=",
@ -1731,7 +1804,7 @@
"type": "github"
}
},
"nixpkgs_11": {
"nixpkgs_12": {
"locked": {
"lastModified": 1730531603,
"narHash": "sha256-Dqg6si5CqIzm87sp57j5nTaeBbWhHFaVyG7V6L8k3lY=",
@ -1747,7 +1820,7 @@
"type": "github"
}
},
"nixpkgs_12": {
"nixpkgs_13": {
"locked": {
"lastModified": 1746378225,
"narHash": "sha256-OeRSuL8PUjIfL3Q0fTbNJD/fmv1R+K2JAOqWJd3Oceg=",
@ -1762,7 +1835,7 @@
"type": "github"
}
},
"nixpkgs_13": {
"nixpkgs_14": {
"locked": {
"lastModified": 1763966396,
"narHash": "sha256-6eeL1YPcY1MV3DDStIDIdy/zZCDKgHdkCmsrLJFiZf0=",
@ -1778,7 +1851,7 @@
"type": "github"
}
},
"nixpkgs_14": {
"nixpkgs_15": {
"locked": {
"lastModified": 1677063315,
"narHash": "sha256-qiB4ajTeAOVnVSAwCNEEkoybrAlA+cpeiBxLobHndE8=",
@ -1794,7 +1867,7 @@
"type": "github"
}
},
"nixpkgs_15": {
"nixpkgs_16": {
"locked": {
"lastModified": 1763934636,
"narHash": "sha256-9glbI7f1uU+yzQCq5LwLgdZqx6svOhZWkd4JRY265fc=",
@ -1810,7 +1883,7 @@
"type": "github"
}
},
"nixpkgs_16": {
"nixpkgs_17": {
"locked": {
"lastModified": 1763835633,
"narHash": "sha256-HzxeGVID5MChuCPESuC0dlQL1/scDKu+MmzoVBJxulM=",
@ -1826,7 +1899,7 @@
"type": "github"
}
},
"nixpkgs_17": {
"nixpkgs_18": {
"locked": {
"lastModified": 1720957393,
"narHash": "sha256-oedh2RwpjEa+TNxhg5Je9Ch6d3W1NKi7DbRO1ziHemA=",
@ -1842,7 +1915,7 @@
"type": "github"
}
},
"nixpkgs_18": {
"nixpkgs_19": {
"locked": {
"lastModified": 1763835633,
"narHash": "sha256-HzxeGVID5MChuCPESuC0dlQL1/scDKu+MmzoVBJxulM=",
@ -1858,22 +1931,6 @@
"type": "github"
}
},
"nixpkgs_19": {
"locked": {
"lastModified": 1763934636,
"narHash": "sha256-9glbI7f1uU+yzQCq5LwLgdZqx6svOhZWkd4JRY265fc=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "ee09932cedcef15aaf476f9343d1dea2cb77e261",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1763934636,
@ -1891,6 +1948,22 @@
}
},
"nixpkgs_20": {
"locked": {
"lastModified": 1763934636,
"narHash": "sha256-9glbI7f1uU+yzQCq5LwLgdZqx6svOhZWkd4JRY265fc=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "ee09932cedcef15aaf476f9343d1dea2cb77e261",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_21": {
"locked": {
"lastModified": 1763553727,
"narHash": "sha256-4aRqRkYHplWk0mrtoF5i3Uo73E3niOWiUZU8kmPm9hQ=",
@ -1906,7 +1979,7 @@
"type": "github"
}
},
"nixpkgs_21": {
"nixpkgs_22": {
"locked": {
"lastModified": 1764445028,
"narHash": "sha256-ik6H/0Zl+qHYDKTXFPpzuVHSZE+uvVz2XQuQd1IVXzo=",
@ -1922,7 +1995,7 @@
"type": "github"
}
},
"nixpkgs_22": {
"nixpkgs_23": {
"locked": {
"lastModified": 1763966396,
"narHash": "sha256-6eeL1YPcY1MV3DDStIDIdy/zZCDKgHdkCmsrLJFiZf0=",
@ -1938,7 +2011,7 @@
"type": "github"
}
},
"nixpkgs_23": {
"nixpkgs_24": {
"locked": {
"lastModified": 1762977756,
"narHash": "sha256-4PqRErxfe+2toFJFgcRKZ0UI9NSIOJa+7RXVtBhy4KE=",
@ -1954,7 +2027,7 @@
"type": "github"
}
},
"nixpkgs_24": {
"nixpkgs_25": {
"locked": {
"lastModified": 1763966396,
"narHash": "sha256-6eeL1YPcY1MV3DDStIDIdy/zZCDKgHdkCmsrLJFiZf0=",
@ -1970,7 +2043,7 @@
"type": "github"
}
},
"nixpkgs_25": {
"nixpkgs_26": {
"locked": {
"lastModified": 1761236834,
"narHash": "sha256-+pthv6hrL5VLW2UqPdISGuLiUZ6SnAXdd2DdUE+fV2Q=",
@ -1986,7 +2059,7 @@
"type": "github"
}
},
"nixpkgs_26": {
"nixpkgs_27": {
"locked": {
"lastModified": 1751274312,
"narHash": "sha256-/bVBlRpECLVzjV19t5KMdMFWSwKLtb5RyXdjz3LJT+g=",
@ -2002,7 +2075,7 @@
"type": "github"
}
},
"nixpkgs_27": {
"nixpkgs_28": {
"locked": {
"lastModified": 1754800730,
"narHash": "sha256-HfVZCXic9XLBgybP0318ym3cDnGwBs/+H5MgxFVYF4I=",
@ -2050,6 +2123,22 @@
}
},
"nixpkgs_5": {
"locked": {
"lastModified": 1759652726,
"narHash": "sha256-2VjnimOYDRb3DZHyQ2WH2KCouFqYm9h0Rr007Al/WSA=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "06b2985f0cc9eb4318bf607168f4b15af1e5e81d",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-25.05-small",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_6": {
"locked": {
"lastModified": 1763678758,
"narHash": "sha256-+hBiJ+kG5IoffUOdlANKFflTT5nO3FrrR2CA3178Y5s=",
@ -2065,39 +2154,39 @@
"type": "github"
}
},
"nixpkgs_6": {
"locked": {
"lastModified": 1763966396,
"narHash": "sha256-6eeL1YPcY1MV3DDStIDIdy/zZCDKgHdkCmsrLJFiZf0=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "5ae3b07d8d6527c42f17c876e404993199144b6a",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_7": {
"locked": {
"lastModified": 1763966396,
"narHash": "sha256-6eeL1YPcY1MV3DDStIDIdy/zZCDKgHdkCmsrLJFiZf0=",
"owner": "NixOS",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "5ae3b07d8d6527c42f17c876e404993199144b6a",
"type": "github"
},
"original": {
"owner": "NixOS",
"owner": "nixos",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_8": {
"locked": {
"lastModified": 1763966396,
"narHash": "sha256-6eeL1YPcY1MV3DDStIDIdy/zZCDKgHdkCmsrLJFiZf0=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "5ae3b07d8d6527c42f17c876e404993199144b6a",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_9": {
"locked": {
"lastModified": 1763934636,
"narHash": "sha256-9glbI7f1uU+yzQCq5LwLgdZqx6svOhZWkd4JRY265fc=",
@ -2113,22 +2202,6 @@
"type": "github"
}
},
"nixpkgs_9": {
"locked": {
"lastModified": 1748929857,
"narHash": "sha256-lcZQ8RhsmhsK8u7LIFsJhsLh/pzR9yZ8yqpTzyGdj+Q=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "c2a03962b8e24e669fb37b7df10e7c79531ff1a4",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixt": {
"inputs": {
"flake-compat": "flake-compat_4",
@ -2225,7 +2298,7 @@
"nswitch-rcm-nix": {
"inputs": {
"flake-parts": "flake-parts_3",
"nixpkgs": "nixpkgs_17"
"nixpkgs": "nixpkgs_18"
},
"locked": {
"lastModified": 1721304043,
@ -2244,7 +2317,7 @@
"nur": {
"inputs": {
"flake-parts": "flake-parts_4",
"nixpkgs": "nixpkgs_18"
"nixpkgs": "nixpkgs_19"
},
"locked": {
"lastModified": 1763996502,
@ -2476,7 +2549,7 @@
"inputs": {
"flake-compat": "flake-compat_7",
"gitignore": "gitignore_4",
"nixpkgs": "nixpkgs_19"
"nixpkgs": "nixpkgs_20"
},
"locked": {
"lastModified": 1763988335,
@ -2500,11 +2573,13 @@
"emacs-overlay": "emacs-overlay",
"flake-parts": "flake-parts",
"home-manager": "home-manager",
"hydra": "hydra",
"impermanence": "impermanence",
"lanzaboote": "lanzaboote",
"microvm": "microvm",
"niri-flake": "niri-flake",
"nix-darwin": "nix-darwin",
"nix-eval-jobs": "nix-eval-jobs",
"nix-index-database": "nix-index-database",
"nix-minecraft": "nix-minecraft",
"nix-on-droid": "nix-on-droid",
@ -2514,7 +2589,7 @@
"nixos-generators": "nixos-generators",
"nixos-hardware": "nixos-hardware",
"nixos-images": "nixos-images",
"nixpkgs": "nixpkgs_16",
"nixpkgs": "nixpkgs_17",
"nixpkgs-dev": "nixpkgs-dev",
"nixpkgs-kernel": "nixpkgs-kernel",
"nixpkgs-stable": "nixpkgs-stable_3",
@ -2649,7 +2724,7 @@
"blobs": "blobs",
"flake-compat": "flake-compat_8",
"git-hooks": "git-hooks",
"nixpkgs": "nixpkgs_20"
"nixpkgs": "nixpkgs_21"
},
"locked": {
"lastModified": 1763564778,
@ -2685,7 +2760,7 @@
},
"sops": {
"inputs": {
"nixpkgs": "nixpkgs_21"
"nixpkgs": "nixpkgs_22"
},
"locked": {
"lastModified": 1764483358,
@ -2719,7 +2794,7 @@
},
"spicetify-nix": {
"inputs": {
"nixpkgs": "nixpkgs_22",
"nixpkgs": "nixpkgs_23",
"systems": "systems_5"
},
"locked": {
@ -2823,7 +2898,7 @@
"firefox-gnome-theme": "firefox-gnome-theme",
"flake-parts": "flake-parts_5",
"gnome-shell": "gnome-shell",
"nixpkgs": "nixpkgs_23",
"nixpkgs": "nixpkgs_24",
"nur": "nur_2",
"systems": "systems_6",
"tinted-foot": "tinted-foot",
@ -2849,7 +2924,7 @@
"swarsel-nix": {
"inputs": {
"flake-parts": "flake-parts_6",
"nixpkgs": "nixpkgs_24",
"nixpkgs": "nixpkgs_25",
"systems": "systems_7"
},
"locked": {
@ -3100,7 +3175,7 @@
},
"treefmt-nix": {
"inputs": {
"nixpkgs": "nixpkgs_25"
"nixpkgs": "nixpkgs_26"
},
"locked": {
"lastModified": 1762938485,
@ -3118,7 +3193,7 @@
},
"vbc-nix": {
"inputs": {
"nixpkgs": "nixpkgs_26",
"nixpkgs": "nixpkgs_27",
"systems": "systems_9"
},
"locked": {
@ -3196,7 +3271,7 @@
"inputs": {
"crane": "crane_3",
"flake-utils": "flake-utils_8",
"nixpkgs": "nixpkgs_27",
"nixpkgs": "nixpkgs_28",
"rust-overlay": "rust-overlay_3"
},
"locked": {

View file

@ -11,6 +11,20 @@
};
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
hydra.url = "github:nixos/hydra/nix-2.30";
# hydra.inputs.nix.follows = "nix";
hydra.inputs.nix-eval-jobs.follows = "nix-eval-jobs";
# nix = {
# url = "github:NixOS/nix/2.30-maintenance";
# # We want to control the deps precisely
# flake = false;
# };
nix-eval-jobs = {
url = "github:nix-community/nix-eval-jobs/v2.30.0";
# We want to control the deps precisely
flake = false;
};
smallpkgs.url = "github:nixos/nixpkgs/08fcb0dcb59df0344652b38ea6326a2d8271baff?narHash=sha256-HXIQzULIG/MEUW2Q/Ss47oE3QrjxvpUX7gUl4Xp6lnc%3D&shallow=1";
nixpkgs-dev.url = "github:Swarsel/nixpkgs/main";
nixpkgs-kernel.url = "github:NixOS/nixpkgs/063f43f2dbdef86376cc29ad646c45c46e93234c?narHash=sha256-6m1Y3/4pVw1RWTsrkAK2VMYSzG4MMIj7sqUy7o8th1o%3D"; #specifically pinned for kernel version

View file

@ -26,7 +26,12 @@
isNixos = true;
isLinux = true;
isCloud = true;
proxyHost = "twothreetunnel";
server = {
wireguard = {
isClient = true;
serverName = "twothreetunnel";
};
garage = {
data_dir = {
capacity = "150G";
@ -49,10 +54,12 @@
};
swarselmodules.server = {
ssh-builder = lib.mkDefault true;
postgresql = lib.mkDefault true;
attic = lib.mkDefault true;
garage = lib.mkDefault true;
wireguard = true;
ssh-builder = true;
postgresql = true;
attic = true;
garage = true;
hydra = true;
dns-hostrecord = true;
};

File diff suppressed because one or more lines are too long

View file

@ -32,6 +32,7 @@
swarselmodules.server = {
mailserver = true;
dns-hostrecord = true;
postgresql = true;
};
swarselprofiles = {

View file

@ -1,5 +1,5 @@
{
"data": "ENC[AES256_GCM,data:nIgv3b+6o5Ce9X9xZtBK62f6dgsAGLPqq7aVFCw2qjD9UiHCrAY9vTn5NSW2O2pbLAfx6h7falS3/0yU+AkJ2H3zhxBy7ZxQ0m9dLoQGrYY/E9Z45xZmdFRxtzexCaxr2DxbP8haJKomQ22cHk07HGsrEZ/CFGkyjRxUr3Y4rewgZPBXahVtM75mWbNpVGApc8cs/W4JbjuXw3qlCQcACz8sZVPHKCjbEypypo6nTmU7NO7worrAJ2QgU75oGJ9g96wp9paFMEDofVp2Y25IVYReGg8T1Qi/kTcZzfzGfSpEwnQBB/ZCW6gNYhMK3shfB8DxKy6+romVXm1K+/0yUmwsCM8xC5zJX0GsO8Uu63YFrW/Y2E6aYZfBHdIgfy4lYOFKC2o0ixirw9EO8HyfsDt47QYB970vLPjYZfKNAZBgltbV3KPsOHxmgiZbTbAl0cb9zRc+jV2voH9T5VhFiUWdfaLBY1HUAVAjU7h62uZoCsi1HWyAroEROKS96npTD+3/vHehYuEGBf1IxYnLwHnKeqsr/Bqoukf3OecOH2EkMTTFQ7E0k9s0keRypoHmeYIh2a3dRcaXXbNEgiAMfabhgUh1NNcYKSZhcIekN8WN8azXjbVIrfEakJ8S+PUf5fJdspN/3Ppm06fDLv7yLHnLc8Eae2COOR8vYKIo3Onu4doxNjisfpHujLXYaCGhWpINEGWF7fkeC1B7,iv:v9MxvhcHg+P00UnOWujSgVlMNcOnDm/gK8kNcN54E2E=,tag:XnPMzsDeGJMt9yv6GnFzqg==,type:str]",
"data": "ENC[AES256_GCM,data:GB11Medb866IeeAeZGNRWO7ckMoNO1DACgP3bLgKhJ2ZYZa+Xkl5FUR6sZTBHJInSODpnOIMZWcV+ZjyRbQHJvvYxt1wJxcDC9fBVPnhoJATbQrV0zQ7XQBlfYyUhzvQ0w4lB+G5sbWeBkVQDwGhNoMxLaPt52Vg3uW0Vq42VIZZkpeWaJtGVDXoMIHCTIz2K/sC7JafRoE25a74i5XSrd2hxvvRFDQA1PFzH6JGguRqOXroqS1M1QNF3DEugsNhl3nwgc9bjLeSzvGdc8cCmUsS4LDITjPBJb4F/2mWqC/o1qUA4rEbgM/jTve3NInptgIUQiyPkHxZCtlU6MK5v5K0idI8njSolvqofy8j85YccsPPpOoQ06NPAUMa9hN0Jv+DpnyjUJAuf74JFzFP4kEMh+a9/6nVB/8cMeQATwt5b9Lbvr7zIZA5PMt1wOVDwAosZigMm6oUpDyYOjSlCvOgvEuojHDR7V6HHYd7mzg8AnIQyHa8iWR/A8/h+hzru5elb6H6rTwKaGW+jisDxRrsBsqxOWQrMrHZyhK3ppTc+IIDdIpKfe1QfVGnhH/cWXLE7YlG80fh48PKwp55azKfb76fDxQHJ4mx3PMHf1dF1bM/D6zGvsMcgIjZTO7xoVTZUZ/j7jiKHUpZnkciGfD9mJZKNGP80DMSgVDhVDUVBrZVCVwqbfksUob6bwU5nT5MSrlmY9Wj70uOl+VGLAaD0WF4T01qB/FBxoFBoYQJ+EIG,iv:5ZEu/YUvgNNgmxx9p/zurljFHRVRuKErhGhZpv/9XVk=,tag:ZFpqY1ewgJ8BLg9tnQc35w==,type:str]",
"sops": {
"age": [
{
@ -7,8 +7,8 @@
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBJR1ZPZFUxRTh0QjB6UDJ4\nOFd2c2lFejhHck5UdUxVbmFFbVRYNEJaSzJZCkNxbndVVThObDkxUmx2WW9ESzhh\na2o0LzFCbWdJVlRIV00rTVUwTktoek0KLS0tIC9qalVvZmpGQXZsV3RIYWRPbmRY\nam80NkRkT2l0ak8wV3pTSW9kSC9nZ3cKCH8eEMmku6WMliEDdAiW2Lk1jAGH9SoP\nWQ5Y6e90jEnp8XbGE7KYiG+jy5fHSc6Y5/YyMmi/b9bF9AhmRT6rdw==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2025-11-28T10:50:22Z",
"mac": "ENC[AES256_GCM,data:lwkkp8YSzX8NM7E65kmPpF/q9Vn+FnCTeePLswDH6AVgndo/7QOy0GtJeXmiwt2YsA4AhRqxexWl2R8tjEysP35pyfQJ4vEkVi+V2tEnoLgftriNJzpoeVuRNXLxTPhPezOZgAcTDDL4yyqJXpcFj0PE1DPHKxazT28BoilaBYE=,iv:3dcAqkw/y6rAPL8wb5iewz37S4xszYFGHxvQiQ98sLk=,tag:SEmbptei6GrTXXyb7zwrIg==,type:str]",
"lastmodified": "2025-12-05T09:21:59Z",
"mac": "ENC[AES256_GCM,data:S0o8zMcZ7cVmhuQ+FyC73T2USIEGryy3v61xXafd63pymEjJiOwgLZk0+nQQii+qKzwFcXNJIOjEjWyHhprcq+2hha79unEH6nfxAFjqyKdhLzFzmP73ML0vB7Fbzl5mEDyc++v2bsH/6J8UakXCkhRTUSjyuotxIChjU0YjTKM=,iv:dzGQH3HyF3lTWYhU6Mv81WcXilYVBMc++ZK5nPSPBVw=,tag:dnsxa1XnUNdZd7XIxmTgWQ==,type:str]",
"pgp": [
{
"created_at": "2025-11-23T15:25:41Z",

View file

@ -1,5 +1,5 @@
{
"data": "ENC[AES256_GCM,data:LZ0+D88y3gJk9OD40ko+msYTB9KUkBlFAup1+rcqthZ5l78mKyMoNR1leBf0AaraKft/9FfGSKT26e9I+Hd62XvGid2VzenR5TpVptm4+KLMBgHSUjcSiO8dl1ZrLOYD9T4vrBlVgnmhjotLMjmsQLNJwXiCuTqe3oE3N6C4J4nqBY0YKeJKoNEqb1oQL81nGgWdncEoRBhSZMLTaYApjqRCzzwlcL366Im1UebHmCb89GMUuHJrBudaiyf8gNOpQiGMFBpLCJZ2AwD78Ob91ELj5vKgv07siY44GvPP8nr7ryo3xThrcd9kde9IqJMLFh70lVM8ULztyYzxLsD0qkaAza4U0649+9UYmoA9grxkRbXtJgphjyxmxFmx2qPxx69A+PSr7l6fLaqV/B70RyXKOWxYPvkGdRW44HZKblcRUC24EjzpllqRJJRCspAUOzo2tHBvMwx8znQdjfGlpa2gSZf21Rx41qQQ7NlHt1wH1E+Twmte6SSd8EoSqdrCmNvnkuRK5tv8fgWxEXyy/3w97YeKjmjgTBqp4yhWLG5GXE2oO9WaQIYC1rbNcjGeBKJutY7fnuVZOWQPyqdDR058fGwznVRqyRxseXLPkES/4/ay0i3Za4C6fmAmiL3znQ+j39HXoFvn4GKig2PpJ/o1W2Cp0s/TqgVT+O/SmRv+VO4g4nZvqTPrXAFSj+dcoRUpof/Y+PGTsFc8WLjDndPqKhq7ApGhHnj+5Dh6dYJV07a+8Mfo6qecEGKhTwnTSCE0tuANI69/2kElExv+RJhbQLFNZ5Q346f0xkhm1Gggd1rPBONJEAm6bu6pBN5QSnpcLIDX5Z2pNIHjVvjcFz9beMbSA3HmEkEX1tEUF8Q4xNmo0h8F7T33V4E9KRRPlz8kM1lBhfnz4lj5cmTB7DCUCVpAm4Q9eDmLtpVdpic3HXmAX+LP+kiFNPUiJJH5En42MSsX/qDT4knwrcsCw7dIrpV3XsnDJ9tifZvOxfiRwRZplu8IJ9hvw9kBUDKUaxrkAw+B1PzmBOE4w19a0fh1ah0MWp7bNopEYDfrtip+FiHUSA5CzqggL6BExFmIffcUvh/Be579gRXzTEs2fhXzodJw4FF8HiyN2QPY6Irvwgs4TfBDH3btaVHvQV8nXE90s5u7PAkdYQ5UEzZePDu0QbbL6rDUk+GmzA04dEWeWfRhxNZ1MNXADqeF9kRCEmoiRANAvi2BK1b6oYQegALbZNm+xGyE5UvWQ6ZiZ4O8MTGzDiDsgnxvLRcgCbjDSC5lhwCd0elFRpeuZMAeE5apGdquLiBHaPJo8mmkE8nBc0HSf/JnKXDHN1NI0FXl14LM/Qm3Z7Mp/8tRpB5RA2AfndZsaAilBwFAqMIbJv21EGZ1UBFaG9SK5TJHO6A2KIE8rZ8OQ8TPbZORW1XfJI7y8OXWW8X1cUfCTEfd8MC4UmDf7s6XWTPVZPQ70fxhaStj+yypGQ2iJoKreC58oN9QFXdgBq6JTXRK3W4AwQoYoK6jNWG/y5wVDlPYKKM5O9fn/ODk6aFPmFs7pdfES7jOxKTAQBcZzgEKToNSvCdT49nhSe/tCBNxr5WNF/hLzIJXgZvqWXEaRz/rfIZCwf7FlqlpMT7XLXNktjItEhis+nEwz5NNdm0RzGVNE2GjaiFr8WQaF6AuoellY3jSWNSOk+jNAg0wBgj4FoklaH5JzQ9cRAKYu4xEC9amYgGGl9x4nWBTLSHfj5o5B5Yj0hBKaSDI7gUFgZNzaC1NgqxH2rhqy9pZO4YcclRh4diJ/3grYd/n8+vLr8Faa/v+68sIyvsLGklGS6IEJmipXWHqng4U+id5zU9xf7o99qZnIw==,iv:vLzkbn3IYrD+L6iwyRLPTtxLrrIKTMzIIZyoGgvXKxU=,tag:Hj2CG+kEnyVt9xlELVGkPA==,type:str]",
"data": "ENC[AES256_GCM,data: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,iv:tRfCSNz1Jm1qQFXt7gVEmd8VxWsqYivXtF/u+J+mnpk=,tag:3V6uLwgc0/XZvk4en2KfIw==,type:str]",
"sops": {
"age": [
{
@ -7,8 +7,8 @@
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA3UFZTaXFNdjF2UmRFd3VL\nY2pZZ3ZaRkhZSjdVUjIraHV5ZlNaNGtwM3k0CkZ4OVRFcmR3MFBDcmdsbWFId3Iy\nVzQyUGI1eG44d3JFL2NvZEg4NnduT2cKLS0tIEdhOEZETk9nRTlVbmJ5UW9GalVx\nS00yaUpJZVFVNThFei8yRzJYejRkYk0Kf6Z8WnG8phRtFIUWIPys3PW0OImhAcF+\nUFLuL4Qr7zWaeItCRieYCs1yBn7KbUJHZNkJcvnkYW50NYvlEa8wBw==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2025-12-04T08:30:09Z",
"mac": "ENC[AES256_GCM,data:AeuHRN9aIfEj18uBBOR4BKGExANsUGZuxWI7K8dX+qhVLfNmsXv3ABM3FoaxhUIAyU/3mfFSK2o4SzHhAEXOo5+aN4gppvFecibSFltgME5+rSWyH9U44YB1v3MWiZkjMHuZJcyM1XDX1sLZ5TMsH72/Cu18w0u7m+QsnJ6Lc+Q=,iv:2ZIeMPnH25EAF2Xtf06ZRsCOILhn7sSWtakjl6KxDos=,tag:V8Sc6BNyi49giz5g3BpAUA==,type:str]",
"lastmodified": "2025-12-05T10:12:13Z",
"mac": "ENC[AES256_GCM,data:2uJJUnYNM7kNysGtiwmlctwjrE2ZAropTNOcph4K51VUr48UZcwYQTPpdJEqEIGiNq4pcT1W5h/ghYFUAZdZdleOKrh+tLnQ5LIib/A9WGkW44m3i6dCVlTXRt+MhrVfJXffRTMM101JoMCq8V00juuFYcDxNhI3uvKqwxXSbyo=,iv:hjMu3oSlc9gKi8cO0RX4leht40PUthldYpLwZKdX4Xw=,tag:n08RFXUHkXyUgE5jB0KZxw==,type:str]",
"pgp": [
{
"created_at": "2025-12-02T14:59:33Z",

View file

@ -483,7 +483,7 @@ in
};
Service = {
ExecStart = "${pkgs._1password-gui}/bin/1password";
ExecStart = "${pkgs._1password-gui-beta}/bin/1password";
};
};

View file

@ -37,6 +37,7 @@ in
}
];
};
programs.ssh = {
knownHosts = {
nixbuild = {

View file

@ -75,6 +75,7 @@ in
_1password.enable = true;
_1password-gui = {
enable = true;
package = pkgs._1password-gui-beta;
polkitPolicyOwners = [ "${mainUser}" ];
};
};

View file

@ -1,4 +1,4 @@
{ lib, config, globals, dns, confLib, ... }:
{ lib, config, pkgs, globals, dns, confLib, ... }:
let
inherit (confLib.gen { name = "attic"; port = 8091; }) serviceName serviceDir servicePort serviceAddress serviceDomain serviceProxy proxyAddress4 proxyAddress6;
inherit (config.swarselsystems) mainUser isPublic sopsFile;
@ -36,8 +36,33 @@ in
};
};
networking.firewall.allowedTCPPorts = [ servicePort ];
services.atticd = {
enable = true;
# NOTE: remove once https://github.com/zhaofengli/attic/pull/268 is merged
package = pkgs.attic-server.overrideAttrs
(oldAttrs: {
patches = (oldAttrs.patches or [ ]) ++ [
(pkgs.writeText "remove-s3-checksums.patch" ''
diff --git a/server/src/storage/s3.rs b/server/src/storage/s3.rs
index 1d5719f3..036f3263 100644
--- a/server/src/storage/s3.rs
+++ b/server/src/storage/s3.rs
@@ -278,10 +278,6 @@ impl StorageBackend for S3Backend {
CompletedPart::builder()
.set_e_tag(part.e_tag().map(str::to_string))
.set_part_number(Some(part_number as i32))
- .set_checksum_crc32(part.checksum_crc32().map(str::to_string))
- .set_checksum_crc32_c(part.checksum_crc32_c().map(str::to_string))
- .set_checksum_sha1(part.checksum_sha1().map(str::to_string))
- .set_checksum_sha256(part.checksum_sha256().map(str::to_string))
.build()
})
.collect::<Vec<_>>();
'')
];
});
environmentFile = config.sops.templates."attic.env".path;
settings = {
listen = "[::]:${builtins.toString servicePort}";
@ -59,12 +84,10 @@ in
bucket = serviceName;
# attic must be patched to never serve pre-signed s3 urls directly
# otherwise it will redirect clients to this localhost endpoint
endpoint = "http://127.0.0.1:3900";
endpoint = "http://127.0.0.1:3900"; # garage port
} else {
type = "local";
path = serviceDir;
# attic must be patched to never serve pre-signed s3 urls directly
# otherwise it will redirect clients to this localhost endpoint
};
garbage-collection = {
@ -73,11 +96,11 @@ in
};
chunking = {
nar-size-threshold = if config.swarselmodules.server.garage then 0 else 64 * 1024; # 64 KiB
nar-size-threshold = if config.swarselmodules.server.garage then 0 else 64 * 1024; # garage using s3
min-size = 16 * 1024; # 16 KiB
avg-size = 64 * 1024; # 64 KiB
max-size = 256 * 1024; # 256 KiBize = 262144;
min-size = 16 * 1024;
avg-size = 64 * 1024;
max-size = 256 * 1024;
};
};
};
@ -109,7 +132,7 @@ in
};
virtualHosts = {
"${serviceDomain}" = {
enableACME = true;
useACMEHost = globals.domains.main;
forceSSL = true;
acmeRoot = null;
oauth2.enable = false;
@ -118,6 +141,11 @@ in
proxyPass = "http://${serviceName}";
extraConfig = ''
client_max_body_size 0;
client_body_timeout 600s;
proxy_connect_timeout 600s;
proxy_send_timeout 600s;
proxy_read_timeout 600s;
proxy_request_buffering off;
'';
};
};

View file

@ -1,6 +1,6 @@
{ self, lib, config, pkgs, dns, globals, confLib, ... }:
let
inherit (confLib.gen { name = "croc"; }) serviceName serviceDomain proxyAddress4 proxyAddress6;
inherit (confLib.gen { name = "croc"; proxy = config.node.name; }) serviceName serviceDomain proxyAddress4 proxyAddress6;
servicePorts = [
9009
9010

View file

@ -19,8 +19,8 @@ let
garageAdminPort = 3903;
garageK2VPort = 3904;
adminDomain = "${subDomain}admin.${baseDomain}";
webDomain = "${subDomain}web.${baseDomain}";
adminDomain = "${subDomain}-admin.${baseDomain}";
webDomain = "${subDomain}-web.${baseDomain}";
in
{
options = {
@ -71,12 +71,14 @@ in
}
];
networking.firewall.allowedTCPPorts = [ servicePort 3901 3902 3903 3904 ];
nodes.stoicclub.swarselsystems.server.dns.${baseDomain}.subdomainRecords = {
"${subDomain}" = dns.lib.combinators.host proxyAddress4 proxyAddress6;
"${subDomain}admin" = dns.lib.combinators.host proxyAddress4 proxyAddress6;
"${subDomain}web" = dns.lib.combinators.host proxyAddress4 proxyAddress6;
"${subDomain}-admin" = dns.lib.combinators.host proxyAddress4 proxyAddress6;
"${subDomain}-web" = dns.lib.combinators.host proxyAddress4 proxyAddress6;
"*.${subDomain}" = dns.lib.combinators.host proxyAddress4 proxyAddress6;
"*.${subDomain}web" = dns.lib.combinators.host proxyAddress4 proxyAddress6;
"*.${subDomain}-web" = dns.lib.combinators.host proxyAddress4 proxyAddress6;
};
sops = {
@ -307,10 +309,6 @@ in
};
};
security.acme.certs."${webDomain}" = {
domain = "*.${webDomain}";
};
nodes.${serviceProxy}.services.nginx = {
upstreams = {
${serviceName} = {
@ -331,7 +329,7 @@ in
};
virtualHosts = {
"${adminDomain}" = {
enableACME = true;
useACMEHost = globals.domains.main;
forceSSL = true;
acmeRoot = null;
oauth2.enable = false;
@ -342,7 +340,7 @@ in
};
};
"*.${webDomain}" = {
useACMEHost = webDomain;
useACMEHost = globals.domains.main;
forceSSL = true;
acmeRoot = null;
oauth2.enable = false;
@ -354,7 +352,7 @@ in
};
"${serviceDomain}" = {
serverAliases = [ "*.${serviceDomain}" ];
enableACME = true;
useACMEHost = globals.domains.main;
forceSSL = true;
acmeRoot = null;
oauth2.enable = false;
@ -363,6 +361,11 @@ in
proxyPass = "http://${serviceName}";
extraConfig = ''
client_max_body_size 0;
client_body_timeout 600s;
proxy_connect_timeout 600s;
proxy_send_timeout 600s;
proxy_read_timeout 600s;
proxy_request_buffering off;
'';
};
};

View file

@ -0,0 +1,133 @@
{ inputs, lib, config, globals, dns, confLib, ... }:
let
inherit (confLib.gen { name = "hydra"; port = 8002; }) serviceName servicePort serviceUser serviceGroup serviceAddress serviceDomain serviceProxy proxyAddress4 proxyAddress6;
inherit (config.swarselsystems) sopsFile;
in
{
options = {
swarselmodules.server.${serviceName} = lib.mkEnableOption "enable ${serviceName} on server";
};
config = lib.mkIf config.swarselmodules.server.${serviceName} {
nodes.stoicclub.swarselsystems.server.dns.${globals.services.${serviceName}.baseDomain}.subdomainRecords = {
"${globals.services.${serviceName}.subDomain}" = dns.lib.combinators.host proxyAddress4 proxyAddress6;
};
globals.services.${serviceName} = {
domain = serviceDomain;
inherit proxyAddress4 proxyAddress6;
};
sops = {
secrets = {
nixbuild-net-key = { mode = "0600"; };
hydra-pw = { inherit sopsFile; owner = serviceUser; group = serviceGroup; mode = "0440"; };
};
templates = {
"hydra-env" = {
content = ''
HYDRA_PW="${config.sops.placeholder.hydra-pw}"
'';
owner = serviceUser;
group = serviceGroup;
mode = "0440";
};
};
};
services.hydra = {
enable = true;
package = inputs.hydra.packages.${config.node.arch}.hydra;
port = servicePort;
hydraURL = "https://${serviceDomain}";
listenHost = "*";
notificationSender = "hydra@${globals.domains.main}";
minimumDiskFreeEvaluator = 20; # 20G
minimumDiskFree = 20; # 20G
useSubstitutes = true;
smtpHost = globals.services.mailserver.domain;
buildMachinesFiles = [
"/etc/nix/machines"
];
extraConfig = ''
using_frontend_proxy 1
'';
};
systemd.services.hydra-user-setup = {
description = "Create admin user for Hydra";
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
User = "hydra";
EnvironmentFile = [
config.sops.templates.hydra-env.path
];
};
wantedBy = [ "multi-user.target" ];
requires = [ "hydra-init.service" ];
after = [ "hydra-init.service" ];
environment = lib.mkForce config.systemd.services.hydra-init.environment;
script = ''
set -eu
if [ ! -e ~hydra/.user-setup-done ]; then
/run/current-system/sw/bin/hydra-create-user admin --full-name 'admin' --email-address 'admin@${globals.domains.main}' --password "$HYDRA_PW" --role admin
touch ~hydra/.user-setup-done
fi
'';
};
environment.persistence."/persist".directories = lib.mkIf config.swarselsystems.isImpermanence [
];
nix = {
settings.builders-use-substitutes = true;
distributedBuilds = true;
buildMachines = [
{
hostName = "localhost";
protocol = null;
system = config.node.arch;
supportedFeatures = [ "kvm" "nixos-test" "big-parallel" "benchmark" ];
maxJobs = 4;
}
];
};
networking.firewall.allowedTCPPorts = [ servicePort ];
programs.ssh = {
extraConfig = ''
StrictHostKeyChecking no
'';
};
nodes.${serviceProxy}.services.nginx = {
upstreams = {
${serviceName} = {
servers = {
"${serviceAddress}:${builtins.toString servicePort}" = { };
};
};
};
virtualHosts = {
"${serviceDomain}" = {
enableACME = true;
forceSSL = true;
acmeRoot = null;
oauth2.enable = false;
locations = {
"/" = {
proxyPass = "http://${serviceName}";
extraConfig = ''
client_max_body_size 0;
proxy_set_header X-Request-Base /hydra;
'';
};
};
};
};
};
};
}

View file

@ -2,7 +2,7 @@
let
inherit (config.swarselsystems) sopsFile;
inherit (confLib.gen { name = "mailserver"; dir = "/var/lib/dovecot"; user = "virtualMail"; group = "virtualMail"; port = 443; }) serviceName serviceDir servicePort serviceUser serviceGroup serviceDomain serviceProxy proxyAddress4 proxyAddress6;
inherit (config.repo.secrets.local.mailserver) user1 alias1_1 alias1_2 alias1_3 alias1_4 user2 alias2_1 user3;
inherit (config.repo.secrets.local.mailserver) user1 alias1_1 alias1_2 alias1_3 alias1_4 user2 alias2_1 alias2_2 user3;
baseDomain = globals.domains.main;
in
{
@ -31,7 +31,7 @@ in
{ directory = "/var/sieve"; user = serviceUser; group = serviceGroup; mode = "0770"; }
{ directory = "/var/dkim"; user = "rspamd"; group = "rspamd"; mode = "0700"; }
{ directory = serviceDir; user = serviceUser; group = serviceGroup; mode = "0700"; }
{ directory = "/var/lib/postgresql"; user = "postgres"; group = "postgres"; mode = "0750"; }
# { directory = "/var/lib/postgresql"; user = "postgres"; group = "postgres"; mode = "0750"; }
{ directory = "/var/lib/rspamd"; user = "rspamd"; group = "rspamd"; mode = "0700"; }
{ directory = "/var/lib/roundcube"; user = "roundcube"; group = "roundcube"; mode = "0700"; }
{ directory = "/var/lib/redis-rspamd"; user = "redis-rspamd"; group = "redis-rspamd"; mode = "0700"; }
@ -63,6 +63,7 @@ in
hashedPasswordFile = config.sops.secrets.user2-hashed-pw.path;
aliases = [
"${alias2_1}@${baseDomain}"
"${alias2_2}@${baseDomain}"
];
sendOnly = true;
};

View file

@ -1,6 +1,6 @@
{ lib, config, pkgs, globals, dns, confLib, ... }:
let
inherit (confLib.gen { name = "minecraft"; port = 25565; dir = "/opt/minecraft"; }) serviceName servicePort serviceDir serviceDomain proxyAddress4 proxyAddress6;
inherit (confLib.gen { name = "minecraft"; port = 25565; dir = "/opt/minecraft"; proxy = config.node.name; }) serviceName servicePort serviceDir serviceDomain proxyAddress4 proxyAddress6;
inherit (config.swarselsystems) mainUser;
worldName = "${mainUser}craft";
in

View file

@ -3,7 +3,7 @@ with dns.lib.combinators; {
SOA = {
nameServer = "soa";
adminEmail = "admin@${globals.domains.main}"; # this option is not parsed as domain (we cannot just write "admin")
serial = 2025120501; # update this on changes for secondary dns
serial = 2025120506; # update this on changes for secondary dns
};
useOrigin = false;

View file

@ -31,5 +31,13 @@ in
};
};
services.openssh = {
settings = {
AllowUsers = [
"builder"
];
};
};
};
}

View file

@ -117,7 +117,7 @@ in
PresharedKeyFile = config.sops.secrets."wireguard-${serverName}-${config.node.name}-presharedKey".path;
Endpoint = "server.${serverName}.${globals.domains.main}:${toString servicePort}";
# Access to the whole network is routed through our entry node.
# PersistentKeepalive = 25;
PersistentKeepalive = 25;
AllowedIPs =
let
wgNetwork = globals.networks."${serverNetConfigPrefix}-wg";

File diff suppressed because one or more lines are too long