add caldav/carddav server & redo some htpasswd stuff

This commit is contained in:
chaos 2023-10-10 22:22:54 +01:00
parent ab830d4469
commit 65165b4a9d
No known key found for this signature in database
25 changed files with 481 additions and 62 deletions

View file

@ -0,0 +1,3 @@
{pkgs, ...}: {
home.packages = with pkgs; [thunderbird];
}

View file

@ -0,0 +1,58 @@
{
self,
hostPath,
tree,
inputs,
config,
pkgs,
...
}: let
containerAddresses = import "${hostPath}/data/containerAddresses.nix";
hostIP = containerAddresses.host;
containerIP = containerAddresses.containers.caldav;
in {
containers.caldav = {
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
./secrets.nix
#./profiles/postgres.nix
#./profiles/restic.nix
]
++ (with hosts.hetzner-arm.containers.caldav.profiles; [
radicale
restic
]);
networking.firewall.allowedTCPPorts = [5232];
home-manager.users.root.home.stateVersion = "23.05";
system.stateVersion = "23.05";
};
};
services.nginx = {
enable = true;
virtualHosts."radicale.owo.monster" = {
enableACME = true;
forceSSL = true;
locations."/".proxyPass = "http://${containerIP}:5232";
};
};
}

View file

@ -0,0 +1,31 @@
{config, ...}: let
secrets = config.services.secrets.secrets;
in {
services.radicale = {
enable = true;
settings = {
server = {
hosts = ["0.0.0.0:5232" "[::]:5232"];
};
auth = {
type = "htpasswd";
htpasswd_filename = "${secrets.radicale_htpasswd.path}";
htpasswd_encryption = "bcrypt";
};
rights = {
type = "owner_only";
};
storage = {
filesystem_folder = "/var/lib/radicale/collections";
};
};
};
users.users.radicale.uid = 1000;
users.groups.radicale.gid = 1000;
systemd.tmpfiles.rules = [
"d /var/lib/radicale - radicale radicale"
"d /var/lib/radicale/collections - radicale radicale"
];
}

View file

@ -0,0 +1,39 @@
{
pkgs,
config,
...
}: let
secrets = config.services.secrets.secrets;
in {
environment.systemPackages = with pkgs; [
restic
(pkgs.writeShellScriptBin "restic-caldav" ''
env \
RESTIC_PASSWORD_FILE=${secrets.restic_password.path} \
$(cat ${secrets.restic_env.path}) \
${pkgs.restic}/bin/restic $@
'')
];
services.restic.backups.caldav = {
user = "root";
paths = [
"/var/lib/radicale"
];
# 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/CalDAV";
passwordFile = "${secrets.restic_password.path}";
environmentFile = "${secrets.restic_env.path}";
pruneOpts = [
"--keep-last 50"
];
timerConfig = {
OnBootSec = "1m";
OnCalendar = "4h";
};
};
}

View file

@ -0,0 +1,60 @@
{pkgs, ...}: {
services.secrets = {
enable = true;
packages = with pkgs; [
apacheHttpd
];
vaultLogin = {
enable = true;
loginUsername = "hetzner-arm-container-caldav";
};
autoSecrets = {
enable = true;
};
requiredVaultPaths = [
"api-keys/data/caldav"
"api-keys/data/storage/restic/CalDAV"
"private-public-keys/data/restic/CalDAV"
];
secrets = {
vault_password = {
manual = true;
};
radicale_htpasswd = {
user = "radicale";
group = "radicale";
fetchScript = ''
if [ -f "$secretFile" ]; then
rm "$secretFile"
fi
touch "$secretFile"
data=$(kv_get "/api-keys/caldav" | base64)
for username in $(echo "$data" | base64 -d | jq -r ".data.data | keys | .[]"); do
password=$(echo "$data" | base64 -d | jq -r ".data.data.\"$username\"")
htpasswd -bB "$secretFile" "$username" "$password" 2>/dev/null
done
'';
};
restic_password = {
fetchScript = ''
simple_get "/private-public-keys/restic/CalDAV" .password > "$secretFile"
'';
};
restic_env = {
fetchScript = ''
RESTIC_PASSWORD=$(simple_get "/api-keys/storage/restic/CalDAV" .restic)
echo "RESTIC_REPOSITORY=rest:https://restic:$RESTIC_PASSWORD@storage-restic.owo.monster/CalDAV" > "$secretFile"
'';
};
};
};
}

