at master 6.1 kB view raw
1{ 2 config, 3 lib, 4 pkgs, 5 ... 6}: 7 8let 9 cfg = config.services.chhoto-url; 10 11 environment = lib.mapAttrs ( 12 _: value: 13 if value == true then 14 "True" 15 else if value == false then 16 "False" 17 else 18 toString value 19 ) cfg.settings; 20in 21 22{ 23 meta.maintainers = with lib.maintainers; [ defelo ]; 24 25 options.services.chhoto-url = { 26 enable = lib.mkEnableOption "Chhoto URL"; 27 28 package = lib.mkPackageOption pkgs "chhoto-url" { }; 29 30 settings = lib.mkOption { 31 description = '' 32 Configuration of Chhoto URL. 33 See <https://github.com/SinTan1729/chhoto-url/blob/main/compose.yaml> for a list of options. 34 ''; 35 example = { 36 port = 4567; 37 }; 38 39 type = lib.types.submodule { 40 freeformType = 41 with lib.types; 42 attrsOf (oneOf [ 43 str 44 int 45 bool 46 ]); 47 48 options = { 49 db_url = lib.mkOption { 50 type = lib.types.path; 51 description = "The path of the sqlite database."; 52 default = "/var/lib/chhoto-url/urls.sqlite"; 53 }; 54 55 port = lib.mkOption { 56 type = lib.types.port; 57 description = "The port to listen on."; 58 example = 4567; 59 }; 60 61 cache_control_header = lib.mkOption { 62 type = lib.types.nullOr lib.types.str; 63 description = "The Cache-Control header to send."; 64 default = null; 65 example = "no-cache, private"; 66 }; 67 68 disable_frontend = lib.mkOption { 69 type = lib.types.bool; 70 description = "Whether to disable the frontend."; 71 default = false; 72 }; 73 74 public_mode = lib.mkOption { 75 type = lib.types.bool; 76 description = "Whether to enable public mode."; 77 default = false; 78 apply = x: if x then "Enable" else "Disable"; 79 }; 80 81 public_mode_expiry_delay = lib.mkOption { 82 type = lib.types.nullOr lib.types.ints.unsigned; 83 description = "The maximum expiry delay in seconds to force in public mode."; 84 default = null; 85 example = 3600; 86 }; 87 88 redirect_method = lib.mkOption { 89 type = lib.types.enum [ 90 "TEMPORARY" 91 "PERMANENT" 92 ]; 93 description = "The redirect method to use."; 94 default = "PERMANENT"; 95 }; 96 97 hash_algorithm = lib.mkOption { 98 type = lib.types.nullOr (lib.types.enum [ "Argon2" ]); 99 description = '' 100 The hash algorithm to use for passwords and API keys. 101 Set to `null` if you want to provide these secrets as plaintext. 102 ''; 103 default = null; 104 }; 105 106 site_url = lib.mkOption { 107 type = lib.types.nullOr lib.types.str; 108 description = "The URL under which Chhoto URL is externally reachable."; 109 default = null; 110 }; 111 112 slug_style = lib.mkOption { 113 type = lib.types.enum [ 114 "Pair" 115 "UID" 116 ]; 117 description = "The slug style to use for auto-generated URLs."; 118 default = "Pair"; 119 }; 120 121 slug_length = lib.mkOption { 122 type = lib.types.addCheck lib.types.int (x: x >= 4); 123 description = "The length of auto-generated slugs."; 124 default = 8; 125 }; 126 127 try_longer_slugs = lib.mkOption { 128 type = lib.types.bool; 129 description = "Whether to try a longer UID upon collision."; 130 default = false; 131 }; 132 133 allow_capital_letters = lib.mkOption { 134 type = lib.types.bool; 135 description = "Whether to allow capital letters in slugs."; 136 default = false; 137 }; 138 139 custom_landing_directory = lib.mkOption { 140 type = lib.types.nullOr lib.types.path; 141 description = "The path of a directory which contains a custom landing page."; 142 default = null; 143 }; 144 }; 145 }; 146 }; 147 148 environmentFiles = lib.mkOption { 149 type = lib.types.listOf lib.types.path; 150 default = [ ]; 151 example = [ "/run/secrets/chhoto-url.env" ]; 152 description = '' 153 Files to load environment variables from in addition to [](#opt-services.chhoto-url.settings). 154 This is useful to avoid putting secrets into the nix store. 155 See <https://github.com/SinTan1729/chhoto-url/blob/main/compose.yaml> for a list of options. 156 ''; 157 }; 158 }; 159 160 config = lib.mkIf cfg.enable { 161 systemd.services.chhoto-url = { 162 wantedBy = [ "multi-user.target" ]; 163 164 inherit environment; 165 166 serviceConfig = { 167 User = "chhoto-url"; 168 Group = "chhoto-url"; 169 DynamicUser = true; 170 StateDirectory = "chhoto-url"; 171 EnvironmentFile = cfg.environmentFiles; 172 173 ExecStart = lib.getExe cfg.package; 174 175 # hardening 176 AmbientCapabilities = ""; 177 CapabilityBoundingSet = [ "" ]; 178 DevicePolicy = "closed"; 179 LockPersonality = true; 180 MemoryDenyWriteExecute = true; 181 NoNewPrivileges = true; 182 PrivateDevices = true; 183 PrivateTmp = true; 184 PrivateUsers = true; 185 ProcSubset = "pid"; 186 ProtectClock = true; 187 ProtectControlGroups = true; 188 ProtectHome = true; 189 ProtectHostname = true; 190 ProtectKernelLogs = true; 191 ProtectKernelModules = true; 192 ProtectKernelTunables = true; 193 ProtectProc = "invisible"; 194 ProtectSystem = "strict"; 195 RemoveIPC = true; 196 RestrictAddressFamilies = [ "AF_INET AF_INET6" ]; 197 RestrictNamespaces = true; 198 RestrictRealtime = true; 199 RestrictSUIDSGID = true; 200 SocketBindAllow = "tcp:${toString cfg.settings.port}"; 201 SocketBindDeny = "any"; 202 SystemCallArchitectures = "native"; 203 SystemCallFilter = [ 204 "@system-service" 205 "~@privileged" 206 "~@resources" 207 ]; 208 UMask = "0077"; 209 }; 210 }; 211 }; 212}