A minimal, configurable, secure container image for running chrony NTP server/client, optimized for systems without a Real-Time Clock (RTC) such as Raspberry Pi.
ghcr.io/chris-short/chrony:latest This container has been tested and verified on:
- macOS (Docker Desktop / Podman)
- Raspberry Pi 5 (arm64, no RTC)
- x86_64 Linux
- RTC-free operation: Optimized configuration for devices without hardware clocks
- Fast sync on boot: Uses
makestepto quickly correct time after restart - Drift tracking: Maintains accuracy across reboots via persistent drift file
- Host networking: Binds directly to host interfaces for reliable IPv4/IPv6 NTP service
- Custom NTP servers: Includes local and public time sources for redundancy
docker compose up -d# Build the image docker build -t chrony:latest . # Run with minimal configuration docker run -d --name chrony \ --network host \ --cap-add SYS_TIME \ chrony:latest # Run with persistent drift/logs docker run -d --name chrony \ --network host \ --cap-add SYS_TIME \ -v chrony-data:/var/lib/chrony \ -v chrony-logs:/var/log/chrony \ chrony:latest# Generate systemd service podman generate systemd --new --name chrony > ~/.config/systemd/user/chrony.service systemctl --user enable --now chronyCreate /etc/systemd/system/chrony-container.service:
[Unit] Description=Chrony NTP Container After=docker.service Requires=docker.service [Service] Restart=always ExecStartPre=-/usr/bin/docker rm -f chrony ExecStart=/usr/bin/docker run --rm --name chrony \ --network host \ --cap-drop ALL \ --cap-add SYS_TIME \ -v chrony-data:/var/lib/chrony \ ghcr.io/chris-short/chrony:latest ExecStop=/usr/bin/docker stop chrony [Install] WantedBy=multi-user.targetEnable and start:
sudo systemctl daemon-reload sudo systemctl enable --now chrony-containerEdit chrony.conf to add your preferred NTP servers:
server your.ntp.server iburst Uncomment in chrony.conf:
allow 10.0.5.0/24 # Check sync status docker exec chrony chronyc tracking # View sources docker exec chrony chronyc sources -v # Check server stats docker exec chrony chronyc serverstats- ~5MB image: Alpine Linux with only
chronypackage installed - Non-root runtime: Drops to
chronyuser immediately after binding port 123 - Weekly rebuilds: Automated builds every Sunday pull the latest Alpine base image with security patches
- Multi-architecture: Native builds for
linux/amd64andlinux/arm64
| Setting | Purpose |
|---|---|
cap_drop: ALL | Drop all Linux capabilities |
cap_add: SYS_TIME | Add back only what chrony needs |
read_only: true | Immutable root filesystem |
no-new-privileges: true | Prevent privilege escalation |
Report security vulnerabilities to: security@chrisshort.net
| Tag | Description |
|---|---|
latest | Most recent build from main branch |
YYYYMMDD | Date-stamped builds |
<sha> | Git commit SHA |
MIT