port mintlify to fumadocs

This commit is contained in:
miloschwartz
2026-09-25 15:31:51 -04:00
parent dc54fb1017
commit 63199a588c
373 changed files with 13533 additions and 4577 deletions
@@ -0,0 +1,40 @@
---
title: "Archiving & Blocking"
description: "Manage clients and block unwanted connections"
---
## Blocking Devices
To block a device that has been compromised or lost:
1. Navigate to the device in your client list
2. Click the Action Menu (three dots)
3. Select **Block**
When you block a device, it is immediately moved to a restricted list and loses access to all resources or the ability to connect.
## Archiving Devices
Devices cannot be permanently deleted from Pangolin. Instead, you can archive devices to remove them from your active client list.
To archive a device:
1. Navigate to the device in your client list
2. Click the Action Menu (three dots)
3. Select **Archive**
### Why Archive Instead of Delete?
Pangolin maintains a permanent audit trail of all devices that have accessed your resources. This ensures:
- Block rules remain effective even for archived devices
- Security logs and access history are preserved
Archiving keeps your interface clean by hiding inactive or duplicate devices while maintaining the integrity of your security records.
## Filtering
You can filter your client list to show only active, blocked, or archived devices.
<Frame>
<img src="/images/device_list_filter.png" alt="Client List Filters" style={{width: "400px", height: "auto"}} />
</Frame>
@@ -0,0 +1,65 @@
---
title: "Client Logs"
description: "View Pangolin client logs on Windows, Mac, Linux, Android, and iOS"
---
How you access client logs depends on the platform. Use the section for your client type below.
## Windows
You can view logs in the Pangolin client GUI under **Preferences > Logs**.
You can also open the log file directly. The default location is:
```
C:\ProgramData\pangolin\logs\pangolin.log
```
To tail the log in PowerShell:
```powershell
Get-Content "C:\ProgramData\pangolin\logs\pangolin.log" -Tail 0 -Wait
```
## Mac
Mac uses the Apple system logger. To stream Pangolin logs:
```bash
log stream --predicate 'subsystem == "net.pangolin.Pangolin" OR subsystem == "net.pangolin.Pangolin.PacketTunnel"' --level debug --style compact
```
## CLI / Linux
The default log file location is:
```
~/.config/pangolin/logs/client.log
```
If you run `pangolin up` in detached mode, you can tail logs with:
```bash
pangolin logs client -f -n 10
```
This example follows new log lines and shows the last 10 rows.
Alternatively, run in attached mode to see logs in the current terminal session:
```bash
sudo pangolin up --attach
```
## Android
View logs within the app under **Preferences > Logs**.
## iOS
Because of how iOS handles system logging, attach the iPhone to a Mac and use Console.app to view logs.
In Console.app, add a **Subsystem** filter for:
```
net.pangolin.Pangolin
```
@@ -0,0 +1,543 @@
---
title: "Configure Clients"
description: "Configure Olm for connecting to Pangolin clients"
---
## GUI Clients (Mac, Windows, Android, iOS/iPadOS)
Each respective client has a preferences window with all currently available configuration parameters. In your desktop client, click the menu bar or system tray icon, select "More" in the menu, and click "Preferences". In the mobile apps, navigate to the "Settings" screen.
To troubleshoot connection or configuration issues, see [Client Logs](/manage/clients/client-logs) for how to view logs on each platform.
## Preferences
The following preferences control how your client handles DNS resolution and network routing. Understanding these settings helps you configure Pangolin to work best with your network setup.
#### Enable Aliases (Override DNS)
When enabled, the client uses custom DNS servers to resolve internal resources and aliases. This overrides your system's default DNS settings. Queries that cannot be resolved as a Pangolin resource will be forwarded to your configured Upstream DNS Server.
**When to use it**: This is required if you use aliases on resources in Pangolin. Aliases are friendly domain names assigned to private resources. Pangolin resolves these alias addresses over a private DNS server running in your client.
**How it works**: The client loops back to itself to resolve the alias. This is why you may see your DNS server as an unfamiliar address (often like `100.90.128.x`) when this is enabled. When a request doesn't resolve to a Pangolin resource and is bound for another website (like `google.com`), it falls back to your configured upstream DNS server.
#### DNS Over Tunnel
When enabled, DNS queries are routed through the tunnel for remote resolution. To ensure queries are tunneled correctly, you must define the DNS server as a Pangolin resource and enter its address as an Upstream DNS Server.
**When to use it**: Tunnel DNS is used when you want to send all DNS queries over the tunnel to a private resource made available in Pangolin. For example, if you host a DNS server like Pi-hole, you could define a private resource for Pi-hole on your remote network. Then in the Pangolin client, you would enable Tunnel DNS and set the host of the Pi-hole private resource as the tunnel DNS server.
**How it works**: When a request needs to be resolved, Pangolin sends it over the tunnel to the site of the private resource with your DNS server. You must enable DNS Over Tunnel and also set the upstream DNS server to your private DNS server.
This requires aliases "override DNS" to be enabled as well. This is because the client must take control of your DNS settings to route queries through the tunnel to your private DNS server.
<Warning>
You cannot use an alias name for your DNS server. It must be the IP address of the resource. This is because it's pointing to the DNS server, so the DNS server can't resolve itself.
</Warning>
#### Primary Upstream DNS
This is the DNS server used to resolve queries that are not bound to a Pangolin alias when Override DNS or DNS Over Tunnel is enabled.
When left blank, **System DNS** is used. This pulls the existing configured system DNS settings and applies them to the tunnel. If Tunnel DNS is enabled and System DNS is used, requests will likely fail if the DNS server is not accessible over the tunnel.
#### Secondary Upstream DNS
This is a fallback DNS server used to resolve queries that are not bound to a Pangolin alias when the primary server is unavailable. Ordering and priority of the server is not guaranteed, but it provides redundancy for DNS resolution. When left blank, **System DNS** is used, same as Primary Upstream DNS.
#### Match Domains
By default, when match domains are not set, all DNS queries are sent to the configured upstream DNS server. Match domains let you whitelist which domains should be sent to the upstream DNS server. When match domains are set, only matching queries go to upstream DNS; all other requests use the system's DNS servers.
**When to use it**: When you have a private or corporate DNS server for specific domains (for example, `*.proxy.internal` or `corp.example.com`) and want everything else resolved by the system DNS as usual.
**How it works**: With no match domains configured, every query is forwarded to your Upstream DNS Server. With match domains set, only queries that match the list are forwarded upstream; the rest use the system's default DNS servers.
#### MTU
You can set the maximum transmission unit (MTU) for the client’s internal WireGuard interface. This value is client-wide: every site the client connects to must use the same MTU on the site side, or you can see fragmentation, failed handshakes, or unstable tunnels. See the **mtu** option on [Configure Sites](/manage/sites/configure-site) and set the same value on each of those sites.
<Warning>
Changing MTU is advanced and not recommended for most users. Only change it when you have a specific, well-understood reason (for example, a constrained network path or a requirement from your infrastructure team). If you do change it, you must update every connected site to the identical value.
</Warning>
## Windows Client (Advanced)
On Windows, the Pangolin GUI reads configuration from two `pangolin.json` files:
- User config: `%LOCALAPPDATA%\Pangolin\pangolin.json` (for example, `C:\Users\USER\AppData\Local\Pangolin\pangolin.json`)
- Global config: `%ProgramData%\Pangolin\pangolin.json`
Most keys in the `Config` object below can be set in either file. If the same key exists in both places, the user config value overrides the global value. This lets administrators define global defaults while still allowing per-user overrides when needed. Keys marked **Global only** must be set in `%ProgramData%\Pangolin\pangolin.json`; restart the Pangolin manager/UI after changing them.
<ResponseField name="Config" type="object">
JSON configuration for the Windows Pangolin client stored in `pangolin.json`.
<Expandable title="Config">
<ResponseField name="dnsOverride" type="boolean">
When true, matches the **Enable Aliases (Override DNS)** preference and lets the client take over DNS resolution for Pangolin resources.
</ResponseField>
<ResponseField name="dnsTunnel" type="boolean">
When true, matches the **DNS Over Tunnel** preference and sends DNS queries through the Pangolin tunnel.
</ResponseField>
<ResponseField name="primaryDNS" type="string">
Primary upstream DNS server used when override/tunnel DNS is enabled.
</ResponseField>
<ResponseField name="secondaryDNS" type="string">
Optional secondary upstream DNS server used as a fallback when the primary is unavailable.
</ResponseField>
<ResponseField name="dnsMatchDomains" type="array of strings">
Optional whitelist of domains sent to the configured upstream DNS server. When unset, all queries go to upstream DNS. When set, only matching queries use your Upstream DNS Server; all other requests use the system's DNS servers. Supports wildcards such as `*.proxy.internal`.
</ResponseField>
<ResponseField name="defaultServerURL" type="string">
When set, skips the deployment option screen during login; all login flows start directly with this server URL.
</ResponseField>
<ResponseField name="authPath" type="string">
Optional path appended to the server URL for authentication, for example `/auth/org/my-org` to always send users to a specific organization or branded login page. Most deployments should leave this unset.
</ResponseField>
<ResponseField name="userSettingsDisabled" type="boolean">
When true, hides and disables the settings form in the GUI so users cannot change these values themselves.
</ResponseField>
<ResponseField name="openStatusTabOnConnect" type="boolean">
When true, opens the Status tab immediately after clicking Connect so users can watch connection feedback while the tunnel is starting.
</ResponseField>
<ResponseField name="mtu" type="integer">
MTU for the internal WireGuard interface. Changing this is advanced and not recommended unless you have a clear reason; if you set a non-default value, configure the same MTU on every site this client connects to—see [Configure Sites](/manage/sites/configure-site).
</ResponseField>
<ResponseField name="preferLocalRoutes" type="boolean">
When true, prioritizes local routes over remote ones by adding an arbitrary metric to the WireGuard routes. This is useful when you want to ensure that local network traffic (for example, to a printer or NAS) is not routed through the Pangolin tunnel.
</ResponseField>
<ResponseField name="autoUpdateChecksEnabled" type="boolean">
**Global only.** When true, periodically check for updates in the background. When false, automatic checks are off; users can still use **Check for Updates** unless that button is also disabled. If omitted, the default is `true`. Enabling checks surfaces the update UI when a new version exists (tray “Pangolin Update Available” and the update prompt). Intended for org admins / MDM so config is the source of truth.
</ResponseField>
<ResponseField name="updateCheckIntervalSeconds" type="integer">
**Global only.** How often automatic checks run, in seconds. Values below `3600` (1 hour) are clamped to `3600`. Only matters when `autoUpdateChecksEnabled` is true. If omitted, the default is `86400` (24 hours). The client applies a small amount of jitter around this interval.
</ResponseField>
<ResponseField name="checkForUpdatesButtonEnabled" type="boolean">
**Global only.** When true, show **Check for Updates** in the system tray More menu. When false, hide that menu item. If omitted, the default is `true`. Manual checks always perform a live network lookup when the button is used. This is independent of `autoUpdateChecksEnabled`.
</ResponseField>
<ResponseField name="logLevel" type="string">
**Global only.** Controls client log verbosity. Supported values include `debug` and `info`. If omitted, the default is `info`.
</ResponseField>
</Expandable>
</ResponseField>
As a system administrator, you can script placing `pangolin.json` in `%ProgramData%\Pangolin\` to set global defaults, and/or in each user's `%LOCALAPPDATA%\Pangolin\` folder for per-user overrides and targeted rollout behavior.
<Tip>
For enterprise customers, contact us if you need a custom MSI installer with baked-in configuration; we can maintain custom installers as an add-on to your enterprise license.
</Tip>
## Mac Client (Advanced)
On Mac, the Pangolin GUI reads configuration from `~/Library/Application Support/Pangolin/pangolin.json`. Restart Pangolin after editing for changes to apply.
<ResponseField name="Config" type="object">
JSON configuration for the Mac Pangolin client stored in `pangolin.json`.
<Expandable title="Config">
<ResponseField name="dnsOverrideEnabled" type="boolean">
When true, matches the **Enable Aliases (Override DNS)** preference and lets the client take over DNS resolution for Pangolin resources.
</ResponseField>
<ResponseField name="dnsTunnelEnabled" type="boolean">
When true, matches the **DNS Over Tunnel** preference and sends DNS queries through the Pangolin tunnel.
</ResponseField>
<ResponseField name="primaryDNSServer" type="string">
Primary upstream DNS server used when override/tunnel DNS is enabled.
</ResponseField>
<ResponseField name="secondaryDNSServer" type="string">
Optional secondary upstream DNS server used as a fallback when the primary is unavailable.
</ResponseField>
<ResponseField name="dnsMatchDomains" type="array of strings">
Optional whitelist of domains sent to the configured upstream DNS server. When unset, all queries go to upstream DNS. When set, only matching queries use your Upstream DNS Server; all other requests use the system's DNS servers. Supports wildcards such as `*.proxy.internal`.
</ResponseField>
<ResponseField name="tunnelMTU" type="integer">
MTU for the internal WireGuard interface. Changing this is advanced and not recommended unless you have a clear reason; if you set a non-default value, configure the same MTU on every site this client connects to. See [Configure Sites](/manage/sites/configure-site).
</ResponseField>
<ResponseField name="autoUpdateChecksEnabled" type="boolean">
When true, periodically check for updates in the background. When false, automatic checks are off; users can still use **Check for Updates**. If omitted, the client default applies (may prompt the user on second launch). Enabling checks without `autoDownloadUpdatesEnabled` still surfaces the update UI when a new version exists. Intended for admin / MDM provisioning so config stays the source of truth over user toggles.
</ResponseField>
<ResponseField name="autoDownloadUpdatesEnabled" type="boolean">
When true, download updates silently when found and stage install for quit/relaunch. When false, show the normal update dialog instead of silent download. Silent download does not replace the running app mid-session; the update installs on quit (and relaunches), so long-running menu bar sessions may keep a staged update until quit. If omitted, the default is `false`.
</ResponseField>
<ResponseField name="updateCheckIntervalSeconds" type="integer">
How often automatic checks run, in seconds. Values below `3600` (1 hour) are clamped to `3600`. Only matters when `autoUpdateChecksEnabled` is true. If omitted, the default is `86400` (24 hours).
</ResponseField>
</Expandable>
</ResponseField>
## Android Battery Optimization
To ensure Pangolin functions correctly in the background on Android devices, it's recommended to disable battery optimization for the app. This prevents the operating system from restricting its background activities, which could lead to disconnections.
1. Open the **Settings** app on your Android device.
2. Navigate to **Apps & notifications** (or simply **Apps** on some devices).
3. Find and select the Pangolin app from the list of installed apps.
4. Tap on **App battery usage**.
5. Select **Allow background usage** and enable if disabled.
6. From the options menu, choose **Unrestricted**.
<Frame caption="Android Battery Optimization Settings">
<img src="/images/android_battery.png" alt="Android Battery Optimization Settings" style={{width: "250px", height: "auto"}} />
</Frame>
## Pangolin CLI
Refer to the [documentation in the official repository](https://github.com/fosrl/cli/blob/main/docs/pangolin.md) for the available commands, default values, and more.
## Olm (Advanced, Deprecated)
<Accordion title="Olm CLI (advanced use only)">
<Tip>
We recommend using the Pangolin CLI for both user and machine clients if you're looking for a CLI interface. Olm is the underlying client for the Pangolin CLI.
</Tip>
Olm is a command-line client for connecting machine clients in Pangolin. You can configure it using command-line flags, environment variables, or a configuration file. Expand the section below to view all available configuration options.
<Accordion title="CLI Arguments and Options">
### Flags
<ResponseField name="id" type="string" required>
Olm ID generated by Pangolin to identify the client.
**Example**: `31frd0uzbjvp721`
</ResponseField>
<ResponseField name="secret" type="string" required>
A unique secret used to authenticate the client ID with the websocket.
**Example**: `h51mmlknrvrwv8s4r1i210azhumt6isgbpyavxodibx1k2d6`
<Warning>
Keep this secret private and secure. It's used for authentication.
</Warning>
</ResponseField>
<ResponseField name="endpoint" type="string" required>
The endpoint where the Pangolin server resides for websocket connections.
**Example**: `https://pangolin.example.com`
</ResponseField>
<ResponseField name="org" type="string">
Organization ID to connect to.
</ResponseField>
<ResponseField name="user-token" type="string">
User authentication token.
</ResponseField>
<ResponseField name="mtu" type="integer">
MTU for the internal WireGuard interface.
**Default**: `1280`
</ResponseField>
<ResponseField name="dns" type="string">
DNS server to use to resolve the endpoint.
**Default**: `8.8.8.8`
</ResponseField>
<ResponseField name="upstream-dns" type="string">
Upstream DNS server(s), comma-separated.
**Default**: `8.8.8.8:53`
</ResponseField>
<ResponseField name="match-domains-dns" type="string">
FQDN wildcard patterns (using `*` and `?` wildcards, comma-separated, e.g. `*.proxy.internal,*.host-0?.autoco.internal`) to check against local records/upstream DNS. Queries for domains that don't match any pattern are sent directly to the host's own system DNS servers instead of being resolved as Pangolin resources.
**Default**: (empty, matches every domain)
</ResponseField>
<ResponseField name="log-level" type="string">
The log level to use for Olm output.
**Options**: `DEBUG`, `INFO`, `WARN`, `ERROR`, `FATAL`
**Default**: `INFO`
</ResponseField>
<ResponseField name="ping-interval" type="string">
Interval for pinging the server.
**Default**: `3s`
</ResponseField>
<ResponseField name="ping-timeout" type="string">
Timeout for each ping.
**Default**: `5s`
</ResponseField>
<ResponseField name="interface" type="string">
Name of the WireGuard interface.
**Default**: `olm`
</ResponseField>
<ResponseField name="enable-api" type="boolean">
Enable API server for receiving connection requests.
**Default**: `false`
</ResponseField>
<ResponseField name="http-addr" type="string">
HTTP server address (e.g., ':9452'). When unset, the HTTP API is not started and the socket API (see `socket-path`) is used instead.
**Default**: (not set)
</ResponseField>
<ResponseField name="socket-path" type="string">
Unix socket path (or named pipe on Windows).
**Default**: `/var/run/olm.sock` (Linux/macOS) or `olm` (Windows)
</ResponseField>
<ResponseField name="disable-holepunch" type="boolean">
Disable hole punching.
**Default**: `false`
</ResponseField>
<ResponseField name="override-dns" type="boolean">
When enabled, the client uses custom DNS servers to resolve internal resources and aliases. This overrides your system's default DNS settings. Queries that cannot be resolved as a Pangolin resource will be forwarded to your configured Upstream DNS Server.
**Default**: `true`
</ResponseField>
<ResponseField name="tunnel-dns" type="boolean">
When enabled, DNS queries are routed through the tunnel for remote resolution. To ensure queries are tunneled correctly, you must define the DNS server as a Pangolin resource and enter its address as an Upstream DNS Server.
**Default**: `false`
</ResponseField>
<ResponseField name="match-domains-dns" type="string">
Optional comma-separated whitelist of domains sent to the configured upstream DNS server. When unset, all queries go to upstream DNS. When set, only matching queries use your Upstream DNS Server; all other requests use the system's DNS servers. Supports wildcards such as `*.proxy.internal`.
</ResponseField>
<ResponseField name="disable-relay" type="boolean">
Disable relay connections.
**Default**: `false`
</ResponseField>
<ResponseField name="prefer-local-routes" type="boolean">
When true, prioritizes local routes over remote ones by adding an arbitrary metric to the WireGuard routes. This is useful when you want to ensure that local network traffic (for example, to a printer or NAS) is not routed through the Pangolin tunnel.
**Default**: `false`
</ResponseField>
### Environment Variables
All CLI arguments can be set using environment variables as an alternative to command line flags. Environment variables are particularly useful when running Olm in containerized environments.
<Note>
When both environment variables and CLI arguments are provided, CLI arguments take precedence.
</Note>
<ResponseField name="PANGOLIN_ENDPOINT" type="string">
Endpoint of your Pangolin server (equivalent to `--endpoint`)
</ResponseField>
<ResponseField name="OLM_ID" type="string">
Olm ID generated by Pangolin (equivalent to `--id`)
</ResponseField>
<ResponseField name="OLM_SECRET" type="string">
Olm secret for authentication (equivalent to `--secret`)
</ResponseField>
<ResponseField name="ORG" type="string">
Organization ID to connect to (equivalent to `--org`)
</ResponseField>
<ResponseField name="USER_TOKEN" type="string">
User authentication token (equivalent to `--user-token`)
</ResponseField>
<ResponseField name="MTU" type="integer">
MTU for the internal WireGuard interface (equivalent to `--mtu`)
**Default**: `1280`
</ResponseField>
<ResponseField name="DNS" type="string">
DNS server to use to resolve the endpoint (equivalent to `--dns`)
**Default**: `8.8.8.8`
</ResponseField>
<ResponseField name="UPSTREAM_DNS" type="string">
Upstream DNS server(s), comma-separated (equivalent to `--upstream-dns`)
**Default**: `8.8.8.8:53`
</ResponseField>
<ResponseField name="MATCH_DOMAINS_DNS" type="string">
FQDN wildcard patterns, comma-separated (equivalent to `--match-domains-dns`)
**Default**: (empty, matches every domain)
</ResponseField>
<ResponseField name="LOG_LEVEL" type="string">
Log level (equivalent to `--log-level`)
**Default**: `INFO`
</ResponseField>
<ResponseField name="PING_INTERVAL" type="string">
Interval for pinging the server (equivalent to `--ping-interval`)
**Default**: `3s`
</ResponseField>
<ResponseField name="PING_TIMEOUT" type="string">
Timeout for each ping (equivalent to `--ping-timeout`)
**Default**: `5s`
</ResponseField>
<ResponseField name="INTERFACE" type="string">
Name of the WireGuard interface (equivalent to `--interface`)
**Default**: `olm`
</ResponseField>
<ResponseField name="ENABLE_API" type="boolean">
Enable API server for receiving connection requests (equivalent to `--enable-api`)
Set to "true" to enable
**Default**: `false`
</ResponseField>
<ResponseField name="HTTP_ADDR" type="string">
HTTP server address (equivalent to `--http-addr`)
**Default**: (not set)
</ResponseField>
<ResponseField name="SOCKET_PATH" type="string">
Unix socket path or Windows named pipe (equivalent to `--socket-path`)
**Default**: `/var/run/olm.sock` (Linux/macOS) or `olm` (Windows)
</ResponseField>
<ResponseField name="DISABLE_HOLEPUNCH" type="boolean">
Disable hole punching (equivalent to `--disable-holepunch`)
Set to "true" to disable
**Default**: `false`
</ResponseField>
<ResponseField name="OVERRIDE_DNS" type="boolean">
Override system DNS settings (equivalent to `--override-dns`)
Set to "true" to enable
**Default**: `true`
</ResponseField>
<ResponseField name="TUNNEL_DNS" type="boolean">
Route DNS queries through the tunnel (equivalent to `--tunnel-dns`)
Set to "true" to enable
**Default**: `false`
</ResponseField>
<ResponseField name="MATCH_DOMAINS_DNS" type="string">
Optional whitelist of domains sent to the configured upstream DNS server (equivalent to `--match_domains_dns`). When unset, all queries go to upstream DNS.
</ResponseField>
<ResponseField name="PREFER_LOCAL_ROUTES" type="boolean">
When true, prioritizes local routes over remote ones by adding an arbitrary metric to the WireGuard routes. This is useful when you want to ensure that local network traffic (for example, to a printer or NAS) is not routed through the Pangolin tunnel.
**Default**: `false`
</ResponseField>
<ResponseField name="DISABLE_RELAY" type="boolean">
Disable relay connections (equivalent to `--disable-relay`)
Set to "true" to disable
**Default**: `false`
</ResponseField>
<ResponseField name="CONFIG_FILE" type="string">
Set to the location of a JSON file to load secret values
</ResponseField>
### Loading secrets from files
You can use `CONFIG_FILE` to define a location of a config file to store the credentials between runs.
```
$ cat ~/.config/olm-client/config.json
{
"id": "spmzu8rbpzj1qq6",
"secret": "f6v61mjutwme2kkydbw3fjo227zl60a2tsf5psw9r25hgae3",
"endpoint": "https://app.pangolin.net",
"org": "",
"userToken": "",
"mtu": 1280,
"dns": "8.8.8.8",
"upstreamDNS": ["8.8.8.8:53"],
"matchDomainsDNS": [],
"interface": "olm",
"logLevel": "INFO",
"enableApi": false,
"httpAddr": "",
"socketPath": "/var/run/olm.sock",
"pingInterval": "3s",
"pingTimeout": "5s",
"disableHolepunch": false,
"overrideDNS": true,
"tunnelDNS": false,
"disableRelay": false,
"tlsClientCert": "",
"preferLocalRoutes": false
}
```
This file is also written to when olm first starts up. So you do not need to run every time with --id and secret if you have run it once!
Default locations:
- **macOS**: `~/Library/Application Support/olm-client/config.json`
- **Windows**: `%PROGRAMDATA%\olm\olm-client\config.json`
- **Linux/Others**: `~/.config/olm-client/config.json`
### API
Olm can be started with a HTTP or socket API to configure and manage it. See the [API documentation](https://github.com/fosrl/olm/blob/main/API.md) for more details.
</Accordion>
</Accordion>
@@ -0,0 +1,51 @@
---
title: "Client Credentials"
description: "Understanding how client credentials work and how they can be rotated & regenerated"
---
## Understanding Credentials
Every machine client is provisioned with a unique identifier (ID), secret, and endpoint. The client uses the combination of these three to establish a secure, encrypted connection to the server.
User devices use a special combination of credentials and temporary session tokens tied to the user account. Therefore, these credentials are obscured and can not be regenerated for user devices. To invalidate a user device, the user should logout via the client of choice.
### ID
Example: `ln8yqs6w85la5zg`
The ID represents the client connection in the system. Every machine client has an ID.
This value is not a secret and it is okay if made publically available.
### Secret
Example: `tfpwoc580jf1l1glfagix0o97p8kirjogdflqg604n0tr3to`
The secret represents the "password" of the client. This secret must match the secret hashed in the system for the relevant ID.
<Note>
This is a _secret_! Only share it with trusted people and be sure to store it safely and securely.
</Note>
When the client connects, it uses this secret as a first handshake with the server. The server then passes temporary session credentials back to the site before it can initiate a websocket connection. Once the websocket connection is established, ephemeral keys are used to establish tunnels using WireGuard.
### Endpoint
Example: `https://app.pangolin.net` or `https://pangolin.my-server.com`
The endpoint is how the client knows which server to connect to. This is the fully qualified hostname of the Pangolin server (the URL you use to access the dashboard). For Pangolin cloud, the endpoint is `https://app.pangolin.net`. The client uses this endpoint ot establish a websocket connection and receive control messages from the server.
## Rotating and Regenerating Credentials
<Note>
This is an [Enterprise Edition](/self-host/enterprise-edition)-only feature.
</Note>
Client credentials can be regenerated. Regenerating credentials will completely invalidate the previous ID and secret. Use this feature if you have lost the secret and need to reset the credentials, or if you wish to rotate credentials on a regular basis for extra security.
To regenerate credentials, visit Clients > Machines > Your Client > Credentials in the Pangolin admin dashboard.
### Regenerate vs. Regenerate and Disconnect
Regenerate simply recreates the credentials and invalidates the old ones. The client will remain connected until you restart it with the new credentials.
Regenerate and Disconnect recreates the credentials and invalides the old ones. The client will instantly disconnect and will require you to restart it with the new credentials.
@@ -0,0 +1,77 @@
---
title: 'Client Fingerprinting'
description:
'A summary of device information that is collected during the connection'
---
## Device Fingerprinting
Pangolin clients collect device fingerprinting information and can perform
security posture checks to help determine trusted devices. This information is
used to enforce security policies, audit device configurations, and monitor
compliance with organizational requirements. Snapshots of device information are
collected periodically on each platform when clients are connected.
## Collected Fingerprint Information
The following device attributes are collected on each device when available:
- Username
- Hostname
- OS version
- Kernel version
- Architecture
- Device model
- Serial number
## Available Posture Checks
<Note>
Posture checks are only collected on [Pangolin Cloud](https://app.pangolin.net/auth/signup) and self-hosted [Enterprise Edition](/self-host/enterprise-edition).
</Note>
Posture checks are also collected on each platform; this is device state that
could potentially change, such as biometric availability, firewall settings, and
other related information if it is available.
Posture checks are supported on a per-platform basis.
### Windows
| Posture Check | What It Reports |
| --------------------- | ----------------------------------------------------------------- |
| Hard drive encryption | Whether the system disk and other disks are encrypted (BitLocker) |
| Firewall | If the firewall (Windows or third party) is enabled |
| Antivirus | If antivirus (Windows or third party) is installed and active |
| TPM availability | If a Trusted Platform Module is available |
### macOS
| Posture Check | What It Reports |
| --------------------------------- | ---------------------------------------- |
| Hard drive encryption | Whether the system disk is encrypted |
| Biometric configuration | If Touch ID or Face ID is configured |
| Firewall | If the macOS firewall is enabled |
| System Integrity Protection (SIP) | Whether SIP is active |
| Gatekeeper | Whether Gatekeeper is active |
| Firewall stealth mode | Whether firewall stealth mode is enabled |
| Auto updates | If automatic updates are enabled |
### Linux
| Posture Check | What It Reports |
| --------------------- | ------------------------------------------------ |
| Hard drive encryption | If LUKS devices are detected on the system |
| Firewall | Whether UFW, firewalld, or iptables are enabled |
| AppArmor | If AppArmor is active |
| SELinux | If SELinux is active |
| TPM availability | If a Trusted Platform Module device is available |
### iOS
No posture checks are currently supported on iOS.
### Android
| Posture Check | What It Reports |
| --------------------- | --------------------------------------- |
| Hard drive encryption | If File-Based Encryption is enabled |
+133
View File
@@ -0,0 +1,133 @@
---
title: "Firewall Quirks"
description: "Improve Pangolin direct-connect success behind restrictive firewalls"
---
Most of the time, Pangolin works with existing firewall policies without any special tuning. Pangolin Sites and Pangolin Clients attempt NAT traversal first so traffic can flow directly between client and site. When direct connectivity cannot be established, traffic falls back to relaying through Gerbil. You can [learn more about how holepunching works here](https://pangolin.net/news/nat-holepunching).
For background on direct vs relayed paths and how to verify connection type, see [NAT Traversal](/manage/clients/nat-traversal).
## Firewall compatibility and workarounds
The table below summarizes common behavior and practical mitigations reported by users.
| Firewall platform | Typical behavior with Pangolin | Practical workaround |
| --- | --- | --- |
| Barracuda | Often relayed | Increase available UDP session capacity; optionally allow a dedicated inbound Pangolin Site port |
| Check Point | Usually direct | No workaround typically required |
| Cisco | Often relayed | Allow required UDP flows and, if needed, open a fixed Pangolin Site listening port |
| Cisco Umbrella Endpoint Security | Usually relayed | Endpoint filtering commonly prevents direct paths |
| Fortinet | Often connects directly | No workaround typically required |
| OPNsense | Often relayed by default | Disable hard NAT |
| pfSense | Often relayed by default | Disable hard NAT |
| Palo Alto Networks | Mixed; may relay without NAT tuning | Use persistent NAT behavior to stabilize UDP mappings |
| Sophos | Commonly direct | No workaround typically required |
| UniFi Gateways (threat detection on) | Often relayed when threat detection is on | Allow peer-to-peer traffic categories |
If your firewall is not listed and connections are consistently relayed, start with:
1. Confirm current path with `pangolin status` (CLI) or client status JSON (`isRelay`).
2. Keep relaying enabled for reliability while testing firewall adjustments.
3. If needed, pin the Pangolin Site to a fixed listening port with `--port` / `PORT` and forward that port to the Pangolin Site host.
## Platform notes
### Barracuda
Barracuda environments commonly struggle with simultaneous UDP flows from multiple clients, which can push connections to relay mode.
What helps:
- Increase the firewall's maximum UDP session capacity [by increasing the max udp parameter](https://campus.barracuda.com/product/cloudgenfirewall/doc/95258827/general-firewall-configuration/?sl=AX5zwzvyOBUvMAhoTe4U&so=2)
- If direct connectivity is still inconsistent, use a fixed Pangolin Site listening port and forward it explicitly.
### Check Point
Check Point deployments generally allow Pangolin direct connectivity without extra configuration.
### Cisco
Cisco firewalls often require additional policy tuning before direct paths become stable.
#### Cisco Umbrella Endpoint Security
When Cisco Umbrella Endpoint Security is in-path, direct peer connectivity is frequently blocked and relay becomes the normal outcome.
### Fortinet
Fortinet environments are often stable for smaller deployments but may shift heavily to relay as concurrent client count grows.
### pfSense
pfSense frequently land in relay mode unless inbound UDP mapping behavior is made explicit. Try the following changes:
By default, pfSense software rewrites the source port on all outgoing connections to enhance security and prevent direct exposure of internal port numbers.
Static port mapping in pfSense involves creating a fixed association between a specific external port number and an internal IP address and port, allowing incoming traffic to be directed to the correct destination within the local network.
Locate the Firewall > NAT, Outbound tab. Select Hybrid Outbound NAT rule generation. Select Save. Select ↑ Add to create a new NAT rule to the top of the list.
Configure the rule: IPv4+IPv6, for Protocol UDP, source address Any. Check Static Port in the Translation section of the page.
Select Save. Select Apply Changes.
### OPNsense
OPNsense frequently land in relay mode unless inbound UDP mapping behavior is made explicit. Try the following changes:
By default, OPNsense software rewrites the source port on all outgoing connections to enhance security and prevent direct exposure of internal port numbers.
Static port mapping in OPNsense involves creating a fixed association between a specific external port number and an internal IP address and port, allowing incoming traffic to be directed to the correct destination within the local network.
Go to Firewall > NAT, Outbound tab. Select Hybrid Outbound NAT rule generation. Select Save. Select ↑ Add to create a new NAT rule to the top of the list.
Configure the rule to match UDP traffic. Note, for each rule, select the appropriate Address Family (IP version), IPv4 for one and IPv6 for the other.
Here is the Markdown table based on the image provided:
| Interface | Source | Source Port | Destination | Destination Port | NAT Address | NAT Port | Static Port | Description |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| WAN | LAN net | udp/ * | * | udp/ * | Interface address | * | YES | Pangolin IPv4 |
| WAN | LAN net | udp/ * | * | udp/ * | Interface address | * | YES | Pangolin IPv6 |
Check Static Port in the Translation section of the page. Select Save. Select Apply Changes.
### Palo Alto Networks
Palo Alto deployments can improve direct path reliability by using persistent NAT translation behavior (dynamic IP and port persistence) so UDP mappings do not churn between destinations. [Take a look at the documentation here](https://docs.paloaltonetworks.com/pan-os/10-1/pan-os-new-features/networking-features/persistent-nat-for-dipp).
PAN-OS 11.1.x and later: Persistent Dynamic IP and Port
Ensure stability and performance by referring to the list of preferred releases for PAN-OS.
PAN-OS 11.1.1 contains the translation type for NAT policies, Persistent Dynamic IP and Port. In this translation type, once a client has sent a packet with a particular source port, the same NAT translated port number will be used for all destinations. This lets Tailscale to predict the port number and establish a direct connection.
To use this translation type, go to NAT Policy Rule, select the Translated Packet tab, then select the Translation Type option Persistent Dynamic IP and Port.
Earlier PAN-OS releases: Static IP
With older PAN-OS releases and the Dynamic IP and Port translation type, every UDP stream will translate to a random UDP port. Opening a specific port will not allow traffic through, and Tailscale cannot predict what port number to try for a direct connection.
With older PAN-OS releases it is possible to use the Static IP NAT Policy to enable one device within the protected zone to make direct connections. One might choose a subnet router or other high-traffic node to optimize. In the PAN-OS software create a NAT policy rule with Translation Type set to Static IP, instead of the default setting Dynamic IP And Port. This helps Tailscale figure out how to get packets through the NAT and establish direct connections.
### Sophos
Sophos gateways usually work well with Pangolin's direct-connect flow under default NAT behavior.
If relay usage rises unexpectedly, verify no extra IPS/inspection rule set is rewriting UDP sessions.
### UniFi Gateways
On UniFi networks with threat detection enabled, peer-to-peer categories can interfere with hole punching.
In UniFi Network version 9.0.107 and earlier, select to Settings, Firewall & Security, Edit threat categories, and uncheck P2P.
In UniFi Network version 9.0.108 and later, select to Network, Security, Protection, Peer to Peer and Dark Web, and uncheck P2P.
## Verify improvements
After each firewall change, validate results from a client:
1. Reconnect the site/client pair.
2. Run `pangolin status` (or check JSON status in GUI clients).
3. Confirm `RELAY=false` / `isRelay: false` for sessions expected to be direct.
If direct paths still fail, keep relay enabled and continue iterating with narrower firewall adjustments rather than broad allow-all rules.
@@ -0,0 +1,460 @@
---
title: "Install Clients"
description: "Install native clients for Mac, Windows, and Linux"
---
## Windows
- [Pangolin for Windows Installer](https://pangolin.net/downloads/windows) - This is the official page to download the latest installer file for Windows.
- [All Versions](https://github.com/fosrl/windows/releases) - The releases section of this repository contains release notes and download artifacts for the latest version and all older versions.
### Installation Steps
1. **Download and install the Pangolin client**
Download and install the Pangolin client using the official .msi installer from the download button above.
2. **Launch Pangolin**
Open Pangolin from the Start menu or the shortcut on your Desktop.
3. **Log in with your Pangolin account**
Log in on your Pangolin Cloud account or your self-hosted Pangolin instance.
- Click the Pangolin icon in the task bar's system tray and select Log in.
## Mac
- [Pangolin for macOS Installer](https://pangolin.net/downloads/mac) - This is the official page to download the latest installer file for macOS.
- [All Versions](https://github.com/fosrl/apple/releases) - The releases section of this repository contains release notes and download artifacts for the latest version and all older versions.
### Installation Steps
1. **Download and install the Pangolin client**
Download and install the Pangolin client using the official .dmg installer from the download button above.
- Open the downloaded .dmg file
- Drag and drop Pangolin.app into your Applications folder
2. **Launch Pangolin**
Open Pangolin from your Applications folder.
3. **Install the VPN configuration**
Follow the Pangolin onboarding flow, which will guide you to install the Pangolin VPN configuration.
- Select Open System Settings on startup when it asks to install a network extension.
- In System Settings, under General > Login Items & Extension > By Category > Network Extensions, ensure that Pangolin.app is toggled on.
- Select Allow when Pangolin asks to add a VPN configuration.
4. **Log in with your Pangolin account**
Log in on your Pangolin Cloud account or your self-hosted Pangolin instance.
- Click the Pangolin icon in the menu bar and select Log in.
## iOS/iPadOS
- [Pangolin on the App Store](https://apps.apple.com/us/app/pangolin-client/id6757407406) - This is the official page to download the latest Pangolin app for iOS and iPadOS.
### Installation Steps
1. **Download and install the Pangolin app**
Download and install the Pangolin app from the App Store using the link above.
2. **Launch Pangolin**
Open the Pangolin app from your home screen.
3. **Install the VPN configuration**
When prompted, allow Pangolin to add VPN configurations to your device.
You may be asked to enter your device passcode or use Face ID/Touch ID to authorize the VPN configuration.
4. **Log in with your Pangolin account**
Log in on your Pangolin Cloud account or your self-hosted Pangolin instance.
5. **Connect to Pangolin**
Tap the Connect button to establish a VPN connection.
## Android
- [Pangolin on Google Play](https://play.google.com/store/apps/details?id=net.pangolin.Pangolin) - This is the official page to download the latest Pangolin app for Android devices.
- [All Versions](https://github.com/fosrl/android/releases) - The releases section of this repository contains release notes and download artifacts for the latest version and all older versions.
### Installation Steps
1. **Download and install the Pangolin app**
Download and install the Pangolin app from the Google Play Store using the link above.
2. **Launch Pangolin**
Open the Pangolin app from your app drawer or home screen.
3. **Log in with your Pangolin account**
Log in on your Pangolin Cloud account or your self-hosted Pangolin instance.
4. **Connect to Pangolin**
Tap the Connect button to establish a VPN connection. On the first connection, you may be prompted to allow the VPN connection.
## Pangolin CLI (Linux, macOS, Windows)
Pangolin CLI is the recommended way to run a client using a command line interface on Mac and Linux.
Pangolin CLI can run on Windows, but the CLI VPN functionality is not supported. You can still use Pangolin CLI on Windows for SSH alongside the Windows GUI client.
Pangolin CLI supports running as user device with authentication or a machine client.
### Install
Use this command to automatically install Pangolin CLI. It detects your system architecture automatically and always pulls the latest version, adding `pangolin` to your PATH:
```bash
curl -fsSL https://static.pangolin.net/get-cli.sh | bash
```
On Windows, [download the latest installer](https://github.com/fosrl/cli/releases/latest/download/pangolin-cli_windows_installer.msi), or choose to install the CLI from menu bar of the desktop app by choosing the "Install Pangolin CLI" option.
Binaries for all platforms are available in the [GitHub releases](https://github.com/fosrl/cli/releases) for ARM and AMD64 (x86_64) architectures.
### Installation Steps
1. **Download and install the Pangolin client**
Install Pangolin using the installation script:
```bash
curl -fsSL https://static.pangolin.net/get-cli.sh | bash
```
2. **Log in with your Pangolin account**
Log in on your Pangolin Cloud account or your self-hosted Pangolin instance:
```bash
pangolin login
```
3. **Start Pangolin**
When logged in as a Pangolin user, connect by running:
```bash
pangolin up
```
To launch a machine client without logging in, use your client credentials:
```bash
pangolin up --id {client_id} --secret {client_secret} --endpoint {endpoint_url} --attach
```
<Tip>
The `--attach` flag runs the client in the foreground instead of spawning it as a background process.
</Tip>
Pangolin CLI can be installed as a systemd service or run in a container. See the sections below for advanced setups.
## Machine Clients
Machine clients don't require a login and are built for machines like services to be able to connect to private resources. Like sites, they have an ID and a secret.
### Run as a Service
The CLI can install and manage a service on your host machine for you. This supports Windows services, MacOS's launchd, and Linux's systemd to create a persistent site connection from that host.
```bash
sudo pangolin service install client \
--id 31frd0uzbjvp721 \
--secret h51mmlknrvrwv8s4r1i210azhumt6isgbpyavxodibx1k2d6 \
--endpoint https://app.pangolin.net
```
Check the service status:
```bash
sudo pangolin service status client
```
And to get the logs:
```bash
sudo pangolin service logs client
```
### Systemd Service (Pangolin CLI)
Create a basic systemd service for Pangolin CLI:
```ini title="/etc/systemd/system/pangolin-cli.service"
[Unit]
Description=Pangolin CLI
After=network.target
[Service]
ExecStart=/usr/local/bin/pangolin up --id {client_id} --secret {client_secret} --endpoint {endpoint_url} --attach
Restart=always
User=root
[Install]
WantedBy=multi-user.target
```
<Warning>
Make sure to move the binary to `/usr/local/bin/pangolin` before creating the service. Replace `{client_id}`, `{client_secret}`, and `{endpoint_url}` with your machine client credentials and endpoint.
</Warning>
### Docker (Pangolin CLI)
You can run Pangolin CLI with Docker Compose. For example, a service in your `docker-compose.yml` might look like this using environment variables (recommended):
```yaml
services:
pangolin-cli:
image: fosrl/pangolin-cli:latest
container_name: pangolin-cli
restart: unless-stopped
network_mode: host
cap_add:
- NET_ADMIN
devices:
- /dev/net/tun:/dev/net/tun
environment:
- PANGOLIN_ENDPOINT=https://app.pangolin.net
- CLIENT_ID=5n52gnzfgl3tdox
- CLIENT_SECRET=wyael1dhftekp0ii2ni0ym6xczwjnwmucy2vr6u9kgkp8tw9
```
You can also pass the CLI args to the container:
```yaml
services:
pangolin-cli:
image: fosrl/pangolin-cli:latest
container_name: pangolin-cli
restart: unless-stopped
network_mode: host
cap_add:
- NET_ADMIN
devices:
- /dev/net/tun:/dev/net/tun
command:
- up
- --id
- "5n52gnzfgl3tdox"
- --secret
- "wyael1dhftekp0ii2ni0ym6xczwjnwmucy2vr6u9kgkp8tw9"
- --endpoint
- https://app.pangolin.net
- --attach
```
**Docker Configuration Notes:**
- `network_mode: host` brings the Pangolin CLI network interface to the host system, allowing the WireGuard tunnel to function properly
- `cap_add: - NET_ADMIN` is required to grant the container permission to manage network interfaces
- `devices: - /dev/net/tun:/dev/net/tun` is required to give the container access to the TUN device for creating WireGuard interfaces
<Note>
Deploying in Kubernetes? See [Kubernetes Deployment](/manage/clients/kubernetes/deployment) for a basic guide, including how to run the client as a sidecar container.
</Note>
## Olm (Advanced)
<Accordion title="Olm CLI (advanced use only)">
Olm CLI is the most basic form of a client. All other clients implement Olm under the hood in some form.
If you're looking for a CLI interface for a client, we recommend using Pangolin CLI where possible.
Olm CLI is mainly only used for machine clients. Though the Pangolin CLI can also be used for machine clients, use Pangolin CLI if you expect to log in as a user.
### Binary Installation (Linux)
#### Quick Install (Recommended)
Use this command to automatically install Olm. It detects your system architecture automatically and always pulls the latest version, adding Olm to your PATH:
```bash
curl -fsSL https://static.pangolin.net/get-olm.sh | bash
```
#### Windows
If you would like to use Olm on Windows, wintun.dll is required. Please use latest installer from [GitHub releases](https://github.com/fosrl/olm/releases/latest).
#### Manual Download
Binaries for Linux, macOS, and Windows are available in the [GitHub releases](https://github.com/fosrl/olm/releases) for ARM and AMD64 (x86_64) architectures.
Download and install manually:
```bash
wget -O olm "https://github.com/fosrl/olm/releases/download/{version}/olm_{architecture}" && chmod +x ./olm
```
<Note>
Replace `{version}` with the desired version and `{architecture}` with your architecture. Check the [release notes](https://github.com/fosrl/olm/releases) for the latest information.
</Note>
### Running Olm
Run Olm with the configuration from Pangolin:
```bash
olm \
--id 31frd0uzbjvp721 \
--secret h51mmlknrvrwv8s4r1i210azhumt6isgbpyavxodibx1k2d6 \
--endpoint https://example.com
```
### Systemd Service
Create a basic systemd service:
```ini title="/etc/systemd/system/olm.service"
[Unit]
Description=Olm
After=network.target
[Service]
ExecStart=/usr/local/bin/olm --id 31frd0uzbjvp721 --secret h51mmlknrvrwv8s4r1i210azhumt6isgbpyavxodibx1k2d6 --endpoint https://example.com
Restart=always
User=root
[Install]
WantedBy=multi-user.target
```
<Warning>
Make sure to move the binary to `/usr/local/bin/olm` before creating the service!
</Warning>
### Docker
You can also run it with Docker compose. For example, a service in your `docker-compose.yml` might look like this using environment vars (recommended):
```yaml
services:
olm:
image: fosrl/olm
container_name: olm
restart: unless-stopped
network_mode: host
cap_add:
- NET_ADMIN
devices:
- /dev/net/tun:/dev/net/tun
environment:
- PANGOLIN_ENDPOINT=https://example.com
- OLM_ID=31frd0uzbjvp721
- OLM_SECRET=h51mmlknrvrwv8s4r1i210azhumt6isgbpyavxodibx1k2d6
```
You can also pass the CLI args to the container:
```yaml
services:
olm:
image: fosrl/olm
container_name: olm
restart: unless-stopped
network_mode: host
cap_add:
- NET_ADMIN
devices:
- /dev/net/tun:/dev/net/tun
command:
- --id 31frd0uzbjvp721
- --secret h51mmlknrvrwv8s4r1i210azhumt6isgbpyavxodibx1k2d6
- --endpoint https://example.com
```
**Docker Configuration Notes:**
- `network_mode: host` brings the olm network interface to the host system, allowing the WireGuard tunnel to function properly
- `cap_add: - NET_ADMIN` is required to grant the container permission to manage network interfaces
- `devices: - /dev/net/tun:/dev/net/tun` is required to give the container access to the TUN device for creating WireGuard interfaces
### Windows Service
On Windows, olm has to be installed and run as a Windows service. When running it with the cli args, it will attempt to install and run the service to function like a cli tool.
Minimum Windows version: Windows 10
#### Service Management Commands
```
# Install the service
olm.exe install
# Start the service
olm.exe start
# Stop the service
olm.exe stop
# Check service status
olm.exe status
# Remove the service
olm.exe remove
# Run in debug mode (console output) with our without id & secret
olm.exe debug
# Show help
olm.exe help
```
Note running the service requires credentials in `%PROGRAMDATA%\olm\olm-client\config.json`.
#### Service Configuration
When running as a service, Olm will read configuration from environment variables or you can modify the service to include command-line arguments:
1. Install the service: `olm.exe install`
2. Set the credentials in `%PROGRAMDATA%\olm\olm-client\config.json`. Hint: if you run olm once with --id and --secret this file will be populated!
3. Start the service: `olm.exe start`
#### Service Logs
When running as a service, logs are written to:
- Windows Event Log (Application log, source: "OlmWireguardService")
- Log files in: `%PROGRAMDATA%\olm\logs\olm.log`
You can view the Windows Event Log using Event Viewer or PowerShell:
```powershell
Get-EventLog -LogName Application -Source "OlmWireguardService" -Newest 10
```
### Gotchas
Olm creates a native tun interface. This usually requires sudo / admin permissions. Some notes:
- **Windows**: Olm will run as a service. You can use the commands described [Configure Client](/manage/clients/configure-client) to manage it. You can use this to run it in the background if needed!
- **LXC containers**: Need to be configured to allow tun access. On Proxmox see below.
- **Linux**: May require root privileges or specific capabilities to create tun interfaces.
- **macOS**: May require additional permissions for network interface creation.
#### LXC Proxmox
1. Create your LXC container.
2. Go to the Resources tab of the container.
3. Select Add. Then select Device Passthrough.
4. On the Add Device prompt, enter dev/net/tun in the Device Path field and select Add.
5. If the container is running, shut it down and start it up again.
Once /dev/net/tun is available, the olm can run within the LXC.
</Accordion>
@@ -0,0 +1,126 @@
---
title: "Deployment"
description: "Basic guide for running a Pangolin client in Kubernetes as a sidecar."
---
This page covers a basic way to run a Pangolin client inside Kubernetes: as a sidecar container that gives a Pod access to your Pangolin resources over the tunnel.
<Note>
This is a minimal example, not a production chart. There is no official Helm chart for the client at this time — adapt the manifests below to your own deployment, Kustomize overlays, or GitOps workflow.
</Note>
## Why a sidecar
Containers in the same Pod share a network namespace. Running Pangolin CLI (or Olm) as a sidecar container brings up the WireGuard tunnel inside that shared namespace, so every other container in the Pod can reach your Pangolin resources as if they were on the tunnel directly — no `hostNetwork` required.
This is useful when a workload running in your cluster (a batch job, an internal service, a CI runner) needs to reach private resources behind Pangolin.
## Prerequisites
- A machine client created in Pangolin, with its `Client ID` and `Client Secret`. See [Install Clients](/manage/clients/install-client).
- A Kubernetes cluster where you can grant the `NET_ADMIN` capability and access to `/dev/net/tun`.
## Step 1: Create a Secret for client credentials
```bash
kubectl create secret generic pangolin-client \
--namespace default \
--from-literal=CLIENT_ID=<client-id> \
--from-literal=CLIENT_SECRET=<client-secret>
```
<Warning>
Do not commit plaintext credentials to Git. For GitOps workflows, use an encrypted or external secret backend such as SOPS, Sealed Secrets, External Secrets Operator, Vault, or Infisical.
</Warning>
## Step 2: Add the sidecar container
Add a `pangolin-cli` container alongside your application container in the Pod spec. It needs the `NET_ADMIN` capability and access to the host's `/dev/net/tun` device to create the WireGuard interface.
```yaml
apiVersion: v1
kind: Pod
metadata:
name: my-app
labels:
app: my-app
spec:
containers:
- name: my-app
image: my-app-image:latest
# This container can reach Pangolin resources through
# the tunnel brought up by the pangolin-cli sidecar below.
- name: pangolin-cli
image: fosrl/pangolin-cli:latest
restartPolicy: Always
envFrom:
- secretRef:
name: pangolin-client
env:
- name: PANGOLIN_ENDPOINT
value: "https://pangolin.example.com"
securityContext:
capabilities:
add: ["NET_ADMIN"]
volumeMounts:
- name: tun
mountPath: /dev/net/tun
volumes:
- name: tun
hostPath:
path: /dev/net/tun
```
<Note>
Setting `restartPolicy: Always` on the container makes it a [native sidecar](https://kubernetes.io/docs/concepts/workloads/pods/sidecar-containers/) on Kubernetes 1.29+. It starts before the main container and Kubernetes keeps it running for the life of the Pod. On older clusters, omit `restartPolicy` and the container runs as a regular container instead — the tunnel still comes up, but startup ordering isn't guaranteed.
</Note>
The `pangolin-cli` image runs `pangolin up --attach` by default, which launches the client as a machine client using the `CLIENT_ID`/`CLIENT_SECRET` from the Secret and keeps it in the foreground so the container stays alive. See [Install Clients](/manage/clients/install-client#pangolin-cli-linux-macos-windows) for the full list of environment variables and flags.
## Step 3: Apply and verify
```bash
kubectl apply -f pod.yaml
```
Check that both containers are running:
```bash
kubectl get pod my-app
```
Check the tunnel came up in the sidecar's logs:
```bash
kubectl logs my-app -c pangolin-cli
```
In the Pangolin dashboard, verify the client shows as connected. Then, from inside the `my-app` container, confirm you can reach a private resource:
```bash
kubectl exec my-app -c my-app -- curl -s http://internal-resource.example
```
## Deployments and other workload types
The same sidecar pattern applies to a `Deployment`, `StatefulSet`, `Job`, or `CronJob` — add the `pangolin-cli` container to `spec.template.spec.containers` (or `initContainers` with `restartPolicy: Always` for native sidecar behavior) the same way as shown above.
<Warning>
Each Pod running the sidecar connects as the same machine client. If you scale a Deployment to multiple replicas, every replica's sidecar authenticates with the same `CLIENT_ID`/`CLIENT_SECRET` and appears as one client in Pangolin. If you need to distinguish traffic per replica, create a separate machine client and Secret for each one.
</Warning>
## Next steps
<CardGroup cols={2}>
<Card title="Install Clients" href="/manage/clients/install-client" icon="download">
Review Pangolin CLI and Olm installation options, including Docker.
</Card>
<Card title="Configure Clients" href="/manage/clients/configure-client" icon="sliders">
Review client configuration options.
</Card>
<Card title="Credentials" href="/manage/clients/credentials" icon="key">
Manage machine client credentials.
</Card>
</CardGroup>
@@ -0,0 +1,150 @@
---
title: "NAT Traversal"
description: "How clients connect on the same network, hole punch through NAT, or relay through Pangolin"
---
When a client connects to a site, Pangolin tries to establish the most direct path possible. If the client and site are on the same local network, they form a direct peer-to-peer connection on that network. Otherwise, the client attempts NAT hole punching before falling back to relaying.
## Same Network Detection
When a client and site share the same local network, they detect this and connect peer-to-peer over the LAN. Packets stay on the local network and are not routed out through the internet or your Pangolin server. The connection does not use the relay path when both peers are on the same network.
Same-network connections typically offer the lowest latency because traffic never leaves the LAN.
The site collects IP addresses from the host's network interfaces and uses them to send UDP test packets to the client. If the site runs inside a Docker container, it only sees the container's internal network, so run it on the host itself to ensure it can detect the host's real IP addresses. This detection also works across VLANs. If a client and site are on different VLANs but routing between them is configured correctly, the connection should still succeed.
## NAT Hole Punching
NAT hole punching establishes a direct peer-to-peer connection between the client and site, bypassing the need to route traffic through the Pangolin server. The server coordinates the initial connection by helping both peers discover each other's network addresses, allowing them to establish a direct tunnel through their respective NATs and firewalls.
For a deeper look at how Pangolin coordinates hole punching between clients and sites, see [NAT Hole Punching in Pangolin](https://pangolin.net/news/nat-holepunching).
Direct connections typically offer:
- Better performance (speed and bandwidth)
- Lower VPS transit costs when you self-host
## Relaying
If the site and client are unable to hole punch, they fall back to relaying through your Pangolin server.
Clients can relay traffic through a Pangolin server, through the Gerbil service specifically. Gerbil listens on UDP port 21820 for new WireGuard connections and forwards the packets down the site tunnels to the right peers. This means your connections back to your site do not require firewall config and uses the existing NAT hole punching capabilities of the site.
Relaying is reliable when direct paths are blocked by NAT or firewall rules, but traffic passes through your Pangolin node instead of traveling directly between the client and site.
<Note>
If you use [Pangolin Cloud](https://app.pangolin.net/auth/signup) and want relayed traffic to stay on infrastructure you control, [self-host a remote node](/manage/remote-node/understanding-nodes). Relayed client traffic then traverses your node rather than Pangolin's shared cloud infrastructure.
</Note>
## Check Whether a Site Is Relayed
You can confirm whether a connection is direct or relayed from the client.
### GUI clients
In a GUI client (Mac, Windows, Android, or iOS/iPadOS), open **Preferences**, go to the **Status** tab, and switch to the **JSON** view. Under each connected site in the `peers` object, check `isRelay` and `isLocal`:
- `isRelay: false` — direct hole-punched connection to the site
- `isRelay: true` — traffic is relayed through your Pangolin server
- `isLocal: true` — the site is on the same local network as the client
- `isLocal: false` — the site is on a different network
Example (values obfuscated):
```json
{
"agent": "Pangolin macOS",
"connected": true,
"orgId": "org_example123",
"peers": {
"1001": {
"connected": true,
"endpoint": "203.0.113.10:51820",
"isRelay": false,
"isLocal": true,
"name": "Office Network",
"siteId": 1001
},
"1002": {
"connected": true,
"endpoint": "198.51.100.5:21820",
"isRelay": true,
"isLocal": false,
"name": "Remote Lab",
"siteId": 1002
}
},
"registered": true,
"version": "0.8.4"
}
```
In this example, **Office Network** is connected directly (`isRelay: false`) and **Remote Lab** is relayed (`isRelay: true`).
### CLI
On Linux or when using [Pangolin CLI](/manage/clients/install-client), run `pangolin status`. The **CONNECTION** column shows whether each site is connected directly (`Direct`) or via relay (`Relay`):
```bash
pangolin status
AGENT VERSION STATUS ORG
Pangolin CLI 0.10.1 Connected org_example123
SITE ENDPOINT STATUS LAST SEEN CONNECTION
Office Network 203.0.113.10:51820 Connected 1s ago Direct
Remote Lab 198.51.100.5:21820 Connected 1s ago Relay
Worklab Lab 192.168.1.33:23423 Connected 1s ago Local
```
Use either view when troubleshooting hole punching or verifying that configuration changes took effect.
## Improve Hole Punching Reliability
Pangolin Sites support NAT traversal so clients can connect directly without relaying through the Pangolin server, improving performance and reducing latency.
In some environments, depending on the NAT type and firewall, you may need to tweak settings to get optimal connectivity in the firewall itself. See [Firewall Integrations](/manage/clients/firewalls) for Pangolin-specific guidance for common platforms.
Another option is to keep the Pangolin Site listening for client connections on a static port. This allows you to open a specific port in your firewall for Pangolin Site client connections instead of random high ports. You can do this by setting the `--port` flag or `PORT` environment variable and then opening this port in your firewall to DNAT to the Pangolin Site. See [Configure Sites](/manage/sites/configure-site) for the full list of Pangolin Site flags and environment variables.
## FAQ
<AccordionGroup>
<Accordion title="What happens when the client and site are on the same network?">
The client and site detect that they share a local network and form a direct peer-to-peer connection on the LAN. Packets are not routed out of the network, and the connection does not use the relay path.
</Accordion>
<Accordion title="Why is my connection relayed instead of direct?">
Hole punching can fail when either side sits behind a restrictive NAT, symmetric NAT, or a firewall that blocks the UDP ports needed for peer discovery. When that happens, the client and site fall back to relaying through your Pangolin server so the tunnel still comes up reliably.
</Accordion>
<Accordion title="How do I check whether a site is relayed?">
**GUI clients:** Open **Preferences**, go to the **Status** tab, and switch to the **JSON** view. Each entry under `peers` includes an `isRelay` field—`false` for direct, `true` when relayed.
**CLI:** Run `pangolin status` and check the **RELAY** column for each site.
See [Check Whether a Site Is Relayed](#check-whether-a-site-is-relayed) for examples.
</Accordion>
<Accordion title="Is relayed traffic still encrypted?">
Yes. Whether the path is direct or relayed, client-to-site traffic is encrypted over WireGuard. Relaying changes the network path, not the encryption of the tunnel itself.
</Accordion>
<Accordion title="Will relaying affect performance?">
Direct hole-punched connections usually offer lower latency and higher throughput because traffic does not pass through your Pangolin node. Relayed connections add an extra hop through Gerbil, which can increase latency and bandwidth use on the node—especially relevant if you self-host and pay for transit.
</Accordion>
<Accordion title="Can I force direct connections only?">
You can disable relaying with `disable-relay` in the client config or `--disable-relay` / `DISABLE_RELAY=true` on CLI clients. If hole punching fails, the client will not fall back to a relay and the site may not connect. See [Configure Clients](/manage/clients/configure-client) for details.
</Accordion>
<Accordion title="Can I always relay and skip hole punching?">
Yes. Set `disable-holepunch` in the client config or use `--disable-holepunch` / `DISABLE_HOLEPUNCH=true` on CLI clients to skip hole punching and connect through the relay path. See [Configure Clients](/manage/clients/configure-client) for details.
</Accordion>
<Accordion title="Does relayed traffic go through Pangolin Cloud?">
On self-hosted Pangolin, relayed traffic passes through your own Gerbil instance. On [Pangolin Cloud](https://app.pangolin.net/auth/signup), relayed traffic may traverse Pangolin's shared infrastructure unless you [self-host a remote node](/manage/remote-node/understanding-nodes), in which case relayed client traffic uses your node instead.
</Accordion>
<Accordion title="Do I need to open firewall ports for hole punching?">
Not always. Many networks hole punch successfully without inbound rules. If punching is unreliable, try [Firewall Integrations](/manage/clients/firewalls) guidance or pin the Pangolin Site to a static port with `--port` / `PORT` and DNAT that port to the Pangolin Site host.
</Accordion>
</AccordionGroup>
@@ -0,0 +1,57 @@
---
title: "Understanding Clients"
description: "Create a client to connect to your Pangolin network from a remote computer"
---
A client is a way to access resources on sites remotely and privately via a virtual private network. Clients are used with private resources to faciliate zero-trust network access.
By default a client does not have access to any hosts on the local network of the site. Admins must explicitly define resources on the site and give specific users and roles access to the resources.
Users must log in and connect from a Pangolin client available on [Windows, Mac, Linux, iOS/iPadOS, and Android](/manage/clients/install-client). Machines (automated systems and servers) connect with an ID and secret.
## Client Types
There are two types of clients: user devices and machines.
<CardGroup cols={2}>
<Card title="User Devices">
- Associated with a user in your Pangolin organization
- Requires login to connect (password, 2fa, etc)
- Available for download on Mac, Windows, and Linux
</Card>
<Card title="Machines">
- Represent a server or automated system instead of a user
- Connect with an ID and secret
- Available in CLI form with Pangolin CLI
</Card>
</CardGroup>
### User Devices
A user may download a client for their specific system. Before they can connect, they must select a Pangolin server to authenticate to using their provided Pangolin account. Users can log in as a Pangolin user or with your attached external identity provider.
Examples include:
- **SSH**: Admins and developers can connect with their client to specific hosts for SSH.
- **RDP**: Users can connect to a remote host using familiar remote desktop software.
Then, just like in the Pangolin dashboard, a user selects the organization to connect to. Once connected, all resources made available to the user in that organization become available via the tunnel.
### Machines
Machine clients are for servers and automated systems that are not associated with a specific user.
Examples include:
- **CICD**: Access remote resources like a database in an automated deployment pipeline.
- **Servers**: Provide a VPS with access to a resource running in a different network.
Though you may connect a server via a user account using a CLI client, we recommend you specifically use a machine client.
Machine clients authenticate with an ID and secret string. These credentials are passed via arguments into one of the supported Pangolin CLI clients. They can be revoked and rotated.
## Client Modalities
Clients connect to sites using NAT hole punching or relaying. A client first attempts a direct peer-to-peer tunnel, then falls back to relaying through your Pangolin server if hole punching fails.
See [NAT Traversal](/manage/clients/nat-traversal) for how each modality works, how to check whether a site is relayed, and tips for improving hole punching reliability.
@@ -0,0 +1,48 @@
---
title: "Update Clients"
description: "Update your installed client to the latest version"
---
## Mac and Windows
### Automatic Updates (Recommended)
The desktop clients for Mac and Windows will periodically check for updates in the background. When an update is available, they will request permission to update. However, you can manually check for updates in the menu bar or system tray menu, or by restarting the application.
Once you accept the update, these clients will automatically download the latest version and replace itself on your computer.
### Manual Updates
- **Mac**: Find the latest version in the [GitHub releases](https://github.com/fosrl/apple/releases).
- **Windows**: Find the latest version in the [GitHub releases](https://github.com/fosrl/windows/releases).
You can download the latest installer files and restart the installation process to install the latest version. Visit [https://pangolin.net/downloads](https://pangolin.net/downloads) to find the latest official installers for your platform.
## Pangolin CLI
Find the latest version in the [GitHub releases](https://github.com/fosrl/cli/releases).
### Automatic Updates (Recommended)
If you already have Pangolin CLI installed, use the update command:
```bash
pangolin update
```
Or you can re-run the installation script:
```bash
curl -fsSL https://static.pangolin.net/get-cli.sh | bash
```
### Manual Updates
Download the latest binary for your system from [GitHub releases](https://github.com/fosrl/cli/releases) and replace your existing binary.
```bash
wget -O pangolin "https://github.com/fosrl/cli/releases/download/{version}/pangolin-cli_{architecture}" && chmod +x ./pangolin
```
<Note>
Replace `{version}` with the desired version and `{architecture}` with your architecture. Check the [release notes](https://github.com/fosrl/cli/releases) for the latest information.
</Note>