Wavelog - my self-hosted logging solution
I love to self-host applications, so when I ran across Wavelog, "a self-hosted PHP application that allows you to log your amateur radio contacts anywhere." I was excited to get it set up.
Wavelog is a fork of Cloudlog, but I chose Wavelog due to its native docker support. I'm running it from a server at my house, but this could also be done with a virtual server hosted by a cloud provider (like AWS, Linode, or many others).
Features
- Centralized logbook with a nice UI, easy to input QSOs manually or via an API
- Automatic uploads to LOTW, QRZ, and eQSL - along with sites I don't have set up yet like ClubLog, HRDLog, and others
- Can be a log source in GridTracker using an API key, my WSJT-X FT8 contacts are logged automatically!
- Existing ADIF files can be uploaded
- Support for multiple logbooks/locations/station setups
Getting the VM set up
I'm using Ubuntu Server 24.04 LTS installed on a VM that has 8gb RAM and 4 CPU cores - this might be more than is needed (their site claims it can run on a Raspberry Pi).
I installed Docker with these instructions, which is also helpful if you chose to run this behind Cloudflare zero trust and need a tunnel on the same host to avoid port forwarding.
Dockerfile
I made a folder for wavelog (at /home/ryan/wavelog/docker-compose.yml), and created my docker-compose.yml with the following contents:
services:
wavelog-db:
image: mariadb:11.3
container_name: wavelog-db
environment:
MARIADB_RANDOM_ROOT_PASSWORD: yes
MARIADB_DATABASE: wavelog
MARIADB_USER: wavelog
MARIADB_PASSWORD: STRONG_PASSWORD # <- Insert a strong password here
volumes:
- wavelog-dbdata:/var/lib/mysql
restart: unless-stopped
wavelog-main:
container_name: wavelog-main
image: ghcr.io/wavelog/wavelog:latest
depends_on:
- wavelog-db-domain
environment:
CI_ENV: docker
volumes:
- wavelog-config:/var/www/html/application/config/docker
- wavelog-uploads:/var/www/html/uploads
- wavelog-userdata:/var/www/html/userdata
ports:
- "8086:80"
restart: unless-stopped
volumes:
wavelog-dbdata:
wavelog-uploads:
wavelog-userdata:
wavelog-config:
driver: local
driver_opts:
o: bind
type: none
device: /home/<YOUR_PATH>/wavelog/configI also wanted to be able to easily edit the config files (since I would be setting up a custom domain), so I created a config folder in the wavelog directory and mapped it in my dockerfile. It got populated with config files once the docker stack ran for the first time.
Next, I ran docker compose up -d in the wavelog directory to pull the docker images and start the services.
Going to http://[your-server-ip]:8086/install allowed me to configure Wavelog without my custom domain, and you can stop here if you don't want to expose your service publicly and just want to use the IP in your browser to access it.
Cloudflare Zero Trust
Cloudflare controls the DNS on my domain, and I use their free Zero Trust offerings, paired with Tunnels, to securely expose self-hosted services to the internet. Cloudflare Tunnels can do this on their own, but with Zero Trust an authentication page is first shown before Wavelogs and users will need to be on an allow list in order to sign in and get past that page.
More details about setting up Tunnels and Zero Trust applications can be found here: https://medium.com/@svenvanginkel/self-hosting-securely-with-cloudflare-zero-trust-tunnels-0a9169378f78
Once I had logger.mydomain.com setup as a host on the tunnel, and a Zero Trust application in front of it for access control. I edited wavelog/config/config.php to set the base_url to my domain https://logger.mydomain.com/ and restarted the docker stack.
Note: if you want to log QSOs via the Wavelog API (like with an api key in GridTracker), zero trust can block the API call, it helps to have the CloudFlare Warp program installed on your computer, and allow the application to authorize warp clients.
Conclusion
Wavelog, fronted by Cloudflare Zero Trust, is my primary logging application, and with Cloudflare Warp on the computer running GridTracker/WSJT-X it auto-logs my FT8 connections. At the same time, I can manually log contacts from any browser and syncing logs to QRZ, LOTW, and eQSL are handled automatically!