View file

@ -1,4 +1,4 @@
{pkgs, ...}: {
{...}: {
services.secrets = {
enable = true;
@ -16,10 +16,6 @@
"private-public-keys/data/restic/Forgejo"
];
packages = with pkgs; [
apacheHttpd
];
secrets = {
vault_password = {
manual = true;
@ -32,9 +28,8 @@
};
restic_env = {
fetchScript = ''
RESTIC_USERNAME=$(simple_get "/api-keys/storage/restic/Forgejo" .username)
RESTIC_PASSWORD=$(simple_get "/api-keys/storage/restic/Forgejo" .password)
echo "RESTIC_REPOSITORY=rest:https://$RESTIC_USERNAME:$RESTIC_PASSWORD@storage-restic.owo.monster/Forgejo" > "$secretFile"
RESTIC_PASSWORD=$(simple_get "/api-keys/storage/restic/Forgejo" .restic)
echo "RESTIC_REPOSITORY=rest:https://restic:$RESTIC_PASSWORD@storage-restic.owo.monster/Forgejo" > "$secretFile"
'';
};
};

View file

@ -36,9 +36,8 @@
};
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"
RESTIC_PASSWORD=$(simple_get "/api-keys/storage/restic/Mail" .restic)
echo "RESTIC_REPOSITORY=rest:https://restic:$RESTIC_PASSWORD@storage-restic.owo.monster/Mail" > "$secretFile"
'';
};
private_mail_aliases = {

View file

@ -47,14 +47,13 @@ in {
inherit backupPrepareCommand;
};
services.postgresqlBackup = {
services.postgreSQLRemoteBackup = {
enable = true;
backupAll = false;
backupUser = "postgres";
databases = [
"piped"
"gotosocial"
"quassel"
];
compression = "zstd";
};
}

View file

@ -28,9 +28,8 @@
};
restic_env = {
fetchScript = ''
RESTIC_USERNAME=$(simple_get "/api-keys/storage/restic/PostgreSQL" .username)
RESTIC_PASSWORD=$(simple_get "/api-keys/storage/restic/PostgreSQL" .password)
echo "RESTIC_REPOSITORY=rest:https://$RESTIC_USERNAME:$RESTIC_PASSWORD@storage-restic.owo.monster/PostgreSQL" > "$secretFile"
RESTIC_PASSWORD=$(simple_get "/api-keys/storage/restic/PostgreSQL" .restic)
echo "RESTIC_REPOSITORY=rest:https://restic:$RESTIC_PASSWORD@storage-restic.owo.monster/PostgreSQL" > "$secretFile"
'';
};
};

View file

@ -28,9 +28,8 @@
};
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"
RESTIC_PASSWORD=$(simple_get "/api-keys/storage/restic/Quassel" .restic)
echo "RESTIC_REPOSITORY=rest:https://restic:$RESTIC_PASSWORD@storage-restic.owo.monster/Quassel" > "$secretFile"
'';
};
};

View file

@ -31,9 +31,8 @@
};
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"
RESTIC_PASSWORD=$(simple_get "/api-keys/storage/restic/Social" .restic)
echo "RESTIC_REPOSITORY=rest:https://restic:$RESTIC_PASSWORD@storage-restic.owo.monster/Social" > "$secretFile"
'';
};
env_secrets = {

View file

@ -2,6 +2,8 @@
rclone_serve_webdav_main = 4200;
rclone_serve_webdav_media = 4201;
rclone_serve_webdav_music_ro = 4202;
rclone_serve_webdav_public = 4202;
rclone_serve_webdav_uploads = 4202;
rclone_serve_restic_music = 4210;
rclone_serve_restic_vault = 4211;
@ -10,7 +12,9 @@
rclone_serve_restic_postgresql = 4214;
rclone_serve_restic_mail = 4215;
rclone_serve_restic_forgejo = 4216;
rclone_serve_restic_caldav = 4217;
rclone_serve_http_music = 4220;
rclone_serve_http_public = 4221;
rclone_serve_http_uploads_public = 4221;
}

