buildInputs = old.buildInputs ++ [ tokyocabinet bzip2 ];
});
- mastodon = stdenv.mkDerivation (fetchedGithub ./fetched/mastodon.json // rec {
- buildPhase = ''
- export GIT_SSL_CAINFO=${cacert}/etc/ssl/certs/ca-bundle.crt
- export SSL_CERT_FILE=${cacert}/etc/ssl/certs/ca-bundle.crt
-
- bundle install --deployment --without development test
- yarn install --pure-lockfile
- '';
- installPhase = ''
- cp -a . $out
- '';
- propagatedBuildInputs = [
- zlib icu libchardet git bundler yarn
- protobuf protobufc libidn libpqxx nodejs
- imagemagick ffmpeg libxml2 libxslt pkgconfig
- autoconf bison libyaml readline ncurses libffi gdbm
- jemalloc which postgresql python3 cacert
- ];
- });
# https://github.com/NixOS/nixpkgs/blob/master/pkgs/stdenv/generic/setup.sh
# https://github.com/NixOS/nixpkgs/blob/master/doc/languages-frameworks
in
inherit mtr;
inherit nixops;
stgit = gitAndTools.stgit;
- #inherit mastodon;
# todo: lx* ?, unrar, unzip, zeromq?
#inherit nextcloud-client;
#inherit nixos;
--- /dev/null
+{ lib, pkgs, config, mylibs, ... }:
+let
+ mastodon = pkgs.callPackage ./mastodon.nix {
+ inherit (mylibs) fetchedGithub checkEnv;
+ };
+
+ cfg = config.services.myWebsites.tools.mastodon;
+in {
+ options.services.myWebsites.tools.mastodon = {
+ enable = lib.mkEnableOption "enable mastodon's website";
+ };
+
+ config = lib.mkIf cfg.enable {
+ # FIXME: Can we use dynamic users from systemd?
+ # nixos/modules/misc/ids.nix
+ ids.uids.mastodon = 399;
+ ids.gids.mastodon = 399;
+
+ users.users.mastodon = {
+ name = "mastodon";
+ uid = config.ids.uids.mastodon;
+ group = "mastodon";
+ description = "Mastodon user";
+ home = "${mastodon.railsRoot}";
+ 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 = mastodon.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 = mastodon.config;
+ PrivateTmp = true;
+ Restart = "always";
+ TimeoutSec = 15;
+ Type = "simple";
+ WorkingDirectory = mastodon.railsRoot;
+ };
+
+ unitConfig.RequiresMountsFor = mastodon.varDir;
+ };
+
+ systemd.services.mastodon-web = {
+ description = "Mastodon Web app";
+ wantedBy = [ "multi-user.target" ];
+ after = [ "network.target" ];
+
+ environment.RAILS_ENV = "production";
+ environment.SOCKET = mastodon.railsSocket;
+
+ path = [ pkgs.bundler ];
+
+ preStart = ''
+ bundle exec rails db:migrate
+ '';
+
+ script = ''
+ exec bundle exec puma -C config/puma.rb
+ '';
+
+ serviceConfig = {
+ User = "mastodon";
+ EnvironmentFile = mastodon.config;
+ PrivateTmp = true;
+ Restart = "always";
+ TimeoutSec = 15;
+ Type = "simple";
+ WorkingDirectory = mastodon.railsRoot;
+ };
+
+ unitConfig.RequiresMountsFor = mastodon.varDir;
+ };
+
+ systemd.services.mastodon-sidekiq = {
+ description = "Mastodon Sidekiq";
+ wantedBy = [ "multi-user.target" ];
+ after = [ "network.target" "mastodon-web.service" ];
+
+ environment.RAILS_ENV="production";
+ environment.DB_POOL="5";
+
+ path = [ pkgs.bundler ];
+
+ script = ''
+ exec bundle exec sidekiq -c 5 -q default -q mailers -q pull -q push
+ '';
+
+ serviceConfig = {
+ User = "mastodon";
+ EnvironmentFile = mastodon.config;
+ PrivateTmp = true;
+ Restart = "always";
+ TimeoutSec = 15;
+ Type = "simple";
+ WorkingDirectory = mastodon.railsRoot;
+ };
+
+ unitConfig.RequiresMountsFor = mastodon.varDir;
+ };
+
+ # FIXME: initial sync
+ system.activationScripts.mastodon = {
+ deps = [ "users" ];
+ text = ''
+ install -m 0755 -o mastodon -g mastodon -d ${mastodon.socketsDir}
+ install -m 0755 -o mastodon -g mastodon -d ${mastodon.varDir}
+ '';
+ };
+
+ services.myWebsites.tools.modules = [
+ "headers" "proxy" "proxy_wstunnel" "proxy_http" "proxy_balancer"
+ # FIXME: probably only one balancer method is needed:
+ "lbmethod_byrequests" "lbmethod_bytraffic" "lbmethod_bybusyness" "lbmethod_heartbeat"
+ ];
+ security.acme.certs."eldiron".extraDomains."mastodon.immae.eu" = null;
+ services.myWebsites.tools.vhostConfs.mastodon = {
+ certName = "eldiron";
+ hosts = ["mastodon.immae.eu" ];
+ root = "${mastodon.railsRoot}/public/";
+ extraConfig = [ ''
+ Header always set Referrer-Policy "strict-origin-when-cross-origin"
+ Header always set Strict-Transport-Security "max-age=31536000"
+
+ <LocationMatch "^/(assets|avatars|emoji|headers|packs|sounds|system)>
+ Header always set Cache-Control "public, max-age=31536000, immutable"
+ Require all granted
+ </LocationMatch>
+
+ ProxyPreserveHost On
+ RequestHeader set X-Forwarded-Proto "https"
+
+ RewriteEngine On
+
+ ProxyPass /500.html !
+ ProxyPass /sw.js !
+ ProxyPass /embed.js !
+ ProxyPass /robots.txt !
+ ProxyPass /manifest.json !
+ ProxyPass /browserconfig.xml !
+ ProxyPass /mask-icon.svg !
+ ProxyPassMatch ^(/.*\.(png|ico|gif)$) !
+ ProxyPassMatch ^/(assets|avatars|emoji|headers|packs|sounds|system|.well-known/acme-challenge) !
+
+ ProxyPassMatch /api/v1/streaming/(.+)$ balancer://node_servers_http/api/v1/streaming/$1
+ ProxyPass /api/v1/streaming/ balancer://node_servers/
+ ProxyPassReverse /api/v1/streaming/ balancer://node_servers/
+ ProxyPass / balancer://puma_servers/
+ ProxyPassReverse / balancer://puma_servers/
+
+ <Proxy balancer://puma_servers>
+ BalancerMember unix://${mastodon.railsSocket}|http://
+ </Proxy>
+
+ <Proxy balancer://node_servers>
+ BalancerMember unix://${mastodon.nodeSocket}|ws://localhost
+ </Proxy>
+
+ <Proxy balancer://node_servers_http>
+ BalancerMember unix://${mastodon.nodeSocket}|http://localhost
+ </Proxy>
+
+ Alias /system ${mastodon.varDir}
+
+ <Directory ${mastodon.varDir}>
+ Require all granted
+ Options -MultiViews
+ </Directory>
+
+ <Directory ${mastodon.railsRoot}/public/>
+ Require all granted
+ Options -MultiViews +FollowSymlinks
+ </Directory>
+
+ ErrorDocument 500 /500.html
+ ErrorDocument 501 /500.html
+ ErrorDocument 502 /500.html
+ ErrorDocument 503 /500.html
+ ErrorDocument 504 /500.html
+ '' ];
+ };
+ };
+}
--- /dev/null
+{ checkEnv, fetchedGithub, stdenv, writeText, pkgs, cacert }:
+let
+ varDir = "/var/lib/mastodon_immae";
+ socketsDir = "/run/mastodon";
+ mastodon = stdenv.mkDerivation (fetchedGithub ./mastodon.json // rec {
+ buildPhase = ''
+ export GIT_SSL_CAINFO=${cacert}/etc/ssl/certs/ca-bundle.crt
+ export SSL_CERT_FILE=${cacert}/etc/ssl/certs/ca-bundle.crt
+
+ bundle install --deployment --without development test
+ yarn install --pure-lockfile
+ '';
+ installPhase = ''
+ cp -a . $out
+ '';
+ propagatedBuildInputs = with pkgs; [
+ zlib icu libchardet git bundler yarn
+ protobuf protobufc libidn libpqxx nodejs
+ imagemagick ffmpeg libxml2 libxslt pkgconfig
+ autoconf bison libyaml readline ncurses libffi gdbm
+ jemalloc which postgresql python3 cacert
+ ];
+ });
+ config =
+ assert checkEnv "NIXOPS_MASTODON_DB_PASS";
+ assert checkEnv "NIXOPS_MASTODON_PAPERCLIP_SECRET";
+ assert checkEnv "NIXOPS_MASTODON_SECRET_KEY_BASE";
+ assert checkEnv "NIXOPS_MASTODON_OTP_SECRET";
+ assert checkEnv "NIXOPS_MASTODON_VAPID_PRIVATE_KEY";
+ assert checkEnv "NIXOPS_MASTODON_VAPID_PUBLIC_KEY";
+ assert checkEnv "NIXOPS_MASTODON_OTP_SECRET";
+ assert checkEnv "NIXOPS_MASTODON_LDAP_PASSWORD";
+ writeText "mastodon_environment" ''
+ REDIS_HOST=localhost
+ REDIS_PORT=6379
+ REDIS_DB=13
+ DB_HOST=/run/postgresql
+ DB_USER=mastodon
+ DB_NAME=mastodon
+ DB_PASS=${builtins.getEnv "NIXOPS_MASTODON_DB_PASS"}
+ DB_PORT=5432
+
+ LOCAL_DOMAIN=mastodon.immae.eu
+ LOCAL_HTTPS=true
+ ALTERNATE_DOMAINS=immae.eu
+
+ PAPERCLIP_SECRET=${builtins.getEnv "NIXOPS_MASTODON_PAPERCLIP_SECRET"}
+ SECRET_KEY_BASE=${builtins.getEnv "NIXOPS_MASTODON_SECRET_KEY_BASE"}
+ OTP_SECRET=${builtins.getEnv "NIXOPS_MASTODON_OTP_SECRET"}
+
+ VAPID_PRIVATE_KEY=${builtins.getEnv "NIXOPS_MASTODON_VAPID_PRIVATE_KEY"}
+ VAPID_PUBLIC_KEY=${builtins.getEnv "NIXOPS_MASTODON_VAPID_PUBLIC_KEY"}
+
+ SMTP_SERVER=mail.immae.eu
+ SMTP_PORT=587
+ SMTP_FROM_ADDRESS=notifications@mastodon.immae.eu
+ SMTP_DELIVERY_METHOD=smtp
+ PAPERCLIP_ROOT_PATH=${varDir}
+
+ STREAMING_CLUSTER_NUM=1
+
+ # LDAP authentication (optional)
+ LDAP_ENABLED=true
+ LDAP_HOST=ldap.immae.eu
+ LDAP_PORT=636
+ LDAP_METHOD=simple_tls
+ LDAP_BASE="dc=immae,dc=eu"
+ LDAP_BIND_DN="cn=mastodon,ou=services,dc=immae,dc=eu"
+ LDAP_PASSWORD="${builtins.getEnv "NIXOPS_MASTODON_LDAP_PASSWORD"}"
+ LDAP_UID="uid"
+ LDAP_SEARCH_FILTER="(&(%{uid}=%{email})(memberOf=cn=users,cn=mastodon,ou=services,dc=immae,dc=eu))"
+ '';
+
+ railsRoot = stdenv.mkDerivation {
+ name = "mastodon_immae";
+ inherit config mastodon;
+ builder = writeText "build_mastodon_immae" ''
+ source $stdenv/setup
+ set -a
+ source $config
+ set +a
+ cp -a $mastodon $out
+ cd $out
+ chmod u+rwX . node_modules public
+ RAILS_ENV=production bundle exec rails assets:precompile
+ '';
+ propagatedBuildInputs = with pkgs; [
+ zlib icu libchardet git bundler yarn
+ protobuf protobufc libidn libpqxx nodejs
+ imagemagick ffmpeg libxml2 libxslt pkgconfig
+ autoconf bison libyaml readline ncurses libffi gdbm
+ jemalloc which postgresql python3 cacert
+ ];
+ };
+in
+ {
+ inherit railsRoot config varDir socketsDir;
+ nodeSocket = "${socketsDir}/live_immae_node.sock";
+ railsSocket = "${socketsDir}/live_immae_puma.sock";
+ }