Chrony package
-
I've written a Chrony package for pfSense. For those unfamiliar with Chrony, it is a modern implementation of NTP which supports Network Time Security (NTS).
I will be submitting the package shortly. For those interested in checking out the current version, please keep reading...
There are currently two versions of Chrony available in FreeBSD, chrony and chrony-lite. The lite version does not have support for NTS, so we only care about the main chrony version.
[Edit: in my initial post, I missed including libtasn1 as a dependency because it was previously installed on my test systems. I've updated the instructions and tar file below to include it.]
To install chrony with NTS support, there are two dependencies required: nettle which is already available in pfSense, and gnults which is not currently available in pfSense. Gnutls also has a dependency on libtasn1 which is not currently available in pfSense. Lastly, Chrony itself is not currently in pfSense.
There are two approaches to getting the required gnutls/libtasn1 and chrony packages.
The first option is to pull the packages from the main FreeBSD distribution. This is not my favorite approach because the default builds in the FreeBSD distribution have options enabled that bring in a lot of extra stuff, and may conflict with pfSense built packages. I have not tested this approach, but if you choose to try it, please post and let people know how it goes.
The second option is to build the packages, which is the approach I have chosen. If you are not able to build the packages yourself, I have included my copies below that were built on FreeBSD 15.1.
For reference, these are the options that I build libtasn1 with:
freebsd-15:/usr/ports/security/libtasn1 # make showconfig ===> The following configuration options are available for libtasn1-4.21.0: DOCS=off: Build and/or install documentationIn short, I’ve turned off DOCS which is on by default.
These are the options that I build gnutls with:
freebsd-15:/usr/ports/security/gnutls # make showconfig ===> The following configuration options are available for gnutls-3.8.13: DANE=off: Certificate verification via DNSSEC EXAMPLES=off: Build and/or install examples IDN=on: International Domain Names support KTLS=on: Enable support for in-kernel TLS MAN3=off: Install API manpages (section 3) NLS=off: Native Language Support P11KIT=off: PKCS#11 and p11-kit support SRP=off: Secure Remote Password supportIn short, I’ve turned off MAN3 and P11KIT which are on by default.
These are the options that I build chrony with:
freebsd-15:/usr/ports/net/chrony # make showconfig ===> The following configuration options are available for chrony-4.8: DOCS=off: Build and/or install documentation EXAMPLES=off: Build and/or install examples HTMLDOCS=off: Build HTML docs (IMPLIES DOCS, needs ruby, asciidoctor) NTS=on: Support Network Time Security (NTS, uses GnuTLS & Nettle) USER=on: Run as user/group chronyd (unset: user/group ntpd) ====> Support for secure hash functions NETTLE=on: Nettle crypto library support for secure hash and NTS NSS=off: NSS-based support for more hashing algorithmsIn short, I’ve turned off DOCS, EXAMPLES and HTMLDOCS, which are on by default. Note also that the user/group used for chrony are not explicitly set, and so default to ntpd/ntpd. The pfSense package expects the user to be ntpd, so don't change this.
The tar file below contains four packages:
- libtasn1-4.21.0.pkg
- gnutls-3.8.13.pkg
- chrony-4.8.pkg
- pfSense-pkg-Chrony-4.8.pkg
The order of installation is as listed, or you can install them all at the same time like so:
pkg install libtasn1-4.21.0.pkg gnutls-3.8.13.pkg chrony-4.8.pkg pfSense-pkg-Chrony-4.8.pkgIf you build your own gnutls/libtasn1 and chrony, or get them from the FreeBSD distribution, then all you will need to install is the pfSense package. FWIW, if you are not the trusting type (
) you can look at or extract the contents of the pfSense package with tar like so:[26.03.1-RELEASE][root@fw.]/root: tar -tvf pfSense-pkg-Chrony-4.8.pkg -rw-r--r-- 0 root wheel 578 Dec 31 1969 +COMPACT_MANIFEST -rw-r--r-- 0 root wheel 3007 Dec 31 1969 +MANIFEST -rw-r--r-- 0 root wheel 1361 Aug 5 10:22 /etc/inc/priv/chrony.priv.inc -rw-r--r-- 0 root wheel 9983 Aug 5 10:22 /usr/local/pkg/chrony.inc -rw-r--r-- 0 root wheel 1812 Aug 5 10:22 /usr/local/pkg/chrony.xml -rw-r--r-- 0 root wheel 10173 Aug 5 10:22 /usr/local/share/licenses/pfSense-pkg-Chrony-4.8/APACHE20 -rw-r--r-- 0 root wheel 66 Aug 5 10:22 /usr/local/share/licenses/pfSense-pkg-Chrony-4.8/LICENSE -rw-r--r-- 0 root wheel 164 Aug 5 10:22 /usr/local/share/licenses/pfSense-pkg-Chrony-4.8/catalog.mk -rw-r--r-- 0 root wheel 376 Aug 5 10:22 /usr/local/share/pfSense-pkg-Chrony/info.xml -rw-r--r-- 0 root wheel 11810 Aug 5 10:22 /usr/local/www/chrony.php -rw-r--r-- 0 root wheel 12964 Aug 5 10:22 /usr/local/www/chrony_edit.php -rw-r--r-- 0 root wheel 906 Aug 5 10:22 /usr/local/www/shortcuts/pkg_chrony.inc -rw-r--r-- 0 root wheel 2183 Aug 5 10:22 /usr/local/www/status_chrony.php drwxr-xr-x 0 root wheel 0 Aug 5 10:22 /etc/inc/ drwxr-xr-x 0 root wheel 0 Aug 5 10:22 /etc/inc/priv/All the executable stuff is php that you can easily read.
Feedback is welcome. Enjoy!
-
D dennypage referenced this topic
-
D dennypage referenced this topic
-
@dennypage
Thanks Denny! I'm knee deep in other projects here on the mountain at the moment, but as soon as I can come up for air, I'll take a hard look at this and give it a whirl!!I was hoping the devs would have added something to allow the native code to talk to the Starlink time service... but no joy.
Rick
-
For those interested, here are some screenshots from the package:
Main page:

Local section expanded:

The source edit page:

There is also a status page (nothing fancy, just chronyc output), but it's a bit too large to post a screenshot.
-
@dennypage said in Chrony package:
pkg install libtasn1-4.21.0.pkg gnutls-3.8.13.pkg chrony-4.8.pkg pfSense-pkg-Chrony-4.8.pkg
Thank you very much for producing this package. This is a big step forward to getting a well-integrated time server running off of my Starlink GPS stratum 2 time source. I hope Netgate will accept this package into the official repository, absent a patch for NTP which is broken with respect to the Starlink GPS time source.
I installed the package without difficulty using your instructions.
I configured it first using my Starlink as the time source plus four NIST server groups and it ran properly and reported good time sync.
However, I don't see it serving the time to my network, unless I'm misinterpreting the following:

So I sent back to the Services>Chrony and enabled local mode (which by the description appeared like it may be necessary to have any server to my network clients, not just a stand-alone server) without orphan mode and statum 2 (which is my Starlink source), and clicked Apply, it blew up.
I'm not sure if I need this to serve to my network. My homebrew Chrony installation served to my network without anything special. (It is currently disabled and not installed in a place that would interfere.)
So, what do I need to get my local network endpoints to be able to see the local Chrony server?
These are the errors I got when I applied the local mode settings:

The crash report showed:
Crash report begins. Anonymous machine information: amd64 16.0-CURRENT FreeBSD 16.0-CURRENT #12 plus-RELENG_26_03_1-n256546-1d1bfd578383: Wed May 20 15:20:10 UTC 2026 root@pfsense-build-release-amd64-2.eng.atx.netgate.com:/var/jenkins/workspace/pfSense-Plus-snapshots-26_03_1-main/obj/amd64/fvF1vE9r/var/jenkins/workspace/ Crash report details: PHP Errors: [09-Aug-2026 14:48:29 US/Mountain] PHP Fatal error: Uncaught Error: Undefined constant "CHRONY_CONF_LOCAL_STRATUM" in /usr/local/pkg/chrony.inc:230 Stack trace: #0 /usr/local/pkg/chrony.inc(305): chrony_write_files() #1 /usr/local/www/chrony.php(122): chrony_sync_config() #2 {main} thrown in /usr/local/pkg/chrony.inc on line 230 No FreeBSD crash data found.How do I fix and serve to my local endpoints?
Thanks again.
-
@Mission-Ghost [Sorry for terse reply -- I broke my clavicle Friday, and I'm one hand typing which is hard.]
Local mode is for serving clients without upstream servers being available. Not related to authorization. See Chrony doc for detail on the local directive.
The "Undefined constant" constant for local/orphan was fixed in the first edit. Please re-download the tar file and re-install the pfSense package.
The "Not authorized" is in the status page, yes? That means the chronyc command had an auth failure to chronyd. I've only seen this when chronyd was starting or stopping. Do the rest of the chronyc outputs look right?
Note that chronyc only reports on clients its seen since chronyd restarted.
-
-
-
Thanks for responding. Weird I didn't get the updated package. I downloaded using your link posted in your message at the top of this thread earlier this afternoon.
So unless you fixed it earlier this afternoon and I missed it, I don't know how I didn't get the most recent one, unless your fixed version didn't over-write the one pointed to by your link. But, anyway, I'll see if I can find a more recent version.
[Update: The only link I know of to download is as posted at the top of this thread, which points to https://forum.netgate.com/assets/uploads/files/1786032467760-chrony_packages.tar. How does one get the "first edit?"]
While waiting for your reply, I disabled the package and went back to my side-loaded version and, after discovering the package had erased my conf file I recreated one for my version and (re-)discovered that to enable clients to use my router as their ntp server I had to edit the "allow" config item to enable this function (by removing the ! prefix) and include my subnet(s), like this:
Was:
####################################################################### ### ACTING AS AN NTP SERVER # You might want the computer to be an NTP server for other computers. # # By default, chronyd does not allow any clients to access it. You need # to explicitly enable access using 'allow' and 'deny' directives. # # e.g. to enable client access from the 192.168.*.* class B subnet, ! allow 192.168/16I changed to:
####################################################################### ### ACTING AS AN NTP SERVER # You might want the computer to be an NTP server for other computers. # # By default, chronyd does not allow any clients to access it. You need # to explicitly enable access using 'allow' and 'deny' directives. # # e.g. to enable client access from the 192.168.*.* class B subnet, allow 192.168/16It appears for your package to be able to do this, the configuration pages need an option to do allow the user to enable this and specify the subnets it is to serve time to.
When I execute chronyc clients with my side-loaded version I get:
Hostname NTP Drop Int IntL Last Cmd Drop Int Last =============================================================================== 192.168.10.21 7 0 1 - 349 0 0 - - 192.168.10.12 1 0 - - 359 0 0 - - 192.168.10.23 5 0 1 - 352 0 0 - -Your package .conf has in it this:
# Access restrctions are implemented using firewall rules. allowI'd try to change it to include my subnets 192.168/16 but I can't disable/enable the package without it re-writing the chrony.conf file, so I can't test it.
This seems like a critical function, since the point of NTP to my way of thinking isn't just to set the time on the router, it's to be a consistent local time source to all my endpoints on my network like the NTP function does, but doesn't work for the Starlink source. So the "allow <subnet>" would be kind of critical to a use case that replaces the built-in NTP with the Chrony package.
So, now I'm going to go back and disable my side-loaded version and re-enable your package to get the errors I wrote about.
Ok; here's my entire package status (local mode is disabled, of course):
Chrony Status - refreshes every 10 seconds Tracking Reference ID : C0A86401 (192.168.100.1) Stratum : 2 Ref time (UTC) : Sun Aug 09 22:00:37 2026 System time : 0.000000328 seconds fast of NTP time Last offset : -0.000074757 seconds RMS offset : 0.000147603 seconds Frequency : 77.781 ppm slow Residual freq : -0.002 ppm Skew : 0.038 ppm Root delay : 0.001953177 seconds Root dispersion : 0.002071446 seconds Update interval : 2.0 seconds Leap status : Normal Sources .-- Source mode '^' = server, '=' = peer, '#' = local clock. / .- Source state '*' = current best, '+' = combined, '-' = not combined, | / 'x' = may be in error, '~' = too variable, '?' = unusable. || .- xxxx [ yyyy ] +/- zzzz || Reachability register (octal) -. | xxxx = adjusted offset, || Log2(Polling interval) --. | | yyyy = measured offset, || \ | | zzzz = estimated error. || | | \ MS Name/IP address Stratum Poll Reach LastRx Last sample =============================================================================== ^* 192.168.100.1 1 9 377 66 -245us[ -320us] +/- 2931us ^- time-e-wwv.nist.gov 1 7 377 66 +5460us[+5460us] +/- 30ms ^- time-a-b.nist.gov 1 6 377 60 +8160us[+8160us] +/- 26ms ^- time-c-wwv.nist.gov 1 7 377 66 +24ms[ +24ms] +/- 40ms ^- time-b-wwv.nist.gov 1 7 377 66 +13ms[ +13ms] +/- 23ms Source Stats .- Number of sample points in measurement set. / .- Number of residual runs with same sign. | / .- Length of measurement set (time). | | / .- Est. clock freq error (ppm). | | | / .- Est. error in freq. | | | | / .- Est. offset. | | | | | | On the -. | | | | | | samples. \ | | | | | | | Name/IP Address NP NR Span Frequency Freq Skew Offset Std Dev ============================================================================== 192.168.100.1 64 34 133m -0.002 0.033 -129ns 187us time-e-wwv.nist.gov 26 16 66m +0.948 2.096 +10ms 3735us time-a-b.nist.gov 20 9 74m -0.026 0.192 +11ms 355us time-c-wwv.nist.gov 36 19 74m +0.224 1.524 +8552us 3236us time-b-wwv.nist.gov 36 17 74m +0.831 1.454 +11ms 3595us Select Data . State: N - noselect, s - unsynchronised, M - missing samples, / d/D - large distance, ~ - jittery, w/W - waits for others, | S - stale, O - orphan, T - not trusted, P - not preferred, | U - waits for update,, x - falseticker, + - combined, * - best. | Effective options ---------. (N - noselect, P - prefer | Configured options ----. \ T - trust, R - require) | Auth. enabled (Y/N) -. \ \ Offset interval --. | | | | | S Name/IP Address Auth COpts EOpts Last Score Interval Leap ======================================================================= 501 Not authorised Auth Data .- Auth. mechanism (NTS, SK - symmetric key) | Key length -. Cookie length (bytes) -. | (bits) | Num. of cookies --. | | | Key est. attempts | | | | | | | Name/IP address Mode KeyID Type KLen Last Atmp NAK Cook CLen ========================================================================= 501 Not authorised Clients Hostname NTP Drop Int IntL Last NTS-KE Drop Int Last =============================================================================== 501 Not authorised -
@Mission-Ghost said in Chrony package:
Thanks for responding. Weird I didn't get the updated package. I downloaded using your link posted in your message at the top of this thread earlier this afternoon.
So unless you fixed it earlier this afternoon and I missed it, I don't know how I didn't get the most recent one, unless your fixed version didn't over-write the one pointed to by your link. But, anyway, I'll see if I can find a more recent version.
It was fixed Aug 5, 20:04 Pacific.
Confirm the checksum of chrony.inc please:
[26.03.1-RELEASE][root@fw]/root: sum /usr/local/pkg/chrony.inc 21514 10 /usr/local/pkg/chrony.inc [26.03.1-RELEASE][root@fw]/root:As to the allow, this is always enabled in the config file. You should see an allow line like this in /usr/local/etc/chrony.conf:
# This file is generated by the pfSense Chrony package. # Do not edit this file, it will be overwritten automatically. # NTP Sources pool time.cloudflare.com minpoll 6 maxpoll 10 iburst maxsources 2 nts ntsservercert /var/db/chrony/ntsservercert.pem ntsserverkey /var/db/chrony/ntsserverkey.pem # Access restrctions are implemented using firewall rules. allow # Record the rate at which the system clock gains/losses time. driftfile /var/db/chrony/driftfile # Keep measurements across restarts. dumpdir /var/db/chrony # Keep NTS cookies and keys. ntsdumpdir /var/db/chrony # Allow the system clock to be stepped in the first three # updates if the offset is larger than 1 second. makestep 1.0 3 -
@Mission-Ghost said in Chrony package:
501 Not authorised
Auth DataAh... are you using chrony-lite by chance?
-
@Mission-Ghost Confim checksum of package file:
[26.03.1-RELEASE][root@fw]/root/packages: sum pfSense-pkg-Chrony-4.8.pkg 52980 14 pfSense-pkg-Chrony-4.8.pkg [26.03.1-RELEASE][root@fw]/root/packages: -
[26.03.1-RELEASE][admin@slbctg-gw-c.slbctg.home.arpa]/cf/conf/chrony_package: sum /usr/local/pkg/chrony.inc 21514 10 /usr/local/pkg/chrony.incI don't know how I could be using chrony lite. I just downloaded your package using the link you provided, un-tarred it, and then installed it with the command you specified.
My side-loaded version is named chrony.exe so I can't see how it's being run by mistake...and it's not the lite version either. ???
-
[26.03.1-RELEASE][admin@slbctg-gw-c.slbctg.home.arpa]/cf/conf/chrony_package: sum pfSense-pkg-Chrony-4.8.pkg 52980 14 pfSense-pkg-Chrony-4.8.pkg -
@Mission-Ghost That's the correct sum. Did you check the sum on the .inc file?
-
@dennypage said in Chrony package:
@Mission-Ghost That's the correct sum. Did you check the sum on the .inc file?
I did:
[26.03.1-RELEASE][admin@slbctg-gw-c.slbctg.home.arpa]/cf/conf/chrony_package: sum /usr/local/pkg/chrony.inc 21514 10 /usr/local/pkg/chrony.inc -
@Mission-Ghost said in Chrony package:
I did:
[26.03.1-RELEASE][admin@slbctg-gw-c.slbctg.home.arpa]/cf/conf/chrony_package: sum /usr/local/pkg/chrony.inc
21514 10 /usr/local/pkg/chrony.incOkay, so you are no longer receiving an error if you enable local mode then?
-
@dennypage said in Chrony package:
[Sorry for terse reply -- I broke my clavicle Friday, and I'm one hand typing which is hard.]
Missed this earlier; I'm sorry for your suffering. I can sympathize. I road-rashed myself sliding on gravel on my bike about 18 mos. ago and it's the most painful thing I've experienced outside of a kidney stone. It's rattles one's confidence, too.
-
@Mission-Ghost And chrony execs:
[26.03.1-RELEASE][root@fw]/root/packages: sum /usr/local/sbin/chronyd 11684 297 /usr/local/sbin/chronyd [26.03.1-RELEASE][root@fw]/root/packages: sum /usr/local/bin/chronyc 53274 104 /usr/local/bin/chronyc [26.03.1-RELEASE][root@fw]/root/packages: -
-
@dennypage still blows up.
Privacy Policy · Cookie Policy