The software
We are going to host a fedi instance on a cheap VPS with Debian and GoToSocial. If you don’t know GoToSocial, it is a fedi server software written in Go for small instances with at most a few dozen active users. Here are some facts about it.
Pros:
- Self contained binary, in principle you don’t need a standalone HTTP server like Nginx;
- Configuration is all done in a very well documented config file;
- Great documentation specially for such a new project;
- Automatically obtains and renews a Let’s Encrypt certificate if not running behind Nginx;
- Uses between 50MB and 100MB of ram;
- SQLite (makes backups very easy) or PostgreSQL;
- Devs provide sane privacy and security defaults, specially useful for inexperienced admins;
- The already available features work very well.
Cons:
- Still alpha so some features are lacking, see the roadmap;
- Not designed for large instances and no clear migration path to Pleroma/Mastodon.
The hardware
Pick a 1 dollar VPS from lowendbox, any will do as long as it has 512MB of ram or more, 256MB could work but I didn’t test. Not all those offers are precisely 1 dollar per month, I bought a RackNerd instance with 512MB of ram for ~10 dollars per year. For single or few user instances GoToSocial should stay between 50MB and 100MB of ram so you might be able to get away with 128MB by using ZRam, Alpine Linux or some other super minimal OS.
The domain
I bought a domain from porkbun, it was 2 dollars for the first year and around 10 dollars for the subsequent years, I can cancel at any time. But you can also get a free domain from freenom, they offer free .tk, .ml, .gq, and .cf domains on a first-come, first-served basis. Freenom will be blacklisted on all email servers but should work fine for fedi and personal sites. In the future I want to look into adding .onion, .eth, .bit and OpenNic domains.
Installing and configuring GoToSocial
sudo adduser gotosocial
sudo -u gotosocial -s
mkdir -p ~/gotosocial/storage/certs
cd ~/gotosocial
Grab the latest version of GoToSocial here, at the moment of writing it was 0.6.0.
wget https://github.com/superseriousbusiness/gotosocial/releases/download/v0.6.0/gotosocial_0.6.0_linux_amd64.tar.gz
tar -zxf gotosocial_0.6.0_linux_amd64.tar.gz
Let’s copy the example config file.
cp ./example/config.yaml .
Now open the config file with your favorite text editor and change the following options. You shouldn’t change the domain related settings after the sever is run for the first time.
# We will run the instance on gts.example.com
# but everyone will see the accounts as user@example.com.
host "gts.example.com"
account-domain: "example.com"
# We will run locally and let nginx forward request to us
bind-address: "localhost"
port 8080
# Backups are just stopping the server and copying a folder
db-type "sqlite"
db-address "gotosocial.db"
storage-local-base-path: "/home/gotosocial/gotosocial/storage"
syslog-enabled: true
First run
./gotosocial --config-path ./config.yaml server start
Create a new user - mind the space at the beginning of the line, this command won’t be saved to history (because it contains a password):
./gotosocial --config-path ./config.yaml admin account create --username user --email user@example.com --password 'abc123'
And make it admin.
./gotosocial --config-path ./config.yaml admin account promote --username user
Add a systemd service
sudo cp /home/gotosocial/gotosocial/example/gotosocial.service /etc/systemd/system
sudo nano /etc/systemd/system/gotosocial.service
ExecStart=/home/gotosocial/gotosocial/gotosocial --config-path config.yaml server start
WorkingDirectory=/home/gotosocial/gotosocial
sudo systemctl start gotosocial
Installing and configuring Nginx
We are going to run GoToSocial on a domain of its own, gts.example.com, but have the user accounts be @user@example.com, for that we need to redirect the webfinger paths from example.com to gts.example.com.
Configuring Nginx is an easy and well documented procedure, I will refer you to this tutorial on how to setup nginx on debian and another one on how to to setup Let’s Encrypt. Remember to configure example.com and gts.example.com.
Reverse proxy
Configure nginx to forward any request to gts.example.com to our GoToSocial server.
sudo nano /etc/nginx/sites-available/gts.example.com
Your file may look slightly different, the important part is adding the location
block
to the server
block with the SSL configurations (the one listening on port 443). Requests to port 80
will be automatically redirected here.
server {
server_name gts.example.com
location / {
# set to 127.0.0.1 instead of localhost to work around
# https://stackoverflow.com/a/52550758
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
}
client_max_body_size 40M;
# The rest of our nginx config...
}
Webfinger redirect
sudo nano /etc/nginx/sites-available/example.com
Again, your file may look slightly different, the important part is adding the location
blocks
to the server
block with the SSL configurations (the one listening on port 443). Requests to port 80
will be automatically redirected here.
http {
server {
server_name example.com, www.example.com;
location /.well-known/webfinger {
rewrite ^.*$ https://gts.example.org/.well-known/webfinger permanent;
}
location /.well-known/nodeinfo {
rewrite ^.*$ https://gts.example.org/.well-known/nodeinfo permanent;
}
# The rest of our nginx config...
}
}
Test and reload
sudo nginx -t
sudo systemctl reload nginx
AppArmor profile
And lastly, a modified AppArmor profile to use our /home/gotosocial installation path.
Save the file below to /etc/apparmor.d/gotosocial
then run.
#include <tunables/global>
profile gotosocial flags=(attach_disconnected, mediate_deleted) {
#include <abstractions/base>
#include <abstractions/nameservice>
/home/gotosocial/gotosocial/gotosocial mrix,
/usr/bin/gotosocial mrix,
/usr/local/bin/gotosocial mrix,
owner /home/gotosocial/gotosocial/{,**} r,
owner /home/gotosocial/gotosocial/storage/** wk,
# Allow GoToSocial to write logs
#
# NOTE: you only need to allow write permissions to /var/log/syslog if you've
# enabled logging to syslog. Otherwise, you can comment out that line.
/var/log/gotosocial/* w,
owner /var/log/syslog w,
# These directories are not currently used by any of the recommended
# GoToSocial installation methods, but they may be used in the future and/or
# for custom installations.
owner /etc/gotosocial/{,**} r,
owner /usr/lib/gotosocial/{,**} r,
owner /usr/share/gotosocial/{,**} r,
owner /usr/local/etc/gotosocial/{,**} r,
owner /usr/local/lib/gotosocial/{,**} r,
owner /usr/local/share/gotosocial/{,**} r,
owner /var/lib/gotosocial/{,**} r,
owner /opt/gotosocial/{,**} r,
owner /run/gotosocial/{,**} r,
/proc/sys/net/core/somaxconn r,
/sys/kernel/mm/transparent_hugepage/hpage_pmd_size r,
owner @{PROC}/@{pid}/cpuset r,
# TCP / UDP network access
network inet stream,
network inet6 stream,
network inet dgram,
network inet6 dgram,
# Allow GoToSocial to send signals to/receive signals from worker processes
# Allow GoToSocial to receive signals from unconfined processes
signal (receive) peer=unconfined,
signal (send,receive) peer=gotosocial,
}
# vim:syntax=apparmor
Now let’s tell systemd about our AppArmor profile.
sudo systemctl stop gotosocial
Open the unit file to add the AppArmor section.
sudo nano /etc/systemd/system/gotosocial.service
This should go on the [Service]
section. You can put it at the bottom.
[Service]
# ...
AppArmorProfile=gotosocial
Reload the daemon because we changed a unit file.
sudo systemctl daemon-reload
Start the service back again.
sudo systemctl start gotosocial
From their documentation:
GoToSocial is currently alpha software, and as more features are implemented these security policies may quickly become outdated. You may find that using AppArmor or SELinux causes GoToSocial to fail in unexpected ways until GTS becomes stable.
It’s unlikely that you (or I) will have any problems, but if you do, simply remove the AppArmorProfile
section from the systemd unit file.
Conclusion
That’s it, your fedi instance is running on gts.example.com. You can access it with most fedi clients but the GoToSocial project mentions pinafore and Tusky as well supported.
To keep up with updates follow GoToSocial’s official account.
Feel free to follow me at master_cat@gts.catona.cloud.