--- title: "Running Wakapi, a Self-Hosted WakaTime Compatible Backend for Coding Stats" description: "A guide to install Wakapi, a self-hosted WakaTime compatible backend for your coding stats" # linkTitle: date: 2023-08-21T01:18:54+07:00 lastmod: draft: false noindex: false featured: false # comments: false nav_weight: 1000 # nav_icon: # vendor: bootstrap # name: toggles # color: '#e24d0e' series: # - Tutorial categories: - Self-Hosted - Programming - SysAdmin - Privacy tags: - WakaTime - Wakapi - Nginx - Go - ActivityWatch - CodeStats images: # menu: # main: # weight: 100 # params: # icon: # vendor: bs # name: book # color: '#e24d0e' authors: - ditatompel --- **Wakapi** is a minimalist, __self-hosted__ **WakaTime** - compatible backend for coding statistics. It's cross-platform (Windows, macOS, Linux) and can be self-hosted to your local computer or your own server, so your data is really yours. This article will guide you how to run Wakapi on Linux operating system. --- ## Introduction As someone who extensively use computers on a daily basis, particularly performing server maintenance and coding, I'm always curious about what I've been working on, which projects consume the most of my time, and which programming languages I use the most. Over the past year, I've tried several services, from [Activity Watch](https://activitywatch.net/), [CodeStats](https://codestats.net/) to [WakaTime](https://wakatime.com/). With **Activity Watch**, while the backend can be installed on a local or remote server, I found it to be somewhat _resource-intensive_. While **CodeStats** and **WakaTime** were excellent, the coding statistics data was sent to their servers; this aspect was a concern for me. A few days ago, I found a solution for that problem: [Wakapi](https://wakapi.dev/). It's an API endpoint **compatible with the WakaTime client**, and it can be _self-hosted_. The **Wakapi server** is built using the **Go** programming language and can be run on various operating systems, including Windows, macOS (both `ARM` and `x86_64`), and Linux (both `ARM` and `x86_64`). In this article, I want to share my experience installing and running Wakapi on a Linux server. ## Server Installation Before we begin, there are some prerequisites to meet in order to follow this article: - Comfortable using Linux terminal - A WakaTime client already installed and working properly - A Linux server / laptop / PC - A web server (for this article, I'm using Nginx. _Optional, but **recommended if Wakapi will be accessed publicly**_) There are a few ways to run your own Wakapi server: 1. Using precompiled binary 2. Using Docker 3. Compiling from source code Since **Go** is already installed on my server, I'll be using the third option here — compiling directly from source code. ### System Preparation & Compiling Executable Binary First, prepare the system by creating a new system user: ```shell sudo useradd -r -m --system -d /opt/wakapi -s /bin/bash wakapi ``` Clone the [mutey/wakapi repository](https://github.com/muety/wakapi) and compile the executable binary: ```shell # clone repo git clone https://github.com/muety/wakapi.git # build executable binary cd wakapi go build -o wakapi ``` ### Wakapi Configuration Setup After the compilation process is complete, move the executable binary to the `wakapi`'s `$HOME` directory that we created earlier: ```shell sudo mv wakapi /opt/wakapi/ ``` Download a sample configuration: ```shell sudo curl -o /opt/wakapi/wakapi.yml https://raw.githubusercontent.com/muety/wakapi/master/config.default.yml # Change file ownership to the wakapi user sudo chown wakapi:wakapi /opt/wakapi/wakapi.yml /opt/wakapi/wakapi ``` Then, edit the `/opt/wakapi/wakapi.yml` configuration file as needed. For instance, if I'm using the subdomain `wakapi.example.com` with **Nginx** as a _reverse proxy_ for Wakapi, I'd set the `listen_ipv4` to `127.0.0.1` and `public_url` to `https://wakapi.example.com`. Adjust other configurations such as database connection, SMTP email, etc. if you need to. ### Creating a Systemd Service Creating **Systemd** service making it easy to start or restart the Wakapi service. Create `/etc/systemd/system/wakapi.service` and adapt from these following example configuration: ```systemd [Unit] Description=Wakatime Wakapi StartLimitIntervalSec=400 StartLimitBurst=3 # Optional, and if you using MySQL or PostgreSQL Requires=mysql.service After=mysql.service [Service] Type=simple WorkingDirectory=/opt/wakapi ExecStart=/opt/wakapi/wakapi -config /opt/wakapi/wakapi.yml User=wakapi Group=wakapi RuntimeDirectory=wakapi # creates /run/wakapi, useful to place your socket file there Restart=on-failure RestartSec=90 # Security hardening PrivateTmp=true PrivateUsers=true NoNewPrivileges=true ProtectSystem=full ProtectHome=true ProtectKernelTunables=true ProtectKernelModules=true ProtectKernelLogs=true ProtectControlGroups=true PrivateDevices=true CapabilityBoundingSet=CAP_NET_BIND_SERVICE ProtectClock=true RestrictSUIDSGID=true ProtectHostname=true ProtectProc=invisible [Install] WantedBy=multi-user.target ``` Then, reload and start the Wakapi service: ```shell sudo systemctl daemon-reload sudo systemctl enable wakapi.service --now # Check if the service is running properly systemctl status wakapi.service ``` If everything is running smoothly, proceed to the next step for Nginx reverse proxy configuration. ### Nginx Reverse Proxy For the Nginx configuration, no special adjustments are needed. You can simply use a standard reverse proxy configuration. For example: ```nginx server { listen 80; server_name wakapi.example.com; root /opt/wakapi; access_log off; location /.well-known/acme-challenge/ { allow all; } location / { return 301 https://$host$request_uri; } } server { listen 443 ssl http2; server_name wakapi.example.com; access_log off; ssl_certificate /path/to/fullchain.pem; ssl_certificate_key /path/to/privkey.pem; # bla bla bla location / { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Real-IP $remote_addr; proxy_set_header Host $http_host; proxy_pass http://127.0.0.1:3000; } } ``` Adjust the `proxy_pass` to match with the `listen_ipv4` and `port` configurations from your `/opt/wakapi/wakapi.yml`. Now, try accessing your Wakapi server and register for an account. You'll receive an API key that you'll need to set in your **WakaTime client**. ## WakaTime Client Configuration Your server is ready to accept your __"heartbeat"__, configure your **WakaTime client** to connect to your __self-hosted__ **Wakapi instance**. To do so, modify the `api_url` and `api_key` in your `.wakatime.cfg` to match with your server configuration. For example: ```ini [settings] api_url = https://wakapi.example.com/api api_key = Your-API-Key-From-Your-Wakapi-Server ``` Start coding and check your coding activity on the Wakapi Dashboard. Wakapi also have a feature to export metrics to **Prometheus** format and then [visualize them with Grafana](https://grafana.com/grafana/dashboards/12790-wakatime-coding-stats/). ![Example Wakapi Grafana Dashboard](grafana-wakapi.png#center) You can also integrate it with [GitHub Readme Stats](https://github.com/anuraghazra/github-readme-stats#wakatime-week-stats) to display your coding activity on your GitHub profile page.