Skip to content

Your first verified tap

This guide takes you from the files on the Releases page to a tag that a phone can tap and that your own server checks. You don’t need to build anything.

  • NTAG 424 DNA tags. Stickers, cards or key fobs with this exact chip. Plain NTAG 213, 215 or 216 tags won’t work.
  • A way to set tags up: a USB NFC reader that speaks PC/SC (such as the ACS ACR122U), or an Android phone with NFC and the Knura app. This guide uses the reader.
  • A computer to run knurd (Linux, macOS or Windows) that stays on while you want taps to work.
  • Java 21 or newer on that computer.
Terminal window
sudo dnf install java-21-openjdk pcsc-lite pcsc-lite-ccid
sudo systemctl enable --now pcscd.socket

Check it with java -version. It should say 21 or higher.

From the latest release, download these two files under Assets:

File What it is
knurctl-<version>.zip The tag setup tool, for the computer with the USB reader.
knurd-<version>.zip The server that checks taps and runs actions.

Unzip both and make one folder for your settings. knurctl and knurd both read knurd.properties from the folder you run them in, so always run them from there.

Terminal window
mkdir -p ~/knura && cd ~/knura
unzip ~/Downloads/knurctl-*.zip
unzip ~/Downloads/knurd-*.zip
mkdir -p home && cd home # your settings live here
# shortcuts for this terminal (add them to ~/.bashrc to keep them)
alias knurctl="$HOME/knura/knurctl-0.3.0-alpha/bin/knurctl"
alias knurd="$HOME/knura/knurd-0.3.0-alpha/bin/knurd"

On Windows, unzip with Explorer and run bin\knurctl.bat and bin\knurd.bat from a Command Prompt opened in your settings folder.

Terminal window
knurctl init

This writes knurd.properties with a new random master key. Every tag you set up gets its own keys worked out from it.

Plug in the reader, then:

Terminal window
knurctl readers # should list your reader
knurctl provision # put a new tag on the reader when asked
knurctl tap # reads the tag like a phone does and checks the link

provision gives the tag its own keys, writes a tap link onto it and reads it back. Leave the tag on the reader until it says it’s done. knurctl info shows the tag’s UID (its ID) at any time.

Terminal window
knurd

It prints knurd listening on http://127.0.0.1:8424. Leave it running, open a second terminal in the same folder and check a tap:

Terminal window
knurctl tap # prints the link the tag just wrote
curl '<the link knurctl printed>' # {"status":"ok","uid":"...","counter":...}
curl '<the same link again>' # {"status":"replay",...}

That second answer is the point of Knura: a link only works once, so a copied or reused link is refused.

A phone opens the link on the tag, so knurd needs an HTTPS address the phone can reach. That address is written onto the tag, so it must never change. The simplest free way is Tailscale Funnel.

  1. Install Tailscale on knurd’s computer and sign in. Turn on HTTPS and Funnel for your tailnet when it asks.

  2. Start the funnel to knurd’s port:

    Terminal window
    sudo tailscale funnel --bg 8424

    It prints your address, ending in .ts.net. tailscale funnel status shows it again later.

  3. Open knurd.properties and set public.url to your address:

    public.url=https://<your-computer>.<your-tailnet>.ts.net
  4. Restart knurd (Ctrl+C, then knurd).

  5. Rewrite the tag’s link to use the new address:

    Terminal window
    knurctl provision --from knura

Now tap the tag with your phone. You should see a Tap verified page. Refresh it and you’ll see Link already used.

Example values. Click a step to jump to it.

A new Funnel address can take up to 15 minutes to work from phones. If the phone shows a blank page, wait and try again.

If you might move knurd to another computer later, register with the free tap.knura.io forwarder. Your tags then carry a tap.knura.io link, and moving means registering the new address instead of rewriting every tag.

Terminal window
knurctl resolver register # creates your owner ID and key
# restart knurd, then:
knurctl resolver register # points tap.knura.io at your public.url
knurctl provision --from knura
knurctl resolver check # shows where your taps go

Back up knurd.properties again afterwards: it now holds your resolver key too.