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