Calckey? Clacky? Is this thing on?

I had been itching to set up a Fediverse server for some time but was undecided on the flavour; Mastodon or Calckey or something entirely different?

Calckey was the eventual winner.

Why?

Because the Mastodon install was “follow these quick 45 steps in a Terminal”.

Which then breaks at step 44.

Calckey was “run this one script and answer a couple of questions”.

This sounds like I’m not a Mastodon fan.

I am.

But.

Calckey vs Mastodon

There are a couple of things that I think Mastodon does really well especially around how to manage your social graph.

  • You can bulk select people to follow and unfollow
  • You can see when someone was last active
  • Posts can be set to auto delete after a set period of time

Calckey does none of the above and I wish it did.

Instead, Calckey presents who you follow in a lovely looking grid but you have no idea if the following is mutual or when they were last active until you click through to the account details.

Edit: the Android ‘Milktea’ app currently does show you if the account you are following is following you back.

For perspective, I’ve hopped around the Fediverse for a while now with different usernames on different services running different software.

I have bots that run when my lights turn on and I’ve already written about how to nuke a Mastodon account .

So why my delay in setting a Fediverse server up?

Well, one of the reasons for my reticence around self-hosting was moving my social graph to a server that lives under the telly.

And then something catastrophic happening.

Which will occur at some point.

So for me to feel comfortable there needed to be a robust backup process in place.

(And obviously a working restore process.)

Fediverse Server Backup Process

I use ‘pg_basebackup’ to take a full copy of the PostgreSQL database.

I also tried ‘pg_dump’ and ‘pg_restore’ for the Calckey database but I couldn’t get it to restore properly.

To run ‘pg_basebackup’ it needs a username / password combination to run.

Fortunately, PostgreSQL has the ability to store this username / password combo in a file.

.pgpass

The file .pgpass in a user’s home directory can contain passwords to be used if the connection requires a password

https://www.postgresql.org/docs/current/libpq-pgpass.html

Obviously it needs creating, and appropriate permissions granting.

First, create the .pgpass file:

sudo nano /home/$USER/.pgpass

#hostname:port:database:username:password
*:*:*:ThePostgresAccount:ThePostgresAccountPassword

Then own it:

sudo chown $USER:$USER /home/$USER/.pgpass

Then give the file the correct permissions:

chmod 600 /home/$USER/.pgpass

Finally, write it to the environment variables:

export PGPASSFILE='/home/$USER/.pgpass'

Then, check the environment variable using:

env

The ‘pg_basebackup’ command will now not ask for a password:

pg_basebackup -h localhost -p 5432 -U postgres_user -D /path/to/the/remote/backup -Fp -Xs -P

Backup the Calckey database

Create the database backup script:

sudo nano /etc/init.d/backup_calckey_db.sh

Give the file the correct permissions:

sudo chmod +x /etc/init.d/backup_calckey_db.sh

backup_calckey_db.sh

#!/bin/bash

