Why?

It’s more a question of ‘Why Not?’.

I was perfectly happy with Iceshrimp.NET but wanted to try something new.

GtS seemed lighter and has hooks into Grafana and Prometheus so I’d be able to mess around with Metrics.

Resources

https://docs.gotosocial.org/en/latest/getting_started/

https://docs.gotosocial.org/en/latest/getting_started/installation/

https://docs.gotosocial.org/en/latest/getting_started/installation/metal/

Preparatory Stuff

Create a PostgreSQL GtS database

In a Terminal, do the following as normal user:

sudo -u postgres psql

Then, (line by line):

create database gotosocial_database with locale 'C.UTF-8' template template0;
create user gotosocial_user with password 'super_long_password';
grant all privileges on database gotosocial_database to gotosocial_user;
ALTER DATABASE gotosocial_database OWNER TO gotosocial_user;

Database Notes:

To list all the databases:

\l

To quit:

\q

To DROP a database (in case something gets bungled):

DROP DATABASE "gotosocial_database";

To DROP a User (in case something gets bungled):

DROP USER "gotosocial_user";

nginx Configuration

In a Terminal, do the following as normal user to create the .conf file:

sudo nano /etc/nginx/sites-available/GtS

Then add (changing as appropriate):

server {
    listen 80;
    # No need for an ipv6 address
    # listen [::]:80;
    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:8888;
        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;
}

Check:

sudo nginx -t

Symlink:

sudo ln -s /etc/nginx/sites-available/GtS /etc/nginx/sites-enabled/

Check and reload the webserver:

sudo nginx -t && sudo systemctl reload nginx

UFW

I use UFW to limit which services can connect to the server.

To authorise traffic on Port 8888, first see a verbose list of currently configured connections:

sudo ufw status verbose

Then, allow GtS on Port 8888:

sudo ufw allow 8888 comment "GtS (GoToSocial) Traffic"

To delete first see a list of currently configured connections:

sudo ufw status numbered

Then, delete the appropriate number:

sudo ufw delete #

Certbot

Certbot is a free, open source software tool for automatically using Let’s Encrypt certificates on manually-administrated websites to enable HTTPS.

Certbot is made by the Electronic Frontier Foundation (EFF), a 501(c)3 nonprofit based in San Francisco, CA, that defends digital privacy, free speech, and innovation.

https://certbot.eff.org/pages/about

If needed Certbot is a Terminal command away:

sudo apt install certbot python3-certbot-nginx

Then, to generate a certificate:

sudo certbot

After cert has been deployed, re-edit the nginx .conf file:

sudo nano /etc/nginx/sites-available/GtS

To:

server {
    # HTTPS configuration
    listen                  443 ssl;

    # Server
    server_name             gts.example.com;

    # SSL
    ssl_certificate         /etc/letsencrypt/live/gts.example.com/fullchain.pem;
    ssl_certificate_key     /etc/letsencrypt/live/gts.example.com/privkey.pem;
    ssl_dhparam             /etc/letsencrypt/ssl-dhparams.pem;

    # logging
    access_log              /var/log/nginx/gts.example.com_access.log combined buffer=512k flush=1m;
    error_log               /var/log/nginx/gts.example.com_error.log warn;

    # security
    include                 nginxconfig.io/security.conf;
    include                 /etc/letsencrypt/options-ssl-nginx.conf;
    client_max_body_size    40M;

    # Proxy to Node
    location / {
        proxy_pass          http://127.0.0.1:8888;
        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;
    }
}

# HTTP redirect
server {
    if ($host = gts.example.com) {
        return 301 https://$host$request_uri;
    }

    listen                  80;
    server_name             gts.example.com;
    return                  404;
}

Check and reload the webserver:

sudo nginx -t && sudo systemctl reload nginx

Install

Now that there is a database to store the info in, and a running webserver, it’s finally time to install GtS.

Create a directory:

mkdir gotosocial

Move to the newly created directory:

cd gotosocial

Make a ‘storage’ directory:

mkdir storage

Grab the latest GtS bundle:

wget https://github.com/superseriousbusiness/gotosocial/releases/download/v0.17.1/gotosocial_0.17.1_linux_arm64.tar.gz

