From f231561276db3f4291b76ada94fbf4a907a44ef7 Mon Sep 17 00:00:00 2001 From: Chris Spiegel Date: Mon, 3 Nov 2025 17:48:04 -0800 Subject: [PATCH 01/13] Stop and restart the Prometheus worker thread when daemonizing Also use _Exit() instead of returning from main() to avoid duplicate cleanup/flusing/etc. --- .../core/include/prometheus/save_to_file.h | 10 ++++++++++ one.cpp | 6 +++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/ext/prometheus-cpp-lite-1.0/core/include/prometheus/save_to_file.h b/ext/prometheus-cpp-lite-1.0/core/include/prometheus/save_to_file.h index 26bd0c95c..d181b1358 100644 --- a/ext/prometheus-cpp-lite-1.0/core/include/prometheus/save_to_file.h +++ b/ext/prometheus-cpp-lite-1.0/core/include/prometheus/save_to_file.h @@ -50,6 +50,16 @@ namespace prometheus { public: SaveToFile() = default; + void stop() { + must_die = true; + worker_thread.join(); + } + + void restart() { + must_die = false; + worker_thread = std::thread(&SaveToFile::worker_function, this); + } + ~SaveToFile() { must_die = true; worker_thread.join(); diff --git a/one.cpp b/one.cpp index 0e2ac4cfa..8c67a3af2 100644 --- a/one.cpp +++ b/one.cpp @@ -2330,14 +2330,18 @@ int main(int argc, char** argv) } #endif // !ZT_ONE_NO_ROOT_CHECK if (runAsDaemon) { + prometheus::simpleapi::saver.stop(); + long p = (long)fork(); if (p < 0) { fprintf(stderr, "%s: could not fork" ZT_EOL_S, argv[0]); return 1; } else if (p > 0) - return 0; // forked + _Exit(0); // forked // else p == 0, so we are daemonized + + prometheus::simpleapi::saver.restart(); } #endif // __UNIX_LIKE__ From 616698fa91c67906851e18c55835831bb5c1aa25 Mon Sep 17 00:00:00 2001 From: Chris Spiegel Date: Wed, 5 Nov 2025 10:42:12 -0800 Subject: [PATCH 02/13] Ensure erase() is called after std::unique() Without this the duplicates are just moved to the end of the collection, but not actually erased. --- osdep/BSDEthernetTap.cpp | 4 ++-- osdep/MacKextEthernetTap.cpp | 2 +- osdep/NetBSDEthernetTap.cpp | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/osdep/BSDEthernetTap.cpp b/osdep/BSDEthernetTap.cpp index 36e70ca7c..82ac07d1a 100644 --- a/osdep/BSDEthernetTap.cpp +++ b/osdep/BSDEthernetTap.cpp @@ -339,7 +339,7 @@ std::vector BSDEthernetTap::ips() const freeifaddrs(ifa); std::sort(r.begin(), r.end()); - std::unique(r.begin(), r.end()); + r.erase(std::unique(r.begin(), r.end()), r.end()); _ifaddrs = r; @@ -394,7 +394,7 @@ void BSDEthernetTap::scanMulticastGroups(std::vector& added, std newGroups.push_back(MulticastGroup::deriveMulticastGroupForAddressResolution(*ip)); std::sort(newGroups.begin(), newGroups.end()); - std::unique(newGroups.begin(), newGroups.end()); + newGroups.erase(std::unique(newGroups.begin(), newGroups.end()), newGroups.end()); for (std::vector::iterator m(newGroups.begin()); m != newGroups.end(); ++m) { if (! std::binary_search(_multicastGroups.begin(), _multicastGroups.end(), *m)) diff --git a/osdep/MacKextEthernetTap.cpp b/osdep/MacKextEthernetTap.cpp index 707858fd9..399742929 100644 --- a/osdep/MacKextEthernetTap.cpp +++ b/osdep/MacKextEthernetTap.cpp @@ -607,7 +607,7 @@ void MacKextEthernetTap::scanMulticastGroups(std::vector& added, newGroups.push_back(MulticastGroup::deriveMulticastGroupForAddressResolution(*ip)); std::sort(newGroups.begin(), newGroups.end()); - std::unique(newGroups.begin(), newGroups.end()); + newGroups.erase(std::unique(newGroups.begin(), newGroups.end()), newGroups.end()); for (std::vector::iterator m(newGroups.begin()); m != newGroups.end(); ++m) { if (! std::binary_search(_multicastGroups.begin(), _multicastGroups.end(), *m)) diff --git a/osdep/NetBSDEthernetTap.cpp b/osdep/NetBSDEthernetTap.cpp index 666a387f6..aa923bdb3 100644 --- a/osdep/NetBSDEthernetTap.cpp +++ b/osdep/NetBSDEthernetTap.cpp @@ -316,7 +316,7 @@ std::vector NetBSDEthernetTap::ips() const freeifaddrs(ifa); std::sort(r.begin(), r.end()); - std::unique(r.begin(), r.end()); + r.erase(std::unique(r.begin(), r.end()), r.end()); return r; } @@ -367,7 +367,7 @@ void NetBSDEthernetTap::scanMulticastGroups(std::vector& added, newGroups.push_back(MulticastGroup::deriveMulticastGroupForAddressResolution(*ip)); std::sort(newGroups.begin(), newGroups.end()); - std::unique(newGroups.begin(), newGroups.end()); + newGroups.erase(std::unique(newGroups.begin(), newGroups.end()), newGroups.end()); for (std::vector::iterator m(newGroups.begin()); m != newGroups.end(); ++m) { if (! std::binary_search(_multicastGroups.begin(), _multicastGroups.end(), *m)) From 48311896f873c1a3ecc413895a6906eb1c46fb3d Mon Sep 17 00:00:00 2001 From: Chris Spiegel Date: Mon, 3 Nov 2025 21:21:47 -0800 Subject: [PATCH 03/13] Allow metrics to be disabled --- service/OneService.cpp | 9 +++++++++ service/README.md | 3 ++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/service/OneService.cpp b/service/OneService.cpp index 41d790516..cd275aa23 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -2931,6 +2931,15 @@ class OneServiceImpl : public OneService { _allowManagementFrom.push_back(nw); } } + + bool disableMetrics = OSUtils::jsonBool(settings["disableMetrics"], false); + if (disableMetrics) { + std::shared_ptr registry; + prometheus::simpleapi::saver.set_registry(registry); + } + else { + prometheus::simpleapi::saver.set_registry(prometheus::simpleapi::registry_ptr); + } } #if ZT_VAULT_SUPPORT diff --git a/service/README.md b/service/README.md index 94e920a58..19a3f80b5 100644 --- a/service/README.md +++ b/service/README.md @@ -41,7 +41,8 @@ Settings available in `local.conf` (this is not valid JSON, and JSON does not al "allowManagementFrom": [ "NETWORK/bits", ...] |null, /* If non-NULL, allow JSON/HTTP management from this IP network. Default is 127.0.0.1 only. */ "bind": [ "ip",... ], /* If present and non-null, bind to these IPs instead of to each interface (wildcard IP allowed) */ "allowTcpFallbackRelay": true|false, /* Allow or disallow establishment of TCP relay connections (true by default) */ - "multipathMode": 0|1|2 /* multipath mode: none (0), random (1), proportional (2) */ + "multipathMode": 0|1|2, /* multipath mode: none (0), random (1), proportional (2) */ + "disableMetrics": true|false /* If true, disable the collection of metrics in metrics.prom. */ } } ``` From 1d9f06d4ac9c9af5e04a0f1ca5a4e944dd363047 Mon Sep 17 00:00:00 2001 From: Chris Spiegel Date: Thu, 6 Nov 2025 05:18:26 -0800 Subject: [PATCH 04/13] Disable metrics by default --- RELEASE-NOTES.md | 4 ++++ service/OneService.cpp | 11 +++++------ service/README.md | 2 +- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index 5cecf3400..1f3551389 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -1,6 +1,10 @@ ZeroTier Release Notes ====== +## WORK-IN-PROGRESS + + * Metrics collection is now disabled by default. It can be enabled via the `enableMetrics` setting in `local.conf`. + ## 2025-08-21 -- Version 1.16.0 * License Changes diff --git a/service/OneService.cpp b/service/OneService.cpp index cd275aa23..d207bd495 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -988,7 +988,6 @@ class OneServiceImpl : public OneService { _ports[1] = 0; _ports[2] = 0; - prometheus::simpleapi::saver.set_registry(prometheus::simpleapi::registry_ptr); prometheus::simpleapi::saver.set_delay(std::chrono::seconds(5)); prometheus::simpleapi::saver.set_out_file(_homePath + ZT_PATH_SEPARATOR + "metrics.prom"); @@ -2932,13 +2931,13 @@ class OneServiceImpl : public OneService { } } - bool disableMetrics = OSUtils::jsonBool(settings["disableMetrics"], false); - if (disableMetrics) { - std::shared_ptr registry; - prometheus::simpleapi::saver.set_registry(registry); + bool enableMetrics = OSUtils::jsonBool(settings["enableMetrics"], false); + if (enableMetrics) { + prometheus::simpleapi::saver.set_registry(prometheus::simpleapi::registry_ptr); } else { - prometheus::simpleapi::saver.set_registry(prometheus::simpleapi::registry_ptr); + std::shared_ptr registry; + prometheus::simpleapi::saver.set_registry(registry); } } diff --git a/service/README.md b/service/README.md index 19a3f80b5..3c9c8045a 100644 --- a/service/README.md +++ b/service/README.md @@ -42,7 +42,7 @@ Settings available in `local.conf` (this is not valid JSON, and JSON does not al "bind": [ "ip",... ], /* If present and non-null, bind to these IPs instead of to each interface (wildcard IP allowed) */ "allowTcpFallbackRelay": true|false, /* Allow or disallow establishment of TCP relay connections (true by default) */ "multipathMode": 0|1|2, /* multipath mode: none (0), random (1), proportional (2) */ - "disableMetrics": true|false /* If true, disable the collection of metrics in metrics.prom. */ + "enableMetrics": true|false /* If true, enable the collection of metrics in metrics.prom. */ } } ``` From fb162084f59ff41aceefc8e59c41e31a328e6476 Mon Sep 17 00:00:00 2001 From: Chris Spiegel Date: Wed, 5 Nov 2025 06:12:41 -0800 Subject: [PATCH 05/13] Fix assignment vs comparison typo At the same time, ensure a newline is written after the error message. --- one.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/one.cpp b/one.cpp index 8c67a3af2..ebd2d9ae3 100644 --- a/one.cpp +++ b/one.cpp @@ -1278,9 +1278,9 @@ static int cli(int argc, char** argv) return 0; } - BOOL err = WriteFile(file, dump.str().c_str(), dump.str().size(), NULL, NULL); - if (err = FALSE) { - fprintf(stderr, "Error writing file"); + BOOL ok = WriteFile(file, dump.str().c_str(), dump.str().size(), NULL, NULL); + if (ok == FALSE) { + fprintf(stderr, "Error writing file\n"); return 1; } CloseHandle(file); From 9e53fe4b12eeb24fa716d8824567860420eab60b Mon Sep 17 00:00:00 2001 From: Chris Spiegel Date: Wed, 5 Nov 2025 06:58:29 -0800 Subject: [PATCH 06/13] Avoid using the same source and destination in snprintf() It's undefined to write to a buffer you're reading from in snprintf(). On modern glibc and musl versions, this results in the string "/zerotier_dump.txt" being generated, i.e. in the root directory. Use a new variable to hold the string dump. This is done for MacOS as well. On Sequoia, at least, it's not necessary, as it handles overlapping objects fine, but this is more future-proof. At the same time, include a specific error message when the dumpfile can't be opened to help users track down problems. Also, truncate the file so that new writes don't potentially leave stale data. --- one.cpp | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/one.cpp b/one.cpp index 8c67a3af2..29179e7d2 100644 --- a/one.cpp +++ b/one.cpp @@ -1196,12 +1196,13 @@ static int cli(int argc, char** argv) return 0; } - snprintf((char*)path, sizeof(path), "%s%szerotier_dump.txt", (char*)path, ZT_PATH_SEPARATOR_S); + char dumpfile[PATH_MAX]; + snprintf(dumpfile, sizeof(dumpfile), "%s%szerotier_dump.txt", (char*)path, ZT_PATH_SEPARATOR_S); - fprintf(stdout, "Writing dump to: %s\n", path); - int fd = open((char*)path, O_CREAT | O_RDWR, 0664); + fprintf(stdout, "Writing dump to: %s\n", dumpfile); + int fd = open(dumpfile, O_CREAT | O_WRONLY | O_TRUNC, 0664); if (fd == -1) { - fprintf(stderr, "Error creating file.\n"); + perror("Error creating file"); return 1; } write(fd, dump.str().c_str(), dump.str().size()); @@ -1346,12 +1347,15 @@ static int cli(int argc, char** argv) } close(sock); char cwd[16384]; - getcwd(cwd, sizeof(cwd)); - snprintf(cwd, sizeof(cwd), "%s%szerotier_dump.txt", cwd, ZT_PATH_SEPARATOR_S); - fprintf(stdout, "Writing dump to: %s\n", cwd); - int fd = open(cwd, O_CREAT | O_RDWR, 0664); + if (getcwd(cwd, sizeof(cwd)) == nullptr) { + strcpy(cwd, "."); + } + char dumpfile[sizeof(cwd) + 32]; + snprintf(dumpfile, sizeof(dumpfile), "%s%szerotier_dump.txt", cwd, ZT_PATH_SEPARATOR_S); + fprintf(stdout, "Writing dump to: %s\n", dumpfile); + int fd = open(dumpfile, O_CREAT | O_WRONLY | O_TRUNC, 0664); if (fd == -1) { - fprintf(stderr, "Error creating file.\n"); + perror("Error creating file"); return 1; } write(fd, dump.str().c_str(), dump.str().size()); From 595a70c5ed8c7bef71edc54257e162efa1b348bc Mon Sep 17 00:00:00 2001 From: Joseph Henry Date: Mon, 10 Nov 2025 09:38:59 -0800 Subject: [PATCH 07/13] Remove old multipathMode setting --- service/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/service/README.md b/service/README.md index 3c9c8045a..5ecbb4e1f 100644 --- a/service/README.md +++ b/service/README.md @@ -41,7 +41,6 @@ Settings available in `local.conf` (this is not valid JSON, and JSON does not al "allowManagementFrom": [ "NETWORK/bits", ...] |null, /* If non-NULL, allow JSON/HTTP management from this IP network. Default is 127.0.0.1 only. */ "bind": [ "ip",... ], /* If present and non-null, bind to these IPs instead of to each interface (wildcard IP allowed) */ "allowTcpFallbackRelay": true|false, /* Allow or disallow establishment of TCP relay connections (true by default) */ - "multipathMode": 0|1|2, /* multipath mode: none (0), random (1), proportional (2) */ "enableMetrics": true|false /* If true, enable the collection of metrics in metrics.prom. */ } } From 4f6b9038f15132a8750018a24feddf55e54ac911 Mon Sep 17 00:00:00 2001 From: Joseph Henry Date: Mon, 1 Dec 2025 14:32:11 -0800 Subject: [PATCH 08/13] Disable debug logging for the HTTP API library This just quiets things down a little since the HTTP library produces so much verbose text. --- service/OneService.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/service/OneService.cpp b/service/OneService.cpp index d207bd495..227b575f7 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -2609,8 +2609,8 @@ class OneServiceImpl : public OneService { _controlPlaneV6.set_pre_routing_handler(authCheck); #if ZT_DEBUG == 1 - _controlPlane.set_logger([](const httplib::Request& req, const httplib::Response& res) { fprintf(stderr, "%s", http_log(req, res).c_str()); }); - _controlPlaneV6.set_logger([](const httplib::Request& req, const httplib::Response& res) { fprintf(stderr, "%s", http_log(req, res).c_str()); }); + //_controlPlane.set_logger([](const httplib::Request& req, const httplib::Response& res) { fprintf(stderr, "%s", http_log(req, res).c_str()); }); + //_controlPlaneV6.set_logger([](const httplib::Request& req, const httplib::Response& res) { fprintf(stderr, "%s", http_log(req, res).c_str()); }); #endif if (_primaryPort == 0) { fprintf(stderr, "unable to determine local control port"); From 23429264426c7d77ff1552796287132ebffeff17 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 12 Dec 2025 14:17:21 -0500 Subject: [PATCH 09/13] All version bumps but Windows. --- debian/changelog | 6 ++++++ ext/installfiles/mac/ZeroTier One.pkgproj | 2 +- version.h | 2 +- zerotier-one.spec | 5 ++++- 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/debian/changelog b/debian/changelog index 84b78f697..57d6b2ac4 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +zerotier-one (1.16.1) unstable; urgency=medium + + * See RELEASE-NOTES.md for release notes. + + -- Adam Ierymenko Mon, 12 Dec 2025 01:00:00 -0700 + zerotier-one (1.16.0-2) unstable; urgency=medium * Fix build settings to include controller. diff --git a/ext/installfiles/mac/ZeroTier One.pkgproj b/ext/installfiles/mac/ZeroTier One.pkgproj index 56ae6ea28..5abe96455 100755 --- a/ext/installfiles/mac/ZeroTier One.pkgproj +++ b/ext/installfiles/mac/ZeroTier One.pkgproj @@ -702,7 +702,7 @@ USE_HFS+_COMPRESSION VERSION - 1.16.0 + 1.16.1 TYPE 0 diff --git a/version.h b/version.h index 3cfa04ffa..b0e5bb00e 100644 --- a/version.h +++ b/version.h @@ -22,7 +22,7 @@ /** * Revision */ -#define ZEROTIER_ONE_VERSION_REVISION 0 +#define ZEROTIER_ONE_VERSION_REVISION 1 /** * Build version diff --git a/zerotier-one.spec b/zerotier-one.spec index ffb010c24..be57e7723 100644 --- a/zerotier-one.spec +++ b/zerotier-one.spec @@ -1,5 +1,5 @@ Name: zerotier-one -Version: 1.16.0 +Version: 1.16.1 Release: 1%{?dist} Summary: ZeroTier network virtualization service @@ -155,6 +155,9 @@ chmod 0755 $RPM_BUILD_ROOT/etc/init.d/zerotier-one %endif %changelog +* Fri Dec 12 2025 Adam Ierymenko - 1.16.1 +- see https://github.com/zerotier/ZeroTierOne for release notes + * Wed Oct 23 2024 Adam Ierymenko - 1.14.2 - see https://github.com/zerotier/ZeroTierOne for release notes From 22b47f851ee3a21d22715bfd0cbcedb84b90817c Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 12 Dec 2025 14:43:40 -0500 Subject: [PATCH 10/13] 1.16.1 Windows bump --- ext/installfiles/windows/ZeroTier One.aip | 8 +- .../windows/ZeroTier One.back.aip | 558 ------------------ 2 files changed, 4 insertions(+), 562 deletions(-) delete mode 100644 ext/installfiles/windows/ZeroTier One.back.aip diff --git a/ext/installfiles/windows/ZeroTier One.aip b/ext/installfiles/windows/ZeroTier One.aip index b787dac15..8a84ad434 100644 --- a/ext/installfiles/windows/ZeroTier One.aip +++ b/ext/installfiles/windows/ZeroTier One.aip @@ -21,10 +21,10 @@ - + - + @@ -62,7 +62,7 @@ - + @@ -515,7 +515,7 @@ - + diff --git a/ext/installfiles/windows/ZeroTier One.back.aip b/ext/installfiles/windows/ZeroTier One.back.aip deleted file mode 100644 index 9ad818277..000000000 --- a/ext/installfiles/windows/ZeroTier One.back.aip +++ /dev/null @@ -1,558 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From 9c2bd25d86d487ace3b5dc38ef83eca8b409da5a Mon Sep 17 00:00:00 2001 From: Chris Spiegel Date: Mon, 22 Dec 2025 12:50:02 -0800 Subject: [PATCH 11/13] Add a couple entries to the release notes The date still needs to be updated when this is actually released. --- RELEASE-NOTES.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index 1f3551389..270ec24b1 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -1,9 +1,11 @@ ZeroTier Release Notes ====== -## WORK-IN-PROGRESS +## XXXX-XX-XX -- Version 1.16.1 * Metrics collection is now disabled by default. It can be enabled via the `enableMetrics` setting in `local.conf`. + * Fix for an issue where metrics were not being recorded while running in daemon mode. + * Fix debug dumpfile being written to the root directory. ## 2025-08-21 -- Version 1.16.0 From a77009e4f04f6e18aeecdced75ab20e61890b34d Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 22 Dec 2025 16:50:13 -0500 Subject: [PATCH 12/13] notes --- RELEASE-NOTES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index 270ec24b1..d3441c885 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -6,6 +6,7 @@ ZeroTier Release Notes * Metrics collection is now disabled by default. It can be enabled via the `enableMetrics` setting in `local.conf`. * Fix for an issue where metrics were not being recorded while running in daemon mode. * Fix debug dumpfile being written to the root directory. + * Minor bug fixes in Mac and BSD tun/tap code. ## 2025-08-21 -- Version 1.16.0 From d2b4b6e91dc6a130d85d48a6c73799bb5e6346ff Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 22 Dec 2025 17:49:15 -0500 Subject: [PATCH 13/13] Add date to release notes. --- RELEASE-NOTES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index d3441c885..7a866b479 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -1,7 +1,7 @@ ZeroTier Release Notes ====== -## XXXX-XX-XX -- Version 1.16.1 +## 2025-12-22 -- Version 1.16.1 * Metrics collection is now disabled by default. It can be enabled via the `enableMetrics` setting in `local.conf`. * Fix for an issue where metrics were not being recorded while running in daemon mode.