1{
2 config,
3 lib,
4 pkgs,
5 ...
6}:
7
8with lib;
9let
10 cfg = config.services.jirafeau;
11
12 group = config.services.nginx.group;
13 user = config.services.nginx.user;
14
15 withTrailingSlash = str: if hasSuffix "/" str then str else "${str}/";
16
17 localConfig = pkgs.writeText "config.local.php" ''
18 <?php
19 $cfg['admin_password'] = '${cfg.adminPasswordSha256}';
20 $cfg['web_root'] = 'http://${withTrailingSlash cfg.hostName}';
21 $cfg['var_root'] = '${withTrailingSlash cfg.dataDir}';
22 $cfg['maximal_upload_size'] = ${builtins.toString cfg.maxUploadSizeMegabytes};
23 $cfg['installation_done'] = true;
24
25 ${cfg.extraConfig}
26 '';
27in
28{
29 options.services.jirafeau = {
30 adminPasswordSha256 = mkOption {
31 type = types.str;
32 default = "";
33 description = ''
34 SHA-256 of the desired administration password. Leave blank/unset for no password.
35 '';
36 };
37
38 dataDir = mkOption {
39 type = types.path;
40 default = "/var/lib/jirafeau/data/";
41 description = "Location of Jirafeau storage directory.";
42 };
43
44 enable = mkEnableOption "Jirafeau file upload application";
45
46 extraConfig = mkOption {
47 type = types.lines;
48 default = "";
49 example = ''
50 $cfg['style'] = 'courgette';
51 $cfg['organisation'] = 'ACME';
52 '';
53 description =
54 let
55 documentationLink = "https://gitlab.com/mojo42/Jirafeau/-/blob/${cfg.package.version}/lib/config.original.php";
56 in
57 ''
58 Jirefeau configuration. Refer to <${documentationLink}> for supported
59 values.
60 '';
61 };
62
63 hostName = mkOption {
64 type = types.str;
65 default = "localhost";
66 description = "URL of instance. Must have trailing slash.";
67 };
68
69 maxUploadSizeMegabytes = mkOption {
70 type = types.int;
71 default = 0;
72 description = "Maximum upload size of accepted files.";
73 };
74
75 maxUploadTimeout = mkOption {
76 type = types.str;
77 default = "30m";
78 description =
79 let
80 nginxCoreDocumentation = "http://nginx.org/en/docs/http/ngx_http_core_module.html";
81 in
82 ''
83 Timeout for reading client request bodies and headers. Refer to
84 <${nginxCoreDocumentation}#client_body_timeout> and
85 <${nginxCoreDocumentation}#client_header_timeout> for accepted values.
86 '';
87 };
88
89 nginxConfig = mkOption {
90 type = types.submodule (import ../web-servers/nginx/vhost-options.nix { inherit config lib; });
91 default = { };
92 example = literalExpression ''
93 {
94 serverAliases = [ "wiki.''${config.networking.domain}" ];
95 }
96 '';
97 description = "Extra configuration for the nginx virtual host of Jirafeau.";
98 };
99
100 package = mkPackageOption pkgs "jirafeau" { };
101
102 poolConfig = mkOption {
103 type =
104 with types;
105 attrsOf (oneOf [
106 str
107 int
108 bool
109 ]);
110 default = {
111 "pm" = "dynamic";
112 "pm.max_children" = 32;
113 "pm.start_servers" = 2;
114 "pm.min_spare_servers" = 2;
115 "pm.max_spare_servers" = 4;
116 "pm.max_requests" = 500;
117 };
118 description = ''
119 Options for Jirafeau PHP pool. See documentation on `php-fpm.conf` for
120 details on configuration directives.
121 '';
122 };
123 };
124
125 config = mkIf cfg.enable {
126 services = {
127 nginx = {
128 enable = true;
129 virtualHosts."${cfg.hostName}" = mkMerge [
130 cfg.nginxConfig
131 {
132 extraConfig =
133 let
134 clientMaxBodySize =
135 if cfg.maxUploadSizeMegabytes == 0 then "0" else "${cfg.maxUploadSizeMegabytes}m";
136 in
137 ''
138 index index.php;
139 client_max_body_size ${clientMaxBodySize};
140 client_body_timeout ${cfg.maxUploadTimeout};
141 client_header_timeout ${cfg.maxUploadTimeout};
142 '';
143 locations = {
144 "~ \\.php$".extraConfig = ''
145 include ${config.services.nginx.package}/conf/fastcgi_params;
146 fastcgi_split_path_info ^(.+\.php)(/.+)$;
147 fastcgi_index index.php;
148 fastcgi_pass unix:${config.services.phpfpm.pools.jirafeau.socket};
149 fastcgi_param PATH_INFO $fastcgi_path_info;
150 fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
151 '';
152 };
153 root = mkForce "${cfg.package}";
154 }
155 ];
156 };
157
158 phpfpm.pools.jirafeau = {
159 inherit group user;
160 phpEnv."JIRAFEAU_CONFIG" = "${localConfig}";
161 settings = {
162 "listen.mode" = "0660";
163 "listen.owner" = user;
164 "listen.group" = group;
165 } // cfg.poolConfig;
166 };
167 };
168
169 systemd.tmpfiles.rules = [
170 "d ${cfg.dataDir} 0750 ${user} ${group} - -"
171 "d ${cfg.dataDir}/files/ 0750 ${user} ${group} - -"
172 "d ${cfg.dataDir}/links/ 0750 ${user} ${group} - -"
173 "d ${cfg.dataDir}/async/ 0750 ${user} ${group} - -"
174 ];
175 };
176
177 # uses attributes of the linked package
178 meta.buildDocsInSandbox = false;
179}