aboutsummaryrefslogtreecommitdiff
path: root/virtual
diff options
context:
space:
mode:
authorIsmaël Bouya <ismael.bouya@normalesup.org>2019-01-13 13:57:55 +0100
committerIsmaël Bouya <ismael.bouya@normalesup.org>2019-01-13 14:11:20 +0100
commit35a397cd22e6c8dd7dec471f09416441b64deee4 (patch)
treeba771babc0e3d5265080f2fe9f1463ab2dd9d555 /virtual
parent108891744eaa7410e305871212d5b81c1b67a095 (diff)
downloadNix-35a397cd22e6c8dd7dec471f09416441b64deee4.tar.gz
Nix-35a397cd22e6c8dd7dec471f09416441b64deee4.tar.zst
Nix-35a397cd22e6c8dd7dec471f09416441b64deee4.zip
Add mastodon service
Diffstat (limited to 'virtual')
-rw-r--r--virtual/modules/databases/default.nix1
-rw-r--r--virtual/modules/websites/default.nix2
-rw-r--r--virtual/modules/websites/tools/mastodon/default.nix207
-rw-r--r--virtual/modules/websites/tools/mastodon/mastodon.json15
-rw-r--r--virtual/modules/websites/tools/mastodon/mastodon.nix100
5 files changed, 325 insertions, 0 deletions
diff --git a/virtual/modules/databases/default.nix b/virtual/modules/databases/default.nix
index de4ace6..db85f3c 100644
--- a/virtual/modules/databases/default.nix
+++ b/virtual/modules/databases/default.nix
@@ -163,6 +163,7 @@ in {
163 163
164 # FIXME: backup 164 # FIXME: backup
165 # Nextcloud: 14 165 # Nextcloud: 14
166 # Mastodon: 13
166 services.redis = rec { 167 services.redis = rec {
167 enable = config.services.myDatabases.redis.enable; 168 enable = config.services.myDatabases.redis.enable;
168 bind = "127.0.0.1"; 169 bind = "127.0.0.1";
diff --git a/virtual/modules/websites/default.nix b/virtual/modules/websites/default.nix
index 6b31381..d88f571 100644
--- a/virtual/modules/websites/default.nix
+++ b/virtual/modules/websites/default.nix
@@ -96,6 +96,7 @@ in
96 ./tools/dav 96 ./tools/dav
97 ./tools/cloud 97 ./tools/cloud
98 ./tools/git 98 ./tools/git
99 ./tools/mastodon
99 # built using: 100 # built using:
100 # sed -e "s/services\.httpd/services\.httpdProd/g" .nix-defexpr/channels/nixpkgs/nixos/modules/services/web-servers/apache-httpd/default.nix 101 # sed -e "s/services\.httpd/services\.httpdProd/g" .nix-defexpr/channels/nixpkgs/nixos/modules/services/web-servers/apache-httpd/default.nix
101 # And removed users / groups 102 # And removed users / groups
@@ -167,6 +168,7 @@ in
167 services.myWebsites.tools.dav.enable = true; 168 services.myWebsites.tools.dav.enable = true;
168 services.myWebsites.tools.cloud.enable = true; 169 services.myWebsites.tools.cloud.enable = true;
169 services.myWebsites.tools.git.enable = true; 170 services.myWebsites.tools.git.enable = true;
171 services.myWebsites.tools.mastodon.enable = true;
170 172
171 services.myWebsites.Chloe.production.enable = cfg.production.enable; 173 services.myWebsites.Chloe.production.enable = cfg.production.enable;
172 services.myWebsites.Ludivine.production.enable = cfg.production.enable; 174 services.myWebsites.Ludivine.production.enable = cfg.production.enable;
diff --git a/virtual/modules/websites/tools/mastodon/default.nix b/virtual/modules/websites/tools/mastodon/default.nix
new file mode 100644
index 0000000..1549ca9
--- /dev/null
+++ b/virtual/modules/websites/tools/mastodon/default.nix
@@ -0,0 +1,207 @@
1{ lib, pkgs, config, mylibs, ... }:
2let
3 mastodon = pkgs.callPackage ./mastodon.nix {
4 inherit (mylibs) fetchedGithub checkEnv;
5 };
6
7 cfg = config.services.myWebsites.tools.mastodon;
8in {
9 options.services.myWebsites.tools.mastodon = {
10 enable = lib.mkEnableOption "enable mastodon's website";
11 };
12
13 config = lib.mkIf cfg.enable {
14 # FIXME: Can we use dynamic users from systemd?
15 # nixos/modules/misc/ids.nix
16 ids.uids.mastodon = 399;
17 ids.gids.mastodon = 399;
18
19 users.users.mastodon = {
20 name = "mastodon";
21 uid = config.ids.uids.mastodon;
22 group = "mastodon";
23 description = "Mastodon user";
24 home = "${mastodon.railsRoot}";
25 useDefaultShell = true;
26 };
27
28 users.groups.mastodon.gid = config.ids.gids.mastodon;
29
30 systemd.services.mastodon-streaming = {
31 description = "Mastodon Streaming";
32 wantedBy = [ "multi-user.target" ];
33 after = [ "network.target" "mastodon-web.service" ];
34
35 environment.NODE_ENV = "production";
36 environment.SOCKET = mastodon.nodeSocket;
37
38 path = [ pkgs.nodejs pkgs.bashInteractive ];
39
40 script = ''
41 exec npm run start
42 '';
43
44 postStart = ''
45 while [ ! -S $SOCKET ]; do
46 sleep 0.5
47 done
48 chmod a+w $SOCKET
49 '';
50
51 postStop = ''
52 rm $SOCKET
53 '';
54
55 serviceConfig = {
56 User = "mastodon";
57 EnvironmentFile = mastodon.config;
58 PrivateTmp = true;
59 Restart = "always";
60 TimeoutSec = 15;
61 Type = "simple";
62 WorkingDirectory = mastodon.railsRoot;
63 };
64
65 unitConfig.RequiresMountsFor = mastodon.varDir;
66 };
67
68 systemd.services.mastodon-web = {
69 description = "Mastodon Web app";
70 wantedBy = [ "multi-user.target" ];
71 after = [ "network.target" ];
72
73 environment.RAILS_ENV = "production";
74 environment.SOCKET = mastodon.railsSocket;
75
76 path = [ pkgs.bundler ];
77
78 preStart = ''
79 bundle exec rails db:migrate
80 '';
81
82 script = ''
83 exec bundle exec puma -C config/puma.rb
84 '';
85
86 serviceConfig = {
87 User = "mastodon";
88 EnvironmentFile = mastodon.config;
89 PrivateTmp = true;
90 Restart = "always";
91 TimeoutSec = 15;
92 Type = "simple";
93 WorkingDirectory = mastodon.railsRoot;
94 };
95
96 unitConfig.RequiresMountsFor = mastodon.varDir;
97 };
98
99 systemd.services.mastodon-sidekiq = {
100 description = "Mastodon Sidekiq";
101 wantedBy = [ "multi-user.target" ];
102 after = [ "network.target" "mastodon-web.service" ];
103
104 environment.RAILS_ENV="production";
105 environment.DB_POOL="5";
106
107 path = [ pkgs.bundler ];
108
109 script = ''
110 exec bundle exec sidekiq -c 5 -q default -q mailers -q pull -q push
111 '';
112
113 serviceConfig = {
114 User = "mastodon";
115 EnvironmentFile = mastodon.config;
116 PrivateTmp = true;
117 Restart = "always";
118 TimeoutSec = 15;
119 Type = "simple";
120 WorkingDirectory = mastodon.railsRoot;
121 };
122
123 unitConfig.RequiresMountsFor = mastodon.varDir;
124 };
125
126 # FIXME: initial sync
127 system.activationScripts.mastodon = {
128 deps = [ "users" ];
129 text = ''
130 install -m 0755 -o mastodon -g mastodon -d ${mastodon.socketsDir}
131 install -m 0755 -o mastodon -g mastodon -d ${mastodon.varDir}
132 '';
133 };
134
135 services.myWebsites.tools.modules = [
136 "headers" "proxy" "proxy_wstunnel" "proxy_http" "proxy_balancer"
137 # FIXME: probably only one balancer method is needed:
138 "lbmethod_byrequests" "lbmethod_bytraffic" "lbmethod_bybusyness" "lbmethod_heartbeat"
139 ];
140 security.acme.certs."eldiron".extraDomains."mastodon.immae.eu" = null;
141 services.myWebsites.tools.vhostConfs.mastodon = {
142 certName = "eldiron";
143 hosts = ["mastodon.immae.eu" ];
144 root = "${mastodon.railsRoot}/public/";
145 extraConfig = [ ''
146 Header always set Referrer-Policy "strict-origin-when-cross-origin"
147 Header always set Strict-Transport-Security "max-age=31536000"
148
149 <LocationMatch "^/(assets|avatars|emoji|headers|packs|sounds|system)>
150 Header always set Cache-Control "public, max-age=31536000, immutable"
151 Require all granted
152 </LocationMatch>
153
154 ProxyPreserveHost On
155 RequestHeader set X-Forwarded-Proto "https"
156
157 RewriteEngine On
158
159 ProxyPass /500.html !
160 ProxyPass /sw.js !
161 ProxyPass /embed.js !
162 ProxyPass /robots.txt !
163 ProxyPass /manifest.json !
164 ProxyPass /browserconfig.xml !
165 ProxyPass /mask-icon.svg !
166 ProxyPassMatch ^(/.*\.(png|ico|gif)$) !
167 ProxyPassMatch ^/(assets|avatars|emoji|headers|packs|sounds|system|.well-known/acme-challenge) !
168
169 ProxyPassMatch /api/v1/streaming/(.+)$ balancer://node_servers_http/api/v1/streaming/$1
170 ProxyPass /api/v1/streaming/ balancer://node_servers/
171 ProxyPassReverse /api/v1/streaming/ balancer://node_servers/
172 ProxyPass / balancer://puma_servers/
173 ProxyPassReverse / balancer://puma_servers/
174
175 <Proxy balancer://puma_servers>
176 BalancerMember unix://${mastodon.railsSocket}|http://
177 </Proxy>
178
179 <Proxy balancer://node_servers>
180 BalancerMember unix://${mastodon.nodeSocket}|ws://localhost
181 </Proxy>
182
183 <Proxy balancer://node_servers_http>
184 BalancerMember unix://${mastodon.nodeSocket}|http://localhost
185 </Proxy>
186
187 Alias /system ${mastodon.varDir}
188
189 <Directory ${mastodon.varDir}>
190 Require all granted
191 Options -MultiViews
192 </Directory>
193
194 <Directory ${mastodon.railsRoot}/public/>
195 Require all granted
196 Options -MultiViews +FollowSymlinks
197 </Directory>
198
199 ErrorDocument 500 /500.html
200 ErrorDocument 501 /500.html
201 ErrorDocument 502 /500.html
202 ErrorDocument 503 /500.html
203 ErrorDocument 504 /500.html
204 '' ];
205 };
206 };
207}
diff --git a/virtual/modules/websites/tools/mastodon/mastodon.json b/virtual/modules/websites/tools/mastodon/mastodon.json
new file mode 100644
index 0000000..11e59fa
--- /dev/null
+++ b/virtual/modules/websites/tools/mastodon/mastodon.json
@@ -0,0 +1,15 @@
1{
2 "tag": "v2.6.5",
3 "meta": {
4 "name": "mastodon",
5 "url": "https://github.com/tootsuite/mastodon",
6 "branch": "refs/tags/v2.6.5"
7 },
8 "github": {
9 "owner": "tootsuite",
10 "repo": "mastodon",
11 "rev": "887f9de6dc12ef405f92b94eeaa775df74ebb1ef",
12 "sha256": "0bszv3cnlqghwpkmh7qzak7wlanlp0dp5k4wxnl3acxzj72p53v5",
13 "fetchSubmodules": true
14 }
15}
diff --git a/virtual/modules/websites/tools/mastodon/mastodon.nix b/virtual/modules/websites/tools/mastodon/mastodon.nix
new file mode 100644
index 0000000..e948852
--- /dev/null
+++ b/virtual/modules/websites/tools/mastodon/mastodon.nix
@@ -0,0 +1,100 @@
1{ checkEnv, fetchedGithub, stdenv, writeText, pkgs, cacert }:
2let
3 varDir = "/var/lib/mastodon_immae";
4 socketsDir = "/run/mastodon";
5 mastodon = stdenv.mkDerivation (fetchedGithub ./mastodon.json // rec {
6 buildPhase = ''
7 export GIT_SSL_CAINFO=${cacert}/etc/ssl/certs/ca-bundle.crt
8 export SSL_CERT_FILE=${cacert}/etc/ssl/certs/ca-bundle.crt
9
10 bundle install --deployment --without development test
11 yarn install --pure-lockfile
12 '';
13 installPhase = ''
14 cp -a . $out
15 '';
16 propagatedBuildInputs = with pkgs; [
17 zlib icu libchardet git bundler yarn
18 protobuf protobufc libidn libpqxx nodejs
19 imagemagick ffmpeg libxml2 libxslt pkgconfig
20 autoconf bison libyaml readline ncurses libffi gdbm
21 jemalloc which postgresql python3 cacert
22 ];
23 });
24 config =
25 assert checkEnv "NIXOPS_MASTODON_DB_PASS";
26 assert checkEnv "NIXOPS_MASTODON_PAPERCLIP_SECRET";
27 assert checkEnv "NIXOPS_MASTODON_SECRET_KEY_BASE";
28 assert checkEnv "NIXOPS_MASTODON_OTP_SECRET";
29 assert checkEnv "NIXOPS_MASTODON_VAPID_PRIVATE_KEY";
30 assert checkEnv "NIXOPS_MASTODON_VAPID_PUBLIC_KEY";
31 assert checkEnv "NIXOPS_MASTODON_OTP_SECRET";
32 assert checkEnv "NIXOPS_MASTODON_LDAP_PASSWORD";
33 writeText "mastodon_environment" ''
34 REDIS_HOST=localhost
35 REDIS_PORT=6379
36 REDIS_DB=13
37 DB_HOST=/run/postgresql
38 DB_USER=mastodon
39 DB_NAME=mastodon
40 DB_PASS=${builtins.getEnv "NIXOPS_MASTODON_DB_PASS"}
41 DB_PORT=5432
42
43 LOCAL_DOMAIN=mastodon.immae.eu
44 LOCAL_HTTPS=true
45 ALTERNATE_DOMAINS=immae.eu
46
47 PAPERCLIP_SECRET=${builtins.getEnv "NIXOPS_MASTODON_PAPERCLIP_SECRET"}
48 SECRET_KEY_BASE=${builtins.getEnv "NIXOPS_MASTODON_SECRET_KEY_BASE"}
49 OTP_SECRET=${builtins.getEnv "NIXOPS_MASTODON_OTP_SECRET"}
50
51 VAPID_PRIVATE_KEY=${builtins.getEnv "NIXOPS_MASTODON_VAPID_PRIVATE_KEY"}
52 VAPID_PUBLIC_KEY=${builtins.getEnv "NIXOPS_MASTODON_VAPID_PUBLIC_KEY"}
53
54 SMTP_SERVER=mail.immae.eu
55 SMTP_PORT=587
56 SMTP_FROM_ADDRESS=notifications@mastodon.immae.eu
57 SMTP_DELIVERY_METHOD=smtp
58 PAPERCLIP_ROOT_PATH=${varDir}
59
60 STREAMING_CLUSTER_NUM=1
61
62 # LDAP authentication (optional)
63 LDAP_ENABLED=true
64 LDAP_HOST=ldap.immae.eu
65 LDAP_PORT=636
66 LDAP_METHOD=simple_tls
67 LDAP_BASE="dc=immae,dc=eu"
68 LDAP_BIND_DN="cn=mastodon,ou=services,dc=immae,dc=eu"
69 LDAP_PASSWORD="${builtins.getEnv "NIXOPS_MASTODON_LDAP_PASSWORD"}"
70 LDAP_UID="uid"
71 LDAP_SEARCH_FILTER="(&(%{uid}=%{email})(memberOf=cn=users,cn=mastodon,ou=services,dc=immae,dc=eu))"
72 '';
73
74 railsRoot = stdenv.mkDerivation {
75 name = "mastodon_immae";
76 inherit config mastodon;
77 builder = writeText "build_mastodon_immae" ''
78 source $stdenv/setup
79 set -a
80 source $config
81 set +a
82 cp -a $mastodon $out
83 cd $out
84 chmod u+rwX . node_modules public
85 RAILS_ENV=production bundle exec rails assets:precompile
86 '';
87 propagatedBuildInputs = with pkgs; [
88 zlib icu libchardet git bundler yarn
89 protobuf protobufc libidn libpqxx nodejs
90 imagemagick ffmpeg libxml2 libxslt pkgconfig
91 autoconf bison libyaml readline ncurses libffi gdbm
92 jemalloc which postgresql python3 cacert
93 ];
94 };
95in
96 {
97 inherit railsRoot config varDir socketsDir;
98 nodeSocket = "${socketsDir}/live_immae_node.sock";
99 railsSocket = "${socketsDir}/live_immae_puma.sock";
100 }