This guide will cover installing Mastodon on Debian 13
Install necessary tools
apt update && \
apt install -y curl wget gnupg lsb-release ca-certificates git gcc make
Install Mastodon dependencies
apt install -y \
imagemagick ffmpeg libvips-tools libpq-dev libxslt1-dev file \
protobuf-compiler pkg-config autoconf bison build-essential \
libssl-dev libyaml-dev libreadline-dev zlib1g-dev libffi-dev \
libgdbm-dev nginx nodejs redis-server postgresql certbot \
python3-certbot-nginx libidn-dev libicu-dev libjemalloc-dev
Create a new system user that will be dedicated to running Mastodon
useradd -md /opt/mastodon -s /bin/bash mastodon
Use this guide.
Add the official PostfreSQL repository. We want the latest version, not what's in Debian's repo.
wget -O /usr/share/keyrings/postgresql.asc https://www.postgresql.org/media/keys/ACCC4CF8.asc
echo "deb [signed-by=/usr/share/keyrings/postgresql.asc] http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/postgresql.list
Install PSQL
apt update && \
apt install postgresql
Login to the DB
sudo -u postgres psql
Create new user and database
CREATE USER mastodon WITH PASSWORD '*****' CREATEDB;
\q
Enable corepack so that the correct version of yarn can be installed automatically
corepack enable
Login as the new mastodon user
su - mastodon
Use git to download the latest stable release of Mastodon:
git clone https://github.com/mastodon/mastodon.git live && cd live && \
git checkout $(git tag -l | grep '^v[0-9.]*$' | sort -V | tail -n 1)
Install rbenv to manage Ruby versions. It simplifies obtaining the correct versions and updating them when new releases are available.
git clone https://github.com/rbenv/rbenv.git ~/.rbenv && \
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc && \
echo 'eval "$(rbenv init -)"' >> ~/.bashrc && \
source ~/.bashrc && \
git clone https://github.com/rbenv/ruby-build.git "$(rbenv root)"/plugins/ruby-build
Install the correct Ruby version:
RUBY_CONFIGURE_OPTS=--with-jemalloc rbenv install
Install Ruby and JavaScript dependencies:
NOTE: The two bundle config commands are only needed the first time you’re installing dependencies. If you’re going to be updating or re-installing dependencies later, just bundle install will be enough.
bundle config deployment 'true' && \
bundle config without 'development test' && \
bundle install && \
yarn install
Run the interactive setup wizard to create a configuration file, run asset precompilation, and create the database schema
RAILS_ENV=production bin/rails mastodon:setup
This is what my wizard looked like:
Your instance is identified by its domain name. Changing it afterward will break things.
Domain name: mastodon.mydomain.com
Single user mode disables registrations and redirects the landing page to your public profile.
Do you want to enable single user mode? No
Are you using Docker to run Mastodon? no
PostgreSQL host: /var/run/postgresql
PostgreSQL port: 5432
Name of PostgreSQL database: mastodon_production
Name of PostgreSQL user: mastodon
Password of PostgreSQL user: ******
Database configuration works! 🎆
Redis host: localhost
Redis port: 6379
Redis password:
Redis configuration works! 🎆
Do you want to store uploaded files on the cloud? No
Do you want to send e-mails from localhost? No
SMTP server: smtp.mydomain.com
SMTP port: 587
SMTP username: mastodon@mydomain.com
SMTP password: ************
SMTP authentication: plain
SMTP OpenSSL verify mode: fail_if_no_peer_cert
Enable STARTTLS: always
E-mail address to send e-mails "from": Mastodon <mastodon@mydomain.com>
Send a test e-mail with this configuration right now? Yes
Send test e-mail to: <your-email-address>
Do you want Mastodon to periodically check for important updates and notify you? (Recommended) Yes
This configuration will be written to .env.production
Save configuration? Yes
Now that configuration is saved, the database schema must be loaded.
If the database already exists, this will erase its contents.
Prepare the database now? Yes
Running `RAILS_ENV=production rails db:setup` ...
I, [2026-01-26T20:23:45.925823 #17101] INFO -- : [dotenv] Loaded .env.production
Created database 'mastodon_production'
Done!
The final step is compiling CSS/JS assets.
This may take a while and consume a lot of RAM.
Compile the assets now? Yes
Running `RAILS_ENV=production rails assets:precompile` ...
...
_Bunch of output here_
...
Building with Vite ⚡️
vite v7.1.12 building for production...
transforming...
✓ 2024 modules transformed.
rendering chunks...
computing gzip size...
...
_Bunch of output here_
...
PWA v1.1.0
Building mastodon/service_worker/sw.js service worker ("es" format)...
vite v7.1.12 building for production...
transforming...
✓ 73 modules transformed.
rendering chunks...
computing gzip size...
../../public/packs/sw.mjs 189.10 kB │ gzip: 60.53 kB │ map: 1,065.94 kB
✓ built in 5.58s
Build with Vite complete: /opt/mastodon/live/public/packs
[baseline-browser-mapping] The data in this module is over two months old. To ensure accurate Baseline data, please update: `npm i baseline-browser-mapping@latest -D`
Done!
All done! You can now power on the Mastodon server 🐘
Do you want to create an admin user straight away? Yes
Username: admin
E-mail: admin@mydomain.com
INFO 2026-01-27T03:28:52.329Z pid=17070 tid=fli: Sidekiq 8.0.9 connecting to Redis with options {size: 10, pool_name: "internal", url: "redis://localhost:6379/0", driver: :hiredis}
I, [2026-01-26T20:28:52.441395 #17070] INFO -- : [ActiveJob] Enqueued ActionMailer::MailDeliveryJob (Job ID: 2ba19c80-2f0f-4348-9277-4e240dc27c26) to Sidekiq(mailers) at 2026-01-27 04:28:52 UTC with arguments: "UserMailer", "welcome", "deliver_now", {args: [#<GlobalID:0x00007f58958e50e0 @uri=#<URI::GID gid://mastodon/User/1>>]}
You can login with the password: ****************
You can change your password once you login.
Logout of the mastodon user, back into root
exit
Copy the included NGINX config file, link it to activate it, and remove NGINX's default site config
cp /opt/mastodon/live/dist/nginx.conf /etc/nginx/sites-available/mastondon.conf && \
ln -s /etc/nginx/sites-available/mastondon.conf /etc/nginx/sites-enabled/mastodon.conf && \
rm /etc/nginx/sites-enabled/default
Modify the NGINX config to your own environment. Change the following:
server_name to the hostname you're using. Make sure to modify both SSL and Non-SSL instances of the server.root to point to /opt/mastodon/live/public (as opposed to /home/)ssl_certificate and ssl_certificate_key accordingly - use ‘real’ certs for public facing, or self-signed for internal when behind a proxy. Or just modify the NGINX config as you see fit, the app won't know any different if you do it right…Change the Mastodon app files permissions to allow other users to traverse the mastodon user’s home directory, so that NGINX’s www-data user can access asset files
chmod o+x /home/mastodon
Restart NGINX to apply the site configuration
systemctl restart nginx.service && \
systemctl status nginx.service
Copy the systemd service templates from the Mastodon directory.
cp /opt/mastodon/live/dist/mastodon-*.service /etc/systemd/system/
Audit and modify any path's to match the installation location used in this guide (/opt/ instead of /home/)
Reload systemd and enable the new Mastodon services
systemctl daemon-reload && \
systemctl enable --now mastodon-web mastodon-sidekiq mastodon-streaming
See this page to configure NGINX to reverse proxy for Mastodon.