Firefly-iii Service

Table of Contents

Usage
Database Inspection
Mobile Apps
Options Reference

Defined in /modules/services/firefly-iii.nix.

This NixOS module is a service that sets up a Firefly-iii instance.

Compared to the stock module from nixpkgs, this one sets up, in a fully declarative manner, LDAP and SSO integration and has a nicer option for secrets. It also sets up the Firefly-iii data importer service and nearly automatically links it to the Firefly-iii instance using a Personal Account Token. Instructions on how to do so is given in the next section.

Usage

The following snippet assumes a few blocks have been setup already:

shb.firefly-iii = {
  enable = true;
  debug = false;

  appKey.result = config.shb.sops.secret."firefly-iii/appKey".result;
  dbPassword.result = config.shb.sops.secret."firefly-iii/dbPassword".result;

  domain = "example.com";
  subdomain = "firefly-iii";
  siteOwnerEmail = "mail@example.com";
  ssl = config.shb.certs.certs.letsencrypt.${domain};

  smtp = {
    host = "smtp.eu.mailgun.org";
    port = 587;
    username = "postmaster@mg.example.com";
    from_address = "firefly-iii@example.com";
    password.result = config.shb.sops.secrets."firefly-iii/smtpPassword".result;
  };

  sso = {
    enable = true;
    authEndpoint = "https://${config.shb.authelia.subdomain}.${config.shb.authelia.domain}";
  };

  importer = {
    # See note hereunder.
    # firefly-iii-accessToken.result = config.shb.sops.secret."firefly-iii/importerAccessToken".result;
  };
};
shb.sops.secret."firefly-iii/appKey".request = config.shb.firefly-iii.appKey.request;
shb.sops.secret."firefly-iii/dbPassword".request = config.shb.firefly-iii.dbPassword.request;
shb.sops.secret."firefly-iii/smtpPassword".request = config.shb.firefly-iii.smtp.password.request;
# See not hereunder.
# shb.sops.secret."firefly-iii/importerAccessToken".request = config.shb.firefly-iii.importer.firefly-iii-accessToken.request;

Secrets can be randomly generated with nix run nixpkgs#openssl -- rand -hex 64. Note that for appKey, the secret length must be exactly 32 characters.

The user and admin LDAP groups are created automatically. Only admin users have access to the Firefly-iii data importer. On the Firefly-iii web UI, the first user to login will be the admin. We cannot yet create multiple admins in the Firefly-iii web UI.

On first start, leave the shb.firefly-iii.importer.firefly-iii-accessToken option empty. To fill it out and connect the data importer to the Firefly-iii instance, you must first create a personal access token then fill that option and redeploy.

Backup

Backing up Firefly-iii using the Restic block is done like so:

shb.restic.instances."firefly-iii" = {
  request = config.shb.firefly-iii.backup;
  settings = {
    enable = true;
  };
};

The name "firefly-iii" in the instances can be anything. The config.shb.firefly-iii.backup option provides what directories to backup. You can define any number of Restic instances to backup Firefly-iii multiple times.

You will then need to configure more options like the repository, as explained in the restic documentation.

Certificates

For Let’s Encrypt certificates, add:

{
  shb.certs.certs.letsencrypt.${domain}.extraDomains = [
    "${config.shb.firefly-iii.subdomain}.${config.shb.firefly-iii.domain}"
    "${config.shb.firefly-iii.importer.subdomain}.${config.shb.firefly-iii.domain}"
  ];
}

Impermanence

To save the data folder in an impermanence setup, add:

{
  shb.zfs.datasets."safe/firefly-iii".path = config.shb.firefly-iii.impermanence;
}

Declarative LDAP

To add a user USERNAME to the user and admin groups for Firefly-iii, add:

shb.lldap.ensureUsers.USERNAME.groups = [
  config.shb.firefly-iii.ldap.userGroup
  config.shb.firefly-iii.ldap.adminGroup
];

Database Inspection

Access the database with:

sudo -u firefly-iii psql

Dump the database with:

sudo -u firefly-iii pg_dump --data-only --inserts firefly-iii > dump

Mobile Apps

