GPS-synchronized time for your network
A monitoring and management stack for GPS-disciplined NTP servers on Raspberry Pi and similar Linux systems.
This project provides a web-based monitoring interface and management tools for building a Stratum 1 NTP server using GPS timing. It sits on top of the standard Linux GPS/NTP stack (gpsd + chrony) and adds:
- Real-time web dashboard showing GPS status, PPS timing, NTP synchronization, and system health
- Visual satellite tracking with sky plot and signal strength display
- Unified installer that configures gpsd, chrony, PPS, and system optimizations
- Hardware abstraction supporting multiple GPS receivers and RTC modules
The underlying time synchronization is handled by chrony (a well-established NTP implementation) using timing data from gpsd. This project doesn't replace those components—it makes them easier to deploy, monitor, and troubleshoot.
A typical GPS-based NTP server on Linux involves installing gpsd and chrony, editing configuration files, and monitoring via command-line tools like chronyc and cgps. This works well but requires familiarity with these tools and manual configuration.
This project differs in several ways:
| Aspect | Standard Setup | This Project |
|---|---|---|
| Monitoring | Command-line (chronyc tracking, cgps -s) |
Web dashboard with real-time updates |
| Visualization | Text output | Sky plot, charts, status indicators |
| Configuration | Manual editing of multiple config files | Unified installer handles gpsd, chrony, boot config, systemd |
| GPS Status | cgps or gpsmon in terminal |
Web page with satellite table, position, DOP values |
| NTP Status | chronyc sources output |
Formatted table with state badges, reachability |
| System Health | Separate tools (htop, df, etc.) | Integrated display of CPU temp, memory, disk |
| SD Card Longevity | Manual optimization | Installer configures tmpfs, volatile journals, disables swap |
| Remote Access | SSH required | Web interface accessible from any browser |
- It doesn't implement its own NTP server—chrony handles all NTP protocol details
- It doesn't provide better timing accuracy than a properly configured gpsd + chrony setup
- It doesn't modify how gpsd or chrony process GPS/PPS signals
The timing accuracy you achieve depends primarily on your hardware (GPS receiver quality, antenna placement, PPS signal integrity) and chrony's disciplining algorithms. This project simply makes it easier to see what's happening and verify everything is working correctly.
While this project doesn't claim to improve timing accuracy over a standard setup, the installer does configure several settings that help achieve good results:
PPS Signal Handling:
- Configures the kernel PPS driver for your GPIO pin
- Sets up gpsd to read both NMEA data and PPS signal
- Fixes SHM segment permissions so chrony can access gpsd's timing data (a common gotcha)
Chrony Configuration:
- Uses SHM refclocks for GPS (coarse time) and PPS (precise timing)
- PPS is marked as preferred source and locked to GPS for time-of-day
- Includes backup NTP servers for holdover if GPS is lost
- Configured for local Stratum 1 operation
System Optimization:
- Disables unnecessary services that could cause latency spikes
- Configures kernel parameters for GPS/UART operation
With typical hardware (Raspberry Pi 4 + Uputronics GPS HAT or similar), you can expect:
- PPS offset: sub-microsecond (typically 100ns - 1μs from system clock)
- NTP offset to clients: low microseconds over a local network
- Stratum 1 operation when GPS is locked
These numbers are consistent with what any well-configured gpsd + chrony system achieves with similar hardware.
- Web Dashboard: Real-time display of GPS, PPS, NTP, and system metrics
- GPS Status Page: Satellite sky plot, position, accuracy (DOP), timing quality
- NTP Status Page: Chrony tracking data, source list with sync status
- System Page: CPU temperature, memory, disk usage, network statistics
- Configuration Page: Hardware profile selection, network settings
- Dark/Light Theme: Comfortable viewing in any environment
- Server-Sent Events: Live updates without polling
- REST API: Programmatic access to all metrics
- Hardware Profiles: Pre-configured settings for common GPS/RTC hardware
- SD Card Optimization: Minimizes writes for long SD card life
Any GPS receiver supported by gpsd will work. Pre-configured profiles exist for:
- Uputronics GPS HAT - ublox MAX-M8Q with PPS and RTC
- ublox NEO-M9N - Multi-constellation USB receiver
- Standalone GPSDO boards - External oscillator-disciplined units
Optional RTC support for time retention during power loss:
- MV-3028-C7 (on Uputronics HAT)
- DS3231
- DS1307
- Raspberry Pi 4 (primary target, ARM64)
- Raspberry Pi 3 (ARM64)
- Other Linux systems with appropriate hardware
Raspberry Pi:
- Raspberry Pi 4 or 5 (ARM64) with Raspberry Pi OS
- GPS receiver with PPS output (e.g., Uputronics GPS HAT)
- Network connectivity
Option 1: Direct install on Raspberry Pi (easiest)
git clone https://github.com/jrsphoto/satclock.git
cd satclock
sudo ./install.sh
sudo rebootThe installer will automatically download pre-built ARM64 binaries from GitHub releases. If you have Go installed, it can also build from source.
Option 2: Cross-compile and deploy
# On your development machine (x86_64)
git clone https://github.com/jrsphoto/satclock.git
cd satclock
make build-pi
# Copy to Raspberry Pi
scp -r . pi@<raspberry-pi-ip>:~/satclock
# On the Raspberry Pi
ssh pi@<raspberry-pi-ip>
cd ~/satclock
sudo ./install.sh
sudo rebootAccess web interface:
http://<raspberry-pi-ip>:8080
For detailed installation options, see docs/INSTALLATION.md.
The install.sh script handles everything:
- Downloads or builds application binaries
- Installs dependencies (gpsd, chrony, pps-tools)
- Configures GPS, PPS, and boot parameters
- Sets up chrony for Stratum 1 NTP operation
- Optimizes SD card for longevity (tmpfs, volatile logs)
- Installs and enables systemd services
Configuration files are in /etc/satclock/:
monitord.yaml - Monitoring daemon settings:
hardware:
profile: uputronics-gps-hat # or: standalone, neo-m9n-usb, custom
gps:
enabled: true
host: localhost
port: 2947
pps:
enabled: true
device: /dev/pps0
chrony:
enabled: truewebapp.yaml - Web interface settings:
http:
host: 0.0.0.0
port: 8080See docs/HARDWARE.md for hardware setup and docs/PROFILES.md for profile details.
┌─────────────────────────────────────────────────────────────────┐
│ Hardware Layer │
│ GPS Receiver ──► gpsd ──► SHM ──► chrony ──► NTP Clients │
│ │ │
│ PPS ─────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Monitoring Layer │
│ │
│ ┌──────────┐ NATS ┌──────────┐ │
│ │ monitord │ ──────────► │ webapp │ ──► Web Dashboard │
│ └──────────┘ pub/sub └──────────┘ │
│ │ │
│ └──────────────────────────────► InfluxDB (optional) │
└─────────────────────────────────────────────────────────────────┘
monitord: Collects metrics from gpsd, chrony, PPS sysfs, RTC, and system. Publishes to NATS message bus.
webapp: Subscribes to metrics via NATS. Serves web interface and REST API. Pushes real-time updates via Server-Sent Events.
All metrics are available via REST:
# Current status snapshot
curl http://localhost:8080/api/status
# GPS details
curl http://localhost:8080/api/gps
# NTP/chrony details
curl http://localhost:8080/api/ntp
# System health
curl http://localhost:8080/api/system
# Historical data
curl http://localhost:8080/api/history?since=2024-01-01T00:00:00Z
# Real-time stream (Server-Sent Events)
curl http://localhost:8080/api/metrics/streamsatclock/
├── cmd/
│ ├── monitord/ # Monitoring daemon
│ └── webapp/ # Web application
├── internal/
│ ├── hardware/ # Hardware abstraction layer
│ │ ├── gps/ # GPS implementations
│ │ ├── pps/ # PPS implementations
│ │ ├── rtc/ # RTC drivers
│ │ └── profiles/ # Hardware profiles
│ ├── monitor/ # Metrics collection
│ ├── web/ # HTTP handlers, SSE, API
│ └── config/ # Configuration loading
├── web/
│ ├── static/ # CSS, JavaScript
│ └── templates/ # HTML templates
├── configs/ # Example configurations
├── scripts/ # Installation script
├── systemd/ # Service files
└── docs/ # Documentation
- INSTALLATION.md - Detailed installation guide
- HARDWARE.md - Hardware setup and wiring
- PROFILES.md - Hardware profile reference
- TROUBLESHOOTING.md - Common issues and solutions
- SD_CARD_OPTIMIZATION.md - SD card longevity
Contributions are welcome. Please open an issue to discuss proposed changes before submitting a pull request.
MIT License - see LICENSE file for details.
This project builds on excellent open-source software:
- gpsd - GPS service daemon
- chrony - NTP implementation
- Chart.js - Charting library
- Gorilla Mux - HTTP router
- NATS - Messaging system