1{ config, options, lib, pkgs, stdenv, ... }:
2let
3 cfg = config.services.pleroma;
4in {
5 options = {
6 services.pleroma = with lib; {
7 enable = mkEnableOption "pleroma";
8
9 package = mkPackageOption pkgs "pleroma" { };
10
11 user = mkOption {
12 type = types.str;
13 default = "pleroma";
14 description = "User account under which pleroma runs.";
15 };
16
17 group = mkOption {
18 type = types.str;
19 default = "pleroma";
20 description = "Group account under which pleroma runs.";
21 };
22
23 stateDir = mkOption {
24 type = types.str;
25 default = "/var/lib/pleroma";
26 readOnly = true;
27 description = "Directory where the pleroma service will save the uploads and static files.";
28 };
29
30 configs = mkOption {
31 type = with types; listOf str;
32 description = ''
33 Pleroma public configuration.
34
35 This list gets appended from left to
36 right into /etc/pleroma/config.exs. Elixir evaluates its
37 configuration imperatively, meaning you can override a
38 setting by appending a new str to this NixOS option list.
39
40 *DO NOT STORE ANY PLEROMA SECRET
41 HERE*, use
42 [services.pleroma.secretConfigFile](#opt-services.pleroma.secretConfigFile)
43 instead.
44
45 This setting is going to be stored in a file part of
46 the Nix store. The Nix store being world-readable, it's not
47 the right place to store any secret
48
49 Have a look to Pleroma section in the NixOS manual for more
50 information.
51 '';
52 };
53
54 secretConfigFile = mkOption {
55 type = types.str;
56 default = "/var/lib/pleroma/secrets.exs";
57 description = ''
58 Path to the file containing your secret pleroma configuration.
59
60 *DO NOT POINT THIS OPTION TO THE NIX
61 STORE*, the store being world-readable, it'll
62 compromise all your secrets.
63 '';
64 };
65 };
66 };
67
68 config = lib.mkIf cfg.enable {
69 users = {
70 users."${cfg.user}" = {
71 description = "Pleroma user";
72 home = cfg.stateDir;
73 group = cfg.group;
74 isSystemUser = true;
75 };
76 groups."${cfg.group}" = {};
77 };
78
79 environment.systemPackages = [ cfg.package ];
80
81 environment.etc."/pleroma/config.exs".text = ''
82 ${lib.concatMapStrings (x: "${x}") cfg.configs}
83
84 # The lau/tzdata library is trying to download the latest
85 # timezone database in the OTP priv directory by default.
86 # This directory being in the store, it's read-only.
87 # Setting that up to a more appropriate location.
88 config :tzdata, :data_dir, "/var/lib/pleroma/elixir_tzdata_data"
89
90 import_config "${cfg.secretConfigFile}"
91 '';
92
93 systemd.services.pleroma = {
94 description = "Pleroma social network";
95 wants = [ "network-online.target" ];
96 after = [ "network-online.target" "postgresql.service" ];
97 wantedBy = [ "multi-user.target" ];
98 restartTriggers = [ config.environment.etc."/pleroma/config.exs".source ];
99 environment.RELEASE_COOKIE = "/var/lib/pleroma/.cookie";
100 serviceConfig = {
101 User = cfg.user;
102 Group = cfg.group;
103 Type = "exec";
104 WorkingDirectory = "~";
105 StateDirectory = "pleroma pleroma/static pleroma/uploads";
106 StateDirectoryMode = "700";
107
108 # Checking the conf file is there then running the database
109 # migration before each service start, just in case there are
110 # some pending ones.
111 #
112 # It's sub-optimal as we'll always run this, even if pleroma
113 # has not been updated. But the no-op process is pretty fast.
114 # Better be safe than sorry migration-wise.
115 ExecStartPre =
116 let preScript = pkgs.writers.writeBashBin "pleromaStartPre" ''
117 if [ ! -f /var/lib/pleroma/.cookie ]
118 then
119 echo "Creating cookie file"
120 dd if=/dev/urandom bs=1 count=16 | hexdump -e '16/1 "%02x"' > /var/lib/pleroma/.cookie
121 fi
122 ${cfg.package}/bin/pleroma_ctl migrate
123 '';
124 in "${preScript}/bin/pleromaStartPre";
125
126 ExecStart = "${cfg.package}/bin/pleroma start";
127 ExecStop = "${cfg.package}/bin/pleroma stop";
128 ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
129
130 # Systemd sandboxing directives.
131 # Taken from the upstream contrib systemd service at
132 # pleroma/installation/pleroma.service
133 PrivateTmp = true;
134 ProtectHome = true;
135 ProtectSystem = "full";
136 PrivateDevices = false;
137 NoNewPrivileges = true;
138 CapabilityBoundingSet = "~CAP_SYS_ADMIN";
139 };
140 # disksup requires bash
141 path = [ pkgs.bash ];
142 };
143
144 };
145 meta.maintainers = with lib.maintainers; [ picnoir ];
146 meta.doc = ./pleroma.md;
147}