From 00473ef07a3cdfb38439e7aecb22c86027474ad5 Mon Sep 17 00:00:00 2001 From: teidesu Date: Sat, 7 Dec 2024 06:52:47 +0300 Subject: [PATCH] chore(koi): ecryptfs -> gocryptfs --- hosts/koi/containers/navidrome/default.nix | 2 +- hosts/koi/containers/sftpgo/default.nix | 2 +- hosts/koi/containers/soulseek/default.nix | 2 +- hosts/koi/services/geesefs.nix | 12 +- services/ecryptfs.nix | 122 --------------------- services/gocryptfs.nix | 84 ++++++++++++++ 6 files changed, 93 insertions(+), 131 deletions(-) delete mode 100644 services/ecryptfs.nix create mode 100644 services/gocryptfs.nix diff --git a/hosts/koi/containers/navidrome/default.nix b/hosts/koi/containers/navidrome/default.nix index d80989d..9b5ab25 100644 --- a/hosts/koi/containers/navidrome/default.nix +++ b/hosts/koi/containers/navidrome/default.nix @@ -37,7 +37,7 @@ in { "--group-add=${builtins.toString config.users.groups.geesefs.gid}" ]; }; - systemd.services.docker-navidrome.requires = [ "ecryptfs.service" ]; + systemd.services.docker-navidrome.requires = [ "gocryptfs.service" ]; systemd.tmpfiles.rules = [ "d /srv/navidrome 0755 ${builtins.toString UID} ${builtins.toString UID} -" diff --git a/hosts/koi/containers/sftpgo/default.nix b/hosts/koi/containers/sftpgo/default.nix index 16c3c1f..65031d8 100644 --- a/hosts/koi/containers/sftpgo/default.nix +++ b/hosts/koi/containers/sftpgo/default.nix @@ -51,7 +51,7 @@ in { "${builtins.toString WEBDAV_PORT}:80" ]; }; - systemd.services.docker-sftpgo.requires = [ "ecryptfs.service" ]; + systemd.services.docker-sftpgo.requires = [ "gocryptfs.service" ]; systemd.tmpfiles.rules = [ "d /srv/sftpgo/data 0700 ${builtins.toString UID} ${builtins.toString UID} -" diff --git a/hosts/koi/containers/soulseek/default.nix b/hosts/koi/containers/soulseek/default.nix index 0b7e179..4c5eb8a 100644 --- a/hosts/koi/containers/soulseek/default.nix +++ b/hosts/koi/containers/soulseek/default.nix @@ -9,7 +9,7 @@ in { extraGroups = [ "geesefs" ]; }; - systemd.services.docker-slskd.requires = [ "ecryptfs.service" ]; + systemd.services.docker-slskd.requires = [ "gocryptfs.service" ]; virtualisation.oci-containers.containers.slskd = { image = "slskd/slskd:0.21.4.65534-9a68c184"; volumes = [ diff --git a/hosts/koi/services/geesefs.nix b/hosts/koi/services/geesefs.nix index 5877003..09dfd32 100644 --- a/hosts/koi/services/geesefs.nix +++ b/hosts/koi/services/geesefs.nix @@ -3,7 +3,7 @@ { imports = [ (abs "services/geesefs.nix") - (abs "services/ecryptfs.nix") + (abs "services/gocryptfs.nix") ]; desu.secrets.geesefs-credentials = {}; @@ -40,12 +40,12 @@ mountPoint = "/mnt/s3-desu-priv"; }; - services.ecryptfs = { + services.gocryptfs = { enable = true; - cipherDir = "/mnt/s3-desu-priv/encrypted"; - passphrasePath = config.desu.secrets.desu-priv-passphrase.path; - masterKeyPath = "/mnt/s3-desu-priv/encrypted.key"; + cipherDir = "/mnt/s3-desu-priv/encrypted-go"; mountPoint = "/mnt/s3-desu-priv-encrypted"; + passwordFile = config.desu.secrets.desu-priv-passphrase.path; + extraOptions = [ "-allow_other" ]; }; - systemd.services.ecryptfs-setup.requires = [ "geesefs.service" ]; + systemd.services.gocryptfs.requires = [ "geesefs.service" ]; } \ No newline at end of file diff --git a/services/ecryptfs.nix b/services/ecryptfs.nix deleted file mode 100644 index e6ac4f1..0000000 --- a/services/ecryptfs.nix +++ /dev/null @@ -1,122 +0,0 @@ -{ config, lib, pkgs, ... }: - -{ - # todo: ideally we should support multiple encrypted directories - options.services.ecryptfs = with lib; { - enable = mkEnableOption "ecryptfs"; - package = mkOption { - type = types.package; - default = pkgs.ecryptfs; - defaultText = "pkgs.ecryptfs"; - description = "ecryptfs package"; - }; - serviceName = mkOption { - type = types.str; - default = "ecryptfs"; - description = "ecryptfs service name"; - }; - - cipherDir = mkOption { - type = types.str; - description = "path to the directory used as the underlying encrypted storage"; - }; - - passphrasePath = mkOption { - type = types.str; - description = "path to the file containing the passphrase (this can be rotated down the line without needing to re-encrypt the data)"; - }; - - masterKeyPath = mkOption { - type = types.str; - description = "path to the master key (i.e. the wrapped passphrase file)"; - }; - - mountPoint = mkOption { - type = types.str; - description = "ecryptfs mount point"; - }; - - encryptFilenames = mkOption { - type = types.bool; - default = true; - description = "whether to encrypt filenames"; - }; - - encryptionKeySize = mkOption { - type = types.int; - default = 32; - description = "size of the encryption key in bytes"; - }; - - extraOptions = mkOption { - type = types.listOf types.str; - default = [ ]; - description = "additional options to pass to ecryptfs"; - }; - }; - - config = let - cfg = config.services.ecryptfs; - - mountOptions = - [ - "ecryptfs_sig=$sig" - "ecryptfs_key_bytes=${toString cfg.encryptionKeySize}" - "ecryptfs_cipher=aes" - "ecryptfs_unlink_sigs" - "no_sig_cache" - ] ++ - (lib.optional cfg.encryptFilenames "ecryptfs_fnek_sig=$sig") ++ - cfg.extraOptions; - in { - systemd.services.${cfg.serviceName} = { - description = "${cfg.serviceName} setup"; - wantedBy = [ "multi-user.target" ]; - path = [ cfg.package pkgs.keyutils ]; - serviceConfig = { - User = "root"; - Group = "root"; - Type = "oneshot"; - RemainAfterExit = true; - ExecStop = "${pkgs.utillinux}/bin/umount ${lib.escapeShellArg cfg.mountPoint}"; - }; - script = '' - set -euo pipefail - if [ ! -f ${lib.escapeShellArg cfg.masterKeyPath} ]; then - echo "master key file ${cfg.masterKeyPath} does not exist, generating..." - passphrase=$(${pkgs.coreutils}/bin/head -c 48 /dev/random | base64) - wrapping_passphrase=$(cat ${lib.escapeShellArg cfg.passphrasePath}) - printf "%s\n%s" "$passphrase" "$wrapping_passphrase" | ecryptfs-wrap-passphrase ${lib.escapeShellArg cfg.masterKeyPath} - - fi - - if [ ! -d ${lib.escapeShellArg cfg.cipherDir} ]; then - echo "ecryptfs: directory ${lib.escapeShellArg cfg.cipherDir} does not exist" - exit 1 - fi - - if [ ! -d ${lib.escapeShellArg cfg.mountPoint} ]; then - mkdir -p ${lib.escapeShellArg cfg.mountPoint} - fi - - result=$(cat ${lib.escapeShellArg cfg.passphrasePath} | ecryptfs-insert-wrapped-passphrase-into-keyring ${lib.escapeShellArg cfg.masterKeyPath} -) - sig=$(echo "$result" | sed -r 's/^.*sig \[(.*)\] into.*$/\1/') - - if [ -z "$sig" ]; then - echo "failed to extract signature" - echo "$result" - exit 1 - fi - - echo "Keyring signature: $sig" - - if ! keyctl show | grep -q "_uid.0"; then - # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=870126 - # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=870335 - keyctl link @u @s - fi - - ${pkgs.utillinux}/bin/mount -i -t ecryptfs ${lib.escapeShellArg cfg.cipherDir} ${lib.escapeShellArg cfg.mountPoint} -o "${lib.concatStringsSep "," mountOptions}" - ''; - }; - }; -} \ No newline at end of file diff --git a/services/gocryptfs.nix b/services/gocryptfs.nix new file mode 100644 index 0000000..ef88415 --- /dev/null +++ b/services/gocryptfs.nix @@ -0,0 +1,84 @@ +{ config, lib, pkgs, ... }: + +{ + # todo: ideally we should support multiple encrypted directories + options.services.gocryptfs = with lib; { + enable = mkEnableOption "gocryptfs"; + package = mkOption { + type = types.package; + default = pkgs.gocryptfs; + defaultText = "pkgs.gocryptfs"; + description = "gocryptfs package"; + }; + serviceName = mkOption { + type = types.str; + default = "gocryptfs"; + description = "gocryptfs service name"; + }; + + passwordFile = mkOption { + type = types.str; + description = "path to the file containing the password"; + }; + + cipherDir = mkOption { + type = types.str; + description = "path to the directory used as the underlying encrypted storage"; + }; + + mountPoint = mkOption { + type = types.str; + description = "gocryptfs mount point"; + }; + + extraInitOptions = mkOption { + type = types.listOf types.str; + default = [ ]; + description = "additional options to pass to gocryptfs -init"; + }; + + extraOptions = mkOption { + type = types.listOf types.str; + default = [ ]; + description = "additional options to pass to gocryptfs mount"; + }; + }; + + config = let + cfg = config.services.gocryptfs; + in { + systemd.services.${cfg.serviceName} = { + description = "${cfg.serviceName} daemon"; + wantedBy = [ "multi-user.target" ]; + path = [ cfg.package ]; + serviceConfig = { + User = "root"; + Group = "root"; + }; + script = '' + set -euo pipefail + + if [ ! -d ${lib.escapeShellArg cfg.cipherDir} ]; then + echo "gocryptfs: directory ${lib.escapeShellArg cfg.cipherDir} does not exist" + exit 1 + fi + + if [ ! -f ${lib.escapeShellArg cfg.cipherDir}/gocryptfs.conf ]; then + echo "gocryptfs: running gocryptfs -init" + gocryptfs -init \ + -passfile ${lib.escapeShellArg cfg.passwordFile} \ + ${builtins.concatStringsSep " " (map lib.escapeShellArg cfg.extraInitOptions)} \ + ${lib.escapeShellArg cfg.cipherDir} + fi + + if [ ! -d ${lib.escapeShellArg cfg.mountPoint} ]; then + mkdir -p ${lib.escapeShellArg cfg.mountPoint} + fi + + gocryptfs -fg -passfile ${lib.escapeShellArg cfg.passwordFile} \ + ${builtins.concatStringsSep " " (map lib.escapeShellArg cfg.extraOptions)} \ + ${lib.escapeShellArg cfg.cipherDir} ${lib.escapeShellArg cfg.mountPoint} + ''; + }; + }; +} \ No newline at end of file