In this article, I’ll guide you through the process of self-hosting Bearlytics with Kamal. It’s a bare-bones alternative to Google Analytics (and even Plausible Analytics - see my installation guide with Kamal).
I saw it online and immediately knew it was my kind of jam:
- low memory footprint
- runs on SQLite
- simple to use and maintain
- lightweight tracking script
It’s designed to be self-hosted, and I love simple self-hosted products (I develop them myself).
I come from the Ruby ecosystem and prefer deploying with
Kamal. Its configuration file looks almost identical
to docker-compose.yml, which Bearlytics already ships with, so using Kamal felt
like a natural fit.
Requirements
Hardware
Bearlytics will run on virtually any VPS or hardware. My running container, with no traffic, consumes only 56 MiB of RAM. Impressive!
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
0db0cbf3fba1 bearlytics-web-9a7059c5bfe6d403d8bf2de40eaf845956ce69ea 0.02% 55.87MiB / 7.57GiB 0.72% 269kB / 582kB 147kB / 13.8MB 3
Go to Hetzner Cloud and grab the cheapest plan (you’ll be totally fine).
Subdomain
To self-host Bearlytics, you’ll need a subdomain, for example
analytics.example.com.
On Cloudflare, create an A record pointing to your server’s IP address. This
will allow you to access Bearlytics at
https://analytics.example.com.
Step-by-step guide
To understand what we’ll be doing, let’s take a look at the docker-compose.yaml file from the repository and translate it into a Kamal configuration.
Bearlytics has no external dependencies: it’s a single container. All we need to do is set a few environment variables and we’re good to go.
Step 1: Clone the Bearlytics repo
Start by cloning the repository:
git clone --single-branch https://github.com/HermanMartinus/bearlytics bearlytics
cd bearlytics
Step 2: Branch out
We don’t want to accidentally push these changes upstream. We’ll be working with our own configuration values, and it’s unlikely the Bearlytics author would want this opinionated setup merged.
Create a new Git branch:
git checkout --b kamal
Step 3: Generate Kamal configuration:
Install Kamal if you don’t already have it (via RubyGems):
gem install kamal
Then generate the Kamal configuration:
kamal init
You should see output similar to this:
Created configuration file in config/deploy.yml
Created .kamal/secrets file
Created sample hooks in .kamal/hooks
We won’t need hooks, so delete that directory:
rm -rf .kamal/hooks
Step 4: Update .gitignore
Next, add the generated files to .gitignore so we don’t accidentally leak
secrets:
# .gitignore
!.kamal
!.kamal/secrets
!.config
!config/deploy.yml
Step 5: Setting up Kamal secrets
Bearlytics requires several mandatory environment variables:
SECRET_KEY: Django secret keySALT_SECRET: Secret key used to hash PIIDEBUG: Set to False in productionDB_PATH: SQLite database location (default:/app/db/db.sqlite3)ALLOWED_HOSTS: Comma-separated list of allowed hostsCSRF_TRUSTED_ORIGINS: Comma-separated list of trusted origins
We’ll define most of them in the config/secrets file generated by Kamal. It
should look like this:
DEBUG=$DEBUG
SECRET_KEY=$SECRET_KEY
SALT_SECRET=$SALT_SECRET
DB_PATH=$DB_PATH
CSRF_TRUSTED_ORIGINS=$CSRF_TRUSTED_ORIGINS
Now we need to populate these values from the environment. I’ll use a .env
file and the dotenv Ruby gem (gem install dotenv). Kamal also supports
several other approaches, which are covered in the
documentation.
- Generate
SECRET_KEYandSALT_SECRETusing any password generator.opensslworks great. DB_PATHrefers to the path inside the Bearlytics Docker container.CSRF_TRUSTED_ORIGINSshould point to your installation URL.
Here’s how .env will look like:
# .env at the bearlytics root directory
SECRET_KEY=$(openssl rand -base64 48)
SALT_SECRET=$(openssl rand -base64 48)
DB_PATH="/app/data/production.sqlite3"
CSRF_TRUSTED_ORIGINS="https://analytics.example.com"
That’s it for secrets. Now we just need to tell Kamal where and how to deploy the app.
Step 6: Update Kamal configuration
We’re almost there. Let’s update the Kamal configuration file. I’ll walk you through the important sections and then provide the full config at the end.
First, set the service name and image:
service: bearlytics
image: bearlytics
Next, define the servers. We’ll use a single server named web:
servers:
web:
- <your-server-ip>
Now configure kamal-proxy to enable SSL. We’ll use the subdomain created earlier.
Important: Bearlytics runs on port 8000, but kamal-proxy assumes port
3000 by default, so we need to override that.
proxy:
ssl: true
host: analytics.example.com
app_port: 8000
healthcheck:
path: /script.js
We also define a health check that hits /script.js. By default, Kamal pings
/up, which Bearlytics doesn’t implement. /script.js is guaranteed to exist
because it’s the tracking script itself.
Next, we’ll build the image locally and use Kamal’s local registry feature so we don’t need to push anything to GHCR or Docker Hub:
registry:
server: localhost:5555
Wire up the environment variables:
env:
clear:
DEBUG: false
secret:
- DB_PATH
- SALT_SECRET
- SECRET_KEY
- CSRF_TRUSTED_ORIGINS
Now mount a volume for the database so we get persistence and can make backups if needed:
volumes:
- "/root/bearlytics-storage:/app/data"
Create the directory on your VPS and adjust permissions:
mkdir /root/bearlytics-storage
chown -R 1000:1000 /root/bearlytics-storage
Finally, specify the build architecture:
builder:
arch: amd64
Here’s the full configuration for convenience:
service: bearlytics
image: bearlytics
servers:
web:
- <your-server-ip>
proxy:
ssl: true
host: analytics.example.com
app_port: 8000
healthcheck:
path: /script.js
registry:
server: localhost:5555
env:
clear:
DEBUG: false
secret:
- DB_PATH
- SALT_SECRET
- SECRET_KEY
- CSRF_TRUSTED_ORIGINS
volumes:
- "/root/bearlytics-storage:/app/data"
builder:
arch: amd64
To verify everything is wired correctly, run:
% kamal config
Wonderful! If everything looks good, commit your changes:
git add .
git commit -m "Add Kamal configuration"
Step 7: Deploy Bearlytics
I deployed Bearlytics on a server that was already provisioned with Kamal. If
you’re using a fresh server, you’ll probably want to run kamal setup first.
In my case, the server was already running Kamal-managed containers, so I simply ran:
% dotenv kamal deploy
The deployment should take about a minute.
Once it’s done, visit
https://analytics.example.com and you should see the
Bearlytics sign-up page.
Congratulations, you’ve just self-hosted Bearlyrics with Kamal! I’m proud of you!