From 981a43b8531fb2535b885e5321d45c41d692be9c Mon Sep 17 00:00:00 2001 From: Nick Date: Fri, 27 Jun 2025 01:37:33 -0500 Subject: [PATCH] feat: firefly-iii test --- modules/config/instances/config/firefly.nix | 38 ++++++++++ modules/nixos/services/acme/default.nix | 1 + modules/nixos/services/firefly/default.nix | 84 +++++++++++++++++++++ secrets/secrets.yaml | 6 +- 4 files changed, 127 insertions(+), 2 deletions(-) create mode 100644 modules/config/instances/config/firefly.nix create mode 100644 modules/nixos/services/firefly/default.nix diff --git a/modules/config/instances/config/firefly.nix b/modules/config/instances/config/firefly.nix new file mode 100644 index 0000000..337bca3 --- /dev/null +++ b/modules/config/instances/config/firefly.nix @@ -0,0 +1,38 @@ +{ moduleFunctions }: +let + inherit (moduleFunctions.instancesFunctions) + domain0 + servicePath + sslPath + sopsPath + ; + + label = "Firefly"; + name = "firefly"; + subdomain = "finances"; + domain = "${subdomain}.${domain0}"; +in +{ + label = label; + name = name; + email = { + address0 = "noreply@${name}.${domain0}"; + }; + sops = { + path0 = "${sopsPath}/${name}"; + }; + domains = { + url0 = domain; + }; + subdomain = subdomain; + paths = { + path0 = "${servicePath}/${label}"; + }; + ports = { + port0 = 3306; + }; + ssl = { + cert = "${sslPath}/${subdomain}.${domain0}/fullchain.pem"; + key = "${sslPath}/${subdomain}.${domain0}/key.pem"; + }; +} diff --git a/modules/nixos/services/acme/default.nix b/modules/nixos/services/acme/default.nix index 659eff6..15d5f4a 100755 --- a/modules/nixos/services/acme/default.nix +++ b/modules/nixos/services/acme/default.nix @@ -41,6 +41,7 @@ in "podgrab" "vaultwarden" "audiobookshelf" + "firefly" ] ) ++ (map diff --git a/modules/nixos/services/firefly/default.nix b/modules/nixos/services/firefly/default.nix new file mode 100644 index 0000000..12887fb --- /dev/null +++ b/modules/nixos/services/firefly/default.nix @@ -0,0 +1,84 @@ +{ flake, config, ... }: +let + inherit (flake.config.people) user0; + inherit (flake.config.services.instances) firefly web; + inherit (flake.config.machines.devices) ceres; + service = firefly; + localhost = web.localhost.address0; + host = service.domains.url0; +in +{ + services = { + firefly-iii = { + enable = true; + virtualHost = host; + settings = { + APP_URL = host; + APP_KEY_FILE = config.sops.secrets."${service.name}-key".path; + SITE_OWNER = user0.email.address0; + # DB_PORT = 3306; + DB_DATABASE = "firefly"; + DB_USERNAME = "firefly"; + DB_PASSWORD_FILE = config.sops.secrets."${service.name}-pass".path; + }; + }; + caddy = { + virtualHosts = { + "${host}" = { + extraConfig = '' + redir /.well-known/carddav /remote.php/dav/ 301 + redir /.well-known/caldav /remote.php/dav/ 301 + + reverse_proxy ${localhost}:${toString service.ports.port0} + + tls ${service.ssl.cert} ${service.ssl.key} + ''; + }; + }; + }; + sops = + let + sopsPath = secret: { + path = "${service.sops.path0}/${service.name}-${secret}"; + owner = service.name; + mode = "600"; + }; + in + { + secrets = builtins.listToAttrs ( + map + (secret: { + name = "${service.name}-${secret}"; + value = sopsPath secret; + }) + [ + "key" + "pass" + ] + ); + }; + }; + fileSystems."/var/lib/${service.name}" = { + device = service.paths.path0; + fsType = "none"; + options = [ + "bind" + ]; + depends = [ + ceres.storage0.mount + ]; + }; + + systemd.tmpfiles.rules = [ + "Z ${service.paths.path0} 755 ${service.name} ${service.name} -" + "Z ${service.sops.path0} 755 ${service.name} ${service.name} -" + ]; + + networking = { + firewall = { + allowedTCPPorts = [ + service.ports.port0 + ]; + }; + }; +} diff --git a/secrets/secrets.yaml b/secrets/secrets.yaml index 8b2a778..5e88889 100755 --- a/secrets/secrets.yaml +++ b/secrets/secrets.yaml @@ -37,6 +37,8 @@ wireguard-CA627: ENC[AES256_GCM,data:chmDsH2nE0nagjFRZWuxX08/Ykt+rIgCHYkMHd+7nIq glance-jellyfin: ENC[AES256_GCM,data:ozdDKgAWkA88J2j8RtiOP/aQPAt/neUOSlAZF20g510=,iv:x+VhYlnA9F/VPrzVcma4/oPelCc8kjWoTZvOs4L9Uqo=,tag:crdSDjr8Y5GH/JAF6t8Yeg==,type:str] kanboard-smtp: ENC[AES256_GCM,data:eOIEGwJZlvbJaTfDRU3IFQ==,iv:Jex01WlHG3uxqUnTSF+v1BgnNcIu4cS9OwHBCFl1m28=,tag:3Eld1FkI6AftlCyC3419BA==,type:str] podgrab-pass: ENC[AES256_GCM,data:DVmJDb4VqcZDKNcedSaRA5dqKOzx1tSzDiK3i23+a6v3nK+4Kh7n8EA=,iv:SiiUjJLHkCOO1VKCmubftKx06laFqNv79tIPnkVYrJU=,tag:kdkT+03DemlNAsuzps8fnw==,type:str] +firefly-key: ENC[AES256_GCM,data:dIigi/MP6L3DwRSH2eJfliG2f1z8i30cM9smDGIJWu4=,iv:OCZJqNHlGgLQ+fGGEkOeYDxBOIouIRenlCpgaUs8d7Q=,tag:/PBkp4FxZHD7D+vYG7O4Iw==,type:str] +firefly-pass: ENC[AES256_GCM,data:HqHm42JyDnGPti7PElfmQNkt72tQdddBfNWJypmDkkc=,iv:A+mmEcOiusxKnwhNKo9ytMteEP60J+ZxGQzJPP5IhEI=,tag:CB/dULemc/rtAxLt3z6BOA==,type:str] sops: age: - recipient: age19dpncsdphdt2tmknjs99eghk527pvdrw0m29qjn2z2gg3et5tdtqycqhl0 @@ -48,7 +50,7 @@ sops: bXBOa1VSakoyaWxpODJEOU11QUZCaUEK8Ch9Ten3DdrPHF1DTH2qei85AlHUOaLD aNfzakake7ej+MxJYdKEU0bcWofNMKzIlZa2uM10KZSENDP8d8qlig== -----END AGE ENCRYPTED FILE----- - lastmodified: "2025-06-25T21:19:21Z" - mac: ENC[AES256_GCM,data:bCdXkiK+gEgdz+MG4Npne7s3PjZL135U4H8vWWxtDoOnCXi+gbKzPMKzwpFkAflfAwWttiswb2I4dfiFFIaEezILmCA5dE48WMZFccyMdCrU30FscQ2x1b41AGrQdiZK4ZwVR7iWSNbcmOJMjIXA8c97Q4ldIInYaSleEt1kvuk=,iv:RNH6cRUOKGfuHaWeNhIsibdpX6ULEtw8KuApTdZb4Vg=,tag:p9CzqXZDxk6hVIL/BK/8Rw==,type:str] + lastmodified: "2025-06-27T06:36:17Z" + mac: ENC[AES256_GCM,data:/v4ok8tjMxMyYIP3P+rZONgkiQUw/cQD/9RyDsXVpfnX8ccTleSS8F/2NO3au0qTFCfD1qO07BvtyTgrBN1Uvdb0v7Pjz3FtWSwWMoT5oJHz2ROKf6GZpApwmJv3W/ruNR+m+Y/1J/T5XhxNp0p7lBYd0i1hpOhBDyos2E3/UWQ=,iv:ETYrtu0SJ4W0hNDn9pOgM7WAAEzMpiHwFN/HG7G8+Zk=,tag:Dyzyd8SQKWkaNVVu0DVfnA==,type:str] unencrypted_suffix: _unencrypted version: 3.10.2