Running Kachhapa- The World Turtle on Raspberry Pi

Kachappa is a project I started some years ago as a way to manage character inventory digitally in an environment that didn't have any Internet access, so everything had to be handled locally. Or more accurately, it needed to be locally hosted. Thus, Raspberry Pi.

What started as a simple inventory management web app quickly grew in scope. Each player would need an account so the web app would know what character inventory to display. The GM would need an account which let them create new items in the database and also issue items to players. In order for the player's page to update when a new item is issued, the web app would need to utilize WebSockets. And if it was gonna use WebSockets anyways and send messages to players (behind the scenes), why not let the users message each other as well? So that led to a Chat widget that has been the most useful and annoying feature to use. That dumb chat widget has been the biggest pain to work on and it seems to break after every update, even when nothing changed.

Some other features got added as well. It wasn't very hard to implement a Journal for each user and a Library page that would let the users read PDFs or view JPEG screenshot snippets of reference books if I kept getting asked to look up the same information or stat block every time.

Eventually, I realized it would be nice to have an option for multiple games instead of just one, which led to me redesigning the database so there is a unique combination for each user-character-game combination. At that time, I also switched from SQLite to PostgreSQL since the later would let me store entire JSON files in byte format, which was useful as I started working on a character creation system (that is still a Work in Progress). I also added a character sheet page for players that used rearrangable tiles for each element, and I wanted to be able to populate those tiles like Feats with appropriate content.

This is still a somewhat ongoing project, although I don't work on it as much anymore. The latest-ish version can be found on my GitHub, which includes instructions for running the project locally in a Docker container. This article is focused on 

Create SSH Keys for the Pi

I'm going to start this walkthrough with the assumption of a newly flashed Rasbperry Pi. For this project, I'm using a Pi 4 and the 64-bit version of Rasbperry Pi OS Lite (no desktop environment) since this will be a headless server.

The first step is to run ssh-keygen -t rsa on your local machine (or whatever you'll be using for development) to generate a public/private key pair. That script will ask you to provide a path to store the key, with a default path of something like /Users/<username>/.ssh/id_rsa, which should be fine. Just hit Enter to accept that. Once the key pair is generated, use the ssh-copy-id command to copy the public key to the Pi.

ssh-keygen -t

ssh-copy-id -i ~/.ssh/id_rsa.pub <username>@raspberrypi.local

Setting Up the Pi

Now that you can easily use Secure Shell to work on the Pi, we can start configuring the actual Pi services. Here is a list of commands that will install some of the basic services needed for the Pi to host the website and host the Postgres database, run a Flask server locally, and also run a RabbitMQ server that is supposed to handle socket messages and such.

sudo apt update && sudo apt upgrade -y

sudo apt install -y nginx git python3-pip python3-venv python3-dev \

  build-essential pkg-config \

  libpq-dev postgresql postgresql-contrib \

  rabbitmq-server

Once that is done updating and installing packages, the next step is to start and enable Nginx, Postgres, and RabbitMQ:

sudo systemctl enable --now nginx

sudo systemctl enable --now postgresql

sudo systemctl enable --now rabbitmq-server

This project uses Supervisor to manage the Gunicorn instance that actually runs Flask, so we'll also need to install that:

sudo apt install -y supervisor

sudo systemctl enable --now supervisor

Setting Up mDNS

In order for the Pi to broadcast its name (raspberrypi.local) on the WiFi network, we need to install and configure Avahi.

sudo apt install -y avahi-daemon

sudo systemctl enable --now avahi-daemon

By default, this will broadcast whatever the hostname of the Pi is. In my case, I named the Pi "rasbperry", so the address will be raspberrypi.local, which is what I wanted. If you want a different name, you can run `sudo hostnamectl set-hostname raspberrypi` and then restart Avahi with `sudo systemctl restart avahi-daemon`

After this, I've created an `install.sh` script that handles most of the other configurations- creating directories, setting up the Wi-Fi hosting, and installs Python packages.