Ma
Developer Tools Azure

Mastodon on Ubuntu 24.04 on Azure User Guide

| Product: Mastodon on Ubuntu 24.04 LTS on Azure

Overview

Mastodon is the reference open-source server for the fediverse: a self-hosted, federated social network that speaks ActivityPub, so your instance can interoperate with thousands of others. It is a Ruby on Rails application served by Puma, with a Node.js streaming API for real-time timelines, Sidekiq background workers, PostgreSQL for storage and Redis for caching and queues. The cloudimg image installs Mastodon 4.6.3 the official "install from source" way (Ruby 4.0.5 via rbenv, Node.js 24, PostgreSQL 16, Redis and nginx), keeps the database and uploaded media on a dedicated Azure data disk, and generates every cryptographic secret plus the initial Owner account uniquely on the first boot of each VM. Backed by 24/7 cloudimg support.

What is included:

  • Mastodon 4.6.3 installed from source (AGPL-3.0), built on Ruby 4.0.5, Node.js 24 and yarn 4.16
  • Three systemd services running as the unprivileged mastodon user, loopback only: mastodon-web (Puma), mastodon-streaming@4000 (Node streaming API) and mastodon-sidekiq (workers)
  • PostgreSQL 16 and Redis bound to loopback; nginx fronting the app with an unauthenticated :80/healthz and the full web UI on :443
  • All per-VM secrets generated on first boot: SECRET_KEY_BASE, OTP_SECRET, the VAPID keypair, the ActiveRecord-encryption keys and the PostgreSQL password - none are baked into the image
  • A per-VM Owner account created on first boot (via tootctl) and recorded in a root-only credentials file, plus a per-VM self-signed TLS certificate
  • A dedicated 20 GiB Azure data disk at /var/lib/mastodon-data holding the PostgreSQL cluster and public/system media, captured into the image and re-provisioned with every VM
  • 24/7 cloudimg support

The Mastodon web interface showing the home timeline served by the VM

Prerequisites

An active Azure subscription, an SSH key pair, and a VNet plus subnet in the target region. Standard_D4s_v5 (4 vCPU / 16 GiB RAM) is the recommended size - Mastodon runs five services plus PostgreSQL and Redis, so do not go below 8 GiB of RAM. NSG inbound: allow 22/tcp from your management network, and 80/tcp + 443/tcp for the web interface. The appliance serves HTTPS on port 443 with a per-VM self-signed certificate so the UI works immediately; for production you install your own certificate and domain (see "Set your own domain").

Step 1 - Deploy from the Azure Marketplace

Sign in to the Azure Portal, choose Create a resource, search the Marketplace for Mastodon by cloudimg, and select Create. On Basics pick your subscription, resource group, region and size (Standard_D4s_v5); under Administrator account choose SSH public key and paste your key; under Inbound port rules allow SSH (22), HTTP (80) and HTTPS (443). Review the dedicated data disk on the Disks tab, then Review + create -> Create.

Step 2 - Deploy from the Azure CLI

az vm create \
  --resource-group <your-rg> \
  --name mastodon \
  --image <marketplace-image-urn> \
  --size Standard_D4s_v5 \
  --admin-username azureuser \
  --ssh-key-values ~/.ssh/id_ed25519.pub \
  --vnet-name <your-vnet> --subnet <your-subnet> \
  --public-ip-sku Standard

az vm open-port --resource-group <your-rg> --name mastodon --port 80 --priority 1010
az vm open-port --resource-group <your-rg> --name mastodon --port 443 --priority 1011

Step 3 - Connect to your VM

ssh azureuser@<vm-public-ip>

Step 4 - Confirm the services are running

On first boot the image generates the per-VM secrets, sets LOCAL_DOMAIN to the VM public IP, creates the Owner account and starts the stack. Confirm all six services are active and bound to loopback:

systemctl is-active postgresql redis-server nginx mastodon-web mastodon-sidekiq mastodon-streaming@4000
sudo ss -tlnp | grep -E ':80 |:443 |:3000 |:4000 |:5432 |:6379 '

