reencrypt secrets and fix nextcloud backups

This commit is contained in:
Noah Masur 2022-10-16 03:18:58 +00:00
parent 69a54b99c8
commit 0f112ea16b
9 changed files with 104 additions and 112 deletions

View File

@ -0,0 +1,46 @@
{ config, pkgs, lib, ... }: {
options = {
backupS3 = {
endpoint = lib.mkOption {
type = lib.types.str;
description = "S3 endpoint for backups";
};
bucket = lib.mkOption {
type = lib.types.str;
description = "S3 bucket for backups";
};
accessKeyId = lib.mkOption {
type = lib.types.str;
description = "S3 access key ID for backups";
};
};
};
config = {
secrets.backup = {
source = ../../private/backup.age;
dest = "${config.secretsDirectory}/backup";
};
# # Backup library to object storage
# services.restic.backups.calibre = {
# user = "calibre-web";
# repository =
# "s3://${config.backupS3.endpoint}/${config.backupS3.bucket}/calibre";
# paths = [
# "/var/books"
# "/var/lib/calibre-web/app.db"
# "/var/lib/calibre-web/gdrive.db"
# ];
# initialize = true;
# timerConfig = { OnCalendar = "00:05:00"; };
# environmentFile = backupS3File;
# };
};
}

View File

@ -1,13 +1,6 @@
{ config, pkgs, lib, ... }: { config, pkgs, lib, ... }: {
let imports = [ ./caddy.nix ./secrets.nix ./backups.nix ];
adminpassFile = "${config.services.nextcloud.datadir}/creds";
backupS3File = "${config.services.nextcloud.datadir}/backup-creds";
in {
imports = [ ./caddy.nix ../shell/age.nix ];
options = { options = {
@ -16,22 +9,6 @@ in {
description = "Hostname for Nextcloud"; description = "Hostname for Nextcloud";
}; };
# Options for backup
backupS3 = {
endpoint = lib.mkOption {
type = lib.types.str;
description = "S3 endpoint for backups";
};
bucket = lib.mkOption {
type = lib.types.str;
description = "S3 bucket for backups";
};
accessKeyId = lib.mkOption {
type = lib.types.str;
description = "S3 access key ID for backups";
};
};
}; };
config = { config = {
@ -43,7 +20,7 @@ in {
hostName = "localhost"; hostName = "localhost";
maxUploadSize = "50G"; maxUploadSize = "50G";
config = { config = {
adminpassFile = adminpassFile; adminpassFile = config.secrets.nextcloud.dest;
extraTrustedDomains = [ config.nextcloudServer ]; extraTrustedDomains = [ config.nextcloudServer ];
}; };
}; };
@ -54,6 +31,7 @@ in {
port = 8080; port = 8080;
}]; }];
# Point Caddy to Nginx
caddyRoutes = [{ caddyRoutes = [{
match = [{ host = [ config.nextcloudServer ]; }]; match = [{ host = [ config.nextcloudServer ]; }];
handle = [{ handle = [{
@ -63,22 +41,16 @@ in {
}]; }];
# Create credentials file for nextcloud # Create credentials file for nextcloud
systemd.services.nextcloud-creds = { secrets.nextcloud = {
source = ../../private/nextcloud.age;
dest = "${config.secretsDirectory}/nextcloud";
owner = "nextcloud";
group = "nextcloud";
permissions = "0440";
};
systemd.services.nextcloud-secret = {
requiredBy = [ "nextcloud-setup.service" ]; requiredBy = [ "nextcloud-setup.service" ];
before = [ "nextcloud-setup.service" ]; before = [ "nextcloud-setup.service" ];
serviceConfig = {
Type = "oneshot";
User = "root";
};
script = ''
mkdir --parents $(dirname ${adminpassFile})
${pkgs.age}/bin/age --decrypt \
--identity ${config.identityFile} \
--output ${adminpassFile} \
${builtins.toString ../../private/nextcloud.age}
chown nextcloud:nextcloud ${adminpassFile}
chmod 0700 ${adminpassFile}
'';
}; };
## Backup config ## Backup config
@ -103,30 +75,14 @@ in {
}]; }];
}]; }];
}; };
environmentFile = backupS3File; environmentFile = config.secrets.backup.dest;
}; };
# Don't start litestream unless nextcloud is up # Don't start litestream unless nextcloud is up
systemd.services.litestream = { systemd.services.litestream = {
after = [ "phpfpm-nextcloud.service" ]; after = [ "phpfpm-nextcloud.service" "backup-secret.service" ];
requires = [ "phpfpm-nextcloud.service" ]; requires = [ "phpfpm-nextcloud.service" "backup-secret.service" ];
environment.LITESTREAM_ACCESS_KEY_ID = config.backupS3.accessKeyId; environment.AWS_ACCESS_KEY_ID = config.backupS3.accessKeyId;
};
# Create credentials file for litestream
systemd.services.litestream-s3 = {
requiredBy = [ "litestream.service" ];
before = [ "litestream.service" ];
serviceConfig = { Type = "oneshot"; };
script = ''
echo \
LITESTREAM_SECRET_ACCESS_KEY=$(${pkgs.age}/bin/age --decrypt \
--identity ${config.identityFile} \
${builtins.toString ../../private/backup.age} \
) > ${backupS3File}
chown litestream:litestream ${backupS3File}
chmod 0700 ${backupS3File}
'';
}; };
}; };

