How to host your own fediverse (Pleroma/Misskey/Mastodon) server for FREE, forever

May 31, 2024

Thanks to Oracle Cloud Free Tier, you can get a good server that can host your fediverse instance 100% free, indefinitely. And with free DNS services, you can get a subdomain name that will allow it to federate.

Part 1: Get a free server

Create an Oracle Cloud account

You will need a credit card to create an account, but no money will ever be charged unless you explicitly upgrade the account to a paid account.

Head over to https://www.oracle.com/cloud/free/ and click “Start for free” to start the process. Choose a region that is close to you for the lowest latency. You cannot change this later.

Create the virtual server

  1. Navigate to Compute -> Instances. On the left, choose your root compartment. Click “Create Instance”.
  2. On “Image and shape”, click Edit.
    1. Click “Change shape”. Click “Ampere”, scroll down and select “VM.Standard.A1.Flex”. Increase “Number of OCPUs” to 4, and “Amount of memory (GB)” to 24.
    2. Click “Change image” and select “Ubuntu” -> “Canonical Ubuntu 22.04”.
  3. Under “Boot volume”, select “Specify a custom boot volume size”. Set “Boot volume size (GB)” to 200.
  4. Click “Save private key” so that you can access the instance with an SSH client.
  5. Everything else can be left as is. Click “Create”.

⚠ If you get a “Out of host capacity” error, then unfortunately you can’t get the good free server at this time. You will have to use this script, https://github.com/hitrov/oci-arm-host-capacity , to automatically try creating the instance over and over again until it works. This might take days, weeks or months. You can create a free AMD instance to run the script 24/7 or you can run it anywhere else. Keep in mind that you only have 30 days to exceed the free tier limits, afterwards you will not be able to have more than 200GB total of storage volumes, so if you’ve created one server with 200GB you will not be able to run another. You may want to change the boot volume size to default before using this script, and then expand it to 200GB once you obtain the ARM server and delete the AMD server.

You might be able to run Pleroma on a 1GB AMD instance, if you add swap. You can add swap with the following commands as root (type sudo -i to become root): dd if=/dev/zero of=/swapfile bs=1M count=4096; chmod 600 /swapfile; mkswap /swapfile; swapon /swapfile; echo "/swapfile none swap sw 0 0" >> /etc/fstab. (then exit root). But it will be slow, you should wait for the free 24GB 4-core ARM server.

Connect to the virtual server

  1. Find the private key you downloaded and rename it to “id_rsa”. Go to your home directory (%homepath%), create a folder named .ssh if it does not exist, and place the id_rsa file in there.
  2. On the Oracle Cloud dashboard, select your instance and copy the “Public IP Address”.
  3. Open a Command Prompt and type in ssh ubuntu@, then paste the IP address by right-clicking. Example: ssh ubuntu@192.9.148.6. Press enter
  4. You should now be connected to your server. Now is a good time to update it, type: sudo apt update; sudo apt upgrade; reboot

Prepare the Oracle firewall for web traffic

  1. On the Instance page on Oracle Cloud dashboard, select “Attached VNICs” on the bottom right, and then select the subnet in the “Subnet or VLAN” column.
  2. Select the “Default Security List”. Click “Add Ingress Rules”. Fill in the following information:
    1. Source CIDR: 0.0.0.0/0
    2. IP Protocol: TCP
    3. Destination Port Range: 80,443
    4. Click “+ Another Ingress Rule”
    5. Source CIDR: 0.0.0.0/0
    6. IP Protocol: UDP
    7. Destination Port Range: 443
  3. Click “Add Ingress Rules”.

Part 2: Obtain a domain name

The domain name is where your server will live and will be a permanent part of your handle. Domains typically cost $10-$20 per year, but you can often get a first year sale for a dollar.

If you don’t want to buy a domain, there are plenty of “free DNS” solutions where you can get a free subdomain, for example: my-awesome-fedi-server.chickenkiller.com. One of the best free DNS providers is https://freedns.afraid.org/ , but there is also https://www.noip.com/ , https://www.duckdns.org/ .

Simply create a subdomain/hostname of type “A” with the “Public IPv4 Address” of your Oracle Server.

Another service you can use is nip.io , this lets you get started without creating an account or anything. Simply append .nip.io to the end of your IP address, and you have a hostname that you can use to host your instance. (It is actually possible to host a server on the raw IP address, but it is hard to set up SSL and it breaks some fedi platforms.)

Once you have a domain/hostname, go to nslookup.io and type in the name. You should see your A record with your server’s IP address. If not, you may need to wait a few minutes and try again. Once you see that, the name is ready to be used.

Part 3: Install the web server

