Compare commits

...

10 commits

106 changed files with 988 additions and 1375 deletions

View file

@ -1,37 +0,0 @@
let
internalWireGuard = import ../wireguard/chaosInternalWireGuard.nix;
ports = import ./pipedClusterPorts.nix;
in rec {
inherit ports;
hosts = {
# map of hostname to config for cluster node
"piped-fi" = rec {
ip = "${internalWireGuard.hosts.hetzner-vm.ip}";
# ssh -L 3014:127.0.0.1:3014 -L 26257:127.0.0.1:26257 hetzner-vm
joinString = "${ip}:${toString ports.cockroachDB}";
advertiseAddr = joinString;
resticBucket = "Piped-Finland";
vaultUserName = "hetzner-vm-container-piped-fi";
baseDomain = "piped-fi.owo.monster";
};
"piped-uk" = rec {
ip = "${internalWireGuard.hosts.raspberry.ip}";
# ssh -L 3014:127.0.0.1:3014 -L 26257:127.0.0.1:26257 raspberry
joinString = "${ip}:${toString ports.cockroachDB}";
advertiseAddr = joinString;
resticBucket = "Piped-UK";
vaultUserName = "rapsberry-container-piped-uk";
baseDomain = "piped-uk.owo.monster";
};
};
}

View file

@ -1,8 +0,0 @@
{
internalPipedBackend = 3012;
internalPipedProxy = 3013;
cockroachDB = 26257;
cockroachDB_HTTP = 3014;
cockroachDB_HAProxy = 26258;
}

View file

