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}