nix-config/modules/c3d2.nix

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

355 lines
9.8 KiB
Nix
Raw Normal View History

2022-09-28 21:10:09 +02:00
{ zentralwerk, hostRegistry, config, options, lib, pkgs, ... }:
2022-01-18 15:39:35 +01:00
let
cfg = config.c3d2;
2022-09-28 21:10:09 +02:00
hqPrefix64 = lib.removeSuffix "::" (builtins.head (
builtins.split "/" zentralwerk.lib.config.site.net.c3d2.subnets6.dn42
));
2022-01-18 15:39:35 +01:00
neighMod = with lib; types.submodule {
options = {
addrs = mkOption {
type = with types; attrsOf str;
default = { };
};
via = mkOption
{
type = with types; listOf str;
default = [ ];
};
} // (with builtins; let value = mkOption { type = types.str; }; in
listToAttrs (map (name: { inherit name value; }) [ "exchpub" "id" "noisepub" "signpub" ]));
};
2022-09-28 21:10:09 +02:00
# Generate a deterministic IPv6 address for a 64 bit prefix
# and seed string. Prefix must not contain trailing ':'.
toIpv6Address = prefix64: seed:
with builtins;
let
digest = builtins.hashString "sha256" seed;
hextets = map (i: substring (4 * i) 4 digest) [ 0 1 2 3 ];
in
concatStringsSep ":" ([ prefix64 ] ++ hextets);
# Generate a deterministic public IPv6 addresses
# for the HQ networking using a seed string.
toHqPrivateAddress = toIpv6Address hqPrefix64;
2022-01-16 00:09:17 +01:00
in
{
2022-09-28 21:10:09 +02:00
options.c3d2 = with lib; {
allUsersCanSshRoot = lib.mkOption {
type = lib.types.bool;
2022-12-19 01:08:09 +01:00
default = true;
2022-09-28 21:10:09 +02:00
description = ''
Let all people in <literal>c3d2.users</literal>
login as root for deployment via SSH.
'';
};
2022-09-28 21:10:09 +02:00
enableMotd = mkOption {
type = types.bool;
2022-12-19 01:08:09 +01:00
default = true;
2022-09-28 21:10:09 +02:00
};
2022-09-28 21:10:09 +02:00
mergeNncpSettings = mkEnableOption ''
Whether to merge <literal>c3d2.nncp.<>.nncp</literal>
into <literal>programs.nncp.settings</literal>.
'';
2022-01-16 12:25:04 +01:00
2022-09-28 21:10:09 +02:00
k-ot.enable = mkEnableOption ''
Add k-ot user to this machine. Anyone with an SSH key listed in
<literal>c3d2.users</literal> can log in as this user.
'';
2022-09-28 21:10:09 +02:00
hq = {
interface = mkOption {
type = with types; nullOr str;
default = null;
example = "eth0";
description = ''
Configure the given interface name with an internal IP address.
'';
};
2022-09-28 21:10:09 +02:00
journalToMqtt = mkOption {
type = types.bool;
# broken :(
default = false;
};
2022-09-28 21:10:09 +02:00
};
2022-09-28 21:10:09 +02:00
nncp = {
neigh = mkOption {
type = with types; attrsOf neighMod;
default = { };
description = ''
Attrset of NNCP neighbours for relaying packets.
User endpoints go in <literal>c3d2.users</literal>.
'';
2022-01-18 15:39:35 +01:00
};
2022-09-28 21:10:09 +02:00
};
2022-01-18 15:39:35 +01:00
simd = {
enable = lib.mkEnableOption "optimized builds with simd instructions";
arch = lib.mkOption {
type = with lib.types; nullOr str;
default = null;
description = ''
Microarchitecture string for nixpkgs.hostPlatform.gcc.march and to generate system-features.
Can be determined with: gcc -march=native -Q --help=target | grep march
'';
};
};
sshKeys = mkOption {
type = with types; attrsOf (listOf str);
default = [ ];
};
2022-09-28 21:10:09 +02:00
};
2022-01-16 12:25:04 +01:00
config =
let
adminKeys = with builtins; lib.lists.flatten (attrValues cfg.sshKeys);
2022-01-16 12:25:04 +01:00
in
{
2022-09-28 21:10:09 +02:00
programs.nncp.settings = lib.optionalAttrs cfg.mergeNncpSettings cfg.nncp;
2022-01-18 15:39:35 +01:00
2022-01-16 12:25:04 +01:00
users.motd = lib.mkIf cfg.enableMotd (builtins.readFile ./motd);
users = {
users = {
k-ot = lib.mkIf cfg.k-ot.enable {
createHome = true;
isNormalUser = true;
uid = 1000;
extraGroups = [
"audio"
"video"
"wheel"
];
password = "k-otk-ot";
openssh.authorizedKeys.keys = adminKeys;
};
root.openssh.authorizedKeys.keys = lib.mkIf cfg.allUsersCanSshRoot adminKeys;
};
2022-01-16 12:25:04 +01:00
};
services.vector = lib.mkIf config.c3d2.hq.journalToMqtt {
enable = true;
journaldAccess = true;
settings = {
sources.journal = {
type = "journald";
current_boot_only = true;
};
sinks.mqtt = {
2022-09-28 21:10:09 +02:00
inputs = [ "journal" ];
type = "mqtt";
host = "broker.serv.zentralwerk.org";
# port = 8883;
user = "SECRET[mqtt.user]";
password = "SECRET[mqtt.password]";
client_id = "vector-${config.networking.hostName}";
encoding.codec = "json";
topic = "journal/{{ host }}/{{ _SYSTEMD_UNIT }}/{{ PRIORITY }}";
# tls.enabled = true;
# tls.ca_file = "/etc/ssl/certs/ca-certificates.crt";
};
secret.mqtt =
let
catSecrets = with pkgs; writeScript "cat-vector-secrets" ''
#!${runtimeShell} -e
echo '{'
COMMA=n
for F in $@; do
if [ $COMMA = y ]; then
echo ' ,'
else
COMMA=y
fi
echo ' "'$(basename $F)'": {"value": "'$(cat $F)'", "error": null }'
done
echo '}'
'';
2022-09-28 21:10:09 +02:00
in
{
type = "exec";
command = [
catSecrets
config.sops.secrets."mqtt/user".path
config.sops.secrets."mqtt/password".path
];
};
};
};
2022-12-19 01:08:09 +01:00
sops.secrets = lib.mkIf config.c3d2.hq.journalToMqtt {
"mqtt/user" = {
2022-09-28 21:10:09 +02:00
sopsFile = ../modules/mqtt.yaml;
owner = config.systemd.services.vector.serviceConfig.User;
};
"mqtt/password" = {
2022-09-28 21:10:09 +02:00
sopsFile = ../modules/mqtt.yaml;
owner = config.systemd.services.vector.serviceConfig.User;
};
};
2022-09-28 21:10:09 +02:00
boot.cleanTmpDir = true;
2022-09-28 21:16:59 +02:00
documentation.nixos.enable = false;
2022-09-28 21:10:09 +02:00
i18n = {
defaultLocale = "en_US.UTF-8";
supportedLocales = [
2022-12-19 02:27:42 +01:00
"en_US.UTF-8/UTF-8"
2022-09-28 21:16:50 +02:00
"de_DE.UTF-8/UTF-8"
2022-09-28 21:10:09 +02:00
];
};
systemd.network.networks = lib.mkIf (cfg.hq.interface != null && config.networking.useNetworkd) {
"40-eth0".routes = [{
routeConfig = {
Gateway = "172.22.99.4";
GatewayOnLink = true;
};
}];
};
networking = {
interfaces = lib.mkIf (cfg.hq.interface != null) {
"${cfg.hq.interface}".ipv6.addresses = [{
address = toHqPrivateAddress config.networking.hostName;
prefixLength = 64;
}];
};
nameservers = with hostRegistry.dnscache; [
2022-09-28 21:10:09 +02:00
ip4
ip6
"9.9.9.9"
];
useHostResolvConf = lib.mkIf (!config.services.resolved.enable) true;
};
environment.etc."resolv.conf" = lib.mkIf (!config.services.resolved.enable) {
text = lib.concatMapStrings
(ns: ''
nameserver ${ns}
'')
config.networking.nameservers;
};
nix = {
settings = {
2022-12-14 20:55:02 +01:00
builders-use-substitutes = true;
connect-timeout = 20;
experimental-features = "nix-command flakes";
fallback = true;
2022-12-19 01:08:09 +01:00
trusted-public-keys = [
"nix-serve.hq.c3d2.de:KZRGGnwOYzys6pxgM8jlur36RmkJQ/y8y62e52fj1ps="
2022-09-28 21:10:09 +02:00
];
2022-12-19 01:08:09 +01:00
# don't self feed hydra
2022-09-28 21:10:09 +02:00
substituters = lib.mkIf (config.networking.hostName != "hydra") (
lib.mkBefore [ "https://nix-serve.hq.c3d2.de" ]
);
};
gc = {
automatic = lib.mkDefault true;
2022-09-28 21:10:09 +02:00
dates = "06:00";
options = "--delete-older-than 21d";
randomizedDelaySec = "6h";
};
registry.c3d2 = {
from = {
id = "c3d2";
type = "indirect";
};
to = {
type = "git";
url = "https://gitea.c3d2.de/C3D2/nix-config.git";
};
};
};
services.openssh = {
2022-12-19 01:08:09 +01:00
# Required for deployment and sops
2022-09-28 21:10:09 +02:00
enable = true;
permitRootLogin = "prohibit-password";
};
sops.age.sshKeyPaths = lib.mkDefault [ "/etc/ssh/ssh_host_ed25519_key" ];
environment = {
noXlibs = (!lib.any (host: host == config.networking.hostName) [ "dacbert" "glotzbert" "rpi-netboot" ]);
2022-09-28 21:10:09 +02:00
systemPackages = with pkgs; [
2022-12-12 23:51:18 +01:00
bmon
2022-09-28 21:10:09 +02:00
curl
2022-12-18 23:41:34 +01:00
dig
2022-12-12 23:51:18 +01:00
ethtool
2022-09-28 21:10:09 +02:00
git
htop
iotop
2022-12-12 23:51:18 +01:00
mtr
pv
2022-09-28 21:10:09 +02:00
ripgrep
screen
tcpdump
2022-12-12 23:51:18 +01:00
tmux
tree
vim
wget
2022-09-28 21:10:09 +02:00
];
};
programs = {
2022-12-19 00:06:03 +01:00
fzf.keybindings = true;
ssh.knownHosts =
2022-09-28 21:10:09 +02:00
let
hosts = (import ../ssh-public-keys.nix).hosts;
2022-09-28 21:10:09 +02:00
list = map
(name: {
inherit name;
value =
let
ip6 = if zentralwerk.lib.config.site.net-combined.hosts6 ? name then
zentralwerk.lib.config.site.net.hosts6.${name}
else
toHqPrivateAddress name;
in
{
publicKey = lib.head (lib.getAttr name hosts);
hostNames = [ ip6 "${name}.hq.c3d2.de" name ];
};
2022-09-28 21:10:09 +02:00
})
(builtins.attrNames hosts);
keyedHosts = lib.filter (x: x.value.publicKey != null || x.value.publicKeyFile != null) list;
2022-09-28 21:10:09 +02:00
in
lib.listToAttrs keyedHosts;
2022-09-28 21:10:09 +02:00
vim.defaultEditor = true;
};
time.timeZone = lib.mkDefault "Europe/Berlin";
# Reboot on hang
systemd.watchdog = lib.mkIf (!config.boot.isContainer) {
runtimeTime = "15s";
rebootTime = "15s";
};
2022-12-19 01:08:09 +01:00
security.acme = {
acceptTerms = true;
defaults = {
email = "mail@c3d2.de";
# letsencrypt staging server with way higher rate limits
# server = "https://acme-staging-v02.api.letsencrypt.org/directory";
2022-09-28 21:10:09 +02:00
};
2022-12-19 01:08:09 +01:00
};
2022-09-28 21:10:09 +02:00
zramSwap.enable = true;
2022-01-16 12:25:04 +01:00
};
}