The web server connects the people on the internet to the web services running on the server. The best web server is Caddy, as it is very easy to configure and it automatically takes care of all the SSL certificate stuff so you don’t even need to THINK about it.

  1. Per the caddy documentation , install caddy by running each of these commands, one by one:
    1. sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl
    2. curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
    3. curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
    4. sudo apt update
    5. sudo apt install caddy
  2. Type in sudo nano /etc/caddy/Caddyfile to open the config in the nano text editor, and add this to the bottom, replacing my-awesome-fedi-server.chickenkiller.com with the domain name you got for the server. Press ctrl O to write and ctrl X to exit.
    my-awesome-fedi-server.chickenkiller.com {
    	reverse_proxy localhost:3000
    }
    
    Or if you are going to use Mastodon:
    my-awesome-mastodon-server.chickenkiller.com {
    	reverse_proxy /api/v1/streaming* localhost:4000
    	reverse_proxy localhost:3000
    }
    
  3. Type sudo systemctl reload caddy. In a few moments you should be able to type in your domain name into the web browser and see a 502 error. This means the web server is working, and now we just need the backend service.

Part 4: Install the fediverse software

Choose one of these applications to install.

Pleroma/Akkoma

I recommend Pleroma because it is the most usable software with relatively few issues, and it is simple and easy to host.

  1. Install all the packages that you will need: sudo apt update; sudo apt install git build-essential postgresql postgresql-contrib cmake libmagic-dev elixir erlang-dev erlang-nox imagemagick ffmpeg libimage-exiftool-perl
  2. Run this: echo "export MIX_ENV=prod >> .profile; exec bash. This will let you run pleroma commands without typing MIX_ENV=prod every time, which is needed to run it in production mode, otherwise it runs in development mode, which we don’t want.
  3. Download the Pleroma code: git clone https://git.pleroma.social/pleroma/pleroma.git -b stable
    • If you want to use Akkoma, just replace the git url with https://akkoma.dev/AkkomaGang/akkoma.git
  4. Enter the pleroma folder: cd pleroma
  5. Load all the dependencies: mix deps.get
  6. Generate configuration file: mix pleroma.instance gen
    1. The server name must be the domain name you got
    2. When it asks for port, type in 3000 so it matches the caddy config.
    3. Leave all the database settings default (just press enter)
    4. I recommend deduplicating uploads to save disk space.
  7. Rename the configuration file: mv config/{generated_config.exs,prod.secret.exs}
  8. Initialize the database: sudo -u postgres psql -f config/setup_db.psql
  9. Import the schema: mix ecto.migrate
  10. Test the server: mix phx.server. Visit your domain name in the browser to see if it is working.
  11. Stop the server with Ctrl-C.
  12. Type: sudo nano /etc/systemd/system/pleroma.service and type or paste in the following:
    [Unit]
    Description=Pleroma social network
    After=postgresql.service
    
    [Service]
    User=ubuntu
    Environment="MIX_ENV=prod"
    WorkingDirectory=/home/ubuntu/pleroma/
    ExecStart=/usr/bin/mix phx.server
    
    [Install]
    WantedBy=multi-user.target
    
  13. Enable and start the service: sudo systemctl daemon-reload; sudo systemctl enable --now pleroma
  14. Create the first admin account: mix pleroma.user new <username> <your@emailaddress> --admin
  15. Open the URL in your browser to activate the account with a password.

Misskey/Sharkey

Misskey is modern and feature-rich but lacks support for post edits, so I recommend using Sharkey instead of Misskey.

  1. Install dependencies
    1. Install Node.js >=20 with the following commands
      1. curl -fsSL https://deb.nodesource.com/setup_lts.x -o nodesource_setup.sh
      2. sudo -E bash nodesource_setup.sh
      3. sudo apt-get install -y nodejs
      4. sudo corepack enable
    2. Install PostgreSQL >=15
      1. sudo apt install -y postgresql-common
      2. sudo /usr/share/postgresql-common/pgdg/apt.postgresql.org.sh
      3. sudo apt install postgresql-16
    3. Install the rest of the packages: sudo apt install redis ffmpeg build-essential git
  2. Prepare the database
    1. Create database user: sudo -u postgres createuser ubuntu.
    2. Create database: sudo -u postgres createdb -O ubuntu sharkey
  3. Download Sharkey: git clone --recurse-submodules -b stable https://activitypub.software/TransFem-org/Sharkey.git sharkey
  4. Enter Sharkey folder: cd sharkey
  5. Load its npm packages: pnpm install --frozen-lockfile
  6. Prepare config file: cp .config/example.yml .config/default.yml
  7. Edit config file: .config/default.yml
    1. Replace example.tld with your domain name.
    2. Set db: to sharkey, user: to ubuntu and delete pass:. Since the DB username is the same as the Linux username, no password is needed.
    3. I suggest setting proxyRemoteFiles: to false or your disk will fill up with other people’s files. Also, if this is enabled, posts will go missing if it can’t download the attachment, such as if it’s too large.
  8. Build Sharkey: pnpm run build
  9. Initialize db: pnpm run init
  10. Test the server: pnpm start. Open the URL in your browser.
  11. Press ctrl C to stop the server. Type sudo nano /etc/systemd/system/sharkey.service and paste in the following:
    [Unit]
    Description=Sharkey 
    After=postgresql.service redis.service
    
    [Service]
    User=ubuntu
    WorkingDirectory=/home/ubuntu/sharkey/
    ExecStart=/usr/bin/pnpm start
    Environment=NODE_OPTIONS=--max-old-space-size=8192 NODE_ENV=production
    
    [Install]
    WantedBy=multi-user.target
    
  12. Enable and start the service: sudo systemctl daemon-reload; sudo systemctl enable --now sharkey

