Skip to main content

Setting up Plausible Analytics on NixOS

·4 mins
Table of Contents

I’ve been looking to set up analytics on my blog and maybe some other websites. I’ve avoided Google Analytics as it’s quite insideous and would like to avoid giving them my readers’ data willingly and for free.

From my research, I found Plausible and Umami to be good alternatives. Both collect so little data that cookie consent banners are not required and both are very minimalistic in their dashboards, focusing on what really matters.

A friend of mine is using Umami and is quite happy with his setup. Umami should also be lighter, as Plausible is designed to support a much larger number of connected websites. Despite all of that, I ended up choosing Plausible simply because it has an upstream NixOS module, allowing me to set it up quite trivially, whereas I would have to package Umami and setup its PostgreSQL integration manually or use containers, which I’m also trying to avoid in my self-hosted infrastructure.

This simple snippet is enough to set up a Plausible instance, all automatically configured for you.

{ self, config, lib, pkgs, ... }:

let domain = "";
in {
  age.secrets = {
    plausibleAdminPassword.file = "${self}/secrets/plausibleAdminPassword.age";
    plausibleReleaseCookie.file = "${self}/secrets/plausibleReleaseCookie.age";
    plausibleSecretKeybase.file = "${self}/secrets/plausibleSecretKeybase.age";

  services = {
    nginx.virtualHosts.${domain} = {
      forceSSL = true;
      enableACME = true;
      locations."/".proxyPass =

    plausible = {
      enable = true;

      adminUser = {
        # activate is used to skip the email verification of the admin-user that's
        # automatically created by plausible. This is only supported if
        # postgresql is configured by the module. This is done by default, but
        # can be turned off with services.plausible.database.postgres.setup.
        activate = true;
        email = "";
        passwordFile = config.age.secrets.plausibleAdminPassword.path;

      server = {
        baseUrl = "https://${domain}";
        secretKeybaseFile = config.age.secrets.plausibleSecretKeybase.path;

  # As this is a root on tmpfs system, we use the impermanence
  # NixOS module to persist WordPress state between reboots.
  # You can omit the next two lines if using a regular configuration.
  environment.persistence."/persist".directories =
    [ "/var/lib/private/plausible" "/var/lib/postgresql" ];

In this snippet I’m using agenix to manage secrets such as the admin password. You’re obvisouly free to use your secrets management tool of choice or you can just use file paths which are not in public version control systems.

As per the official documentation, the secretKeybaseFile’s contents should be generated with:

$ openssl rand -base64 64 | tr -d '\n' ; echo

For some unknown unreason, the admin password I set up didn’t work after the rebuild. I worked around that by using the reset password form on the login page. In my case, this worked out of the box as the host where I deployed this Plausible instance was also a mailserver. If yours isn’t, you may have to adjust the services.plausible.mail.* options accordingly.

All that’s left is to add a website in the dashboard. You’ll be presented with an HTML snippet which you should include on your website’s <head> tag to start collecting privacy-respecting analytics.

As optional configuration, I enabled email alerts for weekly and monthly reports and also traffic spikes, to avoid creating the common addiction of being permanently looking at the analytics dashboard instead of engaging in productive activities.

Conclusion #

I’m quite happy with this setup. As I said before, this gives me some insight into my readership without compromising their privacy.

For many months my only analytics were from the Google Search Console, as I was having configuration and compilation errros in the past when trying to set up Plausible in NixOS. Recently I decided to give it another go for no special reason and was pleasantly surprised to find out that it just works.

It seems to be possible to integrate Plausible with the Google Search Console API and that may be something I’ll look into in the future.

If you wish to work around your readers’ adblockers, this also seems to be possible using a proxy as to not trigger the usual adblocker filters, as explained in this article.

References #