View file

@ -69,6 +69,7 @@ in {
"/Main/".proxyPass = "http://${containerIP}:${toString ports.rclone_serve_webdav_main}";
"/Media/".proxyPass = "http://${containerIP}:${toString ports.rclone_serve_webdav_media}";
"/MusicRO/".proxyPass = "http://${containerIP}:${toString ports.rclone_serve_webdav_music_ro}";
"/Uploads/".proxyPass = "http://${containerIP}:${toString ports.rclone_serve_webdav_uploads}";
};
extraConfig = ''
client_max_body_size ${clientMaxBodySize};
@ -81,6 +82,7 @@ in {
locations = {
"/Music/".proxyPass = "http://${containerIP}:${toString ports.rclone_serve_http_music}";
"/Public/".proxyPass = "http://${containerIP}:${toString ports.rclone_serve_http_public}";
"/Uploads/".proxyPass = "http://${containerIP}:${toString ports.rclone_serve_http_uploads_public}";
};
extraConfig = ''
client_max_body_size ${clientMaxBodySize};
@ -98,6 +100,7 @@ in {
"/PostgreSQL/".proxyPass = "http://${containerIP}:${toString ports.rclone_serve_restic_postgresql}";
"/Mail/".proxyPass = "http://${containerIP}:${toString ports.rclone_serve_restic_mail}";
"/Forgejo/".proxyPass = "http://${containerIP}:${toString ports.rclone_serve_restic_forgejo}";
"/CalDAV/".proxyPass = "http://${containerIP}:${toString ports.rclone_serve_restic_caldav}";
};
extraConfig = ''
client_max_body_size ${clientMaxBodySize};

View file

@ -56,6 +56,27 @@ in {
"--baseurl=/MusicRO/"
];
}
{
id = "public";
remote = "StorageBox:Public";
type = "webdav";
extraArgs = [
"--addr=0.0.0.0:${toString ports.rclone_serve_webdav_public}"
"--htpasswd=${secrets.webdav_media_htpasswd.path}"
"--baseurl=/Public/"
];
}
{
id = "uploads";
remote = "StorageBox:Uploads";
type = "webdav";
extraArgs = [
"--addr=0.0.0.0:${toString ports.rclone_serve_webdav_uploads}"
"--htpasswd=${secrets.webdav_uploads_htpasswd.path}"
"--baseurl=/Uploads/"
];
}
{
id = "music-ro";
remote = "StorageBox:Music";
@ -76,6 +97,16 @@ in {
"--read-only"
];
}
{
id = "uploads-public";
remote = "StorageBox:Uploads/Public";
type = "http";
extraArgs = [
"--addr=0.0.0.0:${toString ports.rclone_serve_http_uploads_public}"
"--baseurl=/Uploads/"
"--read-only"
];
}
{
id = "restic-music";
remote = "StorageBox:Backups/Restic/Music";
@ -126,6 +157,16 @@ in {
"--baseurl=/PostgreSQL/"
];
}
{
id = "restic-caldav";
remote = "StorageBox:Backups/Restic/CalDAV";
type = "restic";
extraArgs = [
"--addr=0.0.0.0:${toString ports.rclone_serve_restic_caldav}"
"--htpasswd=${secrets.restic_caldav_htpasswd.path}"
"--baseurl=/CalDAV/"
];
}
{
id = "restic-mail";
remote = "StorageBox:Backups/Restic/Mail";

View file

@ -31,9 +31,11 @@
"api-keys/data/storage/restic/PostgreSQL"
"api-keys/data/storage/restic/Mail"
"api-keys/data/storage/restic/Forgejo"
"api-keys/data/storage/restic/CalDAV"
"api-keys/data/storage/webdav/main"
"api-keys/data/storage/webdav/media"
"api-keys/data/storage/webdav/Main"
"api-keys/data/storage/webdav/Media"
"api-keys/data/storage/webdav/Public"
"private-public-keys/data/rclone/Chaos-Media-Crypt"
];
@ -75,36 +77,46 @@
sed -i "s/$replace_password/$password/" "$3"
sed -i "s/$replace_salt/$salt/" "$3"
}
simple_get_htpasswd() {
if [ -f "$2" ]; then
rm "$2"
fi
touch "$2"
data=$(kv_get "$1" | base64)
for username in $(echo "$data" | base64 -d | jq -r ".data.data | keys | .[]"); do
password=$(echo "$data" | base64 -d | jq -r ".data.data.\"$username\"")
htpasswd -b "$2" "$username" "$password" 2>/dev/null
done
}
'';
secrets = {
vault_password = {manual = true;};
vault_password = {
manual = true;
};
restic_music_htpasswd = {
user = "storage";
group = "storage";
fetchScript = ''
username=$(simple_get "/api-keys/storage/restic/Music" .username)
password=$(simple_get "/api-keys/storage/restic/Music" .password)
htpasswd -bc "$secretFile" "$username" "$password" 2>/dev/null
simple_get_htpasswd "/api-keys/storage/restic/Music" "$secretFile"
'';
};
restic_vault_htpasswd = {
user = "storage";
group = "storage";
fetchScript = ''
username=$(simple_get "/api-keys/storage/restic/Vault" .username)
password=$(simple_get "/api-keys/storage/restic/Vault" .password)
htpasswd -bc "$secretFile" "$username" "$password" 2>/dev/null
simple_get_htpasswd "/api-keys/storage/restic/Vault" "$secretFile"
'';
};
restic_social_htpasswd = {
user = "storage";
group = "storage";
fetchScript = ''
username=$(simple_get "/api-keys/storage/restic/Social" .username)
password=$(simple_get "/api-keys/storage/restic/Social" .password)
htpasswd -bc "$secretFile" "$username" "$password" 2>/dev/null
simple_get_htpasswd "/api-keys/storage/restic/Social" "$secretFile"
'';
};
@ -112,9 +124,7 @@
user = "storage";
group = "storage";
fetchScript = ''
username=$(simple_get "/api-keys/storage/restic/Quassel" .username)
password=$(simple_get "/api-keys/storage/restic/Quassel" .password)
htpasswd -bc "$secretFile" "$username" "$password" 2>/dev/null
simple_get_htpasswd "/api-keys/storage/restic/Quassel" "$secretFile"
'';
};
@ -122,9 +132,7 @@
user = "storage";
group = "storage";
fetchScript = ''
username=$(simple_get "/api-keys/storage/restic/PostgreSQL" .username)
password=$(simple_get "/api-keys/storage/restic/PostgreSQL" .password)
htpasswd -bc "$secretFile" "$username" "$password" 2>/dev/null
simple_get_htpasswd "/api-keys/storage/restic/PostgreSQL" "$secretFile"
'';
};
@ -132,9 +140,7 @@
user = "storage";
group = "storage";
fetchScript = ''
username=$(simple_get "/api-keys/storage/restic/Mail" .username)
password=$(simple_get "/api-keys/storage/restic/Mail" .password)
htpasswd -bc "$secretFile" "$username" "$password" 2>/dev/null
simple_get_htpasswd "/api-keys/storage/restic/Mail" "$secretFile"
'';
};
@ -142,9 +148,15 @@
user = "storage";
group = "storage";
fetchScript = ''
username=$(simple_get "/api-keys/storage/restic/Forgejo" .username)
password=$(simple_get "/api-keys/storage/restic/Forgejo" .password)
htpasswd -bc "$secretFile" "$username" "$password" 2>/dev/null
simple_get_htpasswd "/api-keys/storage/restic/Forgejo" "$secretFile"
'';
};
restic_caldav_htpasswd = {
user = "storage";
group = "storage";
fetchScript = ''
simple_get_htpasswd "/api-keys/storage/restic/CalDAV" "$secretFile"
'';
};
@ -152,18 +164,28 @@
user = "storage";
group = "storage";
fetchScript = ''
username=$(simple_get "/api-keys/storage/webdav/main" .username)
password=$(simple_get "/api-keys/storage/webdav/main" .password)
htpasswd -bc "$secretFile" "$username" "$password" 2>/dev/null
simple_get_htpasswd "/api-keys/storage/webdav/Main" "$secretFile"
'';
};
webdav_media_htpasswd = {
user = "storage";
group = "storage";
fetchScript = ''
username=$(simple_get "/api-keys/storage/webdav/media" .username)
password=$(simple_get "/api-keys/storage/webdav/media" .password)
htpasswd -bc "$secretFile" "$username" "$password" 2>/dev/null
simple_get_htpasswd "/api-keys/storage/webdav/Media" "$secretFile"
'';
};
webdav_public_htpasswd = {
user = "storage";
group = "storage";
fetchScript = ''
simple_get_htpasswd "/api-keys/storage/webdav/Public" "$secretFile"
'';
};
webdav_uploads_htpasswd = {
user = "storage";
group = "storage";
fetchScript = ''
simple_get_htpasswd "/api-keys/storage/webdav/Uploads" "$secretFile"
'';
};

