Think
dig, but for time sources. No daemon, no root, no config to touch.
rkik queries NTP and NTS servers and tells you what they say: offset, RTT, stratum, authentication status. One shot, stateless, done.
- Passive by design. It never touches your system clock unless you explicitly ask (
--sync). Run it anywhere, as anyone. - NTS that actually works. rkik-nts 1.0.0 is the first Rust implementation of RFC 8915 verified against real public servers (
time.cloudflare.com,nts.ntp.se). Older tools either skip authentication or implement it wrong. - Two protocols, one tool. NTP over IPv4/IPv6 and NTS with full TLS diagnostics — compare mode, JSON output, and Nagios/Centreon plugin support included.
- The only NTS-aware monitoring plugin for Nagios, Centreon and Zabbix
$ rkik --nts time.cloudflare.com -v
Server: time.cloudflare.com [NTS Authenticated]
IP: 162.159.200.1:123
UTC Time: Tue, 28 Apr 2026 14:32:10 +0000
Local Time: 2026-04-28 16:32:10
Clock Offset: 1.243 ms
Round Trip Delay: 14.871 ms
=== NTS-KE Diagnostics ===
Handshake Duration: 87.342 ms
Cookies Received: 8 cookies
AEAD Algorithm: AEAD_AES_SIV_CMAC_256
NTP Server: 162.159.200.1:123
=== TLS Certificate ===
Subject: CN=time.cloudflare.com
Issuer: C=US, O=DigiCert Inc, CN=GeoTrust TLS ECC CA G1
Valid: 2025-02-10 → 2026-03-12
Fingerprint (SHA-256): 4b060f4d...462119
SANs: time.cloudflare.com
cargo install rkikArch Linux (AUR):
yay -S rkik-gitNix / NixOS:
nix shell nixpkgs#rkikDEB / RPM / tar.gz: grab the latest from GitHub Releases.
# Debian / Ubuntu
sudo apt install ./rkik_2.2.0-1_amd64.deb
# Fedora / RHEL / Alma / Rocky
sudo dnf install rkik-2.2.0-1.x86_64.rpm# Basic NTP probe
rkik pool.ntp.org
# NTS — cryptographically authenticated
rkik --nts time.cloudflare.com
# Compare a few servers side by side
rkik --compare pool.ntp.org time.google.com time.cloudflare.com
# Plugin output for Nagios / Centreon / Zabbix
rkik pool.ntp.org --plugin --warning 50 --critical 200
# JSON, prettified
rkik pool.ntp.org --json --prettyrkik time.google.com # basic probe
rkik time.google.com -v # adds stratum, ref ID
rkik time.google.com --count 10 --interval 2 # repeat 10 times
rkik -6 pool.ntp.org # IPv6-only resolutionOutput:
Server: time.google.com
IP: 216.239.35.4:123
UTC Time: Tue, 28 Apr 2026 14:32:08 +0000
Local Time: 2026-04-28 16:32:08
Clock Offset: 0.312 ms
Round Trip Delay: 9.449 ms
NTS (RFC 8915) is authenticated NTP — every packet is verified with AEAD encryption, so you know the response hasn't been tampered with.
rkik --nts time.cloudflare.com # authenticated probe
rkik --nts time.cloudflare.com -v # with TLS/KE diagnostics
rkik --nts --compare nts.ntp.se time.cloudflare.comWhen something goes wrong, rkik tells you what kind of failure it is:
| Kind | Meaning |
|---|---|
aead_failure |
AEAD verification failed — possible tampering |
missing_authenticator |
Authenticator extension absent in response |
unauthenticated_response |
Server completed NTS-KE but sent plain NTP |
ke_handshake_failed |
TLS or NTS-KE handshake failed |
timeout |
Connection timed out |
Security-critical failures (aead_failure, missing_authenticator, unauthenticated_response, invalid_unique_id, invalid_origin_timestamp) exit with code 2 in plugin mode.
See docs/user-guide.md#nts for the full error reference.
rkik time.google.com --plugin --warning 50 --critical 200
# → RKIK OK - offset 4.006ms rtt 9.449ms from time.google.com (216.239.35.4) | offset_ms=4.006ms;50;200;0; rtt_ms=9.449ms;;;0;Exit codes: 0 OK · 1 WARNING · 2 CRITICAL · 3 UNKNOWN (request failed or security error)
Your monitoring fires a time alert on ntp.server.local. You don't know yet whether the problem is that server or its upstream.
$ rkik ntp.server.local -v
Clock Offset: 5000.145 ms
Reference ID: 145.238.80.80Five seconds of drift, and you can see the upstream. Check it directly:
$ rkik 145.238.80.80
Clock Offset: 5001.531 msSame offset upstream. The problem isn't your server — it's the reference. Time to point it somewhere else.
rkik is split into a library and a CLI. The library has no clap, no process::exit, no terminal code — just async functions you can call directly.
[dependencies]
rkik = { version = "2", default-features = false, features = ["json"] }
tokio = { version = "1", features = ["rt-multi-thread", "macros"] }use rkik::query_one;
use std::time::Duration;
let r = query_one("time.google.com", false, Duration::from_secs(3), false, 4460).await?;
println!("{}: offset={:.3}ms", r.target.name, r.offset_ms);Full API reference, architecture overview, and contribution guide: docs/developer-guide.md
To contribute, see CONTRIBUTING — issues labelled good first issue are a good starting point.