Mastodon

Mastodon is the most well known and polished but lacks reactions and has deliberate hard-coded limitations (you cannot see more than four attachments, you cannot attach images with video, you cannot have more than four poll options, etc).

Mastodon requires an email server. You can manually approve accounts on the command line, but it is not possible to allow automatic approval without an email server.

  1. Install system dependencies
    1. Install the latest LTS Node.js with the following commands
      1. curl -fsSL https://deb.nodesource.com/setup_lts.x -o nodesource_setup.sh
      2. sudo -E bash nodesource_setup.sh
      3. sudo apt-get install -y nodejs
      4. sudo corepack enable
      5. yarn set version classic
    2. Install rest of packages: apt install ruby ruby-bundler ruby-dev postgresql postgresql-contrib redis imagemagick ffmpeg git build-essential autoconf libpq-dev libxml2-dev libxslt1-dev libprotobuf-dev protobuf-compiler pkg-config bison libssl-dev libyaml-dev libreadline6-dev zlib1g-dev libncurses5-dev libffi-dev libgdbm-dev libidn11-dev libicu-dev libjemalloc-dev
  2. Create database user: sudo -Hu postgres createuser -d ubuntu
  3. Download mastodon and enter folder: git clone https://github.com/mastodon/mastodon.git; cd mastodon
  4. Checkout the latest version: git checkout $(git tag -l | grep '^v[0-9.]*$' | sort -V | tail -n 1)
  5. Install application dependencies
    1. bundle config deployment 'true'
    2. bundle config without 'development test'
    3. bundle install -j$(getconf _NPROCESSORS_ONLN)
    4. yarn install --pure-lockfile
  6. Run the Mastodon setup wizard: RAILS_ENV=production bundle exec rake mastodon:setup
    • Type ubuntu for the PostgreSQL user. Since it is the same as Linux user, no password is needed.
  7. Create each of these files with sudo nano:
    • /etc/systemd/system/mastodon-web.service
      [Unit]
      Description=mastodon-web
      After=postgresql.service redis.service
      
      [Service]
      User=ubuntu
      WorkingDirectory=/home/ubuntu/mastodon/
      Environment=RAILS_ENV=production PORT=3000 RAILS_SERVE_STATIC_FILES=true LD_PRELOAD=libjemalloc.so
      ExecStart=/usr/bin/bundle exec puma -C config/puma.rb
      
      [Install]
      WantedBy=multi-user.target
      
    • /etc/systemd/system/mastodon-sidekiq.service
      [Unit]
      Description=mastodon-sidekiq
      After=postgresql.service redis.service
      
      [Service]
      User=ubuntu
      WorkingDirectory=/home/ubuntu/mastodon/
      Environment=RAILS_ENV=production DB_POOL=25 MALLOC_ARENA_MAX=2 LD_PRELOAD=libjemalloc.so
      ExecStart=/usr/bin/bundle exec sidekiq -c 25
      
      [Install]
      WantedBy=multi-user.target
      
    • /etc/systemd/system/mastodon-streaming.service
      [Unit]
      Description=mastodon-streaming
      After=postgresql.service redis.service
      
      [Service]
      Type=simple
      User=ubuntu
      WorkingDirectory=/home/ubuntu/mastodon/
      Environment=NODE_ENV=production PORT=4000
      ExecStart=/usr/bin/node ./streaming
      
      [Install]
      WantedBy=multi-user.target
      
  8. Start the services: sudo systemctl daemon-reload; sudo systemctl enable --now mastodon-web mastodon-sidekiq mastodon-streaming
  9. Sign in to your admin account and navigate to https://<your domain>/admin/settings/content_retention. Add a value under “Media cache retention period”, such as 30 days. Otherwise, you will run out of disk space as everyone’s media is downloaded and kept forever.

The End

If you encountered any issues, report them to me on fediverse or wherever. Eventually, I will add comments to this blog site thing.