Upgrade inputs to 24.11 #16

Merged
fabianhauser merged 21 commits from upgrade-2411 into main 2024-12-13 21:33:08 +01:00
60 changed files with 1212 additions and 1328 deletions

View file

@ -27,7 +27,6 @@
- [calanda](nixos-configurations/calanda/README.md) - [calanda](nixos-configurations/calanda/README.md)
- [cyprianspitz](nixos-configurations/cyprianspitz/README.md) - [cyprianspitz](nixos-configurations/cyprianspitz/README.md)
- [fulberg](nixos-configurations/fulberg/README.md)
- [lindberg](nixos-configurations/lindberg/README.md) - [lindberg](nixos-configurations/lindberg/README.md)
- [stompert](nixos-configurations/stompert/README.md) - [stompert](nixos-configurations/stompert/README.md)
- [tierberg](nixos-configurations/tierberg/README.md) - [tierberg](nixos-configurations/tierberg/README.md)

View file

@ -1,58 +0,0 @@
{
pkgs,
lib,
config,
...
}:
let
hostName = config.networking.hostName;
netName = "backplane";
netConfig = config.qois.meta.network.virtual.${netName};
hostNetConfig = netConfig.hosts.${hostName};
wgDefaultPort = 51825;
in
{
sops.secrets."wgautomesh/gossip-secret".restartUnits = [ "wgautomesh.service" ];
networking.wireguard.enable = true;
networking.wireguard.interfaces."wg-${netName}" = {
ips = [ "${hostNetConfig.v4.ip}/${builtins.toString netConfig.v4.prefixLength}" ];
listenPort = if hostNetConfig.endpoint != null then hostNetConfig.endpoint.port else wgDefaultPort;
privateKeyFile = "/secrets/wireguard/private/${netName}";
generatePrivateKeyFile = true;
};
systemd.network.wait-online.ignoredInterfaces = [ "wg-${netName}" ];
networking.firewall.allowedUDPPorts =
if hostNetConfig.endpoint != null then [ hostNetConfig.endpoint.port ] else [ wgDefaultPort ];
# Configure wgautomesh to setup peers. Make sure that the name is not used in the VPN module
services.wgautomesh = {
enable = true;
gossipSecretFile = builtins.toString config.sops.secrets."wgautomesh/gossip-secret".path;
openFirewall = true;
logLevel = "info";
settings = {
interface = "wg-${netName}";
# Map meta network configuration to the format of wgautomesh and filter out peers with endpoints
peers =
let
reachableHosts = lib.filterAttrs (
peerHostName: peerConfig: peerHostName != hostName # Not this host
) netConfig.hosts;
in
lib.mapAttrsToList (_: peerConfig: {
address = peerConfig.v4.ip;
endpoint =
if peerConfig.endpoint != null then
with peerConfig.endpoint; "${fqdn}:${builtins.toString port}"
else
null;
pubkey = peerConfig.publicKey;
}) reachableHosts;
};
};
systemd.services.wgautomesh.requires = [ "wireguard-wg-backplane.service" ];
}

View file

@ -52,27 +52,32 @@
# Package management # Package management
nix = { nix = {
settings = { settings =
trusted-users = [ let
"root"
"@wheel"
];
substituters = [ substituters = [
"https://${inputs.self.nixosConfigurations.lindberg-build.config.qois.nixpkgs-cache.hostname}?priority=39" "https://${inputs.self.nixosConfigurations.lindberg-build.config.qois.nixpkgs-cache.hostname}?priority=39"
"https://cache.nixos.org?priority=40" "https://cache.nixos.org?priority=40"
"https://attic.qo.is/qois-infrastructure" "https://attic.qo.is/qois-infrastructure"
]; ];
in
{
trusted-users = [
"root"
"@wheel"
];
trusted-public-keys = [ trusted-public-keys = [
"cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=" "cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY="
"qois-infrastructure:lh35ymN7Aoxm5Hz0S6JusxE+cYzMU+x9OMKjDVIpfuE=" "qois-infrastructure:lh35ymN7Aoxm5Hz0S6JusxE+cYzMU+x9OMKjDVIpfuE="
]; ];
trusted-substituters = substituters; # For hosts that limit the subst list
inherit substituters;
}; };
gc = { gc = {
automatic = true; automatic = true;
dates = "weekly"; dates = "weekly";
options = "--delete-older-than 90d"; options = "--delete-older-than 90d";
}; };
package = pkgs.nixFlakes; package = pkgs.nixVersions.stable;
extraOptions = '' extraOptions = ''
experimental-features = nix-command flakes experimental-features = nix-command flakes
''; '';
@ -87,10 +92,6 @@
services.openssh = { services.openssh = {
enable = true; enable = true;
settings.PasswordAuthentication = false; settings.PasswordAuthentication = false;
# temporary mitigation agains CVE-2024-6387 «regreSSHion» RCE
# See https://github.com/NixOS/nixpkgs/pull/323753#issuecomment-2199762128
settings.LoginGraceTime = 0;
}; };
security.acme = { security.acme = {
@ -105,7 +106,10 @@
}; };
programs.autojump.enable = true; programs.autojump.enable = true;
programs.vim.defaultEditor = true; programs.vim = {
enable = true;
defaultEditor = true;
};
sops.defaultSopsFile = sops.defaultSopsFile =
let let

View file

@ -1,8 +1,4 @@
{ {
"fulberg": {
"hostName": "fulberg",
"sshKey": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDCG9qqpUOJ2RsohIqhMuw3YZZSrnPqhf5ayh5y0Cq/I"
},
"calanda": { "calanda": {
"hostName": "calanda", "hostName": "calanda",
"sshKey": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKdoOZcFFRXIqEWqUnwCk/kqP8DZw6/4omDefCT6aNN4" "sshKey": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKdoOZcFFRXIqEWqUnwCk/kqP8DZw6/4omDefCT6aNN4"

View file

@ -36,9 +36,6 @@
calanda = { calanda = {
v4.ip = "10.1.2.1"; v4.ip = "10.1.2.1";
}; };
fulberg = {
v4.ip = "10.1.2.2";
};
}; };
}; };
@ -46,6 +43,7 @@
v4 = { v4 = {
id = "10.1.1.0"; id = "10.1.1.0";
prefixLength = 24; prefixLength = 24;
# Note: DHCP from .2 to .249, see calanda config
}; };
domain = "plessur-lan.net.qo.is"; domain = "plessur-lan.net.qo.is";
@ -53,6 +51,7 @@
calanda = { calanda = {
v4.ip = "10.1.1.1"; v4.ip = "10.1.1.1";
}; };
cyprianspitz.v4.ip = "10.1.1.250";
}; };
}; };

View file