Unzip everything:

tar -xzf gotosocial_0.17.1_linux_arm64.tar.gz

Tidy up:

rm gotosocial_0.17.1_linux_arm64.tar.gz

Configure

Copy the example config file before making any changes:

cp example/config.yaml config.yaml

Open it:

nano config.yaml

I made the following adjustments (the descriptors are self-explanatory):

#host: "localhost"
host: "gts.example.com"

#account-domain: ""
account-domain: "example.com"

#bind-address: "0.0.0.0"
bind-address: "localhost"

#Port 8080 is already in use by something else, so change it to something else
#port: 8080
port: 8888

#db-address: ""
db-address: "localhost"

#db-user: ""
db-user: "gotosocial_user"

#db-password: ""
db-password: "super_long_password"

#db-database: "gotosocial"
db-database: "gotosocial_database"

#media-remote-cache-days: 7
media-remote-cache-days: 1

#media-cleanup-every: "24h"
media-cleanup-every: "8h"

Start, Create Account(s)

The moment of truth!

Start the GtS server:

./gotosocial --config-path ./config.yaml server start

Create the first user(s).

https://docs.gotosocial.org/en/latest/getting_started/user_creation/

Personally, I have two accounts:

  • An Admin account
  • A general non privileged (normal) account

YMMV.

Add an account:

cd ~/gotosocial

./gotosocial --config-path ~/gotosocial/config.yaml \
    admin account create \
    --username admin_account \
    --email admin_account@example.com \
    --password 'admin_account_password'

Promote to Admin:

./gotosocial admin account promote --username admin_account --config-path config.yaml

Add another account:

./gotosocial --config-path ~/gotosocial/config.yaml \
    admin account create \
    --username general_account \
    --email general_account@example.com \
    --password 'general_account_password'

Do not promote to Admin.

Enable the systemd service

Create the systemd service that will start when the server reboots.

https://raw.githubusercontent.com/superseriousbusiness/gotosocial/main/example/gotosocial.service

sudo nano /etc/systemd/system/gotosocial.service

Run:

sudo systemctl enable --now gotosocial.service

sudo systemctl start gotosocial.service

Check the service status:

sudo systemctl status gotosocial.service

Authentication with the API (get a TOKEN)

I have a couple of bots that need to post autonomously using the API.

This functionality needs an an Auth token:

https://docs.gotosocial.org/en/latest/api/authentication/

Landing Page (config.yaml)

As this is a self-hosted single user instance, rather than the generic GtS homepage I would like my Account Profile to be displayed.

nano gotosocial/config.yaml

#landing-page-user: ""
landing-page-user: "general_account"

sudo systemctl restart gotosocial

Metrics

https://docs.gotosocial.org/en/latest/advanced/metrics/

I’m a big fan of Metrics and Dashboards , so of course I’m going to enable this feature:

Edit the config.yaml file.

I made the following adjustments (the descriptors are self-explanatory):

nano gotosocial/config.yaml

#metrics-enabled: false
metrics-enabled: true

#metrics-auth-enabled: false
metrics-auth-enabled: true

#metrics-auth-username: ""
metrics-auth-username: "user_login_name"

#metrics-auth-password: ""
metrics-auth-password: "user_login_password"

Restart GtS:

sudo systemctl restart gotosocial

Go to:

https://server.IP/metrics

Now 404 the metrics page from external requests (if desired):

sudo nano /etc/nginx/sites-available/GtS

Add:

# 404 the metrics page from external requests
location /metrics {
    return 404;
}

Check and reload the webserver:

sudo nginx -t && sudo systemctl reload nginx

Add to Prometheus

sudo nano /etc/prometheus/prometheus.yml

Add:

# gotosocial/metrics job
  - job_name: "gotosocial"
    metrics_path: /metrics
    scheme: https
    basic_auth:
      username: "prometheus_login_name"
      password: "prometheus_login_password"
    static_configs:
    - targets:
      - gts.example.com

Restart Prometheus:

sudo systemctl restart prometheus

sudo systemctl status prometheus

Go to:

http://server.IP:9090/targets

