How to host your own Mastodon server using rootless Podman containers
So, you’ve decided to host Mastodon yourself. If you are reading this post, you obviously know what Mastodon is, so I will not waste your time in explaining the things you already know. What I would like to point out, is something that I wish I knew myself before starting on this self-hosted route.
Why should you NOT host Mastodon yourself?
Don’t get me wrong, I love that people are joining Mastodon. I love that decentralized social network is now mainstream. But, there is a difference between joining Mastodon, and hosting a Mastodon instance. If you want to experience Mastodon like any other social networks, just join any well-reputed server that already exists, and you’ll be on your way. But, if you insist on having complete control over your social network presence, and do not want to leave anything up to somebody else’s opinions, including the length of your posts or display name, whether you federate with some specific server, emoji reactions, etc., only then you might want to host your own instance. Since you already considered the advantages of building your own Mastodon instance, let’s take a look at a few downsides to hosting your own.
Moderation headaches:
Even if you plan on running a single-user instance, which my own old personal instance was, you gotta clean up your public feed. This applies even if you don’t subscribe to any relays. And please don’t take moderation lightly. I found and reported (to the FBI) an instance solely used for sharing CSAM (although I was subscribed to two relays at that time, and this was well before Mastodon put in much stronger protection) when one of their members’ account showed up in my federated feed.
Difficult broader outreach:
Unless you plan on hosting a multi-user server serving hundreds of users, you might find broader outreach to be difficult. It is especially difficult for single-user instances, unless you have web notoriety and a lot of people follow you. Although, recently, Mastodon made a lot of changes to help you discover new people. Relays also exist to give your instance a broader outreach without anyone specifically following you.
Storage concerns:
Running Mastodon takes a significant amount of storage space. You either need to look for a cheap S3 compatible object storage service, or be willing to host it in a server you run at your home with a big RAID array. Just as an example, my one year old single-user Mastodon instance uses about 670 GB of storage in my RAID array as of the time of writing this post (keep in mind that I was subscribed to two relays at the time, one quite big, and the other medium sized). If you want to scale, you definitely need S3 compatible object storage in the cloud.
Understood, but how do you host your own instance?
Okay, so you’re adamant about hosting your own Mastodon instance. In that case, let’s look at Podman containers. Containers make everything easier. Whoever made the comic about “it works on my computer”, clearly underestimated the proliferation of containers in the server space. So, to make things easier, we’ll look at how to use Podman rootless containers to host our new Mastodon instance.
Choosing your “version” of Mastodon:
Since Mastodon is open-source, we can choose from multiple different forks of it. In this guide, I will talk about vanilla Mastodon (what mastodon.social runs), Mastodon glitch-soc version (what infosec.exchange, and a bunch of other big servers run), and TheEssem’s fork of glitch-soc (what wetdry.world, and a few other servers including my own run). Let’s run down the main differences of the three.
Vanilla Mastodon
This is the “official” version of Mastodon, and to no one’s surprise, this is also the most widely used version of Mastodon. Most major instances run vanilla Mastodon, including the original server: mastodon.social. With vanilla Mastodon, you will always have a 500 character limit for your toots, 30 character limit for your display name, be stuck to plain text toots, etc. These are the limitations of any other microblogging services that people are used to and are fine with. This also gets the quickest security patches than any other versions/forks, so it is the safest one to use. If you want to use this version, pull the official container image while running your Podman containers:
ghcr.io/mastodon/mastodon:latest
Mastodon glitch-soc
This is a major fork of vanilla Mastodon maintained by an amazing group of volunteers. A lot of major instances like infosec.exchange run this fork of Mastodon. This comes with a lot more customizability, like changing character limits for your toots, display name, bio, publish toots in markdown format, etc. My old personal instance ran this fork of Mastodon. This gets the second quickest security patches, and so, is relatively safe to use. If you want to use this fork, pull this container image while running your Podman containers:
ghcr.io/glitch-soc/mastodon:latest
Chuckya fork of Mastodon (by The Essem)
This is a fork of the glitch-soc fork of Mastodon. This is maintained by one dedicated volunteer, TheEssem on Github. This retains all the customizability of glitch-soc, and adds the ability to react with emojis. Very few instances run this fork, including TheEssem’s wetdry.world, and my new personal instance (meghadeep.social). As much fun as emoji reactions are, please keep in mind that this fork is maintained by one single person for free, so security patches entirely depend on their availability. And, this patch will be merged with glitch-soc soon, so if you can wait for a little while to get emoji reactions, you should stick to the glitch-soc version. If you want to use this fork, pull this container image while running your Podman containers (please note these images are built by me, and pushed manually, so this will take even more time to get an update):
docker.io/meghadeep/mastodon:chuckya-latest
For the purposes of this guide, I will assume that you are using the Chuckya fork (by The Essem on GitHub), since that’s what I personally use.
Preparing your machine:
First, we have to create a few directories where we want to store our data. If you want to use an S3 compatible object storage, you can create these directories anywhere you want, but if you simply wish to use the Linux filesystem to store your Mastodon data, I suggest you create these directories in a partition with plenty of storage space. My old instance had these directories in my RAID array, while my new instance with an S3 compatible object storage has these right in my home partition.
mkdir /path/to/main_directory
Change the path to your liking.
Now we will create the app directory and db directory inside the main directory.
mkdir /path/to/main_directory/db
mkdir /path/to/main_directory/app
Customizing environment:
Now that the directories are set up, we’ll create the environment file that we want our Mastodon containers to use. This would depend on which “version” of Mastodon you want to use. Please read through the whole environment file to change the required few. I have already put in some defaults that I use in my new personal Mastodon instance, so, you should be fine with only adding the few environment variables that I have not added in this example environment file.
# This is a sample configuration file. You can generate your configuration
# with the `rake mastodon:setup` interactive setup wizard, but to customize
# your setup even further, you'll need to edit it manually. This sample does
# not demonstrate all available configuration options. Please look at
# https://docs.joinmastodon.org/admin/config/ for the full documentation.
# Note that this file accepts slightly different syntax depending on whether
# you are using `docker-compose` or not. In particular, if you use
# `docker-compose`, the value of each declared variable will be taken verbatim,
# including surrounding quotes.
# See: https://github.com/mastodon/mastodon/issues/16895
# Federation (REQUIRES CHANGES)
# ----------
# This identifies your server and cannot be changed safely later
# ----------
LOCAL_DOMAIN=
# Use this only if you need to run mastodon on a different domain than the one used for federation.
# You can read more about this option on https://docs.joinmastodon.org/admin/config/#web-domain
# DO *NOT* USE THIS UNLESS YOU KNOW *EXACTLY* WHAT YOU ARE DOING.
# WEB_DOMAIN=mastodon.example.com
# Use this if you want to have several aliases handler@example1.com
# handler@example2.com etc. for the same user. LOCAL_DOMAIN should not
# be added. Comma separated values
# ALTERNATE_DOMAINS=example1.com,example2.com
# Use HTTP proxy for outgoing request (optional)
# http_proxy=http://gateway.local:8118
# Access control for hidden service.
# ALLOW_ACCESS_TO_HIDDEN_SERVICE=true
# Authorized fetch mode (optional)
# Require remote servers to authentify when fetching toots, see
# https://docs.joinmastodon.org/admin/config/#authorized_fetch
AUTHORIZED_FETCH=true
# Limited federation mode (optional)
# Only allow federation with specific domains, see
# https://docs.joinmastodon.org/admin/config/#whitelist_mode
# LIMITED_FEDERATION_MODE=true
# Redis (NO CHANGE)
# -----
REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_NAMESPACE=mastodon
# PostgreSQL (REQUIRES CHANGES)
# ----------
DB_HOST=localhost
DB_USER=postgres
DB_NAME=mastodon_production
DB_PASS=postgres
DB_PORT=5432
# Generate with `podman run --rm meghadeep/mastodon:chuckya-latest bin/rails db:encryption:init`
ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY=
ACTIVE_RECORD_ENCRYPTION_DETERMINISTIC_KEY=
ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT=
# Elasticsearch (optional)
# ------------------------
# ES_ENABLED=true
# ES_HOST=
# ES_PORT=9200
# ES_PRESET=
# Secrets (REQUIRES CHANGES)
# -------
# Generate each with the `RAILS_ENV=production podman run --rm meghadeep/mastodon:chuckya-latest bundle exec rails secret`
# -------
SECRET_KEY_BASE=
OTP_SECRET=
# Web Push (REQUIRES CHANGES)
# --------
# Generate with `podman run --rm meghadeep/mastodon:chuckya-latest rails mastodon:webpush:generate_vapid_key` (first is the private key, second is the public one)
# You should only generate this once per instance. If you later decide to change it, all push subscription will
# be invalidated, requiring the users to access the website again to resubscribe.
# --------
VAPID_PRIVATE_KEY=
VAPID_PUBLIC_KEY=
# Registrations (OPTIONAL CHANGES)
# -------------
# Single user mode will disable registrations and redirect frontpage to the first profile
# SINGLE_USER_MODE=true
# Prevent registrations with following e-mail domains
# EMAIL_DOMAIN_DENYLIST=example1.com|example2.de|etc
# Only allow registrations with the following e-mail domains
# EMAIL_DOMAIN_ALLOWLIST=
#TODO move this
# Optionally change default language
# DEFAULT_LOCALE=de
# Sending mail (REQUIRES CHANGES)
# ------------
SMTP_SERVER=
SMTP_PORT=
SMTP_LOGIN=
SMTP_PASSWORD=
SMTP_FROM_ADDRESS=
# File storage (OPTIONAL CHANGES)
# -----------------------
# The attachment host must allow cross origin request from WEB_DOMAIN or
# LOCAL_DOMAIN if WEB_DOMAIN is not set. For example, the server may have the
# following header field:
# Access-Control-Allow-Origin: https://192.168.1.123:9000/
# -----------------------
# S3_ENABLED=true
# S3_ENDPOINT=
# S3_HOSTNAME=
# S3_BUCKET=
# AWS_ACCESS_KEY_ID=
# AWS_SECRET_ACCESS_KEY=
# S3_PROTOCOL=https
# S3_SIGNATURE_VERSION=v4
# IP and session retention
# -----------------------
# Make sure to modify the scheduling of ip_cleanup_scheduler in config/sidekiq.yml
# to be less than daily if you lower IP_RETENTION_PERIOD below two days (172800).
# -----------------------
IP_RETENTION_PERIOD=31556952
SESSION_RETENTION_PERIOD=31556952
# ------------------------------------
# -------- GLITCH-SOC ONLY ----------
# ------------------------------------
# Swift (optional)
# The attachment host must allow cross origin request - see the description
# above.
# SWIFT_ENABLED=true
# SWIFT_USERNAME=
# For Keystone V3, the value for SWIFT_TENANT should be the project name
# SWIFT_TENANT=
# SWIFT_PASSWORD=
# Some OpenStack V3 providers require PROJECT_ID (optional)
# SWIFT_PROJECT_ID=
# Keystone V2 and V3 URLs are supported. Use a V3 URL if possible to avoid
# issues with token rate-limiting during high load.
# SWIFT_AUTH_URL=
# SWIFT_CONTAINER=
# SWIFT_OBJECT_URL=
# SWIFT_REGION=
# Defaults to 'default'
# SWIFT_DOMAIN_NAME=
# Defaults to 60 seconds. Set to 0 to disable
# SWIFT_CACHE_TTL=
# Optional asset host for multi-server setups
# The asset host must allow cross origin request from WEB_DOMAIN or LOCAL_DOMAIN
# if WEB_DOMAIN is not set. For example, the server may have the
# following header field:
# Access-Control-Allow-Origin: https://example.com/
# CDN_HOST=https://assets.example.com
# Optional list of hosts that are allowed to serve media for your instance
# This is useful if you include external media in your custom CSS or about page,
# or if your data storage provider makes use of redirects to other domains.
# EXTRA_DATA_HOSTS=https://data.example1.com|https://data.example2.com
# Optional alias for S3 (e.g. to serve files on a custom domain, possibly using Cloudfront or Cloudflare)
# S3_ALIAS_HOST=
# Streaming API integration
# STREAMING_API_BASE_URL=
# External authentication (optional)
# ----------------------------------
# LDAP authentication (optional)
# LDAP_ENABLED=true
# LDAP_HOST=localhost
# LDAP_PORT=389
# LDAP_METHOD=simple_tls
# LDAP_BASE=
# LDAP_BIND_DN=
# LDAP_PASSWORD=
# LDAP_UID=cn
# LDAP_MAIL=mail
# LDAP_SEARCH_FILTER=(|(%{uid}=%{email})(%{mail}=%{email}))
# LDAP_UID_CONVERSION_ENABLED=true
# LDAP_UID_CONVERSION_SEARCH=., -
# LDAP_UID_CONVERSION_REPLACE=_
# PAM authentication (optional)
# PAM authentication uses for the email generation the "email" pam variable
# and optional as fallback PAM_DEFAULT_SUFFIX
# The pam environment variable "email" is provided by:
# https://github.com/devkral/pam_email_extractor
# PAM_ENABLED=true
# Fallback email domain for email address generation (LOCAL_DOMAIN by default)
# PAM_EMAIL_DOMAIN=example.com
# Name of the pam service (pam "auth" section is evaluated)
# PAM_DEFAULT_SERVICE=rpam
# Name of the pam service used for checking if an user can register (pam "account" section is evaluated) (nil (disabled) by default)
# PAM_CONTROLLED_SERVICE=rpam
# Global OAuth settings (optional) :
# If you have only one strategy, you may want to enable this
# OAUTH_REDIRECT_AT_SIGN_IN=true
# Optional CAS authentication (cf. omniauth-cas) :
# CAS_ENABLED=true
# CAS_URL=https://sso.myserver.com/
# CAS_HOST=sso.myserver.com/
# CAS_PORT=443
# CAS_SSL=true
# CAS_VALIDATE_URL=
# CAS_CALLBACK_URL=
# CAS_LOGOUT_URL=
# CAS_LOGIN_URL=
# CAS_UID_FIELD='user'
# CAS_CA_PATH=
# CAS_DISABLE_SSL_VERIFICATION=false
# CAS_UID_KEY='user'
# CAS_NAME_KEY='name'
# CAS_EMAIL_KEY='email'
# CAS_NICKNAME_KEY='nickname'
# CAS_FIRST_NAME_KEY='firstname'
# CAS_LAST_NAME_KEY='lastname'
# CAS_LOCATION_KEY='location'
# CAS_IMAGE_KEY='image'
# CAS_PHONE_KEY='phone'
# Optional SAML authentication (cf. omniauth-saml)
# SAML_ENABLED=true
# SAML_ACS_URL=http://localhost:3000/auth/auth/saml/callback
# SAML_ISSUER=https://example.com
# SAML_IDP_SSO_TARGET_URL=https://idp.testshib.org/idp/profile/SAML2/Redirect/SSO
# SAML_IDP_CERT=
# SAML_IDP_CERT_FINGERPRINT=
# SAML_NAME_IDENTIFIER_FORMAT=RAILS_SERVE_STATIC_FILES: true
# SAML_CERT=
# SAML_PRIVATE_KEY=
# SAML_SECURITY_WANT_ASSERTION_SIGNED=true
# SAML_SECURITY_WANT_ASSERTION_ENCRYPTED=true
# SAML_SECURITY_ASSUME_EMAIL_IS_VERIFIED=true
# SAML_ATTRIBUTES_STATEMENTS_UID="urn:oid:0.9.2342.19200300.100.1.1"
# SAML_ATTRIBUTES_STATEMENTS_EMAIL="urn:oid:1.3.6.1.4.1.5923.1.1.1.6"
# SAML_ATTRIBUTES_STATEMENTS_FULL_NAME="urn:oid:2.16.840.1.113730.3.1.241"
# SAML_ATTRIBUTES_STATEMENTS_FIRST_NAME="urn:oid:2.5.4.42"
# SAML_ATTRIBUTES_STATEMENTS_LAST_NAME="urn:oid:2.5.4.4"
# SAML_UID_ATTRIBUTE="urn:oid:0.9.2342.19200300.100.1.1"
# SAML_ATTRIBUTES_STATEMENTS_VERIFIED=
# SAML_ATTRIBUTES_STATEMENTS_VERIFIED_EMAIL=
# Custom settings
# ---------------
# Various ways to customize Mastodon's behavior
# ---------------
# Maximum allowed character count (OPTIONAL CHANGES)
MAX_TOOT_CHARS=2500
# Maximum allowed hashtags to follow in a feed column
# Note that setting this value higher may cause significant
# database load (OPTIONAL CHANGES)
MAX_FEED_HASHTAGS=4
# Maximum number of pinned posts (OPTIONAL CHANGES)
MAX_PINNED_TOOTS=5
# Maximum allowed bio characters (OPTIONAL CHANGES)
MAX_BIO_CHARS=2500
# Maximim number of profile fields allowed (OPTIONAL CHANGES)
MAX_PROFILE_FIELDS=10
# Maximum allowed display name characters (OPTIONAL CHANGES)
MAX_DISPLAY_NAME_CHARS=200
# Maximum allowed poll options (OPTIONAL CHANGES)
MAX_POLL_OPTIONS=10
# Maximum allowed poll option characters (OPTIONAL CHANGES)
MAX_POLL_OPTION_CHARS=300
# Rails option
RAILS_SERVE_STATIC_FILES=true
RAILS_ENV=production
NODE_ENV=production
# LibreTranslate
# LIBRE_TRANSLATE_ENDPOINT=
# Maximum image and video/audio upload sizes
# Units are in bytes
# 1048576 bytes equals 1 megabyte
# MAX_IMAGE_SIZE=8388608
# MAX_VIDEO_SIZE=41943040
# Maximum search results to display
# Only relevant when elasticsearch is installed
# MAX_SEARCH_RESULTS=20
# Maximum hashtags to display
# Customize the number of hashtags shown in 'Explore'
# MAX_TRENDING_TAGS=10
# Maximum custom emoji file sizes
# If undefined or smaller than MAX_EMOJI_SIZE, the value
# of MAX_EMOJI_SIZE will be used for MAX_REMOTE_EMOJI_SIZE
# Units are in bytes
# MAX_EMOJI_SIZE=262144
# MAX_REMOTE_EMOJI_SIZE=262144
# Optional hCaptcha support
# HCAPTCHA_SECRET_KEY=
# HCAPTCHA_SITE_KEY=
# ---------------------------------
# ------ ESSEM'S FORK ONLY --------
# ---------------------------------
# Maximum number of emoji reactions per toot and user (minimum 1) (OPTIONAL CHANGES)
MAX_REACTIONS=5
Change the environment variables that need to be changed, and save it as .env.production in the main_directory
.
nano /path/to/main_directory/.env.production
And paste the entire environment file with your changes. CTRL+X to save and exit.
After we change all the required fields in the environment file, it is time to start initializing our Mastodon instance.
Initializing your Mastodon instance:
As long as you correctly modify the environment file with your own configurations, the hard part for you is done!
Create a new file in the main_directory
to initialize the mastodon instance.
nano /path/to/main_directory/initialize.sh
Copy-paste the following code snippet, make sure to change your directories for the volume mounts and the environment file. If you are using TheEssem’s fork of Mastodon, you won’t need to change the container images, otherwise change it to any version of Mastodon mentioned at the very beginning:
#!/bin/bash
podman pod create \
--replace \
--name mastodon-emoji-pod
podman run \
--replace \
-d \
--name mast-emoji-db \
--pod mastodon-emoji-pod \
--shm-size=256mb \
-e 'POSTGRES_HOST_AUTH_METHOD=trust' \
-v /path/to/main_directory/db:/var/lib/postgresql/data:Z \
--health-cmd='["pg_isready", "-U", "postgres"]' \
--restart=unless-stopped \
postgres:14-alpine
podman run \
--replace \
-d \
--name mast-emoji-valkey \
--pod mastodon-emoji-pod \
valkey/valkey:latest
echo "waiting for postgres to be ready"
sleep 10
podman run \
--replace \
--rm \
--name mast-emoji-web \
--pod mastodon-emoji-pod \
--env-file=/path/to/main_directory/.env.production \
--health-cmd="wget -q --spider --proxy=off localhost:3000/health || exit 1" \
-v /path/to/main_directory/app:/mastodon/public/system:Z \
--requires=mast-emoji-db,mast-emoji-valkey \
docker.io/meghadeep/mastodon:chuckya-latest \
bin/rails db:create
sleep 2
podman run \
--replace \
--rm \
--name mast-emoji-web \
--pod mastodon-emoji-pod \
--env-file=/path/to/main_directory/.env.production \
--health-cmd="wget -q --spider --proxy=off localhost:3000/health || exit 1" \
-v /path/to/main_directory/app:/mastodon/public/system:Z \
--requires=mast-emoji-db,mast-emoji-valkey \
docker.io/meghadeep/mastodon:chuckya-latest \
bin/rails db:migrate
Make sure you change the paths in the env file and volume mapping parts of the script before saving it!
Make the file executable, and run it:
chmod +x /path/to/main_directory/initialize.sh
/path/to/main_directory/initialize.sh
At this point, our database will have been initialized for production use. The only thing left is to run all the containers necessary.
Running your Mastodon instance:
We will create our last shell script to pull up all the necessary Podman containers.
Create a new file in the main_directory
to help start the mastodon instance.
nano /path/to/main_directory/compose.sh
Copy-paste the following code snippet, make sure to change your directories for the volume mounts and the environment file. If you are using TheEssem’s fork of Mastodon, you won’t need to change the container images, otherwise change it to any version of Mastodon mentioned at the very beginning:
#!/bin/bash
podman pod create \
--replace \
--name mastodon-emoji-pod \
--net=slirp4netns:allow_host_loopback=true,port_handler=slirp4netns \
-p 14000:4000 -p 13000:3000
podman run \
--replace \
-d \
--name mast-emoji-db \
--pod mastodon-emoji-pod \
--shm-size=256mb \
-e 'POSTGRES_HOST_AUTH_METHOD=trust' \
-v /path/to/main_directory/db:/var/lib/postgresql/data:Z \
--health-cmd='["pg_isready", "-U", "postgres"]' \
--restart=unless-stopped \
postgres:14-alpine
podman run \
--replace \
-d \
--name mast-emoji-valkey \
--pod mastodon-emoji-pod \
valkey/valkey:latest
podman run \
--replace \
-d \
--name mast-emoji-streaming \
--pod mastodon-emoji-pod \
--restart=unless-stopped \
--env-file=/path/to/main_directory/.env.production \
--health-cmd="wget -q --spider --proxy=off localhost:4000/api/v1/streaming/health || exit 1" \
--requires=mast-emoji-db,mast-emoji-valkey \
docker.io/meghadeep/mastodon:chuckya-streaming-latest \
node ./streaming
podman run \
--replace \
-d \
--name mast-emoji-web \
--pod mastodon-emoji-pod \
--restart=unless-stopped \
--env-file=/path/to/main_directory/.env.production \
--health-cmd="wget -q --spider --proxy=off localhost:3000/health || exit 1" \
-v /path/to/main_directory/app:/mastodon/public/system:Z \
--requires=mast-emoji-db,mast-emoji-valkey \
docker.io/meghadeep/mastodon:chuckya-latest \
bundle exec puma -C config/puma.rb
podman run \
--replace \
-d \
--name mast-emoji-sidekiq \
--pod mastodon-emoji-pod \
--restart=unless-stopped \
--env-file=/path/to/main_directory/.env.production \
--health-cmd="ps aux | grep '[s]idekiq\ 6' || false" \
-v /path/to/main_directory/app:/mastodon/public/system:Z \
--requires=mast-emoji-db,mast-emoji-valkey \
docker.io/meghadeep/mastodon:chuckya-latest \
bundle exec sidekiq
Make the file executable, and run it:
chmod +x /path/to/main_directory/compose.sh
/path/to/main_directory/compose.sh
And that’s it! You now have all the containers pulled up for running your own Mastodon instance. Keep in mind that you’ll need a reverse proxy with proper FQDN that you provisioned in the environment file.
I currently use NGINX, and the following config works for me (replace back.end.ip.addr with the IP address of your server running the containers, and please note that I'm only including the reverse proxy location configs within the server directive):
location /api/v1/streaming {
proxy_pass http://back.end.ip.addr:14000/;
proxy_http_version 1.1;
proxy_redirect off;
proxy_buffering off;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection Upgrade;
proxy_set_header Host $host;
}
location ^~ /.well-known/acme-challenge/ {
try_files $uri /;
}
location / {
proxy_pass http://back.end.ip.addr:13000/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection Upgrade;
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 https;
}
I have used Apache in the past, and the following config worked for me (replace back.end.ip.addr with the IP address of your server running the containers, and please note that I'm only including the reverse proxy location configs within the virtual host directive):
ProxyPass /.well-known/acme-challenge !
ProxyPreserveHost On
RequestHeader set X-Forwarded-Proto "https"
ProxyPass /api/v1/streaming http://back.end.ip.addr:14000/
ProxyPass / http://back.end.ip.addr:13000/
ProxyPassReverse / http://back.end.ip.addr:13000/
Once you have your reverse proxy set up, you’ll need to create and authorize your new Owner account.
podman exec -i mast-emoji-web tootctl accounts create <your-local-username> --email <your-email> --confirmed --role Owner
podman exec -i mast-emoji-web tootctl accounts approve <your-local-username>
You should now be able to login using your newly created account. Make sure to change the password afterwards.
Welcome to the Fediverse!