This module was tested with the Abacus iOS mobile app using a Personal Account Token.

Options Reference

shb.firefly-iii.enable

Whether to enable SHB’s firefly-iii module.

Type: boolean

Default: false

Example: true

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.appKey

Encryption key used for sessions. Must be 32 characters long exactly.

Type: submodule

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.appKey.request

Request part of the secret contract.

Options set by the requester module enforcing some properties the secret should have.

Type: submodule

Default: { mode = 0400; owner = services.firefly-iii.user; group = root; restartUnits = [ firefly-iii-setup.service ]; }

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.appKey.request.group

Linux group owning the secret file.

Type: string

Default: "root"

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.appKey.request.mode

Mode of the secret file.

Type: string

Default: "0400"

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.appKey.request.owner

Linux user owning the secret file.

Type: string

Default: services.firefly-iii.user

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.appKey.request.restartUnits

Systemd units to restart after the secret is updated.

Type: list of string

Default:

[
  "firefly-iii-setup.service"
]

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.appKey.result

Result part of the secret contract.

Options set by the provider module that indicates where the secret can be found.

Type: submodule

Default:

{
  path = "/run/secrets/secret";
}

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.appKey.result.path

Path to the file containing the secret generated out of band.

This path will exist after deploying to a target host, it is not available through the nix store.

Type: absolute path

Default: "/run/secrets/secret"

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.backup

Backup configuration.

Type: submodule

Default: { }

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.backup.request

Request part of the backup contract.

Options set by the requester module enforcing how to backup files.

Type: submodule

Default: { user = services.firefly-iii.user; sourceDirectories = [ config.services.firefly-iii.dataDir ] ; excludePatterns = [ ]; hooks.beforeBackup = [ ]; hooks.afterBackup = [ ]; };

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.backup.request.excludePatterns

File patterns to exclude.

Type: list of string

Default: [ ]

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.backup.request.hooks

Hooks to run around the backup.

Type: submodule

Default: { }

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.backup.request.hooks.afterBackup

Hooks to run after backup.

Type: list of string

Default: [ ]

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.backup.request.hooks.beforeBackup

Hooks to run before backup.

Type: list of string

Default: [ ]

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.backup.request.sourceDirectories

Directories to backup.

Type: non-empty (list of string)

Default: [ config.services.firefly-iii.dataDir ]

Example: "/var/lib/vaultwarden"

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.backup.request.user

Unix user doing the backups.

Type: string

Default: services.firefly-iii.user

Example: "vaultwarden"

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.backup.result

Result part of the backup contract.

Options set by the provider module that indicates the name of the backup and restore scripts.

Type: submodule

Default: ""

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.backup.result.backupService

Name of service backing up the database.

This script can be ran manually to backup the database:

$ systemctl start backup.service

Type: string

Default: "backup.service"

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.backup.result.restoreScript

Name of script that can restore the database. One can then list snapshots with:

$ restore snapshots

And restore the database with:

$ restore restore latest

Type: string

Default: "restore"

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.dbPassword

DB password.

Type: submodule

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.dbPassword.request

Request part of the secret contract.

Options set by the requester module enforcing some properties the secret should have.

Type: submodule

Default: { mode = 0440; owner = services.firefly-iii.user; group = postgres; restartUnits = [ postgresql.service firefly-iii-setup.service ]; }

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.dbPassword.request.group

Linux group owning the secret file.

Type: string

Default: "postgres"

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.dbPassword.request.mode

Mode of the secret file.

Type: string

Default: "0440"

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.dbPassword.request.owner

Linux user owning the secret file.

Type: string

Default: services.firefly-iii.user

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.dbPassword.request.restartUnits

Systemd units to restart after the secret is updated.

Type: list of string

Default:

[
  "postgresql.service"
  "firefly-iii-setup.service"
]

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.dbPassword.result

Result part of the secret contract.

Options set by the provider module that indicates where the secret can be found.

Type: submodule

Default:

{
  path = "/run/secrets/secret";
}

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.dbPassword.result.path

Path to the file containing the secret generated out of band.

This path will exist after deploying to a target host, it is not available through the nix store.

Type: absolute path

