Self-hosted service
thinkst/canarytokens-docker avatar
thinkst/canarytokens-docker

canarytokens-docker: self-hosted tripwires on your own domain

Docker configuration to quickly setup your own Canarytokens.

675 stars121 forksDockerfileBSD-3-Clause

At a glance

What is it?
canarytokens-docker packages the Canarytokens server as a Docker Compose stack, so a team can run its own tokens without sending data to a third party. The setup needs real domains, two environment files, an email provider and a WireGuard key seed, and the deployment lives or dies on DNS being configured correctly.
Who is it for?
Adopt canarytokens-docker if your organisation needs tripwire tokens on infrastructure you control, and you are able to hand over at least one domain, an email provider and the patience to get DNS right. Skip it if you only need a couple of tokens as a hosted service, since the operational cost here is a public Docker host and name servers of your own, or if you cannot accept that every alert path runs through your mail provider.
Can I use it commercially?
Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly Dockerfile, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A Canarytokens server you host, not a service you rent

The premise is short: Canarytokens help track activity and actions on your network, and this repository is the Docker configuration to set up your own.

That matters for a specific reason. A canary token is a deliberate marker, something like a credential, a file or a hostname that an attacker who reaches it cannot tell apart from a real one. If the tokens are generated by a hosted service, that service sees every alert and every request, and the operators of your honeypot infrastructure are effectively a third party in your detection chain. Self hosting removes that party.

The project is by Thinkst Applied Research, the same group behind the commercial Canarytokens offering, and the licence is BSD-3-Clause.

The prerequisites are where the difficulty starts. You need at least one domain name, and if you want PDF-opening tracking you need at least two. You need an internet-facing Docker host, and the README points at the Docker installation documentation for setting one up on Linux. Nothing here assumes a cloud provider, but a public IP address is a hard requirement rather than a convenience.

The token types themselves are documented in the project wiki rather than in this README, which is why the FAQ link at the top of the page is the first thing a new user is pointed at.

Three containers over one shared service definition

The compose file is the clearest view of the architecture. Each service extends a common definition rather than repeating it:

yaml
version: '3'
services:
  redis:
    extends:
      file: common-services.yml
      service: redis_common
  frontend:
    extends:
      file: common-services.yml
      service: frontend_common
    container_name: frontend
  switchboard:
    extends:
      file: common-services.yml
      service: switchboard_common
    container_name: switchboard

So the stack is a frontend, a switchboard and Redis, with the shared building blocks living in common-services.yml and the specific details in the top level compose file. The repository also carries an nginx/ directory and a certbot-nginx/ directory, and the compose file references a log-volume, which is where the two log files named in the environment configuration end up.

The split between frontend and switchboard is worth noting because the environment files mirror it. The frontend serves the token generation interface, and the switchboard is the part that responds when a token is triggered. The README describes the front end as accessible at http://example1.com/generate once the stack is up, and the example configuration assigns the public IP to the switchboard triggers while the frontend is served from a separate domain.

Two more compose variants exist for the same stack: docker-compose-letsencrypt.yml for the HTTPS path, and the AWS logging variants, docker-compose-aws-logging.yml and docker-compose-aws-logging-letsencrypt.yml, for deployments that push logs elsewhere.

The .dist env files exist so your settings survive a pull

Configuration lives in two files, and the way they are distributed is a small lesson worth repeating. The repository ships switchboard.env.dist and frontend.env.dist. You copy and rename them to switchboard.env and frontend.env, and the README explains why: it ensures that your configuration does not get blown away if you pull changes.

Each file has a Required Settings section and an Optional Settings section, and the instruction is explicit that the optional ones have sane defaults and should be left alone unless you have a reason to change them.

The frontend example shows the general token domains and the PDF-specific ones:

bash
#These domains are used for general purpose tokens
CANARY_PUBLIC_IP=1.1.1.1
CANARY_DOMAINS=example1.com,example2.com

#These domains are only used for PDF tokens
CANARY_NXDOMAINS=example3.com

#Requires a Google Cloud API key to generate an incident map on the history page with the Maps JavaScript API
CANARY_GOOGLE_API_KEY=<grab google maps api key>
LOG_FILE=frontend.log

The switchboard file carries the alert delivery settings, and there is a choice to make between mailgun, SMTP and sendgrid as the email provider:

bash
CANARY_PUBLIC_DOMAIN=mydomain.com
LOG_FILE=switchboard.log
CANARY_MAILGUN_DOMAIN_NAME=x.y
CANARY_MAILGUN_API_KEY=zzzzzzzzzz
[email protected]
CANARY_ALERT_EMAIL_FROM_DISPLAY="Example Canarytokens"
CANARY_ALERT_EMAIL_SUBJECT="Canarytoken"
CANARY_WG_PRIVATE_KEY_SEED=vk/GD+frlhve/hDTTSUvqpQ/WsQtioKAri0Rt5mg7dw=

The last variable is the one with a hard requirement behind it. You generate a single unique WireGuard key seed and set it as CANARY_WG_PRIVATE_KEY_SEED in both files, using this command:

bash
dd bs=32 count=1 if=/dev/urandom 2>/dev/null | base64

The same value has to appear in switchboard.env and frontend.env, and the example shows the base64 output in that role.

DNS decides whether the tokens can work at all

The setup section is short but it hides the part that goes wrong most often. You boot the Docker host and note its public IP. Then you configure your domains so their nameservers point to the public IP of that host, and the README stresses that this requires a change at your registrar, and that simply changing NS records in the zone file is insufficient. You also need an A record for the domain pointing at the public IP.

