
This article provides a guide demonstrating how to install Pleroma on Ubuntu VPS.
What is Pleroma?
Pleroma is a free, open-source, self-hostable microblogging server that speaks the ActivityPub federation protocol—so your users can interact with people on other Fediverse platforms (e.g., Mastodon) while you keep full control over your server and policies.
It’s built in Elixir (on the Erlang/OTP “BEAM” VM) with PostgreSQL for storage, and is designed to be efficient enough for modest VPSes while still scaling on stronger hardware.
Pleroma ships as a backend plus a default web UI called Pleroma-FE (you can swap in other front-ends if you prefer). Many Mastodon-targeted mobile/desktop clients also work because Pleroma exposes endpoints compatible with the Mastodon client API.
It’s part of the broader Fediverse—a network of independently run servers that interoperate—licensed under AGPLv3.
Here’s a clean, reproducible way to deploy Pleroma on an Ubuntu VPS (22.04/24.04). We’ll use the official OTP release (prebuilt Elixir/Erlang bundle), PostgreSQL, Nginx, and Let’s Encrypt.
What you’ll set up
- Pleroma (backend + default Pleroma-FE)
- PostgreSQL database
- Nginx reverse proxy with HTTPS (Let’s Encrypt)
- Systemd service for auto-start on boot
- An admin account for first login
Prerequisites
- A fresh Ubuntu 22.04 or Ubuntu 24.04 VPS with root (or sudo) access
- A domain (or subdomain) pointed at your server’s public IP (A/AAAA records)
The Pleroma team recommends using their OTP releases on Debian/Ubuntu and outlines the exact packages we’ll install, plus optional media tools.
How to Install Pleroma on Ubuntu VPS
To install Pleroma on Ubuntu VPS, follow the steps below:
-
Update, set hostname, and basic tools
sudo apt update && sudo apt -y full-upgrade sudo apt -y install curl unzip postgresql postgresql-contrib nginx certbot libmagic-dev
Those are the core dependencies required by the OTP release (curl, unzip, ncurses, PostgreSQL, Nginx, certbot, libmagic).
(Recommended) Media/graphics helpers
sudo apt -y install imagemagick ffmpeg libimage-exiftool-perl
These enable image/video processing and EXIF handling.
-
Create the Pleroma system user and data dirs
sudo adduser --system --shell /bin/false --home /opt/pleroma pleroma sudo groupadd pleroma sudo usermod -aG pleroma pleroma # Uploads and static override directories sudo mkdir -p /var/lib/pleroma/{uploads,static} sudo chown -R pleroma:pleroma /var/lib/pleroma # Config directory sudo mkdir -p /etc/pleroma sudo chown -R pleroma:pleroma /etc/pleroma
These paths match the official OTP layout.
-
Download and install the OTP release
Determine the correct build “flavour” (architecture/libc) and fetch the ZIP:
# Detect flavour (outputs e.g., amd64) arch="$(uname -m)"; if [ "$arch" = "x86_64" ]; then arch="amd64"; \ elif [ "$arch" = "armv7l" ]; then arch="arm"; \ elif [ "$arch" = "aarch64" ]; then arch="arm64"; \ else echo "Unsupported arch: $arch" >&2; fi export FLAVOUR="$arch" # Download + unpack as the pleroma user sudo -Hu pleroma bash -lc " curl 'https://git.pleroma.social/api/v4/projects/2/jobs/artifacts/stable/download?job=$FLAVOUR' -o /tmp/pleroma.zip unzip /tmp/pleroma.zip -d /tmp/ mv /tmp/release/* /opt/pleroma rmdir /tmp/release rm /tmp/pleroma.zip "
The official instructions use this artifact endpoint and directory layout.
-
Generate configuration and initialize the database
Use Pleroma’s CLI to generate a config and DB setup SQL—then create the DB and run migrations:
# Create instance config + SQL (interactive prompts ask for your domain, email, etc.) sudo -Hu pleroma ./opt/pleroma/bin/pleroma_ctl instance gen \ --output /etc/pleroma/config.exs \ --output-psql /tmp/setup_db.psql # Create the PostgreSQL database and role from that SQL sudo -u postgres -s $SHELL -lc "psql -f /tmp/setup_db.psql" # Run database migrations sudo -Hu pleroma ./opt/pleroma/bin/pleroma_ctl migrate
Generation via
pleroma_ctl instance gen
and the subsequentpsql
+migrate
flow are the officially documented OTP steps.Tip: If you plan to keep most settings in the DB, answer Yes when the generator asks to store configuration in the database.
-
One-time verification (optional)
Start Pleroma in the foreground just to confirm the instance answers locally, then stop it:
sudo -Hu pleroma ./opt/pleroma/bin/pleroma daemon sleep 20 && curl -s http://localhost:4000/api/v1/instance | jq . sudo -Hu pleroma ./opt/pleroma/bin/pleroma stop
Official docs suggest this quick check before wiring Nginx.
-
Obtain a Let’s Encrypt certificate
Use the standalone method once (we’ll switch to webroot auto-renew later):
sudo systemctl stop nginx sudo certbot certonly --standalone --preferred-challenges http -d yourinstance.tld sudo systemctl start nginx
(Replace
yourinstance.tld
with your domain.) -
Configure Nginx reverse proxy
Copy the stock Pleroma Nginx template and enable it:
sudo cp /opt/pleroma/installation/pleroma.nginx /etc/nginx/sites-available/pleroma.conf sudo ln -s /etc/nginx/sites-available/pleroma.conf /etc/nginx/sites-enabled/pleroma.conf sudo nginx -t && sudo systemctl reload nginx
The template targets Pleroma on
localhost:4000
and includes ACME challenge location you can switch to webroot for renewals later. -
Install the systemd service and start Pleroma
sudo cp /opt/pleroma/installation/pleroma.service /etc/systemd/system/pleroma.service sudo systemctl daemon-reload sudo systemctl start pleroma sudo systemctl enable pleroma sudo systemctl status pleroma --no-pager
Service installation and
enable
/start
steps are exactly as documented for Debian/Ubuntu.At this point, visiting
https://yourinstance.tld
should load Pleroma-FE. -
Create your admin user
cd /opt/pleroma sudo su -s $SHELL -l pleroma -c "./bin/pleroma_ctl user new --admin"
You’ll be given a one-time login link to set the password. (You can manage users later with
pleroma_ctl user ...
commands.) -
Set up certificate auto-renew (webroot method)
Create the webroot and cron job that reloads Nginx after renewals:
sudo mkdir -p /var/lib/letsencrypt # Ensure your Nginx conf uses webroot for /.well-known/acme-challenge/ -> /var/lib/letsencrypt # Dry-run test: sudo certbot renew --cert-name yourinstance.tld \ --webroot -w /var/lib/letsencrypt/ \ --dry-run --post-hook 'systemctl reload nginx' # Daily cron echo '#!/bin/sh certbot renew --cert-name yourinstance.tld --webroot -w /var/lib/letsencrypt/ --post-hook "systemctl reload nginx" ' | sudo tee /etc/cron.daily/renew-pleroma-cert >/dev/null sudo chmod +x /etc/cron.daily/renew-pleroma-cert
This mirrors the official post-install renewal approach.
-
(Optional) Hardening & polish
- Serve media from a separate domain to reduce attack surface (the docs strongly recommend this). ([Fossies][1])
- Consider a firewall (
ufw allow 80,443/tcp
), system monitoring, and regular database/file backups.
-
Common admin commands
Run these as the
pleroma
user from/opt/pleroma
:# Create a user (non-admin) ./bin/pleroma_ctl user new # Grant / revoke admin ./bin/pleroma_ctl user set --admin ./bin/pleroma_ctl user set --no-admin # Reset a user's password (generates a reset link) ./bin/pleroma_ctl user reset_password # Database migrations (when updating) ./bin/pleroma_ctl migrate
Pleroma documents these user management and CLI tasks.
-
Updating Pleroma (later)
With OTP installs you generally:
# As pleroma user ./bin/pleroma_ctl update sudo systemctl stop pleroma ./bin/pleroma_ctl migrate sudo systemctl start pleroma
(Workflows like this are covered in various step-by-steps and mirror the official tool usage.)
Conclusion
You now know how to install Pleroma on Ubuntu VPS. You now have a production-friendly Pleroma instance behind Nginx with automatic TLS renewal, a systemd service, and an admin account.
[…] Users can follow and interact with accounts from other federated services like Mastodon, Pleroma, and […]