View file

@ -8,5 +8,6 @@
forgejo = "10.0.1.6";
postgresql = "10.0.1.7";
piped-fi = "10.0.1.8";
caldav = "10.0.1.9";
};
}

View file

@ -28,6 +28,7 @@ in {
"piped-fi"
"mail"
"forgejo"
"caldav"
] (name: ./containers + "/${name}"))
++ (with hosts.hetzner-arm.profiles; [
staticSites

View file

@ -18,12 +18,12 @@
restic_music_env = {
user = "chaos";
fetchScript = ''
api_username=$(simple_get "/api-keys/storage/restic/Music" .username)
api_password=$(simple_get "/api-keys/storage/restic/Music" .password)
api_username=restic
api_password=$(simple_get "/api-keys/storage/restic/Music" ".$api_username")
restic_password=$(simple_get "/private-public-keys/restic/Music" .password)
echo > "$secretFile"
echo "RESTIC_REPOSITORY=rest:https://''${api_username}:''${api_password}@storage-restic.owo.monster/Music" >> "$secretFile"
echo "RESTIC_REPOSITORY=rest:https://$api_username:$api_password@storage-restic.owo.monster/Music" >> "$secretFile"
echo "RESTIC_PASSWORD=''${restic_password}" >> "$secretFile"
'';
};

View file

@ -35,6 +35,7 @@
tree.modules.nixos.rcloneServe
tree.modules.nixos.rcloneSync
tree.modules.nixos.secrets
tree.modules.nixos.postgreSQLRemoteBackup
];
nixosUnstableSystem = nixpkgs-unstable.lib.nixosSystem;

View file

@ -65,9 +65,8 @@
};
restic_env = {
fetchScript = ''
RESTIC_USERNAME=$(simple_get "/api-keys/storage/restic/Vault" .username)
RESTIC_PASSWORD=$(simple_get "/api-keys/storage/restic/Vault" .password)
echo "RESTIC_REPOSITORY=rest:https://$RESTIC_USERNAME:$RESTIC_PASSWORD@storage-restic.owo.monster/Vault" > "$secretFile"
RESTIC_PASSWORD=$(simple_get "/api-keys/storage/restic/Vault" .restic)
echo "RESTIC_REPOSITORY=rest:https://restic:$RESTIC_PASSWORD@storage-restic.owo.monster/Vault" > "$secretFile"
'';
};

