at 25.11-pre 5.5 kB view raw
1{ 2 config, 3 lib, 4 pkgs, 5 ... 6}: 7 8let 9 inherit (lib) 10 mkEnableOption 11 mkPackageOption 12 mkOption 13 types 14 literalExpression 15 mkIf 16 mkDefault 17 ; 18 cfg = config.services.miniflux; 19 20 defaultAddress = "localhost:8080"; 21 22 pgbin = "${config.services.postgresql.package}/bin"; 23 preStart = pkgs.writeScript "miniflux-pre-start" '' 24 #!${pkgs.runtimeShell} 25 ${pgbin}/psql "miniflux" -c "CREATE EXTENSION IF NOT EXISTS hstore" 26 ''; 27in 28 29{ 30 options = { 31 services.miniflux = { 32 enable = mkEnableOption "miniflux"; 33 34 package = mkPackageOption pkgs "miniflux" { }; 35 36 createDatabaseLocally = mkOption { 37 type = types.bool; 38 default = true; 39 description = '' 40 Whether a PostgreSQL database should be automatically created and 41 configured on the local host. If set to `false`, you need provision a 42 database yourself and make sure to create the hstore extension in it. 43 ''; 44 }; 45 46 config = mkOption { 47 type = 48 with types; 49 attrsOf (oneOf [ 50 str 51 int 52 ]); 53 example = literalExpression '' 54 { 55 CLEANUP_FREQUENCY = 48; 56 LISTEN_ADDR = "localhost:8080"; 57 } 58 ''; 59 description = '' 60 Configuration for Miniflux, refer to 61 <https://miniflux.app/docs/configuration.html> 62 for documentation on the supported values. 63 64 Correct configuration for the database is already provided. 65 By default, listens on ${defaultAddress}. 66 ''; 67 }; 68 69 adminCredentialsFile = mkOption { 70 type = types.nullOr types.path; 71 default = null; 72 description = '' 73 File containing the ADMIN_USERNAME and 74 ADMIN_PASSWORD (length >= 6) in the format of 75 an EnvironmentFile=, as described by {manpage}`systemd.exec(5)`. 76 ''; 77 example = "/etc/nixos/miniflux-admin-credentials"; 78 }; 79 }; 80 }; 81 82 config = mkIf cfg.enable { 83 assertions = [ 84 { 85 assertion = cfg.config.CREATE_ADMIN == 0 || cfg.adminCredentialsFile != null; 86 message = "services.miniflux.adminCredentialsFile must be set if services.miniflux.config.CREATE_ADMIN is 1"; 87 } 88 ]; 89 services.miniflux.config = { 90 LISTEN_ADDR = mkDefault defaultAddress; 91 DATABASE_URL = lib.mkIf cfg.createDatabaseLocally "user=miniflux host=/run/postgresql dbname=miniflux"; 92 RUN_MIGRATIONS = 1; 93 CREATE_ADMIN = lib.mkDefault 1; 94 WATCHDOG = 1; 95 }; 96 97 services.postgresql = lib.mkIf cfg.createDatabaseLocally { 98 enable = true; 99 ensureUsers = [ 100 { 101 name = "miniflux"; 102 ensureDBOwnership = true; 103 } 104 ]; 105 ensureDatabases = [ "miniflux" ]; 106 }; 107 108 systemd.services.miniflux-dbsetup = lib.mkIf cfg.createDatabaseLocally { 109 description = "Miniflux database setup"; 110 requires = [ "postgresql.service" ]; 111 after = [ 112 "network.target" 113 "postgresql.service" 114 ]; 115 serviceConfig = { 116 Type = "oneshot"; 117 User = config.services.postgresql.superUser; 118 ExecStart = preStart; 119 }; 120 }; 121 122 systemd.services.miniflux = { 123 description = "Miniflux service"; 124 wantedBy = [ "multi-user.target" ]; 125 requires = lib.optional cfg.createDatabaseLocally "miniflux-dbsetup.service"; 126 after = 127 [ "network.target" ] 128 ++ lib.optionals cfg.createDatabaseLocally [ 129 "postgresql.service" 130 "miniflux-dbsetup.service" 131 ]; 132 133 serviceConfig = { 134 Type = "notify"; 135 ExecStart = lib.getExe cfg.package; 136 User = "miniflux"; 137 DynamicUser = true; 138 RuntimeDirectory = "miniflux"; 139 RuntimeDirectoryMode = "0750"; 140 EnvironmentFile = lib.mkIf (cfg.adminCredentialsFile != null) cfg.adminCredentialsFile; 141 WatchdogSec = 60; 142 WatchdogSignal = "SIGKILL"; 143 Restart = "always"; 144 RestartSec = 5; 145 146 # Hardening 147 CapabilityBoundingSet = [ "" ]; 148 DeviceAllow = [ "" ]; 149 LockPersonality = true; 150 MemoryDenyWriteExecute = true; 151 PrivateDevices = true; 152 PrivateUsers = true; 153 ProcSubset = "pid"; 154 ProtectClock = true; 155 ProtectControlGroups = true; 156 ProtectHome = true; 157 ProtectHostname = true; 158 ProtectKernelLogs = true; 159 ProtectKernelModules = true; 160 ProtectKernelTunables = true; 161 ProtectProc = "invisible"; 162 RestrictAddressFamilies = [ 163 "AF_INET" 164 "AF_INET6" 165 "AF_UNIX" 166 ]; 167 RestrictNamespaces = true; 168 RestrictRealtime = true; 169 RestrictSUIDSGID = true; 170 SystemCallArchitectures = "native"; 171 SystemCallFilter = [ 172 "@system-service" 173 "~@privileged" 174 ]; 175 UMask = "0077"; 176 }; 177 178 environment = lib.mapAttrs (_: toString) cfg.config; 179 }; 180 environment.systemPackages = [ cfg.package ]; 181 182 security.apparmor.policies."bin.miniflux".profile = '' 183 include <tunables/global> 184 ${cfg.package}/bin/miniflux { 185 include <abstractions/base> 186 include <abstractions/nameservice> 187 include <abstractions/ssl_certs> 188 include "${pkgs.apparmorRulesFromClosure { name = "miniflux"; } cfg.package}" 189 r ${cfg.package}/bin/miniflux, 190 r @{sys}/kernel/mm/transparent_hugepage/hpage_pmd_size, 191 rw /run/miniflux/**, 192 } 193 ''; 194 }; 195}