{ options, lib, config, pkgs, ... }: let cfg = config.services.biz-deployer; in { options.services.biz-deployer = { enable = lib.mkEnableOption "Enable the biz-deployer mini-PaaS service"; package = lib.mkOption { type = lib.types.package; description = "The biz-deployer package to use"; }; manifestPackage = lib.mkOption { type = lib.types.package; description = "The deploy-manifest package for CLI operations"; }; interval = lib.mkOption { type = lib.types.int; default = 300; description = "Interval in seconds between reconciliation cycles"; }; stateDir = lib.mkOption { type = lib.types.path; default = "/var/lib/biz-deployer"; description = "Directory for deployer state and generated unit files"; }; secretsDir = lib.mkOption { type = lib.types.path; default = "/var/lib/biz-secrets"; description = "Directory containing service secret .env files"; }; gcrootsDir = lib.mkOption { type = lib.types.path; default = "/nix/var/nix/gcroots/biz"; description = "Directory for GC roots to prevent closure garbage collection"; }; }; config = lib.mkIf cfg.enable { # Create required directories systemd.tmpfiles.rules = [ "d ${cfg.stateDir} 0755 root root -" "d ${cfg.stateDir}/services 0755 root root -" "d ${cfg.secretsDir} 0700 root root -" "d ${cfg.gcrootsDir} 0755 root root -" ]; # The deployer service runs as a timer-triggered oneshot systemd.services.biz-deployer = { description = "Mini-PaaS deployment agent"; after = ["network-online.target"]; wants = ["network-online.target"]; path = [cfg.package cfg.manifestPackage pkgs.nix pkgs.awscli2]; serviceConfig = { Type = "oneshot"; ExecStart = "${cfg.package}/bin/biz-deployer once"; Environment = [ "HOME=/root" "AWS_SHARED_CREDENTIALS_FILE=/root/.aws/credentials" ]; # Note: Hardening disabled because deployer needs write access to # /etc/systemd/system, /nix/store, /nix/var, /root/.cache/nix PrivateTmp = true; }; }; # Timer to run deployer every N seconds systemd.timers.biz-deployer = { description = "Timer for biz-deployer reconciliation"; wantedBy = ["timers.target"]; timerConfig = { OnBootSec = "1min"; OnUnitActiveSec = "${toString cfg.interval}s"; Unit = "biz-deployer.service"; }; }; # Caddy reverse proxy for deployed services # TODO: Generate this dynamically from manifest in the future services.caddy = { enable = true; globalConfig = '' admin localhost:2019 ''; virtualHosts."podcastitlater.bensima.com".extraConfig = '' reverse_proxy localhost:8000 ''; }; # Open firewall for HTTP/HTTPS networking.firewall.allowedTCPPorts = [80 443]; }; }