2017-01-21 22:49:08 +01:00
Production guide
================
2017-04-13 19:37:33 +02:00
The following HTTP readers are already set internally and should not be set again:
```
'Server' => 'Mastodon',
'X-Frame-Options' => 'DENY',
'X-Content-Type-Options' => 'nosniff',
'X-XSS-Protection' => '1; mode=block',
```
2017-01-21 22:49:08 +01:00
## Nginx
Regardless of whether you go with the Docker approach or not, here is an example Nginx server configuration:
```nginx
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
2017-04-05 03:43:21 +02:00
server {
listen 80;
listen [::]:80;
server_name example.com;
return 301 https://$host$request_uri;
}
2017-01-21 22:49:08 +01:00
server {
listen 443 ssl;
2017-04-12 16:07:26 +02:00
listen [::]:443 ssl;
2017-01-21 22:49:08 +01:00
server_name example.com;
2017-04-05 03:43:21 +02:00
ssl_protocols TLSv1.2;
2017-04-05 10:44:08 +02:00
ssl_ciphers EECDH+AESGCM:EECDH+AES;
2017-04-07 21:10:39 +02:00
ssl_ecdh_curve prime256v1;
2017-04-05 03:43:21 +02:00
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
2017-01-21 22:49:08 +01:00
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
keepalive_timeout 70;
sendfile on;
client_max_body_size 0;
root /home/mastodon/live/public;
2017-04-11 17:48:27 +02:00
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;
2017-04-13 10:28:50 +02:00
add_header Strict-Transport-Security "max-age=31536000";
2017-01-21 22:49:08 +01:00
location / {
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 X-Forwarded-Proto https;
2017-04-11 17:48:27 +02:00
proxy_set_header Proxy "";
2017-01-21 22:49:08 +01:00
proxy_pass_header Server;
2017-04-12 01:27:25 +02:00
proxy_pass http://127.0.0.1:3000;
2017-01-21 22:49:08 +01:00
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;
}
2017-02-04 00:34:31 +01:00
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;
2017-04-11 17:48:27 +02:00
proxy_set_header Proxy "";
2017-02-04 00:34:31 +01:00
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;
}
2017-01-21 22:49:08 +01:00
error_page 500 501 502 503 504 /500.html;
}
```
## Running in production without Docker
It is recommended to create a special user for mastodon on the server (you could call the user `mastodon` ), though remember to disable outside login for it. You should only be able to get into that user through `sudo su - mastodon` .
## General dependencies
2017-04-05 14:11:08 +02:00
sudo apt-get install imagemagick ffmpeg libpq-dev libxml2-dev libxslt1-dev nodejs file git curl
2017-01-21 22:49:08 +01:00
curl -sL https://deb.nodesource.com/setup_4.x | sudo bash -
2017-04-08 04:59:07 +02:00
2017-04-07 01:05:32 +02:00
sudo apt-get install nodejs
2017-04-08 04:59:07 +02:00
2017-01-21 22:49:08 +01:00
sudo npm install -g yarn
## Redis
sudo apt-get install redis-server redis-tools
## Postgres
sudo apt-get install postgresql postgresql-contrib
2017-04-15 01:10:09 +02:00
Set up a user and database for Mastodon:
2017-02-07 23:57:30 +01:00
sudo su - postgres
psql
In the prompt:
CREATE USER mastodon CREATEDB;
\q
2017-04-12 07:00:57 +02:00
Under Ubuntu 16.04, you will need to explicitly enable ident authentication so that local users can connect to the database without a password:
2017-04-12 07:11:43 +02:00
sudo sed -i '/^local.*postgres.*peer$/a host all all 127.0.0.1/32 ident' /etc/postgresql/9.?/main/pg_hba.conf
2017-04-12 07:00:57 +02:00
and install an ident daemon, which does not come installed by default:
sudo apt-get install pidentd
sudo systemctl enable pidentd
sudo systemctl start pidentd
2017-04-12 07:11:43 +02:00
sudo systemctl restart postgresql
2017-04-12 07:00:57 +02:00
2017-01-21 22:49:08 +01:00
## Rbenv
It is recommended to use rbenv (exclusively from the `mastodon` user) to install the desired Ruby version. Follow the guides to [install rbenv][1] and [rbenv-build][2] (I recommend checking the [prerequisites][3] for your system on the rbenv-build project and installing them beforehand, obviously outside the unprivileged `mastodon` user)
[1]: https://github.com/rbenv/rbenv#installation
[2]: https://github.com/rbenv/ruby-build#installation
[3]: https://github.com/rbenv/ruby-build/wiki#suggested-build-environment
2017-04-11 17:48:27 +02:00
Then once `rbenv` is ready, run `rbenv install 2.4.1` to install the Ruby version for Mastodon.
2017-01-21 22:49:08 +01:00
## Git
You need the `git-core` package installed on your system. If it is so, from the `mastodon` user:
cd ~
2017-04-04 23:45:29 +02:00
git clone https://github.com/tootsuite/mastodon.git live
2017-01-21 22:49:08 +01:00
cd live
Then you can proceed to install project dependencies:
gem install bundler
bundle install --deployment --without development test
yarn install
## Configuration
Then you have to configure your instance:
cp .env.production.sample .env.production
nano .env.production
Fill in the important data, like host/port of the redis database, host/port/username/password of the postgres database, your domain name, SMTP details (e.g. from Mailgun or equivalent transactional e-mail service, many have free tiers), whether you intend to use SSL, etc. If you need to generate secrets, you can use:
rake secret
2017-04-04 15:57:37 +02:00
To get a random string. If you are setting up on one single server (most likely), then `REDIS_HOST` is localhost and `DB_HOST` is `/var/run/postgresql` , `DB_USER` is `mastodon` and `DB_NAME` is `mastodon_production` while `DB_PASS` is empty because this setup will use the ident authentication method (system user "mastodon" maps to postgres user "mastodon").
2017-01-21 22:49:08 +01:00
## Setup
2017-04-15 01:10:09 +02:00
And set up the database for the first time, this will create the tables and basic data:
2017-01-21 22:49:08 +01:00
RAILS_ENV=production bundle exec rails db:setup
Finally, pre-compile all CSS and JavaScript files:
RAILS_ENV=production bundle exec rails assets:precompile
## Systemd
Example systemd configuration for the web workers, to be placed in `/etc/systemd/system/mastodon-web.service` :
```systemd
[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
```
Example systemd configuration for the background workers, to be placed in `/etc/systemd/system/mastodon-sidekiq.service` :
```systemd
[Unit]
Description=mastodon-sidekiq
After=network.target
[Service]
Type=simple
User=mastodon
WorkingDirectory=/home/mastodon/live
Environment="RAILS_ENV=production"
Environment="DB_POOL=5"
2017-04-04 00:53:20 +02:00
ExecStart=/home/mastodon/.rbenv/shims/bundle exec sidekiq -c 5 -q default -q mailers -q pull -q push
2017-01-21 22:49:08 +01:00
TimeoutSec=15
Restart=always
[Install]
WantedBy=multi-user.target
```
2017-02-04 00:34:31 +01:00
Example systemd configuration file for the streaming API, to be placed in `/etc/systemd/system/mastodon-streaming.service` :
```systemd
[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
```
2017-04-03 00:10:51 +02:00
This allows you to `sudo systemctl enable /etc/systemd/system/mastodon-*.service` and `sudo systemctl start mastodon-web.service mastodon-sidekiq.service mastodon-streaming.service` to get things going.
2017-01-21 22:49:08 +01:00
## Cronjobs
2017-04-13 06:57:04 +02:00
There are several tasks that should be run once a day to ensure that mastodon is
running smoothly. As your mastodon user run `crontab -e` and enter the following
2017-01-21 22:49:08 +01:00
2017-04-13 06:57:04 +02:00
```
RAILS_ENV=production
2017-04-13 19:28:57 +02:00
@daily cd /home/mastodon/live && /home/mastodon/.rbenv/shims/bundle exec rake mastodon:media:clear > /dev/null
2017-04-13 06:57:04 +02:00
@daily cd /home/mastodon/live && /home/mastodon/.rbenv/shims/bundle exec rake mastodon:push:refresh > /dev/null
@daily cd /home/mastodon/live && /home/mastodon/.rbenv/shims/bundle exec rake mastodon:feeds:clear > /dev/null
```
2017-01-21 22:49:08 +01:00
## Things to look out for when upgrading Mastodon
You can upgrade Mastodon with a `git pull` from the repository directory. You may need to run:
- `RAILS_ENV=production bundle exec rails db:migrate`
- `RAILS_ENV=production bundle exec rails assets:precompile`
Depending on which files changed, e.g. if anything in the `/db/` or `/app/assets` directory changed, respectively. Also, Mastodon runs in memory, so you need to restart it before you see any changes. If you're using systemd, that would be:
sudo systemctl restart mastodon-*.service