A Go time daemon for Linux and FreeBSD, built around GPS, serial PPS, and an operator who wants to understand what the clock is doing.
Carillon can synchronize a host from NTP upstreams, discipline its clock from a local reference, and serve time to explicitly allowed clients. A separate status command shows the selected sources, clock correction, reference-clock health, and server counters. Production builds are pure Go: two executables, no C runtime dependency, no database.
Install · Try it safely · Configure · Operations · Design
- Network and local references. NTP upstreams, NMEA GPS input, serial-port PPS,
and Linux
/dev/ppsNdevices. A PPS pulse identifies a second boundary; NMEA or a qualified NTP source supplies the second number. - Explicit clock discipline. Filtering, source selection, clustering, and a deterministic discipline loop. Frequency corrections persist in a drift file; step policy is configurable and clock steps are logged.
- Controlled time service. Serving is disabled until you configure allowed networks. Rate limits, bounded client tracking, and source-address filtering constrain the public server. Modes 6 and 7 are not answered; replies are no larger than their requests.
- Authenticated associations. AES-128-CMAC shared keys for a trusted upstream or selected clients. Keys live separately from configuration.
- Useful observability. A Unix control socket, read-only JSON status, health checks, Prometheus metrics, and optional daily statistics. HTTP monitoring is disabled until configured.
flowchart LR
G[GPS / NMEA] --> H[Home host · Carillon]
P[PPS second boundary] --> H
N[Independent NTP sources] --> H
H -->|Authenticated NTP| C[Colocated host · Carillon]
C --> L[Allowed NTP clients]
H -. local status .-> O[carillonctl]
Start with an ordinary NTP client. Add a local reference or downstream clients when the hardware and topology call for them.
An early release for technically involved operators. Network client/server operation, authenticated associations, Linux and FreeBSD clock backends, drift persistence, and init integration have recorded acceptance runs on the maintainer’s hosts. Live GPS/PPS stratum-1 acceptance and a sustained accuracy comparison are still pending. Microsecond accuracy is a hardware-dependent target, not a published measurement or guarantee.
Three review items remain open: GPS ZDA time-validity policy, source independence/quorum, and negative root-delay interoperability. Read known limitations before choosing a deployment.
Carillon implements durable leap data and authenticated distribution: one configured seed downloads from IERS or NIST, and downstreams learn and cache the original file over authenticated NTP. Manual files are supported and updates activate without restarting the loop. Refclock and serving hosts require a current table before reporting synchronization. Configure an acquisition mode when upgrading those hosts; plain network clients can use fresh upstream LI. PPS and NMEA cannot supply advance leap warnings. Offline autonomy lasts through the cached table's expiry; live GPS/PPS leap acceptance remains pending.
| Platform | Release builds | Runtime scope |
|---|---|---|
| Linux | amd64, arm64 | NTP client/server; Linux PPS and serial backends |
| FreeBSD | amd64, arm64 | NTP client/server; FreeBSD serial PPS backends |
| macOS | Build from source | Development tests, configuration checks, and query; clock discipline is unsupported |
Cross-compilation establishes build compatibility. It does not establish hardware or native runtime acceptance on every architecture. NTS, PTP, hardware NIC timestamping, and OpenWrt deployment are outside the current release scope.
Download binaries and packages from the 1.2.0 release. Choose the file matching your OS and architecture, then follow the verification instructions. Development snapshots are also available from successful CI runs.
| Asset | Contents |
|---|---|
carillon-time_<version>_<os>_<arch>.tar.gz |
carillon, carillonctl, configuration examples, deployment notes |
carillon_<version>_amd64.deb / …_arm64.deb |
Linux binaries, systemd unit, preserved configuration |
carillon-<version>-1.x86_64.rpm / …aarch64.rpm |
The same Linux installation for RPM systems |
From a directory containing the appropriate downloaded package:
# Debian / Ubuntu
sudo apt install ./carillon_*_amd64.deb
# Fedora / RHEL family, after importing the release key (see the verification instructions)
sudo dnf --setopt=localpkg_gpgcheck=1 install ./carillon-*.x86_64.rpmPackages do not start or enable the daemon and do not stop your current time
service. Configuration starts as an NTP client, with downstream serving and device
access disabled. Follow Linux setup to configure and activate
it. Packages and checksums.txt are signed with the
release key, and GitHub build attestations
are provided. There is no hosted APT/YUM repository.
For a manual installation or FreeBSD rc.d setup, use the
deployment guide. Packaged binaries live in /usr/bin; manual
installation examples use /usr/local.
You can inspect an NTP server without adjusting your machine’s clock:
carillon -version
carillon query -timeout 5s pool.ntp.orgquery sends an NTP request and reports the response. It does not run the discipline
loop. To build and check configuration from a clone:
make build
./bin/carillon -version
make check-examples
./bin/carillon query -timeout 5s pool.ntp.orgUse the Go toolchain in .go-version. make check-examples also needs
Python 3; it checks both shipped configurations using temporary state/socket paths.
It does not change the clock or open reference-clock devices. The daemon’s -check
command verifies configuration, filesystem paths, and configured key/leap files;
network reachability and synchronization are separate operational checks.
The packaged configuration has three NTP Pool upstream entries and no [serve]
section. Choose appropriate independent upstreams for your network. Multiple
names alone do not establish independent clocks.
To serve a LAN, add an explicit allow list:
[serve]
listen = ["0.0.0.0:123", "[::]:123"]
allow = ["192.168.1.0/24"]
rate_limit_pps = 8
rate_burst = 16Adapt the network to your deployment. For read-only monitoring on loopback:
[monitor]
listen = "127.0.0.1:8923"See the annotated configuration for PPS and GPS devices, shared keys, public-server sizing, drift persistence, leapfiles, and statistics. The Linux package guide shows the systemd drop-in needed to grant device access.
Once configured and running on the intended host:
sudo carillonctl tracking
sudo carillonctl sources
sudo carillonctl refclock
sudo carillonctl serverstats
sudo carillonctl waitsync 120
curl http://127.0.0.1:8923/api/v1/status
curl http://127.0.0.1:8923/healthz
curl http://127.0.0.1:8923/metricsOnly one daemon should discipline a host’s clock. Validate configuration first, then stop the existing time service and explicitly enable Carillon as described in the deployment guide. A service start can adjust time under the configured step and discipline policy.
The discipline core takes measurements and elapsed time as inputs and returns clock actions. Ordinary tests use fake clocks; platform bindings are separate. The design document explains source qualification, holdover, timestamp handling, clock epochs, and the choices behind the control loop.
make test # Vet and race tests; fake clocks, no clock adjustment
make abicheck # Native Linux/FreeBSD header-layout comparisons; needs C compiler
make linux # Static Linux amd64 and arm64 binaries
make freebsd # Static FreeBSD amd64 and arm64 binaries
make release-check # Validate GoReleaser configuration
make snapshot # Release archives, RPMs, and DEBs in dist/, throwaway-signedGitHub CI runs native race tests on Linux amd64, Linux arm64, and macOS arm64; Linux jobs also compare the kernel ABI against system headers. It cross-builds all release targets and checks Linux packages in Debian and Fedora containers without clock privileges. Hardware acceptance remains a separate operator task.
| Read next | Purpose |
|---|---|
| Design | Protocol and discipline specification |
| Configuration | Annotated settings and topologies |
| Linux packages / Manual deployment | Install, activate, inspect, upgrade |
| Known limitations | Open review items and hardware acceptance gaps |
| Release guide | GitHub builds, packages, signatures, checksums, provenance |
| Contributing / Security | Development and private vulnerability reporting |
License: MIT. Commercial use, modification, and redistribution are permitted with the copyright and license notice preserved. Dependencies retain their own licenses; see third-party notices.
A carillon is a set of tuned bells. This one keeps the time between the strikes.
Sigillum → pairs an automatic DNSSEC zone signer with a browser-based validator for inspecting DNS chains of trust. From the same maintainer, for people who operate their own infrastructure.