From 613aea5685ad4c698386c374474d8853bb736503 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Isma=C3=ABl=20Bouya?= Date: Fri, 10 May 2019 19:05:02 +0200 Subject: [PATCH] Move mastodon module outside of nixops --- modules/default.nix | 1 + modules/myids.nix | 2 + modules/webapps/mastodon.nix | 201 +++++++++++++++++++++ nixops/modules/websites/tools/mastodon.nix | 149 ++------------- 4 files changed, 218 insertions(+), 135 deletions(-) create mode 100644 modules/webapps/mastodon.nix diff --git a/modules/default.nix b/modules/default.nix index 4445c55..7db0cc2 100644 --- a/modules/default.nix +++ b/modules/default.nix @@ -2,6 +2,7 @@ myids = ./myids.nix; secrets = ./secrets.nix; + mastodon = ./webapps/mastodon.nix; mediagoblin = ./webapps/mediagoblin.nix; peertube = ./webapps/peertube.nix; } diff --git a/modules/myids.nix b/modules/myids.nix index 8f74425..24d853b 100644 --- a/modules/myids.nix +++ b/modules/myids.nix @@ -6,11 +6,13 @@ peertube = 394; nullmailer = 396; mediagoblin = 397; + mastodon = 399; }; ids.gids = { peertube = 394; nullmailer = 396; mediagoblin = 397; + mastodon = 399; }; }; } 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 + ''; + }; + + }; +} diff --git a/nixops/modules/websites/tools/mastodon.nix b/nixops/modules/websites/tools/mastodon.nix index c461bec..4b9b73e 100644 --- a/nixops/modules/websites/tools/mastodon.nix +++ b/nixops/modules/websites/tools/mastodon.nix @@ -1,15 +1,9 @@ { lib, pkgs, config, myconfig, mylibs, ... }: let - varDir = "/var/lib/mastodon_immae"; - socketsDir = "/run/mastodon"; - nodeSocket = "${socketsDir}/live_immae_node.sock"; - railsSocket = "${socketsDir}/live_immae_puma.sock"; - - mastodon = pkgs.webapps.mastodon.override { inherit varDir; }; - env = myconfig.env.tools.mastodon; root = "/run/current-system/webapps/tools_mastodon"; cfg = config.services.myWebsites.tools.mastodon; + mcfg = config.services.mastodon; in { options.services.myWebsites.tools.mastodon = { enable = lib.mkEnableOption "enable mastodon's website"; @@ -45,7 +39,7 @@ in { SMTP_DELIVERY_METHOD=sendmail SMTP_FROM_ADDRESS=mastodon@tools.immae.eu SENDMAIL_LOCATION="/run/wrappers/bin/sendmail" - PAPERCLIP_ROOT_PATH=${varDir} + PAPERCLIP_ROOT_PATH=${mcfg.dataDir} STREAMING_CLUSTER_NUM=1 @@ -63,126 +57,11 @@ in { LDAP_SEARCH_FILTER="(&(%{uid}=%{email})(memberOf=cn=users,cn=mastodon,ou=services,dc=immae,dc=eu))" ''; }]; - ids.uids.mastodon = env.user.uid; - ids.gids.mastodon = env.user.gid; - - users.users.mastodon = { - name = "mastodon"; - uid = config.ids.uids.mastodon; - group = "mastodon"; - description = "Mastodon user"; - home = varDir; - useDefaultShell = true; - }; - - users.groups.mastodon.gid = config.ids.gids.mastodon; - - systemd.services.mastodon-streaming = { - description = "Mastodon Streaming"; - wantedBy = [ "multi-user.target" ]; - after = [ "network.target" "mastodon-web.service" ]; - - environment.NODE_ENV = "production"; - environment.SOCKET = nodeSocket; - - 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 = "mastodon"; - EnvironmentFile = "/var/secrets/webapps/tools-mastodon"; - PrivateTmp = true; - Restart = "always"; - TimeoutSec = 15; - Type = "simple"; - WorkingDirectory = mastodon; - }; - - unitConfig.RequiresMountsFor = varDir; - }; - - systemd.services.mastodon-web = { - description = "Mastodon Web app"; - wantedBy = [ "multi-user.target" ]; - after = [ "network.target" ]; - - environment.RAILS_ENV = "production"; - environment.BUNDLE_PATH = "${mastodon.gems}/${mastodon.gems.ruby.gemPath}"; - environment.BUNDLE_GEMFILE = "${mastodon.gems.confFiles}/Gemfile"; - environment.SOCKET = railsSocket; - - path = [ mastodon.gems mastodon.gems.ruby pkgs.file ]; - - preStart = '' - ./bin/bundle exec rails db:migrate - ''; - - script = '' - exec ./bin/bundle exec puma -C config/puma.rb - ''; - - serviceConfig = { - User = "mastodon"; - EnvironmentFile = "/var/secrets/webapps/tools-mastodon"; - PrivateTmp = true; - Restart = "always"; - TimeoutSec = 60; - Type = "simple"; - WorkingDirectory = mastodon; - }; - - unitConfig.RequiresMountsFor = varDir; - }; - - systemd.services.mastodon-sidekiq = { - description = "Mastodon Sidekiq"; - wantedBy = [ "multi-user.target" ]; - after = [ "network.target" "mastodon-web.service" ]; - - environment.RAILS_ENV="production"; - environment.BUNDLE_PATH = "${mastodon.gems}/${mastodon.gems.ruby.gemPath}"; - environment.BUNDLE_GEMFILE = "${mastodon.gems.confFiles}/Gemfile"; - environment.DB_POOL="5"; - - path = [ mastodon.gems mastodon.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 = "mastodon"; - EnvironmentFile = "/var/secrets/webapps/tools-mastodon"; - PrivateTmp = true; - Restart = "always"; - TimeoutSec = 15; - Type = "simple"; - WorkingDirectory = mastodon; - }; - - unitConfig.RequiresMountsFor = varDir; - }; - - system.activationScripts.mastodon = { - deps = [ "users" ]; - text = '' - install -m 0755 -o mastodon -g mastodon -d ${socketsDir} - install -m 0755 -o mastodon -g mastodon -d ${varDir} ${varDir}/tmp/cache - ''; + services.mastodon = { + enable = true; + configFile = "/var/secrets/webapps/tools-mastodon"; + socketsPrefix = "live_immae"; + dataDir = "/var/lib/mastodon_immae"; }; services.myWebsites.tools.modules = [ @@ -191,7 +70,7 @@ in { security.acme.certs."eldiron".extraDomains."mastodon.immae.eu" = null; system.extraSystemBuilderCmds = '' mkdir -p $out/webapps - ln -s ${mastodon}/public/ $out/webapps/tools_mastodon + ln -s ${mcfg.workdir}/public/ $out/webapps/tools_mastodon ''; services.myWebsites.tools.vhostConfs.mastodon = { certName = "eldiron"; @@ -221,14 +100,14 @@ in { ProxyPassMatch ^(/.*\.(png|ico|gif)$) ! ProxyPassMatch ^/(assets|avatars|emoji|headers|packs|sounds|system|.well-known/acme-challenge) ! - RewriteRule ^/api/v1/streaming/(.+)$ unix://${nodeSocket}|http://mastodon.immae.eu/api/v1/streaming/$1 [P,NE,QSA,L] - RewriteRule ^/api/v1/streaming/$ unix://${nodeSocket}|ws://mastodon.immae.eu/ [P,NE,QSA,L] - ProxyPass / unix://${railsSocket}|http://mastodon.immae.eu/ - ProxyPassReverse / unix://${railsSocket}|http://mastodon.immae.eu/ + RewriteRule ^/api/v1/streaming/(.+)$ unix://${mcfg.sockets.node}|http://mastodon.immae.eu/api/v1/streaming/$1 [P,NE,QSA,L] + RewriteRule ^/api/v1/streaming/$ unix://${mcfg.sockets.node}|ws://mastodon.immae.eu/ [P,NE,QSA,L] + ProxyPass / unix://${mcfg.sockets.rails}|http://mastodon.immae.eu/ + ProxyPassReverse / unix://${mcfg.sockets.rails}|http://mastodon.immae.eu/ - Alias /system ${varDir} + Alias /system ${mcfg.dataDir} - + Require all granted Options -MultiViews -- 2.41.0