@ -15,7 +15,7 @@
id = "100.64.0.0"; id = "100.64.0.0";
prefixLength = 10; prefixLength = 10;
}; };
domain = "vpn.qo.is"; domain = "vpn.net.qo.is";
hosts = { }; hosts = { };
}; };
@ -27,15 +27,6 @@
domain = "backplane.net.qo.is"; domain = "backplane.net.qo.is";
hosts = { hosts = {
fulberg = {
v4.ip = "10.250.0.1";
endpoint = {
fqdn = physical-network.plessur-ext.hosts.calanda.fqdn;
port = 51821;
};
publicKey = "xcQOu+pp4ckNygcsLmJL1NmUzbbC+k3I7y+hJ9Ul4nk=";
persistentKeepalive = 25;
};
lindberg = { lindberg = {
v4.ip = "10.250.0.2"; v4.ip = "10.250.0.2";
#endpoint = { # TODO: Port forwarding #endpoint = { # TODO: Port forwarding
@ -102,7 +93,7 @@
cyprianspitz-vms-nat = { cyprianspitz-vms-nat = {
v4 = { v4 = {
id = "10.247.0.0"; id = "10.248.0.0";
prefixLength = 24; prefixLength = 24;
}; };
domain = "cyprianspitz-vms-nat.net.qo.is"; domain = "cyprianspitz-vms-nat.net.qo.is";

View file

@ -18,7 +18,7 @@ package "plessur.net.qo.is" {
] ]
node calanda node calanda
node fulberg node cyprianspitz
cloud plessurnet [ cloud plessurnet [
<i>LAN Plessur <i>LAN Plessur
@ -26,7 +26,7 @@ package "plessur.net.qo.is" {
mediaconvchur - "enp4" calanda mediaconvchur - "enp4" calanda
calanda "br0 (enp2, wlp1, wlp5)" --- plessurnet calanda "br0 (enp2, wlp1, wlp5)" --- plessurnet
calanda "enp4" -- "eno1" fulberg plessurnet -- cyprianspitz
} }
package "riedbach.net.qo.is" { package "riedbach.net.qo.is" {

View file

@ -13,7 +13,7 @@
owner = name; owner = name;
}; };
qois.postgresql.enable = true; services.postgresql.enable = true;
qois.backup-client.includePaths = [ config.services.nextcloud.home ]; qois.backup-client.includePaths = [ config.services.nextcloud.home ];
services.nextcloud = { services.nextcloud = {
@ -30,6 +30,24 @@
dbtype = "pgsql"; dbtype = "pgsql";
}; };
appstoreEnable = false;
extraApps = {
inherit (config.services.nextcloud.package.passthru.packages.apps)
calendar
contacts
deck
groupfolders
maps
memories
music
news
notes
notify_push
tasks
twofactor_webauthn
;
};
phpOptions = { phpOptions = {
"opcache.interned_strings_buffer" = "23"; "opcache.interned_strings_buffer" = "23";
}; };

View file

@ -1,53 +1,9 @@
{ {
"nodes": { "nodes": {
"attic": {
"inputs": {
"crane": "crane",
"flake-compat": "flake-compat",
"flake-parts": "flake-parts",
"nix-github-actions": "nix-github-actions",
"nixpkgs": "nixpkgs",
"nixpkgs-stable": "nixpkgs-stable"
},
"locked": {
"lastModified": 1731270564,
"narHash": "sha256-6KMC/NH/VWP5Eb+hA56hz0urel3jP6Y6cF2PX6xaTkk=",
"owner": "zhaofengli",
"repo": "attic",
"rev": "47752427561f1c34debb16728a210d378f0ece36",
"type": "github"
},
"original": {
"owner": "zhaofengli",
"repo": "attic",
"type": "github"
}
},
"crane": {
"inputs": {
"nixpkgs": [
"attic",
"nixpkgs"
]
},
"locked": {
"lastModified": 1722960479,
"narHash": "sha256-NhCkJJQhD5GUib8zN9JrmYGMwt4lCRp6ZVNzIiYCl0Y=",
"owner": "ipetkov",
"repo": "crane",
"rev": "4c6c77920b8d44cd6660c1621dea6b3fc4b4c4f4",
"type": "github"
},
"original": {
"owner": "ipetkov",
"repo": "crane",
"type": "github"
}
},
"deploy-rs": { "deploy-rs": {
"inputs": { "inputs": {
"flake-compat": "flake-compat_2", "flake-compat": "flake-compat",
"nixpkgs": "nixpkgs_2", "nixpkgs": "nixpkgs",
"utils": "utils" "utils": "utils"
}, },
"locked": { "locked": {
@ -71,11 +27,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1731274291, "lastModified": 1734088167,
"narHash": "sha256-cZ0QMpv5p2a6WEE+o9uu0a4ma6RzQDOQTbm7PbixWz8=", "narHash": "sha256-OIitVU+IstPbX/NWn2jLF+/sT9dVKcO2FKeRAzlyX6c=",
"owner": "nix-community", "owner": "nix-community",
"repo": "disko", "repo": "disko",
"rev": "486250f404f4a4f4f33f8f669d83ca5f6e6b7dfc", "rev": "d32f2d1750d61a476a236526b725ec5a32e16342",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -100,129 +56,7 @@
"type": "github" "type": "github"
} }
}, },
"flake-compat_2": {
"flake": false,
"locked": {
"lastModified": 1696426674,
"narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"flake-parts": {
"inputs": {
"nixpkgs-lib": [
"attic",
"nixpkgs"
]
},
"locked": {
"lastModified": 1722555600,
"narHash": "sha256-XOQkdLafnb/p9ij77byFQjDf5m5QYl9b2REiVClC+x4=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "8471fe90ad337a8074e957b69ca4d0089218391d",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"nix-github-actions": {
"inputs": {
"nixpkgs": [
"attic",
"nixpkgs"
]
},
"locked": {
"lastModified": 1729742964,
"narHash": "sha256-B4mzTcQ0FZHdpeWcpDYPERtyjJd/NIuaQ9+BV1h+MpA=",
"owner": "nix-community",
"repo": "nix-github-actions",
"rev": "e04df33f62cdcf93d73e9a04142464753a16db67",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "nix-github-actions",
"type": "github"
}
},
"nixpkgs": { "nixpkgs": {
"locked": {
"lastModified": 1726042813,
"narHash": "sha256-LnNKCCxnwgF+575y0pxUdlGZBO/ru1CtGHIqQVfvjlA=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "159be5db480d1df880a0135ca0bfed84c2f88353",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-nixos-stable": {
"locked": {
"lastModified": 1731239293,
"narHash": "sha256-q2yjIWFFcTzp5REWQUOU9L6kHdCDmFDpqeix86SOvDc=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "9256f7c71a195ebe7a218043d9f93390d49e6884",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-24.05",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-nixos-unstable": {
"locked": {
"lastModified": 1731139594,
"narHash": "sha256-IigrKK3vYRpUu+HEjPL/phrfh7Ox881er1UEsZvw9Q4=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "76612b17c0ce71689921ca12d9ffdc9c23ce40b2",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-stable": {
"locked": {
"lastModified": 1724316499,
"narHash": "sha256-Qb9MhKBUTCfWg/wqqaxt89Xfi6qTD3XpTzQ9eXi3JmE=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "797f7dc49e0bc7fab4b57c021cdf68f595e47841",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-24.05",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_2": {
"locked": { "locked": {
"lastModified": 1702272962, "lastModified": 1702272962,
"narHash": "sha256-D+zHwkwPc6oYQ4G3A1HuadopqRwUY/JkMwHz1YF7j4Q=", "narHash": "sha256-D+zHwkwPc6oYQ4G3A1HuadopqRwUY/JkMwHz1YF7j4Q=",
@ -238,6 +72,38 @@
"type": "github" "type": "github"
} }
}, },
"nixpkgs-nixos-stable": {
"locked": {
"lastModified": 1733808091,
"narHash": "sha256-KWwINTQelKOoQgrXftxoqxmKFZb9pLVfnRvK270nkVk=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "a0f3e10d94359665dba45b71b4227b0aeb851f8e",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-24.11",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-nixos-unstable": {
"locked": {
"lastModified": 1733940404,
"narHash": "sha256-Pj39hSoUA86ZePPF/UXiYHHM7hMIkios8TYG29kQT4g=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "5d67ea6b4b63378b9c13be21e2ec9d1afc921713",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"private": { "private": {
"inputs": { "inputs": {
"nixpkgs-nixos-unstable": [ "nixpkgs-nixos-unstable": [
@ -259,7 +125,6 @@
}, },
"root": { "root": {
"inputs": { "inputs": {
"attic": "attic",
"deploy-rs": "deploy-rs", "deploy-rs": "deploy-rs",
"disko": "disko", "disko": "disko",
"nixpkgs-nixos-stable": "nixpkgs-nixos-stable", "nixpkgs-nixos-stable": "nixpkgs-nixos-stable",
@ -272,17 +137,14 @@
"inputs": { "inputs": {
"nixpkgs": [ "nixpkgs": [
"nixpkgs-nixos-unstable" "nixpkgs-nixos-unstable"
],
"nixpkgs-stable": [
"nixpkgs-nixos-stable"
] ]
}, },
"locked": { "locked": {
"lastModified": 1731213149, "lastModified": 1733965552,
"narHash": "sha256-jR8i6nFLmSmm0cIoeRQ8Q4EBARa3oGaAtEER/OMMxus=", "narHash": "sha256-GZ4YtqkfyTjJFVCub5yAFWsHknG1nS/zfk7MuHht4Fs=",
"owner": "Mic92", "owner": "Mic92",
"repo": "sops-nix", "repo": "sops-nix",
"rev": "f1675e3b0e1e663a4af49be67ecbc9e749f85eb7", "rev": "2d73fc6ac4eba4b9a83d3cb8275096fbb7ab4004",
"type": "github" "type": "github"
}, },
"original": { "original": {

View file

@ -5,19 +5,17 @@
extra-trusted-public-keys = "qois-infrastructure:lh35ymN7Aoxm5Hz0S6JusxE+cYzMU+x9OMKjDVIpfuE="; extra-trusted-public-keys = "qois-infrastructure:lh35ymN7Aoxm5Hz0S6JusxE+cYzMU+x9OMKjDVIpfuE=";
}; };
inputs = { inputs = {
attic.url = "github:zhaofengli/attic";
deploy-rs.url = "github:serokell/deploy-rs"; deploy-rs.url = "github:serokell/deploy-rs";
disko = { disko = {
url = "github:nix-community/disko"; url = "github:nix-community/disko";
inputs.nixpkgs.follows = "nixpkgs-nixos-stable"; inputs.nixpkgs.follows = "nixpkgs-nixos-stable";
}; };
nixpkgs-nixos-unstable.url = "github:NixOS/nixpkgs/nixos-unstable"; nixpkgs-nixos-unstable.url = "github:NixOS/nixpkgs/nixos-unstable";
nixpkgs-nixos-stable.url = "github:NixOS/nixpkgs/nixos-24.05"; nixpkgs-nixos-stable.url = "github:NixOS/nixpkgs/nixos-24.11";
sops-nix = { sops-nix = {
url = "github:Mic92/sops-nix"; url = "github:Mic92/sops-nix";
inputs = { inputs = {
nixpkgs.follows = "nixpkgs-nixos-unstable"; nixpkgs.follows = "nixpkgs-nixos-unstable";
nixpkgs-stable.follows = "nixpkgs-nixos-stable";
}; };
}; };
private.url = "git+file:./private"; private.url = "git+file:./private";

View file

@ -17,5 +17,5 @@
# this value at the release version of the first install of this system. # this value at the release version of the first install of this system.
# Before changing this value read the documentation for this option # Before changing this value read the documentation for this option
# (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
system.stateVersion = "23.05"; # Did you read the comment? system.stateVersion = "24.11"; # Did you read the comment?
} }

View file

@ -4,11 +4,10 @@ let
meta = config.qois.meta; meta = config.qois.meta;
plessur-dmz-net = meta.network.physical.plessur-dmz; plessur-dmz-net = meta.network.physical.plessur-dmz;
plessur-lan-net = meta.network.physical.plessur-lan; plessur-lan-net = meta.network.physical.plessur-lan;
plessur-ext-net = meta.network.physical.plessur-ext;
getCalandaIp4 = net: net.hosts.calanda.v4.ip; getCalandaIp4 = net: net.hosts.calanda.v4.ip;
in in
{ {
imports = [ ../../defaults/backplane-net ];
networking.hostName = meta.hosts.calanda.hostName; networking.hostName = meta.hosts.calanda.hostName;
networking.domain = "ilanz.fh2.ch"; networking.domain = "ilanz.fh2.ch";
networking.enableIPv6 = false; # TODO networking.enableIPv6 = false; # TODO
@ -30,6 +29,8 @@ in
]; ];
}; };
qois.backplane-net.enable = true;
# TODO: Metaize ips # TODO: Metaize ips
services.qois.router = { services.qois.router = {
enable = true; enable = true;
@ -53,6 +54,14 @@ in
}; };
}; };
# Assign the static address to cyprianspitz (required for ssh luks unlock at this time)
services.dnsmasq.settings.dhcp-host =
let
cyprianspitzEnp0s31f6Mac = "9c:6b:00:58:6e:90";
inherit (plessur-lan-net.hosts.cyprianspitz.v4) ip;
in
"${cyprianspitzEnp0s31f6Mac},${ip}";
# DMZ # DMZ
services.unbound.settings.server = { services.unbound.settings.server = {
interface = [ plessur-dmz-net.hosts.calanda.v4.ip ]; interface = [ plessur-dmz-net.hosts.calanda.v4.ip ];
@ -66,43 +75,19 @@ in
# DMZ Portforwarding # DMZ Portforwarding
networking.nat.forwardPorts = networking.nat.forwardPorts =
let let
fulbergPort = ( cyprianspitzPortDst = (
proto: port: { proto: sourcePort: dstPort: {
destination = "10.1.2.2:${toString port}"; destination = "${plessur-lan-net.hosts.cyprianspitz.v4.ip}:${toString dstPort}";
proto = proto; inherit proto;
sourcePort = port; inherit sourcePort;
loopbackIPs = [ "85.195.200.253" ]; loopbackIPs = [ plessur-ext-net.hosts.calanda.v4.ip ];
}
);
cyprianspitzPort = (
proto: port: {
destination = "10.1.1.11:${toString port}";
proto = proto;
sourcePort = port;
loopbackIPs = [ "85.195.200.253" ];
} }
); );
cyprianspitzPort = proto: port: (cyprianspitzPortDst proto port port);
in in
[ [
{ (cyprianspitzPortDst "tcp" 8222 22)
destination = "10.1.2.2:22"; (cyprianspitzPortDst "tcp" 8223 2222)
proto = "tcp";
sourcePort = 8022;
}
{
destination = "10.1.2.2:2222";
proto = "tcp";
sourcePort = 8222;
}
{
destination = "10.1.1.11:2222";
proto = "tcp";
sourcePort = 8223;
}
]
++ map (fulbergPort "udp") [
51820
51821
] ]
++ map (cyprianspitzPort "tcp") [ ++ map (cyprianspitzPort "tcp") [
80 80

View file

@ -8,7 +8,14 @@ Reboot requires passphrase.
# Get HDD Password: # Get HDD Password:
sops decrypt --extract '["system"]["hdd"]' private/nixos-configurations/cyprianspitz/secrets.sops.yaml sops decrypt --extract '["system"]["hdd"]' private/nixos-configurations/cyprianspitz/secrets.sops.yaml
ssh -p 8223 -J root@calanda.plessur-ext.net.qo.is ssh -p 8223 root@calanda.plessur-ext.net.qo.is
```
Direct remote ssh access:
```
ssh -p 8222 root@calanda.plessur-ext.net.qo.is
``` ```
## Hardware ## Hardware
@ -29,4 +36,4 @@ TODO
### HDD Bay ### HDD Bay
Note that slot 5 (the leftmost) SATA bay is not connected due to the mainboard only having 4 SATA plugs. Note that the slot in the middle of the SATA bay is not connected due to the mainboard only having 4 SATA plugs.

View file

@ -1,4 +1,9 @@
{ config, pkgs, ... }: {
config,
pkgs,
lib,
...
}:
{ {
imports = [ imports = [
@ -7,4 +12,5 @@
]; ];
qois.loadbalancer.enable = true; qois.loadbalancer.enable = true;
qois.backplane-net.hosts.loadbalancers = lib.mkForce [ "cyprianspitz" ];
} }

View file

@ -24,5 +24,5 @@
# this value at the release version of the first install of this system. # this value at the release version of the first install of this system.
# Before changing this value read the documentation for this option # Before changing this value read the documentation for this option
# (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
system.stateVersion = "24.05"; # Did you read the comment? system.stateVersion = "24.11"; # Did you read the comment?
} }

View file

@ -2,29 +2,34 @@
let let
meta = config.qois.meta; meta = config.qois.meta;
getNetV4Ip = net: {
address = net.hosts.cyprianspitz.v4.ip;
prefixLength = net.v4.prefixLength;
};
calandaIp = meta.network.physical.plessur-lan.hosts.calanda.v4.ip;
in in
{ {
networking.enableIPv6 = false;
networking.hostName = meta.hosts.cyprianspitz.hostName; networking.hostName = meta.hosts.cyprianspitz.hostName;
imports = [ ../../defaults/backplane-net ]; networking.nameservers = [ calandaIp ];
networking.useDHCP = false; networking.useDHCP = false;
networking.interfaces.enp0s31f6.useDHCP = true; networking.interfaces.enp0s31f6.ipv4.addresses = [
networking.interfaces.enp2s0.useDHCP = true; (getNetV4Ip meta.network.physical.plessur-lan)
];
networking.defaultGateway = {
address = calandaIp;
interface = "enp0s31f6";
};
# Virtualization # Virtualization
networking.interfaces.vms-nat.useDHCP = false; networking.interfaces.vms-nat = {
networking.interfaces.vms-nat.ipv4.addresses = [ useDHCP = false;
( ipv4.addresses = [
let (getNetV4Ip meta.network.virtual.cyprianspitz-vms-nat)
netConfig = meta.network.virtual.cyprianspitz-vms-nat;
in
{
address = netConfig.hosts.cyprianspitz.v4.ip;
prefixLength = netConfig.v4.prefixLength;
}
)
]; ];
};
networking.bridges.vms-nat.interfaces = [ ]; networking.bridges.vms-nat.interfaces = [ ];
networking.nat = { networking.nat = {
@ -41,8 +46,9 @@ in
in in
{ {
enable = true; enable = true;
resolveLocalQueries = false; resolveLocalQueries = true;
settings = { settings = {
server = [ calandaIp ];
interface = "vms-nat"; interface = "vms-nat";
bind-interfaces = true; bind-interfaces = true;
@ -67,31 +73,17 @@ in
}; };
# Boot # Boot
boot.initrd.network.udhcpc.enable = true;
services.qois.luks-ssh = { services.qois.luks-ssh = {
enable = true; enable = true;
interface = "eth0"; interface = "eth0";
sshPort = 2222; sshPort = 2222;
sshHostKey = "/secrets/system/initrd-ssh-key"; sshHostKey = "/secrets/system/initrd-ssh-key";
# TODO Solve sops dependency porblem: config.sops.secrets."system/initrd-ssh-key".path; # TODO Solve sops dependency porblem: config.sops.secrets."system/initrd-ssh-key".path;
}; };
# Configure this node to be used as an vpn exit node qois.backplane-net.enable = true;
qois.backup-client.includePaths = [ "/var/lib/tailscale" ];
services.tailscale = {
enable = true;
openFirewall = true;
useRoutingFeatures = "server";
authKeyFile = config.sops.secrets."tailscale/key".path;
extraUpFlags = [
"--login-server=https://vpn.qo.is"
"--advertise-exit-node"
(
with meta.network.virtual.backplane.v4; "--advertise-routes=${id}/${builtins.toString prefixLength}"
)
"--advertise-tags=tag:srv"
];
};
# Configure this node to be used as an vpn exit node
qois.vpn-exit-node.enable = true;
} }

View file

@ -3,8 +3,5 @@
sops.secrets = { sops.secrets = {
"system/hdd" = { }; "system/hdd" = { };
"system/initrd-ssh-key" = { }; "system/initrd-ssh-key" = { };
"tailscale/key" = {
restartUnits = [ "tailscaled.service" ];
};
}; };
} }

View file

@ -3,7 +3,6 @@
pkgs, pkgs,
nixpkgs-nixos-stable, nixpkgs-nixos-stable,
disko, disko,
attic,
sops-nix, sops-nix,
... ...
}@inputs: }@inputs:
@ -20,13 +19,6 @@ pkgs.lib.genAttrs configs (
modules = [ modules = [
self.nixosModules.default self.nixosModules.default
./${config}/default.nix ./${config}/default.nix
(
{ ... }:
{
imports = [ "${attic}/nixos/atticd.nix" ];
services.atticd.useFlakeCompatOverlay = false;
}
)
disko.nixosModules.disko disko.nixosModules.disko
sops-nix.nixosModules.sops sops-nix.nixosModules.sops
( (

View file

@ -1 +0,0 @@
# fulberg

View file

@ -1 +0,0 @@
{ ... }: { }

View file

@ -1,35 +0,0 @@
{ config, pkgs, ... }:
{
qois.backup-server = {
enable = true;
backupStorageRoot = "/mnt/nas/backup";
};
services.borgbackup.repos =
let
backupRoot = "/mnt/nas/backup";
hostBackupRoot = "${backupRoot}/hosts";
dataBackupRoot = "${backupRoot}/data";
in
{
"lindberg-nextcloud" = {
authorizedKeys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIpzfp9VqclbPJ42ZrkRpvjMSTeyq0qce03zCRXqIHMw backup@lindberg-nextcloud"
];
path = "${hostBackupRoot}/lindberg-nextcloud";
};
"lindberg-data" = {
authorizedKeys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGTmyoVONC12MgOodvzdPpZzLSVwpkC6zkf+Rg0W36gy backup-data@lindberg"
];
path = "${dataBackupRoot}/lindberg";
};
"lindberg-build-system" = {
authorizedKeys = [
"ssh-ed25519 AAAATODOTODOTODONTE5AAAAIGTmyoVONC12MgOodvzdPpZzLSVwpkC6zkf+Rg0W36gy backup-system@lindberg-build"
];
path = "${dataBackupRoot}/lindberg-build-system";
};
};
}

View file

@ -1,22 +0,0 @@
{ config, pkgs, ... }:
{
imports = [
../../defaults/base
../../defaults/hardware/apu.nix
../../defaults/meta
./applications
./backup.nix
./filesystems.nix
./networking.nix
./secrets.nix
];
# This value determines the NixOS release from which the default
# settings for stateful data, like fi:le locations and database versions
# on your system were taken. Its perfectly fine and recommended to leave
# this value at the release version of the first install of this system.
# Before changing this value read the documentation for this option
# (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
system.stateVersion = "23.05"; # Did you read the comment?
}

View file

@ -1,31 +0,0 @@
{ config, pkgs, ... }:
{
fileSystems = {
"/" = {
device = "/dev/disk/by-uuid/360a6bc9-fc4e-4803-bd53-69320ac32ac5";
fsType = "btrfs";
options = [
"defaults"
"subvol=nixos"
"noatime"
];
};
"/mnt/nas" = {
device = "10.1.1.39:/qois";
fsType = "nfs";
options = [
"defaults"
"noatime"
"soft"
];
};
};
swapDevices = [ { device = "/dev/disk/by-uuid/73f91e99-d856-4504-b6b2-d60f855d6d95"; } ];
boot.loader.grub = {
enable = true;
device = "/dev/sda";
};
}

View file

@ -1,48 +0,0 @@
{ config, pkgs, ... }:
let
meta = config.qois.meta;
plessur-dmz-net = meta.network.physical.plessur-dmz;
getCalandaIp4 = net: net.hosts.calanda.v4.ip;
in
{
networking.hostName = meta.hosts.fulberg.hostName;
imports = [ ../../defaults/backplane-net ];
# WWAN is currently not available due to a broken SIM-card.
#services.qois.wwan = {
# enable = true;
# apn = "gprs.swisscom.ch";
# networkInterface = "wwp0s19u1u3i12";
#};
networking.interfaces.enp1s0 = {
useDHCP = false;
ipv4.addresses = [
{
inherit (plessur-dmz-net.v4) prefixLength;
address = plessur-dmz-net.hosts.fulberg.v4.ip;
}
];
};
networking.defaultGateway = plessur-dmz-net.v4.gateway;
networking.nameservers = plessur-dmz-net.v4.nameservers;
# Configure this node to be used as an vpn exit node
qois.backup-client.includePaths = [ "/var/lib/tailscale" ];
services.tailscale = {
enable = true;
openFirewall = true;
useRoutingFeatures = "server";
authKeyFile = config.sops.secrets."tailscale/key".path;
extraUpFlags = [
"--login-server=https://vpn.qo.is"
"--advertise-exit-node"
(
with meta.network.virtual.backplane.v4; "--advertise-routes=${id}/${builtins.toString prefixLength}"
)
"--advertise-tags=tag:srv"
];
};
}

View file

@ -1,8 +0,0 @@
{ ... }:
{
sops.secrets = {
"tailscale/key" = {
restartUnits = [ "tailscale.service" ];
};
};
}

View file

@ -1,77 +0,0 @@
{ config, pkgs, ... }:
let
atticPort = 8080;
atticHostname = "attic.qo.is";
in
{
services.atticd = {
enable = true;
# Replace with absolute path to your credentials file
# generate secret with
# nix run system#openssl rand 64 | base64 -w0
# ATTIC_SERVER_TOKEN_HS256_SECRET_BASE64="output from openssl"
credentialsFile = config.sops.secrets."attic/server_token".path;
settings = {
listen = "127.0.0.1:${builtins.toString atticPort}";
allowed-hosts = [ "attic.qo.is" ];
api-endpoint = "https://attic.qo.is/";
# Data chunking
#
# Warning: If you change any of the values here, it will be
# difficult to reuse existing chunks for newly-uploaded NARs
# since the cutpoints will be different. As a result, the
# deduplication ratio will suffer for a while after the change.
chunking = {
# The minimum NAR size to trigger chunking
#
# If 0, chunking is disabled entirely for newly-uploaded NARs.
# If 1, all NARs are chunked.
nar-size-threshold = 64 * 1024; # 64 KiB
# The preferred minimum size of a chunk, in bytes
min-size = 16 * 1024; # 16 KiB
# The preferred average size of a chunk, in bytes
avg-size = 64 * 1024; # 64 KiB
# The preferred maximum size of a chunk, in bytes
max-size = 256 * 1024; # 256 KiB
};
database.url = "postgresql:///atticd?host=/run/postgresql";
};
};
imports = [ ../../../defaults/webserver ];
qois.postgresql.enable = true;
# Note: Attic cache availability is "best effort", so no artifacts are backed up.
services.postgresql = {
ensureDatabases = [ "atticd" ];
ensureUsers = [
{
name = "atticd";
ensureDBOwnership = true;
}
];
};
services.nginx = {
enable = true;
clientMaxBodySize = "1g";
virtualHosts.${atticHostname} = {
kTLS = true;
forceSSL = true;
enableACME = true;
locations."/".proxyPass = "http://127.0.0.1:${builtins.toString atticPort}";
};
};
}

View file

@ -1,10 +1,24 @@
{ config, pkgs, ... }: {
config,
pkgs,
lib,
...
}:
{ {
imports = [ imports = [
./attic.nix
./nixpkgs-cache.nix ./nixpkgs-cache.nix
]; ];
qois.git-ci-runner.enable = true; qois.git-ci-runner.enable = true;
qois.attic.enable = true;
qois.postgresql.package = pkgs.postgresql_15;
# Remove substituters that are hosted on this node, to prevent lockups
# since the current nix implementation is not forgiving with unavailable subsituters.
# The qois-infrastructure cache is not needed,
# since the builds are done (and cached) on this host anyway.
nix.settings.substituters = lib.mkForce [
"https://cache.nixos.org?priority=40"
];
} }

View file

@ -3,7 +3,6 @@
let let
vnet = config.qois.meta.network.virtual.backplane.hosts; vnet = config.qois.meta.network.virtual.backplane.hosts;
systemTargets = [ systemTargets = [
"fulberg"
"tierberg" "tierberg"
]; ];
systemJobs = builtins.listToAttrs ( systemJobs = builtins.listToAttrs (

View file

@ -4,7 +4,6 @@
imports = [ imports = [
../../defaults/base-vm ../../defaults/base-vm
../../defaults/meta ../../defaults/meta
../../defaults/backplane-net
./applications ./applications
./backup.nix ./backup.nix
@ -22,5 +21,5 @@
# this value at the release version of the first install of this system. # this value at the release version of the first install of this system.
# Before changing this value read the documentation for this option # Before changing this value read the documentation for this option
# (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
system.stateVersion = "23.11"; # Did you read the comment? system.stateVersion = "24.11"; # Did you read the comment?
} }

View file

@ -6,6 +6,8 @@
networking.useDHCP = false; networking.useDHCP = false;
networking.interfaces.enp11s0.useDHCP = true; networking.interfaces.enp11s0.useDHCP = true;
qois.backplane-net.enable = true;
networking.firewall.allowedTCPPorts = [ networking.firewall.allowedTCPPorts = [
80 80
443 443

View file

@ -1,9 +1,6 @@
{ ... }: { ... }:
{ {
sops.secrets = { sops.secrets = {
"attic/server_token" = {
restartUnits = [ "atticd.service" ];
};
"gitlab-runner/default-registration" = { "gitlab-runner/default-registration" = {
restartUnits = [ "gitlab-runner.service" ]; restartUnits = [ "gitlab-runner.service" ];
}; };

View file

@ -6,7 +6,7 @@ in
imports = [ ../../../defaults/nextcloud ]; imports = [ ../../../defaults/nextcloud ];
qois.postgresql.enable = true; services.postgresql.enable = true;
services.nextcloud = { services.nextcloud = {
hostName = host; hostName = host;

View file

@ -2,4 +2,6 @@
{ {
imports = [ ./cloud.nix ]; imports = [ ./cloud.nix ];
qois.postgresql.package = pkgs.postgresql_14;
} }

View file

@ -2,10 +2,8 @@
{ {
imports = [ imports = [
../../defaults/backplane-net
../../defaults/base-vm ../../defaults/base-vm
../../defaults/meta ../../defaults/meta
../../defaults/webserver
./applications ./applications
./backup.nix ./backup.nix
./secrets.nix ./secrets.nix
@ -32,6 +30,8 @@
networking.useDHCP = false; networking.useDHCP = false;
networking.interfaces.enp2s0.useDHCP = true; networking.interfaces.enp2s0.useDHCP = true;
qois.backplane-net.enable = true;
networking.firewall.allowedTCPPorts = [ networking.firewall.allowedTCPPorts = [
80 80
443 443
@ -46,5 +46,5 @@
# this value at the release version of the first install of this system. # this value at the release version of the first install of this system.
# Before changing this value read the documentation for this option # Before changing this value read the documentation for this option
# (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
system.stateVersion = "22.05"; # Did you read the comment? system.stateVersion = "24.11"; # Did you read the comment?
} }

View file

@ -2,7 +2,7 @@
let let
backupConfiguration = { backupConfiguration = {
restartUnits = [ restartUnits = [
"borgbackup-job-system-fulberg.service" "borgbackup-job-system-cyprianspitz.service"
"borgbackup-job-system-tierberg.service" "borgbackup-job-system-tierberg.service"
]; ];
}; };

View file

@ -6,4 +6,5 @@
qois.vault.enable = true; qois.vault.enable = true;
qois.git.enable = true; qois.git.enable = true;
qois.static-page.enable = true; qois.static-page.enable = true;
qois.postgresql.package = pkgs.postgresql_15;
} }

View file

@ -4,7 +4,6 @@
imports = [ imports = [
../../defaults/base-vm ../../defaults/base-vm
../../defaults/meta ../../defaults/meta
../../defaults/backplane-net
./applications ./applications
./disko-config.nix ./disko-config.nix
@ -21,5 +20,5 @@
# this value at the release version of the first install of this system. # this value at the release version of the first install of this system.
# Before changing this value read the documentation for this option # Before changing this value read the documentation for this option
# (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
system.stateVersion = "23.11"; # Did you read the comment? system.stateVersion = "24.11"; # Did you read the comment?
} }

View file

@ -6,6 +6,8 @@
networking.useDHCP = false; networking.useDHCP = false;
networking.interfaces.enp1s0.useDHCP = true; networking.interfaces.enp1s0.useDHCP = true;
qois.backplane-net.enable = true;
networking.firewall.allowedTCPPorts = [ networking.firewall.allowedTCPPorts = [
80 80
443 443

View file

@ -25,5 +25,5 @@
# this value at the release version of the first install of this system. # this value at the release version of the first install of this system.
# Before changing this value read the documentation for this option # Before changing this value read the documentation for this option
# (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
system.stateVersion = "21.11"; # Did you read the comment? system.stateVersion = "24.11"; # Did you read the comment?
} }

View file

@ -6,8 +6,6 @@ in
{ {
networking.hostName = meta.hosts.lindberg.hostName; networking.hostName = meta.hosts.lindberg.hostName;
imports = [ ../../defaults/backplane-net ];
networking.useDHCP = false; networking.useDHCP = false;
networking.interfaces.enp5s0.useDHCP = true; networking.interfaces.enp5s0.useDHCP = true;
@ -40,7 +38,7 @@ in
in in
{ {
enable = true; enable = true;
resolveLocalQueries = false; resolveLocalQueries = true;
settings = { settings = {
interface = "vms-nat"; interface = "vms-nat";
bind-interfaces = true; bind-interfaces = true;
@ -56,7 +54,14 @@ in
dhcp-authoritative = true; dhcp-authoritative = true;
}; };
}; };
systemd.services.dnsmasq.bindsTo = [ "network-addresses-vms-nat.service" ]; systemd.services.dnsmasq =
let
vmsNat = [ "network-addresses-vms-nat.service" ];
in
{
bindsTo = vmsNat;
after = vmsNat;
};
networking.firewall.interfaces.vms-nat = { networking.firewall.interfaces.vms-nat = {
allowedUDPPorts = [ allowedUDPPorts = [
53 53
@ -74,20 +79,7 @@ in
sshPort = 2222; sshPort = 2222;
}; };
# Use this node as vpn exit node qois.backplane-net.enable = true;
qois.backup-client.includePaths = [ "/var/lib/tailscale" ];
services.tailscale = { qois.vpn-exit-node.enable = true;
enable = true;
openFirewall = true;
useRoutingFeatures = "server";
authKeyFile = config.sops.secrets."tailscale/key".path;
extraUpFlags = [
"--login-server=https://vpn.qo.is"
"--advertise-exit-node"
(
with meta.network.virtual.backplane.v4; "--advertise-routes=${id}/${builtins.toString prefixLength}"
)
"--advertise-tags=tag:srv"
];
};
} }

View file

@ -2,7 +2,7 @@
let let
backupConfiguration = { backupConfiguration = {
restartUnits = [ restartUnits = [
"borgbackup-job-data-fulberg.service" "borgbackup-job-data-cyprianspitz.service"
"borgbackup-job-data-tierberg.service" "borgbackup-job-data-tierberg.service"
]; ];
}; };

View file

@ -6,13 +6,13 @@
{ {
imports = [ imports = [
../../defaults/backplane-net
../../defaults/hardware/apu.nix ../../defaults/hardware/apu.nix
../../defaults/base ../../defaults/base
../../defaults/meta ../../defaults/meta
]; ];
boot.initrd.luks.devices."systems".device = "/dev/disk/by-uuid/5718bd19-cb7a-4728-9ec4-6b2be48215fc"; boot.initrd.luks.devices."systems".device =
"/dev/disk/by-uuid/5718bd19-cb7a-4728-9ec4-6b2be48215fc";
fileSystems."/" = { fileSystems."/" = {
device = "/dev/mapper/vg_systems-hv_stompert"; device = "/dev/mapper/vg_systems-hv_stompert";
@ -52,6 +52,8 @@
networking.interfaces.enp3s0.useDHCP = true; networking.interfaces.enp3s0.useDHCP = true;
networking.tempAddresses = "disabled"; networking.tempAddresses = "disabled";
qois.backplane-net.enable = true;
# Set your time zone. # Set your time zone.
# time.timeZone = "Europe/Amsterdam"; # time.timeZone = "Europe/Amsterdam";
@ -59,5 +61,5 @@
# compatible, in order to avoid breaking some software such as database # compatible, in order to avoid breaking some software such as database
# servers. You should change this only after NixOS release notes say you # servers. You should change this only after NixOS release notes say you
# should. # should.
system.stateVersion = "22.11"; # Did you read the comment? system.stateVersion = "24.11"; # Did you read the comment?
} }

View file

@ -20,5 +20,5 @@
# compatible, in order to avoid breaking some software such as database # compatible, in order to avoid breaking some software such as database
# servers. You should change this only after NixOS release notes say you # servers. You should change this only after NixOS release notes say you
# should. # should.
system.stateVersion = "23.05"; # Did you read the comment? system.stateVersion = "24.11"; # Did you read the comment?
} }

View file

@ -7,8 +7,6 @@ in
{ {
networking.hostName = meta.hosts.tierberg.hostName; networking.hostName = meta.hosts.tierberg.hostName;
imports = [ ../../defaults/backplane-net ];
networking.enableIPv6 = false; # TODO networking.enableIPv6 = false; # TODO
networking.useDHCP = false; networking.useDHCP = false;
@ -21,6 +19,8 @@ in
]; ];
networking.interfaces.enp3s0.useDHCP = true; networking.interfaces.enp3s0.useDHCP = true;
qois.backplane-net.enable = true;
services.qois.luks-ssh = { services.qois.luks-ssh = {
enable = true; enable = true;
interface = "eth0"; interface = "eth0";

View file

@ -11,11 +11,15 @@ in
with lib; with lib;
{ {
options.qois.postgresql = { options.qois.postgresql = {
enable = mkEnableOption ''Enable postgresql services with defaults''; # Note: this module is auto-enabled if postgres is used.
package = mkPackageOption pkgs "postgresql" {
example = "postgresql_15";
default = null;
};
}; };
config = mkIf cfg.enable { config = mkIf config.services.postgresql.enable {
services.postgresql.enable = true; services.postgresql.package = cfg.package;
services.postgresqlBackup.enable = true; services.postgresqlBackup.enable = true;
qois.backup-client.includePaths = [ config.services.postgresqlBackup.location ]; qois.backup-client.includePaths = [ config.services.postgresqlBackup.location ];
}; };

View file

@ -0,0 +1,98 @@
{
config,
pkgs,
lib,
...
}:
with lib;
let
cfg = config.qois.attic;
in
{
options.qois.attic = {
enable = mkEnableOption "Enable attic service";
domain = mkOption {
description = "Domain for attic server";
type = types.str;
default = "attic.qo.is";
};
port = mkOption {
description = "Server Port";
type = types.numbers.between 1 65536;
default = 8080;
};
};
config = mkIf cfg.enable {
sops.secrets."attic/server_token".restartUnits = [ "atticd.service" ];
services.atticd = {
enable = true;
# Replace with absolute path to your credentials file
# generate secret with
# nix run system#openssl rand 64 | base64 -w0
# ATTIC_SERVER_TOKEN_HS256_SECRET_BASE64="output from openssl"
environmentFile = config.sops.secrets."attic/server_token".path;
settings = {
listen = "127.0.0.1:${toString cfg.port}";
allowed-hosts = [ cfg.domain ];
api-endpoint = "https://${cfg.domain}/";
# Data chunking
#
# Warning: If you change any of the values here, it will be
# difficult to reuse existing chunks for newly-uploaded NARs
# since the cutpoints will be different. As a result, the
# deduplication ratio will suffer for a while after the change.
chunking = {
# The minimum NAR size to trigger chunking
#
# If 0, chunking is disabled entirely for newly-uploaded NARs.
# If 1, all NARs are chunked.
nar-size-threshold = 64 * 1024; # 64 KiB
# The preferred minimum size of a chunk, in bytes
min-size = 16 * 1024; # 16 KiB
# The preferred average size of a chunk, in bytes
avg-size = 64 * 1024; # 64 KiB
# The preferred maximum size of a chunk, in bytes
max-size = 256 * 1024; # 256 KiB
};
garbage-collection.default-retention-period = "6 months";
database.url = "postgresql:///atticd?host=/run/postgresql";
};
};
# Note: Attic cache availability is "best effort", so no artifacts are backed up.
services.postgresql = {
enable = true;
ensureDatabases = [ "atticd" ];
ensureUsers = [
{
name = "atticd";
ensureDBOwnership = true;
}
];
};
services.nginx = {
enable = true;
clientMaxBodySize = "1g";
virtualHosts.${cfg.domain} = {
kTLS = true;
forceSSL = true;
enableACME = true;
locations."/".proxyPass = "http://127.0.0.1:${toString cfg.port}";
};
};
};
}

View file

@ -0,0 +1,42 @@
{
config,
pkgs,
lib,
...
}:
with lib;
let
cfg = config.qois.backplane-net.hosts;
defaultDomains = attrNames config.qois.loadbalancer.domains;
defaultLoadbalancers = [ "lindberg" ];
in
{
options.qois.backplane-net.hosts = {
enable = mkOption {
default = true;
description = "Whether to enable hosts aliases for loadbalanced services. This prevents turnarounds over external networks for these services.";
type = types.bool;
};
domains = mkOption {
description = "Domains that are hosted by the backplane loadbalancer";
type = with types; listOf str;
default = defaultDomains;
};
loadbalancers = mkOption {
description = "List of Loadbalancer hostnames as listed in the backplane network";
type = with types; listOf str;
default = defaultLoadbalancers;
};
};
config = mkIf cfg.enable {
networking.hosts = pipe cfg.loadbalancers [
(map (hostname: config.qois.meta.network.virtual.backplane.hosts.${hostname}.v4.ip))
(flip genAttrs (lb: cfg.domains))
];
};
}

View file

@ -0,0 +1,83 @@
{
config,
lib,
pkgs,
...
}:
with lib;
let
cfg = config.qois.backplane-net;
hostName = config.networking.hostName;
netConfig = config.qois.meta.network.virtual.${cfg.netName};
hostNetConfig = netConfig.hosts.${hostName};
interface = "wg-${cfg.netName}";
wgService = [ "wireguard-${interface}.service" ];
in
{
options.qois.backplane-net = {
enable = mkEnableOption "Enable backplane server services";
netName = mkOption {
description = "Network Name";
type = types.str;
default = "backplane";
};
domain = mkOption {
description = "Domain";
type = types.str;
default = hostNetConfig;
};
port = mkOption {
description = "Wireguard Default Port";
type = types.number;
default = 51825;
};
};
config = {
sops.secrets."wgautomesh/gossip-secret".restartUnits = [ "wgautomesh.service" ];
networking.wireguard.enable = true;
networking.wireguard.interfaces."wg-${cfg.netName}" = {
ips = [ "${hostNetConfig.v4.ip}/${toString netConfig.v4.prefixLength}" ];
listenPort = if hostNetConfig.endpoint != null then hostNetConfig.endpoint.port else cfg.port;
privateKeyFile = "/secrets/wireguard/private/${cfg.netName}";
generatePrivateKeyFile = true;
};
systemd.network.wait-online.ignoredInterfaces = [ interface ];
networking.firewall.allowedUDPPorts =
if hostNetConfig.endpoint != null then [ hostNetConfig.endpoint.port ] else [ cfg.port ];
# Configure wgautomesh to setup peers. Make sure that the name is not used in the VPN module
services.wgautomesh = {
enable = true;
gossipSecretFile = config.sops.secrets."wgautomesh/gossip-secret".path;
openFirewall = true;
settings = {
inherit interface;
# Map meta network configuration to the format of wgautomesh and filter out peers with endpoints
peers = pipe netConfig.hosts [
(filterAttrs (peerHostName: _: peerHostName != hostName)) # Not this host
(mapAttrsToList (
_: peerConfig: {
address = peerConfig.v4.ip;
endpoint =
if (peerConfig.endpoint != null) then
with peerConfig.endpoint; "${fqdn}:${toString port}"
else
null;
pubkey = peerConfig.publicKey;
}
))
];
};
};
systemd.services.wgautomesh = {
requires = wgService;
after = wgService;
};
};
}

View file

@ -91,9 +91,10 @@ with lib;
emptypassword='$6$1ero.LwbisiU.h3D$GGmnmECbPotJoPQ5eoSTD6tTjKnSWZcjHoVTkxFLZP17W9hRi/XkmCiAMOfWruUwy8gMjINrBMNODc7cYEo4K.' emptypassword='$6$1ero.LwbisiU.h3D$GGmnmECbPotJoPQ5eoSTD6tTjKnSWZcjHoVTkxFLZP17W9hRi/XkmCiAMOfWruUwy8gMjINrBMNODc7cYEo4K.'
useradd --prefix $(pwd) -p "$emptypassword" -m -d /tmp -u "$userid" -g "$groupid" -G nixuser nixuser useradd --prefix $(pwd) -p "$emptypassword" -m -d /tmp -u "$userid" -g "$groupid" -G nixuser nixuser
cat <<NIX_CONFIG > etc/nix/nix.conf cp -a ${config.environment.etc."nix/nix.conf".source} etc/nix/nix.conf
cat <<NIX_CONFIG >> etc/nix/nix.conf
accept-flake-config = true accept-flake-config = true
experimental-features = nix-command flakes
NIX_CONFIG NIX_CONFIG
cat <<NSSWITCH > etc/nsswitch.conf cat <<NSSWITCH > etc/nsswitch.conf

View file

@ -21,10 +21,11 @@ with lib;
}; };
config = mkIf cfg.enable { config = mkIf cfg.enable {
qois.postgresql.enable = true; services.postgresql.enable = true;
services.forgejo = { services.forgejo = {
enable = true; enable = true;
package = pkgs.forgejo;
database.type = "postgres"; database.type = "postgres";
lfs.enable = true; lfs.enable = true;

View file

@ -79,7 +79,7 @@ let
in in
{ {
options.qois.loadbalancer = with lib; { options.qois.loadbalancer = {
enable = mkEnableOption "Enable services http+s loadbalancing"; enable = mkEnableOption "Enable services http+s loadbalancing";
domains = mkOption { domains = mkOption {

View file

@ -1,12 +1,9 @@
{ {
config,
lib,
pkgs,
... ...
}: }:
{ {
services.nginx = { config.services.nginx = {
recommendedTlsSettings = true; recommendedTlsSettings = true;
recommendedOptimisation = true; recommendedOptimisation = true;
recommendedProxySettings = true; recommendedProxySettings = true;

View file

@ -0,0 +1,50 @@
{
config,
pkgs,
lib,
...
}:
with lib;
let
cfg = config.qois.vpn-exit-node;
in
{
options.qois.vpn-exit-node = {
enable = mkEnableOption "vpn exit node";
domain = mkOption {
description = "Domain for the VPN admin server";
type = types.str;
default = "vpn.qo.is";
};
};
config = mkIf cfg.enable {
qois.backup-client.includePaths = [ "/var/lib/tailscale" ];
sops.secrets."tailscale/key".restartUnits = [ "tailscaled.service" ];
services.tailscale = {
enable = true;
openFirewall = true;
useRoutingFeatures = "server";
authKeyFile = config.sops.secrets."tailscale/key".path;
extraUpFlags =
let
backplaneRoute =
with config.qois.meta.network.virtual.backplane.v4;
"${id}/${builtins.toString prefixLength}";
in
[
"--timeout 60s"
"--accept-dns=false"
"--accept-routes=false"
"--login-server=https://${cfg.domain}"
"--advertise-exit-node"
"--advertise-routes=${backplaneRoute}"
"--advertise-tags=tag:srv"
];
};
};
}

View file

@ -8,14 +8,23 @@ with lib;
let let
cfg = config.qois.vpn-server; cfg = config.qois.vpn-server;
cfgLoadbalancer = config.qois.loadbalancer; cfgLoadbalancer = config.qois.loadbalancer;
defaultDnsRecords = mapAttrs ( defaultDnsRecords =
(mapAttrs (
name: value: mkIf (cfgLoadbalancer.hostmap ? ${value}) cfgLoadbalancer.hostmap.${value} name: value: mkIf (cfgLoadbalancer.hostmap ? ${value}) cfgLoadbalancer.hostmap.${value}
) cfgLoadbalancer.domains; ) cfgLoadbalancer.domains)
// {
"vpn.qo.is" = config.services.headscale.address;
};
in in
{ {
options.qois.vpn-server = { options.qois.vpn-server = {
enable = mkEnableOption "Enable vpn server services"; enable = mkEnableOption "Enable vpn server services";
domain = mkOption {
description = "Domain for the VPN admin server";
type = types.str;
default = "vpn.qo.is";
};
dnsRecords = mkOption { dnsRecords = mkOption {
description = "DNS records to add to Hosts"; description = "DNS records to add to Hosts";
type = with types; attrsOf str; type = with types; attrsOf str;
@ -32,18 +41,22 @@ in
environment.systemPackages = [ pkgs.headscale ]; environment.systemPackages = [ pkgs.headscale ];
# We bind to the backplane vpn IP, so wait for the wireguard net to be available
systemd.services.headscale.after = [ "wireguard-wg-backplane.service" ];
qois.backup-client.includePaths = qois.backup-client.includePaths =
with config.services.headscale.settings; with config.services.headscale.settings;
( (
[ [
db_path database.sqlite.path
private_key_path derp.server.private_key_path
noise.private_key_path noise.private_key_path
] ]
++ derp.paths ++ derp.paths
); );
networking.firewall.checkReversePath = "loose"; networking.firewall.checkReversePath = "loose";
networking.firewall.allowedTCPPorts = [ config.services.headscale.port ];
networking.firewall.allowedUDPPorts = [ networking.firewall.allowedUDPPorts = [
41641 41641
]; ];
@ -51,7 +64,7 @@ in
let let
vnet = config.qois.meta.network.virtual; vnet = config.qois.meta.network.virtual;
vpnNet = vnet.vpn; vpnNet = vnet.vpn;
vpnNetPrefix = "${vpnNet.v4.id}/${builtins.toString vpnNet.v4.prefixLength}"; vpnNetPrefix = "${vpnNet.v4.id}/${toString vpnNet.v4.prefixLength}";
backplaneNetPrefix = "${vnet.backplane.v4.id}/${builtins.toString vnet.backplane.v4.prefixLength}"; backplaneNetPrefix = "${vnet.backplane.v4.id}/${builtins.toString vnet.backplane.v4.prefixLength}";
in in
{ {
@ -59,19 +72,19 @@ in
address = vnet.backplane.hosts.cyprianspitz.v4.ip; address = vnet.backplane.hosts.cyprianspitz.v4.ip;
port = 46084; port = 46084;
settings = { settings = {
server_url = "https://${vpnNet.domain}:443"; server_url = "https://${cfg.domain}:443";
tls_letsencrypt_challenge_type = "TLS-ALPN-01"; tls_letsencrypt_challenge_type = "TLS-ALPN-01";
tls_letsencrypt_hostname = vpnNet.domain; tls_letsencrypt_hostname = vpnNet.domain;
dns_config = { dns = {
nameservers = [ vnet.backplane.hosts.calanda.v4.ip ]; base_domain = vpnNet.domain;
domains = [ magic_dns = true;
vpnNet.domain nameservers.global = [ "127.0.0.1" ];
search_domains = [
# First is base_domain by default with magic_dns
vnet.backplane.domain vnet.backplane.domain
]; ];
magic_dns = true;
base_domain = vpnNet.domain;
extra_records = pipe cfg.dnsRecords [ extra_records = pipe cfg.dnsRecords [
attrsToList attrsToList
(map (val: val // { type = "A"; })) (map (val: val // { type = "A"; }))
@ -80,9 +93,10 @@ in
ip_prefixes = [ vpnNetPrefix ]; ip_prefixes = [ vpnNetPrefix ];
acl_policy_path = pkgs.writeTextFile { policy =
name = "acls"; let
text = builtins.toJSON { # Note: headscale has limited acl support currently. This might change in the future.
aclPolicy = {
hosts = { hosts = {
"clients" = vpnNetPrefix; "clients" = vpnNetPrefix;
}; };
@ -129,6 +143,13 @@ in
} }
]; ];
}; };
in
{
mode = "file";
path = pkgs.writeTextFile {
name = "acls";
text = builtins.toJSON aclPolicy;
};
}; };
}; };
}; };

View file

@ -43,12 +43,13 @@ in
}; };
config = mkIf cfg.enable { config = mkIf cfg.enable {
services.dnsmasq.enable = true; services.dnsmasq = {
services.dnsmasq.extraConfig = '' enable = true;
settings = {
# Listen on this specific port instead of the standard DNS port # Listen on this specific port instead of the standard DNS port
# (53). Setting this to zero completely disables DNS function, # (53). Setting this to zero completely disables DNS function,
# leaving only DHCP and/or TFTP. # leaving only DHCP and/or TFTP.
port=${toString cfg.localDnsPort} port = cfg.localDnsPort;
# The following two options make you a better netizen, since they # The following two options make you a better netizen, since they
# tell dnsmasq to filter out queries which the public DNS cannot # tell dnsmasq to filter out queries which the public DNS cannot
@ -57,10 +58,9 @@ in
# these requests from bringing up the link unnecessarily. # these requests from bringing up the link unnecessarily.
# Never forward plain names (without a dot or domain part) # Never forward plain names (without a dot or domain part)
domain-needed domain-needed = true;
# Never forward addresses in the non-routed address spaces. # Never forward addresses in the non-routed address spaces.
bogus-priv bogus-priv = true;
# Uncomment this to filter useless windows-originated DNS requests # Uncomment this to filter useless windows-originated DNS requests
# which can trigger dial-on-demand links needlessly. # which can trigger dial-on-demand links needlessly.
@ -88,7 +88,7 @@ in
# If you don't want dnsmasq to poll /etc/resolv.conf or other resolv # If you don't want dnsmasq to poll /etc/resolv.conf or other resolv
# files for changes and re-read them then uncomment this. # files for changes and re-read them then uncomment this.
no-poll no-poll = true;
# Add other name servers here, with domain specs if they are for # Add other name servers here, with domain specs if they are for
# non-public domains. # non-public domains.
@ -100,13 +100,13 @@ in
# Add local-only domains here, queries in these domains are answered # Add local-only domains here, queries in these domains are answered
# from /etc/hosts or DHCP only. # from /etc/hosts or DHCP only.
local=/${config.networking.hostName}/ local = "/${config.networking.hostName}/";
# Add domains which you want to force to an IP address here. # Add domains which you want to force to an IP address here.
# The example below send any host in double-click.net to a local # The example below send any host in double-click.net to a local
# web-server. # web-server.
#address=/double-click.net/127.0.0.1 #address=/double-click.net/127.0.0.1
address=/${config.networking.hostName}.${cfg.localDomain}/${routerCfg.internalRouterIP} address = "/${config.networking.hostName}.${cfg.localDomain}/${routerCfg.internalRouterIP}";
# --address (and --server) work with IPv6 addresses too. # --address (and --server) work with IPv6 addresses too.
#address=/www.thekelleys.org.uk/fe80::20d:60ff:fe36:f83 #address=/www.thekelleys.org.uk/fe80::20d:60ff:fe36:f83
@ -129,8 +129,10 @@ in
# specified interfaces (and the loopback) give the name of the # specified interfaces (and the loopback) give the name of the
# interface (eg eth0) here. # interface (eg eth0) here.
# Repeat the line for more than one interface. # Repeat the line for more than one interface.
interface=${routerCfg.internalBridgeInterfaceName} interface = [
interface=lo routerCfg.internalBridgeInterfaceName
"lo"
];
# Or you can specify which interface _not_ to listen on # Or you can specify which interface _not_ to listen on
#except-interface= #except-interface=
# Or which to listen on by address (remember to include 127.0.0.1 if # Or which to listen on by address (remember to include 127.0.0.1 if
@ -139,7 +141,7 @@ in
# If you want dnsmasq to provide only DNS service on an interface, # If you want dnsmasq to provide only DNS service on an interface,
# configure it as shown above, and then use the following line to # configure it as shown above, and then use the following line to
# disable DHCP and TFTP on it. # disable DHCP and TFTP on it.
no-dhcp-interface=lo no-dhcp-interface = "lo";
# On systems which support it, dnsmasq binds the wildcard address, # On systems which support it, dnsmasq binds the wildcard address,
# even when it is listening on only some interfaces. It then discards # even when it is listening on only some interfaces. It then discards
@ -148,18 +150,18 @@ in
# want dnsmasq to really bind only the interfaces it is listening on, # want dnsmasq to really bind only the interfaces it is listening on,
# uncomment this option. About the only time you may need this is when # uncomment this option. About the only time you may need this is when
# running another nameserver on the same machine. # running another nameserver on the same machine.
bind-interfaces bind-interfaces = true;
# If you don't want dnsmasq to read /etc/hosts, uncomment the # If you don't want dnsmasq to read /etc/hosts, uncomment the
# following line. # following line.
no-hosts no-hosts = true;
# or if you want it to read another file, as well as /etc/hosts, use # or if you want it to read another file, as well as /etc/hosts, use
# this. # this.
#addn-hosts=/etc/banner_add_hosts #addn-hosts=/etc/banner_add_hosts
# Set this (and domain: see below) if you want to have a domain # Set this (and domain: see below) if you want to have a domain
# automatically added to simple names in a hosts-file. # automatically added to simple names in a hosts-file.
expand-hosts expand-hosts = true;
# Set the domain for dnsmasq. this is optional, but if it is set, it # Set the domain for dnsmasq. this is optional, but if it is set, it
# does the following things. # does the following things.
@ -168,7 +170,7 @@ in
# 2) Sets the "domain" DHCP option thereby potentially setting the # 2) Sets the "domain" DHCP option thereby potentially setting the
# domain of all systems configured by DHCP # domain of all systems configured by DHCP
# 3) Provides the domain part for "expand-hosts" # 3) Provides the domain part for "expand-hosts"
domain=${cfg.localDomain} domain = cfg.localDomain;
# Set a different domain for a particular subnet # Set a different domain for a particular subnet
#domain=wireless.thekelleys.org.uk,192.168.2.0/24 #domain=wireless.thekelleys.org.uk,192.168.2.0/24
@ -181,7 +183,7 @@ in
# a lease time. If you have more than one network, you will need to # a lease time. If you have more than one network, you will need to
# repeat this for each network on which you want to supply DHCP # repeat this for each network on which you want to supply DHCP
# service. # service.
dhcp-range=${cfg.dhcpRange},48h dhcp-range = "${cfg.dhcpRange},48h";
# This is an example of a DHCP range where the netmask is given. This # This is an example of a DHCP range where the netmask is given. This
# is needed for networks we reach the dnsmasq DHCP server via a relay # is needed for networks we reach the dnsmasq DHCP server via a relay
@ -346,10 +348,17 @@ in
# are some options which are recommended, they are detailed at the # are some options which are recommended, they are detailed at the
# end of this section. # end of this section.
dhcp-option = [
# Override the default route supplied by dnsmasq, which assumes the # Override the default route supplied by dnsmasq, which assumes the
# router is the same machine as the one running dnsmasq. # router is the same machine as the one running dnsmasq.
#dhcp-option=3,1.2.3.4 #dhcp-option=3,1.2.3.4
dhcp-option=6,${routerCfg.internalRouterIP} "6,${routerCfg.internalRouterIP}"
# Send RFC-3397 DNS domain search DHCP option. WARNING: Your DHCP client
# probably doesn't support this......
"option:domain-search,${cfg.localDomain}"
];
# Do the same thing, but using the option name # Do the same thing, but using the option name
#dhcp-option=option:router,1.2.3.4 #dhcp-option=option:router,1.2.3.4
@ -407,10 +416,6 @@ in
# Send an empty WPAD option. This may be REQUIRED to get windows 7 to behave. # Send an empty WPAD option. This may be REQUIRED to get windows 7 to behave.
#dhcp-option=252,"\n" #dhcp-option=252,"\n"
# Send RFC-3397 DNS domain search DHCP option. WARNING: Your DHCP client
# probably doesn't support this......
dhcp-option=option:domain-search,${cfg.localDomain}
# Send RFC-3442 classless static routes (note the netmask encoding) # Send RFC-3442 classless static routes (note the netmask encoding)
#dhcp-option=121,192.168.1.0/24,1.2.3.4,10.0.0.0/8,5.6.7.8 #dhcp-option=121,192.168.1.0/24,1.2.3.4,10.0.0.0/8,5.6.7.8
@ -504,7 +509,6 @@ in
# to 5. See page 19 of # to 5. See page 19 of
# http://download.intel.com/design/archives/wfm/downloads/pxespec.pdf # http://download.intel.com/design/archives/wfm/downloads/pxespec.pdf
# Enable dnsmasq's built-in TFTP server # Enable dnsmasq's built-in TFTP server
#enable-tftp #enable-tftp
@ -552,7 +556,7 @@ in
# server for your campus/company accidentally. The ISC server uses # server for your campus/company accidentally. The ISC server uses
# the same option, and this URL provides more information: # the same option, and this URL provides more information:
# http://www.isc.org/files/auth.html # http://www.isc.org/files/auth.html
dhcp-authoritative dhcp-authoritative = true;
# Run an executable when a DHCP lease is created or destroyed. # Run an executable when a DHCP lease is created or destroyed.
# The arguments sent to the script are "add" or "del", # The arguments sent to the script are "add" or "del",
@ -661,7 +665,8 @@ in
# Log lots of extra information about DHCP transactions. # Log lots of extra information about DHCP transactions.
#log-dhcp #log-dhcp
''; };
};
systemd.services.dnsmasq = { systemd.services.dnsmasq = {
bindsTo = [ "network-addresses-${routerCfg.internalBridgeInterfaceName}.service" ]; bindsTo = [ "network-addresses-${routerCfg.internalBridgeInterfaceName}.service" ];

View file

@ -63,6 +63,7 @@ in
enable = wle24GhzEnabled; enable = wle24GhzEnabled;
radios.${cfg.wleInterface24Ghz} = { radios.${cfg.wleInterface24Ghz} = {
channel = 6;
wifi4.enable = true; wifi4.enable = true;
wifi4.capabilities = [ wifi4.capabilities = [
"HT40-" "HT40-"

View file

@ -48,8 +48,6 @@ with lib;
}; };
}; };
qois.postgresql.enable = true;
qois.backup-client.includePaths = [ config.services.vaultwarden.config.DATA_FOLDER ]; qois.backup-client.includePaths = [ config.services.vaultwarden.config.DATA_FOLDER ];
services.postgresql = services.postgresql =
@ -57,6 +55,7 @@ with lib;
name = config.users.users.vaultwarden.name; name = config.users.users.vaultwarden.name;
in in
{ {
enable = true;
ensureUsers = [ ensureUsers = [
{ {
inherit name; inherit name;
@ -81,7 +80,7 @@ with lib;
forceSSL = true; forceSSL = true;
enableACME = true; enableACME = true;
locations."/" = { locations."/" = {
proxyPass = "http://localhost:${toString config.services.vaultwarden.config.ROCKET_PORT}"; proxyPass = "http://127.0.0.1:${toString config.services.vaultwarden.config.ROCKET_PORT}";
proxyWebsockets = true; proxyWebsockets = true;
}; };
}; };

View file

@ -28,7 +28,7 @@ deploy-qois .#lindberg-nextcloud .#lindberg-build
deploy-qois .#lindberg deploy-qois .#lindberg
# Deploy slow physical hosts (maybe do individually) # Deploy slow physical hosts (maybe do individually)
deploy-qois --confirm-timeout 600 --activation-timeout 600 --targets .#fulberg .#tierberg .#stompert .#stompert deploy-qois --confirm-timeout 600 --activation-timeout 600 --targets .#tierberg .#stompert .#stompert
``` ```
@ -39,7 +39,13 @@ For kernel updates, it might be required to reboot machines, which can be done i
pssh -l root -H lindberg-nextcloud.backplane.net.qo.is -H lindberg-build.backplane.net.qo.is reboot pssh -l root -H lindberg-nextcloud.backplane.net.qo.is -H lindberg-build.backplane.net.qo.is reboot
``` ```
## Aplication Updates ## `systemVersion` upgrades
- Make sure to read through the nixpkgs changelog to catch configuration scheme changes,
successor applications or for the need for manual interventions.
- Pay special attention the applications listed below.
## Application Updates
Some applications have pinned versions to prevent problems due to accidental upgrades. Some applications have pinned versions to prevent problems due to accidental upgrades.
The version switch has to be done manually by switching the package used. The version switch has to be done manually by switching the package used.
@ -47,3 +53,5 @@ The version switch has to be done manually by switching the package used.
This includes the modules for: This includes the modules for:
- `nextcloud` - `nextcloud`
- `postgresql`, [&rarr; Nixpkgs manual page](https://nixos.org/manual/nixos/stable/#module-services-postgres-upgrading)