Compare commits

...

2 commits

Author SHA1 Message Date
dcf59faaf6
feat: Add fireflyiii 2026-02-24 10:59:48 -06:00
38e851620c
feat: Add redis database 2026-02-24 10:36:42 -06:00
5 changed files with 303 additions and 0 deletions

136
docker-compose.yaml Normal file
View file

@ -0,0 +1,136 @@
networks:
fireflyiii:
services:
fireflyiii-db:
image: "mariadb:10"
container_name: "fireflyiii-db"
restart: always
networks:
- fireflyiii
volumes:
- "/var/lib/fireflyiii/mysql:/var/lib/mysql"
healthcheck:
test: "healthcheck.sh --connect"
interval: 30s
timeout: 1s
retries: 10
environment:
- "MYSQL_ROOT_PASSWORD=${FIREFLY_III_MYSQL_ROOT_PASSWORD}"
- "MYSQL_PASSWORD=${FIREFLY_III_MYSQL_PASSWORD}"
- "MYSQL_DATABASE=${FIREFLY_III_MYSQL_DB}"
- "MYSQL_USER=${FIREFLY_III_MYSQL_USER}"
fireflyiii:
image: fireflyiii/core:version-6
container_name: "fireflyiii"
restart: always
networks:
- web
- fireflyiii
- redis
volumes:
- "/var/fireflyiii:/var/www/html/storage/upload"
depends_on:
fireflyiii-db:
condition: service_healthy
redis:
condition: service_healthy
labels:
- "traefik.enable=true"
- "traefik.docker.network=traefik_proxy"
- "traefik.http.routers.fireflyiii.rule=Host(`money.millironx.com`)"
- "traefik.http.routers.fireflyiii.tls=true"
- "traefik.http.routers.fireflyiii.tls.certresolver=letsencrypt"
- "traefik.http.services.fireflyiii.loadbalancer.server.port=8080"
environment:
- APP_ENV=local
- SITE_OWNER=${ADMIN_EMAIL}
- APP_KEY=${FIREFLY_III_APP_KEY}
- DEFAULT_LANGUAGE=en_US
- TZ=America/New_York
- TRUSTED_PROXIES=*
- DB_CONNECTION=mysql
- DB_HOST=fireflyiii-db
- DB_PORT=3306
- DB_DATABASE=${FIREFLY_III_MYSQL_DB}
- DB_USERNAME=${FIREFLY_III_MYSQL_USER}
- DB_PASSWORD=${FIREFLY_III_MYSQL_PASSWORD}
- CACHE_DRIVER=redis
- SESSION_DRIER=redis
- REDIS_SCHEME=tcp
- REDIS_HOST=redis
- REDIS_PORT=6379
- REDIS_USERNAME=''
- REDIS_PASSWORD=${REDIS_PASSWORD}
- REDIS_DB="0"
- REDIS_CACHE_DB="1"
- MAIL_MAILER=smtp
- MAIL_HOST=${NOREPLY_EMAIL_HOST}
- MAIL_PORT=${NOREPLY_EMAIL_PORT}
- MAIL_FROM=${NOREPLY_EMAIL}
- MAIL_USERNAME=${NOREPLY_EMAIL_USERNAME}
- MAIL_PASSWORD=${NOREPLY_EMAIL_PASSWORD}
- MAIL_ENCRYPTION=ssl
- APP_URL=https://money.millironx.com
- APP_LOG_LEVEL=debug
- STATIC_CRON_TOKEN=${FIREFLY_III_CRON_TOKEN}
fireflyiii-importer:
image: fireflyiii/data-importer:version-1.5
container_name: "fireflyiii-importer"
restart: always
networks:
- fireflyiii
- redis
- web
depends_on:
- fireflyiii
- redis
labels:
- "traefik.enable=true"
- "traefik.docker.network=traefik_proxy"
- "traefik.http.routers.fireflyiiiimport.rule=Host(`moneyimport.millironx.com`)"
- "traefik.http.routers.fireflyiiiimport.tls=true"
- "traefik.http.services.fireflyiiiimport.loadbalancer.server.port=8080"
environment:
FIREFLY_III_URL: http://fireflyiii:8080
VANITY_URL: https://money.millironx.com
FIREFLY_III_ACCESS_TOKEN: ${FIREFLY_III_IMPORT_TOKEN}
AUTO_IMPORT_SECRET: ${FIREFLY_III_IMPORT_SECRET}
TRUSTED_PROXIES: "*"
TZ: America/New_York
MAIL_MAILER: smtp
MAIL_HOST: ${NOREPLY_EMAIL_HOST}
MAIL_PORT: ${NOREPLY_EMAIL_PORT}
MAIL_FROM: ${NOREPLY_EMAIL}
MAIL_USERNAME: ${NOREPLY_EMAIL_USERNAME}
MAIL_PASSWORD: ${NOREPLY_EMAIL_PASSWORD}
MAIL_ENCRYPTION: ssl
CACHE_DRIVER: redis
SESSION_DRIER: redis
REDIS_SCHEME: tcp
REDIS_HOST: redis
REDIS_PORT: 6379
REDIS_USERNAME: ""
REDIS_PASSWORD: ${REDIS_PASSWORD}
REDIS_DB: "0"
REDIS_CACHE_DB: "1"
fireflyiii-cron:
image: alpine:latest
container_name: "fireflyiii-cron"
restart: always
networks:
- fireflyiii
depends_on:
- fireflyiii
command: sh -c "
apk add tzdata
&& ln -s /usr/share/zoneinfo/$${TZ} /etc/localtime
| echo \"0 3 * * * wget -qO- http://fireflyiii:8080/api/v1/cron/$${CRON_TOKEN};echo\"
| crontab -
&& crond -f -L /dev/stdout"
environment:
TZ: America/New_York
CRON_TOKEN: ${FIREFLY_III_CRON_TOKEN}