The reason for the name server requirement is the token design itself. A canary token is often a hostname that resolves to a server you control, and the alerting depends on the resolution path leading back to your switchboard. If the registrar still points elsewhere, the token never reaches your infrastructure and nothing fires.

There is a documented shortcut for the PDF case. If you own only one domain but want PDF tokens, you can use subdomains for CANARY_NXDOMAINS, setting it to nx.example.com for an example.com domain, and then add an NS record for nx.example.com mapping to example.com in your DNS manager console. The separate NXDOMAINS variable is what keeps PDF token domains apart from the general purpose token domains, and the prerequisite of two domains exists because that separation needs a second name to point at.

So the operational reality is that the token deployment inherits the fragility of DNS.

Starting the stack, and the v3 migration notes

Once the domains resolve and the env files are filled in, the deployment is two commands. The repository is cloned first:

bash
$ git clone https://github.com/thinkst/canarytokens-docker
$ cd canarytokens-docker

Then the images are downloaded and started:

bash
$ docker compose up

That runs the front end and the switchboard in the foreground, so you can see the startup output, and the front end is reachable at http://example1.com/generate. To run it in the background instead, the same command with the detach flag:

bash
$ docker compose up -d

The README also has a migration section for people coming from the v2 layout, and the details matter if you have an existing deployment. The compose file changed name to docker-compose.yml, docker-compose no longer works, and you need to run docker network prune before bringing the instance up with docker compose. Older Docker versions have to be upgraded first, and the v2 Dockerfile is no longer in the repository, so running v2 means using the tagged image thinkst/canarytokens:v2_latest. The project recommends moving to v3.

One more prerequisite in that path: the README's compose install snippet uses pip to install docker-compose, and warns that PyYAML errors mean the libyaml development package is missing.

HTTPS runs through a separate compose file

TLS is handled by a separate compose file, docker-compose-letsencrypt.yml, which automates most of getting a server up with HTTPS. The configuration goes in certbot.env, and the values are a domain and an email address, which are necessary for the certbot registration process:

bash
# Specify a single domain name
MY_DOMAIN_NAME=example.com

# or multiple domains names with this different key (comment out MY_DOMAIN_NAME above if you do):
# MY_DOMAIN_NAMES=example.com anotherexample.net thirdexample.org

[email protected]

You bring the server up with docker compose -f docker-compose-letsencrypt.yml up, which stays in the foreground so you can confirm everything started, and then bring it down with the matching down command to get to a clean slate before the next start. The certbot-nginx/ directory in the repository holds the pieces for that path, and nginx/ holds the plain HTTP configuration.

The README also lists an option for putting basic auth in front of the Canarytokens site. That is a sensible default for an exposed token generation interface, since a public page that mints tokens for anyone who finds the URL is not what you want on the open internet.

Tokens live in dump.rdb, and the wipe is one file

Persistence is handled by Redis, and the file that matters is dump.rdb, which lives in the canarytokens-docker/data directory outside the containers. The README is explicit that the tokens are saved in that Redis database file, and that deleting dump.rdb wipes all your tokens.

That single-file storage model is a genuine advantage for an operation that has to be reproducible. The data directory can be backed up, copied between hosts and inspected, and the loss of a container does not lose the token list. It also means the file is the crown jewel of the deployment, since anyone who obtains it can read the token records.

The repository has a small but telling layout. There is a canarytokens/ directory, nginx/ and certbot-nginx/ for the web layers, a data/ directory for the Redis file, a .pre-commit-config.yaml, and the certificate and environment templates alongside the compose variants. There are no GitHub releases, so the compose files and images are tracked in the repository rather than versioned as artefacts, and the last push was on 2026-07-28.

Because the project is a Compose configuration rather than an application, the upgrade cost is a git pull plus a compose up, and the migration notes above are the part to read carefully when you do it.

Editorial conclusion

Adopt canarytokens-docker if your organisation needs tripwire tokens on infrastructure you control, and you are able to hand over at least one domain, an email provider and the patience to get DNS right. Skip it if you only need a couple of tokens as a hosted service, since the operational cost here is a public Docker host and name servers of your own, or if you cannot accept that every alert path runs through your mail provider. Before the first run, copy switchboard.env.dist and frontend.env.dist to their non-dist names, generate the WireGuard key seed once with the documented dd command and place it in both files, and confirm your A records point at the host. The last push was on 2026-07-28 and the repository has no GitHub releases.

Frequently asked questions

What do I need before deploying canarytokens-docker?

At least one domain name, two if you want PDF opening tracking, and an internet-facing Docker host with a public IP. You also need to change your name servers at the registrar and add an A record pointing at that IP, and you need to pick an email provider for alerts.

How do I configure the alerts in canarytokens-docker?

Copy switchboard.env.dist and frontend.env.dist to switchboard.env and frontend.env, then fill in the Required Settings. You choose between mailgun, SMTP and sendgrid as the email provider, and the relevant keys are in the switchboard file.

Where are the tokens stored?

In a Redis database file that sits outside the containers, in the canarytokens-docker/data directory as dump.rdb. Deleting that file wipes all your tokens, so it is the file to back up and to protect.

How do I enable HTTPS for my Canarytokens server?

Use the separate letsencrypt compose file and fill in certbot.env with your domain and email address, then start with docker compose -f docker-compose-letsencrypt.yml up. The same file also has a variant that logs to AWS.

Official sources

  1. Issues
  2. License: BSD-3-Clause
  3. README
  4. thinkst/canarytokens-docker on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/thinkst-canarytokens-docker.svg)](https://hysenlabs.com/projects/thinkst-canarytokens-docker)

Was this useful?