Default: "/run/secrets/secret"

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.debug

Enable more verbose logging.

Type: boolean

Default: false

Example: true

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.domain

Domain under which firefly-iii is served.

<subdomain>.<domain>[:<port>]

Type: string

Example: "domain.com"

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.impermanence

Path to save when using impermanence setup.

Type: string

Default: "services.firefly-iii.dataDir"

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.importer

Configuration for Firefly-iii data importer.

Type: submodule

Default: { }

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.importer.enable

Whether to enable Firefly-iii Data Importer…

Type: boolean

Default: true

Example: true

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.importer.firefly-iii-accessToken

Create a Personal Access Token then set then token in this option.

Type: null or (submodule)

Default: null

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.importer.firefly-iii-accessToken.request

Request part of the secret contract.

Options set by the requester module enforcing some properties the secret should have.

Type: submodule

Default: { mode = 0400; owner = services.firefly-iii-data-importer.user; group = root; restartUnits = [ firefly-iii-data-importer-setup.service ]; }

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.importer.firefly-iii-accessToken.request.group

Linux group owning the secret file.

Type: string

Default: "root"

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.importer.firefly-iii-accessToken.request.mode

Mode of the secret file.

Type: string

Default: "0400"

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.importer.firefly-iii-accessToken.request.owner

Linux user owning the secret file.

Type: string

Default: services.firefly-iii-data-importer.user

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.importer.firefly-iii-accessToken.request.restartUnits

Systemd units to restart after the secret is updated.

Type: list of string

Default:

[
  "firefly-iii-data-importer-setup.service"
]

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.importer.firefly-iii-accessToken.result

Result part of the secret contract.

Options set by the provider module that indicates where the secret can be found.

Type: submodule

Default:

{
  path = "/run/secrets/secret";
}

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.importer.firefly-iii-accessToken.result.path

Path to the file containing the secret generated out of band.

This path will exist after deploying to a target host, it is not available through the nix store.

Type: absolute path

Default: "/run/secrets/secret"

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.importer.subdomain

Subdomain under which the firefly-iii data importer will be served.

Type: string

Default: ${shb.firefly-iii.subdomain}-importer

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.ldap

LDAP Integration

Type: submodule

Default: { }

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.ldap.adminGroup

Group users must belong to to be able to import data user the Firefly-iii data importer.

Type: string

Default: "firefly-iii_admin"

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.ldap.userGroup

Group users must belong to to be able to login to Firefly-iii.

Type: string

Default: "firefly-iii_user"

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.siteOwnerEmail

Email of the site owner.

Type: string

Example: "mail@example.com"

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.smtp

If set, send notifications through smtp.

https://docs.firefly-iii.org/how-to/firefly-iii/advanced/notifications/

Type: null or (submodule)

Default: null

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.smtp.from_address

SMTP address from which the emails originate.

Type: string

Example: "authelia@mydomain.com"

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.smtp.host

SMTP host to send the emails to.

Type: string

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.smtp.password

File containing the password to connect to the SMTP host.

Type: submodule

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.smtp.password.request

Request part of the secret contract.

Options set by the requester module enforcing some properties the secret should have.

Type: submodule

Default: { mode = 0400; owner = services.firefly-iii.user; group = root; restartUnits = [ firefly-iii-setup.service ]; }

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.smtp.password.request.group

Linux group owning the secret file.

Type: string

Default: "root"

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.smtp.password.request.mode

Mode of the secret file.

Type: string

Default: "0400"

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.smtp.password.request.owner

Linux user owning the secret file.

Type: string

Default: services.firefly-iii.user

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.smtp.password.request.restartUnits

Systemd units to restart after the secret is updated.

Type: list of string

Default:

[
  "firefly-iii-setup.service"
]

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.smtp.password.result

Result part of the secret contract.

Options set by the provider module that indicates where the secret can be found.

Type: submodule

Default:

{
  path = "/run/secrets/secret";
}

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.smtp.password.result.path

Path to the file containing the secret generated out of band.

This path will exist after deploying to a target host, it is not available through the nix store.

Type: absolute path

Default: "/run/secrets/secret"

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.smtp.port

