- Install to Debian Buster
- All of services needed to run Mastodon instance (tor, postgresql, redis, nginx) will be installed to the same server.
# apt install postgresql redis nodejs npm ruby tor ffmpeg imagemagick git \
nginx wget bundler protobuf-compiler iptables-persistent ncurses-term vim \
gcc g++ make patch ruby-dev libprotobuf-dev libidn11-dev libpq-dev libicu-dev libxml2-dev libxslt1-dev
# adduser mastodon
# adduser mastodon www-data
Create mastodon
as superuser.
# su -c 'createuser -s mastodon' postgres
Edit following directives in /etc/redis/redis.conf
.
port 0
unixsocket /run/redis/redis-server.sock
unixsocketperm 666
# systemctl restart redis-server
# npm install -g --prefix /opt/yarn yarn
# echo 'export PATH=$PATH:/opt/yarn/bin' >/etc/profile.d/yarn.sh
Append following to /etc/tor/torrc
.
TransPort 127.0.0.1:9040
DNSPort 127.0.0.1:5353
VirtualAddrNetwork 127.192.0.0/10
TransPort [::1]:9040
DNSPort [::1]:5353
VirtualAddrNetworkIPv6 [fc00:70a::]/32
AutomapHostsOnResolve 1
HiddenServiceDir /var/lib/tor/mastodon
HiddenServiceVersion 3
HiddenServicePort 80 [::1]:80
# systemctl restart tor
The onion address will be generated at /var/lib/tor/mastodon/hostname
.
Make transparent proxy by iptables.
Create a chain for "torify."
# iptables -N TORIFY
# iptables -A TORIFY -m state --state RELATED,ESTABLISHED -j ACCEPT
# iptables -A TORIFY -j REJECT --reject-with icmp-net-prohibited
# iptables -t nat -N TORIFY
# iptables -t nat -A TORIFY -p udp --dport 53 -j REDIRECT --to-ports 5353
# iptables -t nat -A TORIFY -p tcp -j REDIRECT --to-ports 9040
Create a chain for accessing to mastodon backends. If you choose to access backend services on remote, You need to prepend the rules (-I) to this chain.
# iptables -N MASTODON-BE
# iptables -A MASTODON-BE -j TORIFY
# iptables -t nat -N MASTODON-BE
# iptables -t nat -A MASTODON-BE -j TORIFY
Apply these rules for mastodon
user.
# iptables -A OUTPUT -m owner --uid-owner mastodon -d 127.0.0.0/8 -j ACCEPT
# iptables -A OUTPUT -m owner --uid-owner mastodon -j MASTODON-BE
# iptables -t nat -A OUTPUT -d 127.0.0.0/8 -j ACCEPT
# iptables -t nat -A OUTPUT -m owner --uid-owner mastodon -j MASTODON-BE
Repeat to IPv6.
# ip6tables -N TORIFY
# ip6tables -A TORIFY -m state --state RELATED,ESTABLISHED -j ACCEPT
# ip6tables -A TORIFY -j REJECT --reject-with icmp6-adm-prohibited
# ip6tables -t nat -N TORIFY
# ip6tables -t nat -A TORIFY -p udp --dport 53 -j REDIRECT --to-ports 5353
# ip6tables -t nat -A TORIFY -p tcp -j REDIRECT --to-ports 9040
# ip6tables -N MASTODON-BE
# ip6tables -A MASTODON-BE -j TORIFY
# ip6tables -t nat -N MASTODON-BE
# ip6tables -t nat -A MASTODON-BE -j TORIFY
# ip6tables -A OUTPUT -m owner --uid-owner mastodon -d ::1 -j ACCEPT
# ip6tables -A OUTPUT -m owner --uid-owner mastodon -j MASTODON-BE
# ip6tables -t nat -A OUTPUT -d ::1 -j ACCEPT
# ip6tables -t nat -A OUTPUT -m owner --uid-owner mastodon -j MASTODON-BE
Persistent the rules.
# iptables-save >/etc/iptables/rules.v4
# ip6tables-save >/etc/iptables/rules.v6
Check connectivity
# su -c 'wget -O- --quiet https://check.torproject.org |sed -n "/<h1/,/<\\/h1/p"' mastodon
<h1 class="not">
Congratulations. This browser is configured to use Tor.
</h1>
# su -c 'wget -O/dev/null https://www.facebookcorewwwi.onion' mastodon
Save following as /etc/nginx/sites-available/mastodon
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen [::1]:80;
server_name %%%.onion;
keepalive_timeout 70;
sendfile on;
client_max_body_size 8m;
root /home/mastodon/live/public;
add_header Referrer-Policy "same-origin";
gzip on;
gzip_disable "msie6";
gzip_vary on;
gzip_proxied any;
gzip_comp_level 8;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
location / {
try_files $uri @proxy;
}
location ~ ^/(emoji|packs) {
add_header Cache-Control "public, max-age=31536000, immutable";
gzip_static on;
try_files $uri @proxy;
}
location /system {
add_header Cache-Control "public, max-age=31536000, immutable";
gzip off;
try_files $uri @proxy;
}
location @proxy {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Proxy "";
proxy_pass_header Server;
proxy_pass http://unix:/home/mastodon/live/tmp/web.sock:;
proxy_buffering off;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
location /api/v1/streaming {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Proxy "";
proxy_pass http://unix:/home/mastodon/live/tmp/streaming.sock:;
proxy_buffering off;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
error_page 500 501 502 503 504 /500.html;
}
# ln -s ../sites-available/mastodon /etc/nginx/sites-enabled/
# systemctl restart nginx
Login as mastodon
$ git clone https://github.com/tootsuite/mastodon live
$ cd live
$ git checkout -b run v2.4.5
Save following as ~/disable-https.patch
.
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 29ba6cad6..df22cf32e 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -33,7 +33,7 @@ class ApplicationController < ActionController::Base
private
def https_enabled?
- Rails.env.production?
+ false
end
def store_current_location
diff --git a/config/initializers/ostatus.rb b/config/initializers/ostatus.rb
index 5773b7290..93961fd19 100644
--- a/config/initializers/ostatus.rb
+++ b/config/initializers/ostatus.rb
@@ -7,7 +7,7 @@ web_host = ENV.fetch('WEB_DOMAIN') { host }
alternate_domains = ENV.fetch('ALTERNATE_DOMAINS') { '' }
Rails.application.configure do
- https = Rails.env.production? || ENV['LOCAL_HTTPS'] == 'true'
+ https = false
config.x.local_domain = host
config.x.web_domain = web_host
diff --git a/config/initializers/session_store.rb b/config/initializers/session_store.rb
index 3dc0edd6f..85983d259 100644
--- a/config/initializers/session_store.rb
+++ b/config/initializers/session_store.rb
@@ -1,3 +1,3 @@
# Be sure to restart your server when you modify this file.
-Rails.application.config.session_store :cookie_store, key: '_mastodon_session', secure: (Rails.env.production? || ENV['LOCAL_HTTPS'] == 'true')
+Rails.application.config.session_store :cookie_store, key: '_mastodon_session'
$ cd live
$ patch -p1 <~/disable-https.patch
patching file app/controllers/application_controller.rb
patching file config/initializers/ostatus.rb
patching file config/initializers/session_store.rb
$ bundle config --local build.nokogiri --use-system-libraries
You are replacing the current local value of build.nokogiri, which is currently nil
$ bundle install --deployment --jobs 3 --without development:test
$ yarn install --pure-lockfile --prod
~/live/.env.production
LOCAL_DOMAIN=%%%.onion
SINGLE_USER_MODE=true|false
DB_HOST=/run/postgresql
DB_NAME=mastodon_production
DB_USER=mastodon
REDIS_URL=unix:///run/redis/redis-server.sock
SMTP_FROM_ADDRESS=notifications@%%%.onion
SMTP_DELIVERY_METHOD=smtp|sendmail
SMTP_SERVER=***.onion
SMTP_PORT=25
#SMTP_LOGIN=
#SMTP_PASSWORD=
SMTP_AUTH_METHOD=none|plain|cram_md5
SMTP_OPENSSL_VERIFY_MODE=none|...
ALLOW_ACCESS_TO_HIDDEN_SERVICE=true
Generate some keys and append them
$ echo SECRET_KEY_BASE=$(openssl rand -hex 64) >>.env.production
$ echo OTP_SECRET=$(openssl rand -hex 64) >>.env.production
$ RAILS_ENV=production bundle exec rails mastodon:webpush:generate_vapid_key >>.env.production
$ RAILS_ENV=production bundle exec rails db:setup SAFETY_ASSURED=1
$ RAILS_ENV=production bundle exec rails assets:precompile
# su -c 'psql -c "alter role mastodon nosuperuser nocreaterole nocreatedb;"' postgres
ALTER ROLE
/etc/systemd/system/mastodon-web.service
[Unit]
Description=mastodon-web
After=network.target
[Service]
Type=simple
User=mastodon
WorkingDirectory=/home/mastodon/live
ExecStartPre=/bin/sh -c '/bin/rm tmp/web.sock 2>/dev/null || :'
ExecStart=/usr/bin/bundle exec puma -C config/puma.rb -e production -b unix:///home/mastodon/live/tmp/web.sock
TimeoutSec=15
Restart=always
[Install]
WantedBy=multi-user.target
/etc/systemd/system/mastodon-sidekiq.service
[Unit]
Description=mastodon-sidekiq
After=network.target
[Service]
Type=simple
User=mastodon
WorkingDirectory=/home/mastodon/live
Environment=RAILS_ENV=production
Environment=DB_POOL=5
ExecStart=/usr/bin/bundle exec sidekiq -c 5 -q default -q mailers -q pull -q push
TimeoutSec=15
Restart=always
[Install]
WantedBy=multi-user.target
/etc/systemd/system/mastodon-streaming.service
[Unit]
Description=mastodon-streaming
After=network.target
[Service]
Type=simple
User=mastodon
WorkingDirectory=/home/mastodon/live
Environment=NODE_ENV=production
Environment=PORT=/home/mastodon/live/tmp/streaming.sock
ExecStartPre=/bin/sh -c '/bin/rm $PORT 2>/dev/null || :'
ExecStart=/opt/npm/bin/npm run start
ExecStartPost=/bin/sh -c 'retry=30; while [ $retry -gt 0 ]; do if [ -e $PORT ]; then chmod 660 $PORT; chown :www-data $PORT; exit; else sleep 1; retry=$((retry-1)); fi; done; kill $MAINPID; exit 1'
TimeoutSec=15
Restart=always
[Install]
WantedBy=multi-user.target
# systemctl daemon-reload
# systemctl start mastodon-{web,sidekiq,streaming}
# systemctl enable mastodon-{web,sidekiq,streaming}
Created symlink /etc/systemd/system/multi-user.target.wants/mastodon-web.service → /etc/systemd/system/mastodon-web.service.
Created symlink /etc/systemd/system/multi-user.target.wants/mastodon-sidekiq.service → /etc/systemd/system/mastodon-sidekiq.service.
Created symlink /etc/systemd/system/multi-user.target.wants/mastodon-streaming.service → /etc/systemd/system/mastodon-streaming.service.
@grubles
This is affected by the following commit:
mastodon/mastodon@69bf116
Reverting this commit will allow you to log in as before. Also, I need to update the patch in this document...