1 { lib, pkgs, config, ... }:
4 cfg = config.services.mastodon;
6 uid = config.ids.uids.mastodon;
7 gid = config.ids.gids.mastodon;
10 options.services.mastodon = {
11 enable = lib.mkEnableOption "Enable Mastodon’s service";
15 description = "User account under which Mastodon runs";
17 group = lib.mkOption {
20 description = "Group under which Mastodon runs";
22 dataDir = lib.mkOption {
23 type = lib.types.path;
24 default = "/var/lib/${name}";
26 The directory where Mastodon stores its data.
29 socketsPrefix = lib.mkOption {
30 type = lib.types.string;
33 The prefix to use for Mastodon sockets.
36 socketsDir = lib.mkOption {
37 type = lib.types.path;
38 default = "/run/${name}";
40 The directory where Mastodon puts runtime files and sockets.
43 configFile = lib.mkOption {
44 type = lib.types.path;
46 The configuration file path for Mastodon.
49 package = lib.mkOption {
50 type = lib.types.package;
51 default = pkgs.webapps.mastodon;
53 Mastodon package to use.
57 workdir = lib.mkOption {
58 type = lib.types.package;
59 default = cfg.package.override { varDir = cfg.dataDir; };
61 Adjusted mastodon package with overriden varDir
65 sockets = lib.mkOption {
66 type = lib.types.attrsOf lib.types.path;
68 node = "${cfg.socketsDir}/${cfg.socketsPrefix}_node.sock";
69 rails = "${cfg.socketsDir}/${cfg.socketsPrefix}_puma.sock";
78 config = lib.mkIf cfg.enable {
79 users.users = lib.optionalAttrs (cfg.user == name) (lib.singleton {
83 description = "Mastodon user";
85 useDefaultShell = true;
87 users.groups = lib.optionalAttrs (cfg.group == name) (lib.singleton {
92 systemd.services.mastodon-streaming = {
93 description = "Mastodon Streaming";
94 wantedBy = [ "multi-user.target" ];
95 after = [ "network.target" "mastodon-web.service" ];
97 environment.NODE_ENV = "production";
98 environment.SOCKET = cfg.sockets.node;
100 path = [ pkgs.nodejs pkgs.bashInteractive ];
107 while [ ! -S $SOCKET ]; do
119 EnvironmentFile = cfg.configFile;
124 WorkingDirectory = cfg.workdir;
127 unitConfig.RequiresMountsFor = cfg.dataDir;
130 systemd.services.mastodon-web = {
131 description = "Mastodon Web app";
132 wantedBy = [ "multi-user.target" ];
133 after = [ "network.target" ];
135 environment.RAILS_ENV = "production";
136 environment.BUNDLE_PATH = "${cfg.workdir.gems}/${cfg.workdir.gems.ruby.gemPath}";
137 environment.BUNDLE_GEMFILE = "${cfg.workdir.gems.confFiles}/Gemfile";
138 environment.SOCKET = cfg.sockets.rails;
140 path = [ cfg.workdir.gems cfg.workdir.gems.ruby pkgs.file ];
143 ./bin/bundle exec rails db:migrate
147 exec ./bin/bundle exec puma -C config/puma.rb
152 EnvironmentFile = cfg.configFile;
157 WorkingDirectory = cfg.workdir;
160 unitConfig.RequiresMountsFor = cfg.dataDir;
163 systemd.services.mastodon-sidekiq = {
164 description = "Mastodon Sidekiq";
165 wantedBy = [ "multi-user.target" ];
166 after = [ "network.target" "mastodon-web.service" ];
168 environment.RAILS_ENV="production";
169 environment.BUNDLE_PATH = "${cfg.workdir.gems}/${cfg.workdir.gems.ruby.gemPath}";
170 environment.BUNDLE_GEMFILE = "${cfg.workdir.gems.confFiles}/Gemfile";
171 environment.DB_POOL="5";
173 path = [ cfg.workdir.gems cfg.workdir.gems.ruby pkgs.imagemagick pkgs.ffmpeg pkgs.file ];
176 exec ./bin/bundle exec sidekiq -c 5 -q default -q mailers -q pull -q push
181 EnvironmentFile = cfg.configFile;
186 WorkingDirectory = cfg.workdir;
189 unitConfig.RequiresMountsFor = cfg.dataDir;
192 system.activationScripts.mastodon = {
195 install -m 0755 -o ${cfg.user} -g ${cfg.group} -d ${cfg.socketsDir}
196 install -m 0755 -o ${cfg.user} -g ${cfg.group} -d ${cfg.dataDir} ${cfg.dataDir}/tmp/cache