description: Welcome to the Mastodon documentation!
menu:
docs:
weight: -99
---
Welcome to the Mastodon documentation!
{{<youtubeid="IPSbNdBmWKE"caption="An introductory video explaining basic Mastodon concepts with visual animations">}}
## What is a microblog?
Similar to how blogging is the act of publishing updates to a website, **microblogging** is the act of publishing small updates to a stream of updates on your profile. You can publish text posts and optionally attach media such as pictures, audio, video, or polls. Mastodon lets you follow friends and discover new ones.
## What is federation? <aid="what-is-federation"></a>
**Federation** is a form of decentralization. Instead of a single central service that all people use, there are multiple services, that any number of people can use.
| Grade of centralization | Examples |
| :--- | :--- |
| Centralized | Twitter, Facebook, Instagram |
| Federated | Email, XMPP, phone networks, physical mail |
| Distributed | BitTorrent, IPFS, Scuttlebutt |
A Mastodon website can operate alone. Just like a traditional website, people sign up on it, post messages, upload pictures and talk to each other. _Unlike_ a traditional website, Mastodon websites can interoperate, letting their users communicate with each other; just like you can send an email from your Gmail account to someone from Outlook, Fastmail, Protonmail, or any other email provider, as long as you know their email address, **you can mention or message anyone on any website using their address**.
{{<figuresrc="/assets/image%20%289%29.png"caption="From left to right: Centralized, Federated, Distributed">}}
## What is ActivityPub? <aid="the-fediverse"></a>
Mastodon uses a standardized, open protocol to implement federation. It is called **ActivityPub**. Any software that likewise implements federation via ActivityPub can seamlessly communicate with Mastodon, just like Mastodon websites communicate with one another.
The **fediverse** \(“federated universe”\) is the name for all websites that can communicate with each other over ActivityPub and the World Wide Web. That includes all Mastodon servers, but also other implementations:
* Pleroma, a modular microblogging engine,
* Pixelfed, which lets you share and consume media posts,
* Misskey, which includes microblogging alongside a customizable dashboard,
* PeerTube, which lets you upload videos to channels,
* Plume, which lets you publish longer-form articles,
* and many more, including individual and personal websites!
The fediverse does not have its own brand, so you might more often hear “follow me on Mastodon” than “follow me on the fediverse”, but technically the latter is more correct.
Because Mastodon is simply software that can be used to power any website, potential users of Mastodon have the option of choosing a service provider from already-existing Mastodon websites, or to create their own Mastodon website if they wish. The Mastodon project maintains a list of recommended service providers at [joinmastodon.org](https://joinmastodon.org), sortable by category and/or language. Some websites may have moderation policies that go beyond this, such as requiring the use of certain tags on potentially sensitive content, and some websites may have more relaxed moderation policies, but websites listed in the picker all agree to adopt the [Mastodon Server Covenant](https://joinmastodon.org/covenant), meaning that they pledge to actively moderate against hate speech, to take daily backups, to have at least one emergency admin, and to provide at least 3 months advance notice in case of shutdown.
> Maintaining communities that feel safe for all of its members is not easy. Mastodon provides a lot of foundational framework and tools for doing it, and shifts the power to effect change from one commercial entity to the communities themselves.
>
> -- Eugen Rochko, Jul 6 2018, ["Cage the Mastodon"](https://blog.joinmastodon.org/2018/07/cage-the-mastodon/)
> A centralized social media platform has a hierarchical structure where rules and their enforcement, as well as the development and direction of the platform, are decided by the CEO \[...\] A decentralized network deliberately relinquishes control of the platform owner, by essentially not having one.
>
> -- Eugen Rochko, Dec 30 2018, ["Why does decentralization matter?"](https://blog.joinmastodon.org/2018/12/why-does-decentralization-matter/)
### Funding and monetization <aid="funding-and-monetization"></a>
Mastodon websites are operated by different people or organizations completely independently. Mastodon does not implement any monetization strategies in the software.
Some server operators choose to offer paid accounts, some server operators are companies who can utilize their existing infrastructure, some server operators rely on crowdfunding from their users via Patreon and similar services, and some server operators are just paying out-of-pocket for a personal server for themselves and maybe some friends. So if you want to support the server hosting your account, check if it offers a way to donate.
Mastodon development is likewise crowdfunded via [Patreon](https://patreon.com/mastodon) and via [OpenCollective](https://opencollective.com/mastodon). **No venture capital is involved.**
> In my opinion, “instant, public, global messaging and conversation” should, in fact, be _global_. Distributed between independent organizations and actors who can self-govern. A public utility, without incentives to exploit the conversations for profit.
>
> -- Eugen Rochko, Mar 3 2018, ["Twitter is not a public utility"](https://blog.joinmastodon.org/2018/03/twitter-is-not-a-public-utility/)
### Interoperability between different software <aid="impersonation-and-verification"></a>
In practical terms: Imagine if you could follow an Instagram user from your Twitter account and comment on their photos without leaving your account. If Twitter and Instagram were federated services that used the same protocol, that would be possible. With a Mastodon account, **you can communicate with any other compatible website,**_**even if it is not running on Mastodon**_. All that is necessary is that the software support the same subset of the ActivityPub protocol that allows for creating and interacting with status updates. To find out more about the technical specifications required to interoperate with Mastodon, see [ActivityPub](spec/activitypub.md), [WebFinger](spec/webfinger.md), and [Security](spec/security.md). To read more about what ActivityPub allows us to do, see [Why ActivityPub is the future](https://blog.joinmastodon.org/2018/06/why-activitypub-is-the-future/).
> All of these platforms are different and they focus on different needs. And yet, the foundation is all the same: people subscribing to receive posts from other people. And so, they are all compatible.
>
> -- Eugen Rochko, Jun 27 2018, ["Why ActivityPub is the future"](https://blog.joinmastodon.org/2018/06/why-activitypub-is-the-future/)
### Free/libre software
Unlike proprietary services, **anyone has the complete freedom to run, examine, inspect, copy, modify, distribute, and reuse the Mastodon source code, provided they guarantee the same freedoms for any derivative work.** Just like how users of Mastodon can choose their service provider, you as an individual are free to contribute features to Mastodon or publish a modified version of Mastodon that includes different features. These modified versions, also known as software forks, are required to also uphold the same freedoms as the original Mastodon project. For example, [glitch-soc](https://glitch-soc.github.io/docs/) is a software distribution that adds various experimental features. Many individual forks exist as well, perhaps themed slightly differently or including small modifications to the codebase. Because Mastodon is libre software that respects your freedom, personalizations like this are not only allowed but encouraged.
> The ultimate power is in giving people the ability to create their own spaces, their own communities, to modify the software as they see fit, but without sacrificing the ability of people from different communities to interact with each other.
>
> -- Eugen Rochko, Feb 20 2017, ["The power to build communities: A response to Mark Zuckerberg"](https://blog.joinmastodon.org/2017/02/the-power-to-build-communities/)
> Decentralization is biodiversity of the digital world, the hallmark of a healthy ecosystem. A decentralized network like the fediverse allows different user interfaces, different software, different forms of government to co-exist and cooperate.
>
> -- Eugen Rochko, Dec 30 2018, ["Why does decentralization matter?"](https://blog.joinmastodon.org/2018/12/why-does-decentralization-matter/)
## Choose your path

Learn how to use Mastodon:
{{<page-refpage="user/signup.md">}}
Learn how to install Mastodon:
{{<page-refpage="admin/prerequisites.md">}}
Learn how to write an app for Mastodon:
{{<page-refpage="client/intro.md">}}
Learn about the Mastodon backend and how to contribute:
{{<page-refpage="dev/overview.md">}}
<divstyle="margin-bottom: 26px">
{{<youtube"IPSbNdBmWKE">}}
</div>
**Choose your path:**
- [Learn how to use Mastodon]({{< relref "usage/basics.md" >}})
- [Learn how to install Mastodon]({{< relref "administration/installation.md" >}})
- [Learn how to write an app for Mastodon]({{< relref "api/guidelines.md" >}})
## Setting up regular backups \(optional, but not really\) <aid="setting-up-regular-backups-optional-but-not-really"></a>
For any real-world use, you should make sure to regularly backup your Mastodon server.
### Overview <aid="overview"></a>
Things that need to be backed up in order of importance:
1. PostgreSQL database
2. Application secrets from the `.env.production` file or equivalent
3. User-uploaded files
4. Redis database
### Failure modes <aid="failure-modes"></a>
There are two failure types that people in general may guard for: The failure of the hardware, such as data corruption on the disk; and human and software error, such as wrongful deletion of particular piece of data. In this documentation, only the former type is considered.
A lost PostgreSQL database is complete game over. Mastodon stores all the most important data in the PostgreSQL database. If the database disappears, all the accounts, posts and followers on your server will disappear with it.
If you lose application secrets, some functions of Mastodon will stop working for your users, they will be logged out, two-factor authentication will become unavailable, Web Push API subscriptions will stop working.
If you lose user-uploaded files, you will lose avatars, headers, and media attachments, but Mastodon _will_ work moving forward.
Losing the Redis database is almost harmless: The only irrecoverable data will be the contents of the Sidekiq queues and scheduled retries of previously failed jobs. The home and list feeds are stored in Redis, but can be regenerated with tootctl.
The best backups are so-called off-site backups, i.e. ones that are not stored on the same machine as Mastodon itself. If the server you are hosted on goes on fire and the hard disk drive explodes, backups stored on that same hard drive won’t be of much use.
### Backing up application secrets <aid="backing-up-application-secrets"></a>
Application secrets are the easiest to backup, since they never change. You only need to store `.env.production` somewhere safe.
### Backing up PostgreSQL <aid="backing-up-postgresql"></a>
PostgreSQL is at risk of data corruption from power cuts, hard disk drive failure, and botched schema migrations. For that reason, occassionally making a backup with `pg_dump` or `pg_dumpall` is recommended.
For high-availability setups, it is possible to use hot streaming replication to have a second PostgreSQL server with always up-to-date data, ready to be switched over to if the other server goes down.
### Backing up user-uploaded files <aid="backing-up-user-uploaded-files"></a>
If you are using an external object storage provider such as Amazon S3, Google Cloud or Wasabi, then you don’t need to worry about backing those up. The respective companies are responsible for handling hardware failures.
If you are using local file storage, then it’s up to you to make copies of the sizeable `public/system` directory, where uploaded files are stored by default.
### Backing up Redis <aid="backing-up-redis"></a>
Backing up Redis is easy. Redis regularly writes to `/var/lib/redis/dump.rdb` which is the only file you need to make a copy of.
Mastodon uses environment variables as its configuration.
For convenience, it can read them from a flat file called `.env.production` in the Mastodon directory, but they can always be overridden by a specific process. For example, systemd service files can read environment variables from an `EnvironmentFile` or from inline definitions with `Environment`, so you can have different configuration parameters for specific services. They can also be specified when calling Mastodon from the command line.
We will be using rbenv to manage Ruby versions, because it’s easier to get the right versions and to update once a newer release comes out. rbenv must be installed for a single Linux user, therefore, first we must create the user Mastodon will be running as:
For optimal performance, you may use [pgTune](https://pgtune.leopard.in.ua/#/) to generate an appropriate configuration and edit values in `/etc/postgresql/9.6/main/postgresql.conf` before restarting PostgreSQL with `systemctl restart postgresql`
#### Creating a user <aid="creating-a-user"></a>
You will need to create a PostgreSQL user that Mastodon could use. It is easiest to go with “ident” authentication in a simple setup, i.e. the PostgreSQL user does not have a separate password and can be used by the Linux user with the same username.
Open the prompt:
In the prompt, execute:
```sql
CREATE USER mastodon CREATEDB;
\q
```
Done!
### Setting up Mastodon <aid="setting-up-mastodon"></a>
It is time to download the Mastodon code. Switch to the mastodon user:
#### Checking out the code <aid="checking-out-the-code"></a>
Use git to download the latest stable release of Mastodon:
```bash
git clone https://github.com/tootsuite/mastodon.git live && cd live
The configuration file is saved as `.env.production`. You can review and edit it to your liking. Refer to the [documentation on configuration.]({{< relref "config.md" >}})
You’re done with the mastodon user for now, so switch back to root:
### Setting up nginx <aid="setting-up-nginx"></a>
Copy the configuration template for nginx from the Mastodon directory:
Then edit `/etc/nginx/sites-available/mastodon` to replace `example.com` with your own domain name, and make any other adjustments you might need.
Reload nginx for the changes to take effect:
### Acquiring a SSL certificate <aid="acquiring-a-ssl-certificate"></a>
We’ll use Let’s Encrypt to get a free SSL certificate:
```bash
certbot --nginx -d example.com
```
This will obtain the certificate, automatically update `/etc/nginx/sites-available/mastodon` to use the new certificate, and reload nginx for the changes to take effect.
At this point you should be able to visit your domain in the browser and see the elephant hitting the computer screen error page. This is because we haven’t started the Mastodon process yet.
### Setting up systemd services <aid="setting-up-systemd-services"></a>
Copy the systemd service templates from the Mastodon directory:
Sometimes, for various reasons, you may want to migrate your Mastodon instance from one server to another. Fortunately this is not too difficult of a process, although it may result in some downtime.
{{<hintstyle="info">}}
This guide was written with Ubuntu Server in mind; your mileage may vary for other setups.
{{</hint>}}
## Basic steps <aid="basic-steps"></a>
1. Set up a new Mastodon server using the [Production Guide]({{< relref "install.md" >}}) \(however, don’t run `mastodon:setup`\).
2. Stop Mastodon on the old server \(e.g. `systemctl stop 'mastodon-*.service'`\).
3. Dump and load the Postgres database using the instructions below.
4. Copy the `system/` files using the instructions below. \(Note: if you’re using S3, you can skip this step.\)
5. Copy the `.env.production` file.
6. Run `RAILS_ENV=production bundle exec rails assets:precompile` to compile Mastodon
7. Run `RAILS_ENV=production ./bin/tootctl feeds build` to rebuild the home timelines for each user.
8. Start Mastodon on the new server.
9. Update your DNS settings to point to the new server.
10. Update or copy your Nginx configuration, re-run LetsEncrypt as necessary.
11. Enjoy your new server!
## Detailed steps <aid="detailed-steps"></a>
### What data needs to be migrated <aid="what-data-needs-to-be-migrated"></a>
At a high level, you’ll need to copy over the following:
* The `~/live/public/system` directory, which contains user-uploaded images and videos \(if using S3, you don’t need this\)
* The Postgres database \(using [pg\_dump](https://www.postgresql.org/docs/9.1/static/backup-dump.html)\)
* The `~/live/.env.production` file, which contains server config and secrets
Less crucially, you’ll probably also want to copy the following for convenience:
* The nginx config \(under `/etc/nginx/sites-available/default`\)
* The systemd config files \(`/etc/systemd/system/mastodon-*.service`\), which may contain your server tweaks and customizations
* The pgbouncer configuration under `/etc/pgbouncer` \(if you’re using it\)
### Dump and load Postgres <aid="dump-and-load-postgres"></a>
Instead of running `mastodon:setup`, we’re going to create an empty Postgres database using the `template0` database \(which is useful when restoring a Postgres dump, [as described in the pg\_dump documentation](https://www.postgresql.org/docs/9.1/static/backup-dump.html#BACKUP-DUMP-RESTORE)\).
Run this as the `mastodon` user on your old system:
```bash
pg_dump -Fc mastodon_production -f backup.dump
```
Copy the `backup.dump` file over, using `rsync` or `scp`. Then on the new system, create an empty database as the `mastodon` user:
```bash
createdb -T template0 mastodon_production
```
Then import it:
```bash
pg_restore -U mastodon -n public --no-owner --role=mastodon \
-d mastodon_production backup.dump
```
\(Note that if the username is not `mastodon` on the new server, you should change the `-U` AND `--role` values above. It’s okay if the username is different between the two servers.\)
### Copy files <aid="copy-files"></a>
This will probably take some time, and you’ll want to avoid re-copying unnecessarily, so using `rsync` is recommended. On your old machine, as the `mastodon` user, run:
You’ll want to re-run this if any of the files on the old server change.
You should also copy over the `.env.production` file, which contains secrets.
Optionally, you may copy over the nginx, systemd, and pgbouncer config files, or rewrite them from scratch.
### During migration <aid="during-migration"></a>
You can edit the `~/live/public/500.html` page on the old machine if you want to show a nice error message to let existing users know that a migration is in progress.
You’ll probably also want to set the DNS TTL to something small \(30-60 minutes\) about a day in advance, so that DNS can propagate quickly once you point it to the new IP address.
### After migrating <aid="after-migrating"></a>
You can check [whatsmydns.net](https://whatsmydns.net/) to see the progress of DNS propagation. To jumpstart the process, you can always edit your own `/etc/hosts` file to point to your new server so you can start playing around with it early.
Moderation in Mastodon is always applied locally, i.e. as seen from the particular server. An admin or moderator on one server cannot affect a user on another server, they can only affect the local copy on their own server.
### Disable login
### Disable login<aid="disable-login"></a>
A Mastodon account can be disabled. This prevents the user from doing anything with the account, but all of the content is still there untouched. This limitation is reversible, the account can be re-enabled at any time. This limitation is only available for local users on your server.
### Silence
### Silence<aid="silence"></a>
A Mastodon silence is synonymous with sandbox. A silenced account does not appear to users who are not already following it. All of the content is still there, and it can still be found via search, mentioned, and followed, but the content is invisible.
At this moment, silence does not affect federation. A locally silenced account is *not* silenced automatically on other servers.
At this moment, silence does not affect federation. A locally silenced account is _not_ silenced automatically on other servers.
This limitation is reversible, the account can be unsilenced at any time.
### Suspend
### Suspend<aid="suspend"></a>
A Mastodon suspension is synonymous with deletion. The account no longer appears in search, the profile page is gone, all of the posts, uploads, followers, and all other data is removed. This limitation is **irreversible**. While the account can be unsuspended, allowing the user to take control of it again, the old data is gone for good.
Because individually moderating a large volume of users from a misbehaving server can be exhausting, it is possible to pre-emptively moderate against all users from that particular server using a so-called **domain block**, which comes with several different levels of severity.
### Reject media
### Reject media<aid="reject-media"></a>
With this option active, no files from the server will be processed locally. That includes avatars, headers, emojis and media attachments.
### Silence
### Silence<aid="silence-1"></a>
Applies a silence to all past and future accounts from the server.
### Suspend
### Suspend<aid="suspend-1"></a>
Applies a suspension to all past and future accounts from the server. No content from the server will be stored locally except for usernames.
There are a few baseline measures for preventing spam in Mastodon:
- Signing up requires confirming an e-mail address
- Signing up is rate-limited by IP
* Signing up requires confirming an e-mail address
* Signing up is rate-limited by IP
However, dedicated spammers will get through that. The other measure you can employ is **e-mail domain blacklisting**. During sign up, Mastodon resolves the given e-mail address for an A or MX record, i.e. the IP address of the e-mail server, and checks that IP address against a dynamically stored blacklist.
### Blocking by e-mail server
### Blocking by e-mail server<aid="blocking-by-e-mail-server"></a>
Spammers will often use different e-mail domains so it looks like they are using a lot of different e-mail servers that would all be difficult to blacklist separately. However, sometimes all of those domains resolve to a single e-mail server IP. If you see a lot of spammers signing up at the same time, you can check for this, either using an online DNS lookup tool, or the Linux `dig` utility, e.g. `dig 1.2.3.4` will return all DNS records for that IP. If you notice the IP is the same for all domains, you can add it to the e-mail domain blacklist.
### Blocking by IP
### Blocking by IP<aid="blocking-by-ip"></a>
It is not possible to block visitors by IP address in Mastodon itself, and it is not a fool-proof strategy. IPs are sometimes shared by a lot of different people, and sometimes change hands. But it is possible to block visitors by IP address in Linux using a firewall. Here is an example using `iptables` and `ipset`:
@ -71,3 +71,4 @@ sudo iptables -I INPUT 1 -m set --match-set spambots src -j DROP
```
Be careful not to lock yourself out of your machine.
Mastodon supports full-text search when it ElasticSearch is available. Mastodon’s full-text search allows logged in users to find results from their own toots, their favourites, and their mentions. It deliberately does not allow searching for arbitrary strings in the entire database.
echo "deb https://artifacts.elastic.co/packages/6.x/apt stable main" | tee -a /etc/apt/sources.list.d/elastic-6.x.list
apt update
```
Now you can install ElasticSearch:
```bash
apt install elasticsearch
```
{{<hintstyle="warning">}}
**Security warning:** By default, ElasticSearch is supposed to bind to localhost only, i.e. be inaccessible from the outside network. You can check which address ElasticSearch binds to by looking at `network.host` within `/etc/elasticsearch/elasticsearch.yml`. Consider that anyone who can access ElasticSearch can access and modify any data within it, as there is no authentication layer. So it’s really important that the access is secured. Having a firewall that only exposes the 22, 80 and 443 ports is advisable, as outlined in the [main installation instructions](). If you have a multi-host setup, you must know how to secure internal traffic.
Edit `.env.production` to add the following variables:
```bash
ES_ENABLED=true
ES_HOST=localhost
ES_PORT=9200
```
If you have multiple Mastodon servers on the same machine, and you are planning to use the same ElasticSearch installation for all of them, make sure that all of them have unique `REDIS_NAMESPACE` in their configurations, to differentiate the indices. If you need to override the prefix of the ElasticSearch index, you can set `ES_PREFIX` directly.
After saving the new configuration, create the index in ElasticSearch with:
description: How to enable Mastodon's optional features
title: Hidden services
menu:
docs:
parent: administration
weight: 5
weight: 20
parent: admin-optional
---
## Full-text search
Mastodon can be served through Tor as an onion service. This will give you a \*.onion address that can only be used while connected to the Tor network.
Mastodon supports full-text search when it ElasticSearch is available. Mastodon's full-text search allows logged in users to find results from their own toots, their favourites, and their mentions. It deliberately does not allow searching for arbitrary strings in the entire database.
## Installing Tor
### Install ElasticSearch
First Tor’s Debian archive needs to be added to apt.
ElasticSearch requires a Java runtime. If you don't have Java already installed, do it now. Assuming you are logged in as `root`:
echo "deb https://artifacts.elastic.co/packages/6.x/apt stable main" | tee -a /etc/apt/sources.list.d/elastic-6.x.list
apt update
Now you can install ElasticSearch:
apt install elasticsearch
> **Security warning:** By default, ElasticSearch is supposed to bind to localhost only, i.e. be inaccessible from the outside network. You can check which address ElasticSearch binds to by looking at `network.host` within `/etc/elasticsearch/elasticsearch.yml`. Consider that anyone who can access ElasticSearch can access and modify any data within it, as there is no authentication layer. So it's really important that the access is secured. Having a firewall that only exposes the 22, 80 and 443 ports is advisable, as outlined in the [main installation instructions]({{< relref "installation.md" >}}). If you have a multi-host setup, you must know how to secure internal traffic.
To start ElasticSearch:
systemctl enable elasticsearch
systemctl start elasticsearch
### Setup Mastodon
Edit `.env.production` to add the following variables:
```bash
ES_ENABLED=true
ES_HOST=localhost
ES_PORT=9200
```
If you have multiple Mastodon servers on the same machine, and you are planning to use the same ElasticSearch installation for all of them, make sure that all of them have unique `REDIS_NAMESPACE` in their configurations, to differentiate the indices. If you need to override the prefix of the ElasticSearch index, you can set `ES_PREFIX` directly.
After saving the new configuration, create the index in ElasticSearch with:
Then restart Mastodon processes for the new configuration to take effect:
systemctl restart mastodon-sidekiq
systemctl reload mastodon-web
Now new statuses will be written to the ElasticSearch index. The last step is importing all of the old data as well. This might take a long while:
RAILS_ENV=production bundle exec rake chewy:sync
> **Compatibility note:** There is a known bug in Ruby 2.6.0 that prevents the above task from working. Other versions of Ruby, such as 2.6.1, are fine.
## Hidden services
Mastodon can be served through Tor as an onion service. This will give you a *.onion address that can only be used while connected to the Tor network.
### Installing Tor
First Tor's Debian archive needs to be added to apt.
```
```text
deb https://deb.torproject.org/torproject.org stretch main
deb-src https://deb.torproject.org/torproject.org stretch main
```
@ -86,11 +29,11 @@ Finally install the required packages.
apt install tor deb.torproject.org-keyring
```
### Configure Tor
## Configure Tor
Edit the file at `/etc/tor/torrc` and add the following configuration.
```bash
```text
HiddenServiceDir /var/lib/tor/hidden_service/
HiddenServiceVersion 3
HiddenServicePort 80 127.0.0.1:80
@ -104,13 +47,13 @@ sudo service tor restart
Your tor hostname can now be found at `/var/lib/tor/hidden_service/hostname`.
### Move your Mastodon configuration
## Move your Mastodon configuration
We will need to tell Nginx about your Mastodon configuration twice. To keep things [DRY](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself) we need to move the Mastodon configuration into its own file that can be referenced.
Create a new file at `/etc/nginx/snippets/mastodon.conf`. Put all of your Mastodon configuration parameters in this file with the exception of the `listen`, `server_name`, `include` and all of the SSL options. Your new file may look something like this.
```
```text
add_header Referrer-Policy "same-origin";
keepalive_timeout 70;
@ -129,7 +72,7 @@ In place of your old Mastodon configuration add an include directive to this new
Your Nginx configuration file will be left looking something like this.
```
```text
server {
listen 80;
server_name mastodon.myhosting.com;
@ -152,13 +95,13 @@ server {
}
```
### Serve Tor over http
## Serve Tor over http
While it may be tempting to serve your Tor version of Mastodon over https it is not a good idea for most people. See [this](https://blog.torproject.org/facebook-hidden-services-and-https-certs) blog post from the Tor Project about why https certificates do not add value. Since you cannot get an SSL cert for an onion domain, you will also be plagued with certificate errors when trying to use your Mastodon instance. A Tor developer has more recently spelled out the reasons why serving a Tor service over https is not beneficial for most use cases [here](https://matt.traudt.xyz/p/o44SnkW2.html).
The solution is to serve your Mastodon instance over http, but only for Tor. This can be added by pre-pending an additional configuration to your Nginx configuration.
Replace the long hash provided here with your Tor domain located in the file at `/var/lib/tor/hidden_service/hostname`.
Note that the onion hostname has been prefixed with "mastodon.". Your Tor address acts a wildcard domain. All subdomains will be routed through, and you can configure Nginx to respond to any subdomain you wish. If you do not wish to host any other services on your tor address you can omit the subdomain, or choose a different subdomain.
Note that the onion hostname has been prefixed with “mastodon.”. Your Tor address acts a wildcard domain. All subdomains will be routed through, and you can configure Nginx to respond to any subdomain you wish. If you do not wish to host any other services on your tor address you can omit the subdomain, or choose a different subdomain.
Here you can see the payoff of moving your mastodon configurations to a different file. Without this all of your configurations would have to be copied to both places. Any change to your configuration would have to be made both places.
@ -199,13 +142,9 @@ Restart your web server.
service nginx restart
```
### Gotchas
There are a few things you will need to be aware of. Certain redirects will push your users to https. They will have to manually replace the URL with http to continue.
Various resources, such as images, will still be offered through your regular non-Tor domain. How much of a problem this is will depend greatly on your user's level of caution.
## Gotchas
## Login via LDAP/PAM/CAS/SAML
There are a few things you will need to be aware of. Certain redirects will push your users to https. They will have to manually replace the URL with http to continue.
TODO
Various resources, such as images, will still be offered through your regular non-Tor domain. How much of a problem this is will depend greatly on your user’s level of caution.
If you are setting up a fresh machine, it is recommended that you secure it first. Assuming that you are running **Ubuntu 18.04**:
## Do not allow password-based SSH login \(keys only\)
First make sure you are actually logging in to the server using keys and not via a password, otherwise this will lock you out. Many hosting providers support uploading a public key and automatically set up key-based root login on new machines for you.
Edit `/etc/ssh/sshd_config` and find `PasswordAuthentication`. Make sure it’s uncommented and set to `no`. If you made any changes, restart sshd:
## Update system packages
```bash
apt update && apt upgrade -y
```
## Install fail2ban so it blocks repeated login attempts
Edit `/etc/fail2ban/jail.local` and put this inside:
```text
[DEFAULT]
destemail = your@email.here
sendername = Fail2Ban
[sshd]
enabled = true
port = 22
[sshd-ddos]
enabled = true
port = 22
```
Finally restart fail2ban:
```bash
systemctl restart fail2ban
```
## Install a firewall and only whitelist SSH, HTTP and HTTPS ports
First, install iptables-persistent. During installation it will ask you if you want to keep current rules–decline.
```bash
apt install -y iptables-persistent
```
Edit `/etc/iptables/rules.v4` and put this inside:
```text
*filter
# Allow all loopback (lo0) traffic and drop all traffic to 127/8 that doesn't use lo0
-A INPUT -i lo -j ACCEPT
-A INPUT ! -i lo -d 127.0.0.0/8 -j REJECT
# Accept all established inbound connections
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# Allow all outbound traffic - you can modify this to only allow certain traffic
-A OUTPUT -j ACCEPT
# Allow HTTP and HTTPS connections from anywhere (the normal ports for websites and SSL).
-A INPUT -p tcp --dport 80 -j ACCEPT
-A INPUT -p tcp --dport 443 -j ACCEPT
# Allow SSH connections
# The -dport number should be the same port number you set in sshd_config
-A INPUT -p tcp -m state --state NEW --dport 22 -j ACCEPT
# Reject all other inbound - default deny unless explicitly allowed policy
-A INPUT -j REJECT
-A FORWARD -j REJECT
COMMIT
```
With iptables-persistent, that configuration will be loaded at boot time. But since we are not rebooting right now, we need to load it manually for the first time: