Loading Now

How to Install Mastodon on Ubuntu 24

How to Install Mastodon on Ubuntu 24

Mastodon is a decentralised social network that operates on an open-source framework belonging to the ActivityPub “fediverse.” Unlike typical social media platforms that are centralised, Mastodon allows you to set up your own instance while interacting with users from a multitude of other Servers. This guide will help you establish your own Mastodon instance on Ubuntu 24, granting you full authority over your community’s data management, moderation strategies, and available features. The installation process will be covered thoroughly, including common troubleshooting tips to ease your setup experience.

Understanding Mastodon’s Functionality

Mastodon is constructed with Ruby on Rails and has a React-based frontend, utilising PostgreSQL for data storage and Redis for caching and live functionalities. Its architecture includes various interacting components:

  • Web Process: Manages HTTP requests and delivers the web interface
  • Streaming API: Facilitates real-time updates via WebSockets
  • Sidekiq Workers: Handle background tasks such as federation, email dispatching, and media processing
  • PostgreSQL: Houses all application data including posts, account details, and connections
  • Redis: Responsible for caching, session storage, and managing job queues
  • Elasticsearch: Enables full-text search capabilities (optional but advised)

The system’s federation feature relies on ActivityPub, allowing your instance to interact with other Mastodon Servers and compatible platforms like PeerTube, Pixelfed, and Pleroma. When a user from your instance follows someone on another server, your instance subscribes to their updates.

System Requirements and Prerequisites

Before getting started with the installation, let’s outline the necessary requirements. Mastodon is relatively resource-intensive, especially if planning to federate with multiple instances.

Component Minimum Recommended Notes
RAM 2GB 4GB+ More required for larger instances
CPU 1 core 2+ cores Background processes benefit from additional cores
Storage 10GB 50GB+ Media files can accumulate rapidly
Bandwidth Unmetered Unmetered Federation generates considerable traffic

Additionally, you’ll need a domain name directed towards your server, and an email service for user communication is recommended. Let’s begin with a clean installation of Ubuntu 24.04.

Step-by-Step Installation Instructions

Step 1: Update System and Install Basic Dependencies

To start, make sure your system is up-to-date and install the essential packages:

sudo apt update && sudo apt upgrade -y
sudo apt install -y curl wget gnupg apt-transport-https lsb-release ca-certificates

Step 2: Install Node.js and Yarn

Mastodon needs Node.js 18+ and Yarn for frontend asset compilation:

# Install Node.js 20.x
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install -y nodejs

Install Yarn

curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add - echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list sudo apt update && sudo apt install -y yarn

Step 3: Install and Configure PostgreSQL

PostgreSQL is essential for storing your Mastodon data:

sudo apt install -y postgresql postgresql-contrib libpq-dev
sudo -u postgres createuser --createdb mastodon
sudo -u postgres psql

While in the PostgreSQL prompt, set up your database:

\password mastodon
CREATE DATABASE mastodon_production OWNER mastodon;
\q

Step 4: Install Redis

Redis will manage caching and help with background job queues:

sudo apt install -y redis-server
sudo systemctl enable redis-server
sudo systemctl start redis-server

Step 5: Install Ruby Using rbenv

You need a specific Ruby version for Mastodon, and using rbenv allows better version management:

# Create mastodon user
sudo adduser --disabled-login mastodon

Switch to mastodon user

sudo su - mastodon

Install rbenv

git clone https://github.com/rbenv/rbenv.git ~/.rbenv echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc echo 'eval "$(rbenv init -)"' >> ~/.bashrc exec bash

Install ruby-build

git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build

Install Ruby 3.2.2 (check Mastodon documentation for the current version)

rbenv install 3.2.2 rbenv global 3.2.2

Install bundler

gem install bundler --document

Step 6: Download and Configure Mastodon

Still logged in as the mastodon user:

cd ~
git clone https://github.com/mastodon/mastodon.git live
cd live
git checkout $(git tag -l | grep -v 'rc[0-9]*$' | sort -V | tail -n 1)

Install Ruby and Node.js dependencies:

bundle config deployment 'true'
bundle config without 'development test'
bundle install -j$(getconf _NPROCESSORS_ONLN)
yarn install --pure-lockfile

Step 7: Configure Mastodon

Generate the configuration file:

RAILS_ENV=production bundle exec rake mastodon:setup

This interactive setup will prompt you for:

  • Your domain name
  • Database connection particulars
  • Redis connection particulars
  • Email settings (SMTP configuration)
  • File storage options (local or cloud)

The setup process generates a .env.production file containing your settings. Here’s what a standard configuration appears like:

# Domain and URLs
LOCAL_DOMAIN=your-domain.com
WEB_DOMAIN=your-domain.com

Database

DB_HOST=localhost DB_PORT=5432 DB_NAME=mastodon_production DB_USER=mastodon DB_PASS=your_password

Redis

REDIS_HOST=localhost REDIS_PORT=6379

SMTP

SMTP_SERVER=smtp.your-provider.com SMTP_PORT=587 [email protected] SMTP_PASSWORD=your_smtp_password [email protected]

Security keys (generated by setup)

SECRET_KEY_BASE=very_long_random_string OTP_SECRET=another_long_random_string

Step 8: Set Up Systemd Services

Return to your standard user account, then create systemd service files. Start with the web service:

sudo nano /etc/systemd/system/mastodon-web.service
[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 ExecReload=/bin/kill -SIGUSR1 $MAINPID TimeoutSec=15 Restart=always RestartSec=10

[Install] WantedBy=multi-user.target

Create the streaming service:

sudo nano /etc/systemd/system/mastodon-streaming.service
[Unit]
Description=mastodon-streaming
After=network.target

[Service] Type=simple User=mastodon WorkingDirectory=/home/mastodon/live Environment="RAILS_ENV=production" Environment="PORT=4000" ExecStart=/usr/bin/node ./streaming TimeoutSec=15 Restart=always RestartSec=10

[Install] WantedBy=multi-user.target

Establish the Sidekiq service for background processes:

sudo nano /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=25" ExecStart=/home/mastodon/.rbenv/shims/bundle exec sidekiq -c 25 TimeoutSec=15 Restart=always RestartSec=10

[Install] WantedBy=multi-user.target

Step 9: Configure Nginx

Install Nginx and set up the reverse proxy:

sudo apt install -y nginx
sudo nano /etc/nginx/sites-available/mastodon

Here’s a production-ready Nginx configuration:

map $http_upgrade $connection_upgrade {
    default upgrade;
    '' close;
}

upstream backend { server 127.0.0.1:3000 fail_timeout=0; }

upstream streaming { server 127.0.0.1:4000 fail_timeout=0; }

proxy_cache_path /var/cache/nginx/mastodon clean_time=30d levels=2 keys_zone=mastodon:10m max_size=1g;

server { listen 80; listen [::]:80; server_name your-domain.com; root /home/mastodon/live/public; location /.well-known/acme-challenge/ { allow all; } location / { return 301 https://$host$request_uri; } }

server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name your-domain.com;

ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!MEDIUM:!LOW:!aNULL:!NULL:!SHA;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;

# SSL certificates (configure after obtaining Let's Encrypt certs)
ssl_certificate     /etc/letsencrypt/live/your-domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;

keepalive_timeout    70;
sendfile             on;
client_max_body_size 99m;

root /home/mastodon/live/public;

gzip on;
gzip_disable "msie6";
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types
    text/plain
    text/css
    text/xml
    text/javascript
    application/json
    application/javascript
    application/xml+rss
    application/atom+xml
    image/svg+xml;

location / {
    try_files $uri @proxy;
}

location ~ ^/(emoji|packs|system/accounts/avatars|system/media_attachments/files) {
    add_header Cache-Control "public, max-age=31536000, immutable";
    add_header Strict-Transport-Security "max-age=31536000" always;
    try_files $uri @proxy;
}

location /sw.js {
    add_header Cache-Control "public, max-age=604800, must-revalidate";
    add_header Strict-Transport-Security "max-age=31536000" always;
    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 $scheme;
    proxy_set_header Proxy "";
    proxy_pass_header server;

    proxy_pass http://backend;
    proxy_buffering on;
    proxy_redirect off;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;

    proxy_cache mastodon;
    proxy_cache_valid 200 7d;
    proxy_cache_valid 410 24h;
    proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
    add_header X-Cached $upstream_cache_status;

    tcp_delay 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 $scheme;
    proxy_set_header Proxy "";

    proxy_pass http://streaming;
    proxy_buffering off;
    proxy_redirect off;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;

    tcp_delay on;
}

error_page 500 501 502 503 504 /500.html;

}

Enable the site and create the cache directory:

sudo ln -s /etc/nginx/sites-available/mastodon /etc/nginx/sites-enabled/
sudo mkdir -p /var/cache/nginx/mastodon
sudo chown www-data:www-data /var/cache/nginx/mastodon
sudo nginx -t

Step 10: Set Up SSL Certificates

For Let’s Encrypt SSL certificates, install Certbot:

sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d your-domain.com

Configure automatic renewal:

sudo crontab -e
# Add this line:
0 12 * * * /usr/bin/certbot renew --quiet

Step 11: Activate All Services

Enable and launch all Mastodon services:

sudo systemctl daemon-reload
sudo systemctl enable mastodon-web mastodon-streaming mastodon-sidekiq nginx
sudo systemctl start mastodon-web mastodon-streaming mastodon-sidekiq nginx

Verify that everything is operational:

sudo systemctl status mastodon-web mastodon-streaming mastodon-sidekiq nginx

Creating Your First Admin Account

To utilise your instance, you need to create an admin account:

sudo su - mastodon
cd live
RAILS_ENV=production bin/tootctl accounts create yourusername --email [email protected] --confirmed --role Owner

This will generate a temporary password, which can be changed through the web interface once you log in.

Common Problems and Solutions

Memory-Related Issues

For smaller VPS setups, memory issues may arise. Here are a few optimisation tips:

# Lower Sidekiq concurrency in .env.production
DB_POOL=5
# Update the systemd service accordingly

You might also consider adding swap space:

sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

Federation-Related Issues

If federation encounters issues, check for common pitfalls:

  • Ensure your domain’s SSL certificate is valid and reachable
  • Confirm that the streaming service is operational and reachable
  • Inspect firewall settings for outbound HTTPS permissions
  • Look at Sidekiq logs for failures in federation jobs
# Verify federation status
sudo su - mastodon
cd live
RAILS_ENV=production bin/tootctl self-destruct --dry-run

Monitoring Performance

Keep track of your instance’s performance with these commands:

# Service status checks
systemctl status mastodon-*

Resource usage monitoring

htop

Database performance analysis

sudo -u postgres psql mastodon_production -c "SELECT schemaname,tablename,attname,n_distinct,correlation FROM pg_stats WHERE tablename='statuses';"

Evaluate Sidekiq queues

sudo su - mastodon cd live RAILS_ENV=production bin/tootctl statuses count

Mastodon in Comparison with Other Platforms

Here’s how Mastodon compares to other fediverse platforms:

Platform Language Resource Use Features Ideal For
Mastodon Ruby/Rails High Feature-rich, similar to Twitter Large communities
Pleroma Elixir Low Lightweight and customisable Smaller instances
Misskey Node.js Medium Distinctive UI, interactions Creative communities
GoToSocial Go Very Low API-focused Personal instances

Best Practices and Security Tips

Enhancing Security

Consider implementing these security measures for better protection:

# Activate the firewall
sudo ufw allow ssh
sudo ufw allow http
sudo ufw allow https
sudo ufw enable

Install and set up fail2ban

sudo apt install -y fail2ban sudo systemctl enable fail2ban

Create a fail2ban configuration for Mastodon:

sudo nano /etc/fail2ban/jail.local
[mastodon]
enabled = true
port = http,https
filter = mastodon
logpath = /home/mastodon/live/log/production.log
maxretry = 5
bantime = 3600

Backup Strategy

Execute regular backups with the following script:

#!/bin/bash
# backup-mastodon.sh
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="/home/backups/mastodon"

Database backup

sudo -u postgres pg_dump mastodon_production > $BACKUPDIR/db$DATE.sql

Media files backup

tar -czf $BACKUPDIR/media$DATE.tar.gz /home/mastodon/live/public/system

Configuration backup

cp /home/mastodon/live/.env.production $BACKUPDIR/env$DATE.backup

Cleanup old backups (retain 7 days)

find $BACKUP_DIR -name ".sql" -mtime +7 -delete find $BACKUP_DIR -name ".tar.gz" -mtime +7 -delete

Monitoring and Maintenance

Establish log rotation and monitoring:

# Add to /etc/logrotate.d/mastodon
/home/mastodon/live/log/*.log {
    daily
    missingok
    rotate 30
    compress
    delaycompress
    notifempty
    copytruncate
    su mastodon mastodon
}

Real-World Use Cases and Performance Data

From actual deployments, here’s what performance looks like:

  • Small instance (10-50 users): 2GB RAM, 1 CPU core, ~500MB daily federation traffic
  • Medium instance (100-500 users): 4GB RAM, 2 CPU cores, ~2GB daily federation traffic
  • Large instance (1000+ users): 8GB+ RAM, 4+ CPU cores, ~10GB+ daily federation traffic

A typical small instance federating with major instances like mastodon.social may observe:

  • ~50,000 federation jobs daily
  • Database expansion by ~100MB monthly
  • Media storage increasing by ~1GB each month (with media retention policies)

Performance tuning becomes vital as your instance grows. Consider using external media storage, such as S3-compatible services, and implementing CDN caching for static files.

For comprehensive documentation and updates, refer to the Mastodon documentation and the GitHub repository. The community maintains additional resources at Fediverse.info for a broader ecosystem overview.

Your Mastodon instance now should be operational and ready to connect with the wider fediverse. Running a social media platform is an ongoing responsibility that involves regular updates, moderation, and community involvement. Begin small, master the processes, and expand as your community evolves.



This article uses information and resources from various online platforms. We recognise and appreciate the contributions of all original authors, publishers, and sites. Efforts have been made to credit the source material properly; any unintentional oversights or omissions shall not constitute copyright infringement. All trademarks, logos, and images mentioned are the property of their respective owners. If you believe any content in this article infringes upon your copyright, please contact us for review and prompt action.

This article is for informational and educational purposes only and does not infringe on the rights of copyright holders. Should any copyrighted material be utilized without proper attribution or in violation of copyright law, this is unintentional and will be rectified promptly upon notification. Please note that republishing, redistribution, or reproduction of any part or all of the content in any form is forbidden without express written consent from the author and website owner. For permissions or further inquiries, please reach out to us.