Chronos is an HTTP-backend time synchronization gateway. It lets a restricted
data center — one that may only egress over HTTPS — keep accurate time without
outbound NTP. A chronos-gateway samples time from a chronos-server over
HTTP/HTTPS and feeds the samples to a local chronyd via chrony's SOCK
refclock; chronyd then disciplines the host clock and serves NTP internally.
| Crate | Role |
|---|---|
chronos-core |
Domain types, ports (traits), and pure logic. No I/O. |
chronos-chrony |
OutputBackend writing chrony's SOCK refclock over a Unix datagram socket. |
chronos-server |
HTTP/HTTPS Time API (/time, /healthz, /status). |
chronos-gateway |
Backend client, burst sampler, offset estimator, status API. |
chronos-ntp |
Reserved placeholder for v2 output backends. |
cargo build --release
cargo test --all
cargo clippy --all-targets --all-features -- -D warningsBinaries are produced at target/release/chronos-server and
target/release/chronos-gateway. TLS uses rustls with the ring backend, which
needs a C compiler to build (but not cmake). The container image is built as a
fully static musl binary and shipped on distroless/static.
chronos-server --config /etc/chronos/server.yaml
chronos-gateway --config /etc/chronos/gateway.yamlExample configurations live under examples/config.
# 1. Server (native HTTP), reporting status from chrony on its host.
chronos-server --config examples/config/server.http.yaml
# 2. Gateway sampling that server and writing to the host chrony socket.
# Prereq: configure chronyd's SOCK refclock. The helper derives the right
# `poll` from gateway.yaml and installs the drop-in for you:
# sudo packaging/setup-chrony-refclock.sh \
# --config examples/config/gateway.yaml --install
# Run the gateway as root (it writes chrony's root-owned socket).
# Details: docs/deployment-gateway.md.
sudo chronos-gateway --config examples/config/gateway.yaml
# 3. Inspect.
curl -fsS http://127.0.0.1:8080/time | jq
curl -fsS http://127.0.0.1:9090/status | jqA single combined image contains both binaries; consumers pick the binary via
command. There is no fixed ENTRYPOINT and no baked-in HEALTHCHECK
(healthchecks are per service in Compose, using each binary's healthcheck
subcommand rather than curl, which the distroless image does not ship).
TS=$(date -u +%Y%m%d%H%M%S)
docker build -t "ghcr.io/maple52046/chronos:1.0.0-${TS}" .
docker push "ghcr.io/maple52046/chronos:1.0.0-${TS}"See examples/compose.
Gateway Kubernetes manifests live under examples/k8s/gateway.
Shared resources are kept in base/; choose one daemon-specific overlay for the
node-local NTP daemon:
kubectl apply -k examples/k8s/gateway/ntpsec
kubectl apply -k examples/k8s/gateway/ntpd
kubectl apply -k examples/k8s/gateway/chronyBefore applying, edit the selected overlay's configmap.yaml and set
data.gateway.yaml -> backends[0].base_url to the Chronos server URL. See the
gateway example README for daemon prerequisites and verification steps.
- Architecture
- HTTP Time API protocol
- chrony integration
- Deploying the server
- Deploying the gateway
- Security
- Troubleshooting
- Develop plan
MIT. See LICENSE.