View File

@ -13,11 +13,11 @@
default = "/etc/ssh/ssh_host_ed25519_key"; default = "/etc/ssh/ssh_host_ed25519_key";
}; };
# secretsDirectory = lib.mkOption { secretsDirectory = lib.mkOption {
# type = lib.types.str; type = lib.types.str;
# description = "Default path to place secrets."; description = "Default path to place secrets.";
# default = "/var/lib/private"; default = "/var/private";
# }; };
secrets = lib.mkOption { secrets = lib.mkOption {
type = lib.types.attrsOf (lib.types.submodule { type = lib.types.attrsOf (lib.types.submodule {
@ -57,7 +57,7 @@
# Create a default directory to place secrets # Create a default directory to place secrets
# systemd.tmpfiles.rules = [ "d ${config.secretsDirectory} 0750 root wheel" ]; systemd.tmpfiles.rules = [ "d ${config.secretsDirectory} 0755 root wheel" ];
# Declare oneshot service to decrypt secret using SSH host key # Declare oneshot service to decrypt secret using SSH host key
# - Requires that the secret is already encrypted for the host # - Requires that the secret is already encrypted for the host

View File

@ -69,7 +69,7 @@
# Create credentials file for transmission # Create credentials file for transmission
secrets.transmission = { secrets.transmission = {
source = ../../private/transmission.json.age; source = ../../private/transmission.json.age;
dest = "/var/lib/private/transmission.json"; dest = "${config.secretsDirectory}/transmission.json";
owner = "transmission"; owner = "transmission";
group = "transmission"; group = "transmission";
}; };

View File

@ -1,14 +1,6 @@
{ config, pkgs, lib, ... }: { { config, pkgs, lib, ... }: {
options.networking.wireguard = { imports = [ ./secrets.nix ];
encryptedPrivateKey = lib.mkOption {
type = lib.types.path;
description = "Nix path to age-encrypted client private key";
default = ../../private/wireguard.age;
};
};
config = { config = {
@ -19,7 +11,7 @@
# Establishes identity of this machine # Establishes identity of this machine
generatePrivateKeyFile = false; generatePrivateKeyFile = false;
privateKeyFile = "/private/wireguard/wg0"; privateKeyFile = config.secrets.wireguard.dest;
# Move to network namespace for isolating programs # Move to network namespace for isolating programs
interfaceNamespace = "wg"; interfaceNamespace = "wg";
@ -42,25 +34,9 @@
}; };
# Create private key file for wireguard # Create private key file for wireguard
systemd.services.wireguard-private-key = { secrets.wireguard = {
wantedBy = [ "wireguard-wg0.service" ]; source = ../../private/wireguard.age;
requiredBy = [ "wireguard-wg0.service" ]; dest = "${config.secretsDirectory}/wireguard";
before = [ "wireguard-wg0.service" ];
serviceConfig = { Type = "oneshot"; };
script = let
encryptedPrivateKey = config.networking.wireguard.encryptedPrivateKey;
privateKeyFile =
config.networking.wireguard.interfaces.wg0.privateKeyFile;
in ''
mkdir --parents --mode 0755 ${builtins.dirOf privateKeyFile}
if [ ! -f "${privateKeyFile}" ]; then
${pkgs.age}/bin/age --decrypt \
--identity ${config.identityFile} \
--output ${privateKeyFile} \
${builtins.toString encryptedPrivateKey}
chmod 0700 ${privateKeyFile}
fi
'';
}; };
}; };

View File

@ -1,6 +1,10 @@
age-encryption.org/v1 -----BEGIN AGE ENCRYPTED FILE-----
-> ssh-ed25519 MgHaOw 2y5C1sRq3NZqmfGBiPgMS7qcU5v+70wri5xkXbceaHM YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IE1nSGFPdyBuMUg4
zyd7b+OuVi3rxxUEm+QW/80M80SSKaebOwOioRjnYak TG5Oa1U5WERGOWJibkRZRVJwZGdEZmRsSVBraHdVYTJwbGpNL1VnCjRYaW1nTUR0
--- yZQxxjYYNouD5wnEj+qNjUSrRU01hXvWUuax4C252i8 cjR2NHJ1V1lhRHp4a2VOekVTZVl5Rk5CcG1heHhsR2M5SHMKLT4gc3NoLWVkMjU1
¤à/<2F>2*®ŒM•ûD©ø^ÓœOßÆQ MTkgWXlTVU1RIHhEN3o1NzNTTVIvZG1VcERJQitkRk4vTmtFQk9SVUVJQUVOdVY2
5<¤áÝM18o»3´LÓœZiïùºò¹Ö7ð±9ÆTL<54>ø YWoxM1UKVVVMWTYzKzE4ZjVDWitGNkUvR2U1Z1VJdVdqOWhWZVAxNWFOaFZvZGpS
OAotLS0gWlU2TEY0TFZiM3VCM0hWcDAvQlQzTjE3MkZSOGNXaUhDdVQzL2pVRzlT
VQoP0xMzUx0ozRvXFrNfFNyqwzUoHl7GM1P6VFjjDjuMkuWtQ/+V6DV/rGlXDKJ9
jidhm8Y0hbjL6cbQrolUSgHSzG5CPD/4pb3zmxTZ9ol7cQuR4PbnPQ==
-----END AGE ENCRYPTED FILE-----

View File

@ -1,5 +1,10 @@
age-encryption.org/v1 -----BEGIN AGE ENCRYPTED FILE-----
-> ssh-ed25519 MgHaOw 8h/ESNjn0gknNXoHM34UobHzPgmRunoP97H+KHOuGQM YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IE1nSGFPdyBIRnEy
qowH+6TlCRECGCscRgKx6kswY+PZezYUD6E+x9e+5pM am1HTXptMmpSTjZQa2hQSUxNUU1rdXlod3U3bVZ0VGxQVlE2WldBClg0K3k5MDZH
--- kFj1JzRdh/D13Uq9aNTzMJIFysEE+kzzthjewOIR2+o NFlPdHI0VnZSZE9DTTNMeDdldUpFQ3V0V0k0RnRIZHFhdzAKLT4gc3NoLWVkMjU1
Ȳ²¸6<EFBFBD>Àï}rCìzó™ð øà ï>&Ä=jW ^W‰l! "}MSÍå8=‰xƒ²÷m =ЇøL MTkgWXlTVU1RIFlxZFpqNU5kNVY2VUk0Um0zZ1d1M2FlRkYvV1BoTEFSNjZ2Vk9I
QTVHM0UKY2gvVU9wckVUNEFwdUwyVFJZUGwxOFFKYm12cUlFTEVrb3IvcXI3TnND
UQotLS0gMHdaajFjV2ozd0g5dWN5YkhiU2NBVWZVSU00aVIzY0VKYjJleVlQTUdX
QQo7rH6kOTRFP43U/qiBOCHx+hBGlaODFRS1CgzkuqfMOq8PM28RsIN+l3sbwjxE
W8chE/A0EChjIDtfYTMgsN3cYg==
-----END AGE ENCRYPTED FILE-----

Binary file not shown.

View File

@ -1,5 +1,10 @@
age-encryption.org/v1 -----BEGIN AGE ENCRYPTED FILE-----
-> ssh-ed25519 MgHaOw lG6VtLpEU/33egpB9WqJiulVdL3K5a2IGjekIu6HtSI YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IE1nSGFPdyBOOXNm
VsAfCbtQuHU9tptKQR4buD3ydwb89aSbUVdEoetU1gc VG5EMHhEU2JLbkYyY1VXdXZJd2VxSEVXUjZaaURnU254QUVzUENzCnhnV21oRFNY
--- kts74pY8NdQh4pTlMT3NTHxU0qnA0txwQKH5FkQCdXA NGpMeXlqdDlYRmltN1cxTlJ3eWFTVElpK0ZBalA3QVFoL2MKLT4gc3NoLWVkMjU1
ø¿SŸÐ8˜A 0<>`0åªýÕ$,1*/H¼íÞå³ÏV ½þñZtWˆ¬<CB86>ÔBC¯[<¬N@cûá™h_QtÀÀ(ÞÈ Â£fz MTkgWXlTVU1RIDk3TVhDVVBjQU5XNjVTbkxKdUNEU25uZXREeEpHcTF4STg4VXR1
V2xzRTQKZTBXZUQrbjIwTDEwOEc3MktpQzBjTzhjS3lTNTJ0TEMyMVBOODQ0N0lt
OAotLS0gODA2L2FpSmxiWDAyM1IvM2Q4U2QrNmRkVjl1bFhURW5sNCtWZ2tiMnZU
YwoC0chavNt+a/AImm/7bNheZIPghrobp9g+ga+UpRWBtM2snpkyFZrBR0qAkw/f
3krp5Rrco7IOlEwWx96UzvAUpKlC7CdVI1MFa76ZUg==
-----END AGE ENCRYPTED FILE-----