1{ config, lib, pkgs, ... }: 2 3with lib; 4let 5 gunicorn = pkgs.pythonPackages.gunicorn; 6 bepasty = pkgs.pythonPackages.bepasty-server; 7 gevent = pkgs.pythonPackages.gevent; 8 python = pkgs.pythonPackages.python; 9 cfg = config.services.bepasty; 10 user = "bepasty"; 11 group = "bepasty"; 12 default_home = "/var/lib/bepasty"; 13in 14{ 15 options.services.bepasty = { 16 enable = mkEnableOption "Bepasty servers"; 17 18 servers = mkOption { 19 default = {}; 20 description = '' 21 configure a number of bepasty servers which will be started with 22 gunicorn. 23 ''; 24 type = with types ; attrsOf (submodule ({ 25 26 options = { 27 28 bind = mkOption { 29 type = types.str; 30 description = '' 31 Bind address to be used for this server. 32 ''; 33 example = "0.0.0.0:8000"; 34 default = "127.0.0.1:8000"; 35 }; 36 37 38 dataDir = mkOption { 39 type = types.str; 40 description = '' 41 Path to the directory where the pastes will be saved to 42 ''; 43 default = default_home+"/data"; 44 }; 45 46 defaultPermissions = mkOption { 47 type = types.str; 48 description = '' 49 default permissions for all unauthenticated accesses. 50 ''; 51 example = "read,create,delete"; 52 default = "read"; 53 }; 54 55 extraConfig = mkOption { 56 type = types.str; 57 description = '' 58 Extra configuration for bepasty server to be appended on the 59 configuration. 60 see https://bepasty-server.readthedocs.org/en/latest/quickstart.html#configuring-bepasty 61 for all options. 62 ''; 63 default = ""; 64 example = '' 65 PERMISSIONS = { 66 'myadminsecret': 'admin,list,create,read,delete', 67 } 68 MAX_ALLOWED_FILE_SIZE = 5 * 1000 * 1000 69 ''; 70 }; 71 72 secretKey = mkOption { 73 type = types.str; 74 description = '' 75 server secret for safe session cookies, must be set. 76 ''; 77 default = ""; 78 }; 79 80 workDir = mkOption { 81 type = types.str; 82 description = '' 83 Path to the working directory (used for config and pidfile). 84 Defaults to the users home directory. 85 ''; 86 default = default_home; 87 }; 88 89 }; 90 })); 91 }; 92 }; 93 94 config = mkIf cfg.enable { 95 environment.systemPackages = [ bepasty ]; 96 97 # creates gunicorn systemd service for each configured server 98 systemd.services = mapAttrs' (name: server: 99 nameValuePair ("bepasty-server-${name}-gunicorn") 100 ({ 101 description = "Bepasty Server ${name}"; 102 wantedBy = [ "multi-user.target" ]; 103 after = [ "network.target" ]; 104 restartIfChanged = true; 105 106 environment = let 107 penv = python.buildEnv.override { 108 extraLibs = [ bepasty gevent ]; 109 }; 110 in { 111 BEPASTY_CONFIG = "${server.workDir}/bepasty-${name}.conf"; 112 PYTHONPATH= "${penv}/${python.sitePackages}/"; 113 }; 114 115 serviceConfig = { 116 Type = "simple"; 117 PrivateTmp = true; 118 ExecStartPre = assert server.secretKey != ""; pkgs.writeScript "bepasty-server.${name}-init" '' 119 #!/bin/sh 120 mkdir -p "${server.workDir}" 121 mkdir -p "${server.dataDir}" 122 chown ${user}:${group} "${server.workDir}" "${server.dataDir}" 123 cat > ${server.workDir}/bepasty-${name}.conf <<EOF 124 SITENAME="${name}" 125 STORAGE_FILESYSTEM_DIRECTORY="${server.dataDir}" 126 SECRET_KEY="${server.secretKey}" 127 DEFAULT_PERMISSIONS="${server.defaultPermissions}" 128 ${server.extraConfig} 129 EOF 130 ''; 131 ExecStart = ''${gunicorn}/bin/gunicorn bepasty.wsgi --name ${name} \ 132 -u ${user} \ 133 -g ${group} \ 134 --workers 3 --log-level=info \ 135 --bind=${server.bind} \ 136 --pid ${server.workDir}/gunicorn-${name}.pid \ 137 -k gevent 138 ''; 139 }; 140 }) 141 ) cfg.servers; 142 143 users.extraUsers = [{ 144 uid = config.ids.uids.bepasty; 145 name = user; 146 group = group; 147 home = default_home; 148 }]; 149 150 users.extraGroups = [{ 151 name = group; 152 gid = config.ids.gids.bepasty; 153 }]; 154 }; 155}