Wakapi
There’s a nifty service, call WakaTime, that allows you to track your coding habits: the projects you work on, the languages, the file, and especially how long you work on everything. I was interested to have this kind of tracking, but didn’t feel like sharing my personal coding information with a company (moreover, there are limitations after a certain number of hours).
Luckily, the API is open and the CLI tools for WakaTime support alternative servers (and the plugin I use, the one for Rider, is based on the CLI tools). Because of this we have an open source, self-hostable version in Wakapi, a project mostly developed and coordinated by Ferdinand Mütsch. That was perfect to install on my YunoHost server. I will add here the steps I followed to produce a working installation, since there are a couple of tricks that stumped me for some days.
Docker installation
First of all, I chose to use the dockerized version of it, which is self-contained and based on a simple SQLite database. That’s more than enough for personal use (or at most inviting a couple of friends or someone from the polecule). To do that, I followed the instructions to install Docker on a Debian distribution:
sudo apt remove $(dpkg --get-selections docker.io docker-compose docker-doc podman-docker containerd runc | cut -f1)
sudo apt update
sudo apt install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
sudo tee /etc/apt/sources.list.d/docker.sources <<EOF
Types: deb
URIs: https://download.docker.com/linux/debian
Suites: $(. /etc/os-release && echo "$VERSION_CODENAME")
Components: stable
Signed-By: /etc/apt/keyrings/docker.asc
EOF
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
After that, I followed the Wakapi instructions linked above for creating the Wakapi docker container. The only difference is that I set the docker image to always restart, and a different port (3000 tends to be used by many self-hosted services, and I prefer to leave it free):
sudo docker volume create wakapi-data
SALT="$(cat /dev/urandom | LC_ALL=C tr -dc 'a-zA-Z0-9' | fold -w ${1:-32} | head -n 1)"
sudo docker run -d --init -p 9572:3000 -e "WAKAPI_PASSWORD_SALT=$SALT" -v wakapi-data:/data --name wakapi --restart=always ghcr.io/muety/wakapi:latest
PS: either don’t close this shell to perform the next few operations, or better yet temporarily save the value of the SALT bash variable.
Redirect YunoHost configuration (1/2)
Once this step was done, I moved on to put the YunoHost nginx reverse proxy in front of it, which is implemented by the Redirect app. The only relevant configurations were to set the redirect as an nginx reverse proxy, and the access level to “Visitors” (which means any user, unauthenticated too), since there’s no SSO integration with YunoHost.


Creating the initial user
At this point, I could log-in inside the portal and… I received error when trying to create the user. The problem was about the email, since I wanted to use my self-hosted email and the MX DNS check refused to work. Which brought another problem: logging in the docker machine, editing the configuration file, and saving it. I needed to login as root for it to work at all ,otherwise the bash simply hanged indefinitely:
sudo docker exec -it --user=root wakapi bash
Once inside, add vim (I’m totally incompetent with vi!):
apk add vim
And once this was done, I could edit the configuration file:
vim config.yml
In here, I changed the mail => skip_verify_mx_record to true, saved, and restarted docker for good measure, so I could also check that the docker machine for Wakapi started automatically:
sudo systemctl restart docker
Once that was done, I could create a user for myself. Once this was done, I closed the registrations changing the Wakapi configuration and restarting once again: security => allow_signup to false.
Addendum
It’s not enough for the Docker version of Wakapi to set allow_signup to false, as explained in this bug report. It’s also needed to overwrite a Docker environment variable. For this, we need to recreate the Docker machine, but remember to keep the same SALT variable as before, or the password you set won’t match any longer!
sudo docker container stop wakapi
sudo docker rm wakapi
sudo docker run -d --init -p 9572:3000 -e "WAKAPI_PASSWORD_SALT=$SALT" -e "WAKAPI_ALLOW_SIGNUP=false" -v wakapi-data:/data --name wakapi --restart=always ghcr.io/muety/wakapi:latest
In case you lost the SALT and already recreated the docker machine, like I did (sigh!), you can go into config.yml and enable the mails to make it possible from the interface to send the reset email. Personally, I haven’t found a combination of postfix and docker configuration that allowed a mail to be successfully sent from the docker machine to my user. What I resorted to was something more complicated. That is, enable the emails in the container with whatever setting:
mail:
enabled: true
Restart the machine, then send the recovery email from the interface. It will fail internally, but generate the reset token nonetheless. Now you can enter again, and check the database, after you’ve installed the sqlite CLI:
apk add sqlite
sqlite3 /data/wakapi.db
select reset_token from users;
This will display you the reset token. Now you can open your browser on https://wakapi.foxthesystem.space/set-password?token=<RESET_TOKEN_FROM_BEFORE> and reset your password.
Redirect YunoHost configuration (2/2)
Once this was done, I reached the hardest part for me. Once logged in, I was given the configuration to override in my .wakatime.cfg file (in my home directory), but the plugin did not send data correctly. The whole story is in my discussion on Wakapi’s GitHub and YunoHost forum post, but the point is that by default YunoHost’s SSO system (SSOWat) blocks an external application to send their own Authorization header to the apps behind. But the Authorization header is exactly how the API key is passed to Wakapi in order to know the user it’s receiving information from! So, you need to tell YunoHost to disable this anti-spoofing mechanism for this specific app (redirect__3 was the name of the redirect app in my case):
sudo yunohost app setting redirect__3 protect_against_basic_auth_spoofing -v false
sudo yunohost app ssowatconf
sudo systemctl reload nginx.service
Once this was done, the plugin could successfully send data to Wakapi, and after some time I could start to see the data!
