at 25.11-pre 4.2 kB view raw
1{ 2 config, 3 pkgs, 4 lib, 5 utils, 6 ... 7}: 8let 9 cfg = config.services.pghero; 10 settingsFormat = pkgs.formats.yaml { }; 11 settingsFile = settingsFormat.generate "pghero.yaml" cfg.settings; 12in 13{ 14 options.services.pghero = { 15 enable = lib.mkEnableOption "PgHero service"; 16 package = lib.mkPackageOption pkgs "pghero" { }; 17 18 listenAddress = lib.mkOption { 19 type = lib.types.str; 20 example = "[::1]:3000"; 21 description = '' 22 `hostname:port` to listen for HTTP traffic. 23 24 This is bound using the systemd socket activation. 25 ''; 26 }; 27 28 extraArgs = lib.mkOption { 29 type = lib.types.listOf lib.types.str; 30 default = [ ]; 31 description = '' 32 Additional command-line arguments for the systemd service. 33 34 Refer to the [Puma web server documentation] for available arguments. 35 36 [Puma web server documentation]: https://puma.io/puma#configuration 37 ''; 38 }; 39 40 settings = lib.mkOption { 41 type = settingsFormat.type; 42 default = { }; 43 example = { 44 databases = { 45 primary = { 46 url = "<%= ENV['PRIMARY_DATABASE_URL'] %>"; 47 }; 48 }; 49 }; 50 description = '' 51 PgHero configuration. Refer to the [PgHero documentation] for more 52 details. 53 54 [PgHero documentation]: https://github.com/ankane/pghero/blob/master/guides/Linux.md#multiple-databases 55 ''; 56 }; 57 58 environment = lib.mkOption { 59 type = lib.types.attrsOf lib.types.str; 60 default = { }; 61 description = '' 62 Environment variables to set for the service. Secrets should be 63 specified using {option}`environmentFile`. 64 ''; 65 }; 66 67 environmentFiles = lib.mkOption { 68 type = lib.types.listOf lib.types.path; 69 default = [ ]; 70 description = '' 71 File to load environment variables from. Loaded variables override 72 values set in {option}`environment`. 73 ''; 74 }; 75 76 extraGroups = lib.mkOption { 77 type = lib.types.listOf lib.types.str; 78 default = [ ]; 79 example = [ "tlskeys" ]; 80 description = '' 81 Additional groups for the systemd service. 82 ''; 83 }; 84 }; 85 86 config = lib.mkIf cfg.enable { 87 systemd.sockets.pghero = { 88 unitConfig.Description = "PgHero HTTP socket"; 89 wantedBy = [ "sockets.target" ]; 90 listenStreams = [ cfg.listenAddress ]; 91 }; 92 93 systemd.services.pghero = { 94 description = "PgHero performance dashboard for PostgreSQL"; 95 wantedBy = [ "multi-user.target" ]; 96 requires = [ "pghero.socket" ]; 97 after = [ 98 "pghero.socket" 99 "network.target" 100 ]; 101 102 environment = { 103 RAILS_ENV = "production"; 104 PGHERO_CONFIG_PATH = settingsFile; 105 } // cfg.environment; 106 107 serviceConfig = { 108 Type = "notify"; 109 WatchdogSec = "10"; 110 111 ExecStart = utils.escapeSystemdExecArgs ( 112 [ 113 (lib.getExe cfg.package) 114 "--bind-to-activated-sockets" 115 "only" 116 ] 117 ++ cfg.extraArgs 118 ); 119 Restart = "always"; 120 121 WorkingDirectory = "${cfg.package}/share/pghero"; 122 123 EnvironmentFile = cfg.environmentFiles; 124 SupplementaryGroups = cfg.extraGroups; 125 126 DynamicUser = true; 127 UMask = "0077"; 128 129 ProtectHome = true; 130 ProtectProc = "invisible"; 131 ProcSubset = "pid"; 132 ProtectClock = true; 133 ProtectHostname = true; 134 ProtectControlGroups = true; 135 ProtectKernelLogs = true; 136 ProtectKernelModules = true; 137 ProtectKernelTunables = true; 138 PrivateUsers = true; 139 PrivateDevices = true; 140 RestrictRealtime = true; 141 RestrictNamespaces = true; 142 RestrictAddressFamilies = [ 143 "AF_INET" 144 "AF_INET6" 145 "AF_UNIX" 146 ]; 147 DeviceAllow = [ "" ]; 148 DevicePolicy = "closed"; 149 CapabilityBoundingSet = [ "" ]; 150 MemoryDenyWriteExecute = true; 151 LockPersonality = true; 152 SystemCallArchitectures = "native"; 153 SystemCallErrorNumber = "EPERM"; 154 SystemCallFilter = [ "@system-service" ]; 155 }; 156 }; 157 }; 158}