View file

@ -0,0 +1,165 @@
{
config,
lib,
pkgs,
...
}: let
inherit (builtins) listToAttrs getAttr;
inherit (lib.modules) mkIf mkMerge;
inherit (lib.options) mkOption mkEnableOption mdDoc;
inherit (lib.strings) optionalString;
inherit (lib.attrsets) attrValues;
inherit (lib) types;
cfg = config.services.postgreSQLRemoteBackup;
in {
options = {
# TODO: add host, port, user options
services.postgreSQLRemoteBackup = {
enable = mkEnableOption (mdDoc "PostgreSQL database dumps");
keepPrev = mkOption {
default = true;
type = types.bool;
description = mdDoc ''
Keep the previous run's backups but rename them to $name.prev
'';
};
startAt = mkOption {
default = "4h";
type = with types; either (listOf str) str;
description = mdDoc ''
This option defines (see `systemd.time` for format) when the
databases should be dumped.
The default is run every 4 hours.
'';
};
backupUser = mkOption {
default = "root";
type = types.str;
description = mdDoc ''
User which will be used for backup job and files
'';
};
databases = mkOption {
default = [];
type = types.listOf types.str;
description = mdDoc ''
List of database names to dump.
'';
};
location = mkOption {
default = "/var/backup/postgresql";
type = types.path;
description = mdDoc ''
Path of directory where the PostgreSQL database dumps will be placed.
'';
};
pgdumpOptions = mkOption {
type = types.separatedString " ";
default = "-C";
description = mdDoc ''
Command line options for pg_dump.
'';
};
compression = mkOption {
type = types.enum ["none" "zstd"];
default = "zstd";
description = mdDoc ''
The type of compression to use on the generated database dump.
'';
};
compressionLevel = mkOption {
type = types.int;
default = 9;
description = mdDoc ''
The compression level used when compression is enabled.
zstd accepts levels 1 to 19.
'';
};
};
};
config = mkMerge [
(mkIf cfg.enable {
systemd.tmpfiles.rules = [
"d '${cfg.location}' 0700 ${cfg.backupUser} - - -"
];
})
(mkIf (cfg.enable) {
systemd.services = listToAttrs (map (db: {
name = "remotePostgreSQLBackup-${db}";
value = let
compressSuffixes = {
"none" = "";
"zstd" = ".zstd";
};
compressSuffix = getAttr cfg.compression compressSuffixes;
compressCmd = getAttr cfg.compression {
"none" = "cat";
"zstd" = "${pkgs.zstd}/bin/zstd -c -${toString cfg.compressionLevel}";
};
mkSqlPath = prefix: suffix: "${cfg.location}/${db}${prefix}.sql${suffix}";
curFile = mkSqlPath "" compressSuffix;
prevFile = mkSqlPath ".prev" compressSuffix;
prevFiles = map (mkSqlPath ".prev") (attrValues compressSuffixes);
inProgressFile = mkSqlPath ".in-progress" compressSuffix;
in {
enable = true;
description = "Backup of ${db} database(s)";
requires = mkIf (config.services.postgresql.enable) [
"postgresql.service"
];
path = [
pkgs.coreutils
(let
pgCfg = config.services.postgresql;
in
if pgCfg.enable
then pgCfg.package
else pkgs.postgresql)
];
script = ''
set -e -o pipefail
umask 0077 # ensure backup is only readable by backup user
${optionalString (cfg.keepPrev) ''
if [ -e ${curFile} ]; then
rm -f ${toString prevFiles}
mv ${curFile} ${prevFile}
fi
''}
pg_dump ${cfg.pgdumpOptions} ${db} \
| ${compressCmd} \
> ${inProgressFile}
mv ${inProgressFile} ${curFile}
'';
serviceConfig = {
Type = "oneshot";
User = cfg.backupUser;
};
startAt = cfg.startAt;
};
})
cfg.databases);
})
];
}

View file

@ -141,7 +141,7 @@ in
# All machines/containers with secrets.nix
machines = rec {
"hetzner-arm" = {
containers = ["storage" "music" "quassel" "social" "mail" "postgresql" "piped-fi" "forgejo"];
containers = ["storage" "music" "quassel" "social" "mail" "postgresql" "piped-fi" "forgejo" "caldav"];
sshAddress = "hetzner-arm.servers.genderfucked.monster";
};
"vault" = {

View file

@ -11,6 +11,7 @@
modules.nixos.rcloneServe
modules.nixos.rcloneSync
modules.nixos.secrets
modules.nixos.postgreSQLRemoteBackup
])
++ [
# Default modules which are usually included in nixos.nix

View file

@ -21,6 +21,7 @@
home.apps.firefox
home.apps.telegram
home.apps.thunderbird
home.apps.quassel
home.apps.session
home.apps.toot-cli

View file

@ -22,8 +22,7 @@ in {
config = {
allowUnfree = true;
permittedInsecurePackages = [
];
permittedInsecurePackages = [];
};
overlays = [
(import ../../overlay)