diff --git a/modules/config/instances/config/firefly-iii.nix b/modules/config/instances/config/firefly-iii.nix new file mode 100644 index 0000000..2b8c1a1 --- /dev/null +++ b/modules/config/instances/config/firefly-iii.nix @@ -0,0 +1,38 @@ +{ moduleFunctions }: +let + inherit (moduleFunctions.instancesFunctions) + domain0 + servicePath + sslPath + sopsPath + ; + + label = "Firefly-III"; + name = "firefly-iii"; + 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/default.nix b/modules/nixos/default.nix index 27be9b5..955d979 100755 --- a/modules/nixos/default.nix +++ b/modules/nixos/default.nix @@ -66,6 +66,7 @@ in searx vaultwarden forgejo + firefly ; }; }; diff --git a/modules/nixos/services/acme/default.nix b/modules/nixos/services/acme/default.nix index 659eff6..be6fedc 100755 --- a/modules/nixos/services/acme/default.nix +++ b/modules/nixos/services/acme/default.nix @@ -41,6 +41,7 @@ in "podgrab" "vaultwarden" "audiobookshelf" + "firefly-iii" ] ) ++ (map diff --git a/modules/nixos/services/firefly/default.nix b/modules/nixos/services/firefly/default.nix new file mode 100644 index 0000000..4dc6940 --- /dev/null +++ b/modules/nixos/services/firefly/default.nix @@ -0,0 +1,123 @@ +{ flake, config, ... }: +let + inherit (flake.config.people) user0; + inherit (flake.config.people.users.${user0}) email; + inherit (flake.config.services.instances) firefly-iii web; + inherit (flake.config.machines.devices) ceres; + service = firefly-iii; + localhost = web.localhost.address1; + host = service.domains.url0; +in +{ + services = { + firefly-iii = { + enable = true; + virtualHost = host; + enableNginx = true; + settings = { + APP_KEY_FILE = config.sops.secrets."${service.name}-key".path; + SITE_OWNER = email.address0; + DB_DATABASE = "firefly"; + DB_USERNAME = "firefly"; + DB_PASSWORD_FILE = config.sops.secrets."${service.name}-pass".path; + TRUSTED_PROXIES = "**"; + }; + }; + + nginx = { + enable = true; + virtualHosts.${config.services.firefly-iii.virtualHost} = { + listen = [ + { + addr = "0.0.0.0"; + port = 8080; + } + ]; + }; + }; + + caddy = { + virtualHosts = { + "${host}" = { + extraConfig = '' + encode gzip + + reverse_proxy localhost:8080 { + header_up Host {host} + header_up X-Real-IP {remote_host} + header_up X-Forwarded-For {remote_host} + header_up X-Forwarded-Proto https + header_up X-Forwarded-Host {host} + header_up X-Forwarded-Ssl on + header_up Connection "" + timeout 240s + dial_timeout 240s + } + + @session_cookie header Cookie *session* + handle @session_cookie { + header Cache-Control "no-cache, no-store, must-revalidate" + } + + request_body { + max_size 64MB + } + + 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 + # ]; + # }; + + users.users.${service.name}.extraGroups = [ + "caddy" + ]; + + systemd.tmpfiles.rules = [ + # "Z ${service.paths.path0} 755 ${service.name} ${service.name} -" + "Z ${service.sops.path0} 755 ${service.name} ${service.name} -" + ]; + + networking = { + firewall = { + allowedTCPPorts = [ + 8080 + service.ports.port0 + ]; + }; + }; +} diff --git a/secrets/secrets.yaml b/secrets/secrets.yaml index 8b2a778..43f3976 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-iii-key: ENC[AES256_GCM,data:tLJfwB8De1vdGeccr4SxifU7KYAfnasoXISvz5mSR28=,iv:vknG+h2D04lECHE/PPA53aZqWk4ouYcH+WfP7WooPYU=,tag:HKma2cydw58pAnvOFH53fA==,type:str] +firefly-iii-pass: ENC[AES256_GCM,data:eJwIM4YHnXTqTOUfU/0CKMSS534VEZIxkBviI1pd7R4=,iv:pUv8ok5nLDGeCcP2hsTculk+MPPAjkupidQO0Jkc3Wc=,tag:zq7+lFjdOr5ORpthqXW8EA==,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-27T07:07:16Z" + mac: ENC[AES256_GCM,data:yNS+bjiHnrHHmmMkChrF5PmxrYAY9HEEErhScsxTNS2OIpiK3Q+ARiTfmT01vmqFBu63RtYJFPQ3gXM1iNrqjQcnp0btXPo2uvLewbHqfj6UaQsj34GXzf9dIzeHAnXWxtlJxkrCA1ufVwW78bzlDt0x64DhboWk5pqlDUaGR6Y=,iv:oEZzK7RBxIK/DbV3wvbL4UYB59PBygGFV3uktHtjVjg=,tag:Lldass5AJL3Ka1bniaxECg==,type:str] unencrypted_suffix: _unencrypted version: 3.10.2