firefly-iii-data-importer: init
This commit is contained in:
@@ -54,6 +54,7 @@
|
||||
# ../../services/llama-cpp.nix
|
||||
../../services/trilium.nix
|
||||
../../services/firefly-iii.nix
|
||||
../../services/firefly-iii-data-importer.nix
|
||||
|
||||
../../services/ups.nix
|
||||
|
||||
|
||||
@@ -340,6 +340,15 @@ rec {
|
||||
domain = "firefly.${site_config.domain}";
|
||||
};
|
||||
|
||||
firefly_iii_data_importer = rec {
|
||||
dataDir = services_dir + "/firefly-iii-data-importer";
|
||||
domain = "firefly-import.${site_config.domain}";
|
||||
# SimpleFIN config json the user uploads after first interactive setup.
|
||||
# `JSON_CONFIGURATION_DIR` defaults to `<storage>/configurations` per the
|
||||
# data-importer module's tmpfiles rules; we reuse that path.
|
||||
simplefinConfigPath = "${dataDir}/storage/configurations/simplefin.json";
|
||||
};
|
||||
|
||||
media = {
|
||||
moviesDir = torrents_path + "/media/movies";
|
||||
tvDir = torrents_path + "/media/tv";
|
||||
|
||||
@@ -199,5 +199,23 @@
|
||||
owner = "firefly-iii";
|
||||
group = "caddy";
|
||||
};
|
||||
|
||||
# Firefly III Data Importer Laravel APP_KEY (base64:<32 random bytes>)
|
||||
firefly-iii-data-importer-app-key = {
|
||||
file = ../secrets/server/firefly-iii-data-importer-app-key.age;
|
||||
mode = "0400";
|
||||
owner = "firefly-iii-data-importer";
|
||||
group = "caddy";
|
||||
};
|
||||
|
||||
# Firefly III Personal Access Token used by the data importer (FIREFLY_III_ACCESS_TOKEN).
|
||||
# First-deploy ciphertext is a placeholder string; rotate after creating
|
||||
# the PAT in the Firefly UI (Profile → OAuth → Personal Access Tokens).
|
||||
firefly-iii-fidi-token = {
|
||||
file = ../secrets/server/firefly-iii-fidi-token.age;
|
||||
mode = "0400";
|
||||
owner = "firefly-iii-data-importer";
|
||||
group = "caddy";
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
Binary file not shown.
BIN
secrets/server/firefly-iii-data-importer-app-key.age
Normal file
BIN
secrets/server/firefly-iii-data-importer-app-key.age
Normal file
Binary file not shown.
BIN
secrets/server/firefly-iii-fidi-token.age
Normal file
BIN
secrets/server/firefly-iii-fidi-token.age
Normal file
Binary file not shown.
128
services/firefly-iii-data-importer.nix
Normal file
128
services/firefly-iii-data-importer.nix
Normal file
@@ -0,0 +1,128 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
service_configs,
|
||||
...
|
||||
}:
|
||||
let
|
||||
fidi = service_configs.firefly_iii_data_importer;
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
# Same chicanery as services/firefly-iii.nix: the upstream module's
|
||||
# actual systemd units are firefly-iii-data-importer-setup.service and
|
||||
# phpfpm-firefly-iii-data-importer.service. Hook the zfs mount into the
|
||||
# `-setup` unit; the upstream `requiredBy` chain pulls phpfpm forward.
|
||||
(lib.serviceMountWithZpool "firefly-iii-data-importer-setup" service_configs.zpool_ssds [
|
||||
fidi.dataDir
|
||||
])
|
||||
];
|
||||
|
||||
services.firefly-iii-data-importer = {
|
||||
enable = true;
|
||||
dataDir = fidi.dataDir;
|
||||
# Same trick as firefly-iii: run as group caddy so caddy can read the
|
||||
# php-fpm unix socket without us having to override `listen.group`.
|
||||
group = "caddy";
|
||||
virtualHost = fidi.domain;
|
||||
settings = {
|
||||
APP_ENV = "production";
|
||||
APP_KEY_FILE = config.age.secrets.firefly-iii-data-importer-app-key.path;
|
||||
LOG_CHANNEL = "syslog";
|
||||
LOG_LEVEL = "info";
|
||||
|
||||
# Importer → Firefly III. The /etc/hosts override below pins this hostname
|
||||
# to 127.0.0.1 on muffin so the importer's outbound HTTPS lands on the
|
||||
# local Caddy without hairpinning through the WAN gateway. The TLS cert
|
||||
# is the same wildcard Caddy serves externally, so verification works.
|
||||
FIREFLY_III_URL = "https://${service_configs.firefly_iii.domain}";
|
||||
FIREFLY_III_ACCESS_TOKEN_FILE = config.age.secrets.firefly-iii-fidi-token.path;
|
||||
|
||||
TRUSTED_PROXIES = "127.0.0.1,::1";
|
||||
|
||||
# SimpleFIN polls the last 90d every run; without this, every daily run
|
||||
# logs hundreds of "duplicate transaction" warnings as Firefly's server-
|
||||
# side dedup catches them. Firefly still rejects the duplicates; we just
|
||||
# don't see the noise.
|
||||
IGNORE_DUPLICATE_ERRORS = true;
|
||||
|
||||
# CLI-driven imports only. Leave the /autoimport HTTP endpoint disabled
|
||||
# (default) — the systemd timer below uses `artisan importer:import`
|
||||
# against a static config file, which avoids exposing another web-
|
||||
# reachable surface that needs its own shared secret.
|
||||
CAN_POST_AUTOIMPORT = false;
|
||||
CAN_POST_FILES = false;
|
||||
};
|
||||
};
|
||||
|
||||
# Pin the firefly-iii hostname to loopback on muffin so the importer's
|
||||
# outbound API calls hit local Caddy directly. No effect on any other host.
|
||||
networking.extraHosts = "127.0.0.1 ${service_configs.firefly_iii.domain}";
|
||||
|
||||
services.caddy.virtualHosts.${fidi.domain}.extraConfig = ''
|
||||
encode zstd gzip
|
||||
import ${config.age.secrets.caddy_auth.path}
|
||||
|
||||
root * ${config.services.firefly-iii-data-importer.package}/public
|
||||
php_fastcgi unix/${config.services.phpfpm.pools.firefly-iii-data-importer.socket}
|
||||
file_server
|
||||
'';
|
||||
|
||||
# Daily SimpleFIN import via the importer's CLI. The unit is gated by
|
||||
# ConditionPathExists so it silently no-ops until the user has uploaded
|
||||
# `simplefin.json` (per the post-deploy operational steps).
|
||||
systemd.services.firefly-iii-data-importer-import = {
|
||||
description = "Run scheduled Firefly III data importer config (SimpleFIN)";
|
||||
after = [
|
||||
"phpfpm-firefly-iii-data-importer.service"
|
||||
"network-online.target"
|
||||
];
|
||||
wants = [ "network-online.target" ];
|
||||
unitConfig.ConditionPathExists = fidi.simplefinConfigPath;
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
User = config.services.firefly-iii-data-importer.user;
|
||||
Group = config.services.firefly-iii-data-importer.group;
|
||||
WorkingDirectory = config.services.firefly-iii-data-importer.package;
|
||||
ExecStart = "${config.services.firefly-iii-data-importer.package}/artisan importer:import ${fidi.simplefinConfigPath}";
|
||||
# Same hardening posture as the upstream commonServiceConfig.
|
||||
ReadWritePaths = [ fidi.dataDir ];
|
||||
PrivateTmp = true;
|
||||
PrivateDevices = true;
|
||||
ProtectSystem = "strict";
|
||||
ProtectHome = "tmpfs";
|
||||
ProtectKernelTunables = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectKernelLogs = true;
|
||||
ProtectControlGroups = true;
|
||||
ProtectClock = true;
|
||||
ProtectHostname = true;
|
||||
ProtectProc = "invisible";
|
||||
ProcSubset = "pid";
|
||||
RestrictAddressFamilies = "AF_INET AF_INET6 AF_UNIX";
|
||||
RestrictNamespaces = true;
|
||||
RestrictRealtime = true;
|
||||
RestrictSUIDSGID = true;
|
||||
LockPersonality = true;
|
||||
NoNewPrivileges = true;
|
||||
RemoveIPC = true;
|
||||
CapabilityBoundingSet = "";
|
||||
AmbientCapabilities = "";
|
||||
SystemCallArchitectures = "native";
|
||||
SystemCallFilter = [
|
||||
"@system-service @resources"
|
||||
"~@obsolete @privileged"
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
systemd.timers.firefly-iii-data-importer-import = {
|
||||
description = "Daily Firefly III SimpleFIN import";
|
||||
wantedBy = [ "timers.target" ];
|
||||
timerConfig = {
|
||||
OnCalendar = "daily";
|
||||
RandomizedDelaySec = "1h";
|
||||
Persistent = true;
|
||||
};
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user