1{ config, lib, pkgs, ... }:
2
3let
4 cfg = config.services.meguca;
5 postgres = config.services.postgresql;
6in with lib; {
7 options.services.meguca = {
8 enable = mkEnableOption "meguca";
9
10 dataDir = mkOption {
11 type = types.path;
12 default = "/var/lib/meguca";
13 example = "/home/okina/meguca";
14 description = "Location where meguca stores it's database and links.";
15 };
16
17 password = mkOption {
18 type = types.str;
19 default = "meguca";
20 example = "dumbpass";
21 description = "Password for the meguca database.";
22 };
23
24 passwordFile = mkOption {
25 type = types.path;
26 default = "/run/keys/meguca-password-file";
27 example = "/home/okina/meguca/keys/pass";
28 description = "Password file for the meguca database.";
29 };
30
31 reverseProxy = mkOption {
32 type = types.nullOr types.str;
33 default = null;
34 example = "192.168.1.5";
35 description = "Reverse proxy IP.";
36 };
37
38 sslCertificate = mkOption {
39 type = types.nullOr types.str;
40 default = null;
41 example = "/home/okina/meguca/ssl.cert";
42 description = "Path to the SSL certificate.";
43 };
44
45 listenAddress = mkOption {
46 type = types.nullOr types.str;
47 default = null;
48 example = "127.0.0.1:8000";
49 description = "Listen on a specific IP address and port.";
50 };
51
52 cacheSize = mkOption {
53 type = types.nullOr types.int;
54 default = null;
55 example = 256;
56 description = "Cache size in MB.";
57 };
58
59 postgresArgs = mkOption {
60 type = types.str;
61 example = "user=meguca password=dumbpass dbname=meguca sslmode=disable";
62 description = "Postgresql connection arguments.";
63 };
64
65 postgresArgsFile = mkOption {
66 type = types.path;
67 default = "/run/keys/meguca-postgres-args";
68 example = "/home/okina/meguca/keys/postgres";
69 description = "Postgresql connection arguments file.";
70 };
71
72 compressTraffic = mkOption {
73 type = types.bool;
74 default = false;
75 description = "Compress all traffic with gzip.";
76 };
77
78 assumeReverseProxy = mkOption {
79 type = types.bool;
80 default = false;
81 description = "Assume the server is behind a reverse proxy, when resolving client IPs.";
82 };
83
84 httpsOnly = mkOption {
85 type = types.bool;
86 default = false;
87 description = "Serve and listen only through HTTPS.";
88 };
89 };
90
91 config = mkIf cfg.enable {
92 security.sudo.enable = cfg.enable;
93 services.postgresql.enable = cfg.enable;
94 services.meguca.passwordFile = mkDefault (pkgs.writeText "meguca-password-file" cfg.password);
95 services.meguca.postgresArgsFile = mkDefault (pkgs.writeText "meguca-postgres-args" cfg.postgresArgs);
96 services.meguca.postgresArgs = mkDefault "user=meguca password=${cfg.password} dbname=meguca sslmode=disable";
97
98 systemd.services.meguca = {
99 description = "meguca";
100 after = [ "network.target" "postgresql.service" ];
101 wantedBy = [ "multi-user.target" ];
102
103 preStart = ''
104 # Ensure folder exists or create it and links and permissions are correct
105 mkdir -p ${escapeShellArg cfg.dataDir}
106 ln -sf ${pkgs.meguca}/share/meguca/www ${escapeShellArg cfg.dataDir}
107 chmod 750 ${escapeShellArg cfg.dataDir}
108 chown -R meguca:meguca ${escapeShellArg cfg.dataDir}
109
110 # Ensure the database is correct or create it
111 ${pkgs.sudo}/bin/sudo -u ${postgres.superUser} ${postgres.package}/bin/createuser \
112 -SDR meguca || true
113 ${pkgs.sudo}/bin/sudo -u ${postgres.superUser} ${postgres.package}/bin/createdb \
114 -T template0 -E UTF8 -O meguca meguca || true
115 ${pkgs.sudo}/bin/sudo -u meguca ${postgres.package}/bin/psql \
116 -c "ALTER ROLE meguca WITH PASSWORD '$(cat ${escapeShellArg cfg.passwordFile})';" || true
117 '';
118
119 script = ''
120 cd ${escapeShellArg cfg.dataDir}
121
122 ${pkgs.meguca}/bin/meguca -d "$(cat ${escapeShellArg cfg.postgresArgsFile})"''
123 + optionalString (cfg.reverseProxy != null) " -R ${cfg.reverseProxy}"
124 + optionalString (cfg.sslCertificate != null) " -S ${cfg.sslCertificate}"
125 + optionalString (cfg.listenAddress != null) " -a ${cfg.listenAddress}"
126 + optionalString (cfg.cacheSize != null) " -c ${toString cfg.cacheSize}"
127 + optionalString (cfg.compressTraffic) " -g"
128 + optionalString (cfg.assumeReverseProxy) " -r"
129 + optionalString (cfg.httpsOnly) " -s" + " start";
130
131 serviceConfig = {
132 PermissionsStartOnly = true;
133 Type = "forking";
134 User = "meguca";
135 Group = "meguca";
136 ExecStop = "${pkgs.meguca}/bin/meguca stop";
137 };
138 };
139
140 users = {
141 groups.meguca.gid = config.ids.gids.meguca;
142
143 users.meguca = {
144 description = "meguca server service user";
145 home = cfg.dataDir;
146 createHome = true;
147 group = "meguca";
148 uid = config.ids.uids.meguca;
149 };
150 };
151 };
152
153 imports = [
154 (mkRenamedOptionModule [ "services" "meguca" "baseDir" ] [ "services" "meguca" "dataDir" ])
155 ];
156
157 meta.maintainers = with maintainers; [ chiiruno ];
158}