View file

@ -34,6 +34,8 @@ in {
++ [ mcentire-host ]; ++ [ mcentire-host ];
"secrets/darwin-policies-json.age".publicKeys = system-administrators "secrets/darwin-policies-json.age".publicKeys = system-administrators
++ [ corianne-host ]; ++ [ corianne-host ];
"secrets/fireflyiii.toml.age".publicKeys = system-administrators
++ [ mcentire-host ];
"secrets/freshrss.toml.age".publicKeys = system-administrators "secrets/freshrss.toml.age".publicKeys = system-administrators
++ [ mcentire-host ]; ++ [ mcentire-host ];
"secrets/millironx-books-s3.age".publicKeys = system-administrators "secrets/millironx-books-s3.age".publicKeys = system-administrators

BIN
secrets/fireflyiii.toml.age Normal file

Binary file not shown.

162
services/fireflyiii.nix Normal file
View file

@ -0,0 +1,162 @@
{ config, pkgs, home-manager-quadlet-nix, ... }:
let
user = "fireflyiii";
port = "34733";
containerPort = "8080";
authentikPort = "9000";
stateDirectory = "/var/lib/${user}";
servicePaths = [ "upload" ];
databasePaths = [ "database" ];
in {
age.secrets."fireflyiii.toml" = {
file = ./../secrets/fireflyiii.toml.age;
owner = user;
};
millironx.podman-secrets.fireflyiii = {
inherit user;
secrets-files = [ config.age.secrets."fireflyiii.toml".path ];
};
systemd.tmpfiles.rules =
map (d: "d ${stateDirectory}/${d} 1775 ${user} ${user} -") [ "" ]
++ servicePaths ++ databasePaths;
services.borgmatic.configurations."${config.networking.hostName}" = {
source_directories = map (d: "${stateDirectory}/${d}") servicePaths;
postgresql_databases = [{
name = user;
psql_command =
"/run/wrappers/bin/sudo -iu ${user} ${pkgs.podman}/bin/podman exec ${user}-db psql --username=${user}";
pg_dump_command =
"/run/wrappers/bin/sudo -iu ${user} ${pkgs.podman}/bin/podman exec ${user}-db pg_dump --username=${user}";
pg_restore_command =
"/run/wrappers/bin/sudo -iu ${user} ${pkgs.podman}/bin/podman exec ${user}-db pg_restore --username=${user}";
}];
};
services.caddy.virtualHosts."money.millironx.com".extraConfig = ''
reverse_proxy /outpost.goauthentik.io/* http://127.0.0.1:${authentikPort}
forward_auth http://127.0.0.1:${authentikPort} {
uri /outpost.goauthentik.io/auth/caddy
copy_headers X-Authentik-Username X-Authentik-Groups X-Authentik-Entitlements X-Authentik-Email X-Authentik-Name X-Authentik-Uid X-Authentik-Jwt X-Authentik-Meta-Jwks X-Authentik-Meta-Outpost X-Authentik-Meta-Provider X-Authentik-Meta-App X-Authentik-Meta-Version
}
reverse_proxy http://127.0.0.1:${port}
'';
users.users."${user}" = {
group = user;
isNormalUser = true;
home = stateDirectory;
createHome = true;
linger = true;
autoSubUidGidRange = true;
};
users.groups."${user}" = { };
home-manager.users."${user}" = { config, osConfig, ... }: {
imports = [ home-manager-quadlet-nix ];
home.stateVersion = "25.05";
systemd.user = let inherit (config.virtualisation.quadlet) containers;
in {
services."${user}-cron" = {
Unit = {
Description = "Firefly III cron";
Requires = [ containers."${user}".ref ];
After = [ containers."${user}".ref ];
};
Service.ExecStart =
"${pkgs.podman}/bin/podman exec ${user} /usr/local/bin/php /var/www/html/artisan firefly-iii:cron";
};
timers."${user}-cron" = {
Unit.Description = "Firefly III cron";
Timer.OnCalendar = "daily";
};
};
virtualisation.quadlet = let
inherit (config.virtualisation.quadlet) containers;
inherit (config.virtualisation.quadlet) networks;
secrets = osConfig.millironx.podman-secrets.freshrss;
in {
autoUpdate.enable = true;
autoEscape = true;
networks."${user}" = { };
containers = {
"${user}-db" = {
autoStart = true;
containerConfig = {
image = "docker.io/library/postgres:16";
environments = {
POSTGRES_DB = user;
POSTGRES_USER = user;
};
secrets = [
"POSTGRES_PASSWORD,type=env"
"POSTGRES_PASSWORD,type=env,target=PGPASSWORD"
];
healthCmd = "pg_isready -d $\${POSTGRES_DB} -U $\${POSTGRES_USER}";
healthInterval = "30s";
healthRetries = 5;
healthStartPeriod = "20s";
volumes =
[ "${stateDirectory}/database:/var/lib/postgresql/data:U" ];
networks = [ networks."${user}".ref ];
};
unitConfig.Requires = [ secrets.ref ];
unitConfig.After = [ secrets.ref ];
};
"${user}" = {
autoStart = true;
containerConfig = {
image = "docker.io/fireflyiii/core:version-6";
environments = {
APP_ENV = "local";
DEFAULT_LANGUAGE = "en_US";
TZ = "America/New_York";
TRUSTED_PROXIES = "*";
DB_CONNECTION = "pgsql";
DB_HOST = "${user}-db";
DB_PORT = "5432";
DB_DATABASE = user;
DB_USERNAME = user;
CACHE_DRIVER = "redis";
SESSION_DRIVER = "redis";
REDIS_SCHEME = "tcp";
REDIS_HOST = "host.docker.internal";
REDIS_PORT = "6379";
REDIS_DB = "0";
REDIS_CACHE_DB = "1";
MAIL_MAILER = "smtp";
APP_URL = "https://money.millironx.com";
AUTHENTICATION_GUARD = "remote_user_guard";
AUTHENTICATION_GUARD_HEADER = "HTTP_X_AUTHENTIK_USERNAME";
AUTHENTICATION_GUARD_EMAIL = "HTTP_X_AUTHENTIK_EMAIL";
};
secrets = map (s: "${s},type=env") [
"SITE_OWNER"
"APP_KEY"
"DB_PASSWORD"
"MAIL_HOST"
"MAIL_PORT"
"MAIL_FROM"
"MAIL_USERNAME"
"MAIL_PASSWORD"
"MAIL_ENCRYPTION"
];
volumes = [ "${stateDirectory}/upload:/var/html/storage/upload:U" ];
networks = [ networks."${user}".ref ];
publishPorts = [ "127.0.0.1:${port}:${containerPort}" ];
};
unitConfig.Requires = [ secrets.ref containers."${user}".ref ];
unitConfig.After = [ secrets.ref containers."${user}".ref ];
};
};
};
};
}

View file

@ -8,6 +8,7 @@
./../../services/crowdsec.nix ./../../services/crowdsec.nix
./../../services/authentik.nix ./../../services/authentik.nix
./../../services/audiobookshelf.nix ./../../services/audiobookshelf.nix
./../../services/fireflyiii.nix
./../../services/freshrss.nix ./../../services/freshrss.nix
./../../services/navidrome.nix ./../../services/navidrome.nix
]; ];
@ -65,6 +66,8 @@
# Do not "enable" database services, but include the package configuration # Do not "enable" database services, but include the package configuration
# so that borgmatic does not freak out about unset variables # so that borgmatic does not freak out about unset variables
postgresql.package = pkgs.postgresql_17; postgresql.package = pkgs.postgresql_17;
redis.servers.redis.enable = true;
}; };
virtualisation.quadlet.enable = true; virtualisation.quadlet.enable = true;