@ -1,8 +1,4 @@
rec { rec {
"hetzner-vm" = {
ipv4 = "65.21.182.73";
ipv6 = "2a01:4f9:c010:8beb::1";
};
"hetzner-arm" = { "hetzner-arm" = {
ipv4 = "65.21.145.62"; ipv4 = "65.21.145.62";
ipv6 = "2a01:4f9:c012:9dbf::1"; ipv6 = "2a01:4f9:c012:9dbf::1";

View file

@ -2,10 +2,10 @@ let
pubkeys = builtins.fromJSON (builtins.readFile ./chaosInternalWireGuardPubKeys.json); pubkeys = builtins.fromJSON (builtins.readFile ./chaosInternalWireGuardPubKeys.json);
in rec { in rec {
hosts = { hosts = {
"hetzner-vm" = { "hetzner-arm" = {
ip = "10.69.42.1"; ip = "10.69.42.1";
public = pubkeys."hetzner-vm"; public = pubkeys."hetzner-arm";
endpoint = "hetzner-vm.servers.genderfucked.monster:51820"; endpoint = "hetzner-arm.servers.genderfucked.monster:51820";
}; };
"vault" = { "vault" = {
ip = "10.69.42.2"; ip = "10.69.42.2";
@ -25,11 +25,5 @@ in rec {
public = pubkeys."raspberry"; public = pubkeys."raspberry";
endpoint = "raspberry.servers.genderfucked.monster:51820"; endpoint = "raspberry.servers.genderfucked.monster:51820";
}; };
# TODO: make this .1 again after migration like hetzner-vm
"hetzner-arm" = {
ip = "10.69.42.6";
public = pubkeys."hetzner-arm";
endpoint = "hetzner-arm.servers.genderfucked.monster:51820";
};
}; };
} }

View file

@ -1,8 +1,7 @@
{ {
"hetzner-vm": "xgOQQcZQXftPC25+A7Iyf/XK6/iSo3Osyx6kTrZKdzw=", "vault": "0jGdR0yBnjY5CUCQpqWIaWAfgT36QdGdhZXtaAV+MkE=",
"vault": "u8hSeht8xR48O9AN+0cSsXPK0ZZFNcnPhOxdc+rsrlI=", "raspberry": "DXXUfkR4qlytdsf37NGzgzVhDxPuhz8oxRcSxOX2fQk=",
"raspberry": "Ghrs0ps2RCsg0My9seLq+8ZFZCM4NLZWE8RiY3g9/RU=", "lappy-t495": "kyykcuDMWy1WRxX97PImEYgwWw8HUbhM53kW6bEyryA=",
"lappy-t495": "8aZBM3f8/qThiHvGlGP1IHLoe61m/3VTwNzCi7CrhF8=", "iphone8": "1u/G60EWg2bo1iyViWAGXs8HXES2zenZCVdD5X+yJi4=",
"iphone8": "jHPQuWXO5TTBACr4o/tk4bpb+N/x/AjCPGbmqkopOko=", "hetzner-arm": "rCkptlaz5IFSZ+4OPaylbyKVoUwYNWBNkaT63QApymA="
"hetzner-arm": "2SS9jT6Sba61lB2ayhp+2fz+GN706Jr1Ydr6/RveqUQ="
} }

View file

@ -47,11 +47,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1694166985, "lastModified": 1695831427,
"narHash": "sha256-8tVqDfKfZ4vbOV5i+E2xWhiNAQVJhaI6shx3e0925S8=", "narHash": "sha256-wyWgooFXg8SLF1DYMLU4JP6aB/zkwRCLBajO8sIeHQM=",
"owner": "ChaotiCryptidz", "owner": "ChaotiCryptidz",
"repo": "gitlab_archiver", "repo": "gitlab_archiver",
"rev": "4aac975a7cc375084c7f9eb4bc60a1c0948c1c28", "rev": "090ace071629556b50087a2e80f9255340b286df",
"type": "gitlab" "type": "gitlab"
}, },
"original": { "original": {
@ -73,11 +73,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1694166776, "lastModified": 1695831616,
"narHash": "sha256-wMTnkW98Fx/BpRpSABf9b0PlruVnzd4m3zEQaopE2+o=", "narHash": "sha256-86pme6c8WtplRoZVcZp/zjsq9XnGuBjPrO6V/pAmW94=",
"owner": "ChaotiCryptidz", "owner": "ChaotiCryptidz",
"repo": "gitlab_artifacts_sync", "repo": "gitlab_artifacts_sync",
"rev": "09a5988927a3493585357f5d61abdce3a9e4da17", "rev": "5099274ccff8fae50979ce94eb5287c3dcf5b914",
"type": "gitlab" "type": "gitlab"
}, },
"original": { "original": {
@ -93,11 +93,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1694643239, "lastModified": 1695738267,
"narHash": "sha256-pv2k/5FvyirDE8g4TNehzwZ0T4UOMMmqWSQnM/luRtE=", "narHash": "sha256-LTNAbTQ96xSj17xBfsFrFS9i56U2BMLpD0BduhrsVkU=",
"owner": "nix-community", "owner": "nix-community",
"repo": "home-manager", "repo": "home-manager",
"rev": "d9b88b43524db1591fb3d9410a21428198d75d49", "rev": "0f4e5b4999fd6a42ece5da8a3a2439a50e48e486",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -119,11 +119,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1694166910, "lastModified": 1695831628,
"narHash": "sha256-6Vxz6H4H3bfl1PUCeHTmIKg96PHwJEzkE7XRN09y5nM=", "narHash": "sha256-UyVJXVWjbZ4TLgCeOVYUE44ekfD5duUfA2akoc1VGj0=",
"owner": "ChaotiCryptidz", "owner": "ChaotiCryptidz",
"repo": "musicutil", "repo": "musicutil",
"rev": "7580e1fd0164e414a11e03c1037b37722160df25", "rev": "0e9aceb2b9b418f876a5fcd549420edbf8e8fdcb",
"type": "gitlab" "type": "gitlab"
}, },
"original": { "original": {
@ -134,11 +134,11 @@
}, },
"nixpkgs-unstable": { "nixpkgs-unstable": {
"locked": { "locked": {
"lastModified": 1694669921, "lastModified": 1695644571,
"narHash": "sha256-6ESpJ6FsftHV96JO/zn6je07tyV2dlLR7SdLsmkegTY=", "narHash": "sha256-asS9dCCdlt1lPq0DLwkVBbVoEKuEuz+Zi3DG7pR/RxA=",
"owner": "nixos", "owner": "nixos",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "f2ea252d23ebc9a5336bf6a61e0644921f64e67c", "rev": "6500b4580c2a1f3d0f980d32d285739d8e156d92",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -150,11 +150,11 @@
}, },
"nur": { "nur": {
"locked": { "locked": {
"lastModified": 1694778311, "lastModified": 1695844033,
"narHash": "sha256-Hu5U9pXwMqUjWF7uh4SKqdKy1QMy9RVGxmst11srSgA=", "narHash": "sha256-UX5sbK9dc/bOupgDGWer75zBjoh7eWIheyGGCjD7FIg=",
"owner": "nix-community", "owner": "nix-community",
"repo": "NUR", "repo": "NUR",
"rev": "7a673ac1f35648a908730206a2793b0e3818bc25", "rev": "f08568d903901b7ac1017572b9af9855e935155a",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -176,11 +176,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1695142252, "lastModified": 1695847501,
"narHash": "sha256-rcYxKVb6Mpna3xNSwRHMw/Yzw3tky0+JuMLM5qoBiUw=", "narHash": "sha256-UxYiNfUApZ6IYJ0U83CzRBSRvmApDHMWa5o9WT99ukM=",
"owner": "ChaotiCryptidz", "owner": "ChaotiCryptidz",
"repo": "piped-flake", "repo": "piped-flake",
"rev": "994a8e983eef9071d73c9b2daad9bd42aac0b1aa", "rev": "2a03d86df5075f5060704bb68742af2ace8973e3",
"type": "gitlab" "type": "gitlab"
}, },
"original": { "original": {
@ -268,11 +268,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1694618271, "lastModified": 1695831820,
"narHash": "sha256-8y2/x27QkhRtTZ/3A0HOmfNJT0hDSk+2ZSGyKB46Q40=", "narHash": "sha256-ZhSQqGg32WA/WYsjPMuYU96GgyljszPcjvc+GBLZVpY=",
"owner": "ChaotiCryptidz", "owner": "ChaotiCryptidz",
"repo": "VaultUI", "repo": "VaultUI",
"rev": "6365eb49cec7eb8a76a24160b25363cf4a8bfa40", "rev": "d5fc05612e44cc2c8307186b0d36f7022d7a2f91",
"type": "gitlab" "type": "gitlab"
}, },
"original": { "original": {

View file

@ -106,10 +106,7 @@ in {
# browser toolbar and UI # browser toolbar and UI
# may need updating when extensions change # may need updating when extensions change
"browser.toolbars.bookmarks.visibility" = "always"; "browser.toolbars.bookmarks.visibility" = "always";
"layout.css.devPixelsPerPx" = "layout.css.devPixelsPerPx" = "1.4";
if nixosConfig.networking.hostName == "lappy-t495"
then "1.4"
else "1.8";
"browser.uiCustomization.state" = builtins.toJSON { "browser.uiCustomization.state" = builtins.toJSON {
currentVersion = 18; currentVersion = 18;
dirtyAreaCache = [ dirtyAreaCache = [

View file

@ -7,22 +7,22 @@
inherit (lib.lists) forEach; inherit (lib.lists) forEach;
inherit (builtins) attrNames; inherit (builtins) attrNames;
containerAddresses = import "${self}/hosts/hetzner-vm/data/containerAddresses.nix"; containerAddresses = import "${self}/hosts/hetzner-arm/data/containerAddresses.nix";
in { in {
programs.ssh.enable = true; programs.ssh.enable = true;
programs.ssh.matchBlocks = programs.ssh.matchBlocks =
mkMerge mkMerge
((forEach ["hetzner-vm" "vault" "raspberry" "vault-decrypt"] (hostname: { ((forEach ["hetzner-arm" "hetzner-arm-decrypt" "vault" "vault-decrypt" "raspberry"] (hostname: {
"${hostname}" = { "${hostname}" = {
user = "root"; user = "root";
hostname = "${hostname}.servers.genderfucked.monster"; hostname = "${hostname}.servers.genderfucked.monster";
}; };
})) }))
++ (forEach (attrNames containerAddresses.containers) (name: { ++ (forEach (attrNames containerAddresses.containers) (name: {
"hetzner-vm-container-${name}" = { "hetzner-arm-container-${name}" = {
user = "root"; user = "root";
hostname = "${containerAddresses.containers.${name}}"; hostname = "${containerAddresses.containers.${name}}";
proxyJump = "hetzner-vm"; proxyJump = "hetzner-arm";
}; };
})) }))
++ [ ++ [

View file

@ -7,6 +7,7 @@
tmux tmux
socat socat
file file
python3
binutils # for strings binutils # for strings
# (pkgs.busybox.override {enableAppletSymlinks = false;}) # (pkgs.busybox.override {enableAppletSymlinks = false;})

View file

@ -1,10 +1,21 @@
{pkgs, ...}: { {pkgs, ...}: let
gitPackage = pkgs.gitAndTools.gitFull;
in {
programs.git = { programs.git = {
enable = true; enable = true;
lfs.enable = true; lfs.enable = true;
package = pkgs.gitAndTools.gitFull; package = gitPackage;
userName = "chaos"; userName = "chaos";
userEmail = "chaoticryptidz@owo.monster"; userEmail = "chaos@owo.monster";
extraConfig = {credential = {helper = "store";};}; extraConfig = {credential.helper = "store";};
}; };
home.packages = [
(pkgs.runCommand "git-extras" {} (let
gitLibExec = "${gitPackage}/libexec/git-core";
in ''
mkdir -p $out/bin
ln -s ${gitLibExec}/git-diff $out/bin/git-diff
''))
];
} }

View file

@ -1,3 +1,3 @@
{pkgs, ...}: { {pkgs, ...}: {
home.packages = with pkgs; [neofetch inxi htop pciutils usbutils iotop iptraf-ng]; home.packages = with pkgs; [neofetch inxi btop htop pciutils usbutils iotop iptraf-ng];
} }

View file

@ -9,5 +9,7 @@
openssh openssh
nmap nmap
tcpdump tcpdump
iftop
speedtest-cli
]; ];
} }

View file

@ -3,8 +3,12 @@
nixosConfig, nixosConfig,
pkgs, pkgs,
inputs, inputs,
lib,
... ...
}: let }: let
inherit (lib.lists) optional;
inherit (lib.modules) mkIf;
homeManagerLib = inputs.home-manager.lib.hm; homeManagerLib = inputs.home-manager.lib.hm;
fontSizesAll = { fontSizesAll = {
@ -18,10 +22,16 @@
if fontSizesAll ? nixosConfig.networking.hostName if fontSizesAll ? nixosConfig.networking.hostName
then fontSizesAll.${nixosConfig.networking.hostName} then fontSizesAll.${nixosConfig.networking.hostName}
else fontSizesAll.default; else fontSizesAll.default;
in {
imports = with tree; [home.gui.base home.apps.kitty];
home.packages = with pkgs; [dconf2nix gnome.dconf-editor xclip]; isWayland = nixosConfig.services.xserver.displayManager.gdm.wayland;
in {
imports = with tree; [home.gui.base home.apps.kitty] ++ (optional isWayland home.apps.rofi);
home.packages = with pkgs; [
dconf2nix
gnome.dconf-editor
xclip
];
home.sessionVariables = { home.sessionVariables = {
SAL_USE_VCLPLUGIN = "gtk3"; # GTK3 on LibreOffice SAL_USE_VCLPLUGIN = "gtk3"; # GTK3 on LibreOffice
@ -126,17 +136,18 @@ in {
area-screenshot-clip = ["<Shift>Print"]; area-screenshot-clip = ["<Shift>Print"];
screenshot = []; screenshot = [];
screenshot-clip = ["Print"]; screenshot-clip = ["Print"];
search = mkIf isWayland ["<Alt>d"];
custom-keybindings = [ custom-keybindings = [
# Rofi & Kitty # Rofi & Kitty
#"/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/rofi/" "/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/rofi/"
"/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/kitty/" "/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/kitty/"
]; ];
}; };
#"org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/rofi" = { "org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/rofi" = mkIf (!isWayland) {
# binding = "<Alt>d"; binding = "<Alt>d";
# command = "rofi -show run"; command = "rofi -show run";
# name = "rofi"; name = "rofi";
#}; };
"org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/kitty" = { "org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/kitty" = {
binding = "<Alt>Return"; binding = "<Alt>Return";
command = "kitty"; command = "kitty";

View file

@ -8,8 +8,7 @@
hostPath, hostPath,
... ...
}: let }: let
inherit (lib.modules) mkMerge; inherit (lib.modules) mkMerge mkForce;
inherit (lib.lists) forEach;
ports = [ ports = [
# SMTP # SMTP
@ -26,20 +25,6 @@
4190 4190
]; ];
containerLib = import "${self}/lib/containerLib.nix" {
inherit lib;
};
# Using secrets from Host
secrets = config.services.secrets.secrets;
secretsList = [
"mail_restic_password"
"mail_restic_env"
"private_mail_aliases"
"chaos_mail_passwd"
"system_mail_passwd"
"gotosocial_mail_passwd"
];
sharedFiles = [ sharedFiles = [
"/var/lib/acme/mail.owo.monster/fullchain.pem" "/var/lib/acme/mail.owo.monster/fullchain.pem"
"/var/lib/acme/mail.owo.monster/key.pem" "/var/lib/acme/mail.owo.monster/key.pem"
@ -48,74 +33,51 @@ in {
containers.mail = { containers.mail = {
autoStart = true; autoStart = true;
bindMounts = mkMerge [ bindMounts = mkMerge (map (file: {
(containerLib.genBindHostsForSecrets secrets secretsList)
(mkMerge (forEach sharedFiles (file: {
"${file}" = { "${file}" = {
hostPath = "${file}"; hostPath = "${file}";
}; };
}))) })
]; sharedFiles);
specialArgs = { specialArgs = {
inherit inputs; inherit inputs;
inherit tree; inherit tree;
inherit self; inherit self;
inherit hostPath; inherit hostPath;
hostSecrets = secrets;
}; };
config = {config, ...}: { config = {...}: {
nixpkgs.pkgs = pkgs; nixpkgs.pkgs = pkgs;
imports = with tree; imports = with tree;
[ [
profiles.base presets.nixos.containerBase
inputs.home-manager-unstable.nixosModules.home-manager
profiles.nginx profiles.nginx
modules.nixos.secrets
users.root ./secrets.nix
] ]
++ (with hosts.hetzner-vm.containers.mail; [ ++ (with hosts.hetzner-arm.containers.mail; [
modules.mailserver modules.mailserver
profiles.mailserver profiles.mailserver
profiles.restic profiles.restic
]); ]);
# For Shared Secrets
systemd.tmpfiles.rules = [ systemd.tmpfiles.rules = [
"d ${config.services.secrets.secretsDir} - root root"
"d /var/lib/acme - root root" "d /var/lib/acme - root root"
"d /var/lib/acme/mail.owo.monster - root root" "d /var/lib/acme/mail.owo.monster - root root"
]; ];
networking.firewall = { networking.firewall = {
enable = false; enable = mkForce false;
}; };
home-manager.users.root = { home-manager.users.root.home.stateVersion = "23.05";
imports = with tree; [home.base home.dev.small];
home.stateVersion = "23.05";
};
# Manually configure nameserver. Using resolved inside the container seems to fail
# currently
environment.etc."resolv.conf".text = "nameserver 8.8.8.8";
system.stateVersion = "23.05"; system.stateVersion = "23.05";
}; };
}; };
# users for secrets
users.users."dovecot2" = {
uid = config.ids.uids.dovecot2;
group = "dovecot2";
};
users.groups."dovecot2".gid = config.ids.gids.dovecot2;
# ssl for mail # ssl for mail
services.nginx = { services.nginx = {
enable = true; enable = true;

View file

@ -1,9 +1,9 @@
{ {
pkgs, pkgs,
hostSecrets, config,
... ...
}: let }: let
secrets = hostSecrets; secrets = config.services.secrets.secrets;
in { in {
services.mailserver = { services.mailserver = {
enable = true; enable = true;

View file

@ -1,11 +1,12 @@
{ {
pkgs, pkgs,
config, config,
hostSecrets,
... ...
}: let }: let
secrets = hostSecrets; secrets = config.services.secrets.secrets;
mailConfig = config.services.mailserver; mailConfig = config.services.mailserver;
backupPrepareCommand = "${ backupPrepareCommand = "${
(pkgs.writeShellScriptBin "backupPrepareCommand" '' (pkgs.writeShellScriptBin "backupPrepareCommand" ''
systemctl start postgresqlBackup-roundcube --wait systemctl start postgresqlBackup-roundcube --wait
@ -16,8 +17,8 @@ in {
restic restic
(pkgs.writeShellScriptBin "restic-mail" '' (pkgs.writeShellScriptBin "restic-mail" ''
env \ env \
RESTIC_PASSWORD_FILE=${secrets.mail_restic_password.path} \ RESTIC_PASSWORD_FILE=${secrets.restic_password.path} \
$(cat ${secrets.mail_restic_env.path}) \ $(cat ${secrets.restic_env.path}) \
${pkgs.restic}/bin/restic $@ ${pkgs.restic}/bin/restic $@
'') '')
]; ];
@ -36,8 +37,8 @@ in {
# repository is overrided in environmentFile to contain auth # repository is overrided in environmentFile to contain auth
# make sure to keep up to date when changing repository # make sure to keep up to date when changing repository
repository = "rest:https://storage-restic.owo.monster/Mail"; repository = "rest:https://storage-restic.owo.monster/Mail";
passwordFile = "${secrets.mail_restic_password.path}"; passwordFile = "${secrets.restic_password.path}";
environmentFile = "${secrets.mail_restic_env.path}"; environmentFile = "${secrets.restic_env.path}";
pruneOpts = [ pruneOpts = [
"--keep-last 5" "--keep-last 5"

View file

@ -0,0 +1,75 @@
{pkgs, ...}: {
services.secrets = {
enable = true;
vaultLogin = {
enable = true;
loginUsername = "hetzner-arm-container-mail";
};
autoSecrets = {
enable = true;
};
requiredVaultPaths = [
"api-keys/data/storage/restic/Mail"
"api-keys/data/chaos_mail/system"
"api-keys/data/chaos_mail/gotosocial"
"passwords/data/mail"
"private-public-keys/data/restic/Mail"
"infra/data/private-mail-aliases"
];
packages = with pkgs; [
apacheHttpd
];
secrets = {
vault_password = {
manual = true;
};
restic_password = {
fetchScript = ''
simple_get "/private-public-keys/restic/Mail" .password > "$secretFile"
'';
};
restic_env = {
fetchScript = ''
RESTIC_USERNAME=$(simple_get "/api-keys/storage/restic/Mail" .username)
RESTIC_PASSWORD=$(simple_get "/api-keys/storage/restic/Mail" .password)
echo "RESTIC_REPOSITORY=rest:https://$RESTIC_USERNAME:$RESTIC_PASSWORD@storage-restic.owo.monster/Mail" > "$secretFile"
'';
};
private_mail_aliases = {
fetchScript = ''
kv_get "/infra/private-mail-aliases" | jq .data.data | jq -r 'to_entries|map("\(.key) \(.value.to)")[]' > "$secretFile"
'';
};
chaos_mail_passwd = {
user = "dovecot2";
group = "dovecot2";
fetchScript = ''
password=$(simple_get "/passwords/mail" .password)
htpasswd -nbB "" "$password" 2>/dev/null | cut -d: -f2 > "$secretFile"
'';
};
system_mail_passwd = {
user = "dovecot2";
group = "dovecot2";
fetchScript = ''
password=$(simple_get "/api-keys/chaos_mail/system" .password)
htpasswd -nbB "" "$password" 2>/dev/null | cut -d: -f2 > "$secretFile"
'';
};
gotosocial_mail_passwd = {
user = "dovecot2";
group = "dovecot2";
fetchScript = ''
password=$(simple_get "/api-keys/chaos_mail/gotosocial" .password)
htpasswd -nbB "" "$password" 2>/dev/null | cut -d: -f2 > "$secretFile"
'';
};
};
};
}

View file

@ -4,50 +4,40 @@
tree, tree,
lib, lib,
inputs, inputs,
config,
pkgs, pkgs,
config,
... ...
}: let }: let
inherit (lib.modules) mkMerge; inherit (lib.modules) mkMerge;
inherit (lib.lists) forEach; inherit (lib.lists) forEach;
containerName = "music";
containerAddresses = import "${hostPath}/data/containerAddresses.nix"; containerAddresses = import "${hostPath}/data/containerAddresses.nix";
hostIP = containerAddresses.host; hostIP = containerAddresses.host;
containerIP = containerAddresses.containers.${containerName}; containerIP = containerAddresses.containers.${containerName};
containerName = "music";
containerConfig = config.containers.${containerName}.config;
containerLib = import "${self}/lib/containerLib.nix" {
inherit lib;
};
# Using secrets from Host
secrets = config.services.secrets.secrets;
secretsList = [
"mpd_control_password"
"slskd_env"
];
ports = import ./data/ports.nix; ports = import ./data/ports.nix;
# these secrets should probs be in host but im lazy
containerSecrets = config.containers.${containerName}.config.services.secrets.secrets;
pathInContainer = path: "/var/lib/nixos-containers/${containerName}" + path;
in { in {
containers.music = { containers.music = {
autoStart = true; autoStart = true;
privateNetwork = true; privateNetwork = true;
hostAddress = hostIP; hostAddress = hostIP;
localAddress = containerIP; localAddress = containerIP;
bindMounts = containerLib.genBindHostsForSecrets secrets secretsList;
specialArgs = { specialArgs = {
inherit inputs; inherit inputs;
inherit tree; inherit tree;
inherit self; inherit self;
inherit hostPath; inherit hostPath;
hostSecrets = secrets;
}; };
config = {config, ...}: { config = {...}: {
nixpkgs.pkgs = pkgs; nixpkgs.pkgs = pkgs;
imports = with tree; imports = with tree;
@ -58,8 +48,10 @@ in {
profiles.nginx profiles.nginx
profiles.firewallAllow.httpCommon profiles.firewallAllow.httpCommon
./secrets.nix
] ]
++ (with hosts.hetzner-vm.containers.music; [ ++ (with hosts.hetzner-arm.containers.music; [
profiles.mpd profiles.mpd
profiles.musicSync profiles.musicSync
profiles.soulseek profiles.soulseek
@ -75,11 +67,6 @@ in {
slskd-web slskd-web
]; ];
# For Shared Secrets
systemd.tmpfiles.rules = [
"d ${config.services.secrets.secretsDir} - root root"
];
home-manager.users.root.home.stateVersion = "23.05"; home-manager.users.root.home.stateVersion = "23.05";
system.stateVersion = "23.05"; system.stateVersion = "23.05";
}; };
@ -97,7 +84,7 @@ in {
services.nginx.virtualHosts."stream.owo.monster" = let services.nginx.virtualHosts."stream.owo.monster" = let
extraConfig = '' extraConfig = ''
auth_basic "Music Password"; auth_basic "Music Password";
auth_basic_user_file ${secrets.music_stream_passwd.path}; auth_basic_user_file ${pathInContainer containerSecrets.music_stream_passwd.path};
''; '';
in { in {
forceSSL = true; forceSSL = true;
@ -118,15 +105,6 @@ in {
}))); })));
}; };
# For permissions of secrets
users.users."mpd" = {
uid = containerConfig.ids.uids.mpd;
group = "mpd";
};
users.groups."mpd" = {
gid = containerConfig.ids.gids.mpd;
};
networking = { networking = {
nat.forwardPorts = [ nat.forwardPorts = [
{ {

View file

@ -1,14 +1,14 @@
{ {
lib, lib,
pkgs, pkgs,
hostSecrets, config,
... ...
}: let }: let
inherit (lib.strings) concatStringsSep; inherit (lib.strings) concatStringsSep;
inherit (lib.lists) forEach; inherit (lib.lists) forEach;
ports = import ../data/ports.nix; ports = import ../data/ports.nix;
secrets = hostSecrets; secrets = config.services.secrets.secrets;
in { in {
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [
mpc_cli mpc_cli

View file

@ -1,10 +1,10 @@
{ {
lib, lib,
hostSecrets, config,
... ...
}: let }: let
ports = import ../data/ports.nix; ports = import ../data/ports.nix;
secrets = hostSecrets; secrets = config.services.secrets.secrets;
inherit (lib.modules) mkForce; inherit (lib.modules) mkForce;
in { in {

View file

@ -0,0 +1,57 @@
{pkgs, ...}: {
services.secrets = {
enable = true;
vaultLogin = {
enable = true;
loginUsername = "hetzner-arm-container-music";
};
autoSecrets = {
enable = true;
};
requiredVaultPaths = [
"api-keys/data/mpd"
"api-keys/data/music-stream"
"passwords/data/soulseek"
"passwords/data/slskd"
];
packages = with pkgs; [
apacheHttpd
];
secrets = {
vault_password = {
manual = true;
};
mpd_control_password = {
user = "mpd";
group = "mpd";
fetchScript = ''
simple_get "/api-keys/mpd" .password > "$secretFile"
'';
};
music_stream_passwd = {
user = "nginx";
group = "nginx";
fetchScript = ''
username=$(simple_get "/api-keys/music-stream" .username)
password=$(simple_get "/api-keys/music-stream" .password)
htpasswd -bc "$secretFile" "$username" "$password" 2>/dev/null
'';
};
slskd_env = {
fetchScript = ''
soulseek_password=$(simple_get "/passwords/soulseek" .password)
slskd_password=$(simple_get "/passwords/slskd" .password)
echo > "$secretFile"
echo "SLSKD_SLSK_PASSWORD=$soulseek_password" >> "$secretFile"
echo "SLSKD_PASSWORD=$slskd_password" >> "$secretFile"
'';
};
};
};
}

View file

@ -0,0 +1,41 @@
{
self,
hostPath,
tree,
inputs,
config,
pkgs,
lib,
...
}: let
inherit (lib.modules) mkForce;
in {
containers.piped-db = {
autoStart = true;
privateNetwork = false;
specialArgs = {
inherit inputs;
inherit tree;
inherit self;
inherit hostPath;
};
config = {...}: {
nixpkgs.pkgs = pkgs;
imports = with tree; [
presets.nixos.containerBase
./secrets.nix
./profiles/postgres.nix
./profiles/restic.nix
];
networking.firewall.enable = mkForce false;
home-manager.users.root.home.stateVersion = "23.05";
system.stateVersion = "23.05";
};
};
}

View file

@ -0,0 +1,21 @@
{self, ...}: let
wireguardData = import "${self}/data/wireguard/chaosInternalWireGuard.nix";
wireguardHosts = wireguardData.hosts;
in {
services.postgresql = {
enable = true;
port = 5434;
enableTCPIP = true;
ensureUsers = [
{
name = "piped";
ensurePermissions."DATABASE piped" = "ALL PRIVILEGES";
}
];
ensureDatabases = ["piped"];
authentication = ''
host piped piped ${wireguardHosts."raspberry".ip}/32 trust
host piped piped ${wireguardHosts."hetzner-arm".ip}/32 trust
'';
};
}

View file

@ -0,0 +1,55 @@
{
pkgs,
config,
...
}: let
secrets = config.services.secrets.secrets;
backupPrepareCommand = "${
(pkgs.writeShellScriptBin "backupPrepareCommand" ''
systemctl start postgresqlBackup-piped --wait
'')
}/bin/backupPrepareCommand";
in {
environment.systemPackages = with pkgs; [
restic
(pkgs.writeShellScriptBin "restic-piped" ''
env \
RESTIC_PASSWORD_FILE=${secrets.restic_password.path} \
$(cat ${secrets.restic_env.path}) \
${pkgs.restic}/bin/restic $@
'')
];
services.restic.backups.piped = {
user = "root";
paths = [
"/var/backup/postgresql"
];
# repository is overrided in environmentFile to contain auth
# make sure to keep up to date when changing repository
repository = "rest:https://storage-restic.owo.monster/Piped";
passwordFile = "${secrets.restic_password.path}";
environmentFile = "${secrets.restic_env.path}";
pruneOpts = [
"--keep-last 5"
];
timerConfig = {
OnBootSec = "1m";
OnCalendar = "daily";
};
inherit backupPrepareCommand;
};
services.postgresqlBackup = {
enable = true;
backupAll = false;
pgdumpOptions = "-p ${toString config.services.postgresql.port}";
databases = ["piped"];
compression = "zstd";
};
}

View file

@ -0,0 +1,38 @@
{...}: {
services.secrets = {
enable = true;
vaultLogin = {
enable = true;
loginUsername = "hetzner-arm-container-piped-db";
};
autoSecrets = {
enable = true;
};
requiredVaultPaths = [
"api-keys/data/storage/restic/Piped"
"private-public-keys/data/restic/Piped"
];
secrets = {
vault_password = {
manual = true;
};
restic_password = {
fetchScript = ''
simple_get "/private-public-keys/restic/Piped" .password > "$secretFile"
'';
};
restic_env = {
fetchScript = ''
RESTIC_USERNAME=$(simple_get "/api-keys/storage/restic/Piped" .username)
RESTIC_PASSWORD=$(simple_get "/api-keys/storage/restic/Piped" .password)
echo "RESTIC_REPOSITORY=rest:https://$RESTIC_USERNAME:$RESTIC_PASSWORD@storage-restic.owo.monster/Piped" > "$secretFile"
'';
};
};
};
}

View file

@ -5,16 +5,19 @@
inputs, inputs,
config, config,
pkgs, pkgs,
lib,
... ...
}: let }: let
containerName = "piped-fi"; inherit (lib.modules) mkForce;
containerConfig = config.containers.${containerName}.config;
pipedName = "piped-fi";
containerName = pipedName;
pipedSocketForComponent = ( pipedSocketForComponent = (
component: "/var/lib/nixos-containers/${containerName}/var/sockets/piped-${component}.sock" component: "/var/lib/nixos-containers/${containerName}/var/sockets/piped-${component}.sock"
); );
in { in {
containers.piped-fi = { containers.${containerName} = {
autoStart = true; autoStart = true;
privateNetwork = false; privateNetwork = false;
@ -28,32 +31,19 @@ in {
config = {...}: { config = {...}: {
nixpkgs.pkgs = pkgs; nixpkgs.pkgs = pkgs;
imports = with tree; imports = with tree; [
[ presets.nixos.containerBase
presets.nixos.containerBase presets.nixos.pipedNode
profiles.nginx
profiles.firewallAllow.httpCommon
profiles.pipedCluster
./secrets.nix
]
++ (with hosts.hetzner-vm.containers.piped-fi.profiles; [
restic
]);
# For Shared Secrets
systemd.tmpfiles.rules = [
"d /var/lib/cockroachdb-certs - root root"
]; ];
networking.firewall.enable = mkForce false;
home-manager.users.root.home.stateVersion = "23.05"; home-manager.users.root.home.stateVersion = "23.05";
system.stateVersion = "23.05"; system.stateVersion = "23.05";
}; };
}; };
services.nginx.virtualHosts."piped-fi.owo.monster" = { services.nginx.virtualHosts."${pipedName}.owo.monster" = {
forceSSL = true; forceSSL = true;
enableACME = true; enableACME = true;
locations."/" = { locations."/" = {
@ -61,7 +51,7 @@ in {
}; };
}; };
services.nginx.virtualHosts."backend.piped-fi.owo.monster" = { services.nginx.virtualHosts."backend.${pipedName}.owo.monster" = {
forceSSL = true; forceSSL = true;
enableACME = true; enableACME = true;
locations."/" = { locations."/" = {
@ -69,7 +59,7 @@ in {
}; };
}; };
services.nginx.virtualHosts."proxy.piped-fi.owo.monster" = { services.nginx.virtualHosts."proxy.${pipedName}.owo.monster" = {
forceSSL = true; forceSSL = true;
enableACME = true; enableACME = true;
locations."/" = { locations."/" = {

View file

@ -2,7 +2,6 @@
self, self,
hostPath, hostPath,
tree, tree,
lib,
inputs, inputs,
config, config,
pkgs, pkgs,
@ -11,34 +10,21 @@
containerAddresses = import "${hostPath}/data/containerAddresses.nix"; containerAddresses = import "${hostPath}/data/containerAddresses.nix";
hostIP = containerAddresses.host; hostIP = containerAddresses.host;
containerIP = containerAddresses.containers.quassel; containerIP = containerAddresses.containers.quassel;
containerLib = import "${self}/lib/containerLib.nix" {
inherit lib;
};
# Using secrets from Host
secrets = config.services.secrets.secrets;
secretsList = [
"quassel_restic_env"
"quassel_restic_password"
];
in { in {
containers.quassel = { containers.quassel = {
autoStart = true; autoStart = true;
privateNetwork = true; privateNetwork = true;
hostAddress = hostIP; hostAddress = hostIP;
localAddress = containerIP; localAddress = containerIP;
bindMounts = containerLib.genBindHostsForSecrets secrets secretsList;
specialArgs = { specialArgs = {
inherit inputs; inherit inputs;
inherit tree; inherit tree;
inherit self; inherit self;
inherit hostPath; inherit hostPath;
hostSecrets = secrets;
}; };
config = {config, ...}: { config = {...}: {
nixpkgs.pkgs = pkgs; nixpkgs.pkgs = pkgs;
imports = with tree; imports = with tree;
@ -46,17 +32,14 @@ in {
presets.nixos.containerBase presets.nixos.containerBase
profiles.sshd profiles.sshd
profiles.firewallAllow.ssh profiles.firewallAllow.ssh
./secrets.nix
] ]
++ (with hosts.hetzner-vm.containers.quassel.profiles; [ ++ (with hosts.hetzner-arm.containers.quassel.profiles; [
quassel quassel
restic restic
]); ]);
# For Shared Secrets
systemd.tmpfiles.rules = [
"d ${config.services.secrets.secretsDir} - root root"
];
networking.firewall.allowedTCPPorts = [4242]; networking.firewall.allowedTCPPorts = [4242];
home-manager.users.root.home.stateVersion = "23.05"; home-manager.users.root.home.stateVersion = "23.05";

View file

@ -1,9 +1,9 @@
{ {
pkgs, pkgs,
hostSecrets, config,
... ...
}: let }: let
secrets = hostSecrets; secrets = config.services.secrets.secrets;
backupPrepareCommand = "${ backupPrepareCommand = "${
(pkgs.writeShellScriptBin "backupPrepareCommand" '' (pkgs.writeShellScriptBin "backupPrepareCommand" ''
@ -15,8 +15,8 @@ in {
restic restic
(pkgs.writeShellScriptBin "restic-quassel" '' (pkgs.writeShellScriptBin "restic-quassel" ''
env \ env \
RESTIC_PASSWORD_FILE=${secrets.quassel_restic_password.path} \ RESTIC_PASSWORD_FILE=${secrets.restic_password.path} \
$(cat ${secrets.quassel_restic_env.path}) \ $(cat ${secrets.restic_env.path}) \
${pkgs.restic}/bin/restic $@ ${pkgs.restic}/bin/restic $@
'') '')
]; ];
@ -31,8 +31,8 @@ in {
# repository is overrided in environmentFile to contain auth # repository is overrided in environmentFile to contain auth
# make sure to keep up to date when changing repository # make sure to keep up to date when changing repository
repository = "rest:https://storage-restic.owo.monster/Quassel"; repository = "rest:https://storage-restic.owo.monster/Quassel";
passwordFile = "${secrets.quassel_restic_password.path}"; passwordFile = "${secrets.restic_password.path}";
environmentFile = "${secrets.quassel_restic_env.path}"; environmentFile = "${secrets.restic_env.path}";
pruneOpts = [ pruneOpts = [
"--keep-last 5" "--keep-last 5"

View file

@ -0,0 +1,38 @@
{...}: {
services.secrets = {
enable = true;
vaultLogin = {
enable = true;
loginUsername = "hetzner-arm-container-quassel";
};
autoSecrets = {
enable = true;
};
requiredVaultPaths = [
"api-keys/data/storage/restic/Quassel"
"private-public-keys/data/restic/Quassel"
];
secrets = {
vault_password = {
manual = true;
};
restic_password = {
fetchScript = ''
simple_get "/private-public-keys/restic/Quassel" .password > "$secretFile"
'';
};
restic_env = {
fetchScript = ''
RESTIC_USERNAME=$(simple_get "/api-keys/storage/restic/Quassel" .username)
RESTIC_PASSWORD=$(simple_get "/api-keys/storage/restic/Quassel" .password)
echo "RESTIC_REPOSITORY=rest:https://$RESTIC_USERNAME:$RESTIC_PASSWORD@storage-restic.owo.monster/Quassel" > "$secretFile"
'';
};
};
};
}

View file

@ -0,0 +1,70 @@
{
self,
hostPath,
tree,
inputs,
config,
pkgs,
...
}: let
containerAddresses = import "${hostPath}/data/containerAddresses.nix";
hostIP = containerAddresses.host;
containerIP = containerAddresses.containers.social;
in {
containers.social = {
autoStart = true;
privateNetwork = true;
hostAddress = hostIP;
localAddress = containerIP;
specialArgs = {
inherit inputs;
inherit tree;
inherit self;
inherit hostPath;
};
config = {...}: {
nixpkgs.pkgs = pkgs;
imports = with tree;
[
presets.nixos.containerBase
profiles.sshd
profiles.firewallAllow.ssh
./secrets.nix
]
++ (with hosts.hetzner-arm.containers.social.profiles; [
gotosocial
restic
]);
networking.firewall = {
enable = true;
allowedTCPPorts = [8080];
};
home-manager.users.root.home.stateVersion = "23.05";
system.stateVersion = "23.05";
};
};
services.nginx.virtualHosts."gts-01.owo.monster" = {
forceSSL = true;
enableACME = true;
locations."/" = {
proxyPass = "http://${containerIP}:8080";
proxyWebsockets = true;
extraConfig = ''
# uncomment if running nginx without recommendedProxySettings
# proxy_set_header Host $host;
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# proxy_set_header X-Forwarded-Proto $scheme;
'';
};
extraConfig = ''
client_max_body_size 128M;
'';
};
}

View file

@ -1,18 +1,18 @@
{ {
hostPath, hostPath,
hostSecrets, config,
... ...
}: let }: let
containerAddresses = import "${hostPath}/data/containerAddresses.nix"; containerAddresses = import "${hostPath}/data/containerAddresses.nix";
hostIP = containerAddresses.host; hostIP = containerAddresses.host;
containerIP = containerAddresses.containers.social; containerIP = containerAddresses.containers.social;
secrets = hostSecrets; secrets = config.services.secrets.secrets;
in { in {
services.gotosocial = { services.gotosocial = {
enable = true; enable = true;
setupPostgresqlDB = true; setupPostgresqlDB = true;
environmentFile = secrets.social_env_secrets.path; environmentFile = secrets.env_secrets.path;
settings = { settings = {
application-name = "chaos-gts"; application-name = "chaos-gts";

View file

@ -2,13 +2,12 @@
pkgs, pkgs,
config, config,
lib, lib,
hostSecrets,
... ...
}: let }: let
inherit (lib.strings) concatStringsSep; inherit (lib.strings) concatStringsSep;
inherit (lib.lists) forEach; inherit (lib.lists) forEach;
secrets = hostSecrets; secrets = config.services.secrets.secrets;
# Because gotosocial-admin isn't a seporate package we need to generate a seperate config # Because gotosocial-admin isn't a seporate package we need to generate a seperate config
# and duplicate the wrapper for use in a systemd unit # and duplicate the wrapper for use in a systemd unit
@ -48,8 +47,8 @@ in {
restic restic
(pkgs.writeShellScriptBin "restic-social" '' (pkgs.writeShellScriptBin "restic-social" ''
env \ env \
RESTIC_PASSWORD_FILE=${secrets.social_restic_password.path} \ RESTIC_PASSWORD_FILE=${secrets.restic_password.path} \
$(cat ${secrets.social_restic_env.path}) \ $(cat ${secrets.restic_env.path}) \
${pkgs.restic}/bin/restic $@ ${pkgs.restic}/bin/restic $@
'') '')
]; ];
@ -64,8 +63,8 @@ in {
# repository is overrided in environmentFile to contain auth # repository is overrided in environmentFile to contain auth
# make sure to keep up to date when changing repository # make sure to keep up to date when changing repository
repository = "rest:https://storage-restic.owo.monster/Social"; repository = "rest:https://storage-restic.owo.monster/Social";
passwordFile = "${secrets.social_restic_password.path}"; passwordFile = "${secrets.restic_password.path}";
environmentFile = "${secrets.social_restic_env.path}"; environmentFile = "${secrets.restic_env.path}";
pruneOpts = [ pruneOpts = [
"--keep-last 10" "--keep-last 10"

View file

@ -0,0 +1,47 @@
{...}: {
services.secrets = {
enable = true;
vaultLogin = {
enable = true;
loginUsername = "hetzner-arm-container-social";
};
autoSecrets = {
enable = true;
};
requiredVaultPaths = [
"private-public-keys/data/restic/Social"
"api-keys/data/storage/restic/Social"
"api-keys/data/chaos_mail/gotosocial"
];
secrets = {
vault_password = {
manual = true;
};
restic_password = {
fetchScript = ''
simple_get "/private-public-keys/restic/Social" .password > "$secretFile"
'';
};
restic_env = {
fetchScript = ''
RESTIC_USERNAME=$(simple_get "/api-keys/storage/restic/Social" .username)
RESTIC_PASSWORD=$(simple_get "/api-keys/storage/restic/Social" .password)
echo "RESTIC_REPOSITORY=rest:https://$RESTIC_USERNAME:$RESTIC_PASSWORD@storage-restic.owo.monster/Social" > "$secretFile"
'';
};
env_secrets = {
fetchScript = ''
smtp_password=$(simple_get "/api-keys/chaos_mail/gotosocial" .password)
echo "GTS_SMTP_PASSWORD=$smtp_password" > "$secretFile"
'';
};
};
};
}

View file

@ -7,7 +7,7 @@
rclone_serve_restic_vault = 4211; rclone_serve_restic_vault = 4211;
rclone_serve_restic_social = 4212; rclone_serve_restic_social = 4212;
rclone_serve_restic_quassel = 4213; rclone_serve_restic_quassel = 4213;
rclone_serve_restic_piped_finland = 4214; rclone_serve_restic_piped = 4214;
rclone_serve_restic_mail = 4215; rclone_serve_restic_mail = 4215;
rclone_serve_http_music = 4220; rclone_serve_http_music = 4220;

View file

@ -36,20 +36,14 @@ in {
imports = with tree; imports = with tree;
[ [
profiles.base presets.nixos.containerBase
inputs.home-manager-unstable.nixosModules.home-manager
profiles.sshd profiles.sshd
profiles.firewallAllow.ssh
modules.nixos.rclone-serve
modules.nixos.rclone-sync
modules.nixos.secrets
./secrets.nix ./secrets.nix
users.root
] ]
++ (with hosts.hetzner-vm.containers.storage.profiles; [ ++ (with hosts.hetzner-arm.containers.storage.profiles; [
rcloneConfigs rcloneConfigs
rcloneServe rcloneServe
rcloneSync rcloneSync
@ -58,20 +52,12 @@ in {
environment.systemPackages = with pkgs; [rclone]; environment.systemPackages = with pkgs; [rclone];
home-manager.users.root = {
imports = with tree; [home.base home.dev.small];
home.packages = with pkgs; [vault-bin];
home.stateVersion = "23.05";
};
networking.firewall = { networking.firewall = {
enable = true; enable = true;
allowedTCPPorts = attrValues ports; allowedTCPPorts = attrValues ports;
}; };
# Manually configure nameserver. Using resolved inside the container seems to fail home-manager.users.root.home.stateVersion = "23.05";
# currently
environment.etc."resolv.conf".text = "nameserver 8.8.8.8";
system.stateVersion = "23.05"; system.stateVersion = "23.05";
}; };
}; };
@ -109,7 +95,7 @@ in {
"/Vault/".proxyPass = "http://${containerIP}:${toString ports.rclone_serve_restic_vault}"; "/Vault/".proxyPass = "http://${containerIP}:${toString ports.rclone_serve_restic_vault}";
"/Social/".proxyPass = "http://${containerIP}:${toString ports.rclone_serve_restic_social}"; "/Social/".proxyPass = "http://${containerIP}:${toString ports.rclone_serve_restic_social}";
"/Quassel/".proxyPass = "http://${containerIP}:${toString ports.rclone_serve_restic_quassel}"; "/Quassel/".proxyPass = "http://${containerIP}:${toString ports.rclone_serve_restic_quassel}";
"/Piped-Finland/".proxyPass = "http://${containerIP}:${toString ports.rclone_serve_restic_piped_finland}"; "/Piped/".proxyPass = "http://${containerIP}:${toString ports.rclone_serve_restic_piped}";
"/Mail/".proxyPass = "http://${containerIP}:${toString ports.rclone_serve_restic_mail}"; "/Mail/".proxyPass = "http://${containerIP}:${toString ports.rclone_serve_restic_mail}";
}; };
extraConfig = '' extraConfig = ''

View file

@ -117,13 +117,13 @@ in {
]; ];
} }
{ {
id = "restic-piped-finland"; id = "restic-piped";
remote = "StorageBox:Backups/Restic/Piped-Finland"; remote = "StorageBox:Backups/Restic/Piped";
type = "restic"; type = "restic";
extraArgs = [ extraArgs = [
"--addr=0.0.0.0:${toString ports.rclone_serve_restic_piped_finland}" "--addr=0.0.0.0:${toString ports.rclone_serve_restic_piped}"
"--htpasswd=${secrets.restic_piped_finland_htpasswd.path}" "--htpasswd=${secrets.restic_piped_htpasswd.path}"
"--baseurl=/Piped-Finland/" "--baseurl=/Piped/"
]; ];
} }
{ {

View file

@ -10,11 +10,16 @@
wants = ["auto-secrets.service"]; wants = ["auto-secrets.service"];
}; };
timerConfig = { timerConfig = {
OnStartupSec = "60"; OnStartupSec = "120";
OnCalendar = "4h"; OnCalendar = "4h";
}; };
extraArgs = [ extraArgs = [
"--fast-list" "--fast-list"
"--check-first"
"--delete-before"
"--b2-upload-concurrency=4"
"--transfers=4"
"--bwlimit 80M"
]; ];
}) [ }) [
# My B2 # My B2

View file

@ -1,4 +1,4 @@
[StorageBox-Remote] [StorageBox-Remote-WebDAV]
type = webdav type = webdav
vendor = other vendor = other
host = u323231.your-storagebox.de host = u323231.your-storagebox.de
@ -6,6 +6,22 @@ url = https://u323231.your-storagebox.de
user = u323231 user = u323231
pass = STORAGEBOX_PASSWORD pass = STORAGEBOX_PASSWORD
[StorageBox-Remote-SFTP]
type = sftp
host = u323231.your-storagebox.de
user = u323231
port = 23
pass = STORAGEBOX_PASSWORD
shell_type = unix
md5sum_command = md5 -r
sha1sum_command = sha1 -r
# Can change which protocol to use at runtime by editing config
# after deploy or redeploying with different alias if storagebox breaks
[StorageBox-Remote]
type = alias
remote = StorageBox-Remote-SFTP:
[StorageBox-Hasher] [StorageBox-Hasher]
type = hasher type = hasher
remote = StorageBox-Remote: remote = StorageBox-Remote:
@ -101,4 +117,4 @@ password2 = STORAGE_MEDIA_CRYPT_SALT
[Media-Combine-Serve] [Media-Combine-Serve]
type = combine type = combine
upstreams = "Media=Storage-Media-Crypt:" "PutIO=PutIO-WebDAV:" upstreams = "Media=Storage-Media-Crypt:" "PutIO=PutIO-WebDAV:"

View file

@ -1,17 +1,10 @@
{ {pkgs, ...}: {
config,
pkgs,
...
}: let
cfg = config.services.secrets;
in {
services.secrets = { services.secrets = {
enable = true; enable = true;
vaultLogin = { vaultLogin = {
enable = true; enable = true;
loginUsername = "hetzner-vm-container-storage"; loginUsername = "hetzner-arm-container-storage";
loginPasswordFile = cfg.secrets.vault_password.path;
}; };
autoSecrets = { autoSecrets = {
@ -35,7 +28,7 @@ in {
"api-keys/data/storage/restic/Vault" "api-keys/data/storage/restic/Vault"
"api-keys/data/storage/restic/Social" "api-keys/data/storage/restic/Social"
"api-keys/data/storage/restic/Quassel" "api-keys/data/storage/restic/Quassel"
"api-keys/data/storage/restic/Piped-Finland" "api-keys/data/storage/restic/Piped"
"api-keys/data/storage/restic/Mail" "api-keys/data/storage/restic/Mail"
"api-keys/data/storage/webdav/main" "api-keys/data/storage/webdav/main"
@ -51,14 +44,6 @@ in {
rclone rclone
]; ];
uidMap = {
"storage" = config.users.users."storage".uid;
};
gidMap = {
"storage" = config.users.groups."storage".gid;
};
extraFunctions = '' extraFunctions = ''
replace_slash_for_sed() { replace_slash_for_sed() {
sed "s#/#\\\/#" sed "s#/#\\\/#"
@ -80,11 +65,11 @@ in {
} }
simple_get_replace_crypt() { simple_get_replace_crypt() {
password=$(simple_get "$1" .password | replace_slash_for_sed) password=$(simple_get_obscure "$1" .password)
salt=$(simple_get "$1" .salt | replace_slash_for_sed) salt=$(simple_get_obscure "$1" .salt)
replace_password=''${2}_ACCOUNT replace_password=''${2}_PASSWORD
replace_salt=''${2}_KEY replace_salt=''${2}_SALT
sed -i "s/$replace_password/$password/" "$3" sed -i "s/$replace_password/$password/" "$3"
sed -i "s/$replace_salt/$salt/" "$3" sed -i "s/$replace_salt/$salt/" "$3"
@ -132,12 +117,12 @@ in {
''; '';
}; };
restic_piped_finland_htpasswd = { restic_piped_htpasswd = {
user = "storage"; user = "storage";
group = "storage"; group = "storage";
fetchScript = '' fetchScript = ''
username=$(simple_get "/api-keys/storage/restic/Piped-Finland" .username) username=$(simple_get "/api-keys/storage/restic/Piped" .username)
password=$(simple_get "/api-keys/storage/restic/Piped-Finland" .password) password=$(simple_get "/api-keys/storage/restic/Piped" .password)
htpasswd -bc "$secretFile" "$username" "$password" 2>/dev/null htpasswd -bc "$secretFile" "$username" "$password" 2>/dev/null
''; '';
}; };

View file

@ -5,6 +5,5 @@
social = "192.168.100.12"; social = "192.168.100.12";
music = "192.168.100.13"; music = "192.168.100.13";
quassel = "192.168.100.14"; quassel = "192.168.100.14";
piped = "192.168.100.15";
}; };
} }

View file

@ -3,4 +3,4 @@
systemd-boot.enable = true; systemd-boot.enable = true;
efi.canTouchEfiVariables = true; efi.canTouchEfiVariables = true;
}; };
} }

View file

@ -11,25 +11,25 @@ in {
presets.nixos.serverHetzner presets.nixos.serverHetzner
presets.nixos.serverEncryptedDrive presets.nixos.serverEncryptedDrive
#profiles.nginx profiles.nginx
#profiles.firewallAllow.httpCommon profiles.firewallAllow.httpCommon
#profiles.chaosInternalWireGuard profiles.chaosInternalWireGuard
./hardware.nix ./hardware.nix
./secrets.nix ./secrets.nix
] ]
++ (forEach [ ++ (forEach [
#"social" "social"
#"storage" "storage"
#"music" "music"
#"quassel" "quassel"
#"piped-fi" "piped-db"
#"mail" "piped-fi"
"mail"
] (name: ./containers + "/${name}")) ] (name: ./containers + "/${name}"))
++ (with hosts.hetzner-vm.profiles; [ ++ (with hosts.hetzner-arm.profiles; [
#vaultUI gitlabStaticSites
#gitlabStaticSites
]); ]);
# For Containers # For Containers

View file

@ -1,4 +1,4 @@
{pkgs, ...}: { {...}: {
services.secrets = { services.secrets = {
enable = true; enable = true;
@ -9,12 +9,15 @@
autoSecrets = { autoSecrets = {
enable = true; enable = true;
#affectedSystemdServices = [ affectedSystemdServices = [
# "wg-quick-wg0" "wg-quick-wg0"
#]; ];
}; };
requiredVaultPaths = [ requiredVaultPaths = [
"private-public-keys/data/ssh/root@hetzner-arm"
"private-public-keys/data/ssh/root@hetzner-arm-decrypt"
"api-keys/data/gitlab/gitlab_pages_serve" "api-keys/data/gitlab/gitlab_pages_serve"
]; ];
@ -23,6 +26,34 @@
manual = true; manual = true;
}; };
ssh_host_ed25519_key = {
path = "/etc/ssh/ssh_host_ed25519_key";
permissions = "600";
fetchScript = ''
[ ! -d "$SYSROOT/etc/ssh" ] && mkdir -p "$SYSROOT/etc/ssh/"
simple_get "/private-public-keys/ssh/root@hetzner-arm" .private | base64 -d > "$secretFile"
'';
};
ssh_host_ed25519_key_pub = {
path = "/etc/ssh/ssh_host_ed25519_key.pub";
permissions = "600";
fetchScript = ''
[ ! -d "$SYSROOT/etc/ssh" ] && mkdir -p "$SYSROOT/etc/ssh/"
simple_get "/private-public-keys/ssh/root@hetzner-arm" .private | base64 -d > "$secretFile"
'';
};
# this doesn't need to be a secret and can be generated at install time
# but it makes it easier to install.
# it's stored in /nix store anyway
initrd_ssh_host_ed25519_key = {
path = "/initrd_ssh_host_ed25519_key";
permissions = "600";
fetchScript = ''
simple_get "/private-public-keys/ssh/root@hetzner-arm-decrypt" .private | base64 -d > "$secretFile"
'';
};
# Used directly by server # Used directly by server
# for fetching gitlab static sites # for fetching gitlab static sites
gitlab_env = { gitlab_env = {

View file

@ -1,38 +0,0 @@
{
pkgs,
config,
...
}: let
secrets = config.services.secrets.secrets;
in {
environment.systemPackages = with pkgs; [
restic
(pkgs.writeShellScriptBin "restic-piped-finland" ''
env \
RESTIC_PASSWORD_FILE=${secrets.restic_password.path} \
$(cat ${secrets.restic_env.path}) \
${pkgs.restic}/bin/restic $@
'')
];
services.restic.backups.piped-finland = {
user = "root";
paths = [
"/var/lib/cockroachdb"
"/var/lib/cockroachdb-certs"
];
repository = "rest:https://storage-restic.owo.monster/Piped-Finland";
passwordFile = "${secrets.restic_password.path}";
environmentFile = "${secrets.restic_env.path}";
pruneOpts = [
"--keep-last 5"
];
timerConfig = {
OnBootSec = "1m";
OnCalendar = "daily";
};
};
}

View file

@ -1,75 +0,0 @@
{...}: {
services.secrets = {
enable = true;
vaultLogin = {
enable = true;
loginUsername = "hetzner-vm-container-piped-fi";
};
autoSecrets = {
enable = true;
};
requiredVaultPaths = [
"api-keys/data/storage/restic/Piped-Finland"
"private-public-keys/data/piped-cockroachdb-ca/nodes/piped-fi"
"private-public-keys/data/restic/Piped-Finland"
];
secrets = {
vault_password = {
manual = true;
};
restic_password = {
fetchScript = ''
simple_get "/private-public-keys/restic/Piped-Finland" .password > "$secretFile"
'';
};
restic_env = {
fetchScript = ''
RESTIC_USERNAME=$(simple_get "/api-keys/storage/restic/Piped-Finland" .username)
RESTIC_PASSWORD=$(simple_get "/api-keys/storage/restic/Piped-Finland" .password)
echo "RESTIC_REPOSITORY=rest:https://$RESTIC_USERNAME:$RESTIC_PASSWORD@storage-restic.owo.monster/Piped-Finland" > "$secretFile"
'';
};
cockroachdb_ca_certificate = {
user = "cockroachdb";
group = "cockroachdb";
permissions = "600";
path = "/var/lib/cockroachdb-certs/ca.crt";
fetchScript = ''
simple_get "/private-public-keys/piped-cockroachdb-ca/nodes/piped-fi" .ca_certificate \
| base64 -d > "$secretFile"
'';
};
cockroachdb_node_certificate = {
user = "cockroachdb";
group = "cockroachdb";
permissions = "600";
path = "/var/lib/cockroachdb-certs/node.crt";
fetchScript = ''
simple_get "/private-public-keys/piped-cockroachdb-ca/nodes/piped-fi" .node_certificate \
| base64 -d > "$secretFile"
'';
};
cockroachdb_node_key = {
user = "cockroachdb";
group = "cockroachdb";
permissions = "600";
path = "/var/lib/cockroachdb-certs/node.key";
fetchScript = ''
simple_get "/private-public-keys/piped-cockroachdb-ca/nodes/piped-fi" .node_key \
| base64 -d > "$secretFile"
'';
};
};
};
}

View file

@ -1,105 +0,0 @@
{
self,
hostPath,
tree,
inputs,
config,
pkgs,
...
}: let
containerAddresses = import "${hostPath}/data/containerAddresses.nix";
hostIP = containerAddresses.host;
containerIP = containerAddresses.containers.social;
# Using secrets from Host
secrets = config.services.secrets.secrets;
in {
containers.social = {
autoStart = true;
privateNetwork = true;
hostAddress = hostIP;
localAddress = containerIP;
bindMounts = {
"${secrets.social_restic_password.path}" = {
hostPath = "${secrets.social_restic_password.path}";
};
"${secrets.social_restic_env.path}" = {
hostPath = "${secrets.social_restic_env.path}";
};
"${secrets.social_env_secrets.path}" = {
hostPath = "${secrets.social_env_secrets.path}";
};
};
specialArgs = {
inherit inputs;
inherit tree;
inherit self;
inherit hostPath;
hostSecrets = secrets;
};
config = {config, ...}: {
nixpkgs.pkgs = pkgs;
imports = with tree;
[
profiles.base
inputs.home-manager-unstable.nixosModules.home-manager
profiles.sshd
modules.nixos.secrets
users.root
]
++ (with hosts.hetzner-vm.containers.social; [
profiles.gotosocial
profiles.restic
]);
environment.systemPackages = with pkgs; [
rclone
restic
];
# For Shared Secrets
systemd.tmpfiles.rules = [
"d ${config.services.secrets.secretsDir} - root root"
];
networking.firewall = {
enable = true;
allowedTCPPorts = [22 8080];
};
home-manager.users.root = {
imports = with tree; [home.base home.dev.small];
home.stateVersion = "23.05";
};
# Manually configure nameserver. Using resolved inside the container seems to fail
# currently
environment.etc."resolv.conf".text = "nameserver 8.8.8.8";
system.stateVersion = "23.05";
};
};
services.nginx.virtualHosts."gts-01.owo.monster" = {
forceSSL = true;
enableACME = true;
locations."/" = {
proxyPass = "http://${containerIP}:8080";
proxyWebsockets = true;
extraConfig = ''
# uncomment if running nginx without recommendedProxySettings
# proxy_set_header Host $host;
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# proxy_set_header X-Forwarded-Proto $scheme;
'';
};
extraConfig = ''
client_max_body_size 128M;
'';
};
}

View file

@ -1,15 +0,0 @@
{...}: {
boot.loader = {
grub = {
enable = true;
device = "/dev/sda";
};
};
boot.initrd.kernelModules = ["nvme"];
fileSystems."/" = {
device = "/dev/sda1";
fsType = "ext4";
};
}

View file

@ -1,46 +0,0 @@
{
tree,
lib,
...
}: let
inherit (lib.lists) forEach;
in {
imports = with tree;
[
presets.nixos.serverBase
presets.nixos.serverHetzner
profiles.nginx
profiles.firewallAllow.httpCommon
profiles.cross.arm64
profiles.chaosInternalWireGuard
./hardware.nix
./secrets.nix
]
++ (forEach [
"social"
"storage"
"music"
"quassel"
"piped-fi"
"mail"
] (name: ./containers + "/${name}"))
++ (with hosts.hetzner-vm.profiles; [
vaultUI
gitlabStaticSites
]);
# For Containers
networking.nat = {
enable = true;
internalInterfaces = ["ve-+"];
externalInterface = "enp1s0";
};
networking.hostName = "hetzner-vm";
home-manager.users.root.home.stateVersion = "23.05";
system.stateVersion = "23.05";
}

View file

@ -1,171 +0,0 @@
{pkgs, ...}: {
services.secrets = {
enable = true;
vaultLogin = {
enable = true;
loginUsername = "hetzner-vm";
};
autoSecrets = {
enable = true;
affectedSystemdServices = [
"wg-quick-wg0"
"container@music"
"container@social"
"container@quassel"
"container@piped-fi"
];
};
packages = with pkgs; [
# for music & mail passwd files
apacheHttpd
];
requiredVaultPaths = [
"api-keys/data/mpd"
"api-keys/data/music-stream"
"api-keys/data/gitlab/gitlab_pages_serve"
"api-keys/data/storage/restic/Mail"
"api-keys/data/storage/restic/Social"
"api-keys/data/storage/restic/Quassel"
"api-keys/data/chaos_mail/system"
"api-keys/data/chaos_mail/gotosocial"
"passwords/data/soulseek"
"passwords/data/slskd"
"passwords/data/mail"
"private-public-keys/data/restic/Mail"
"private-public-keys/data/restic/Social"
"private-public-keys/data/restic/Quassel"
"infra/data/private-mail-aliases"
];
secrets = {
vault_password = {
manual = true;
};
# Used directly by server
# for fetching gitlab static sites
gitlab_env = {
user = "gitlab_artifacts_sync";
group = "gitlab_artifacts_sync";
fetchScript = ''
token=$(simple_get "/api-keys/gitlab/gitlab_pages_serve" .token)
echo "GITLAB_TOKEN=$token" > "$secretFile"
'';
};
# Container: music
mpd_control_password = {
user = "mpd";
group = "mpd";
fetchScript = ''
simple_get "/api-keys/mpd" .password > "$secretFile"
'';
};
music_stream_passwd = {
user = "nginx";
group = "nginx";
fetchScript = ''
username=$(simple_get "/api-keys/music-stream" .username)
password=$(simple_get "/api-keys/music-stream" .password)
htpasswd -bc "$secretFile" "$username" "$password" 2>/dev/null
'';
};
slskd_env = {
fetchScript = ''
soulseek_password=$(simple_get "/passwords/soulseek" .password)
slskd_password=$(simple_get "/passwords/slskd" .password)
echo > "$secretFile"
echo "SLSKD_SLSK_PASSWORD=$soulseek_password" >> "$secretFile"
echo "SLSKD_PASSWORD=$slskd_password" >> "$secretFile"
'';
};
# Container: mail
mail_restic_password = {
fetchScript = ''
simple_get "/private-public-keys/restic/Mail" .password > "$secretFile"
'';
};
mail_restic_env = {
fetchScript = ''
RESTIC_USERNAME=$(simple_get "/api-keys/storage/restic/Mail" .username)
RESTIC_PASSWORD=$(simple_get "/api-keys/storage/restic/Mail" .password)
echo "RESTIC_REPOSITORY=rest:https://$RESTIC_USERNAME:$RESTIC_PASSWORD@storage-restic.owo.monster/Mail" > "$secretFile"
'';
};
private_mail_aliases = {
fetchScript = ''
kv_get "/infra/private-mail-aliases" | jq .data.data | jq -r 'to_entries|map("\(.key) \(.value.to)")[]' > "$secretFile"
'';
};
chaos_mail_passwd = {
user = "dovecot2";
group = "dovecot2";
fetchScript = ''
password=$(simple_get "/passwords/mail" .password)
htpasswd -nbB "" "$password" 2>/dev/null | cut -d: -f2 > "$secretFile"
'';
};
system_mail_passwd = {
user = "dovecot2";
group = "dovecot2";
fetchScript = ''
password=$(simple_get "/api-keys/chaos_mail/system" .password)
htpasswd -nbB "" "$password" 2>/dev/null | cut -d: -f2 > "$secretFile"
'';
};
gotosocial_mail_passwd = {
user = "dovecot2";
group = "dovecot2";
fetchScript = ''
password=$(simple_get "/api-keys/chaos_mail/gotosocial" .password)
htpasswd -nbB "" "$password" 2>/dev/null | cut -d: -f2 > "$secretFile"
'';
};
# Container: social
social_restic_password = {
fetchScript = ''
simple_get "/private-public-keys/restic/Social" .password > "$secretFile"
'';
};
social_restic_env = {
fetchScript = ''
RESTIC_USERNAME=$(simple_get "/api-keys/storage/restic/Social" .username)
RESTIC_PASSWORD=$(simple_get "/api-keys/storage/restic/Social" .password)
echo "RESTIC_REPOSITORY=rest:https://$RESTIC_USERNAME:$RESTIC_PASSWORD@storage-restic.owo.monster/Social" > "$secretFile"
'';
};
social_env_secrets = {
fetchScript = ''
smtp_password=$(simple_get "/api-keys/chaos_mail/gotosocial" .password)
echo "GTS_SMTP_PASSWORD=$smtp_password" > "$secretFile"
'';
};
# Container: quassel
quassel_restic_password = {
fetchScript = ''
simple_get "/private-public-keys/restic/Quassel" .password > "$secretFile"
'';
};
quassel_restic_env = {
fetchScript = ''
RESTIC_USERNAME=$(simple_get "/api-keys/storage/restic/Quassel" .username)
RESTIC_PASSWORD=$(simple_get "/api-keys/storage/restic/Quassel" .password)
echo "RESTIC_REPOSITORY=rest:https://$RESTIC_USERNAME:$RESTIC_PASSWORD@storage-restic.owo.monster/Quassel" > "$secretFile"
'';
};
};
};
}

View file

@ -9,8 +9,9 @@
presets.nixos.encryptedUSB presets.nixos.encryptedUSB
profiles.cross.arm64 profiles.cross.arm64
#profiles.remote-builders profiles.remoteBuilders
profiles.chaosInternalWireGuard profiles.chaosInternalWireGuard
profiles.fingerprint
./secrets.nix ./secrets.nix
]; ];

View file

@ -7,7 +7,7 @@
}; };
music_stream_password = { music_stream_password = {
user = 1000; user = "chaos";
group = "users"; group = "users";
fetchScript = '' fetchScript = ''
simple_get "/api-keys/music-stream" .password > "$secretFile" simple_get "/api-keys/music-stream" .password > "$secretFile"
@ -17,8 +17,6 @@
# Required for home.apps.manualBackupApps # Required for home.apps.manualBackupApps
gitlab_archiver_token = { gitlab_archiver_token = {
user = "chaos"; user = "chaos";
group = "users";
fetchScript = '' fetchScript = ''
simple_get "/api-keys/gitlab/gitlab_archiver" .token > "$secretFile" simple_get "/api-keys/gitlab/gitlab_archiver" .token > "$secretFile"
''; '';
@ -27,8 +25,6 @@
# Required for home.apps.manualBackupApps # Required for home.apps.manualBackupApps
restic_music_env = { restic_music_env = {
user = "chaos"; user = "chaos";
group = "users";
fetchScript = '' fetchScript = ''
api_username=$(simple_get "/api-keys/storage/restic/Music" .username) api_username=$(simple_get "/api-keys/storage/restic/Music" .username)
api_password=$(simple_get "/api-keys/storage/restic/Music" .password) api_password=$(simple_get "/api-keys/storage/restic/Music" .password)

View file

@ -33,10 +33,9 @@
inputs.gitlab_artifacts_sync.nixosModules.default inputs.gitlab_artifacts_sync.nixosModules.default
inputs.piped-flake.nixosModules.default inputs.piped-flake.nixosModules.default
tree.modules.nixos.rclone-serve tree.modules.nixos.rcloneServe
tree.modules.nixos.rclone-sync tree.modules.nixos.rcloneSync
tree.modules.nixos.secrets tree.modules.nixos.secrets
tree.modules.nixos.cockroachdb-bin
]; ];
nixosUnstableSystem = nixpkgs-unstable.lib.nixosSystem; nixosUnstableSystem = nixpkgs-unstable.lib.nixosSystem;
@ -81,16 +80,6 @@ in {
modules = defaultModules ++ [./hetzner-arm/hetzner-arm.nix]; modules = defaultModules ++ [./hetzner-arm/hetzner-arm.nix];
}; };
hetzner-vm = nixosUnstableSystem {
specialArgs =
defaultSpecialArgs
// {
hostPath = ./hetzner-vm;
};
system = "x86_64-linux";
modules = defaultModules ++ [./hetzner-vm/hetzner-vm.nix];
};
vault = nixosUnstableSystem { vault = nixosUnstableSystem {
specialArgs = specialArgs =
defaultSpecialArgs defaultSpecialArgs

View file

@ -5,16 +5,19 @@
inputs, inputs,
config, config,
pkgs, pkgs,
lib,
... ...
}: let }: let
containerName = "piped-uk"; inherit (lib.modules) mkForce;
containerConfig = config.containers.${containerName}.config;
pipedName = "piped-uk";
containerName = pipedName;
pipedSocketForComponent = ( pipedSocketForComponent = (
component: "/var/lib/nixos-containers/${containerName}/var/sockets/piped-${component}.sock" component: "/var/lib/nixos-containers/${containerName}/var/sockets/piped-${component}.sock"
); );
in { in {
containers.piped-uk = { containers.${containerName} = {
autoStart = true; autoStart = true;
privateNetwork = false; privateNetwork = false;
@ -30,26 +33,17 @@ in {
imports = with tree; [ imports = with tree; [
presets.nixos.containerBase presets.nixos.containerBase
presets.nixos.pipedNode
profiles.nginx
profiles.firewallAllow.httpCommon
profiles.pipedCluster
./secrets.nix
]; ];
# For Shared Secrets networking.firewall.enable = mkForce false;
systemd.tmpfiles.rules = [
"d /var/lib/cockroachdb-certs - root root"
];
home-manager.users.root.home.stateVersion = "23.05"; home-manager.users.root.home.stateVersion = "23.05";
system.stateVersion = "23.05"; system.stateVersion = "23.05";
}; };
}; };
services.nginx.virtualHosts."piped-uk.owo.monster" = { services.nginx.virtualHosts."${pipedName}.owo.monster" = {
forceSSL = true; forceSSL = true;
enableACME = true; enableACME = true;
locations."/" = { locations."/" = {
@ -57,7 +51,7 @@ in {
}; };
}; };
services.nginx.virtualHosts."backend.piped-uk.owo.monster" = { services.nginx.virtualHosts."backend.${pipedName}.owo.monster" = {
forceSSL = true; forceSSL = true;
enableACME = true; enableACME = true;
locations."/" = { locations."/" = {
@ -65,7 +59,7 @@ in {
}; };
}; };
services.nginx.virtualHosts."proxy.piped-uk.owo.monster" = { services.nginx.virtualHosts."proxy.${pipedName}.owo.monster" = {
forceSSL = true; forceSSL = true;
enableACME = true; enableACME = true;
locations."/" = { locations."/" = {

View file

@ -1,73 +0,0 @@
{pkgs, ...}: {
services.secrets = {
enable = true;
packages = with pkgs; [rclone];
vaultLogin = {
enable = true;
loginUsername = "raspberry";
};
autoSecrets = {
enable = true;
affectedSystemdServices = ["wg-quick-wg0" "cockroachdb"];
};
extraFunctions = ''
simple_get_obscure() {
rclone obscure "$(simple_get "$@")"
}
'';
requiredVaultPaths = [
"private-public-keys/data/piped-cockroachdb-ca/nodes/raspberry"
];
secrets = {
vault_password = {
manual = true;
};
piped_cockroachdb_ca_certificate = {
user = "cockroachdb";
group = "cockroachdb";
permissions = "600";
path = "/var/lib/cockroachdb-certs/ca.crt";
fetchScript = ''
if [ ! -d "$SYSROOT/var/lib/cockroachdb-certs" ]; then
mkdir -p "$SYSROOT/var/lib/cockroachdb-certs"
fi
simple_get "/private-public-keys/piped-cockroachdb-ca/nodes/raspberry" .ca_certificate \
| base64 -d > "$secretFile"
'';
};
piped_cockroachdb_node_certificate = {
user = "cockroachdb";
group = "cockroachdb";
permissions = "600";
path = "/var/lib/cockroachdb-certs/node.crt";
fetchScript = ''
if [ ! -d "$SYSROOT/var/lib/cockroachdb-certs" ]; then
mkdir -p "$SYSROOT/var/lib/cockroachdb-certs"
fi
simple_get "/private-public-keys/piped-cockroachdb-ca/nodes/raspberry" .node_certificate \
| base64 -d > "$secretFile"
'';
};
piped_cockroachdb_node_key = {
user = "cockroachdb";
group = "cockroachdb";
permissions = "600";
path = "/var/lib/cockroachdb-certs/node.key";
fetchScript = ''
if [ ! -d "$SYSROOT/var/lib/cockroachdb-certs" ]; then
mkdir -p "$SYSROOT/var/lib/cockroachdb-certs"
fi
simple_get "/private-public-keys/piped-cockroachdb-ca/nodes/raspberry" .node_key \
| base64 -d > "$secretFile"
'';
};
};
};
}

View file

@ -15,7 +15,8 @@
}; };
requiredVaultPaths = [ requiredVaultPaths = [
"/private-public-keys/data/ssh/root@vault-decrypt" "private-public-keys/data/ssh/root@vault"
"private-public-keys/data/ssh/root@vault-decrypt"
"private-public-keys/data/restic/Vault" "private-public-keys/data/restic/Vault"
@ -27,11 +28,28 @@
manual = true; manual = true;
}; };
ssh_host_ed25519_key = {
path = "/etc/ssh/ssh_host_ed25519_key";
permissions = "600";
fetchScript = ''
[ ! -d "$SYSROOT/etc/ssh" ] && mkdir -p "$SYSROOT/etc/ssh/"
simple_get "/private-public-keys/ssh/root@vault" .private | base64 -d > "$secretFile"
'';
};
ssh_host_ed25519_key_pub = {
path = "/etc/ssh/ssh_host_ed25519_key.pub";
permissions = "600";
fetchScript = ''
[ ! -d "$SYSROOT/etc/ssh" ] && mkdir -p "$SYSROOT/etc/ssh/"
simple_get "/private-public-keys/ssh/root@vault" .private | base64 -d > "$secretFile"
'';
};
# this doesn't need to be a secret and can be generated at install time # this doesn't need to be a secret and can be generated at install time
# but it makes it easier to install. # but it makes it easier to install.
# it's stored in /nix store anyway # it's stored in /nix store anyway
ssh_host_ed25519_key = { initrd_ssh_host_ed25519_key = {
path = "/ssh_host_ed25519_key"; path = "/initrd_ssh_host_ed25519_key";
permissions = "600"; permissions = "600";
fetchScript = '' fetchScript = ''
simple_get "/private-public-keys/ssh/root@vault-decrypt" .private | base64 -d > "$secretFile" simple_get "/private-public-keys/ssh/root@vault-decrypt" .private | base64 -d > "$secretFile"

View file

@ -14,6 +14,7 @@
] ]
++ (with hosts.vault.profiles; [ ++ (with hosts.vault.profiles; [
vault vault
vaultUI
restic restic
]); ]);

View file

@ -1,248 +0,0 @@
{
config,
lib,
pkgs,
...
}:
with lib; let
cfg = config.services.cockroachdb-bin;
crdb = cfg.package;
escapeSystemdExecArg = arg: let
s =
if builtins.isPath arg
then "${arg}"
else if builtins.isString arg
then arg
else if builtins.isInt arg || builtins.isFloat arg
then toString arg
else throw "escapeSystemdExecArg only allows strings, paths and numbers";
in
lib.replaceStrings ["%" "$"] ["%%" "$$"] (builtins.toJSON s);
# Quotes a list of arguments into a single string for use in a Exec*
# line.
escapeSystemdExecArgs = lib.concatMapStringsSep " " escapeSystemdExecArg;
startupCommand =
escapeSystemdExecArgs
([
# Basic startup
"${crdb}/bin/cockroach"
(
if (cfg.join != null)
then "start"
else "start-single-node"
)
"--logtostderr"
"--store=/var/lib/cockroachdb"
# WebUI settings
"--http-addr=${cfg.http.address}:${toString cfg.http.port}"
# Cluster listen address
"--listen-addr=${cfg.listen.address}:${toString cfg.listen.port}"
# Cache and memory settings.
"--cache=${cfg.cache}"
"--max-sql-memory=${cfg.maxSqlMemory}"
# Certificate/security settings.
(
if cfg.insecure
then "--insecure"
else "--certs-dir=${cfg.certsDir}"
)
]
++ lib.optional (cfg.join != null) "--join=${cfg.join}"
++ lib.optional (cfg.locality != null) "--locality=${cfg.locality}"
++ cfg.extraArgs);
addressOption = descr: defaultPort: {
address = mkOption {
type = types.str;
default = "localhost";
description = lib.mdDoc "Address to bind to for ${descr}";
};
port = mkOption {
type = types.port;
default = defaultPort;
description = lib.mdDoc "Port to bind to for ${descr}";
};
};
in {
options = {
services.cockroachdb-bin = {
enable = mkEnableOption (lib.mdDoc "CockroachDB Server");
listen = addressOption "intra-cluster communication" 26257;
http = addressOption "http-based Admin UI" 8080;
locality = mkOption {
type = types.nullOr types.str;
default = null;
description = lib.mdDoc ''
An ordered, comma-separated list of key-value pairs that describe the
topography of the machine. Topography might include country,
datacenter or rack designations. Data is automatically replicated to
maximize diversities of each tier. The order of tiers is used to
determine the priority of the diversity, so the more inclusive
localities like country should come before less inclusive localities
like datacenter. The tiers and order must be the same on all nodes.
Including more tiers is better than including fewer. For example:
```
country=us,region=us-west,datacenter=us-west-1b,rack=12
country=ca,region=ca-east,datacenter=ca-east-2,rack=4
planet=earth,province=manitoba,colo=secondary,power=3
```
'';
};
join = mkOption {
type = types.nullOr types.str;
default = null;
description = lib.mdDoc "The addresses for connecting the node to a cluster.";
};
insecure = mkOption {
type = types.bool;
default = false;
description = lib.mdDoc "Run in insecure mode.";
};
certsDir = mkOption {
type = types.nullOr types.path;
default = null;
description = lib.mdDoc "The path to the certificate directory.";
};
user = mkOption {
type = types.str;
default = "cockroachdb";
description = lib.mdDoc "User account under which CockroachDB runs";
};
group = mkOption {
type = types.str;
default = "cockroachdb";
description = lib.mdDoc "User account under which CockroachDB runs";
};
openPorts = mkOption {
type = types.bool;
default = false;
description = lib.mdDoc "Open firewall ports for cluster communication by default";
};
cache = mkOption {
type = types.str;
default = "25%";
description = lib.mdDoc ''
The total size for caches.
This can be a percentage, expressed with a fraction sign or as a
decimal-point number, or any bytes-based unit. For example,
`"25%"`, `"0.25"` both represent
25% of the available system memory. The values
`"1000000000"` and `"1GB"` both
represent 1 gigabyte of memory.
'';
};
maxSqlMemory = mkOption {
type = types.str;
default = "25%";
description = lib.mdDoc ''
The maximum in-memory storage capacity available to store temporary
data for SQL queries.
This can be a percentage, expressed with a fraction sign or as a
decimal-point number, or any bytes-based unit. For example,
`"25%"`, `"0.25"` both represent
25% of the available system memory. The values
`"1000000000"` and `"1GB"` both
represent 1 gigabyte of memory.
'';
};
package = mkOption {
type = types.package;
default = pkgs.cockroachdb-bin;
defaultText = literalExpression "pkgs.cockroachdb-bin";
description = lib.mdDoc ''
The CockroachDB derivation to use for running the service.
'';
};
extraArgs = mkOption {
type = types.listOf types.str;
default = [];
example = ["--advertise-addr" "[fe80::f6f2:::]"];
description = lib.mdDoc ''
Extra CLI arguments passed to {command}`cockroach start`.
For the full list of supported arguments, check <https://www.cockroachlabs.com/docs/stable/cockroach-start.html#flags>
'';
};
};
};
config = mkIf config.services.cockroachdb-bin.enable {
assertions = [
{
assertion = !cfg.insecure -> cfg.certsDir != null;
message = "CockroachDB must have a set of SSL certificates (.certsDir), or run in Insecure Mode (.insecure = true)";
}
];
environment.systemPackages = [crdb];
users.users = optionalAttrs (cfg.user == "cockroachdb") {
cockroachdb = {
description = "CockroachDB Server User";
uid = config.ids.uids.cockroachdb;
group = cfg.group;
};
};
users.groups = optionalAttrs (cfg.group == "cockroachdb") {
cockroachdb.gid = config.ids.gids.cockroachdb;
};
networking.firewall.allowedTCPPorts =
lib.optionals cfg.openPorts
[cfg.http.port cfg.listen.port];
systemd.services.cockroachdb = {
description = "CockroachDB Server";
documentation = ["man:cockroach(1)" "https://www.cockroachlabs.com"];
after = ["network.target" "time-sync.target"];
requires = ["time-sync.target"];
wantedBy = ["multi-user.target"];
unitConfig.RequiresMountsFor = "/var/lib/cockroachdb";
serviceConfig = {
ExecStart = startupCommand;
Type = "notify";
User = cfg.user;
StateDirectory = "cockroachdb";
StateDirectoryMode = "0700";
Restart = "always";
# A conservative-ish timeout is alright here, because for Type=notify
# cockroach will send systemd pings during startup to keep it alive
TimeoutStopSec = 60;
RestartSec = 10;
};
};
};
meta.maintainers = with lib.maintainers; [thoughtpolice];
}

View file

@ -84,6 +84,12 @@ in {
(mkIf (cfg.enable && cfg.syncJobs != []) { (mkIf (cfg.enable && cfg.syncJobs != []) {
environment.systemPackages = environment.systemPackages =
[ [
(pkgs.writeShellScriptBin "rclone-sync-stop-all" (concatStringsSep "\n" (map (
job: ''
systemctl stop rclone-sync-${job.id}.service
''
)
cfg.syncJobs)))
(pkgs.writeShellScriptBin "rclone-sync-all" (concatStringsSep "\n" (map ( (pkgs.writeShellScriptBin "rclone-sync-all" (concatStringsSep "\n" (map (
job: '' job: ''
${pkgs.rclone}/bin/rclone sync ${job.source} ${job.dest} ${concatStringsSep " " job.extraArgs} -P $@ ${pkgs.rclone}/bin/rclone sync ${job.source} ${job.dest} ${concatStringsSep " " job.extraArgs} -P $@

View file

@ -8,7 +8,7 @@
inherit (lib.options) mkOption mkEnableOption; inherit (lib.options) mkOption mkEnableOption;
inherit (lib.lists) filter; inherit (lib.lists) filter;
inherit (lib) types; inherit (lib) types;
inherit (builtins) isString listToAttrs; inherit (builtins) isString listToAttrs attrNames;
cfg = config.services.secrets; cfg = config.services.secrets;
@ -115,25 +115,79 @@ in {
extraFunctions = mkOption { extraFunctions = mkOption {
type = types.lines; type = types.lines;
default = ""; default = "";
description = "extra bash functions to add to top of script"; description = "extra bash functions to add to top of script for init";
};
extraCheckFunctions = mkOption {
type = types.lines;
default = "";
description = "extra bash functions to add to top of script for check";
}; };
uidMap = mkOption { uidMap = mkOption {
type = types.attrsOf types.int; type = types.attrsOf types.int;
default = {}; default = listToAttrs (map (
description = "optional mapping of users to user IDs; required for SYSROOT when user isn't available on host"; secretName: let
secretUserName = cfg.secrets.${secretName}.user;
in {
name = "${secretUserName}";
value = config.users.users.${secretUserName}.uid;
}
) (filter
(secretName: let
secret = cfg.secrets.${secretName};
in
isString secret.user
&& (
if config.users.users ? "${secret.user}"
then true
else builtins.trace "warning: secrets module could not find a uid mapping for user ${secret.user}" false
))
(attrNames cfg.secrets)));
description = ''
optional mapping of users to user IDs
required for SYSROOT when user isn't available on host
defaults to getting values from users.users.<name>.uid for all secrets with user set as string
'';
}; };
gidMap = mkOption { gidMap = mkOption {
type = types.attrsOf types.int; type = types.attrsOf types.int;
default = {}; default = listToAttrs (map (
description = "optional mapping of groups to group IDs; required for SYSROOT when group isn't available on host"; secretName: let
secretGroupName = cfg.secrets.${secretName}.group;
in {
name = "${secretGroupName}";
value = config.users.groups.${secretGroupName}.gid;
}
) (filter
(secretName: let
secret = cfg.secrets.${secretName};
in
isString secret.group
&& (
if config.users.groups ? "${secret.group}"
then true
else builtins.trace "warning: secrets module could not find a gid mapping for group ${secret.group}" false
))
(attrNames cfg.secrets)));
description = ''
optional mapping of groups to group IDs
required for SYSROOT when group isn't available on host
defaults to getting values from users.groups.<group>.gid for all secrets with group set as string
'';
}; };
packages = mkOption { packages = mkOption {
type = types.listOf types.package; type = types.listOf types.package;
default = []; default = [];
description = "packages for script"; description = "packages for init script";
};
checkPackages = mkOption {
type = types.listOf types.package;
default = [];
description = "packages for checkscript";
}; };
secrets = mkOption { secrets = mkOption {
@ -241,7 +295,7 @@ in {
// { // {
auto-secrets.partOf = auto-secrets.partOf =
map (unitConfig: unitConfig.name + ".service") map (unitConfig: unitConfig.name + ".service")
(lib.filter (filter
(unitConfig: unitConfig.withPartOf) (unitConfig: unitConfig.withPartOf)
affectedSystemdServices); affectedSystemdServices);
}; };

View file

@ -195,6 +195,11 @@
stat --format "%a" "$1" 2>/dev/null stat --format "%a" "$1" 2>/dev/null
} }
emojiTick=""
emojiCross=""
${cfg.extraCheckFunctions}
GLOBAL_FAIL=false GLOBAL_FAIL=false
'' ''
+ (concatStringsSep "\n" (mapAttrsToList (_name: secret: let + (concatStringsSep "\n" (mapAttrsToList (_name: secret: let
@ -226,40 +231,40 @@
secretFile="$SYSROOT${secretPath}" secretFile="$SYSROOT${secretPath}"
if [[ -f "$SYSROOT${secretPath}" ]]; then if [[ -f "$SYSROOT${secretPath}" ]]; then
echo " File Exists" echo "$emojiTick File Exists"
else else
echo " File Does Not Exist" echo "$emojiCross File Does Not Exist"
LOCAL_FAIL=true LOCAL_FAIL=true
fi fi
if getUserID "$SYSROOT${secretPath}" >/dev/null && ${userCheck}; then if getUserID "$SYSROOT${secretPath}" >/dev/null && ${userCheck}; then
echo " File Is Owned By Correct User" echo "$emojiTick File Is Owned By Correct User"
else else
echo " File Is Not Owned By Correct User (${toString secretUser})" echo "$emojiCross File Is Not Owned By Correct User (${toString secretUser})"
LOCAL_FAIL=true LOCAL_FAIL=true
fi fi
if getGroupID "$SYSROOT${secretPath}" >/dev/null && ${groupCheck}; then if getGroupID "$SYSROOT${secretPath}" >/dev/null && ${groupCheck}; then
echo " File Is Owned By Correct Group" echo "$emojiTick File Is Owned By Correct Group"
else else
echo " File Is Not Owned By Correct Group (${toString secretGroup})" echo "$emojiCross File Is Not Owned By Correct Group (${toString secretGroup})"
LOCAL_FAIL=true LOCAL_FAIL=true
fi fi
if getPermissions "$SYSROOT${secretPath}" >/dev/null && [[ "$(getPermissions "$SYSROOT${secretPath}")" -eq "${secretPermissions}" ]]; then if getPermissions "$SYSROOT${secretPath}" >/dev/null && [[ "$(getPermissions "$SYSROOT${secretPath}")" -eq "${secretPermissions}" ]]; then
echo " File Has Correct Permissions" echo "$emojiTick File Has Correct Permissions"
else else
echo " File Does Not Have Correct Permissions (${secretPermissions})" echo "$emojiCross File Does Not Have Correct Permissions (${secretPermissions})"
LOCAL_FAIL=true LOCAL_FAIL=true
fi fi
${optionalString (secret.checkScript != null) secret.checkScript} ${optionalString (secret.checkScript != null) secret.checkScript}
if [[ "$LOCAL_FAIL" == "true" ]]; then if [[ "$LOCAL_FAIL" == "true" ]]; then
echo " File Did Not Pass The Vibe Check" echo "$emojiCross File Did Not Pass The Vibe Check"
GLOBAL_FAIL=true GLOBAL_FAIL=true
else else
echo " File Passed The Vibe Check" echo "$emojiTick File Passed The Vibe Check"
fi fi
echo echo
@ -267,10 +272,10 @@
cfg.secrets)) cfg.secrets))
+ '' + ''
if [[ "$GLOBAL_FAIL" == "true" ]]; then if [[ "$GLOBAL_FAIL" == "true" ]]; then
echo " One Or More Secrets Did Not Pass The Vibe Check" echo "$emojiCross One Or More Secrets Did Not Pass The Vibe Check"
exit 1 exit 1
else else
echo " All Secrets Passed The Vibe Check" echo "$emojiTick All Secrets Passed The Vibe Check"
fi fi
''; '';
}; };
@ -319,7 +324,7 @@ in rec {
scripts = genScripts cfg; scripts = genScripts cfg;
in (writeShellApplication { in (writeShellApplication {
name = scriptName; name = scriptName;
runtimeInputs = defaultPackages ++ cfg.packages; runtimeInputs = defaultPackages ++ cfg.checkPackages;
text = scripts.checkScript; text = scripts.checkScript;
}) })
); );

View file

@ -18,6 +18,22 @@ in
overlays = [ overlays = [
(import ./overlay) (import ./overlay)
inputs.piped-flake.overlays.default inputs.piped-flake.overlays.default
(_prev: final: {
piped-backend-deps =
final.piped-backend-deps.overrideAttrs
{
# Won't build due to this; added a native-arm64 to all builders on arm64
# https://github.com/NixOS/nixpkgs/issues/255780
requiredSystemFeatures = ["native-arm64"];
};
piped-backend =
final.piped-backend.overrideAttrs
{
# Won't build due to this; added a native-arm64 to all builders on arm64
# https://github.com/NixOS/nixpkgs/issues/255780
requiredSystemFeatures = ["native-arm64"];
};
})
]; ];
}; };
in in
@ -50,7 +66,6 @@ in
inherit (pkgs) comic-code comic-sans; inherit (pkgs) comic-code comic-sans;
inherit (pkgs) mk-enc-usb mk-encrypted-drive mk-raspberry-ext-drive; inherit (pkgs) mk-enc-usb mk-encrypted-drive mk-raspberry-ext-drive;
inherit (pkgs) gotosocial; inherit (pkgs) gotosocial;
inherit (pkgs) cockroachdb;
inherit (pkgs) piped-backend piped-frontend piped-proxy; inherit (pkgs) piped-backend piped-frontend piped-proxy;
inherit (pkgs) kitty-terminfo; inherit (pkgs) kitty-terminfo;
}; };
@ -124,18 +139,15 @@ in
# All machines/containers with secrets.nix # All machines/containers with secrets.nix
machines = rec { machines = rec {
"hetzner-vm" = {
containers = ["storage" "piped-fi"];
sshAddress = "hetzner-vm.servers.genderfucked.monster";
};
"hetzner-arm" = { "hetzner-arm" = {
containers = ["storage" "piped-fi"]; containers = ["storage" "music" "quassel" "social" "mail" "piped-db" "piped-fi"];
sshAddress = "hetzner-vm.servers.genderfucked.monster"; sshAddress = "hetzner-arm.servers.genderfucked.monster";
}; };
"vault" = { "vault" = {
sshAddress = "vault.servers.genderfucked.monster"; sshAddress = "vault.servers.genderfucked.monster";
}; };
"raspberry" = { "raspberry" = {
containers = ["piped-uk"];
sshAddress = "raspberry.servers.genderfucked.monster"; sshAddress = "raspberry.servers.genderfucked.monster";
}; };
"lappy-t495" = {}; "lappy-t495" = {};

View file

@ -1,48 +0,0 @@
{
lib,
stdenv,
autoPatchelfHook,
fetchzip,
}:
stdenv.mkDerivation rec {
pname = "cockroachdb-bin";
version = "23.1.9";
src = let
inherit (stdenv.hostPlatform) system;
selectSystem = attrs: attrs.${system} or (throw "Unsupported system: ${system}");
suffix = selectSystem {
x86_64-linux = "linux-amd64";
aarch64-linux = "linux-arm64";
};
sha256 = selectSystem {
x86_64-linux = "sha256-TopDCszdU73WiD/fsa/lq4h7jPUk0u50v3ELiuakzTU=";
aarch64-linux = "sha256-uRW1g2IFAfQ6a1w7pz5GKklHmfaNgk70qj3hhm6KV6s=";
};
in
fetchzip {
url = "https://binaries.cockroachdb.com/cockroach-v${version}.${suffix}.tgz";
inherit sha256;
};
dontConfigure = true;
dontBuild = true;
dontStrip = stdenv.isDarwin;
nativeBuildInputs = [autoPatchelfHook];
installPhase = ''
runHook preInstall
install -D cockroach $out/bin/cockroach
runHook postInstall
'';
meta = with lib; {
homepage = "https://www.cockroachlabs.com";
description = "A scalable, survivable, strongly-consistent SQL database";
license = licenses.bsl11;
mainProgram = "cockroach";
sourceProvenance = with sourceTypes; [binaryNativeCode];
platforms = ["x86_64-linux" "aarch64-linux"];
};
}

View file

@ -13,9 +13,6 @@ final: prev: rec {
cp -r ${./kitty-terminfo}/* $out/share cp -r ${./kitty-terminfo}/* $out/share
''; '';
cockroachdb-bin = final.callPackage ./cockroachdb-bin {};
cockroachdb = cockroachdb-bin;
gotosocial = prev.gotosocial.overrideAttrs (_old: let gotosocial = prev.gotosocial.overrideAttrs (_old: let
owner = "superseriousbusiness"; owner = "superseriousbusiness";
repo = "gotosocial"; repo = "gotosocial";

View file

@ -8,10 +8,9 @@
profiles.base profiles.base
users.root users.root
modules.nixos.rclone-serve modules.nixos.rcloneServe
modules.nixos.rclone-sync modules.nixos.rcloneSync
modules.nixos.secrets modules.nixos.secrets
modules.nixos.cockroachdb-bin
]) ])
++ [ ++ [
# Default modules which are usually included in nixos.nix # Default modules which are usually included in nixos.nix

View file

@ -8,6 +8,8 @@
profiles.tor profiles.tor
]; ];
services.fwupd.enable = true;
# TODO: Better DNS setup # TODO: Better DNS setup
services.resolved.enable = false; services.resolved.enable = false;
environment.etc."resolv.conf".text = '' environment.etc."resolv.conf".text = ''

View file

@ -1,17 +1,44 @@
{ {
self, self,
config, config,
tree,
... ...
}: let }: let
clusterConfig = import "${self}/data/piped/pipedClusterConfig.nix"; inherit (builtins) attrNames elem;
inherit (clusterConfig) hosts ports;
currentHostName = config.networking.hostName; wireguardData = import "${self}/data/wireguard/chaosInternalWireGuard.nix";
currentHostConfig = hosts.${currentHostName}; wireguardHosts = wireguardData.hosts;
baseDomain = currentHostConfig.baseDomain; hostName = config.networking.hostName;
defaultPorts = {
internalPipedBackend = 3012;
internalPipedProxy = 3013;
internalNginxPort = 8199;
};
hostConfigs = {
"piped-fi" = {
baseDomain = "piped-fi.owo.monster";
ports = defaultPorts;
};
"piped-uk" = {
baseDomain = "piped-uk.owo.monster";
ports = defaultPorts;
};
};
hostConfig =
if elem hostName (attrNames hostConfigs)
then hostConfigs.${hostName}
else throw "host isn't configured for piped node";
inherit (hostConfig) baseDomain ports;
in { in {
systemd.coredump.enable = true; imports = with tree; [
profiles.nginx
];
services.piped = { services.piped = {
enable = true; enable = true;
@ -42,10 +69,9 @@ in {
disablePostgresDB = true; disablePostgresDB = true;
name = "piped"; name = "piped";
username = "piped"; username = "piped";
passwordFile = builtins.toFile "password-file" "piped"; usePassword = false;
host = "127.0.0.1"; host = "${wireguardHosts."hetzner-arm".ip}";
port = ports.cockroachDB; port = 5434;
dialect = "org.hibernate.dialect.CockroachDialect";
}; };
}; };
@ -70,42 +96,28 @@ in {
]; ];
}; };
systemd.services.piped-backend = {
after = ["network.target" "cockroachdb.service" "haproxy.service"];
wants = ["network.target" "cockroachdb.service" "haproxy.service"];
};
services.nginx.virtualHosts = let services.nginx.virtualHosts = let
componentPath = component: "/var/sockets/piped-${component}.sock"; componentPath = component: "/var/sockets/piped-${component}.sock";
listen = [
{
addr = "127.0.0.1";
port = ports.internalNginxPort;
}
];
in { in {
"${baseDomain}" = { "${baseDomain}" = {
listen = [ inherit listen;
{
addr = "127.0.0.1";
port = 8091;
}
];
extraConfig = "listen unix:${componentPath "frontend"};"; extraConfig = "listen unix:${componentPath "frontend"};";
}; };
"backend.${baseDomain}" = { "backend.${baseDomain}" = {
inherit listen;
extraConfig = "listen unix:${componentPath "backend"};"; extraConfig = "listen unix:${componentPath "backend"};";
listen = [
{
addr = "127.0.0.1";
port = 8092;
}
];
}; };
"proxy.${baseDomain}" = { "proxy.${baseDomain}" = {
inherit listen;
extraConfig = "listen unix:${componentPath "proxy"};"; extraConfig = "listen unix:${componentPath "proxy"};";
listen = [
{
addr = "127.0.0.1";
port = 8093;
}
];
}; };
}; };
} }

View file

@ -27,6 +27,8 @@
''; '';
boot.kernel.sysctl = { boot.kernel.sysctl = {
"net.core.default_qdisc" = "fq";
"net.ipv4.tcp_congestion_control" = "bbr";
"fs.inotify.max_user_watches" = 1024 * 64 * 16; "fs.inotify.max_user_watches" = 1024 * 64 * 16;
}; };

View file

@ -7,7 +7,7 @@
... ...
}: let }: let
inherit (lib.modules) mkForce; inherit (lib.modules) mkForce;
inherit (lib.lists) optional; inherit (lib.lists) optionals;
system = pkgs.system; system = pkgs.system;
@ -33,10 +33,10 @@ in {
"dm_mod" "dm_mod"
"cryptd" "cryptd"
] ]
++ (lib.optionals (system == "x86_64_linux") ["aesni_intel"]); ++ (optionals (system == "x86_64_linux") ["aesni_intel"]);
secrets = { secrets = {
"/ssh_host_ed25519_key" = "/ssh_host_ed25519_key"; "/ssh_host_ed25519_key" = mkForce "/initrd_ssh_host_ed25519_key";
}; };
luks = { luks = {

View file

@ -42,13 +42,12 @@ in {
boot.kernelParams = boot.kernelParams =
[ [
"console=tty0"
"ip=${hostServerIPs.ipv4}::${gateway}:${netmask}:${hostName}:enp1s0:any" "ip=${hostServerIPs.ipv4}::${gateway}:${netmask}:${hostName}:enp1s0:any"
"boot.shell_on_fail" "boot.shell_on_fail"
"nohibernate" "nohibernate"
"loglevel=4" "loglevel=4"
] ]
++ (lib.optionals (system == "aarch64-linux") ["console=tty" "console=ttyAMA0,115200" "console=ttyS0,115200"]); ++ (lib.optionals (system == "aarch64-linux") ["console=tty"]);
systemd.network = { systemd.network = {
enable = true; enable = true;

View file

@ -1,5 +0,0 @@
{lib, ...}: let
inherit (lib.modules) mkForce;
in {
security.sudo.wheelNeedsPassword = mkForce false;
}

View file

@ -1,10 +1,12 @@
{ {
inputs, inputs,
config, config,
pkgs,
lib, lib,
... ...
}: let }: let
inherit (lib.strings) optionalString versionAtLeast; inherit (lib.strings) optionalString versionAtLeast;
inherit (lib.optional);
in { in {
nix = { nix = {
nixPath = ["nixpkgs=${inputs.nixpkgs}"]; nixPath = ["nixpkgs=${inputs.nixpkgs}"];
@ -13,6 +15,7 @@ in {
(versionAtLeast config.nix.package.version "2.4") '' (versionAtLeast config.nix.package.version "2.4") ''
experimental-features = nix-command flakes experimental-features = nix-command flakes
''; '';
settings.system-features = lib.optional (pkgs.system == "aarch64-linux") "native-arm64";
settings.trusted-users = ["root" "@wheel"]; settings.trusted-users = ["root" "@wheel"];
}; };
nixpkgs = { nixpkgs = {
@ -30,6 +33,23 @@ in {
inputs.gitlab_artifacts_sync.overlays.default inputs.gitlab_artifacts_sync.overlays.default
inputs.gitlab_archiver.overlays.default inputs.gitlab_archiver.overlays.default
inputs.piped-flake.overlays.default inputs.piped-flake.overlays.default
(_prev: final: {
piped-backend-deps =
final.piped-backend-deps.overrideAttrs
{
# Won't build due to this; added a native-arm64 to all builders on arm64
# https://github.com/NixOS/nixpkgs/issues/255780
requiredSystemFeatures = ["native-arm64"];
};
piped-backend =
final.piped-backend.overrideAttrs
{
# Won't build due to this; added a native-arm64 to all builders on arm64
# https://github.com/NixOS/nixpkgs/issues/255780
requiredSystemFeatures = ["native-arm64"];
};
})
]; ];
}; };
environment.etc."nixpkgs-commit".text = inputs.nixpkgs-unstable.rev; environment.etc."nixpkgs-commit".text = inputs.nixpkgs-unstable.rev;

5
profiles/base/sudo.nix Normal file
View file

@ -0,0 +1,5 @@
{lib, ...}: let
inherit (lib.modules) mkDefault;
in {
security.sudo.wheelNeedsPassword = mkDefault false;
}

37
profiles/fingerprint.nix Normal file
View file

@ -0,0 +1,37 @@
{
lib,
pkgs,
config,
...
}: let
inherit (lib.modules) mkIf mkForce;
in {
services.fprintd.enable = true;
security.sudo.wheelNeedsPassword = mkForce true;
security.pam.services = {
sudo.fprintAuth = true;
login.fprintAuth = true;
gdm-fingerprint = mkIf (config.services.xserver.displayManager.gdm.enable) {
text = ''
auth required pam_shells.so
auth requisite pam_nologin.so
auth requisite pam_faillock.so preauth
auth required ${pkgs.fprintd}/lib/security/pam_fprintd.so
auth optional pam_permit.so
auth required pam_env.so
auth [success=ok default=1] ${pkgs.gnome.gdm}/lib/security/pam_gdm.so
auth optional ${pkgs.gnome.gnome-keyring}/lib/security/pam_gnome_keyring.so
account include login
password required pam_deny.so
session include login
session optional ${pkgs.gnome.gnome-keyring}/lib/security/pam_gnome_keyring.so auto_start
'';
};
};
}

View file

@ -72,5 +72,7 @@ in {
programs.dconf.enable = true; programs.dconf.enable = true;
services.gnome.gnome-keyring.enable = mkForce false;
services.xserver = {layout = "gb";}; services.xserver = {layout = "gb";};
} }

View file

@ -1,40 +0,0 @@
{
self,
config,
lib,
...
}: let
inherit (lib.lists) filter;
inherit (builtins) attrNames;
clusterConfig = import "${self}/data/piped/pipedClusterConfig.nix";
inherit (clusterConfig) hosts ports;
currentHostName = config.networking.hostName;
joinString = lib.concatStringsSep "," ([
"localhost:${toString ports.cockroachDB}"
]
++ (
map
(hostName: hosts.${hostName}.joinString)
(filter (hostName: hostName != currentHostName) (attrNames hosts))
));
in {
systemd.services.haproxy.wantedBy = ["piped-backend.service"];
services.cockroachdb-bin = {
enable = true;
certsDir = "/var/lib/cockroachdb-certs";
join = joinString;
extraArgs = ["--advertise-addr=${hosts.${currentHostName}.advertiseAddr}"];
listen = {
port = ports.cockroachDB;
address = "0.0.0.0";
};
http = {
address = "0.0.0.0";
port = ports.cockroachDB_HTTP;
};
};
}

View file

@ -1,36 +0,0 @@
{self, ...}: let
inherit (builtins) concatStringsSep attrNames;
clusterConfig = import "${self}/data/piped/pipedClusterConfig.nix";
inherit (clusterConfig) hosts ports;
in {
systemd.services.haproxy.wantedBy = ["piped-backend.service"];
services.haproxy = {
enable = true;
config = ''
global
maxconn 4096
defaults
mode tcp
retries 5
timeout connect 5s
timeout client 10m
timeout server 10m
option clitcpka
listen psql
bind :${toString ports.cockroachDB_HAProxy}
mode tcp
balance roundrobin
option httpchk GET /health?ready=1
${concatStringsSep "\n" (
map (serverConfig: " " + serverConfig)
(map (
hostName: "server ${hostName} ${hosts.${hostName}.advertiseAddr} check port ${toString ports.cockroachDB_HTTP}"
) (attrNames hosts))
)}
'';
};
}

View file

@ -3,7 +3,7 @@
config, config,
... ...
}: let }: let
inherit (lib.modules) mkIf; inherit (lib.modules) mkIf mkMerge;
currentHostname = config.networking.hostName; currentHostname = config.networking.hostName;
@ -26,22 +26,28 @@
}; };
in { in {
nix.buildMachines = [ nix.buildMachines = [
(mkIf (currentHostname != "hetzner-vm") (builderDefaults (mkIf (currentHostname != "hetzner-arm") (mkMerge [
// { builderDefaults
hostName = "hetzner-vm.servers.genderfucked.monster"; {
systems = ["x86_64-linux" "aarch64-linux"]; hostName = "hetzner-arm.servers.genderfucked.monster";
publicHostKey = "c3NoLWVkMjU1MTkgQUFBQUMzTnphQzFsWkRJMU5URTVBQUFBSU1JdDJBQnF3SGhNano5cjZhdHY0WHVYNTh4RVdlU3RrbVhVd3ZNVkd2NHcgcm9vdEBuaXhvcwo="; systems = ["aarch64-linux"];
maxJobs = 3; supportedFeatures = ["native-arm64"];
speedFactor = 2; publicHostKey = "c3NoLWVkMjU1MTkgQUFBQUMzTnphQzFsWkRJMU5URTVBQUFBSUk5cGM0REU1UlV4UUp2T1pwenFOQWVac0JlRW1kcmp4OFlnV3orVXBMckcgcm9vdEBoZXR6bmVyLWFybQo=";
})) maxJobs = 4;
(mkIf (currentHostname != "vault") (builderDefaults speedFactor = 3;
// { }
]))
(mkIf (currentHostname != "vault") (mkMerge [
builderDefaults
{
hostName = "vault.servers.genderfucked.monster"; hostName = "vault.servers.genderfucked.monster";
systems = ["x86_64-linux"]; systems = ["aarch64-linux"];
publicHostKey = "c3NoLWVkMjU1MTkgQUFBQUMzTnphQzFsWkRJMU5URTVBQUFBSU16L1dyaG81MTFGdzhXN3FsU0NUY1V4cWh4TGlBQkJXbFNNNFRNNzJ5RWQgcm9vdEBuaXhvcwo="; supportedFeatures = ["native-arm64"];
maxJobs = 2; publicHostKey = "c3NoLWVkMjU1MTkgQUFBQUMzTnphQzFsWkRJMU5URTVBQUFBSURGTlFjUTdkbUlRS1lqMUVVTFBlcTI4d2hzMTg2YVZ0WitWU05rd3I2aEkgcm9vdEB2YXVsdAo=";
maxJobs = 1;
speedFactor = 1; speedFactor = 1;
})) }
]))
]; ];
nix.distributedBuilds = true; nix.distributedBuilds = true;
nix.extraOptions = "builders-use-substitutes = true"; nix.extraOptions = "builders-use-substitutes = true";

9
scripts/deploy/hetzner-arm.sh Executable file
View file

@ -0,0 +1,9 @@
#!/usr/bin/env bash
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
cd $SCRIPT_DIR
cd $(git rev-parse --show-toplevel)
DEFAULT_HOST="root@hetzner-arm.servers.genderfucked.monster"
TARGET_HOST=${HOST:-${DEFAULT_HOST}}
nixos-rebuild switch --flake .#hetzner-arm --target-host "$TARGET_HOST" --use-substitutes -s "$@"

View file

@ -1,7 +0,0 @@
#!/usr/bin/env bash
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
cd $SCRIPT_DIR
cd $(git rev-parse --show-toplevel)
nixos-rebuild switch --flake .#hetzner-vm --target-host hetzner-vm -s "$@"

Some files were not shown because too many files have changed in this diff Show more