SMTP port to send the emails to.

Type: 16 bit unsigned integer; between 0 and 65535 (both inclusive)

Default: 25

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.smtp.username

Username to connect to the SMTP host.

Type: string

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.ssl

Path to SSL files

Type: null or (open submodule of anything)

Default: null

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.ssl.paths

Paths where the files for the certificate will be located.

This option is the contract output of the shb.certs.certs SSL block.

Type: open submodule of anything

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.ssl.paths.cert

Path to the cert file.

Type: absolute path

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.ssl.paths.key

Path to the key file.

Type: absolute path

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.ssl.systemdService

Systemd oneshot service used to generate the certificate. Ends with the .service suffix.

Use this if downstream services must wait for the certificates to be generated before starting.

Type: string

Example: "cert-generator.service"

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.sso

SSO Integration

Type: submodule

Default: { }

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.sso.enable

Whether to enable SSO integration…

Type: boolean

Default: false

Example: true

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.sso.adminGroup

Group admins must belong to to be able to login to Firefly-iii.

Type: string

Default: "firefly-iii_admin"

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.sso.authEndpoint

OIDC endpoint for SSO.

Type: string

Example: "https://authelia.example.com"

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.sso.authorization_policy

Require one factor (password) or two factor (device) authentication.

Type: one of “one_factor”, “two_factor”

Default: "one_factor"

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.sso.clientID

Client ID for the OIDC endpoint.

Type: string

Default: "firefly-iii"

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.sso.port

If given, adds a port to the endpoint.

Type: null or 16 bit unsigned integer; between 0 and 65535 (both inclusive)

Default: null

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.sso.provider

OIDC provider name, used for display.

Type: value “Authelia” (singular enum)

Default: "Authelia"

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.sso.secret

OIDC shared secret.

Type: submodule

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.sso.secret.request

Request part of the secret contract.

Options set by the requester module enforcing some properties the secret should have.

Type: submodule

Default: ""

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.sso.secret.request.group

Linux group owning the secret file.

Type: string

Default: "root"

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.sso.secret.request.mode

Mode of the secret file.

Type: string

Default: "0400"

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.sso.secret.request.owner

Linux user owning the secret file.

Type: string

Default: "firefly-iii"

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.sso.secret.request.restartUnits

Systemd units to restart after the secret is updated.

Type: list of string

Default:

[
  "firefly-iii-setup.service"
]

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.sso.secret.result

Result part of the secret contract.

Options set by the provider module that indicates where the secret can be found.

Type: submodule

Default:

{
  path = "/run/secrets/secret";
}

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.sso.secret.result.path

Path to the file containing the secret generated out of band.

This path will exist after deploying to a target host, it is not available through the nix store.

Type: absolute path

Default: "/run/secrets/secret"

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.sso.secretForAuthelia

OIDC shared secret. Content must be the same as secretFile option.

Type: submodule

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.sso.secretForAuthelia.request

Request part of the secret contract.

Options set by the requester module enforcing some properties the secret should have.

Type: submodule

Default: ""

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.sso.secretForAuthelia.request.group

Linux group owning the secret file.

Type: string

Default: "root"

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.sso.secretForAuthelia.request.mode

Mode of the secret file.

Type: string

Default: "0400"

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.sso.secretForAuthelia.request.owner

Linux user owning the secret file.

Type: string

Default: "authelia"

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.sso.secretForAuthelia.request.restartUnits

Systemd units to restart after the secret is updated.

Type: list of string

Default: [ ]

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.sso.secretForAuthelia.result

Result part of the secret contract.

Options set by the provider module that indicates where the secret can be found.

Type: submodule

Default:

{
  path = "/run/secrets/secret";
}

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.sso.secretForAuthelia.result.path

Path to the file containing the secret generated out of band.

This path will exist after deploying to a target host, it is not available through the nix store.

Type: absolute path

Default: "/run/secrets/secret"

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>
shb.firefly-iii.subdomain

Subdomain under which firefly-iii will be served.

<subdomain>.<domain>

Type: string

Example: "firefly-iii"

Declared by:

<selfhostblocks/modules/services/firefly-iii.nix>