WHAT TO EXPECT
In this article, users will learn how to install a groundSwXtch on an existing Ubuntu 24.04 machine. For more information about VM or hardware prerequisites, please see the groundSwXtch System Requirements
Pre-Installation Step: Create the environment
What is needed:
For prerequisites, see groundSwXtch System Requirements
VM must be Ubuntu 24.04
The VM needs an internet connection.
The user must be able to log into the VM or physical machine (each agent)
Prerequisites
Currently, users must install and enable Docker on their Ubuntu VM. Please see "How to Install Docker on RHEL and Ubuntu".
NOTE
The installation script will also install all dependencies.
STEP ONE: Prepare the installation by updating the OS
Update all of the currently installed OS packages
sudo apt update && sudo apt upgrade -yReboot VM
sudo reboot now
STEP TWO: Install groundSwXtch
In this step, users will execute commands in their VMs or hardware devices to manually install a groundSwXtch.
Connect to the VM instance or hardware device that will be used as a groundSwXtch.
Download the package onto the groundSwXtch
Enter the following commands to download and install the groundSwXtch installer script:
curl -fL "https://swxrkdistribution.blob.core.windows.net/swxcontainer01/install-groundswxtch.sh?sp=rl&st=2026-05-21T21:40:09Z&se=2027-05-23T05:55:09Z&spr=https&sv=2026-02-06&sr=c&sig=HA9RA9sUQwLBKfePWwB3UhLKGlvtJgoT6z2bCU1Kb6k%3D" -o install-groundswxtch.sh && chmod +x install-groundswxtch.shThe recommended method will install with dependencies:
chmod +x install-groundswxtch.sh sudo ~/install-groundswxtch.sh install --image-tag groundswxtch:dev-2494302cNIC selection for wan and lan interfaces can be added with these arguments:
--lan-iface enp2s0 --wan-iface enp2s0
Example:
sudo ~/install-groundswxtch.sh install --image-tag groundswxtch:dev-2494302c --lan-iface enp2s0 --wan-iface enp2s0Configuration and Log files for a groundSwXtch:
Configuration files can be found in /var/lib/groundswxtch.
Logs can be viewed using
docker logs -f gswx
After the installation, run the following command to see if the container is running:
docker psThere should be a line with the name gswx. For example:
ubuntu@drs-ground-swxtch-001:~$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES d50428d6b201 groundswxtch:dev-70d1fc5c "groundswxtchd" 5 hours ago Up 5 hours gswx 95d07c68d75e swx-tools:1.0.0 "sleep infinity" 5 days ago Up 29 hours swx-tools ubuntu@drs-ground-swxtch-001:~$
Air-Gapped Deployment
For groundSwXtch without GHCR or Azure Blob access (emergency fallback — the install-groundswxtch.sh path is preferred):
# On a connected host:
docker pull ghcr.io/swxtchio/groundswxtch:v1.1.0-spp.7dbc218
docker save ghcr.io/swxtchio/groundswxtch:v1.1.0-spp.7dbc218 \
| gzip > groundswxtch-v1.1.0.tar.gz
scp groundswxtch-v1.1.0.tar.gz nuc-2:/tmp/
# On the air-gapped NUC:
docker load < /tmp/groundswxtch-v1.1.0.tar.gz
docker image ls ghcr.io/swxtchio/groundswxtchThen follow the following steps:
Help Arguments
To get a list of arguments that can be used during the installation, use the help command -h:
$ ./install-groundswxtch.sh -hA list of installation arguments will display as shown below:
ubuntu@drs-ground-swxtch-006:~$ sudo ./install-groundswxtch.sh tools -h [install-groundswxtch] WARN: 'tools' is a deprecated alias for 'swx-tools' — please switch (the alias still works for now). Usage: install-groundswxtch.sh <subcommand> [flags] ═══ SIMPLEST INSTALL (recommended for customer deployments) ═══ sudo ./install-groundswxtch.sh install --image-tag groundswxtch:v1.1 Defaults to host networking — container shares the host's network namespace, no IP/subnet/gateway flags needed. Daemon auto-detects its gateway. ═══ FIRST-RUN ON UNLICENSED HARDWARE ═══ License is OPTIONAL at boot — the container starts in degraded mode (daemon + REST API up; no traffic processing). First-run flow on a new machine: 1. sudo ./install-groundswxtch.sh install --image-tag groundswxtch:v1.1 → boots unlicensed, logs a banner explaining the degraded state. 2. curl http://127.0.0.1/api/v1/license/fingerprint → returns the machine's fingerprint hash; send it to swxtch. 3. Receive your fingerprint-bound license.key, drop it at /var/lib/groundswxtch/license.key (sudo cp ...). 4. curl -X POST http://127.0.0.1/api/v1/license/reload → daemon hot-reloads the new license — no container restart needed. ═══ Subcommands ═══ gswx-fetch Download + verify + docker-load the gswx image. No launch. Use this to pre-stage a new release before bring-up, or to stage an upgrade (combine with --force-fetch). Idempotent. Alias: 'fetch' (legacy). network Create the gswx-wan macvlan network. Only required when --network-mode=macvlan. Skip in host mode. gswx-run Launch the gswx container (image must already be loaded). Replaces any existing gswx container with the same name — use this to bring up a new tag after gswx-fetch (upgrade). Alias: 'run' (legacy). install gswx-fetch + gswx-run (host mode), or gswx-fetch + network + gswx-run (macvlan mode). DEFAULT when no subcommand is given. swx-tools-fetch Download + verify + docker-load the swx-tools image. No launch. Use to upgrade the tools image independently of running. Alias: 'tools-fetch' (legacy, deprecated). swx-tools-run Launch the swx-tools container (image must already be loaded). Replaces any existing swx-tools container with the same name. Alias: 'tools-run' (legacy, deprecated). swx-tools swx-tools-fetch + swx-tools-run convenience. Alias: 'tools' (legacy, deprecated). teardown Stop + remove gswx and swx-tools containers (preserves state, images, and network so reinstall is fast). Pass --full to also remove the gswx-wan network, /var/lib/groundswxtch state, and both loaded images. restart Recreate the gswx container with the current flag values (e.g. after changing --name). Inherits the running container's --image-tag so you don't have to remember which version is loaded — pass --image-tag only to also upgrade in-place. ═══ Flags ═══ Required by 'fetch', 'run', 'install': --image-tag <ref> Image to fetch + run. Accepts: latest-prod newest blessed prod release (channel alias; auto-resolved by this script) latest-dev newest blessed dev build (channel alias) groundswxtch:v1.2 newest patch of a minor groundswxtch:v1.2.0 exact immutable build No implicit default — the blob carries multiple versions in parallel. The channel aliases resolve to a concrete build via a pointer in the blob (logged as 'channel latest-X → ...'); a channel with nothing promoted yet fails with a distinct "not currently published" error. Exact tags + moving minors fetch directly with no pointer lookup. Network mode (drives which other flags are needed): --network-mode <mode> host (default) | macvlan. host — share host's network namespace; no IP/subnet/gateway needed. macvlan — dedicated container IP on a macvlan over a host NIC; needs --ip --subnet --gateway --parent-iface. Use for multi-instance on the same host. Required by 'run' and 'install' only when --network-mode=macvlan: --ip <addr> Container IP on gswx-wan (e.g. 192.168.1.10). --subnet <cidr> macvlan subnet (e.g. 192.168.1.0/24). --gateway <addr> macvlan gateway (e.g. 192.168.1.1). --parent-iface <nic> Host NIC for macvlan parent (e.g. enp2s0). Optional (all modes): --name <name> Instance display name. Surfaces on /api/v1/stats as `instance`, rendered in the SPA as "this instance", and reported to peers via peer-health. Default = the host's short hostname (e.g. groundswxtch-1) so each peer in a fleet shows up distinctly in the UI. NOTE: this is the daemon's self-identity, NOT the docker container name (docker --name stays 'gswx' for muscle-memory portability — `docker exec gswx` works identically on every host). --role boundary|leaf PTP grandmaster (boundary) or PTP2 client (leaf). Default: leaf. Drives TIMEBEAT_PTP2_CONCURRENT. --wan-gateway <addr> GROUNDSWXTCH_WAN_GATEWAY. Optional — daemon falls back to rtnetlink (CFG-13) when unset. Pass only if auto-detect picks the wrong gateway. --wan-iface <nic> GROUNDSWXTCH_WAN_DEV (issue #1004). WAN NIC the daemon binds. Optional — daemon auto-detects when unset. --lan-iface <nic> GROUNDSWXTCH_LAN_DEV (issue #1004). LAN NIC for local-multicast. INDEPENDENT of --wan-iface (dual-NIC). Optional — omit for the default virtual LAN (swx0-lan); set to the WAN NIC for same-NIC mode, or a distinct NIC for dual-NIC mode. NOTE (both --wan-iface/--lan-iface): these are FIRST-BOOT config SEEDS. yaml-trumps-env — once the daemon has persisted groundswxtch.yaml the persisted value wins and these are IGNORED (the installer WARNs when a persisted config already exists). Change a running install via the SPA / PUT /api/v1/config, or 'teardown --full' then re-seed. Env vars accepted too. --veth-instance <N> GROUNDSWXTCH_VETH_INSTANCE (1..=255). PINS the per-host swx0-lan veth /30: N=1 → 169.254.1.{1,2}, N=221 → 169.254.221.{1,2}. DEFAULT (omit this flag): the daemon AUTO-derives the instance from network.address' last octet and OWNS it — a VLAN move recomputes it automatically (#170). Pass --veth-instance ONLY to pin a fixed value the daemon must never recompute (e.g. two hosts on different /24s with the same last octet, or multiple gswx on a single host). --peer-id <fp> Boundary clock libp2p fingerprint (leaf clients). --peer-ip <addr> Boundary clock IP (leaf clients). --peer-port <port> Boundary clock DHT port (default: 65107). --state-root <dir> Persistent state root (default: /var/lib/groundswxtch). Mounted inside the container at /etc/groundswxtch. --license-dir <dir> Convenience: seeds <dir>/license.key into --state-root when the state-root has none. Checked every run (so a re-install after 'teardown --full' re-seeds); never overwrites an existing key; warns if <dir>/license.key is missing/empty rather than booting unlicensed silently. --force-fetch Re-download + reload even if image is already present. --skip-docker-install Don't auto-install Docker if it's missing. By default a missing Docker engine is auto-installed (issue #77) via https://get.docker.com so a fresh host runs the full setup end-to-end; pass this (or set SKIP_DOCKER_INSTALL=true) to get a clear actionable error instead — e.g. for air-gapped / managed hosts. --ptp2-concurrent <int> Override role-derived TIMEBEAT_PTP2_CONCURRENT. --extra-mount <triple> Extra docker -v mount, e.g. /tmp/19.1-spa:/opt/groundswxtch/ui/spa. Repeatable. Phase 19.1 plan 04 codex HIGH-2 dev knob — production installs leave this unset. --extra-daemon-arg <a> Extra CLI flag forwarded to the daemon, e.g. --ui-dev=/opt/groundswxtch/ui/spa. Repeatable. Phase 19.1 plan 04 codex HIGH-2 dev knob — production installs leave this unset. -h, --help Show this help. 'swx-tools-fetch', 'swx-tools-run', 'swx-tools' flags (legacy aliases: 'tools*'): --tools-version <ver> swx-tools version to pull. Default: 1.0.0. Pass 'latest' to auto-resolve the current prod-blessed swx-tools build via the channel pointer (prod ONLY — swx-tools has no latest-dev). Pass an exact version when a specific tools release is needed. --network <name> Docker network for the swx-tools container. Default: host (shares the host's net namespace with spp). This is the only mode where round- trip mcast testing works end-to-end today — send + receive both flow correctly through spp's tunnel. Avoid UDP 5000 + 6000 (spp reserves them at boot via KernelSocketClaim). Pass 'bridge' for SEND-only tests on the docker0 bridge (receive is broken on docker0 due to source-IP collisions + bridge IGMP forwarding quirks). Pass 'gswx-wan' when gswx was installed with --network-mode=macvlan. --tools-ip <addr> Container IP — required only when --network is a macvlan. Pick an unused IP in the macvlan subnet. --tools-container-name <name> Docker container name. Default: <hostname>-tools. 'teardown' flags: --full Also remove the gswx-wan network, /var/lib/groundswxtch state directory, and both loaded images. Without --full, only the containers are removed (state, images, and network are preserved so a re-install is fast). The script is idempotent: fetch / swx-tools-fetch skip curl+load if the image is already present (unless --force-fetch); network skips create if gswx-wan already exists; run / swx-tools-run remove any pre-existing container with the same name before launching.
files are located in /var/lib/groundswxtch/
timebeat logs are in /var/log/timebeat
swx tools can be installed using the following commands after the download for groundSwXtch:
sudo ./install-groundswxtch.sh toolsswx-tools are used to test the system. Refer to Tools and Testing for more information on the tools provided.
The swx tools run in docker, therefore to access them and run swx commands:
sudo docker exec -it swx-tools bash
STEP THREE: License the groundSwXtch
For more information, see How to license the groundSwXtch.
NEXT STEPS
The groundSwXtch is ready to use. The next step is to install at least one more groundSwXtch to connect one on-prem network to another.