How to install Mastodon on Debian 8
As many of you may have noticed there is a new player around that may cause some trouble to the micro-blogging platform called Twitter.
This new player, called Mastodon, isn't the usual type of centralised "free" service that attracts millions of users with the intent of monetise them by selling their data and selling advert spaces, quite the contrary. Mastodon is very similar to Twitter in terms of features but it has the added bonuses of being really free, Open Source and decentralised.
This means that each one of us could download the software and create a Twitter-like service for his/her own family/friends/colleagues linked with the Mastodon servers around the world.
To know more about why and when Mastodon has been created check out the following links:
- The power to build communities, a response to Mark Zuckerberg
- Learning from Twitter’s mistakes
- Two reasons why organizations should switch to self-hosting social media
- Welcome to Mastodon
- Mastodon's project on GitHub
- Up to date list of Mastodon instances
- Worldwide distribution and statistics
- Manuals and FAQs
- User manual
What follows is a step by step guide on how to install Mastodon on your own server.
Setting up mastodon on Debian 8
Setting up Mastodon on Debian Jessie is generally a copy/paste exercise of the commands you'll find below but keep in mind that this guide doesn't include (yet) information on how to setup and configure many other important elements such as firewall, Nginx, Postfix, etc....
Those that aren't used to configure Linux servers every day could find it easier and faster to use Webmin/Virtualmin or similar management tools which may introduce slight variations in the commands you'll have to type.
If you'd like to create a test environment and you have some experience with Docker then follow this guide.
It is strongly advised to proceed with the installation on a freshly installed Debian to avoid interfering with production environments.
General dependencies
The following commands must be run as "root".
Add Jessie backports to install ffmpeg .
echo "deb http://httpredir.debian.org/debian jessie-backports main" >> /etc/apt/sources.list apt update && apt full-upgrade -y apt-get install imagemagick ffmpeg libpq-dev libxml2-dev libxslt1-dev file curl git
Install Node.js
curl -sL https://deb.nodesource.com/setup_4.x | bash - apt install nodejs npm install -g yarn
Install Redis
apt install redis-server redis-tools
Install PostgreSQL
apt-get install postgresql postgresql-contrib
Create the user mastodon giving it rights to create databases:
su - postgres psql CREATE USER mastodon CREATEDB; \q exit
create the user Mastodon
The mastodon user will be used to install and manage all the components necessary to run Mastodon. This user cannot login to the console directly so you'll have to su to it.
adduser --disabled-password --disabled-login mastodon -s /bin/bash
To login as mastodon user:
su - mastodon
To go back to the previous user:
exit
Install Ruby
apt install autoconf bison build-essential libssl-dev libyaml-dev libreadline6-dev zlib1g-dev libncurses5-dev libffi-dev libgdbm3 libgdbm-dev
Install rbenv
In this section all commands will need to be run as user mastodon
su - mastodon git clone https://github.com/rbenv/rbenv.git ~/.rbenv cd ~/.rbenv && src/configure && make -C src echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
In the section above some environment variables are set, to apply them to the user mastodon logout and login again.
exit su - mastodon
Make sure you logged in as mastodon again before continuing.
Install ruby-build
git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build
Install Ruby
rbenv install 2.4.1
Prepare yourself a coffee as it's going to take a few minutes.
Install Mastodon
cd ~ git clone https://github.com/tootsuite/mastodon.git live cd live
With the following command we'll install the latest production ready version of Mastodon.
git checkout $(git tag | tail -n 1)
Install the remaining packets:
gem install bundler bundle install --deployment --without development test yarn install
Configuration
Copy the existing sample file into .env.production
:
cp .env.production.sample .env.production nano .env.production
Modify the following lines:
REDIS_HOST=localhost DB_HOST=/var/run/postgresql DB_USER=mastodon DB_NAME=mastodon_production LOCAL_DOMAIN=mastodon.partecipa.digital # this must be your full domain name
LOCAL_HTTPS=true # make sure this is set to true
Use the command bundle exec rake secret
3 times to create 3 random strings similar to this one:
d250201baf31243159865836db1826b8cf1d442ea5cc37119908cadde0d160b3f248b6e47a8035c62d7fd9538fb3a5bcec6bc808040bc4995426a5c27b230420
Copy each of the generated strings after the = sign (no spaces) in each of the following lines:
PAPERCLIP_SECRET= SECRET_KEY_BASE= OTP_SECRET=
Mail server configuration:
SMTP_SERVER=smtp.mailgun.org # or your mail server FQDN
SMTP_PORT=587 # or 25 if you don't plan to use TLS
SMTP_LOGIN=
SMTP_PASSWORD=
SMTP_FROM_ADDRESS=This email address is being protected from spambots. You need JavaScript enabled to view it.
#SMTP_DOMAIN= # defaults to LOCAL_DOMAIN
#SMTP_DELIVERY_METHOD=smtp # delivery method can also be sendmail
#SMTP_AUTH_METHOD=plain
#SMTP_OPENSSL_VERIFY_MODE=peer
#SMTP_ENABLE_STARTTLS_AUTO=true
The section above depends on the mail server you will be using and the eventual limits imposed by your service providers if you are using one. The example shows a configuration for Mailgun, a mass mail provider, which you could use if you plan/hope to have thousands of accounts on your Mastodon instance, otherwise configure your local Postfix and related MX/SPF records to manage the emails from your local server.
If you plan to have mainly English speaking users then set this variable:
DEFAULT_LOCALE=en
create and populate the db
RAILS_ENV=production bundle exec rails db:setup
precompile all the assets (css/js)
RAILS_ENV=production bundle exec rails assets:precompile
Once the assets have been compiled you can return to the user root:
exit
End of the section where you must use the user mastodon.
Configure the Systemd scripts
Mastodon requires to run 3 Systemd scripts.
Run the following commands as root.
web Services
nano /etc/systemd/system/mastodon-web.service
Paste the following lines:
[Unit] Description=mastodon-web After=network.target [Service] Type=simple User=mastodon WorkingDirectory=/home/mastodon/live Environment="RAILS_ENV=production" Environment="PORT=3000" ExecStart=/home/mastodon/.rbenv/shims/bundle exec puma -C config/puma.rb TimeoutSec=15 Restart=always [Install] WantedBy=multi-user.target
Background workers
nano /etc/systemd/system/mastodon-sidekiq.service
Paste the following lines:
[Unit] Description=mastodon-sidekiq After=network.target [Service] Type=simple User=mastodon WorkingDirectory=/home/mastodon/live Environment="RAILS_ENV=production" Environment="DB_POOL=20" ExecStart=/home/mastodon/.rbenv/shims/bundle exec sidekiq -c 20 -q default -q mailers -q pull -q push TimeoutSec=15 Restart=always [Install] WantedBy=multi-user.target
Streaming API
nano /etc/systemd/system/mastodon-streaming.service
Paste the following lines:
[Unit] Description=mastodon-streaming After=network.target [Service] Type=simple User=mastodon WorkingDirectory=/home/mastodon/live Environment="NODE_ENV=production" Environment="PORT=4000" ExecStart=/usr/bin/npm run start TimeoutSec=15 Restart=always [Install] WantedBy=multi-user.target
Activate the scripts:
systemctl enable /etc/systemd/system/mastodon-*.service
Run the services:
systemctl start mastodon-web.service mastodon-sidekiq.service mastodon-streaming.service
If you make changes to the configuration or update Mastodon restart the services:
systemctl restart mastodon-web.service mastodon-sidekiq.service mastodon-streaming.service
Check if the services are running:
systemctl status mastodon-web.service mastodon-sidekiq.service mastodon-streaming.service
If all the services are active (running) then you are good to go:
If you see some errors then check the logs (replace mastodon-<servicename> with eg. mastodon-web.service:
journalctl -u mastodon-<servicename>
Create the cronjob
Edit the cronjob for the user mastodon:
crontab -e -u mastodon
Past the following line:
@daily cd /home/mastodon/live && RAILS_ENV=production /home/mastodon/.rbenv/shims/bundle exec rake mastodon:daily
Install and configure Nginx
Debian 8 provides a dated version of Nginx so we'll add the official repository to use the latest one:
wget -O - https://nginx.org/keys/nginx_signing.key | apt-key add - echo "deb http://nginx.org/packages/debian/ $(lsb_release -sc) nginx" > /etc/apt/sources.list.d/nginx.list apt update apt install nginx
Note: If you use Virtualmin you should create the directories sites-available and sites-enabled, as root, under /etc/nginx as they are not created by default and Virtualmin likes to use them.
Create a new conf file for mastodon:
nano /etc/nginx/conf.d/mastodon.conf
Paste inside it the following configuration (replace the example domain mastodon.partecipa.digital with your own and edit the relevant path) :
map $http_upgrade $connection_upgrade { default upgrade; '' close; } server { listen 80; listen [::]:80; server_name mastodon.partecipa.digital;
# Redirect all requests to https location / { return 301 https://$host$request_uri; }
# Useful if you use Let's Encrypt
location /.well-known/acme-challenge/ { allow all; } access_log /dev/null; error_log /dev/null; } server { listen 443 ssl http2; # listen [::]:443 ssl http2; # Remove # if you are using IPv6 server_name mastodon.partecipa.digital;
root /home/mastodon/live/public; index index.html index.htm index.php;
access_log /var/log/mastodon.partecipa.digital_access_log;
error_log /var/log/mastodon.partecipa.digital_error_log;
# If you don't use a subdomain (eg. mastodon.partecipa.digital) remove the # from the 3 lines below
#if ($host = www.partecipa.digital) { # return 301 https://partecipa.digital$request_uri; #}
#HTTPS
ssl on;
ssl_protocols TLSv1.2; ssl_ecdh_curve prime256v1;
ssl_ciphers EECDH+AESGCM:EECDH+AES;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_certificate /home/partecipa/domains/mastodon.partecipa.digital/ssl.cert;
ssl_certificate_key /home/partecipa/domains/mastodon.partecipa.digital/ssl.key;
keepalive_timeout 70;
sendfile on;
client_max_body_size 0;
gzip on;
gzip_disable "msie6";
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
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;
add_header Content-Security-Policy "default-src 'none'; font-src 'self'; media-src 'self'; style-src 'self' 'unsafe-inline'; script-src 'self'; img-src 'self' data:; connect-src 'self' wss://mastodon.partecipa.digital; frame-ancestors 'none';";
add_header Referrer-Policy "no-referrer";
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload;";
location / {
try_files $uri @proxy;
root /home/mastodon/live/public;
}
location ~ ^/(assets|system/media_attachments/files|system/accounts/avatars) {
add_header Cache-Control "public, max-age=31536000, immutable";
}
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 X-Forwarded-Proto https;
proxy_set_header Proxy "";
proxy_pass_header Server;
proxy_pass http://127.0.0.1:3000;
proxy_buffering off;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
tcp_nodelay on;
}
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 X-Forwarded-Proto https;
proxy_set_header Proxy "";
proxy_pass http://localhost:4000;
proxy_buffering off;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
tcp_nodelay on;
}
error_page 500 501 502 503 504 /500.html;
}
Once you saved the file you can start Nginx:
systemctl start nginx
Or. if Nginx was already running, you can simply reload the configuration:
systemctl reload nginx
upgrades management
Upgrade Ruby
You may want to update Mastodon quite often, especially now that plenty of new features and patches are becoming available, and that may require to upgrade Ruby as well. Read carefully the release notices to check what steps or upgrades are required.
If required upgrade Ruby as follows (replace X.X.X with the version of Ruby required) :
su - mastodon rbenv install X.X.X rbenv global X.X.X gem install bundler --no-ri
Then follow Mastodon's upgrade procedures.
Upgrading mastodon
Before starting any upgrades remember that backups and snapshots may help if something goes wrong.
Update your repositories and upgrade your system:
apt update && apt full-upgrade
Especially if you are installing a major release don't forget to stop Mastodon's services:
systemctl stop mastodon-web.service mastodon-sidekiq.service mastodon-streaming.service
Main commands generally used to upgrade Mastodon:
(It may not be necessary to run all the commands so check the release notes before performing an upgrade)
su - mastodon cd live git fetch git checkout $(git tag | tail -n 1) bundle install npm upgrade yarn yarn install RAILS_ENV=production bundle exec rails assets:clean RAILS_ENV=production bundle exec rails assets:precompile RAILS_ENV=production bundle exec rails db:migrate exit
Start Mastodon's services:
systemctl start mastodon-web.service mastodon-sidekiq.service mastodon-streaming.service
Have you found errors or you'd like to suggest improvements? Then contact the author of this article.