# The remote backup process
# ~~~~~~~~~~~~~~~~~~~~~~~~~
# Backup the whole of the PostgreSQL database
rm -R /home/foo/Backups/calckey/postgresql/*;
pg_basebackup -h localhost -p 5432 -U postgres -D /home/foo/Backups/calckey/postgresql -Fp -Xs -P;

Backup the Calckey /files/ directory

The calckey/files/ directory holds all of the ‘Drive’ files.

(All of those avatars, headers, wallpapers and meme collections.)

Create the /files/ backup script:

sudo nano /etc/init.d/backup_calckey_files.sh

Give the file the correct permissions:

sudo chmod +x /etc/init.d/backup_calckey_files.sh

backup_calckey_files.sh

#!/bin/bash

# The remote backup process
# ~~~~~~~~~~~~~~~~~~~~~~~~~
# Backup the Calckey /files/ directory
rm -r /home/foo/Backups/calckey/files/
cp -r /home/calckey/calckey/files /home/foo/Backups/calckey/files/

Because the /files/ directory is owned by the Calckey user it needs a sudo cron job.

sudo crontab -e

#
# Backup the Calckey /files/ directory hourly
0 * * * * sh /etc/init.d/backup_calckey_files.sh
#

Archive the two backups

Obviously the database and the files directory backups need to be in place prior to archiving.

Create the archive script:

sudo nano /etc/init.d/backup_calckey_zipped.sh

Give the file the correct permissions:

sudo chmod +x /etc/init.d/backup_calckey_zipped.sh

backup_calckey_zipped.sh

#!/bin/bash

# The remote backup process
# ~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Backup the whole of the PostgreSQL database
# Is called by the user crontab '/etc/init.d/backup_calckey_db.sh'
#
# Backup the Calckey /files/ directory
# Is called by the sudo crontab '/etc/init.d/backup_calckey_files.sh'
#
#  So call this in normal crontab after '/etc/init.d/backup_calckey_db.sh'
rm /home/foo/Backups/backup_calckey.zip;
zip -r /home/foo/Backups/backup_calckey.zip /home/foo/Backups/calckey

I backup the whole PostgreSQL and the /files/ database hourly using cron.

Then archive (zip) the whole lot.

crontab -e

#
# Backup the whole of the PostgreSQL database hourly
# Then put the previous /files/ backup and this db backup into one zip
0 * * * * sh /etc/init.d/backup_calckey_db.sh; sh /etc/init.d/backup_calckey_zipped.sh
#

Fediverse Server Restore Process

Obviously there is no sense in keeping a server backup on the server where the original files are held.

That’s why there are two backups:

  • A pair of folders on the server containing the database and the needed files
  • A single zipped file that can be copied as part of a daily backup routine off the server

This way, I can easily restore from the hourly created server files and in the case of a yet-to-happen catastrophic event I can copy over the last locally held zip archive and restore from there.

I’m not going to cover how to get the zip archive on and off the server (hint: I use ssh keys and scp).

However the following script executed server-side will restore (and give the correct permissions to) a Calckey PostgreSQL database and the /files/ directory.

First, create the restore script:

sudo nano /etc/init.d/restore_calckey.sh

Then give the file the correct permissions:

sudo chmod +x /etc/init.d/restore_calckey.sh

Files

restore_calckey.sh

#!/bin/bash

# The remote restore process
# ~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Restore from the hourly backup on the server

clear

# Stop the running PostgreSQL service
echo -e "\e[1;33mStop the running PostgreSQL service...\e[0m"
sudo systemctl stop postgresql.service
echo -e "\e[32mDone\e[0m"
echo ""

# Current PostgreSQL status
echo -e "\e[1;33mCurrent PostgreSQL status...\e[0m"
sudo systemctl status postgresql
echo -e "\e[32mDone\e[0m"
echo ""

# chown the existing PostgreSQL installation
echo -e "\e[1;33mchown the existing PostgreSQL installation...\e[0m"
sudo chown -R foo:foo /var/lib/postgresql/15/main/
echo -e "\e[32mDone\e[0m"
echo ""

# Remove the existing PostgreSQL files
echo -e "\e[1;33mRemove the existing PostgreSQL files...\e[0m"
sudo rm -fr /var/lib/postgresql/15/main/*
echo -e "\e[32mDone\e[0m"
echo ""

# Copy the latest backup to the PostgreSQL target location
echo -e "\e[1;33mCopy the latest backup to the PostgreSQL target location...\e[0m"
sudo cp -R /home/foo/Backups/calckey/postgresql/* /var/lib/postgresql/15/main/
echo -e "\e[32mDone\e[0m"
echo ""

# Make the PostgreSQL user take ownership of the target location
echo -e "\e[1;33mMake the PostgreSQL user take ownership of the target location...\e[0m"
sudo chown -R postgres:postgres /var/lib/postgresql/15/main/
echo -e "\e[32mDone\e[0m"
echo ""

# Start the PostgreSQL service
echo -e "\e[1;33mStart the PostgreSQL service...\e[0m"
sudo systemctl start postgresql.service
echo -e "\e[32mDone\e[0m"
echo ""

# Current PostgreSQL status
echo -e "\e[1;33mCurrent PostgreSQL status...\e[0m"
sudo systemctl status postgresql
echo -e "\e[32mDone\e[0m"
echo ""

# Restore the calckey /files/ directory
echo -e "\e[1;33mRestore the calckey /files/ directory...\e[0m"
sudo cp /home/foo/Backups/calckey/files/* /home/calckey/calckey/files
echo -e "\e[32mDone\e[0m"
echo ""

The script needs running using:

bash /etc/init.d/restore_calckey.sh

To see the correctly coloured prompts.

Some extra notes on running my Calckey Fediverse Server

Federation

Federation was straightforward and happened rather quickly.

I posted that this was a new, self-hosted instance and would appreciate a boost; within a couple of days I was federated with over 300 other Fediverse servers (instances).

Tweaking my Calckey Fediverse Server

Right now this is a single user instance so it’s just me.

I’ve turned off the Global Timeline as it was whizzing past far too quickly

I’ve also turned off the Local Timeline as there are no other people on the server.

To save space I’ve also set the files to not cache.

Finally

For anyone interested in getting into the SQL side, pgAdmin is useful.

I installed it using.

curl -fsS https://www.pgadmin.org/static/packages_pgadmin_org.pub | sudo gpg --dearmor -o /usr/share/keyrings/packages-pgadmin-org.gpg

sudo sh -c 'echo "deb [signed-by=/usr/share/keyrings/packages-pgadmin-org.gpg] https://ftp.postgresql.org/pub/pgadmin/pgadmin4/apt/jammy pgadmin4 main" > /etc/apt/sources.list.d/pgadmin4.list && apt update'

sudo apt update

sudo apt install pgadmin4

A screenshot of the Linux application pgAdmin, used to administer PostgreSQL databases. The Calckey Fediverse Server uses PostgreSQL as its back end darabase engine. pgAdmin Screenshot

Anyway, if you feel like following I’m at @nanode@calckey.consummatetinkerer.net no longer using Calckey; it rebranded to Firefish and then died a slow death.

All of the Calckey code examples can also be found on Forgejo , along with some SQL Snippets .

However you Fediverse, Enjoy!