To see then new endpoint ‘gotosocial’

Add Dashboard to Grafana

http://server.IP:3030/login

UFW

I already mentioned that I use UFW to limit access to the server.

As Prometheus and Grafana were already set up and running, there was no need for me to adjust or add to the existing UFW rules.

Allow Prometheus:

sudo ufw allow from 192.168.0.0/24 to any port 3030 comment "Grafana traffic from LAN only"

Allow Grafana:

sudo ufw allow from 192.168.0.0/24 to any port 9090 comment "Prometheus traffic from LAN only"

Both of the above allow access to Grafana and Prometheus from the LAN only.

I have no interest in viewing my dashboard when away from home or allowing the data to be publicly accessible.

Metrics Notes:

Remember to allow access to the gotosocial_database to the grafana user

sudo -u postgres psql

\connect gotosocial_database;

GRANT CONNECT ON DATABASE "gotosocial_database" TO grafana;
GRANT USAGE ON SCHEMA public TO grafana;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO grafana;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO grafana;

The Scripts

A selection of SQL scripts for the GoToSocial PostgreSQL database.

These three scripts are the routines that I run daily, hourly and monthly.

Why?

All of the Fediverse software that I have used seem to retain too much data for too long.

Personally I see no need to keep the e.g. account details for every account that has passed through my timeline.

Likewise, I do not need to store, archive and backup a huge amount of emoji from various Fediverse instances.

So I remove them, along with what I consider to be other extraneous info.

(The list of data to be removed will probably grow as I dig deeper into the database.)

gotosocial_tidy_daily.sql

gotosocial_tidy_daily.sql

WARNING:

This script will:

  • Tidy (DELETE FROM) the gotosocial db accounts table

    • Don’t remove any accounts with the following id’s
    • Remove any accounts that are not followers
    • Remove any accounts that are not followees
    • Don’t remove any accounts that are in the blocking table
    • Don’t remove any accounts that are in the muting table
  • Tidy (DELETE FROM) the gotosocial db accounts_stats table

    • Don’t remove any stats with the following id’s
    • Remove any stats that are not followers
    • Remove any stats that are not followees
  • Tidy (DELETE FROM) the gotosocial db tokens table

    • Keeping the (bot) sessions
  • Tidy (TRUNCATE) the gotosocial db tables

    • public.clients
    • public.emojis
    • public.tombstones
  • Tidy (VACUUM.ANALYZE) the gotosocial db

gotosocial_tidy_hourly.sql

gotosocial_tidy_hourly.sql

WARNING:

This script will:

  • Tidy (DELETE FROM) the gotosocial db mentions table

    • Delete all mentions over n days old
  • General (DELETE FROM) the gotosocial db statuses table

    • Per account deletes will be done later
    • Delete all statuses over n days old
    • Don’t remove any statuses from any accounts in the ‘users’ table
  • Per account (DELETE FROM) the gotosocial db statuses table

    • Delete all statuses over n days old
    • Probably makes sense to keep this in line with the ‘General’ setting
    • Delete from: account_1_username account
    • Retain pinned posts
  • Per account (DELETE FROM) the gotosocial db statuses table

    • Delete all statuses over n days old
    • Probably makes sense to keep account_2_username posts for longer
    • Delete from: account_2_username account
    • Retain pinned posts
  • Tidy (DELETE FROM) the gotosocial db status_faves table

    • Delete all status_faves over n days old
  • Tidy (ANALYZE) any table that has had a DELETE performed upon it

    • public.“mentions
    • public.“statuses”
    • public.“status_faves

gotosocial_tidy_monthly.sql

gotosocial_tidy_monthly.sql

This script will:

  • Perform a VACUUM FULL ANALYZE on the database and only needs to be run occasionally:

Bugs

So far I have found very few bugs and certainly zero application killing ones.

There doesn’t seem to be a way to clear previously authorised sessions i.e. an old browser session, clearing the table stops the application from functioning.

Also, also_known_as if present prevents the account from being found yet the account can still create content.

Neither of the above would be encountered during normal everyday usage; it’s more me, tinkering with the guts of the database, something a normal person would ever do.