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 {
"hetzner-vm" = {
ipv4 = "65.21.182.73";
ipv6 = "2a01:4f9:c010:8beb::1";
};
"hetzner-arm" = {
ipv4 = "65.21.145.62";
ipv6 = "2a01:4f9:c012:9dbf::1";

View file

@ -2,10 +2,10 @@ let
pubkeys = builtins.fromJSON (builtins.readFile ./chaosInternalWireGuardPubKeys.json);
in rec {
hosts = {
"hetzner-vm" = {
"hetzner-arm" = {
ip = "10.69.42.1";
public = pubkeys."hetzner-vm";
endpoint = "hetzner-vm.servers.genderfucked.monster:51820";
public = pubkeys."hetzner-arm";
endpoint = "hetzner-arm.servers.genderfucked.monster:51820";
};
"vault" = {
ip = "10.69.42.2";
@ -25,11 +25,5 @@ in rec {
public = pubkeys."raspberry";
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": "u8hSeht8xR48O9AN+0cSsXPK0ZZFNcnPhOxdc+rsrlI=",
"raspberry": "Ghrs0ps2RCsg0My9seLq+8ZFZCM4NLZWE8RiY3g9/RU=",
"lappy-t495": "8aZBM3f8/qThiHvGlGP1IHLoe61m/3VTwNzCi7CrhF8=",
"iphone8": "jHPQuWXO5TTBACr4o/tk4bpb+N/x/AjCPGbmqkopOko=",
"hetzner-arm": "2SS9jT6Sba61lB2ayhp+2fz+GN706Jr1Ydr6/RveqUQ="
"vault": "0jGdR0yBnjY5CUCQpqWIaWAfgT36QdGdhZXtaAV+MkE=",
"raspberry": "DXXUfkR4qlytdsf37NGzgzVhDxPuhz8oxRcSxOX2fQk=",
"lappy-t495": "kyykcuDMWy1WRxX97PImEYgwWw8HUbhM53kW6bEyryA=",
"iphone8": "1u/G60EWg2bo1iyViWAGXs8HXES2zenZCVdD5X+yJi4=",
"hetzner-arm": "rCkptlaz5IFSZ+4OPaylbyKVoUwYNWBNkaT63QApymA="
}

View file

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

View file

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

View file

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

View file

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

View file

@ -1,10 +1,21 @@
{pkgs, ...}: {
{pkgs, ...}: let
gitPackage = pkgs.gitAndTools.gitFull;
in {
programs.git = {
enable = true;
lfs.enable = true;
package = pkgs.gitAndTools.gitFull;
package = gitPackage;
userName = "chaos";
userEmail = "chaoticryptidz@owo.monster";
extraConfig = {credential = {helper = "store";};};
userEmail = "chaos@owo.monster";
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, ...}: {
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
nmap
tcpdump
iftop
speedtest-cli
];
}

View file

@ -3,8 +3,12 @@
nixosConfig,
pkgs,
inputs,
lib,
...
}: let
inherit (lib.lists) optional;
inherit (lib.modules) mkIf;
homeManagerLib = inputs.home-manager.lib.hm;
fontSizesAll = {
@ -18,10 +22,16 @@
if fontSizesAll ? nixosConfig.networking.hostName
then fontSizesAll.${nixosConfig.networking.hostName}
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 = {
SAL_USE_VCLPLUGIN = "gtk3"; # GTK3 on LibreOffice
@ -126,17 +136,18 @@ in {
area-screenshot-clip = ["<Shift>Print"];
screenshot = [];
screenshot-clip = ["Print"];
search = mkIf isWayland ["<Alt>d"];
custom-keybindings = [
# 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/rofi" = {
# binding = "<Alt>d";
# command = "rofi -show run";
# name = "rofi";
#};
"org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/rofi" = mkIf (!isWayland) {
binding = "<Alt>d";
command = "rofi -show run";
name = "rofi";
};
"org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/kitty" = {
binding = "<Alt>Return";
command = "kitty";

View file

@ -8,8 +8,7 @@
hostPath,
...
}: let
inherit (lib.modules) mkMerge;
inherit (lib.lists) forEach;
inherit (lib.modules) mkMerge mkForce;
ports = [
# SMTP
@ -26,20 +25,6 @@
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 = [
"/var/lib/acme/mail.owo.monster/fullchain.pem"
"/var/lib/acme/mail.owo.monster/key.pem"
@ -48,74 +33,51 @@ in {
containers.mail = {
autoStart = true;
bindMounts = mkMerge [
(containerLib.genBindHostsForSecrets secrets secretsList)
(mkMerge (forEach sharedFiles (file: {
bindMounts = mkMerge (map (file: {
"${file}" = {
hostPath = "${file}";
};
})))
];
})
sharedFiles);
specialArgs = {
inherit inputs;
inherit tree;
inherit self;
inherit hostPath;
hostSecrets = secrets;
};
config = {config, ...}: {
config = {...}: {
nixpkgs.pkgs = pkgs;
imports = with tree;
[
profiles.base
inputs.home-manager-unstable.nixosModules.home-manager
presets.nixos.containerBase
profiles.nginx
modules.nixos.secrets
users.root
./secrets.nix
]
++ (with hosts.hetzner-vm.containers.mail; [
++ (with hosts.hetzner-arm.containers.mail; [
modules.mailserver
profiles.mailserver
profiles.restic
]);
# For Shared Secrets
systemd.tmpfiles.rules = [
"d ${config.services.secrets.secretsDir} - root root"
"d /var/lib/acme - root root"
"d /var/lib/acme/mail.owo.monster - root root"
];
networking.firewall = {
enable = false;
enable = mkForce false;
};
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";
home-manager.users.root.home.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
services.nginx = {
enable = true;

View file

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

View file

@ -1,11 +1,12 @@
{
pkgs,
config,
hostSecrets,
...
}: let
secrets = hostSecrets;
secrets = config.services.secrets.secrets;
mailConfig = config.services.mailserver;
backupPrepareCommand = "${
(pkgs.writeShellScriptBin "backupPrepareCommand" ''
systemctl start postgresqlBackup-roundcube --wait
@ -16,8 +17,8 @@ in {
restic
(pkgs.writeShellScriptBin "restic-mail" ''
env \
RESTIC_PASSWORD_FILE=${secrets.mail_restic_password.path} \
$(cat ${secrets.mail_restic_env.path}) \
RESTIC_PASSWORD_FILE=${secrets.restic_password.path} \
$(cat ${secrets.restic_env.path}) \
${pkgs.restic}/bin/restic $@
'')
];
@ -36,8 +37,8 @@ in {
# 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/Mail";
passwordFile = "${secrets.mail_restic_password.path}";
environmentFile = "${secrets.mail_restic_env.path}";
passwordFile = "${secrets.restic_password.path}";
environmentFile = "${secrets.restic_env.path}";
pruneOpts = [
"--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,
lib,
inputs,
config,
pkgs,
config,
...
}: let
inherit (lib.modules) mkMerge;
inherit (lib.lists) forEach;
containerName = "music";
containerAddresses = import "${hostPath}/data/containerAddresses.nix";
hostIP = containerAddresses.host;
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;
# 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 {
containers.music = {
autoStart = true;
privateNetwork = true;
hostAddress = hostIP;
localAddress = containerIP;
bindMounts = containerLib.genBindHostsForSecrets secrets secretsList;
specialArgs = {
inherit inputs;
inherit tree;
inherit self;
inherit hostPath;
hostSecrets = secrets;
};
config = {config, ...}: {
config = {...}: {
nixpkgs.pkgs = pkgs;
imports = with tree;
@ -58,8 +48,10 @@ in {
profiles.nginx
profiles.firewallAllow.httpCommon
./secrets.nix
]
++ (with hosts.hetzner-vm.containers.music; [
++ (with hosts.hetzner-arm.containers.music; [
profiles.mpd
profiles.musicSync
profiles.soulseek
@ -75,11 +67,6 @@ in {
slskd-web
];
# For Shared Secrets
systemd.tmpfiles.rules = [
"d ${config.services.secrets.secretsDir} - root root"
];
home-manager.users.root.home.stateVersion = "23.05";
system.stateVersion = "23.05";
};
@ -97,7 +84,7 @@ in {
services.nginx.virtualHosts."stream.owo.monster" = let
extraConfig = ''
auth_basic "Music Password";
auth_basic_user_file ${secrets.music_stream_passwd.path};
auth_basic_user_file ${pathInContainer containerSecrets.music_stream_passwd.path};
'';
in {
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 = {
nat.forwardPorts = [
{

View file

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

View file

@ -1,10 +1,10 @@
{
lib,
hostSecrets,
config,
...
}: let
ports = import ../data/ports.nix;
secrets = hostSecrets;
secrets = config.services.secrets.secrets;
inherit (lib.modules) mkForce;
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,
config,
pkgs,
lib,
...
}: let
containerName = "piped-fi";
containerConfig = config.containers.${containerName}.config;
inherit (lib.modules) mkForce;
pipedName = "piped-fi";
containerName = pipedName;
pipedSocketForComponent = (
component: "/var/lib/nixos-containers/${containerName}/var/sockets/piped-${component}.sock"
);
in {
containers.piped-fi = {
containers.${containerName} = {
autoStart = true;
privateNetwork = false;
@ -28,32 +31,19 @@ in {
config = {...}: {
nixpkgs.pkgs = pkgs;
imports = with tree;
[
imports = with tree; [
presets.nixos.containerBase
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"
presets.nixos.pipedNode
];
networking.firewall.enable = mkForce false;
home-manager.users.root.home.stateVersion = "23.05";
system.stateVersion = "23.05";
};
};
services.nginx.virtualHosts."piped-fi.owo.monster" = {
services.nginx.virtualHosts."${pipedName}.owo.monster" = {
forceSSL = true;
enableACME = true;
locations."/" = {
@ -61,7 +51,7 @@ in {
};
};
services.nginx.virtualHosts."backend.piped-fi.owo.monster" = {
services.nginx.virtualHosts."backend.${pipedName}.owo.monster" = {
forceSSL = true;
enableACME = true;
locations."/" = {
@ -69,7 +59,7 @@ in {
};
};
services.nginx.virtualHosts."proxy.piped-fi.owo.monster" = {
services.nginx.virtualHosts."proxy.${pipedName}.owo.monster" = {
forceSSL = true;
enableACME = true;
locations."/" = {

View file

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

View file

@ -1,9 +1,9 @@
{
pkgs,
hostSecrets,
config,
...
}: let
secrets = hostSecrets;
secrets = config.services.secrets.secrets;
backupPrepareCommand = "${
(pkgs.writeShellScriptBin "backupPrepareCommand" ''
@ -15,8 +15,8 @@ in {
restic
(pkgs.writeShellScriptBin "restic-quassel" ''
env \
RESTIC_PASSWORD_FILE=${secrets.quassel_restic_password.path} \
$(cat ${secrets.quassel_restic_env.path}) \
RESTIC_PASSWORD_FILE=${secrets.restic_password.path} \
$(cat ${secrets.restic_env.path}) \
${pkgs.restic}/bin/restic $@
'')
];
@ -31,8 +31,8 @@ in {
# 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/Quassel";
passwordFile = "${secrets.quassel_restic_password.path}";
environmentFile = "${secrets.quassel_restic_env.path}";
passwordFile = "${secrets.restic_password.path}";
environmentFile = "${secrets.restic_env.path}";
pruneOpts = [
"--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,
hostSecrets,
config,
...
}: let
containerAddresses = import "${hostPath}/data/containerAddresses.nix";
hostIP = containerAddresses.host;
containerIP = containerAddresses.containers.social;
secrets = hostSecrets;
secrets = config.services.secrets.secrets;
in {
services.gotosocial = {
enable = true;
setupPostgresqlDB = true;
environmentFile = secrets.social_env_secrets.path;
environmentFile = secrets.env_secrets.path;
settings = {
application-name = "chaos-gts";

View file

@ -2,13 +2,12 @@
pkgs,
config,
lib,
hostSecrets,
...
}: let
inherit (lib.strings) concatStringsSep;
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
# and duplicate the wrapper for use in a systemd unit
@ -48,8 +47,8 @@ in {
restic
(pkgs.writeShellScriptBin "restic-social" ''
env \
RESTIC_PASSWORD_FILE=${secrets.social_restic_password.path} \
$(cat ${secrets.social_restic_env.path}) \
RESTIC_PASSWORD_FILE=${secrets.restic_password.path} \
$(cat ${secrets.restic_env.path}) \
${pkgs.restic}/bin/restic $@
'')
];
@ -64,8 +63,8 @@ in {
# 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/Social";
passwordFile = "${secrets.social_restic_password.path}";
environmentFile = "${secrets.social_restic_env.path}";
passwordFile = "${secrets.restic_password.path}";
environmentFile = "${secrets.restic_env.path}";
pruneOpts = [
"--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_social = 4212;
rclone_serve_restic_quassel = 4213;
rclone_serve_restic_piped_finland = 4214;
rclone_serve_restic_piped = 4214;
rclone_serve_restic_mail = 4215;
rclone_serve_http_music = 4220;

View file

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

View file

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

View file

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

View file

@ -1,4 +1,4 @@
[StorageBox-Remote]
[StorageBox-Remote-WebDAV]
type = webdav
vendor = other
host = u323231.your-storagebox.de
@ -6,6 +6,22 @@ url = https://u323231.your-storagebox.de
user = u323231
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]
type = hasher
remote = StorageBox-Remote:

View file

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

View file

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

View file

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

View file

@ -1,4 +1,4 @@
{pkgs, ...}: {
{...}: {
services.secrets = {
enable = true;
@ -9,12 +9,15 @@
autoSecrets = {
enable = true;
#affectedSystemdServices = [
# "wg-quick-wg0"
#];
affectedSystemdServices = [
"wg-quick-wg0"
];
};
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"
];
@ -23,6 +26,34 @@
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
# for fetching gitlab static sites
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
profiles.cross.arm64
#profiles.remote-builders
profiles.remoteBuilders
profiles.chaosInternalWireGuard
profiles.fingerprint
./secrets.nix
];

View file

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

View file

@ -33,10 +33,9 @@
inputs.gitlab_artifacts_sync.nixosModules.default
inputs.piped-flake.nixosModules.default
tree.modules.nixos.rclone-serve
tree.modules.nixos.rclone-sync
tree.modules.nixos.rcloneServe
tree.modules.nixos.rcloneSync
tree.modules.nixos.secrets
tree.modules.nixos.cockroachdb-bin
];
nixosUnstableSystem = nixpkgs-unstable.lib.nixosSystem;
@ -81,16 +80,6 @@ in {
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 {
specialArgs =
defaultSpecialArgs

View file

@ -5,16 +5,19 @@
inputs,
config,
pkgs,
lib,
...
}: let
containerName = "piped-uk";
containerConfig = config.containers.${containerName}.config;
inherit (lib.modules) mkForce;
pipedName = "piped-uk";
containerName = pipedName;
pipedSocketForComponent = (
component: "/var/lib/nixos-containers/${containerName}/var/sockets/piped-${component}.sock"
);
in {
containers.piped-uk = {
containers.${containerName} = {
autoStart = true;
privateNetwork = false;
@ -30,26 +33,17 @@ in {
imports = with tree; [
presets.nixos.containerBase
profiles.nginx
profiles.firewallAllow.httpCommon
profiles.pipedCluster
./secrets.nix
presets.nixos.pipedNode
];
# 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";
system.stateVersion = "23.05";
};
};
services.nginx.virtualHosts."piped-uk.owo.monster" = {
services.nginx.virtualHosts."${pipedName}.owo.monster" = {
forceSSL = true;
enableACME = true;
locations."/" = {
@ -57,7 +51,7 @@ in {
};
};
services.nginx.virtualHosts."backend.piped-uk.owo.monster" = {
services.nginx.virtualHosts."backend.${pipedName}.owo.monster" = {
forceSSL = true;
enableACME = true;
locations."/" = {
@ -65,7 +59,7 @@ in {
};
};
services.nginx.virtualHosts."proxy.piped-uk.owo.monster" = {
services.nginx.virtualHosts."proxy.${pipedName}.owo.monster" = {
forceSSL = true;
enableACME = true;
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 = [
"/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"
@ -27,11 +28,28 @@
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
# but it makes it easier to install.
# it's stored in /nix store anyway
ssh_host_ed25519_key = {
path = "/ssh_host_ed25519_key";
initrd_ssh_host_ed25519_key = {
path = "/initrd_ssh_host_ed25519_key";
permissions = "600";
fetchScript = ''
simple_get "/private-public-keys/ssh/root@vault-decrypt" .private | base64 -d > "$secretFile"

View file

@ -14,6 +14,7 @@
]
++ (with hosts.vault.profiles; [
vault
vaultUI
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 != []) {
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 (
job: ''
${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.lists) filter;
inherit (lib) types;
inherit (builtins) isString listToAttrs;
inherit (builtins) isString listToAttrs attrNames;
cfg = config.services.secrets;
@ -115,25 +115,79 @@ in {
extraFunctions = mkOption {
type = types.lines;
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 {
type = types.attrsOf types.int;
default = {};
description = "optional mapping of users to user IDs; required for SYSROOT when user isn't available on host";
default = listToAttrs (map (
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 {
type = types.attrsOf types.int;
default = {};
description = "optional mapping of groups to group IDs; required for SYSROOT when group isn't available on host";
default = listToAttrs (map (
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 {
type = types.listOf types.package;
default = [];
description = "packages for script";
description = "packages for init script";
};
checkPackages = mkOption {
type = types.listOf types.package;
default = [];
description = "packages for checkscript";
};
secrets = mkOption {
@ -241,7 +295,7 @@ in {
// {
auto-secrets.partOf =
map (unitConfig: unitConfig.name + ".service")
(lib.filter
(filter
(unitConfig: unitConfig.withPartOf)
affectedSystemdServices);
};

View file

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

View file

@ -18,6 +18,22 @@ in
overlays = [
(import ./overlay)
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
@ -50,7 +66,6 @@ in
inherit (pkgs) comic-code comic-sans;
inherit (pkgs) mk-enc-usb mk-encrypted-drive mk-raspberry-ext-drive;
inherit (pkgs) gotosocial;
inherit (pkgs) cockroachdb;
inherit (pkgs) piped-backend piped-frontend piped-proxy;
inherit (pkgs) kitty-terminfo;
};
@ -124,18 +139,15 @@ in
# All machines/containers with secrets.nix
machines = rec {
"hetzner-vm" = {
containers = ["storage" "piped-fi"];
sshAddress = "hetzner-vm.servers.genderfucked.monster";
};
"hetzner-arm" = {
containers = ["storage" "piped-fi"];
sshAddress = "hetzner-vm.servers.genderfucked.monster";
containers = ["storage" "music" "quassel" "social" "mail" "piped-db" "piped-fi"];
sshAddress = "hetzner-arm.servers.genderfucked.monster";
};
"vault" = {
sshAddress = "vault.servers.genderfucked.monster";
};
"raspberry" = {
containers = ["piped-uk"];
sshAddress = "raspberry.servers.genderfucked.monster";
};
"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
'';
cockroachdb-bin = final.callPackage ./cockroachdb-bin {};
cockroachdb = cockroachdb-bin;
gotosocial = prev.gotosocial.overrideAttrs (_old: let
owner = "superseriousbusiness";
repo = "gotosocial";

View file

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

View file

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

View file

@ -1,17 +1,44 @@
{
self,
config,
tree,
...
}: let
clusterConfig = import "${self}/data/piped/pipedClusterConfig.nix";
inherit (clusterConfig) hosts ports;
inherit (builtins) attrNames elem;
currentHostName = config.networking.hostName;
currentHostConfig = hosts.${currentHostName};
wireguardData = import "${self}/data/wireguard/chaosInternalWireGuard.nix";
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 {
systemd.coredump.enable = true;
imports = with tree; [
profiles.nginx
];
services.piped = {
enable = true;
@ -42,10 +69,9 @@ in {
disablePostgresDB = true;
name = "piped";
username = "piped";
passwordFile = builtins.toFile "password-file" "piped";
host = "127.0.0.1";
port = ports.cockroachDB;
dialect = "org.hibernate.dialect.CockroachDialect";
usePassword = false;
host = "${wireguardHosts."hetzner-arm".ip}";
port = 5434;
};
};
@ -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
componentPath = component: "/var/sockets/piped-${component}.sock";
in {
"${baseDomain}" = {
listen = [
{
addr = "127.0.0.1";
port = 8091;
port = ports.internalNginxPort;
}
];
in {
"${baseDomain}" = {
inherit listen;
extraConfig = "listen unix:${componentPath "frontend"};";
};
"backend.${baseDomain}" = {
inherit listen;
extraConfig = "listen unix:${componentPath "backend"};";
listen = [
{
addr = "127.0.0.1";
port = 8092;
}
];
};
"proxy.${baseDomain}" = {
inherit listen;
extraConfig = "listen unix:${componentPath "proxy"};";
listen = [
{
addr = "127.0.0.1";
port = 8093;
}
];
};
};
}

View file

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

View file

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

View file

@ -42,13 +42,12 @@ in {
boot.kernelParams =
[
"console=tty0"
"ip=${hostServerIPs.ipv4}::${gateway}:${netmask}:${hostName}:enp1s0:any"
"boot.shell_on_fail"
"nohibernate"
"loglevel=4"
]
++ (lib.optionals (system == "aarch64-linux") ["console=tty" "console=ttyAMA0,115200" "console=ttyS0,115200"]);
++ (lib.optionals (system == "aarch64-linux") ["console=tty"]);
systemd.network = {
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,
config,
pkgs,
lib,
...
}: let
inherit (lib.strings) optionalString versionAtLeast;
inherit (lib.optional);
in {
nix = {
nixPath = ["nixpkgs=${inputs.nixpkgs}"];
@ -13,6 +15,7 @@ in {
(versionAtLeast config.nix.package.version "2.4") ''
experimental-features = nix-command flakes
'';
settings.system-features = lib.optional (pkgs.system == "aarch64-linux") "native-arm64";
settings.trusted-users = ["root" "@wheel"];
};
nixpkgs = {
@ -30,6 +33,23 @@ in {
inputs.gitlab_artifacts_sync.overlays.default
inputs.gitlab_archiver.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;

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;
services.gnome.gnome-keyring.enable = mkForce false;
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,
...
}: let
inherit (lib.modules) mkIf;
inherit (lib.modules) mkIf mkMerge;
currentHostname = config.networking.hostName;
@ -26,22 +26,28 @@
};
in {
nix.buildMachines = [
(mkIf (currentHostname != "hetzner-vm") (builderDefaults
// {
hostName = "hetzner-vm.servers.genderfucked.monster";
systems = ["x86_64-linux" "aarch64-linux"];
publicHostKey = "c3NoLWVkMjU1MTkgQUFBQUMzTnphQzFsWkRJMU5URTVBQUFBSU1JdDJBQnF3SGhNano5cjZhdHY0WHVYNTh4RVdlU3RrbVhVd3ZNVkd2NHcgcm9vdEBuaXhvcwo=";
maxJobs = 3;
speedFactor = 2;
}))
(mkIf (currentHostname != "vault") (builderDefaults
// {
(mkIf (currentHostname != "hetzner-arm") (mkMerge [
builderDefaults
{
hostName = "hetzner-arm.servers.genderfucked.monster";
systems = ["aarch64-linux"];
supportedFeatures = ["native-arm64"];
publicHostKey = "c3NoLWVkMjU1MTkgQUFBQUMzTnphQzFsWkRJMU5URTVBQUFBSUk5cGM0REU1UlV4UUp2T1pwenFOQWVac0JlRW1kcmp4OFlnV3orVXBMckcgcm9vdEBoZXR6bmVyLWFybQo=";
maxJobs = 4;
speedFactor = 3;
}
]))
(mkIf (currentHostname != "vault") (mkMerge [
builderDefaults
{
hostName = "vault.servers.genderfucked.monster";
systems = ["x86_64-linux"];
publicHostKey = "c3NoLWVkMjU1MTkgQUFBQUMzTnphQzFsWkRJMU5URTVBQUFBSU16L1dyaG81MTFGdzhXN3FsU0NUY1V4cWh4TGlBQkJXbFNNNFRNNzJ5RWQgcm9vdEBuaXhvcwo=";
maxJobs = 2;
systems = ["aarch64-linux"];
supportedFeatures = ["native-arm64"];
publicHostKey = "c3NoLWVkMjU1MTkgQUFBQUMzTnphQzFsWkRJMU5URTVBQUFBSURGTlFjUTdkbUlRS1lqMUVVTFBlcTI4d2hzMTg2YVZ0WitWU05rd3I2aEkgcm9vdEB2YXVsdAo=";
maxJobs = 1;
speedFactor = 1;
}))
}
]))
];
nix.distributedBuilds = 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 "$@"

View file

@ -4,5 +4,6 @@ SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
cd $SCRIPT_DIR
cd $(git rev-parse --show-toplevel)
[ -n "$NO_BUILD_PIPED_BACKEND" ] && ./scripts/buildPipedBackendAArch64.nix
nixos-rebuild switch --flake .#raspberry --target-host raspberry -s "$@"
DEFAULT_HOST="root@raspberry.servers.genderfucked.monster"
TARGET_HOST=${HOST:-${DEFAULT_HOST}}
nixos-rebuild switch --flake .#raspberry --target-host "$TARGET_HOST" --use-substitutes -s "$@"

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