Self hosting Wakatime
Introduction
This article will show you how to properly deploy the Wakapi project on your dokku server.
Deployment strategy
Deploying to dokku using the default buildpack strategy is not possible as the project needs some custom configuration. So we will use the Dockerfile Deployment strategy.
Steps
The following are the steps needed to deploy the project.
Create the dokku app and add services
We will create a dokku app and the various services it needs.
dokku apps:create wakapi
dokku mysql:create wakapi # you can use any database you want
dokku mysql:link wakapi wakapi
dokku domains:set wakapi wakapi.example.com
# do this only if the dockerfile is not in the root of the repository
dokku builder-dockerfile:set wakapi dockerfile-path 'apps/wakapi/Dockerfile'
Create the required files
I normally keep all my self hosted projects in a single repository. So I will create
apps/wakapi folder in my repository.
The following files are required:
-
apps/wakapi/Dockerfile: The dockerfile that is reponsible for building the image.FROM ghcr.io/muety/wakapi:latest as builder FROM stephenc/envsub as deps FROM alpine:3 as runner RUN apk add ca-certificates curl tar ca-certificates tzdata # You might need to change the architecture to match your server RUN curl -L "https://github.com/IgnisDa/rust-libs/releases/download/v0.3.0%2Bconnection-string-parser/connection-string-parser-x86_64-unknown-linux-musl.tar.gz" --output csp.tar.gz ;\ tar -xvf csp.tar.gz ;\ mv connection-string-parser /bin/csp ;\ csp --version ;\ rm csp.tar.gz COPY --from=builder /app/wakapi /bin/wakapi COPY --from=deps /bin/envsub /bin/envsub COPY apps/wakapi/* / CMD /set-env-and-start.sh wakapi -config /config/config.yml -
apps/wakapi/config.yml: Next we have the wakapi config file.env: 'production' server: listen_ipv4: 0.0.0.0 # leave blank to disable ipv4 listen_ipv6: # leave blank to disable ipv6 tls_cert_path: # leave blank to not use https tls_key_path: # leave blank to not use https port: ${PORT:-5000} base_path: / public_url: '${SERVER_PUBLIC_URL}' # required for links (e.g. password reset) in e-mail app: import_batch_size: 200 heartbeat_max_age: '4320h' data_retention_months: -1 avatar_url_template: api/avatar/{username_hash}.svg db: dialect: '${DATABASE_DIALECT}' user: '${DATABASE_USER}' password: '${DATABASE_PASSWORD}' host: '${DATABASE_HOST}' port: ${DATABASE_PORT} name: '${DATABASE_NAME}' security: password_salt: '${SECURITY_PASSWORD_SALT}' insecure_cookies: true cookie_max_age: 172800 allow_signup: ${SECURITY_ALLOW_SIGNUP:-false} expose_metrics: false sentry: dsn: # leave blank to disable sentry integration mail: enabled: true provider: smtp sender: '${MAIL_SENDER}' smtp: host: '${SMTP_HOST}' port: ${SMTP_PORT} username: '${SMTP_USERNAME}' password: '${SMTP_PASSWORD}' -
apps/wakapi/set-env-and-start.sh: This is the script that will be used to set the environment variables and start the service.#!/usr/bin/env sh export DATABASE_USER="$(csp $DATABASE_URL --part user)" export DATABASE_PASSWORD="$(csp $DATABASE_URL --part password)" export DATABASE_HOST="$(csp $DATABASE_URL --part host)" export DATABASE_PORT="$(csp $DATABASE_URL --part port)" export DATABASE_NAME="$(csp $DATABASE_URL --part path)" export DATABASE_DIALECT="$(csp $DATABASE_URL --part scheme)" mkdir -p config (cat config.yml) | envsub --greedy-defaults > config/config.yml # delete the config file with placeholders rm config.yml echo "Wrote configuration..." echo "Starting service..." exec $@Remember to make the script executable using
chmod +x apps/wakapi/set-env-and-start.sh. -
apps/wakapi/CHECKS: Optionally, aCHECKSfile for zero downtime deploys.TIMEOUT=10 ATTEMPTS=5 WAIT=5 /api/health
Some notable things
Most of the above configuration is pretty simple, but here are some things to note.
- We use
envsubto replace the environment variables in the config file during runtime. - We use
connection-string-parserto parse the database url into the various parts. - We do not bake the configuration file with secrets into the image itself, this allows us to publish this image to a public registry without worrying about leaking secrets.
Set the environment variables
As you can see in the config file above, we have a lot of environment variables that
need to be set. We can set them using the dokku config:set command.
dokku config:set wakapi \
SERVER_PUBLIC_URL="https://wakapi.example.com" \
SECURITY_PASSWORD_SALT="supersecret" \
MAIL_SENDER="Wakapi <my@email.com>" \
SMTP_HOST="smtp.example.com" \
SMTP_PORT="587" \
SMTP_USERNAME="username" \
SMTP_PASSWORD="password"
Make sure you replace the values with your own.
Push the app
Next, we will make a commit and push the app to dokku.
git add .
git commit -m "Add wakapi configuration"
git push dokku main
Enable SSL
Once the deployment is successful, we can enable SSL using the letsencrypt plugin.
dokku letsencrypt:enable wakapi
Bonus
You can check the configuration file that was generated by entering the running container:
dokku enter wakapi web sh
# you are now inside the shell of the running container
cat "config/config.yml"
Client setup
After the self hosted instance is up and running, you can following these instructions to set up your client.
Conclusion
It is pretty straightforward to self host Wakatime. We used some tools that made it much easier. Be sure to visit their repositories and give them a star.