Random-write SQLite traffic fragments CoW filesystems quickly. The `h`
tmpfiles directive sets +C on the database directory; new SQLite files
(WAL, SHM, recreated main DB) inherit no-CoW automatically. No-op on
non-btrfs filesystems.
Migration of existing files must be done manually with checkpoint-first:
systemctl stop phpfpm-firefly-iii.service
sqlite3 .../database.sqlite 'PRAGMA wal_checkpoint(TRUNCATE);'
# then recreate main file inside the +C dir
systemctl start phpfpm-firefly-iii.service
Skipping the wal_checkpoint and naively deleting .sqlite-wal will lose
all writes that haven't been checkpointed (PHP-FPM SIGTERM does not
trigger a checkpoint).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
End-to-end verified: aqbanking-cli fetches Sparda Südwest transactions
via FinTS PIN/TAN + SecureGo+, exports CSV using a custom decimal-amount
profile, POSTs to firefly-iii-data-importer's autoupload endpoint, which
creates transactions in Firefly III via API.
Changes vs. previous WIP commit:
- firefly/access_token sops slot for the importer's Firefly III API auth
(FIREFLY_III_ACCESS_TOKEN_FILE — was the missing piece causing 401s
from the API after the autoupload secret authenticated)
- nginx fastcgi_read_timeout=600s on the importer vhost (prevents 504
while PHP-FPM is still processing the batch)
- PHP-FPM max_execution_time=600s + memory_limit=512M on the importer
pool (PHP's stock 30s aborts mid-import for batches > ~50 transactions)
- timer re-enabled, wantedBy=[timers.target]
Caveats baked into a code comment:
- Sparda online-banking PIN must be [A-Za-z0-9] only. aqbanking 6.8.2's
-P pinfile mangles `:`, `+`, `'`, `?`, `@`, `%`, `*`; bank locks the
access (3 soft / 9 hard strikes) on rejected attempts. Same applies
whenever the sops secret is rotated.
- Bulk historical imports beyond the PSD2 90-day window need interactive
SCA approval per ~30-day chunk and cannot run from the timer; the
daily 35-day rolling window stays inside the no-SCA region.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
End-to-end FinTS pipeline against Sparda Südwest is wired up but
disabled — aqbanking 6.8.2's `-P pinfile` flag does not consume the
file content correctly on this build (verified: pinfile bytes match
the manually-typed PIN exactly, yet the bank receives a wrong PIN).
Three rejected attempts locked the access at Sparda; do not re-arm
the timer until the auth path is replaced (likely python-fints).
What works:
- aqbanking config and FinTS dialog (manual PIN entry)
- getaccsepa workaround for HKCAZ "Mussfeld 9160" rejection
- custom CSV profile (decimal amounts + IBAN columns) wired in
- Firefly importer auto-upload settings + sops secret slot
- inbox + profile-symlink tmpfiles
What's broken:
- Headless PIN delivery via aqbanking-cli -P
- Timer left wantedBy=[] so it cannot fire post-deploy
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Lays the groundwork for Sparda-Bank Südwest transaction sync via
direct FinTS (no third-party data proxy). aqbanking-cli in the system
PATH, persistent state at /var/lib/firefly-aqbanking, sops slot for
the online-banking PIN. Initial enrollment must be done interactively
on the host; systemd timer for automated fetches comes in a follow-up.
Share the check script via a parameterized mkDiskCheck function over
{ name, mountPoint, label } and iterate an attrset to emit the boot
and root services plus their daily timers.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Files vanishing during transfer is expected for mail directories
where messages are constantly moved.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Added `blackhole-2ch` to casks and `darktable` to system packages.
- Disabled `wezterm` and kept `direnv` and `alacritty` enabled in tools.
- Improves utility and functionality by refining the configuration.
Replace broken proxy_cache_bypass (was bypassing every request) with
proxy_cache_lock to coalesce concurrent requests for the same path.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Allow TCP ports 80 and 443 in the firewall for HTTP and HTTPS traffic.
- Enable Nginx with ACME integration for automatic SSL certificate management.
- Configure a virtual host with proxy settings and support for WebSocket traffic.
- Rename `attic` database to `atticd` and set `atticd` user as the owner directly.
- Remove redundant `postStart` script for altering database ownership.
- Update `database.url` to match the renamed database.
- Set `libvirtd.enable` to `false` in `default.nix` to align with the current virtualization setup.
- Prevents unnecessary service activation and reduces resource usage.
- Update `psql` command in the `postStart` script to explicitly connect to the `postgres` database before altering ownership of the `attic` database.
- Ensures the command runs without issues in environments with restricted default database access.
- Replace `$PSQL` with `psql` to use the correct PostgreSQL CLI directly.
- Ensures compatibility and prevents potential runtime issues in the systemd service.
- Replace `dhcpcd` with `systemd-networkd` by setting `networking.useDHCP` to `false` and `networking.useNetworkd` to `true`.
- Add a static IPv6 configuration and routes for `enp1s0` in `30-wan`.
- Ensures a more streamlined and customizable network configuration.
- Set `security.sudo.wheelNeedsPassword` to `false` in `default.nix`.
- Simplifies sudo access for users in the wheel group and aligns with system usage patterns.
- Set `networking.dhcpcd.IPv6rs` to `true` in `default.nix` to support IPv6 router solicitation.
- Ensures better compatibility with networks requiring IPv6 RA for configuration.
- Remove the ESP partition configuration in `disko.nix` as it’s unnecessary for legacy BIOS setups.
- Enable GRUB bootloader and disable EFI settings in `default.nix` for compatibility with Hetzner cloud instances.
- Switch disk device from `/dev/vda` to `/dev/sda` for compatibility.
- Add S3 storage configuration with bucket, region, and endpoint.
- Update system state version from `24.05` to `25.11`.
- Remove unused imports and clean up redundant attributes.
Runs on sgx so alerts (via Gmail) still work even if mx is down.
Available at https://status.hoyer.world behind nginx with ACME cert.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add configurable ntfy options (tokenFile, url, topic) to the shared
emailOnFailure module. When tokenFile is set, a ntfy-failure@ template
service is added alongside the existing email notifications. Systems
without ntfy configured are unaffected.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Disk check scripts now send ntfy alerts in addition to email
- New ntfy-failure@ template service notifies on any systemd service failure
- Uses sops-managed token for ntfy authentication
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Self-hosted at ntfy.hoyer.xyz with deny-all default access.
After deploying, create a user with: ntfy user add --role=admin harald
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Temporary upgrade script following the official NixOS procedure.
Run `upgrade-pg-cluster --jobs 4 --link` on the server, then switch
the package to postgresql_16 and remove the script.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The check_root service incorrectly used '/boot Disk Space Alert' as
the email subject instead of '/ Disk Space Alert'. Also merged the
duplicate systemd.services and systemd.timers attribute sets.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Enable ManageSieve in Dovecot (port 4190) and add the managesieve
plugin to Roundcube for managing Sieve filter rules via webmail.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>