X-Git-Url: https://git.immae.eu/?a=blobdiff_plain;f=modules%2Fwebapps%2Fmastodon.nix;fp=modules%2Fwebapps%2Fmastodon.nix;h=ad6d0c3aa625cdb15408dda1940a6554fed38212;hb=613aea5685ad4c698386c374474d8853bb736503;hp=0000000000000000000000000000000000000000;hpb=1a7188052f235fb632700478fad0108e4306107d;p=perso%2FImmae%2FConfig%2FNix.git diff --git a/modules/webapps/mastodon.nix b/modules/webapps/mastodon.nix new file mode 100644 index 0000000..ad6d0c3 --- /dev/null +++ b/modules/webapps/mastodon.nix @@ -0,0 +1,201 @@ +{ lib, pkgs, config, ... }: +let + name = "mastodon"; + cfg = config.services.mastodon; + + uid = config.ids.uids.mastodon; + gid = config.ids.gids.mastodon; +in +{ + options.services.mastodon = { + enable = lib.mkEnableOption "Enable Mastodon’s service"; + user = lib.mkOption { + type = lib.types.str; + default = name; + description = "User account under which Mastodon runs"; + }; + group = lib.mkOption { + type = lib.types.str; + default = name; + description = "Group under which Mastodon runs"; + }; + dataDir = lib.mkOption { + type = lib.types.path; + default = "/var/lib/${name}"; + description = '' + The directory where Mastodon stores its data. + ''; + }; + socketsPrefix = lib.mkOption { + type = lib.types.string; + default = "live"; + description = '' + The prefix to use for Mastodon sockets. + ''; + }; + socketsDir = lib.mkOption { + type = lib.types.path; + default = "/run/${name}"; + description = '' + The directory where Mastodon puts runtime files and sockets. + ''; + }; + configFile = lib.mkOption { + type = lib.types.path; + description = '' + The configuration file path for Mastodon. + ''; + }; + package = lib.mkOption { + type = lib.types.package; + default = pkgs.webapps.mastodon; + description = '' + Mastodon package to use. + ''; + }; + # Output variables + workdir = lib.mkOption { + type = lib.types.package; + default = cfg.package.override { varDir = cfg.dataDir; }; + description = '' + Adjusted mastodon package with overriden varDir + ''; + readOnly = true; + }; + sockets = lib.mkOption { + type = lib.types.attrsOf lib.types.path; + default = { + node = "${cfg.socketsDir}/${cfg.socketsPrefix}_node.sock"; + rails = "${cfg.socketsDir}/${cfg.socketsPrefix}_puma.sock"; + }; + readOnly = true; + description = '' + Mastodon sockets + ''; + }; + }; + + config = lib.mkIf cfg.enable { + users.users = lib.optionalAttrs (cfg.user == name) (lib.singleton { + inherit name; + inherit uid; + group = cfg.group; + description = "Mastodon user"; + home = cfg.dataDir; + useDefaultShell = true; + }); + users.groups = lib.optionalAttrs (cfg.group == name) (lib.singleton { + inherit name; + inherit gid; + }); + + systemd.services.mastodon-streaming = { + description = "Mastodon Streaming"; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" "mastodon-web.service" ]; + + environment.NODE_ENV = "production"; + environment.SOCKET = cfg.sockets.node; + + path = [ pkgs.nodejs pkgs.bashInteractive ]; + + script = '' + exec npm run start + ''; + + postStart = '' + while [ ! -S $SOCKET ]; do + sleep 0.5 + done + chmod a+w $SOCKET + ''; + + postStop = '' + rm $SOCKET + ''; + + serviceConfig = { + User = cfg.user; + EnvironmentFile = cfg.configFile; + PrivateTmp = true; + Restart = "always"; + TimeoutSec = 15; + Type = "simple"; + WorkingDirectory = cfg.workdir; + }; + + unitConfig.RequiresMountsFor = cfg.dataDir; + }; + + systemd.services.mastodon-web = { + description = "Mastodon Web app"; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + + environment.RAILS_ENV = "production"; + environment.BUNDLE_PATH = "${cfg.workdir.gems}/${cfg.workdir.gems.ruby.gemPath}"; + environment.BUNDLE_GEMFILE = "${cfg.workdir.gems.confFiles}/Gemfile"; + environment.SOCKET = cfg.sockets.rails; + + path = [ cfg.workdir.gems cfg.workdir.gems.ruby pkgs.file ]; + + preStart = '' + ./bin/bundle exec rails db:migrate + ''; + + script = '' + exec ./bin/bundle exec puma -C config/puma.rb + ''; + + serviceConfig = { + User = cfg.user; + EnvironmentFile = cfg.configFile; + PrivateTmp = true; + Restart = "always"; + TimeoutSec = 60; + Type = "simple"; + WorkingDirectory = cfg.workdir; + }; + + unitConfig.RequiresMountsFor = cfg.dataDir; + }; + + systemd.services.mastodon-sidekiq = { + description = "Mastodon Sidekiq"; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" "mastodon-web.service" ]; + + environment.RAILS_ENV="production"; + environment.BUNDLE_PATH = "${cfg.workdir.gems}/${cfg.workdir.gems.ruby.gemPath}"; + environment.BUNDLE_GEMFILE = "${cfg.workdir.gems.confFiles}/Gemfile"; + environment.DB_POOL="5"; + + path = [ cfg.workdir.gems cfg.workdir.gems.ruby pkgs.imagemagick pkgs.ffmpeg pkgs.file ]; + + script = '' + exec ./bin/bundle exec sidekiq -c 5 -q default -q mailers -q pull -q push + ''; + + serviceConfig = { + User = cfg.user; + EnvironmentFile = cfg.configFile; + PrivateTmp = true; + Restart = "always"; + TimeoutSec = 15; + Type = "simple"; + WorkingDirectory = cfg.workdir; + }; + + unitConfig.RequiresMountsFor = cfg.dataDir; + }; + + system.activationScripts.mastodon = { + deps = [ "users" ]; + text = '' + install -m 0755 -o ${cfg.user} -g ${cfg.group} -d ${cfg.socketsDir} + install -m 0755 -o ${cfg.user} -g ${cfg.group} -d ${cfg.dataDir} ${cfg.dataDir}/tmp/cache + ''; + }; + + }; +}