{ lib, config, pkgs, ... }: let cfg = config.services.otf; in { options.services.otf = { enable = lib.mkEnableOption "Open Terraform Framework"; # It is important to expose the datadirectory to the user so we make it a reusable option dataDir = lib.mkOption { type = lib.types.str; default = "/var/lib/otf"; description = "Directory to store OTF data."; }; package = lib.mkPackageOption pkgs "otf" { }; pgPackage = lib.mkPackageOption pkgs "postgresql_16" { }; environmentFile = lib.mkOption { type = with lib.types; nullOr path; default = lib.types.null; }; # this application is configured entirely by environment variables and needs to be exposed environment = lib.mkOption { type = with lib.types; attrsOf ( nullOr (oneOf [ str path package ]) ); default = { OTF_ADDRESS = "localhost:9000"; # OTF_SITE_TOKEN = "my-token"; # OTF_SSL = "false"; # OTF_SECRET = ""; # OTF_CERT_FILE = ""; # OTF_KEY_FILE = ""; }; description = "Environment variables for the OTF service."; }; }; config = lib.mkIf cfg.enable { # it is best for this project to have a dedicated user for database access users.groups.otf = { }; users.users.otf = { isSystemUser = true; home = cfg.dataDir; createHome = true; group = "otf"; }; services.postgresql = { enable = true; # this lets us set the package # TODO: expose to end user package = cfg.pgPackage; # This enabled autoconfig of both a database and a user of the same name ensureDatabases = [ "otf" ]; ensureUsers = [ { name = "otf"; ensureDBOwnership = true; } ]; }; systemd.services.otf = { description = "Open Terraform Framework"; after = [ "network.target" "postgresql.service" ]; requires = [ "postgresql.service" ]; wantedBy = [ "multi-user.target" ]; inherit (cfg) environment; serviceConfig = { User = "otf"; Group = "otf"; WorkingDirectory = cfg.dataDir; ExecStart = "${cfg.package}/bin/otfd"; Restart = "on-failure"; EnvironmentFile = lib.mkIf (cfg.environmentFile != null) cfg.environmentFile; }; }; }; }