Merge branch 'dev'

This commit is contained in:
miloschwartz
2026-09-30 14:20:13 -04:00
59 changed files with 2269 additions and 1481 deletions
+1 -1
View File
@@ -3,7 +3,7 @@
"version": "1.0.0",
"private": true,
"scripts": {
"dev": "next dev -H 127.0.0.1 -p 3005",
"dev": "next dev -H 127.0.0.1 -p 4005",
"build": "next build",
"start": "next start -H 127.0.0.1 -p 3005",
"types:check": "next typegen && tsc --noEmit"
+14
View File
@@ -559,6 +559,20 @@ figure.shiki .line.highlighted {
margin-bottom: 0;
}
/* The callout sits inside .not-prose, which disables typography's link/bold styles. */
.pg-callout-body a {
color: var(--color-fd-primary);
font-weight: 500;
text-decoration: underline;
text-underline-offset: 2px;
}
.pg-callout-body a:hover {
opacity: 0.8;
}
.pg-callout-body strong {
font-weight: 600;
}
/* ---------- cards ---------- */
.pg-card-group {
display: grid;
+4
View File
@@ -189,6 +189,10 @@ const icons: Record<string, IconComponent> = {
slack: SlackIcon,
linkedin: LinkedInIcon,
youtube: YouTubeIcon,
windows: WindowsIcon,
apple: AppleIcon,
android: AndroidIcon,
linux: LinuxIcon,
};
export function Icon({ name, ...props }: { name?: string } & SVGProps<SVGSVGElement>) {
+4 -4
View File
@@ -84,7 +84,7 @@ The access model stays the same while the protocol changes.
<img src="/images/public-resources.png" alt="Manage Public Resources page in the Pangolin dashboard"/>
</Frame>
[Private resources](/manage/resources/understanding-resources#private-resource-types) require a [Pangolin client](/manage/clients/install-client) connection and stay off the public internet. They are for VPN-like, fully private access to resources on your remote network.
[Private resources](/manage/resources/understanding-resources#private-resource-types) require a [Pangolin client](/manage/clients/platforms) connection and stay off the public internet. They are for VPN-like, fully private access to resources on your remote network.
<Frame caption="Private resources in the dashboard: hosts, HTTP, SSH, and CIDR ranges with destinations and aliases.">
<img src="/images/private-resources.png" alt="Manage Private Resources page in the Pangolin dashboard"/>
@@ -138,13 +138,13 @@ Roles group people for RBAC. You assign roles on each resource, so access follow
Clients are software components installed on user devices or machines. They let users and automated systems connect directly to sites to access [private resources](/manage/resources/understanding-resources#private-resource-types) through a secure tunnel. Clients also enforce access control and security at the edge.
Users authenticate through the client using their [accounts](/manage/access-control/create-user). [Machines](/manage/clients/credentials) connect with credentials. Once connected, users can reach all resources their account has access to. The client handles [routing](/manage/clients/nat-traversal) decisions and establishes encrypted tunnels to the appropriate [sites](/manage/sites/understanding-sites).
Users authenticate through the client with their [user credentials](/manage/access-control/create-user) in a web login flow. [Machines](/manage/clients/credentials) connect with machine client credentials. Once connected, users can reach all resources their account has access to. The client handles [routing](/manage/clients/nat-traversal) decisions and establishes encrypted tunnels to the appropriate [sites](/manage/sites/understanding-sites).
<Frame caption="User devices in the dashboard, with identity provider, connection status, and client version.">
<img src="/images/user-devices.png" alt="User Devices page in the Pangolin dashboard"/>
</Frame>
Clients are available on [all major platforms](/manage/clients/install-client). They work transparently with applications, so no application configuration is required.
Clients are available on [all major platforms](/manage/clients/platforms). They work transparently with applications, so no application configuration is required.
<Card title="Download Pangolin clients" icon="download" href="https://pangolin.net/downloads" arrow="true">
Get the client for Mac, Windows, Linux, iOS, and Android.
@@ -170,7 +170,7 @@ Access is identity-based. You grant users and roles on the resource the same way
<img src="/images/ai/expanded-session-logs.png" alt="AI Gateway session logs in the Pangolin dashboard"/>
</Frame>
A [private AI Gateway](/manage/resources/private/ai-gateway) uses the [Pangolin client](/manage/clients/install-client) the same way every other private resource does. The client running on the end user's device already authenticated that user. Coding agents on that device call the resource over the tunnel, and Pangolin attributes the request to the connected identity. That eliminates provider API keys on the laptop: the upstream key stays on the [provider](/manage/ai/providers/overview).
A [private AI Gateway](/manage/resources/private/ai-gateway) uses the [Pangolin client](/manage/clients/platforms) the same way every other private resource does. The client running on the end user's device already authenticated that user. Coding agents on that device call the resource over the tunnel, and Pangolin attributes the request to the connected identity. That eliminates provider API keys on the laptop: the upstream key stays on the [provider](/manage/ai/providers/overview).
<Card title="Read more about AI Gateway" icon="sparkles" href="/manage/ai/overview">
Set up providers, resources, and identity-based access for coding agents and AI clients.
@@ -7,7 +7,7 @@ You can run Pangolin as [Pangolin Cloud](https://app.pangolin.net/auth/signup) o
## Pangolin Cloud
Cloud is the managed control plane. You create an account, install [sites](/manage/sites/install-site) and [clients](/manage/clients/install-client), and define resources. Pangolin runs the dashboard, database, certificates, and globally distributed nodes.
Cloud is the managed control plane. You create an account, install [sites](/manage/sites/install-site) and [clients](/manage/clients/platforms), and define resources. Pangolin runs the dashboard, database, certificates, and globally distributed nodes.
Use Cloud when you want high availability, automatic updates, and less operational work. You can still keep traffic on infrastructure you control with [remote nodes](/manage/remote-node/understanding-nodes).
@@ -25,7 +25,7 @@ That is the justification in Pangolin terms: an identity-aware gateway, not only
**[Bifrost](https://www.getmaxim.ai/bifrost)** is a dedicated LLM gateway focused on complex routing rules, failover, and performance. For example, you can use it to route requests to different models based on the user's location or the request's content. You can also run it downstream of Pangolin as a [Custom provider](/manage/ai/providers/custom/bifrost) when Pangolin should authenticate callers and Bifrost should pick models.
**Pangolin** provides the same gateway job as a [protocol-aware resource](/about/how-pangolin-works#ai-gateway). Providers, model lists, [virtual API keys](/manage/ai/virtual-api-keys) on public resources, budgets, and session logs are all there. Identity comes from Pangolin users, roles, and (for private AI gateway resources) the [desktop client](/manage/clients/install-client). Site and client tunnels are how you reach self-hosted models and how you keep provider keys off laptops.
**Pangolin** provides the same gateway job as a [protocol-aware resource](/about/how-pangolin-works#ai-gateway). Providers, model lists, [virtual API keys](/manage/ai/virtual-api-keys) on public resources, budgets, and session logs are all there. Identity comes from Pangolin users, roles, and (for private AI gateway resources) the [desktop client](/manage/clients/platforms). Site and client tunnels are how you reach self-hosted models and how you keep provider keys off laptops.
## Identity-Aware Gateway
@@ -33,7 +33,7 @@ Access follows the resource. You grant [users and roles](/manage/access-control/
On a [public AI Gateway](/manage/resources/public/ai-gateway), coding agents send a [virtual API key](/manage/ai/virtual-api-keys). Pangolin identity keys identify the user; you grant the user or role, not the key.
On a [private AI Gateway](/manage/resources/private/ai-gateway), the [Pangolin client](/manage/clients/install-client) running on the end user's device already authenticated that user. Coding agents on that device call over the tunnel fully privately. Pangolin attributes the request to the connected identity. That eliminates provider API keys on the laptop: the upstream key never leaves the provider.
On a [private AI Gateway](/manage/resources/private/ai-gateway), the [Pangolin client](/manage/clients/platforms) running on the end user's device already authenticated that user. Coding agents on that device call over the tunnel fully privately. Pangolin attributes the request to the connected identity. That eliminates provider API keys on the laptop: the upstream key never leaves the provider.
## Virtual API Keys
+1 -1
View File
@@ -195,7 +195,7 @@ Then choose your database:
</Step>
</Steps>
## Exit Nodes
## Gerbil Registration
When running Pangolin for the first time there will be no exit nodes. This means that there have been no Gerbil "exit nodes" registered in the database, and therefore, you cannot create Newt sites. When Gerbil first starts up and requests its config from Pangolin for the first time it gets registered as an exit node.
@@ -97,7 +97,7 @@ How Olm is hosted depends on the client:
- **Pangolin CLI** — spawns Olm as a subprocess and manages it over a local API
- **Olm CLI** — exposes Olm directly for minimal machine-client deployments
Olm is an internal building block, not a product surface. Use the [native clients](/manage/clients/install-client) built for each operating system for the best experience, support, and integration with OS networking APIs. Direct Olm usage is limited to advanced machine-client and automation scenarios; see [Olm (Advanced)](/manage/clients/install-client#olm-advanced) if you need that path.
Olm is an internal building block, not a product surface. Use the [native clients](/manage/clients/platforms) built for each operating system for the best experience, support, and integration with OS networking APIs. Direct Olm usage is limited to advanced machine-client and automation scenarios; see [Olm](/manage/clients/platforms/olm) if you need that path.
Once connected, the client installs routes for each authorized destination. Pangolin selects the correct site connector automatically; users connect to resources, not to sites directly. See [multi-site routing](/manage/resources/private/multi-site-routing) for how failover works when a resource spans multiple connectors.
@@ -106,8 +106,8 @@ Once connected, the client installs routes for each authorized destination. Pang
User devices, machine clients, and how access is granted.
</Card>
<Card title="Install clients" icon="download" href="/manage/clients/install-client">
Downloads for Mac, Windows, Linux, iOS, iPadOS, and Android.
<Card title="Platforms" icon="download" href="/manage/clients/platforms">
Install, configure, and update clients for Mac, Windows, Linux, iOS, iPadOS, and Android.
</Card>
</CardGroup>
@@ -59,6 +59,6 @@ These authentication methods do not provide user identity information:
- A public resource called with an [identity key](/manage/ai/virtual-api-keys#identity-keys)
- A public resource called with a [manual key](/manage/ai/virtual-api-keys#manual-keys) attributed to a user
- A private AI Gateway resource called from a connected [Pangolin client](/manage/clients/install-client)
- A private AI Gateway resource called from a connected [Pangolin client](/manage/clients/platforms)
An unattributed manual key authenticates without sending these headers. Details are in [Identity Headers](/manage/ai/providers/configuration#identity-headers).
@@ -12,7 +12,7 @@ You'll need the resource's URL (its `<endpoint>`) and its API key (`<key>`). Bot
## Fastest: Pangolin CLI
[Install the Pangolin CLI](/manage/clients/install-client#quick-install-recommended) if you don't have it, then log in:
[Install the Pangolin CLI](/manage/clients/platforms/cli#install) if you don't have it, then log in:
```bash
pangolin login
@@ -12,7 +12,7 @@ You'll need the resource's URL (its `<endpoint>`) and its API key (`<key>`). Bot
## Fastest: Pangolin CLI
[Install the Pangolin CLI](/manage/clients/install-client#quick-install-recommended) if you don't have it, then log in:
[Install the Pangolin CLI](/manage/clients/platforms/cli#install) if you don't have it, then log in:
```bash
pangolin login
@@ -12,7 +12,7 @@ You'll need the resource's URL (its `<endpoint>`) and its API key (`<key>`). Bot
## Fastest: Pangolin CLI
[Install the Pangolin CLI](/manage/clients/install-client#quick-install-recommended) if you don't have it, then log in:
[Install the Pangolin CLI](/manage/clients/platforms/cli#install) if you don't have it, then log in:
```bash
pangolin login
@@ -12,7 +12,7 @@ You'll need the resource's URL (its `<endpoint>`) and its API key (`<key>`). Bot
## Fastest: Pangolin CLI
[Install the Pangolin CLI](/manage/clients/install-client#quick-install-recommended) if you don't have it, then log in:
[Install the Pangolin CLI](/manage/clients/platforms/cli#install) if you don't have it, then log in:
```bash
pangolin login
+1 -1
View File
@@ -37,7 +37,7 @@ How a client authenticates depends on whether the resource is public or private.
### Private Resources
Reachable only on devices connected with the [Pangolin client](/manage/clients/install-client). Identity comes from that connection, so you do not issue a [virtual API key](/manage/ai/virtual-api-keys). The desktop client already proved who is calling. Details are on the [private AI Gateway](/manage/resources/private/ai-gateway) resource page.
Reachable only on devices connected with the [Pangolin client](/manage/clients/platforms). Identity comes from that connection, so you do not issue a [virtual API key](/manage/ai/virtual-api-keys). The desktop client already proved who is calling. Details are on the [private AI Gateway](/manage/resources/private/ai-gateway) resource page.
### Public Resources
@@ -86,7 +86,7 @@ The user is known when:
- A public resource is called with an [identity key](/manage/ai/virtual-api-keys#identity-keys)
- A public resource is called with a [manual key](/manage/ai/virtual-api-keys#manual-keys) attributed to a user
- A private AI Gateway resource is called from a connected [Pangolin client](/manage/clients/install-client), and that client maps to a user
- A private AI Gateway resource is called from a connected [Pangolin client](/manage/clients/platforms), and that client maps to a user
An unattributed manual key still authenticates, but these headers are omitted. Empty values are omitted rather than sent blank.
+1 -1
View File
@@ -23,7 +23,7 @@ Logging into Pangolin in a browser is how you **retrieve** a key. Model calls st
## Public Resources Only
Virtual keys apply to **public** AI Gateway resources. [Private resources](/manage/resources/understanding-resources) are reached through the [Pangolin client](/manage/clients/install-client), so the gateway does not check a key. Clients still need a placeholder in the key field; use the literal string `none`. Deleting the field usually breaks the client.
Virtual keys apply to **public** AI Gateway resources. [Private resources](/manage/resources/understanding-resources) are reached through the [Pangolin client](/manage/clients/platforms), so the gateway does not check a key. Clients still need a placeholder in the key field; use the literal string `none`. Deleting the field usually breaks the client.
## Authentication Is Always On
+29 -5
View File
@@ -20,7 +20,7 @@ Some features in this documentation are marked with **(EE)**, which means they r
A blueprint can contain up to four top-level sections:
- **`public-resources`**: Internet-facing HTTP, TCP, UDP, SSH, RDP, or VNC resources
- **`private-resources`**: Client-only access to hosts or CIDR ranges
- **`private-resources`**: Client-only access to hosts, CIDR ranges, or an exit node
- **`public-policies`**: Reusable authentication and access policy objects
- **`sites`**: Site-level settings such as container label discovery
@@ -360,6 +360,7 @@ Private resources define what Pangolin clients can reach after they connect to y
- Use **`mode: http`** to expose an internal HTTP endpoint to clients via a private domain
- Use **`mode: ssh`** for SSH access workflows (including native auth-daemon mode)
- Use **`mode: inference`** for a private [AI Gateway](/manage/ai/overview) resource reachable only by Pangolin clients, not the public internet
- Use **`mode: exit-node`** to send all of a client's internet traffic out through the site network
<Note>
When applying a blueprint from a site (using `--blueprint-file` or container labels), `sites` is optional. If omitted, the resource is assigned to the site that applied the blueprint.
@@ -398,6 +399,27 @@ private-resources:
- Member
```
### Exit Node Example
Set `mode: exit-node` to turn a site into an exit node. Clients with access to the resource route all of their internet traffic through the site network, so it egresses from the site instead of the client's local connection.
```yaml
private-resources:
office-exit:
name: Office Exit Node
mode: exit-node
sites:
- office-site
roles:
- Developer
users:
- user@example.com
```
- `destination` is not needed. An exit node always routes the full range (`0.0.0.0/0`), and any `destination` you set is ignored.
- All TCP and UDP ports and ICMP are always allowed. `tcp-ports`, `udp-ports`, and `disable-icmp` are ignored.
- `gateway` is accepted as an equivalent value for `mode`.
## Resource Labels
Attach labels to public and private resources to organize and filter them in the dashboard. These are the same labels manageable from **Settings > Labels** - not to be confused with the [Docker container labels](#container-labels-format) used to define blueprints from Compose.
@@ -1365,13 +1387,14 @@ private-resources:
<ResponseField name="mode" type="string" required>
Private resource type.
**Options**: `host`, `cidr`, `http`, `ssh`, `inference`
**Options**: `host`, `cidr`, `http`, `ssh`, `inference`, `exit-node`
- `host`: A single host or IP. If `destination` is a domain, `alias` is required.
- `cidr`: An entire IPv4 or IPv6 CIDR range.
- `http`: An internal HTTP endpoint exposed to clients via `full-domain`.
- `ssh`: SSH access resource. `destination` may be omitted only when `auth-daemon.mode` is `native` (or when `auth-daemon` is omitted).
- `inference`: A private [AI Gateway](/manage/ai/overview) exposed to clients via `full-domain`, proxying to attached `ai-providers` instead of a `destination`.
- `exit-node`: Sends all of a client's internet traffic out through the site network. Does not take a `destination`; all ports and ICMP are always allowed. `gateway` is accepted as an alias.
YAML: `mode: cidr`
Container label: `pangolin.private-resources.internal-net.mode=cidr`
@@ -1401,6 +1424,7 @@ private-resources:
- `http`: a host or IP for the upstream HTTP endpoint
- `ssh`: optional only for `auth-daemon.mode: native`; required otherwise
- `inference`: not used; the resource proxies to `ai-providers` instead
- `exit-node`: not used; always routes `0.0.0.0/0`
YAML: `destination: 10.0.0.0/24`
Container label: `pangolin.private-resources.internal-net.destination=10.0.0.0/24`
@@ -1671,7 +1695,7 @@ public-policies:
4. When mode/protocol is `tcp` or `udp`, the resource must have `proxy-port`, targets must not include `method`, and `auth` is not allowed.
5. `proxy-protocol` and `proxy-protocol-version` are only valid when mode/protocol is `tcp`.
6. If `auth-daemon.mode` is `remote`, `auth-daemon.port` is required.
7. In private resources, `destination` is required unless `mode: ssh` with native auth-daemon mode, or `mode: inference`.
7. In private resources, `destination` is required unless `mode: ssh` with native auth-daemon mode, `mode: inference`, or `mode: exit-node`.
8. `full-domain` values must be unique across public resources.
9. `proxy-port` values must be unique per protocol within `public-resources`. TCP `3000` and UDP `3000` can coexist, but two TCP resources cannot both use `3000`.
10. `alias` values must be unique across private resources in the blueprint.
@@ -1712,9 +1736,9 @@ Only TCP public resources can define proxy protocol behavior.
Set `auth-daemon.port` whenever `auth-daemon.mode: remote` is used.
### "destination is required unless mode is 'ssh' with auth-daemon mode 'native'"
### "destination is required unless mode is 'ssh' with auth-daemon mode 'native', 'inference', or 'gateway'"
For private SSH resources, `destination` can be omitted only for native auth-daemon mode.
Private resources need a `destination` except for SSH resources using native auth-daemon mode, `inference` resources, and `exit-node` (`gateway`) resources.
### "Resource must either be targets-only or have both 'name' and 'protocol' fields"
+1 -1
View File
@@ -52,7 +52,7 @@ sudo pangolin up --attach
## Android
View logs within the app under **Preferences > Logs**.
Turn on **Enable Log Collection** under **Preferences**. Tunnel logs are then saved to a file you can download from the app. You can also view logs under **Preferences > Logs**. See [Android](/manage/clients/platforms/android).
## iOS
@@ -1,543 +0,0 @@
---
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>
+5 -5
View File
@@ -1,12 +1,12 @@
---
title: "Client Credentials"
description: "Understanding how client credentials work and how they can be rotated & regenerated"
title: "Machine Client Credentials"
description: "How machine clients authenticate with an ID and secret, and how to rotate or regenerate those credentials"
---
## 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.
Machine client credentials are only for [machine clients](/manage/clients/understanding-clients#machines): servers and automated systems that connect without a person present. Each machine client is provisioned with a unique identifier (ID), secret, and endpoint. The client uses those three values 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.
User devices do not use machine client credentials. A person logs in with their Pangolin user credentials, or with an external identity provider, through the web login flow in the client. That login creates a session tied to their account. The session is not shown in the dashboard and cannot be regenerated. To disconnect a user device, have the user log out in the client.
### ID
@@ -40,7 +40,7 @@ The endpoint is how the client knows which server to connect to. This is the ful
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.
Machine 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.
@@ -1,5 +1,5 @@
---
title: 'Client Fingerprinting'
title: 'Client Fingerprinting and Posture'
description:
'A summary of device information that is collected during the connection'
---
@@ -1,460 +0,0 @@
---
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>
@@ -17,10 +17,10 @@ This is useful when a workload running in your cluster (a batch job, an internal
## Prerequisites
- A machine client created in Pangolin, with its `Client ID` and `Client Secret`. See [Install Clients](/manage/clients/install-client).
- A machine client created in Pangolin, with its `Client ID` and `Client Secret`. See [Pangolin CLI](/manage/clients/platforms/cli#machine-clients).
- 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
## Step 1: Create a Secret for machine client credentials
```bash
kubectl create secret generic pangolin-client \
@@ -77,7 +77,7 @@ spec:
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.
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 [Pangolin CLI](/manage/clients/platforms/cli#docker-pangolin-cli) for the environment variables and flags.
## Step 3: Apply and verify
@@ -114,13 +114,13 @@ Each Pod running the sidecar connects as the same machine client. If you scale a
## 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 title="Pangolin CLI" href="/manage/clients/platforms/cli" icon="terminal">
Install, configure, and run the CLI, including Docker.
</Card>
<Card title="Configure Clients" href="/manage/clients/configure-client" icon="sliders">
Review client configuration options.
<Card title="Platforms" href="/manage/clients/platforms" icon="sliders">
Shared client preferences for DNS and routing.
</Card>
<Card title="Credentials" href="/manage/clients/credentials" icon="key">
Manage machine client credentials.
<Card title="Machine Client Credentials" href="/manage/clients/credentials" icon="key">
Rotate and regenerate the ID and secret used by a machine client.
</Card>
</CardGroup>
+16 -43
View File
@@ -37,52 +37,25 @@ If you use [Pangolin Cloud](https://app.pangolin.net/auth/signup) and want relay
## Check Whether a Site Is Relayed
You can confirm whether a connection is direct or relayed from the client.
You can confirm whether a connection is direct or relayed from the client. GUI clients and the CLI both report a connection value:
- `Direct`: hole-punched connection to the site
- `Relay`: traffic is relayed through your Pangolin server
- `Local`: the site is on the same local network as 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`:
In a GUI client (Mac, Windows, Android, or iOS/iPadOS), open **Preferences** and go to the **Status** tab. The formatted view lists each site and its status. Click a site to open its details and read **Connection**.
- `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
<Frame caption="Site details from the Status tab. Connection is Relay for this site.">
<img src="/images/client-site-status.png" alt="Site details for Prod VPC Bastion us-east-1 showing Status Connected and Connection Relay" />
</Frame>
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`).
In this example, **Prod VPC Bastion us-east-1** is connected through the relay.
### 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`):
On Linux or when using [Pangolin CLI](/manage/clients/platforms/cli), run `pangolin status`. The **CONNECTION** column shows the same value for each site:
```bash
pangolin status
@@ -92,7 +65,7 @@ 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
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.
@@ -117,9 +90,9 @@ Another option is to keep the Pangolin Site listening for client connections on
</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.
**GUI clients:** Open **Preferences**, go to the **Status** tab, and click a site. **Connection** is `Relay` when the site is relayed, and `Direct` or `Local` when the path is direct.
**CLI:** Run `pangolin status` and check the **RELAY** column for each site.
**CLI:** Run `pangolin status` and check the **CONNECTION** column for each site.
See [Check Whether a Site Is Relayed](#check-whether-a-site-is-relayed) for examples.
</Accordion>
@@ -133,11 +106,11 @@ Another option is to keep the Pangolin Site listening for client connections on
</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.
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 [Olm](/manage/clients/platforms/olm) 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.
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 [Olm](/manage/clients/platforms/olm) for details.
</Accordion>
<Accordion title="Does relayed traffic go through Pangolin Cloud?">
@@ -0,0 +1,66 @@
---
title: "Android"
description: "Install, configure, and update the Pangolin app for Android"
---
## Install
- [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.
## Configure
<Note>
DNS, MTU, and other preferences shared across clients are on [Platforms](/manage/clients/platforms#shared-preferences).
</Note>
### Show Persistent VPN Notification
When enabled, Pangolin keeps a status notification while connected. A temporary notification may still appear when connecting or recovering. Android's own VPN indicators are unaffected.
Leaving this on makes it less likely that Android will stop the connection while the app is in the background.
### Enable Log Collection
When enabled, tunnel logs are saved to a file that can be downloaded for troubleshooting. See [Client Logs](/manage/clients/client-logs).
### 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>
## Update
Updates are delivered through the Google Play Store. Release notes and older builds are in the [GitHub releases](https://github.com/fosrl/android/releases).
@@ -0,0 +1,331 @@
---
title: "Pangolin CLI"
description: "Install, configure, and update Pangolin CLI on Linux, macOS, and 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. With [companion mode](#companion-mode), connect in the Windows app and use the CLI for commands such as SSH, on the same account, without a second login.
Pangolin CLI supports running as a user device with authentication or a machine client.
The CLI stores its own defaults in a config file.
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.
## 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>
### 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>
## Companion Mode
Companion mode lets Pangolin CLI use the [Windows desktop app](/manage/clients/platforms/windows#companion-mode) for authentication and the tunnel. Log in and connect in the desktop app, then run CLI commands as that same account. You do not run `pangolin login` separately.
Companion mode is available on Windows only, and it requires Pangolin for Windows 0.11.0 or later. On macOS and Linux the CLI keeps its own login, and `pangolin companion` is not available. On Windows, companion mode is on by default.
### SSH through the desktop connection
1. Log in and connect with the Windows client.
2. SSH to a [private SSH resource](/manage/resources/private/ssh):
```bash
pangolin ssh username@alias
```
The CLI uses the desktop app's session and the tunnel that app already opened. `pangolin scp` works the same way.
### Commands
Enable companion mode. This takes effect on the next `pangolin` command:
```bash
pangolin companion enable
```
Turn it off and go back to a standalone CLI login:
```bash
pangolin companion disable
```
Check whether the desktop app session is ready:
```bash
pangolin companion status
```
When the desktop app is logged in, status looks like this:
```text
Companion mode: enabled
Client: Pangolin Windows
Ready: yes
```
If the desktop app is not logged in, status reports `Ready: no` and tells you to open Pangolin and log in.
With companion mode off, status reports:
```text
Companion mode: disabled
Auth source: standalone CLI
```
### What stays in the desktop app
While companion mode is on, the CLI reads accounts, the active organization, and exit node selection from the desktop app. Change those in the app.
These commands are blocked. The CLI tells you to use the desktop app, or to run `pangolin companion disable`:
- `pangolin login`
- `pangolin logout`
- `pangolin select account`
- `pangolin select org`
- `pangolin select exit-node`
Other commands, including `pangolin ssh` and `pangolin scp`, run with the desktop app's session. The desktop app has to be open and logged in. If it is not, the CLI asks you to start Pangolin for Windows 0.11.0 or later and log in.
You can also set `disable_companion_mode` in the [CLI config file](#config-file). `true` matches `pangolin companion disable`.
## Configure
<Note>
DNS, MTU, and other preferences shared across clients are on [Platforms](/manage/clients/platforms#shared-preferences).
</Note>
### Config File
The Pangolin CLI stores persistent settings in `~/.config/pangolin/config.json` on every platform. When the CLI is run with `sudo`, it uses the home directory of the user who invoked `sudo`, so the same file applies with and without it. Run `pangolin config path` to print the exact location.
<ResponseField name="Config" type="object">
JSON configuration for the Pangolin CLI stored in `config.json`.
<Expandable title="Config">
<ResponseField name="log_level" type="string">
Controls CLI log verbosity. Supported values are `debug` and `info`. If omitted, the default is `info`.
</ResponseField>
<ResponseField name="log_file" type="string">
Path of the client log file. If omitted, the default is `~/.config/pangolin/logs/client.log`. This key can only be changed by editing the file; it is not available through `pangolin config set`.
</ResponseField>
<ResponseField name="disable_update_check" type="boolean">
When true, the CLI does not check for new versions. If omitted, the default is `false`, except in builds distributed through a package manager, where it is `true`.
</ResponseField>
<ResponseField name="disable_companion_mode" type="boolean">
When true, the CLI uses its own standalone authentication instead of [companion mode](#companion-mode), where login, accounts, organizations, and exit node selection are managed by the Pangolin desktop app. If omitted, the default is `false`, so companion mode is on. This only applies on Windows.
</ResponseField>
<ResponseField name="companion_app_data_dirs" type="object">
Overrides where the CLI looks for the desktop app's data directory in companion mode. Accepts a `windows` and a `darwin` path. Most installations should leave this unset. This key can only be changed by editing the file.
</ResponseField>
<ResponseField name="session_cookie_name" type="string">
Overrides the cookie name used for the CLI's session token. Most deployments should leave this unset.
</ResponseField>
<ResponseField name="up.override_dns" type="boolean">
Default for `--override-dns`. When true, matches the [Enable Aliases (Override DNS)](/manage/clients/platforms#enable-aliases-override-dns) preference and lets the client take over DNS resolution for Pangolin resources. If omitted, the default is `true`.
</ResponseField>
<ResponseField name="up.tunnel_dns" type="boolean">
Default for `--tunnel-dns`. When true, matches the [DNS Over Tunnel](/manage/clients/platforms#dns-over-tunnel) preference and sends DNS queries through the Pangolin tunnel. If omitted, the default is `false`.
</ResponseField>
<ResponseField name="up.upstream_dns" type="array of strings">
Default for `--upstream-dns`. Upstream DNS servers used when override/tunnel DNS is enabled. With `pangolin config set`, pass a comma-separated list such as `10.0.0.53,10.0.0.54`.
</ResponseField>
<ResponseField name="up.match_domains_dns" type="array of strings">
Default for `--match-domains`. 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`. With `pangolin config set`, pass a comma-separated list.
</ResponseField>
<ResponseField name="up.prefer_local_routes" type="boolean">
Default for `--prefer-local-routes`. 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. If omitted, the default is `false`.
</ResponseField>
<ResponseField name="up.exit_node_takes_precedence" type="boolean">
Default for `--exit-node-takes-precedence`. When true, matches the [Exit Nodes Take Precedence Over Resources](/manage/clients/platforms#exit-nodes-take-precedence-over-resources) preference. While connected through an exit node, routes for other resources are not added and their aliases are not resolved, so all traffic flows through the exit node. If omitted, the default is `false`.
</ResponseField>
</Expandable>
</ResponseField>
## Update
Find the latest version in the [GitHub releases](https://github.com/fosrl/cli/releases).
### Automatic Updates
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>
@@ -0,0 +1,92 @@
---
title: "Platforms"
description: "Install, configure, and update Pangolin clients, and shared DNS and routing preferences"
---
Each client has a preferences window. On Mac and Windows, click the menu bar or system tray icon and select "Preferences". In the mobile apps, open the "Preferences" screen.
The preferences below are shared across GUI clients. Install steps, settings that exist only on one client, and updates are documented on that client's page.
To troubleshoot connection or configuration issues, see [Client Logs](/manage/clients/client-logs) for how to view logs on each platform.
<CardGroup cols={2}>
<Card title="Windows" icon="windows" href="/manage/clients/platforms/windows">
Install the Windows client, set preferences, and update.
</Card>
<Card title="Mac" icon="apple" href="/manage/clients/platforms/mac">
Install the Mac client, set preferences, and update.
</Card>
<Card title="iOS/iPadOS" icon="apple" href="/manage/clients/platforms/ios">
Install the iOS app, set preferences, and update from the App Store.
</Card>
<Card title="Android" icon="android" href="/manage/clients/platforms/android">
Install the Android app, set preferences, and update from Google Play.
</Card>
<Card title="Pangolin CLI" icon="terminal" href="/manage/clients/platforms/cli">
Install the CLI on Linux, macOS, and Windows, including machine clients.
</Card>
<Card title="Olm" icon="terminal" href="/manage/clients/platforms/olm">
Deprecated command-line client. Use the Pangolin CLI instead.
</Card>
</CardGroup>
## Shared Preferences
The following preferences control how your client handles DNS resolution and network routing. They are available on Mac, Windows, Android, and iOS/iPadOS.
### 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.
### Exit Nodes Take Precedence Over Resources
By default this is disabled. When a client is connected using an exit node other Pangolin resources will still be accessible and resolvable even on other sites not designated on the exit node resource. In this way Pangolin is still split tunneling these destinations. By enabling this setting, you are configuring Pangolin to ignore other resources outside of the exit node. All traffic will flow to and through the exit node resource and DNS aliases and subnets on other resources will no longer function.
### 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>
@@ -0,0 +1,58 @@
---
title: "iOS/iPadOS"
description: "Install, configure, and update the Pangolin app for iOS and iPadOS"
---
## Install
- [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.
## Configure
<Note>
DNS, MTU, and other preferences shared across clients are on [Platforms](/manage/clients/platforms#shared-preferences).
</Note>
### Dynamic Island and Live Activity
When enabled, Pangolin shows connection status in the Dynamic Island and on the Lock Screen.
### Connect Automatically On
Choose when Pangolin may connect automatically. Tap **Connect** to enable on-demand for that interface; **Disconnect** disables it.
**Cellular** connects automatically while the device is on cellular.
**Wi-Fi** connects automatically while the device is on Wi-Fi. You can limit which networks that applies to:
- **Any Wi-Fi Network** connects on every Wi-Fi network.
- **Only these Wi-Fi Networks** connects only on the networks you list.
- **Except these Wi-Fi Networks** connects on every network except the ones you list.
## Update
Updates are delivered through the App Store.
@@ -0,0 +1,143 @@
---
title: "Mac"
description: "Install, configure, and update the Pangolin client for Mac"
---
## Install
- [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.
## Configure
<Note>
DNS, MTU, and other preferences shared across clients are on [Platforms](/manage/clients/platforms#shared-preferences).
</Note>
### Start at Login
When enabled, Pangolin opens automatically when you log in to your Mac.
### Connect Automatically On
Choose when Pangolin may connect automatically. **Connect** enables on-demand for that interface; **Disconnect** disables it.
**Ethernet** connects automatically while the Mac is on Ethernet.
**Wi-Fi** connects automatically while the Mac is on Wi-Fi. You can limit which networks that applies to:
- **Any Wi-Fi Network** connects on every Wi-Fi network.
- **Only these Wi-Fi Networks** connects only on the networks you list.
- **Except these Wi-Fi Networks** connects on every network except the ones you list.
### Config File
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)](/manage/clients/platforms#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](/manage/clients/platforms#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="exitNodeTakesPrecedence" type="boolean">
When true, matches the [Exit Nodes Take Precedence Over Resources](/manage/clients/platforms#exit-nodes-take-precedence-over-resources) preference. While connected through an exit node, routes for other resources are not added and their aliases are not resolved, so all traffic flows through the exit node. If omitted, the default is `false`.
</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="onDemandWiFiEnabled" type="boolean">
When true, matches the **Wi-Fi** option under **Connect Automatically On** and connects on demand whenever the Mac is on Wi-Fi. Use `onDemandSSIDOption` and `onDemandSSIDs` to limit this to specific networks. If omitted, the default is `false`.
</ResponseField>
<ResponseField name="onDemandNonWiFiEnabled" type="boolean">
When true, matches the **Ethernet** option under **Connect Automatically On** and connects on demand whenever the Mac is on Ethernet. If omitted, the default is `false`.
</ResponseField>
<ResponseField name="onDemandSSIDOption" type="string">
Which Wi-Fi networks on-demand applies to when `onDemandWiFiEnabled` is true. Supported values are `any` (**Any Wi-Fi Network**), `only` (**Only these Wi-Fi Networks**, the names in `onDemandSSIDs`), and `except` (**Except these Wi-Fi Networks**). If omitted, or if `onDemandSSIDs` is empty, the default is `any`.
</ResponseField>
<ResponseField name="onDemandSSIDs" type="array of strings">
Wi-Fi network names (SSIDs) used by the `only` and `except` modes of `onDemandSSIDOption`.
</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>
<ResponseField name="sessionCookieName" type="string">
Overrides the cookie name the session token is sent and read under. Most deployments should leave this unset.
</ResponseField>
</Expandable>
</ResponseField>
## Update
### Automatic Updates
The Mac client periodically checks for updates in the background. When an update is available, it requests permission to update. You can also check for updates from the menu bar, or by restarting the application.
Once you accept the update, the client downloads the latest version and replaces itself.
### Manual Updates
Find the latest version in the [GitHub releases](https://github.com/fosrl/apple/releases).
You can download the latest installer and run it again to install the latest version. Visit [https://pangolin.net/downloads](https://pangolin.net/downloads) for the official installer.
@@ -0,0 +1,570 @@
---
title: "Olm (Deprecated)"
description: "Deprecated command-line client for machine connections"
---
<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.
## Install
### 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 [service management commands](#service-management-commands) to manage it and run it in the background.
- **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.
## Configure
<Note>
DNS, MTU, and other preferences shared across clients are on [Platforms](/manage/clients/platforms#shared-preferences).
</Note>
### 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>
### Config File
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.
## Update
Re-run the install script to pull the latest version:
```bash
curl -fsSL https://static.pangolin.net/get-olm.sh | bash
```
On Windows, download the latest installer from the [GitHub releases](https://github.com/fosrl/olm/releases/latest). You can also download a binary for your system from the [GitHub releases](https://github.com/fosrl/olm/releases) and replace the existing binary.
@@ -0,0 +1,173 @@
---
title: "Windows"
description: "Install, configure, and update the Pangolin client for Windows"
---
## Install
- [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.
## Companion Mode
Companion mode lets [Pangolin CLI](/manage/clients/platforms/cli) use this app's login and tunnel. Sign in and connect here, then run CLI commands as that same account. You do not run `pangolin login` again.
Companion mode is available on Windows only. It requires Pangolin for Windows 0.11.0 or later, and it is on by default once the CLI is installed.
1. Log in with the Windows client and connect.
2. Install Pangolin CLI if it is not already installed. From the Pangolin menu bar, choose **Install Pangolin CLI**, or follow the [CLI install steps](/manage/clients/platforms/cli).
3. Run CLI commands in a terminal. For example, open SSH to a [private SSH resource](/manage/resources/private/ssh):
```bash
pangolin ssh username@alias
```
The CLI follows the account, organization, and exit node selected in the desktop app. Change those in the app. While companion mode is on, `pangolin login`, `pangolin logout`, and `pangolin select` for account, organization, or exit node are blocked.
The desktop app has to be open and logged in. If it is not, the CLI asks you to start Pangolin and log in.
Commands to check status or turn companion mode off are on the [CLI companion mode section](/manage/clients/platforms/cli#companion-mode).
## Configure
<Note>
DNS, MTU, and other preferences shared across clients are on [Platforms](/manage/clients/platforms#shared-preferences).
</Note>
### Start at Login
When enabled, Pangolin starts when you sign in to Windows.
### Connect at Start
When enabled, the tunnel connects whenever Pangolin starts. This also opens Pangolin at sign-in.
### Config File
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)](/manage/clients/platforms#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](/manage/clients/platforms#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="exitNodeTakesPrecedence" type="boolean">
When true, matches the [Exit Nodes Take Precedence Over Resources](/manage/clients/platforms#exit-nodes-take-precedence-over-resources) preference. While connected through an exit node, routes for other resources are not added and their aliases are not resolved, so all traffic flows through the exit node. If omitted, the default is `false`.
</ResponseField>
<ResponseField name="openUIAtLogin" type="boolean">
When true, matches the **Start at Login** preference and starts Pangolin when you sign in to Windows. If omitted, the default is `false`.
</ResponseField>
<ResponseField name="autoConnectAtLogin" type="boolean">
When true, matches the **Connect at Start** preference. The tunnel connects whenever Pangolin starts, and Pangolin also opens at sign-in, regardless of `openUIAtLogin`. If omitted, the default is `false`.
</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>
<ResponseField name="sessionCookieName" type="string">
Overrides the cookie name the session token is sent and read under. Most deployments should leave this unset.
</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>
## Update
### Automatic Updates
The Windows client periodically checks for updates in the background. When an update is available, it requests permission to update. You can also check for updates from the system tray menu, or by restarting the application.
Once you accept the update, the client downloads the latest version and replaces itself.
### Manual Updates
Find the latest version in the [GitHub releases](https://github.com/fosrl/windows/releases).
You can download the latest installer and run it again to install the latest version. Visit [https://pangolin.net/downloads](https://pangolin.net/downloads) for the official installer.
@@ -0,0 +1,135 @@
---
title: "Subnet Router"
description: ""
---
A subnet router lets devices that can't run the Pangolin client access Pangolin resources. It sits between the Pangolin network and a physical subnet, so legacy devices, whole networks, or services still have access without installing Pangolin on each one.
<Note>
Subnet routing currently only works on Linux with the [Pangolin
CLI](/manage/clients/platforms/cli).
</Note>
Installing the Pangolin client on a device gives you end-to-end encryption and the best performance, so do that whenever you can. Often you can't. Printers usually can't run the client, and in a large AWS VPC or a legacy network that is being modernized step by step, touching every endpoint isn't realistic.
In those cases a subnet router relays traffic between your Pangolin network and the regular subnet. It enforces your access control policies on that traffic, so non-Pangolin devices get connectivity without a gap in security.
Devices behind a subnet router don't count toward your plan's limit. Even so, a direct install remains the better option for performance, security, and simpler configuration.
## Benefits
- Connect legacy devices that can't run the Pangolin client.
- Bring in entire networks, such as AWS VPCs, without installing Pangolin on each device.
- Adopt Pangolin gradually by connecting existing network segments through subnet routers.
- Keep access control in place, since subnet routers follow Pangolin's access control policies.
## Use cases
- Reach managed services such as Amazon RDS or Google Cloud SQL without exposing them to the public internet.
- Connect cloud VPCs or other cloud network segments to your Pangolin network.
- Let remote Pangolin users reach devices like printers or cameras that can't run the client.
## How subnet routers work
A subnet router links separate network environments under one access model. It works at the network layer to pass traffic between your Pangolin network and traditional subnet-based networks.
In Pangolin, a subnet router is a client in your Pangolin network that acts as a gateway and advertises routes to a subnet. Other devices in that subnet can then connect to your Pangolin network without running the Pangolin client.
A device that uses the subnet router as its gateway is said to be behind it. By default, subnet routers apply Source Network Address Translation (SNAT), so traffic from a device behind the router appears to come from the router rather than from the device.
<Note>
Subnet routers and exit nodes both route traffic, but they do different jobs. An exit node sends outbound internet traffic from your Pangolin clients through a site, like a VPN server. Your traffic appears to originate from the exit node's location, which helps with geo-restricted content or privacy. A subnet router gives access to Pangolin resources do devices not running the Pangolin client on private subnets. Devices can reach Pangolin resources in those subnets, and internet routing is unchanged.
</Note>
## Set up a subnet router
### Deploy the site
You need a site in the dashboard, running on the remote network. See [Install Sites](/manage/sites/install-site).
### Create resources
Create [CIDR](/manage/resources/private/cidr) resources, or [host](/manage/resources/private/host) resources with an IP destination. The destination must be an IP or CIDR so that other devices on the subnet router's network can set up routes that point at the router. Give the machine client from the next steps access to these resources.
### Install the Pangolin CLI
The host must run Linux. Install the CLI with:
```bash
curl -fsSL https://static.pangolin.net/get-cli.sh | bash
```
When you run the CLI with `--subnet-router`, it enables forwarding and manages the nftables backend for you. See [Pangolin CLI](/manage/clients/platforms/cli) for other install options.
<Warning>
By default Docker adds its own forwarding rules to iptables, which can interfere with subnet routing if Docker is on the host. Let forwarded traffic through Docker's chain by setting this in `/etc/docker/daemon.json`:
```json title="/etc/docker/daemon.json"
{
"ip-forward-no-drop": true
}
```
Restart Docker after changing this file. For background on running Docker on a router, see Docker's [packet filtering and firewalls guide](https://docs.docker.com/engine/network/packet-filtering-firewalls/#docker-on-a-router).
</Warning>
### Log in or create a machine client
A machine client is the usual choice for a router, since it isn't tied to a user account. In the dashboard, go to Clients > Machines and create one. Copy its ID, secret, and endpoint. See [Machine Client Credentials](/manage/clients/credentials).
You can also log in as a user with `pangolin login` and run `pangolin up`, but a machine client is better suited to a long-running service.
### Connect the client as a subnet router
Start the client with the `--subnet-router` flag. It needs the CAP_NET_ADMIN capability, so run it as root:
```bash
sudo pangolin up client \
--id {client_id} \
--secret {client_secret} \
--endpoint {endpoint_url} \
--subnet-router \
--attach
```
`--attach` keeps the client in the foreground. To keep it running across reboots, install it as a service instead. See [Run as a Service](/manage/clients/platforms/cli#run-as-a-service).
### Check the firewall and NAT rules
Make sure no firewall rules on the host or the network block traffic from the resource ranges going up the tunnel. Connections from the LAN to those ranges must be able to reach the Pangolin client and leave through its tunnel interface.
When the client starts with `--subnet-router`, it enables IPv4 forwarding on the host and adds NAT rules for traffic leaving through the tunnel. It also accepts forwarded traffic to and from the tunnel interface, so a default-deny forward policy elsewhere on the host doesn't drop it. To see the rules, run:
```bash
sudo nft list table ip olm_subnet_router
```
The client removes the rules when it disconnects, and turns forwarding back off only if it was the one that enabled it.
### Set up routing on the network
If the Pangolin client is not running on the network's gateway/router then you will need to teach the network where to find these specific resource routes.
On the default gateway of the network, add a route that sends the resource CIDRs to the device running the Pangolin client. For example, with a LAN of 192.168.18.0/24, the client running on 192.168.18.10, and a resource CIDR of 10.1.0.0/16:
| Where | Destination | Next hop |
|-------|-------------|----------|
| Default gateway of 192.168.18.0/24 | 10.1.0.0/16 | 192.168.18.10 |
On a Linux gateway, that route looks like this:
```bash
sudo ip route add 10.1.0.0/16 via 192.168.18.10
```
Devices on the LAN can now reach the resource through the subnet router without running the Pangolin client.
## Logging
All subnet traffic will show up in the network connection logs but will originate from the source of the Pangolin client because of the SNAT.
<Tip>
Network connection logs are availble on Enterprise Edition and Pangolin Cloud.
</Tip>
@@ -6,7 +6,7 @@ A client is a way to access resources on sites remotely and privately via a virt
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.
Users must log in and connect from a Pangolin client available on [Windows, Mac, Linux, iOS/iPadOS, and Android](/manage/clients/platforms). They sign in with their user credentials through a web login flow. Machines (automated systems and servers) connect with [machine client credentials](/manage/clients/credentials): an ID, secret, and endpoint.
## Client Types
@@ -15,20 +15,20 @@ 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)
- Logs in with user credentials through a web login flow (password, 2FA, or an identity provider)
- 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
- Connect with machine client credentials (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.
A user may download a client for their specific system. Before they can connect, they select a Pangolin server and log in with their user credentials through the web login flow. Users can log in as a Pangolin user or with your attached external identity provider.
Examples include:
@@ -48,7 +48,7 @@ Examples include:
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.
Machine clients authenticate with [machine client credentials](/manage/clients/credentials): an ID and secret. These are passed as arguments to the Pangolin CLI. They can be revoked and rotated. User devices never use these credentials.
## Client Modalities
@@ -1,48 +0,0 @@
---
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>
+1 -1
View File
@@ -25,7 +25,7 @@ Selecting a resource always expands a details panel. The panel shows what matter
<img src="/images/resource-launcher-expanded.png" alt="Resource Launcher detail panel showing a private SSH resource as an example."/>
</Frame>
From a card, list row, or the panel you can open HTTP-style resources in a new tab (HTTP/HTTPS, SSH, RDP, VNC, AI Gateway) or copy the access string. Private resources remind you to connect with a [Pangolin client](/manage/clients/install-client).
From a card, list row, or the panel you can open HTTP-style resources in a new tab (HTTP/HTTPS, SSH, RDP, VNC, AI Gateway) or copy the access string. Private resources remind you to connect with a [Pangolin client](/manage/clients/platforms).
For [AI Gateway](/manage/ai/overview) resources, the panel also lists available models, [virtual API keys](/manage/ai/virtual-api-keys), and copy-paste setup for coding agents. Public gateways use your API key. Private gateways use the connected client as the credential.
@@ -3,7 +3,7 @@ title: "AI Gateway"
description: "Reach an AI API over the Pangolin tunnel using the connected client's identity"
---
A private AI Gateway resource exposes an AI API only to devices connected with the [Pangolin client](/manage/clients/install-client). Nothing is reachable from the public internet. Unlike [public AI Gateway](/manage/resources/public/ai-gateway), the gateway does not check a virtual API key. Identity comes from the active client connection.
A private AI Gateway resource exposes an AI API only to devices connected with the [Pangolin client](/manage/clients/platforms). Nothing is reachable from the public internet. Unlike [public AI Gateway](/manage/resources/public/ai-gateway), the gateway does not check a virtual API key. Identity comes from the active client connection.
This page covers how the **resource** works: reachability, access, and what you attach. Providers, model routing, the catalog, and client setup live in [AI Gateway](/manage/ai/overview).
@@ -34,6 +34,6 @@ The `.local` TLD is reserved for local networking and multicast DNS (mDNS). mDNS
## Custom Upstream DNS
Aliases work by overriding the DNS of your computer running the client so that all DNS requests are sent to the Pangolin client for resolution. That behavior is controlled by the Enable Aliases (Override DNS) preference; see [Configure Clients](/manage/clients/configure-client#enable-aliases-override-dns). The DNS server on your computer is typically `100.96.128.1` (the first address inside of your utility subnet on the org) when connected to the tunnel, which forwards requests to an upstream server. By default, we use `1.1.1.1`, but this upstream address can be configured in the CLI or in the client settings.
Aliases work by overriding the DNS of your computer running the client so that all DNS requests are sent to the Pangolin client for resolution. That behavior is controlled by the Enable Aliases (Override DNS) preference; see [Platforms](/manage/clients/platforms#enable-aliases-override-dns). The DNS server on your computer is typically `100.96.128.1` (the first address inside of your utility subnet on the org) when connected to the tunnel, which forwards requests to an upstream server. By default, we use `1.1.1.1`, but this upstream address can be configured in the CLI or in the client settings.
**If you are attempting to set an upstream DNS server that is only accessible via the tunnel, ensure that you create a resource and check the tunnel DNS option in the client configuration settings.** Otherwise, connectivity to the server may fail when connected to the tunnel. Enable Aliases (Override DNS) must also be on—see [Configure Clients](/manage/clients/configure-client#enable-aliases-override-dns)—so the client can intercept DNS and forward queries to the upstream server.
**If you are attempting to set an upstream DNS server that is only accessible via the tunnel, ensure that you create a resource and check the tunnel DNS option in the client configuration settings.** Otherwise, connectivity to the server may fail when connected to the tunnel. Enable Aliases (Override DNS) must also be on—see [Platforms](/manage/clients/platforms#enable-aliases-override-dns)—so the client can intercept DNS and forward queries to the upstream server.
@@ -60,4 +60,4 @@ If a resource's destination overlaps with the user's local subnet, the client ca
**To fix it**, have the user check their local IP and subnet (`ipconfig` on Windows, `ifconfig`/`ip addr` on macOS/Linux), then compare it against your resource destinations. The recommended solution is to use more specific routes for your resources to prevent routing conflicts. For example instead of using a whole CIDR, use only host resources, or use more specific CIDRs like a /30 instead of a /24. Clients will always route to more specific routes over less specific ones. This way resource access is still controlled by Pangolin while the user's local and internet traffic is undisturbed.
If the above does not work, on Windows and Linux you can update the Pangolin client configuration to add a `prefer local routes` entry for the user's local subnet. This will tell the client to leave that traffic on the local network instead of routing it over the tunnel. See the [Configure Clients](/manage/clients/configure-client) page.
If the above does not work, on Windows and Linux you can update the Pangolin client configuration to add a `prefer local routes` entry for the user's local subnet. This will tell the client to leave that traffic on the local network instead of routing it over the tunnel. See [Windows](/manage/clients/platforms/windows) and the [Pangolin CLI](/manage/clients/platforms/cli).
@@ -0,0 +1,92 @@
---
title: "Exit Node (route all traffic)"
description: "Create private exit node resources to act as full"
---
Pangolin works as a split tunnel VPN by default. It carries traffic between sites and clients and leaves your public internet traffic alone, for example when you visit Google or Wikipedia. This suits most people, who want secure communication between sensitive devices such as company servers or home computers, without the extra encryption and latency on their regular internet connection.
Sometimes you do want Pangolin to carry your public internet traffic, for instance when:
- You're on untrusted coffee shop Wi-Fi.
- You're abroad and need an online service, such as banking, that only works from your home country.
To do this, make a site an exit node and point other devices at it using an exit node resource. Routing everything through an exit node uses the default routes (0.0.0.0/0, ::/0), the same way a typical VPN does.
<Note>
Subnet routers and exit nodes both route traffic, but they do different
jobs. A subnet router gives access to resources to devices not running the
Pangolin client on private subnets. Devices can reach Pangolin resources in
those subnets, and internet routing is unchanged. An exit node sends
outbound internet traffic from your Pangolin clients through sites, like a
VPN server. Your traffic appears to originate from the exit node's location,
which helps with geo-restricted content or privacy.
</Note>
## Benefits
- All traffic is secured, including traffic to internet sites and applications.
- You can deploy exit nodes around the world to fit your scale and location needs.
- Network connection logging shows traffic across the Pangolin network and supports analysis after a security incident.
## Use cases
- Traveling staff have all their internet traffic secured, whatever network they're on.
- You can test applications from different locations by deploying exit nodes in several regions and choosing between them.
- If regulations or compliance rules require your workforce to use a VPN, exit nodes can meet that requirement.
## How it works
With the exit node feature, you send all traffic through one or more sites on your Pangolin network. That device is the exit node. You can use exit nodes in several ways:
- Route all non-Pangolin traffic through an exit node.
- Use multiple exit nodes on the resource and clients will pick the best one automatically based on latency.
## Set up a exit node
### Deploy the site
Create a site in the dashboard and run it on the network you want your traffic to leave from. Traffic exits from that site's internet connection. See [Install Sites](/manage/sites/install-site). For redundancy or lower latency, deploy more than one site.
### Create the exit node resource
1. Create a new private resource and set the mode to Exit Node.
2. Select the sites to use as exit nodes. With several sites, clients pick the best one by latency.
3. Choose the roles, users, and machine clients that can use the exit node.
An exit node has no destination, since it always routes 0.0.0.0/0. All TCP and UDP ports and ICMP are allowed.
### Select the node in your client
Each device enables the exit node on its own, and the steps depend on the client.
#### MacOS, Windows, iOS, Android
1. Open the Pangolin app and go to the exit node section.
2. Select the exit node you want.
3. Check that the status shows active in the exit node section and when clicking on the sites they are marked for exit node use.
4. To stop using an exit node, go to the Exit Node section and select None.
#### CLI
Run this command and pick an exit node from the list:
```bash
pangolin select exit-node
```
If the client is running, the change applies immediately. If not, the choice is saved and applied on the next `pangolin up`. To turn it off, run the command again and choose None. To select an exit node without the prompt, pass its nice ID with `--exit-node`.
To confirm routing works, look up your public IP address with an online tool. It should show the exit node's public address instead of your local device's.
## Other Resources When Connected
When a client is connected using an exit node other Pangolin resources will still be accessible and resolvable - even on other sites not designated on the exit node resource. In this way Pangolin is still split tunneling these destinations. If you would like to disable this, set the [Exit Nodes Take Precedence Over Resources](/manage/clients/platforms#exit-nodes-take-precedence-over-resources) setting on. By enabling this setting, you are configuring Pangolin to ignore other resources outside of the exit node - all traffic will flow to and through the exit node resource and DNS aliases and subnets on other resources will no longer function.
## Logging
All exit node traffic appears in the network connection logs.
<Tip>
Network connection logs are available on Enterprise Edition and Pangolin
Cloud.
</Tip>
@@ -19,7 +19,7 @@ The Pangolin client provides the tunnel; the CLI handles certificate generation,
pangolin ssh <resource-alias>
```
The tunnel can be provided by the CLI or by another Pangolin client (for example the macOS app). You can run the GUI for the tunnel and use the CLI only for SSH.
The tunnel can be provided by the CLI or by another Pangolin client (for example the macOS app). You can run the GUI for the tunnel and use the CLI only for SSH. On Windows, [companion mode](/manage/clients/platforms/windows#companion-mode) uses the desktop app's login and connection, so `pangolin ssh` runs as the account you already signed in with.
## Destination and Access
@@ -113,6 +113,10 @@ Private resources require users to connect with the Pangolin client before any t
<Card title="SSH" icon="terminal" href="/manage/resources/private/ssh" arrow="true">
Traditional terminal SSH over the tunnel via `pangolin ssh`.
</Card>
<Card title="Exit Node" icon="route" href="/manage/resources/private/exit-node" arrow="true">
Route all client internet traffic out through the site.
</Card>
</CardGroup>
Private resources can only be created on Pangolin Sites.
+1 -1
View File
@@ -247,7 +247,7 @@ flowchart LR
### Prerequisites
- **Pangolin Site** running on one host (the site / bastion) with a pre-shared key for external auth daemons.
- **Pangolin CLI** installed on each server where you will run the auth daemon. See [Install Clients - Quick Install (Recommended)](/manage/clients/install-client#quick-install-recommended).
- **Pangolin CLI** installed on each server where you will run the auth daemon. See [Pangolin CLI](/manage/clients/platforms/cli#install).
### Step 1: On the Server Running the Pangolin Site
@@ -38,12 +38,6 @@ server:
allowed_headers: ["X-CSRF-Token", "Content-Type"]
credentials: false
# Optional organization network settings (defaults shown):
# orgs:
# block_size: 24
# subnet_group: "100.90.128.0/20"
# utility_subnet_group: "100.96.128.0/20"
flags:
require_email_verification: false
disable_signup_without_invite: true
@@ -305,6 +299,40 @@ This section contains the complete reference for all configuration options in `c
</Tip>
</ResponseField>
<ResponseField name="trust_ips" type="array of strings">
IP ranges, in CIDR format, of the upstream proxies or load balancers that Badger trusts to supply the real client IP.
**Example**: `["10.0.0.0/8", "172.16.0.0/12"]`
**Default**: `[]`
<Note>
By default Badger trusts Cloudflare's IP ranges and reads the client IP from the `CF-Connecting-IP` header. Setting one or more ranges here replaces the Cloudflare ranges, so only the ranges you list are trusted. Use this when a proxy other than Cloudflare sits in front of Pangolin.
</Note>
<Warning>
Only list addresses of proxies you control. Any request arriving from a trusted range can set the client IP that Pangolin uses for rules and logging.
</Warning>
</ResponseField>
<ResponseField name="custom_ip_header" type="string">
Name of the HTTP header Badger reads the real client IP from when a request arrives from a trusted IP range.
**Example**: `X-Real-Ip`
**Default**: `""` (uses `CF-Connecting-IP`)
<Note>
The header is only honored for requests from a trusted source: the ranges in `trust_ips`, or Cloudflare's ranges when `trust_ips` is empty. The header value is used as-is, so choose a header your proxy sets to a single IP address. If the header is missing, Badger falls back to `CF-Connecting-IP` and then to the connection's remote address.
</Note>
```yaml
server:
trust_ips: ["10.0.0.0/8"]
custom_ip_header: "X-Real-Ip"
```
</ResponseField>
<ResponseField name="enable_ai_gateway_client_ip_header" type="boolean">
Whether to have Badger stamp the resolved client IP into a dedicated `X-Pangolin-Client-Ip` header on the site-resource AI Gateway route.
@@ -1,317 +0,0 @@
---
title: "Enterprise Edition"
description: "Learn about Enterprise Edition licensing, plans, and how to get started"
---
When self-hosting Pangolin, you can run the **Community Edition** or the **Enterprise Edition**. Both editions provide the same core functionality. Enterprise Edition unlocks additional features with a license key on the `ee` Docker image.
<Check>
Enterprise Edition is **free** for personal use and organizations with **less than $100,000 USD** gross annual revenue. You still need a valid license key to activate it.
</Check>
<Warning>
Organizations with **$100,000+ USD** gross annual revenue require a **paid commercial license** to use Enterprise Edition.
</Warning>
<CardGroup cols={3}>
<Card title="Get a free license" icon="user" href="#get-a-free-license-personal-use">
Personal use and small organizations under the revenue threshold.
</Card>
<Card title="Compare features and plans" icon="table-list" href="https://pangolin.net/pricing#Self-Hosted-identity-and-access-management">
Full feature comparison and plan tiers for self-hosted Pangolin.
</Card>
<Card title="Purchase a license" icon="credit-card" href="/self-host/purchase-license-key">
Paid commercial licenses for businesses above the revenue threshold.
</Card>
</CardGroup>
## Licensing Overview
Enterprise Edition is distributed under the **Fossorial Commercial License**. Your organization's gross annual revenue determines whether you qualify for a free license or need a paid one.
### Personal Use
Free for individuals and small businesses:
- **Revenue threshold**: Less than $100,000 USD gross annual revenue
- **License cost**: Free
- **Usage**: Personal and small business use allowed
You still need to apply for a valid license key to unlock Enterprise features, even with free licensing.
### Business Use
Larger businesses require a paid license:
- **Revenue threshold**: $100,000+ USD gross annual revenue
- **License cost**: Paid license required — see [Self-Hosted pricing](https://pangolin.net/pricing#Self-Hosted) for tiers
- **Usage**: Business use with commercial terms
- **Trial**: Want to evaluate Enterprise Edition before buying? Contact [sales@pangolin.net](mailto:sales@pangolin.net) to request a free limited trial license.
Businesses exceeding the revenue threshold must purchase a commercial license to use Enterprise Edition.
## Enterprise Features and Plans
Enterprise Edition unlocks capabilities beyond Community Edition. Your license tier determines which features and limits apply.
<Card title="View full feature comparison" icon="table-list" href="https://pangolin.net/pricing#Self-Hosted-identity-and-access-management">
The Self-Hosted pricing page is the source of truth for features, limits, and plan tiers.
</Card>
<Tip>
For setup instructions on a specific feature, search the docs or browse from the pricing page. Individual doc pages mark Enterprise-only features with notes linking back to this page.
</Tip>
## Hiding Enterprise Features on Community Edition
On Community Edition, Enterprise-only capabilities may still appear in the dashboard but remain locked without the `ee` Docker image and a valid license key. To hide those UI elements entirely, set `disable_enterprise_features` under `flags` in your [`config.yml`](/self-host/advanced/config-file):
```yaml
flags:
disable_enterprise_features: true
```
When enabled, Enterprise-only features are hidden from the UI. Restart the stack after updating the configuration file.
## Get a Free License (Personal Use)
<Steps>
<Step title="Create an account">
Visit [app.pangolin.net](https://app.pangolin.net) and create your account.
</Step>
<Step title="Create an organization">
After signing up you will be prompted to create an organization. This is required to apply for a license key.
</Step>
<Step title="Complete the license application">
Go to the **Licenses** section in your account dashboard and complete the license application form.
<Warning>
Inaccurate representation is a violation of the license and will result in the license being revoked.
</Warning>
</Step>
<Step title="Receive your key">
Once approved, you'll receive your license key immediately. Continue to [Activate Enterprise Edition](#activating-enterprise-edition) to use it on your server.
</Step>
</Steps>
Organizations above the revenue threshold should [purchase a commercial license](/self-host/purchase-license-key) instead. See [Self-Hosted pricing](https://pangolin.net/pricing#Self-Hosted) for paid tiers.
## Purchase a License (Business Use)
Businesses with $100,000+ USD gross annual revenue need a paid commercial license.
### Self-serve Purchase
You can buy a **Starter** or **Scale** license online at any time through [app.pangolin.net](https://app.pangolin.net). Follow the steps in [Purchase a license key](/self-host/purchase-license-key) to choose your tier, complete checkout, and receive your key immediately. Compare features and limits on the [Self-Hosted pricing page](https://pangolin.net/pricing#Self-Hosted-identity-and-access-management), then activate your key — see [Activate Enterprise Edition](#activating-enterprise-edition).
### Custom Licensing
Need more users, more sites, or special add-ons — such as compliance packages, SLA support, pay-by-invoice, or bank transfer? Contact [sales@pangolin.net](mailto:sales@pangolin.net) for a custom quote.
<Info>
Not ready to purchase? Businesses can request a **free limited trial** of Enterprise Edition by emailing [sales@pangolin.net](mailto:sales@pangolin.net). Include your organization details and what you'd like to evaluate.
</Info>
## Upgrade from Community Edition
If you're already running Community Edition and want Enterprise features:
<Steps>
<Step title="Get a license key">
Apply for a [free license](#get-a-free-license-personal-use) or [purchase a commercial license](/self-host/purchase-license-key), depending on your organization's revenue.
</Step>
<Step title="Switch to the Enterprise image">
Update your Docker Compose configuration:
```yaml
services:
pangolin:
image: fosrl/pangolin:ee-latest # Enterprise Edition
# ... rest of configuration
```
<Warning>
The Enterprise Edition image is tagged with `ee` (e.g., `fosrl/pangolin:ee-latest`) and is different from the Community Edition (`fosrl/pangolin:latest`).
</Warning>
</Step>
<Step title="Restart the stack">
```bash
sudo docker compose down && sudo docker compose up -d
```
</Step>
<Step title="Activate your license key">
Log in with server admin credentials, open the Server Admin panel, and go to the License section at `/admin/license`. Enter and activate your key.
</Step>
<Step title="Verify activation">
Confirm Enterprise Edition features are unlocked in your dashboard.
</Step>
</Steps>
## Activating Enterprise Edition
Use these steps if you're setting up Enterprise Edition for the first time (including after a fresh install with the `ee` image).
<Steps>
<Step title="Use Enterprise Edition image">
Your Docker Compose configuration must use the Enterprise Edition image:
```yaml
services:
pangolin:
image: fosrl/pangolin:ee-latest # Enterprise Edition
# ... rest of configuration
```
</Step>
<Step title="Restart the stack">
```bash
sudo docker compose down && sudo docker compose up -d
```
</Step>
<Step title="Add license key to instance">
Log in to the Pangolin instance via the server admin credentials. Visit the Server Admin panel and navigate to the License section (`/admin/license`). Enter and activate the license key.
<Info>
The license key should be provided exactly as received.
</Info>
</Step>
<Step title="Verify activation">
Check your Pangolin dashboard to confirm Enterprise Edition features are unlocked.
</Step>
</Steps>
### Troubleshooting Activation
<AccordionGroup>
<Accordion title="Admin panel still shows Community Edition">
You're likely running the Community Edition Docker image. Confirm your `docker-compose.yml` uses `fosrl/pangolin:ee-latest` (or a pinned version like `fosrl/pangolin:ee-1.14.1`), not `fosrl/pangolin:latest`. Restart the stack after changing the image:
```bash
sudo docker compose down && sudo docker compose up -d
```
Check container logs if the issue persists:
```bash
sudo docker compose logs pangolin
```
</Accordion>
<Accordion title="No License section in the admin panel">
The License section only appears when the Enterprise Edition image is running. Switch to the `ee` image and restart the stack — see the accordion above.
</Accordion>
<Accordion title="Enterprise settings are missing after activation">
Some features require a valid activated license **and** additional configuration. For example, branding and certain identity provider settings need a [`privateConfig.yml`](/self-host/advanced/private-config-file) file mounted in your container. Verify your license is active and check the docs for the specific feature you're enabling.
</Accordion>
</AccordionGroup>
## License Requirements
<AccordionGroup>
<Accordion title="How many license keys do I need?">
**One key per Pangolin server instance**
Each host (server) running Pangolin requires its own license key. You cannot share a single key across multiple servers. A server is considered to be a single database instance.
</Accordion>
<Accordion title="Can I get a trial license?">
Yes. Businesses that require a paid commercial license can request a **free limited trial** of Enterprise Edition by contacting [sales@pangolin.net](mailto:sales@pangolin.net). Include your organization details and which features you want to evaluate.
Trial licenses are intended for organizations above the personal-use revenue threshold that want to test Enterprise Edition before purchasing.
</Accordion>
<Accordion title="What if I'm unsure about my license type?">
If you're uncertain whether you qualify for free licensing or need a commercial license, reach out to [sales@pangolin.net](mailto:sales@pangolin.net) with your organization details.
</Accordion>
</AccordionGroup>
## FAQ
<AccordionGroup>
<Accordion title="What features does Enterprise Edition include?">
Enterprise Edition unlocks advanced features beyond Community Edition.
See the [Self-Hosted pricing page](https://pangolin.net/pricing#Self-Hosted-identity-and-access-management) for the full feature comparison — it is the source of truth for what each plan includes.
</Accordion>
<Accordion title="What are Paid Features?">
"Paid Features" refers to the advanced capabilities unlocked by Enterprise Edition with a valid license key. Personal and small-business users get a free license. Larger organizations purchase a paid license.
For the complete list, see [Self-Hosted pricing](https://pangolin.net/pricing#Self-Hosted).
</Accordion>
<Accordion title="Can I use Enterprise Edition for personal projects?">
Yes. Individuals and small businesses under the $100,000 USD revenue threshold can use Enterprise Edition for personal projects at no cost. [Apply for a free license](#get-a-free-license-personal-use) to get started.
</Accordion>
<Accordion title="Why would a business pay for self-hosted Enterprise Edition?">
Paid tiers unlock features most organizations need at scale: external identity providers and RBAC, multi-organization support and branding, and custom limits with SIEM streaming and SLA support.
Compare tiers on the [Self-Hosted pricing page](https://pangolin.net/pricing#Self-Hosted) to find the right fit.
</Accordion>
<Accordion title="Is self-hosted Enterprise Edition the same as Pangolin Cloud?">
No. Self-hosted Enterprise Edition runs on your own infrastructure with a license key on the `ee` Docker image. [Pangolin Cloud](https://app.pangolin.net/auth/signup) is a managed hosting option with its own pricing tab on the [pricing page](https://pangolin.net/pricing#Self-Hosted). Both offer advanced features, but the deployment model is different.
</Accordion>
<Accordion title="Is Enterprise Edition opt-in?">
Yes. You can continue using the Community Edition indefinitely. Enterprise Edition requires switching to the `ee` Docker image and activating a license key.
</Accordion>
<Accordion title="Can I switch between editions?">
Yes. Switching between Community and Enterprise Edition is a **container swap** — update the Docker image in your `docker-compose.yml` and restart the stack:
- **To Enterprise:** `fosrl/pangolin:ee-latest` (or a pinned `ee-<version>` tag), then activate your license key at `/admin/license`
- **To Community:** `fosrl/pangolin:latest` (or a pinned community tag)
Community and Enterprise Edition share the same database schema, so there should be no data migration issues. You can freely switch between versions to test. Enterprise-only features are disabled when running the Community image.
<Tip>
Always back up your database and configuration before switching editions, just in case.
</Tip>
</Accordion>
<Accordion title="Can I downgrade from Enterprise to Community Edition?">
Yes. Downgrading is a simple container swap:
1. Change your Docker image from `fosrl/pangolin:ee-latest` to `fosrl/pangolin:latest` (or the matching community version tag)
2. Restart the stack: `sudo docker compose down && sudo docker compose up -d`
Community and Enterprise Edition use the **same database schema**, so you should not run into data migration issues. You can freely switch between editions to test. Enterprise-only features will be disabled on the Community image, but your existing data remains intact.
<Tip>
Always make a backup of your database and configuration before switching, just in case.
</Tip>
</Accordion>
<Accordion title="What happens if my license expires?">
If your license expires or becomes invalid:
- Enterprise features will be disabled
- You can renew your license to restore Enterprise features
</Accordion>
<Accordion title="Are there special license terms for educational institutions, non-profits, or government organizations?">
No. Educational institutions, non-profit organizations, and government entities are subject to the same license terms as all other organizations. There are no special exceptions or discounts.
<Info>
If you have questions about how your organization's revenue is calculated for licensing purposes, contact [sales@pangolin.net](mailto:sales@pangolin.net).
</Info>
</Accordion>
</AccordionGroup>
## Support and Contact
For licensing questions and quotes, email [sales@pangolin.net](mailto:sales@pangolin.net). Include your organization details and use case for faster assistance.
@@ -0,0 +1,86 @@
---
title: "Activate a License"
description: "Switch to the Enterprise Edition image and activate a license key"
---
Use these steps after you have a license key from [personal use](/self-host/enterprise-edition/personal-use) or [commercial use](/self-host/enterprise-edition/commercial-use). A new install and an existing Community Edition server follow the same path.
If you install with the [quick installer](/self-host/quick-install), it asks whether you want Enterprise Edition and writes the image for you. You still add the license key once the stack is up.
<Steps>
<Step title="Get a license key">
[Apply for a free license](/self-host/enterprise-edition/personal-use) or [purchase a commercial license](/self-host/enterprise-edition/purchase-license-key), depending on your organization's revenue.
</Step>
<Step title="Use the Enterprise image">
In Docker Compose, the default SQLite image is:
```yaml
services:
pangolin:
image: fosrl/pangolin:ee-latest # Enterprise Edition (SQLite)
# ... rest of configuration
```
If you run PostgreSQL, use the Enterprise PostgreSQL image instead:
```yaml
services:
pangolin:
image: fosrl/pangolin:ee-postgresql-latest # Enterprise Edition (PostgreSQL)
# ... rest of configuration
```
<Warning>
The Enterprise tags are `ee-latest` for SQLite and `ee-postgresql-latest` for PostgreSQL. They are different images from Community Edition (`fosrl/pangolin:latest` and `fosrl/pangolin:postgresql-latest`).
</Warning>
</Step>
<Step title="Restart the stack">
```bash
sudo docker compose down && sudo docker compose up -d
```
</Step>
<Step title="Activate your license key">
Log in with server admin credentials, open the Server Admin panel, and go to the License section at `/admin/license`. Enter the key exactly as you received it. That binds the key to this server's [host ID](#host-id).
</Step>
<Step title="Verify activation">
Confirm the host shows as licensed. If it shows **Unlicensed** while the key itself is valid, check [License limits](/self-host/enterprise-edition/limits).
</Step>
</Steps>
## Host ID
Activating a key binds it to this server. The License page shows the host ID that binding uses, and a key can only be active on one host at a time.
If you rebuild the server, it often comes back with a new host ID. The key is still bound to the old one, so it will not register again until you clear that binding. In your [Pangolin account](https://app.pangolin.net), open the license table, click the three dots on that license, and reset the associated server. Then activate the key on the new host.
## Troubleshooting
<AccordionGroup>
<Accordion title="Admin panel still shows Community Edition">
You're likely running the Community Edition Docker image. Confirm your `docker-compose.yml` uses an Enterprise tag: `fosrl/pangolin:ee-latest` for SQLite, or `fosrl/pangolin:ee-postgresql-latest` if you run PostgreSQL. You can pin a version the same way, for example `fosrl/pangolin:ee-1.14.1` or `fosrl/pangolin:ee-postgresql-1.14.1`. Restart the stack after changing the image:
```bash
sudo docker compose down && sudo docker compose up -d
```
Check container logs if the issue persists:
```bash
sudo docker compose logs pangolin
```
</Accordion>
<Accordion title="No License section in the admin panel">
The License section only appears when the Enterprise Edition image is running. Switch to the `ee` image and restart the stack. See the accordion above.
</Accordion>
<Accordion title="Enterprise settings are missing after activation">
Some features require a valid activated license and additional configuration. Branding and certain identity provider settings need a [`privateConfig.yml`](/self-host/advanced/private-config-file) file mounted in your container. Verify the host license is valid, then check the docs for the feature you are enabling.
If the key is valid and the host still shows **Unlicensed**, you are over a [user or site limit](/self-host/enterprise-edition/limits).
</Accordion>
</AccordionGroup>
@@ -0,0 +1,22 @@
---
title: "Commercial Use"
description: "Paid Enterprise Edition licenses for organizations above the revenue threshold"
---
Organizations with **$100,000+ USD** gross annual revenue need a paid commercial license to use Enterprise Edition. Compare plans on the [features page](/self-host/enterprise-edition/features).
<Info>
Not ready to purchase? Businesses can request a **free limited trial** by emailing [sales@pangolin.net](mailto:sales@pangolin.net). Include your organization details and what you'd like to evaluate.
</Info>
Individuals and organizations under the revenue threshold should [apply for a free license](/self-host/enterprise-edition/personal-use) instead.
## Self-serve purchase
You can buy a **Starter** or **Scale** license online at any time through [app.pangolin.net](https://app.pangolin.net). Follow [Purchase a license key](/self-host/enterprise-edition/purchase-license-key) to choose a tier, complete checkout, and receive your key. Then [activate it](/self-host/enterprise-edition/activate).
## Custom licensing
Need more users, more sites, or add-ons such as compliance packages, SLA support, pay-by-invoice, or bank transfer? Contact [sales@pangolin.net](mailto:sales@pangolin.net).
Custom licenses are for capacity above the Scale tier. Overages can be added monthly and are prorated. Multi-year options are available on request. The [Self-Hosted pricing page](https://pangolin.net/pricing#Self-Hosted) lists the published tiers. Quotes for anything above those tiers come from sales.
@@ -0,0 +1,103 @@
---
title: "Enterprise Edition FAQ"
description: "Common questions about Enterprise Edition licensing, editions, and limits"
---
<AccordionGroup>
<Accordion title="What features does Enterprise Edition include?">
See [Features](/self-host/enterprise-edition/features). The Self-Hosted table on the pricing page is the list of what each plan includes.
</Accordion>
<Accordion title="What are Paid Features?">
Paid Features are the capabilities unlocked by Enterprise Edition with a valid license key. Who pays depends on revenue: [personal use](/self-host/enterprise-edition/personal-use) is free under the threshold, and [commercial use](/self-host/enterprise-edition/commercial-use) is paid above it. The feature list is on the [features page](/self-host/enterprise-edition/features).
</Accordion>
<Accordion title="Can I use Enterprise Edition for personal projects?">
Yes. Individuals and small organizations under the $100,000 USD revenue threshold can use Enterprise Edition for personal projects at no cost. [Apply for a free license](/self-host/enterprise-edition/personal-use).
</Accordion>
<Accordion title="Why would a business pay for self-hosted Enterprise Edition?">
Paid tiers raise limits and unlock the capabilities listed in the [feature comparison](/self-host/enterprise-edition/features). [Commercial use](/self-host/enterprise-edition/commercial-use) covers how to buy a Starter, Scale, or custom license.
</Accordion>
<Accordion title="Is self-hosted Enterprise Edition the same as Pangolin Cloud?">
Self-hosted Enterprise Edition runs on your own infrastructure with a license key on the `ee` Docker image. [Pangolin Cloud](https://app.pangolin.net/auth/signup) is a managed hosting option with its own tab on the [pricing page](https://pangolin.net/pricing#Self-Hosted). Both offer advanced features. The deployment model is different.
</Accordion>
<Accordion title="Is Enterprise Edition opt-in?">
Yes. You can keep using Community Edition. Enterprise Edition means switching to the `ee` Docker image and activating a license key. See [Activate a license](/self-host/enterprise-edition/activate).
</Accordion>
<Accordion title="Can I switch between editions?">
Switching is a container swap. Update the Docker image in your `docker-compose.yml` and restart the stack.
- To Enterprise: `fosrl/pangolin:ee-latest` (or a pinned `ee-<version>` tag), then activate your license key at `/admin/license`
- To Community: `fosrl/pangolin:latest` (or a pinned community tag)
Community and Enterprise Edition share the same database schema, so there is no data migration. Enterprise-only features are disabled on the Community image.
<Tip>
Back up your database and configuration before switching editions.
</Tip>
</Accordion>
<Accordion title="Can I downgrade from Enterprise to Community Edition?">
Yes. Change the Docker image from `fosrl/pangolin:ee-latest` to `fosrl/pangolin:latest` (or the matching community version tag), then restart:
```bash
sudo docker compose down && sudo docker compose up -d
```
The database schema is the same, so existing data stays. Enterprise-only features are disabled on the Community image.
<Tip>
Back up your database and configuration before switching.
</Tip>
</Accordion>
<Accordion title="What happens if my license expires?">
Enterprise features are disabled. Renew the license to turn them back on. This is separate from going over a [user or site limit](/self-host/enterprise-edition/limits), which can show the same red banner while the key itself is still valid.
</Accordion>
<Accordion title="The banner says my license is invalid, but the key shows as valid. What does that mean?">
The red banner reads:
> Invalid or expired license keys detected. Follow license terms to continue using all features.
If the key row is valid and the host shows **Unlicensed**, the usual cause is too many registered users or too many sites. Read [License limits](/self-host/enterprise-edition/limits) before you clear or re-register the key. Re-registering does not fix a capacity violation.
</Accordion>
<Accordion title="Do machine clients count toward the user limit?">
No. Machine clients that authenticate with an ID and secret, and are not tied to a user account, do not count. Devices attached to a person do not count separately either. The registered account does. Details are on [License limits](/self-host/enterprise-edition/limits).
</Accordion>
<Accordion title="Do archived or blocked users count?">
Yes, until you delete the account. Archiving or blocking a device leaves the account in place, and that account still counts.
</Accordion>
<Accordion title="Does a user in more than one organization count once?">
Once. The limit is accounts on the server, not memberships.
</Accordion>
<Accordion title="How many license keys do I need?">
One key per Pangolin server. A server is one database. You cannot share a single key across multiple servers.
You can put more than one key on the same server. Capacity adds together. See [License limits](/self-host/enterprise-edition/limits).
</Accordion>
<Accordion title="Can I get a trial license?">
Businesses that need a paid license can request a free limited trial from [sales@pangolin.net](mailto:sales@pangolin.net). Include your organization details and which features you want to evaluate.
</Accordion>
<Accordion title="What if I'm unsure about my license type?">
Email [sales@pangolin.net](mailto:sales@pangolin.net) with your organization details.
</Accordion>
<Accordion title="Are there special terms for educational institutions, non-profits, or government organizations?">
No. Educational institutions, non-profits, and government organizations follow the same license terms as everyone else and are not considered personal use. There are no separate exceptions. We do offer discounted pricing for some non-profits and government organizations.
<Info>
If you have questions about how your organization's revenue is calculated, contact [sales@pangolin.net](mailto:sales@pangolin.net).
</Info>
</Accordion>
</AccordionGroup>
@@ -0,0 +1,14 @@
---
title: "Features"
description: "Where to compare Enterprise Edition features and plan tiers"
---
The [Self-Hosted pricing comparison](https://pangolin.net/pricing#Self-Hosted-identity-and-access-management) is the source of truth for which features and limits each plan includes.
<Card title="View the feature comparison" icon="table-list" href="https://pangolin.net/pricing#Self-Hosted-identity-and-access-management">
Open the Self-Hosted table on the pricing page.
</Card>
Doc pages for a specific capability note when it requires Enterprise Edition and link back to setup steps for that feature. Search the docs from the pricing table when you want to turn something on.
[Personal use](/self-host/enterprise-edition/personal-use) covers who qualifies for a free license. [Commercial use](/self-host/enterprise-edition/commercial-use) covers paid tiers. [License limits](/self-host/enterprise-edition/limits) explains how users and sites are counted.
@@ -0,0 +1,55 @@
---
title: "Enterprise Edition"
description: "Licensing, plans, and how to get started with self-hosted Enterprise Edition"
---
When self-hosting Pangolin, you can run the **Community Edition** or the **Enterprise Edition**. Both editions provide the same core functionality. Enterprise Edition unlocks additional features with a license key on the `ee` Docker image.
<Check>
Enterprise Edition is **free** for personal use and organizations with **less than $100,000 USD** gross annual revenue. You still need a valid license key to activate it.
</Check>
<Warning>
Organizations with **$100,000+ USD** gross annual revenue require a **paid commercial license** to use Enterprise Edition.
</Warning>
<CardGroup cols={2}>
<Card title="Personal use" icon="user" href="/self-host/enterprise-edition/personal-use">
Free license for individuals and organizations under the revenue threshold.
</Card>
<Card title="Commercial use" icon="building" href="/self-host/enterprise-edition/commercial-use">
Paid licenses for organizations above the revenue threshold.
</Card>
<Card title="Features" icon="table-list" href="/self-host/enterprise-edition/features">
Compare what each plan includes on the pricing page.
</Card>
<Card title="License limits" icon="chart-bar" href="/self-host/enterprise-edition/limits">
How users and sites are counted, and what the red license banner means.
</Card>
<Card title="Activate a license" icon="key" href="/self-host/enterprise-edition/activate">
Switch to the Enterprise image and add your key.
</Card>
<Card title="Purchase a license" icon="credit-card" href="/self-host/enterprise-edition/purchase-license-key">
Buy a Starter or Scale key from the dashboard.
</Card>
</CardGroup>
## Hiding Enterprise features on Community Edition
On Community Edition, Enterprise-only capabilities may still appear in the dashboard but remain locked without the `ee` Docker image and a valid license key. To hide those UI elements entirely, set `disable_enterprise_features` under `flags` in your [`config.yml`](/self-host/advanced/config-file):
```yaml
flags:
disable_enterprise_features: true
```
When enabled, Enterprise-only features are hidden from the UI. Restart the stack after updating the configuration file.
## Support and contact
For licensing questions and quotes, email [sales@pangolin.net](mailto:sales@pangolin.net). Include your organization details and use case.
@@ -0,0 +1,49 @@
---
title: "License Limits"
description: "How Enterprise Edition counts users and sites, and what happens when you go over"
---
A self-hosted Enterprise license has two capacity numbers: **users** and **sites**. The quantities are on your license key. Published tier ceilings are on the [Self-Hosted pricing page](https://pangolin.net/pricing#Self-Hosted). This page explains how those numbers are counted.
The host license is invalid when registered users **exceed** the user quantity, or sites **exceed** the site quantity. Matching the limit exactly is allowed.
## How users are counted
Every registered account counts, whether or not that person has ever connected a device or is online right now.
The count is one row per account on the server, across every organization. A person who belongs to more than one organization counts **once**. Server admin accounts count, because they are accounts on the server.
Accounts that have never registered a device or logged in still count. Archiving or blocking a device does not remove the account.
### What does not count as a user
- **Machine clients** authenticate with an ID and secret and are not tied to a user account. They do not count.
- **Person clients** (devices) do not count on their own. The account they belong to is what counts, even if that account has several devices.
- **Concurrent sessions** are not checked against the license.
## How sites are counted
Every site on the server counts, across every organization.
## Where to see the numbers
- **Server Admin**, **Users** (`/admin/users`): the flattened account list for the whole server, not per organization.
- **Server Admin**, **License** (`/admin/license`): usage against the key, shown as used users out of the licensed maximum, and the same for sites.
## More than one key on the same server
Each Pangolin server (one database) needs its own license. You cannot share one key across servers.
You can activate more than one key on the **same** server. User quantities add together, and site quantities add together. The host uses the highest tier among the valid keys.
A personal-use key does not add capacity when a paid key is also active on that server. The personal key is ignored for the totals.
## When you are over the limit
The key itself can still say valid. The host shows **Unlicensed**, and a red banner sits along the bottom of the dashboard:
> Invalid or expired license keys detected. Follow license terms to continue using all features.
Enterprise features that need a valid license stay unavailable until you are back within the quantities on the key, and a license left over the limit can be revoked.
Delete accounts or sites until you are at or under the licensed quantity, or add capacity with a higher tier or another key on the same server. See [Commercial use](/self-host/enterprise-edition/commercial-use).
@@ -0,0 +1,40 @@
---
title: "Personal Use"
description: "Free Enterprise Edition licenses for personal use and small organizations"
---
Enterprise Edition is free for individuals and organizations with **less than $100,000 USD** gross annual revenue. Personal and small-business use is allowed.
You still need to apply for a valid license key. The free license does not activate on its own.
Apply on [app.pangolin.net](https://app.pangolin.net). Create an account and an organization there so we can track your application and keep the license key. You can sign back in later to copy the key or check usage, then activate it on your own server.
Signing up also starts a free Pangolin Cloud trial, and you may get emails about it. That trial is separate from your license key. If you only want to self-host, you can ignore Cloud.
Organizations at or above the revenue threshold need a [paid commercial license](/self-host/enterprise-edition/commercial-use) instead.
## Get a free license
<Steps>
<Step title="Create an account">
Visit [app.pangolin.net](https://app.pangolin.net) and create your account. This is the account we use to track your application and license key.
</Step>
<Step title="Create an organization">
After signing up you will be prompted to create an organization. The license application is filed against that organization, so it is required even if you only run one self-hosted server.
</Step>
<Step title="Complete the license application">
Go to the **Licenses** section in your account dashboard and complete the license application form.
<Warning>
Inaccurate representation is a violation of the license and will result in the license being revoked.
</Warning>
</Step>
<Step title="Receive your key">
Once approved, you'll receive your license key immediately. Continue to [Activate a license](/self-host/enterprise-edition/activate) to use it on your server.
</Step>
</Steps>
See [Features](/self-host/enterprise-edition/features) for what the license unlocks, and [License limits](/self-host/enterprise-edition/limits) for how users and sites are counted.
@@ -3,7 +3,7 @@ title: "Purchase a License Key"
description: "How to buy an Enterprise license key for Pangolin from the dashboard"
---
Buy an Enterprise license key directly from the Pangolin dashboard. You choose your tier, complete checkout, and get your key right away — in the dashboard and by email.
Buy an Enterprise license key directly from the Pangolin dashboard or the pricing page at [pangolin.net/pricing](https://pangolin.net/pricing). You choose your tier, complete checkout, and get your key right away.
## License tiers
@@ -55,7 +55,7 @@ Need more users, more sites, or special add-ons — such as compliance packages,
<AccordionGroup>
<Accordion title="I reset my host and can’t re-register my key. What do I do?">
A license is tied to one host (by host ID) at a time. If you reset your instance and need to use the same key on a new host, contact us at [support@pangolin.net](mailto:support@pangolin.net) and we’ll reset it for you.
A license is tied to one host (by host ID) at a time. If you reset your instance and need the same key on a new host, open the license table in your [Pangolin account](https://app.pangolin.net), click the three dots on that license, and reset the associated server. Then register the key on the new host. See [Host ID](/self-host/enterprise-edition/activate#host-id).
</Accordion>
<Accordion title="How do I cancel my subscription?">
+2 -2
View File
@@ -11,8 +11,8 @@ This page covers updating your self-hosted Pangolin server. To update sites and
<Card title="Update Sites" icon="plug" href="/manage/sites/update-site">
Update sites to the latest version.
</Card>
<Card title="Update Clients" icon="desktop" href="/manage/clients/update-client">
Update your installed client to the latest version.
<Card title="Platforms" icon="desktop" href="/manage/clients/platforms">
Update the client for each platform.
</Card>
</CardGroup>
+1 -1
View File
@@ -4,7 +4,7 @@
Wherever these instructions show `<key>`, what you put there depends on the resource type:
- **Public resource** - reachable from anywhere, so the gateway checks a [virtual API key](/manage/ai/virtual-api-keys). Copy it from the resource URL after login, the Resource Launcher more-info panel, or `https://app.pangolin.net/<org-id>/keys` (use your self-hosted dashboard URL in place of `app.pangolin.net` if you self-host).
- **Private resource** - only reachable from devices connected to your Pangolin network, so no key is checked. You must have the [Pangolin client](/manage/clients/install-client) installed and connected. Use the literal string `none` as the key.
- **Private resource** - only reachable from devices connected to your Pangolin network, so no key is checked. You must have the [Pangolin client](/manage/clients/platforms) installed and connected. Use the literal string `none` as the key.
Don't delete the key field for private resources. Most clients refuse to start without *some* key set, so they need an inert placeholder rather than a missing one.
</Note>
+27 -4
View File
@@ -63,6 +63,7 @@
"pages": [
"manage/resources/private/host",
"manage/resources/private/cidr",
"manage/resources/private/exit-node",
"manage/resources/private/private-http",
"manage/resources/private/ai-gateway",
"manage/resources/private/ssh",
@@ -81,10 +82,20 @@
"pages": [
"manage/clients/understanding-clients",
"manage/clients/nat-traversal",
"manage/clients/install-client",
"manage/clients/configure-client",
{
"group": "Platforms",
"index": "manage/clients/platforms",
"pages": [
"manage/clients/platforms/windows",
"manage/clients/platforms/mac",
"manage/clients/platforms/ios",
"manage/clients/platforms/android",
"manage/clients/platforms/cli",
"manage/clients/platforms/olm"
]
},
"manage/clients/client-logs",
"manage/clients/update-client",
"manage/clients/subnet-router",
"manage/clients/credentials",
"manage/clients/fingerprinting",
"manage/clients/archiving-blocking",
@@ -325,7 +336,19 @@
"self-host/community-guides/geolite2automation"
]
},
"self-host/enterprise-edition"
{
"group": "Enterprise Edition",
"index": "self-host/enterprise-edition",
"pages": [
"self-host/enterprise-edition/personal-use",
"self-host/enterprise-edition/commercial-use",
"self-host/enterprise-edition/features",
"self-host/enterprise-edition/limits",
"self-host/enterprise-edition/activate",
"self-host/enterprise-edition/purchase-license-key",
"self-host/enterprise-edition/faq"
]
}
]
},
{
+8 -1
View File
@@ -12,6 +12,8 @@ type NavItem = string | NavGroup;
interface NavGroup {
group: string;
icon?: string;
/** When set, the folder label links to this page (usually the folder index). */
index?: string;
pages: NavItem[];
}
@@ -51,11 +53,13 @@ function buildItems(items: NavItem[], idPrefix: string): PageTree.Node[] {
}
const id = `${idPrefix}/${item.group}`;
const index = item.index ? pageNode(item.index) : null;
out.push({
$id: id,
type: 'folder',
name: item.group,
icon: item.icon ? <Icon name={item.icon} /> : undefined,
index: index ?? undefined,
children: buildItems(item.pages, id),
});
}
@@ -84,7 +88,10 @@ export function getOrderedPagePaths(): string[] {
function walk(items: NavItem[]) {
for (const item of items) {
if (typeof item === 'string') seen.add(item);
else walk(item.pages);
else {
if (item.index) seen.add(item.index);
walk(item.pages);
}
}
}
walk(navigation.groups as NavGroup[]);
+50
View File
@@ -78,5 +78,55 @@
"source": "/manage/ai/openclaw",
"destination": "/manage/ai/configure-ai-clients/openclaw",
"permanent": false
},
{
"source": "/self-host/purchase-license-key",
"destination": "/self-host/enterprise-edition/purchase-license-key",
"permanent": true
},
{
"source": "/manage/clients/install-client",
"destination": "/manage/clients/platforms",
"permanent": true
},
{
"source": "/manage/clients/update-client",
"destination": "/manage/clients/platforms",
"permanent": true
},
{
"source": "/manage/clients/configure-client",
"destination": "/manage/clients/platforms",
"permanent": true
},
{
"source": "/manage/clients/configure-client/windows",
"destination": "/manage/clients/platforms/windows",
"permanent": true
},
{
"source": "/manage/clients/configure-client/mac",
"destination": "/manage/clients/platforms/mac",
"permanent": true
},
{
"source": "/manage/clients/configure-client/ios",
"destination": "/manage/clients/platforms/ios",
"permanent": true
},
{
"source": "/manage/clients/configure-client/android",
"destination": "/manage/clients/platforms/android",
"permanent": true
},
{
"source": "/manage/clients/configure-client/cli",
"destination": "/manage/clients/platforms/cli",
"permanent": true
},
{
"source": "/manage/clients/configure-client/olm",
"destination": "/manage/clients/platforms/olm",
"permanent": true
}
]
+1 -1
View File
@@ -4,7 +4,7 @@
"private": true,
"scripts": {
"build": "next build",
"dev": "next dev",
"dev": "next dev --port 4000",
"start": "next start",
"types:check": "next typegen && tsc --noEmit",
"migrate": "python3 scripts/migrate-from-mintlify.py ../docs-v2"
Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB