Timed in the worker around the BulkApply call; reported on the per-batch
completion line and the exception line. Gives a direct client-observed
latency signal to compare against Bigtable's server-side metrics.
Replace AsyncBulkApply with synchronous BulkApply calls fanned out to a
small worker pool (8 threads, 500-row batches). The async client path
makes progress only on the connection's shared background event threads,
which stall for tens of seconds at a time in production (observed
2026-07-21: 26k-row flushes taking 3.5-8 minutes against a near-idle
cluster with server-side MutateRows p99 of 50-80ms, completions arriving
in window-sized bursts). A sync call is driven entirely by its own
thread and has months of healthy history in this environment.
Batches are built and their results processed on the calling thread, so
_lastNodeInfo and the re-queue list stay lock-free; workers only perform
the RPC and record the outcome.
Also stop dropping failed mutations: re-queue them for the next cycle
(idempotent replays via deterministic cell timestamps, backlog capped by
requeuePendingStatus) unless the status is INVALID_ARGUMENT. This
covers transient per-mutation failures the client does not retry
internally, e.g. ACCESS_TOKEN_EXPIRED and UNAVAILABLE.
A stale .deps-build/otel CMake cache from an API-only run kept
WITH_API_ONLY=ON even under ZT_CONTROLLER_DEPS=1, silently installing an
API-only opentelemetry-cpp; the controller configure then fails with
"Component sdk is not a built component". Pass the flag explicitly so
the full build always overrides a cached value.
Bigtable's MutateRows API rejects requests with more than 100,000
mutations total, and google-cloud-cpp sends a BulkMutation as a single
request -- it never splits by mutation count. writePending() built one
batch from every pending check-in (up to 5 SetCells per row), so a cold
node_info cache after a controller restart could push a single flush far
past the limit (observed: 124582). INVALID_ARGUMENT is permanent, so the
whole batch failed and those check-ins were dropped for the cycle.
Flush in chunks of at most 25,000 mutations. Failure handling is now
per-chunk: FailedMutation::original_index() aligns against a chunk-local
row-hash vector, and if BulkApply throws, only the not-yet-written tail
is re-queued so already-applied chunks are not replayed.
Template was looking for {{networkId}} but that hadn't been populated
yet in the case where the IdP returned an error. This caused the
template parsing to crash and return its own error, disguising the error
from the IdP
* Brewfile for homebrew dependencies on macos
* Pull & build google-cloud-cpp/otel via bootstrap script rather than
keeping it all in the ext/ subfolder.
* Update controller CI build with new steps
writePending() did a synchronous ReadRow per queued node to avoid
rewriting unchanged os/arch/version. With thousands of check-ins per
cycle that's thousands of sequential round-trips every 10s, and the read
was nearly pointless since last_seen and the IP cell are written every
cycle anyway.
Replace it with an in-process cache of the last-written node_info per
row (keyed by a 64-bit hash of the row key). node_info is emitted only
when changed, new, or past its refresh window; check_in is still written
every cycle. Failed rows are dropped from the cache so they're rewritten
next cycle, and stale entries are evicted (24h TTL). Net result: one
BulkApply per cycle, no read RPCs.
- Default enableBroadcast to true on load (initializeNetworks and _getNetwork) to match DB::initNetwork. Networks whose JSONB lacks the field now get broadcast on instead of off, which is the documented ZeroTier default.
- Stop overwriting networks_ctl.frontend on every UPDATE. It should remain whatever was set at INSERT. The early-exit guard already prevents cross-frontend writes from applying, so dropping the SET preserves correctness. Members are unaffected — they source frontend from the network row, not the change payload.
- Add enableBroadcast, creationTime, and revision to PubSubListener's network toJson. The protobuf carries them, but the listener was dropping them on inbound, which caused revision to reset on every PubSub-delivered network update.
- Rename member version keys to vMajor/vMinor/vRev/vProto in both PubSubListener (incoming) and PubSubWriter (outgoing). CentralDB, EmbeddedNetworkController, and the rest of the codebase already use these names; the listener/writer were the only sites using versionMajor/Minor/Rev/Protocol, so member version info was being silently dropped through PubSub in both directions.
- Pass newMember by const reference in ControllerChangeNotifier::notifyMemberChange to match notifyNetworkChange. Avoids a full JSON copy on every member notify.
- Remove duplicate nlohmann::json::parse call in RedisNetworkListener.
ssoConfig checked wrong variable
DNS missing-branch wrote to input not output
SSO fields renamed to sso* and nested under ssoConfig (across CentralDB, DB defaults, migration_models)
Member identity populated into the right field; address = memberId
noAutoAssignIPs → noAutoAssignIps casing
Member version columns now SELECTed + populated (both sites)
removeTraceLevel typo in DB.cpp defaults
8. eraseMember uninitialized tmp2 — member deletes now actually delete
9. Connection leak on continue in both commit branches
10. Unsafe (uint64_t)config["revision"] cast → OSUtils::jsonInt
11. target = "NULL" literal text → std::optional<std::string> for real SQL NULL
~13 unsafe direct json→string casts → OSUtils::jsonString; dead vars removed from save(); change_source blocks use is_string() checks.
Heartbeat zadd literal "controllerId" → variable
Network revision double-increment removed
PubSub notifier now sees actual old state (DB query moved before INSERT in both branches)
_delete_network reads config["id"] instead of config["nwid"]
ip_assignments empty-string guards added at both sites (also closes G)
ensure last_modified is set on every write to networks & members
The 10-second session.cancel() loop raced with in-flight acks — when
cancel fired while the GCP client was processing messages, acks were
lost before reaching the server. With message ordering enabled, an
unacked message blocks all subsequent messages on that ordering key,
causing silent stalls with no error output.
Two fixes:
- Replace the cancel/reconnect timer with a blocking session.get(),
storing the session future so the destructor can cancel on shutdown.
- Always ack messages even when onNotification fails — permanent errors
(bad protobuf, missing fields) will never succeed on retry and would
otherwise poison the ordering key indefinitely.
Allow controllers to advertise which central version (cv1, cv2, or all)
they are assigned to handle via a new configurable field. The value is
persisted to the database on each heartbeat and validated at startup
against the DB CHECK constraint.
Publish CTL_NONCE_UPDATE to PubSub when nonces are created or reused in
getSSOAuthInfo(), with the network's frontend as a message attribute so
only the correct CV frontend receives it. Listen for ZT1_AUTH_UPDATE
messages and update sso_expiry.authentication_expiry_time accordingly,
with a network existence check before applying.
- Add sso_send_topic/sso_recv_topic to PubSubConfig
- Add PubSubWriter::publishSSONonceUpdate() with frontend param
- Add PubSubSSOListener class for inbound auth updates
- Rename CV1_AUTH_UPDATE to ZT1_AUTH_UPDATE in sso.proto
- Fix pre-existing connection pool leak in getSSOAuthInfo() catch block
Required to get the list of configs for a particular org that the controller has. Named it `linked_id` rather than `org_id` since we don't know what it will be linked to in CV2
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.
_enabled is set to true by setUpPostDecodeReceiveThreads(), so disabled
until then, but the constructor wasn't initializing it. _concurrency is
not being used before being set but for safety's sake, ensure it has a
starting value as well.
Also, remove the vestigial _rxThreadCount, which is no longer used.
Also for pubsub trips back to CV1/CV2, rather than having 2 queues for each service (networks & members), theres now only a single queue for each change type, and `frontend = (cv1|cv2)` attribute is set on the message for filtering.
Muuuuch easier to use external dependencies now
Also tried out conan and vcpkg. Ran into dependency issues when solving for packages to install with conan.
vcpkg is just obtuse as all hell to install and not easy to integrate
PubSub allows us to do schema validation, however it only allows one top level message at a time. Move other sub-message declarations under the main message declaration so that we can enable schema validation in the pubsub stream directly
{"name":"linux-controller-release","inherits":"linux-base","displayName":"Linux Central Controller (Release)","cacheVariables":{"ZT1_CENTRAL_CONTROLLER":"ON"}},
{"name":"linux-controller-debug","inherits":"linux-base","displayName":"Linux Central Controller (Debug)","cacheVariables":{"ZT1_CENTRAL_CONTROLLER":"ON","CMAKE_BUILD_TYPE":"Debug"}},
{"name":"linux-free-release","inherits":"linux-base","displayName":"Linux daemon, free / no controller (Release)","cacheVariables":{"ZT_NONFREE":"OFF"}},
{"name":"linux-free-debug","inherits":"linux-base","displayName":"Linux daemon, free / no controller (Debug)","cacheVariables":{"ZT_NONFREE":"OFF","CMAKE_BUILD_TYPE":"Debug"}},
{"name":"macos-controller-release","inherits":"macos-base","displayName":"macOS Central Controller (Release)","cacheVariables":{"ZT1_CENTRAL_CONTROLLER":"ON"}},
{"name":"macos-controller-debug","inherits":"macos-base","displayName":"macOS Central Controller (Debug)","cacheVariables":{"ZT1_CENTRAL_CONTROLLER":"ON","CMAKE_BUILD_TYPE":"Debug"}},
{"name":"macos-free-release","inherits":"macos-base","displayName":"macOS daemon, free / no controller (Release)","cacheVariables":{"ZT_NONFREE":"OFF"}},
{"name":"macos-free-debug","inherits":"macos-base","displayName":"macOS daemon, free / no controller (Debug)","cacheVariables":{"ZT_NONFREE":"OFF","CMAKE_BUILD_TYPE":"Debug"}},
*This document is written for a software developer audience. For information on using ZeroTier, see the: [Website](https://www.zerotier.com), [Documentation Site](https://docs.zerotier.com), and [Discussion Forum](https://discuss.zerotier.com).*
## Quick Links
* [ZeroTier Documentation](https://docs.zerotier.com) - **Start here for downloads, installation, and usage**
* [How to build](build.md) - **Build instructions and platform requirements**
ZeroTier is a smart programmable Ethernet switch for planet Earth. It allows all networked devices, VMs, containers, and applications to communicate as if they all reside in the same physical data center or cloud region.
This is accomplished by combining a cryptographically addressed and secure peertopeer network (termed VL1) with an Ethernet emulation layer somewhat similar to VXLAN (termed VL2). Our VL2 Ethernet virtualization layer includes advanced enterprise SDN features like fine grained access control rules for network micro-segmentation and security monitoring.
This is accomplished by combining a cryptographically addressed and secure peer-to-peer network (termed VL1) with an Ethernet emulation layer somewhat similar to VXLAN (termed VL2). Our VL2 Ethernet virtualization layer includes advanced enterprise SDN features like fine grained access control rules for network micro-segmentation and security monitoring.
All ZeroTier traffic is encrypted end-to-end using secret keys that only you control. Most traffic flows peertopeer, though we offer free (but slow) relaying for users who cannot establish peertopeer connections.
All ZeroTier traffic is encrypted end-to-end using secret keys that only you control. Most traffic flows peer-to-peer, though we offer free (but slow) relaying for users who cannot establish peer-to-peer connections.
The goals and design principles of ZeroTier are inspired by among other things the original [Google BeyondCorp](https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/43231.pdf) paper and the [Jericho Forum](https://en.wikipedia.org/wiki/Jericho_Forum) with its notion of "deperimeterization."
Apps for Android and iOS are available for free in the Google Play and Apple app stores.
Visit [ZeroTier's site](https://www.zerotier.com/) for more information and [pre-built binary packages](https://www.zerotier.com/download/). Apps for Android and iOS are available for free in the Google Play and Apple app stores.
For repository layout, build instructions, platform requirements, and information about running ZeroTier, see [build.md](build.md).
ZeroTier is licensed under the [BSL version 1.1](https://mariadb.com/bsl11/). See [LICENSE.txt](LICENSE.txt) and the [ZeroTier pricing page](https://www.zerotier.com/pricing) for details. ZeroTier is free to use internally in businesses and academic institutions and for non-commercial purposes. Certain types of commercial use such as building closed-source apps and devices based on ZeroTier or offering ZeroTier network controllers and network management as a SaaS service require a commercial license.
## License
A small amount of third party code is also included in ZeroTier and is not subject to our BSL license. See [AUTHORS.md](AUTHORS.md) for a list of third party code, where it is included, and the licenses that apply to it. All of the third party code in ZeroTier is liberally licensed (MIT, BSD, Apache, public domain, etc.).
See [LICENSE-MPL.txt](LICENSE-MPL.txt) for all code in node/, osdep/. service/, and everywhere else except ext/ and nonfree/.
### Getting Started
See [nonfree/LICENSE.md](nonfree/LICENSE.md) for all non-free ("source available") portions of this repository.
Everything in the ZeroTier world is controlled by two types of identifier: 40-bit/10-digit *ZeroTier addresses* and 64-bit/16-digit *network IDs*. These identifiers are easily distinguished by their length. A ZeroTier address identifies a node or "device" (laptop, phone, server, VM, app, etc.) while a network ID identifies a virtual Ethernet network that can be joined by devices.
ZeroTier addresses can be thought of as port numbers on an enormous planet-wide enterprise Ethernet smart switch supporting VLANs. Network IDs are VLAN IDs to which these ports may be assigned. A single port can be assigned to more than one VLAN.
A ZeroTier address looks like `8056c2e21c` and a network ID looks like `8056c2e21c000001`. Network IDs are composed of the ZeroTier address of that network's primary controller and an arbitrary 24-bit ID that identifies the network on this controller. Network controllers are roughly analogous to SDN controllers in SDN protocols like [OpenFlow](https://en.wikipedia.org/wiki/OpenFlow), though as with the analogy between VXLAN and VL2 this should not be read to imply that the protocols or design are the same. You can use our convenient and inexpensive SaaS hosted controllers at [my.zerotier.com](https://my.zerotier.com/) or [run your own controller](controller/) if you don't mind messing around with JSON configuration files or writing scripts to do so.
### Project Layout
The base path contains the ZeroTier One service main entry point (`one.cpp`), self test code, makefiles, etc.
-`artwork/`: icons, logos, etc.
-`attic/`: old stuff and experimental code that we want to keep around for reference.
-`controller/`: the reference network controller implementation, which is built and included by default on desktop and server build targets.
-`debian/`: files for building Debian packages on Linux.
-`doc/`: manual pages and other documentation.
-`ext/`: third party libraries, binaries that we ship for convenience on some platforms (Mac and Windows), and installation support files.
-`include/`: include files for the ZeroTier core.
-`java/`: a JNI wrapper used with our Android mobile app. (The whole Android app is not open source but may be made so in the future.)
-`node/`: the ZeroTier virtual Ethernet switch core, which is designed to be entirely separate from the rest of the code and able to be built as a stand-alone OS-independent library. Note to developers: do not use C++11 features in here, since we want this to build on old embedded platforms that lack C++11 support. C++11 can be used elsewhere.
-`osdep/`: code to support and integrate with OSes, including platform-specific stuff only built for certain targets.
-`rule-compiler/`: JavaScript rules language compiler for defining network-level rules.
-`service/`: the ZeroTier One service, which wraps the ZeroTier core and provides VPN-like connectivity to virtual networks for desktops, laptops, servers, VMs, and containers.
-`windows/`: Visual Studio solution files, Windows service code, and the Windows task bar app UI.
-`zeroidc/`: OIDC implementation used by ZeroTier service to log into SSO-enabled networks. (This part is written in Rust, and more Rust will be appearing in this repository in the future.)
### Contributing
Please do pull requests off of the `dev` branch.
Releases are done by merging `dev` into `main` and then tagging and doing builds.
### Build and Platform Notes
To build on Mac and Linux just type `make`. On FreeBSD and OpenBSD `gmake` (GNU make) is required and can be installed from packages or ports. For Windows there is a Visual Studio solution in `windows/`.
- **Mac**
- Xcode command line tools for macOS 10.13 or newer are required.
- Rust for x86_64 and ARM64 targets *if SSO is enabled in the build*.
- **Linux**
- The minimum compiler versions required are GCC/G++ 8.x or CLANG/CLANG++ 5.x.
- Linux makefiles automatically detect and prefer clang/clang++ if present as it produces smaller and slightly faster binaries in most cases. You can override by supplying CC and CXX variables on the make command line.
- Rust for x86_64 and ARM64 targets *if SSO is enabled in the build*.
- **Windows**
- Visual Studio 2022 on Windows 10 or newer.
- Rust for x86_64 and ARM64 targets *if SSO is enabled in the build*.
- **FreeBSD**
- GNU make is required. Type `gmake` to build.
-`binutils` is required. Type `pkg install binutils` to install.
- Rust for x86_64 and ARM64 targets *if SSO is enabled in the build*.
- **OpenBSD**
- There is a limit of four network memberships on OpenBSD as there are only four tap devices (`/dev/tap0` through `/dev/tap3`).
- GNU make is required. Type `gmake` to build.
- Rust for x86_64 and ARM64 targets *if SSO is enabled in the build*.
Typing `make selftest` will build a *zerotier-selftest* binary which unit tests various internals and reports on a few aspects of the build environment. It's a good idea to try this on novel platforms or architectures.
### Running
Running *zerotier-one* with `-h` option will show help.
On Linux and BSD, if you built from source, you can start the service with:
sudo ./zerotier-one -d
On most distributions, macOS, and Windows, the installer will start the service and set it up to start on boot.
A home folder for your system will automatically be created.
The service is controlled via the JSON API, which by default is available at `127.0.0.1:9993`. It also listens on `0.0.0.0:9993` which is only usable if `allowManagementFrom` is properly configured in `local.conf`. We include a *zerotier-cli* command line utility to make API calls for standard things like joining and leaving networks. The *authtoken.secret* file in the home folder contains the secret token for accessing this API. See [service/README.md](service/README.md) for API documentation.
Here's where home folders live (by default) on each OS:
* **Windows**: `\ProgramData\ZeroTier\One` (That's the default. The base 'shared app data' folder might be different if Windows is installed with a non-standard drive letter assignment or layout.)
### Basic Troubleshooting
For most users, it just works.
If you are running a local system firewall, we recommend adding a rules permitting zerotier. If you installed binaries for Windows this should be done automatically. Other platforms might require manual editing of local firewall rules depending on your configuration.
See the [documentation site](https://docs.zerotier.com/zerotier/troubleshooting) for more information.
The Mac firewall can be found under "Security" in System Preferences. Linux has a variety of firewall configuration systems and tools.
On CentOS check `/etc/sysconfig/iptables` for IPTables rules. For other distributions consult your distribution's documentation. You'll also have to check the UIs or documentation for commercial third party firewall applications like Little Snitch (Mac), McAfee Firewall Enterprise (Windows), etc. if you are running any of those. Some corporate environments might have centrally managed firewall software, so you might also have to contact IT.
ZeroTier One peers will automatically locate each other and communicate directly over a local wired LAN *if UDP port 9993 inbound is open*. If that port is filtered, they won't be able to see each others' LAN announcement packets. If you're experiencing poor performance between devices on the same physical network, check their firewall settings. Without LAN auto-location peers must attempt "loopback" NAT traversal, which sometimes fails and in any case requires that every packet traverse your external router twice.
Users behind certain types of firewalls and "symmetric" NAT devices may not be able to connect to external peers directly at all. ZeroTier has limited support for port prediction and will *attempt* to traverse symmetric NATs, but this doesn't always work. If P2P connectivity fails you'll be bouncing UDP packets off our relay servers resulting in slower performance. Some NAT router(s) have a configurable NAT mode, and setting this to "full cone" will eliminate this problem. If you do this you may also see a magical improvement for things like VoIP phones, Skype, BitTorrent, WebRTC, certain games, etc., since all of these use NAT traversal techniques similar to ours.
If a firewall between you and the Internet blocks ZeroTier's UDP traffic, you will fall back to last-resort TCP tunneling to rootservers over port 443 (https impersonation). This will work almost anywhere but is *very slow* compared to UDP or direct peer to peer connectivity.
Additional help can be found in our [knowledge base](https://zerotier.atlassian.net/wiki/spaces/SD/overview).
### Prometheus Metrics
Prometheus Metrics are available at the `/metrics` API endpoint. This endpoint is protected by an API key stored in `metricstoken.secret` to prevent unwanted information leakage. Information that could be gleaned from the metrics include joined networks and peers your instance is talking to.
Access control is via the ZeroTier control interface itself and `metricstoken.secret`. This can be sent as a bearer auth token, via the `X-ZT1-Auth` HTTP header field, or appended to the URL as `?auth=<token>`. You can see the current metrics via `cURL` with the following command:
To configure a scrape job in Prometheus on the machine ZeroTier is running on, add this to your Prometheus `scrape_config`:
- job_name: zerotier-one
honor_labels: true
scrape_interval: 15s
metrics_path: /metrics
static_configs:
- targets:
- 127.0.0.1:9993
labels:
group: zerotier-one
node_id: $YOUR_10_CHARACTER_NODE_ID
authorization:
credentials: $YOUR_METRICS_TOKEN_SECRET
If neither of these methods are desirable, it is probably possible to distribute metrics via [Prometheus Proxy](https://github.com/pambrose/prometheus-proxy) or some other tool. Note: We have not tested this internally, but will probably work with the correct configuration.
Metrics are also available on disk in ZeroTier's working directory:
* Fixed line endings for the zttap300.inf for the Windows ARM x64 install.
* Internal updates to the central controller (CV1) including schema changes and a multi-architecture Docker build pipeline.
* Increased `ZT_MAX_NETWORK_SPECIALISTS` from 256 to 512 to accommodate users with large networks that exceeded the previous limit. The network config dictionary capacity was raised correspondingly.
* Resolved intermittent multi-minute delays when leaving one network and joining another under Windows.
* Compiler warning cleanup across the codebase, covering GCC 14, Clang 18, and Clang 21.
## 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.
* Fix debug dumpfile being written to the root directory.
To build on Mac and Linux just type `make`. On FreeBSD and OpenBSD `gmake` (GNU make) is required and can be installed from packages or ports. For Windows there is a Visual Studio solution in `windows/`.
### Platform Requirements
#### Mac
- Xcode command line tools for macOS 10.13 or newer are required.
- Rust for x86_64 and ARM64 targets *if SSO is enabled in the build*.
#### Linux
- The minimum compiler versions required are GCC/G++ 8.x or CLANG/CLANG++ 5.x.
- Linux makefiles automatically detect and prefer clang/clang++ if present as it produces smaller and slightly faster binaries in most cases. You can override by supplying CC and CXX variables on the make command line.
- Rust for x86_64 and ARM64 targets *if SSO is enabled in the build*.
#### Windows
- Visual Studio 2022 on Windows 10 or newer.
- Rust for x86_64 and ARM64 targets *if SSO is enabled in the build*.
#### FreeBSD
- GNU make is required. Type `gmake` to build.
-`binutils` is required. Type `pkg install binutils` to install.
- Rust for x86_64 and ARM64 targets *if SSO is enabled in the build*.
#### OpenBSD
- There is a limit of four network memberships on OpenBSD as there are only four tap devices (`/dev/tap0` through `/dev/tap3`).
- GNU make is required. Type `gmake` to build.
- Rust for x86_64 and ARM64 targets *if SSO is enabled in the build*.
### Building with CMake (optional)
> **Note:** CMake is an *alternative* build path, offered as a convenience. The official
> builds are still produced by the platform makefiles (above) and the Visual Studio solution
> in `windows/`.
#### Prerequisites
- **CMake** 3.15 or newer.
- The same compiler/toolchain (and Rust, if SSO is enabled) as the makefile build for your
platform — see *Platform Requirements* above.
- The header-only **OpenTelemetry API** must be present on `CMAKE_PREFIX_PATH`. Populate it
into `./.deps` by running the bootstrap script once, in its **default** (quick, header-only)
mode — i.e. *without*`ZT_CONTROLLER_DEPS=1`, which is the heavyweight controller-only path:
```bash
scripts/bootstrap-deps.sh # default mode: header-only OTel API into ./.deps
```
The script prints the exact `-DCMAKE_PREFIX_PATH` to use when it finishes.
#### Free vs. default (non-free) builds
By default the daemon is built **with the bundled FileDB network controller**, which lives
under `nonfree/` and is "source available" (non-free) — this matches what ships in official
builds (`ZT_NONFREE=ON`). To produce a **purely free** daemon (MPL-2.0 `node/`, `osdep/`,
`service/` only, with no `nonfree/` code compiled or linked), set **`-DZT_NONFREE=OFF`** — or
use one of the `*-free-*` presets, which set it for you.
#### Using presets (recommended)
`cmake --list-presets` shows the presets for your OS. The daemon presets are:
The binary is `build/zerotier-one`. (On macOS, append the Homebrew prefixes to
`CMAKE_PREFIX_PATH` if your dependencies come from Homebrew, as the presets do.)
### Testing
Typing `make selftest` will build a *zerotier-selftest* binary which unit tests various internals and reports on a few aspects of the build environment. It's a good idea to try this on novel platforms or architectures.
## Running ZeroTier
Running *zerotier-one* with `-h` option will show help.
On Linux and BSD, if you built from source, you can start the service with:
sudo ./zerotier-one -d
On most distributions, macOS, and Windows, the installer will start the service and set it up to start on boot.
A home folder for your system will automatically be created.
The service is controlled via the JSON API, which by default is available at `127.0.0.1:9993`. It also listens on `0.0.0.0:9993` which is only usable if `allowManagementFrom` is properly configured in `local.conf`. We include a *zerotier-cli* command line utility to make API calls for standard things like joining and leaving networks. The *authtoken.secret* file in the home folder contains the secret token for accessing this API. See [service/README.md](service/README.md) for API documentation.
## Directory Structure
### Home Folder Locations
ZeroTier stores its configuration and state files in platform-specific locations:
* **Windows**: `\ProgramData\ZeroTier\One` (That's the default. The base 'shared app data' folder might be different if Windows is installed with a non-standard drive letter assignment or layout.)
Loaded 20 of 1435 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.