A step-by-step guide to use a laptop/PC as a time server and Raspberry Pis as clients, with or without Internet.
You can keep your Raspberry Pis in sync by running Chrony on a computer (the “server”) and pointing the Pis (the “clients”) at it. This works even with no Internet (server serves its own clock), and across hotspots (NetworkManager shared AP or phone hotspot) or normal Wi-Fi LANs.
This guide covers:
- Server setup (Ubuntu 24/25+ or similar)
- Raspberry Pi client setup (Raspberry Pi OS Bookworm+)
- Hotspot/LAN subnet rules
- Verification & troubleshooting
- Server hostname (example):
roadking→ reachable asroadking.localvia mDNS. - Hotspot/LAN subnets (pick what you actually use):
- NetworkManager Wi-Fi Hotspot: typically
10.42.0.0/24(server IP often10.42.0.1) - Android phone hotspot: often
192.168.43.0/24 - Any other router: check with
ip -4 addr
- NetworkManager Wi-Fi Hotspot: typically
Find your active subnet on the server:
ip -4 addr show # identify the Wi-Fi interface (e.g., wlp… or wlan0)
ip -4 addr show <iface> # look for: inet X.Y.Z.W/24 → your subnet is X.Y.Z.0/24Note: in this example the server is called 'roadking'.
1.1 Set hostname & enable mDNS (so roadking.local resolves). This may already be enabled on the computer, so if it already resolves (ping), then can skip this and go to 1.2.
sudo hostnamectl set-hostname roadking
sudo apt update
sudo apt install -y avahi-daemon libnss-mdns
sudo systemctl enable --now avahi-daemonTest from another machine on the same Wi-Fi:
ping -c1 roadking.localsudo apt install -y chronyBack up and edit the main config:
sudo cp /etc/chrony/chrony.conf /etc/chrony/chrony.conf.bak.$(date +%s)
sudo nano /etc/chrony/chrony.confIf you are on Ubuntu 25+, Chrony may include extra snippets via:
sourcedir /etc/chrony/chrony.d
Comment that out if you want a minimal, explicit config:
#sourcedir /etc/chrony/chrony.d
A) If the server HAS Internet and you want it to sync upstream:
- Keep a couple of
poollines or add your preferred NTP servers. - Add allow for your hotspot/LAN subnet so Pis can query you.
- (Optional)
cmdallowif you want to runchronyc clientsfrom other hosts without sudo.
Example:
# Upstream time (keep 1–2 pools)
pool 0.pool.ntp.org iburst
pool 1.pool.ntp.org iburst
# Allow clients on my subnet to use me as NTP server
allow 10.42.0.0/24
# or: allow 192.168.43.0/24
# (Optional) allow chronyc control commands from subnet (e.g., 'chronyc clients')
cmdallow 10.42.0.0/24
B) If the server has NO Internet and should serve its own clock:
- Remove/comment any
pool/serverlines. - Add
local stratum 10so Chrony serves its own clock. - Add allow for your subnet.
- (Optional)
cmdallow.
Example (standalone):
# Act as a standalone local time source (no upstream)
local stratum 10
# Allow clients on hotspot/LAN
allow 10.42.0.0/24
# or: allow 192.168.43.0/24
# Optional control channel permissions
cmdallow 10.42.0.0/24
Save & exit.
sudo systemctl restart chrony
sudo systemctl enable chronyIf UFW is enabled:
sudo ufw allow proto udp to any port 123
sudo ufw reloadchronyc sources -v # shows upstream (case A) or local clock (case B)
sudo chronyc clients # shows clients once Pis start querying
journalctl -u chrony --no-pager | grep -i denied # check for refused requestssudo apt update
sudo apt install -y avahi-utils libnss-mdns
getent ahosts roadking.local # should print an IPTip: If mDNS lookups feel slow or your hotspot renumbers, you can pin a static entry in
/etc/hostson each Pi:echo "10.42.0.1 roadking.local roadking" | sudo tee -a /etc/hosts(Replace
10.42.0.1with Roadking’s current hotspot IP.)
sudo apt install -y chronysudo cp /etc/chrony/chrony.conf /etc/chrony/chrony.conf.bak.$(date +%s)
sudo nano /etc/chrony/chrony.confComment out default pools/servers and add your server:
# Comment out any defaults:
# pool ...
# server ...
# sourcedir ...
# Use the local server (by name)
server roadking.local iburst minpoll 3 maxpoll 8
# (Optional) add a fallback server if Roadking is sometimes unavailable:
# server thria.local iburst minpoll 3 maxpoll 8
Save & exit.
sudo systemctl restart chrony
sudo systemctl enable chronyImmediately:
chronyc sources -v
chronyc trackingAfter ~30–60s you should see ^* roadking.local in sources and a sensible offset/skew in tracking.
Quick one-shot query (also tests UDP 123 reachability):
sudo apt install -y ntpdate
ntpdate -q roadking.local- NetworkManager Wi-Fi Hotspot (Linux) defaults to
10.42.0.0/24, server IP10.42.0.1. - Phone hotspots often use
192.168.43.0/24(Android) or other192.168.x.0/24. - Always match the server’s active subnet in
allow(andcmdallowif you use it). - If you change hotspot types, update
allowand restart Chrony on the server.
Symptom: chronyc clients on server says 501 Not authorised
- That message refers to Chrony’s control channel, not NTP service.
- Run as root:
sudo chronyc clients - Or add
cmdallow <your-subnet>/24to server’schrony.confand restart.
Symptom: Pi shows:
chronyc sources
^? roadking.local ...
chronyc tracking → Stratum: 0 / Not synchronised
- Give it 30–60 seconds after the first query.
- Verify name resolution:
getent ahosts roadking.local - Try direct IP:
server 10.42.0.1 iburst ...(replace with server IP). - On server, confirm
allow <subnet>/24matches the Pi’s actual IP subnet. - Check firewall: allow UDP/123 on server.
Symptom: “Refusing NTP request” or “denied” in server logs
journalctl -u chrony | grep -i denied- Fix
allowsubnet (e.g.,allow 10.42.0.0/24) and restart Chrony.
Symptom: Name resolution slow (mDNS delay)
- Ensure
libnss-mdnsis installed and/etc/nsswitch.confhas:hosts: files mdns4_minimal [NOTFOUND=return] dns myhostname - Optionally add static
/etc/hostslines for instant lookups.
Symptom: Server has no Internet but must still serve time
- Use the standalone config (remove pools; add
local stratum 10).
Server (standalone, hotspot 10.42.0.0/24):
sudo apt update
sudo apt install -y avahi-daemon libnss-mdns chrony
sudo cp /etc/chrony/chrony.conf /etc/chrony/chrony.conf.bak.$(date +%s)
sudo bash -c 'cat >/etc/chrony/chrony.conf' <<'CONF'
#sourcedir /etc/chrony/chrony.d
local stratum 10
allow 10.42.0.0/24
#cmdallow 10.42.0.0/24
CONF
sudo systemctl restart chrony
sudo systemctl enable chronyClient (Pi → roadking.local):
sudo apt update
sudo apt install -y avahi-utils libnss-mdns chrony
sudo cp /etc/chrony/chrony.conf /etc/chrony/chrony.conf.bak.$(date +%s)
sudo bash -c 'cat >/etc/chrony/chrony.conf' <<'CONF'
server roadking.local iburst minpoll 3 maxpoll 8
CONF
sudo systemctl restart chrony
sudo systemctl enable chrony
chronyc sources -v
chronyc tracking- Install Chrony on the server and Pis.
- On the server: use
allow <subnet>/24(andlocal stratum 10if offline). Comment outsourcediron Ubuntu 25+ if you want a minimal config. - On the Pis: set
server roadking.local iburst(or the server IP). - Enable mDNS or add
/etc/hostsentries for instant resolution. - Verify with
chronyc sources/tracking(Pi) andchronyc clients(server).