diff options
author | Ismaël Bouya <ismael.bouya@normalesup.org> | 2019-01-13 13:57:55 +0100 |
---|---|---|
committer | Ismaël Bouya <ismael.bouya@normalesup.org> | 2019-01-13 14:11:20 +0100 |
commit | 35a397cd22e6c8dd7dec471f09416441b64deee4 (patch) | |
tree | ba771babc0e3d5265080f2fe9f1463ab2dd9d555 /virtual | |
parent | 108891744eaa7410e305871212d5b81c1b67a095 (diff) | |
download | Nix-35a397cd22e6c8dd7dec471f09416441b64deee4.tar.gz Nix-35a397cd22e6c8dd7dec471f09416441b64deee4.tar.zst Nix-35a397cd22e6c8dd7dec471f09416441b64deee4.zip |
Add mastodon service
Diffstat (limited to 'virtual')
-rw-r--r-- | virtual/modules/databases/default.nix | 1 | ||||
-rw-r--r-- | virtual/modules/websites/default.nix | 2 | ||||
-rw-r--r-- | virtual/modules/websites/tools/mastodon/default.nix | 207 | ||||
-rw-r--r-- | virtual/modules/websites/tools/mastodon/mastodon.json | 15 | ||||
-rw-r--r-- | virtual/modules/websites/tools/mastodon/mastodon.nix | 100 |
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, ... }: | ||
2 | let | ||
3 | mastodon = pkgs.callPackage ./mastodon.nix { | ||
4 | inherit (mylibs) fetchedGithub checkEnv; | ||
5 | }; | ||
6 | |||
7 | cfg = config.services.myWebsites.tools.mastodon; | ||
8 | in { | ||
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 }: | ||
2 | let | ||
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 | }; | ||
95 | in | ||
96 | { | ||
97 | inherit railsRoot config varDir socketsDir; | ||
98 | nodeSocket = "${socketsDir}/live_immae_node.sock"; | ||
99 | railsSocket = "${socketsDir}/live_immae_puma.sock"; | ||
100 | } | ||