Mastodon services active and the loopback listeners for Puma, streaming, PostgreSQL, Redis and nginx

Step 5 - Check the health endpoints

The unauthenticated :80/healthz returns 200 for load-balancer probes, the app exposes /health, and the streaming API has its own health endpoint:

curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1/healthz
curl -s http://127.0.0.1:3000/health
curl -sk https://127.0.0.1/api/v1/streaming/health

Mastodon component versions and the health endpoints returning OK

Step 6 - Retrieve the per-VM Owner credentials

The Owner account and a strong password are generated on first boot and written to a root-only file. The .env.production secrets are unique to this VM and never leave it:

sudo cat /root/mastodon-credentials.txt

The file records the web URL, the Owner e-mail and password. The PostgreSQL cluster and media live on the dedicated data disk:

findmnt -no SOURCE,TARGET,FSTYPE /var/lib/mastodon-data

The per-VM Mastodon credentials file (password masked) and the data disk holding PostgreSQL and media

Step 7 - Sign in to the web interface

Browse to https://<vm-public-ip>/ and sign in with the Owner e-mail and password from the credentials file. Your browser will warn about the self-signed certificate on first visit - that is expected until you install your own certificate. The home timeline, the compose box and your profile are the standard Mastodon web UI.

The Mastodon compose box with a draft post alongside the home timeline

The Owner's public profile showing account details and posts

Step 8 - Set your own domain (do this BEFORE creating content)

This is the most important step. Mastodon bakes LOCAL_DOMAIN into accounts, posts and federation identifiers at setup and cannot cleanly change it later. The appliance boots with LOCAL_DOMAIN set to the VM IP purely as an evaluation placeholder. Before you create real accounts or content, and before you federate, set your own domain:

  1. Point a DNS record (for example social.example.com) at the VM public IP.
  2. Edit /home/mastodon/live/.env.production and set LOCAL_DOMAIN and WEB_DOMAIN to your domain.
  3. Install a real TLS certificate (for example with certbot) and reference it in /etc/nginx/sites-available/mastodon, then reload nginx.
  4. Add your SMTP server settings (SMTP_SERVER, SMTP_PORT, SMTP_LOGIN, SMTP_PASSWORD, SMTP_FROM_ADDRESS) so users receive confirmation and notification e-mails.
  5. Restart the services so the new configuration takes effect:
sudo systemctl restart mastodon-web mastodon-sidekiq mastodon-streaming@4000 nginx

Federation with the fediverse requires a real domain and a valid TLS certificate - a bare IP is only suitable for evaluating the software.

Step 9 - Administration dashboard

As the Owner, open Preferences -> Administration to reach the server dashboard: user and content moderation, server rules, custom emoji, federation controls and instance settings.

The Mastodon administration dashboard with server metrics and moderation queues

Maintenance and production notes

  • Object storage and disk size: a real instance accumulates a large volume of federated media. The 20 GiB data disk is sized for evaluation - for production, attach a larger disk and configure object storage (S3-compatible) via the S3_* variables in .env.production.
  • tootctl: the tootctl command (run as the mastodon user from /home/mastodon/live) manages accounts, media, search indexing and maintenance tasks.
  • Backups: back up the PostgreSQL database and /home/mastodon/live/public/system (or your object storage bucket) regularly.
  • Updates: apply OS security updates with sudo apt update && sudo apt upgrade. Mastodon version upgrades follow the upstream release notes.
  • Security: the appliance ships no default credentials - every secret and the Owner account are generated uniquely per VM on first boot. Keep /root/mastodon-credentials.txt protected and rotate the Owner password after first sign-in.

Mastodon is free software licensed under the AGPL-3.0. This image is produced by cloudimg and is not affiliated with, sponsored by, or endorsed by Mastodon gGmbH. "Mastodon" is a trademark of Mastodon gGmbH.