Merge branch 'main' into v1_0_0

This commit is contained in:
Michael Quigley 2025-01-08 17:03:53 -05:00
commit be0bf95226
No known key found for this signature in database
GPG Key ID: 9B60314A9DD20A62
26 changed files with 362 additions and 181 deletions

View File

@ -14,7 +14,7 @@ jobs:
matrix:
spec:
- { name: 'linux x86_64', runner: ubuntu-20.04, target: manylinux_2_27_x86_64 }
- { name: 'macOS x86_64', runner: macos-12, target: macosx_10_14_x86_64 }
- { name: 'macOS x86_64', runner: macos-13, target: macosx_10_14_x86_64 }
- { name: 'Windows x86_64', runner: windows-2019, target: win_amd64 }
name: building ${{ matrix.spec.name }}
runs-on: ${{ matrix.spec.runner }}
@ -68,12 +68,12 @@ jobs:
uses: pypa/gh-action-pypi-publish@release/v1
with:
repository-url: https://test.pypi.org/legacy/
packages_dir: dist
skip_existing: true
packages-dir: dist
skip-existing: true
verbose: true
- name: Publish wheels (PyPI)
uses: pypa/gh-action-pypi-publish@release/v1
with:
packages_dir: dist
verbose: true
packages-dir: dist
verbose: true

View File

@ -227,7 +227,7 @@ jobs:
build-darwin:
if: github.repository_owner == 'openziti' || vars.ZROK_SKIP_MACOS_BUILD == 'false'
runs-on: macos-latest
runs-on: macos-14
steps:
- name: import distribution cert
uses: apple-actions/import-codesign-certs@v3

View File

@ -109,6 +109,9 @@ nfpms:
- dst: /lib/systemd/system/
src: ./nfpm/zrok-share.service
- dst: /usr/lib/systemd/user/
src: ./nfpm/zrok-share@.service
- dst: /etc/systemd/system/zrok-share.service.d/override.conf
src: ./nfpm/zrok-share.service.override.conf

View File

@ -113,6 +113,9 @@ nfpms:
- dst: /lib/systemd/system/
src: ./nfpm/zrok-share.service
- dst: /usr/lib/systemd/user/
src: ./nfpm/zrok-share@.service
- dst: /etc/systemd/system/zrok-share.service.d/override.conf
src: ./nfpm/zrok-share.service.override.conf

View File

@ -117,6 +117,9 @@ nfpms:
- dst: /lib/systemd/system/
src: ./nfpm/zrok-share.service
- dst: /usr/lib/systemd/user/
src: ./nfpm/zrok-share@.service
- dst: /etc/systemd/system/zrok-share.service.d/override.conf
src: ./nfpm/zrok-share.service.override.conf

View File

@ -115,6 +115,9 @@ nfpms:
- dst: /lib/systemd/system/
src: ./nfpm/zrok-share.service
- dst: /usr/lib/systemd/user/
src: ./nfpm/zrok-share@.service
- dst: /etc/systemd/system/zrok-share.service.d/override.conf
src: ./nfpm/zrok-share.service.override.conf

View File

@ -12,9 +12,25 @@ FEATURE: `zrok share [public|private|reserved]` and `zrok access private` now au
FEATURE `zrok access private` supports a new `--auto` mode, which can automatically find an available open address/port to bind the frontend listener on. Also includes `--auto-address`, `--auto-start-port`, and `--auto-end-port` features with sensible defaults. Supported by both the agent and local operating modes (https://github.com/openziti/zrok/issues/780)
## v0.4.46
FEATURE: Linux service template for systemd user units (https://github.com/openziti/zrok/pull/818)
FIX: Docker share examples had incorrect default path for zrok environment mountpoint
FIX: Clarify how to use DNS providers like Route53 with the zrok Docker instance sample.
CHANGE: Use port 80 for the default Ziti API endpoint in the zrok Docker instance sample (https://github.com/openziti/zrok/issues/793).
CHANGE: Clarify OS requirements for zrok VPN
CHANGE: Set the Windows executable search path in the Windows install guide.
CHANGE: bump macOS runner for Python module from macos-12 to macos-13
## v0.4.45
FEATURE: Minimal support for "organizations". Site admin API endpoints provided to create, list, and delete "organizations". Site admin API endpoints provided to add, list, and remove "organization members" (zrok accounts) with the ability to mark accounts as a "organization admin". API endpoints provided for organization admins to list the members of their organizations, and to also see the overview (environments, shares, and accesses) for any account in their organization. API endpoint for end users to see which organizations their account is a member of (https://github.com/openziti/zrok/issues/537)
FEATURE: Minimal support for "organizations". Site admin API endpoints provided to create, list, and delete "organizations". Site admin API endpoints provided to add, list, and remove "organization members" (zrok accounts) with the ability to mark accounts as a "organization admin". API endpoints provided for organization admins to list the members of their organizations, and to also see the overview (environments, shares, and accesses) for any account in their organization. API endpoint for end users to see which organizations their account is a member of (https://github.com/openziti/zrok/issues/537)
CHANGE: briefly mention the backend modes that apply to public and private share concepts
@ -28,7 +44,6 @@ FIX: Docker reserved private share startup error (https://github.com/openziti/zr
FIX: Correct the download URL for the armv7 Linux release (https://github.com/openziti/zrok/issues/782)
## v0.4.44
FIX: Fix for goreleaser build action to align with changed ARM64 build path.

View File

@ -4,9 +4,9 @@
admin 0.0.0.0:2019
}
http:// {
redir https://{host}{uri} permanent
}
# http:// {
# redir https://{host}{uri} permanent
# }
*.{$ZROK_DNS_ZONE} {
tls {
@ -22,7 +22,7 @@ http:// {
# ziti administration console uses :443 for the benefit of a web UI cert and accesses the ziti edge-management API
@ziti host ziti.{$ZROK_DNS_ZONE}
reverse_proxy @ziti ziti-quickstart:{$ZITI_CTRL_ADVERTISED_PORT:1280} {
reverse_proxy @ziti ziti-quickstart:{$ZITI_CTRL_ADVERTISED_PORT:80} {
transport http {
tls_insecure_skip_verify
}

View File

@ -65,6 +65,10 @@ ZROK_ADMIN_TOKEN=zroktoken
```bash title=".env options"
# Caddy TLS option: rename compose.caddy.yml to compose.override.yml and set these vars; allow 80,443 in firewall
#
## set these in .env for providers other than Route53
#
# plugin name for your DNS provider
CADDY_DNS_PLUGIN=cloudflare
# API token from your DNS provider
@ -72,22 +76,34 @@ CADDY_DNS_PLUGIN_TOKEN=abcd1234
# use the staging API until you're sure everything is working to avoid hitting the rate limit
CADDY_ACME_API=https://acme-staging-v02.api.letsencrypt.org/directory
# no TLS option: publish the insecure ports to the internet and allow them in the firewall
ZROK_INSECURE_INTERFACE=0.0.0.0
#
## set these in .env for Route53
#
# AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID}
# AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY}
# AWS_REGION: ${AWS_REGION}
# AWS_SESSION_TOKEN: ${AWS_SESSION_TOKEN} # if temporary credential, e.g., from STS
#
## if not using Caddy for TLS, uncomment to publish the insecure ports to the internet
#
#ZROK_INSECURE_INTERFACE=0.0.0.0
# these insecure ports must be proxied with TLS for security
ZROK_CTRL_PORT=18080
ZROK_FRONTEND_PORT=8080
ZROK_OAUTH_PORT=8081
# ziti ports must be published to the internet and allowed by firewall
ZITI_CTRL_ADVERTISED_PORT=1280
# these secure ziti ports must be published to the internet
ZITI_CTRL_ADVERTISED_PORT=80
ZITI_ROUTER_PORT=3022
# configure oauth for public shares
ZROK_OAUTH_HASH_KEY=oauthhashkeysecret
ZROK_OAUTH_GITHUB_CLIENT_ID=abcd1234
ZROK_OAUTH_GITHUB_CLIENT_SECRET=abcd1234
ZROK_OAUTH_GOOGLE_CLIENT_ID=abcd1234
ZROK_OAUTH_GOOGLE_CLIENT_SECRET=abcd1234
# optionally configure oauth for public shares
#ZROK_OAUTH_HASH_KEY=oauthhashkeysecret
#ZROK_OAUTH_GITHUB_CLIENT_ID=abcd1234
#ZROK_OAUTH_GITHUB_CLIENT_SECRET=abcd1234
#ZROK_OAUTH_GOOGLE_CLIENT_ID=abcd1234
#ZROK_OAUTH_GOOGLE_CLIENT_SECRET=abcd1234
# zrok version, e.g., 1.0.0
ZROK_CLI_TAG=latest
@ -157,14 +173,13 @@ The `ziti-quickstart` and `caddy` containers publish ports to all devices that u
#### Required
1. `443/tcp` - reverse proxy handles HTTPS requests for zrok API, OAuth, and public shares (published by container `caddy`)
1. `1280/tcp` - ziti ctrl plane (published by container `ziti-quickstart`)
1. `80/tcp` - ziti ctrl plane (published by container `ziti-quickstart`)
1. `3022/tcp` - ziti data plane (published by container `ziti-quickstart`)
#### Optional
1. `80/tcp` - reverse proxy redirects non-HTTPS requests to `443/tcp` (published by container `caddy`)
<!-- 1. 443/udp used by Caddy for HTTP/3 QUIC protocol (published by container `caddy`) -->
See "My internet connection can only send traffic to common ports" below about changing the required ports.
### Troubleshooting
1. Check the ziti and zrok logs.
@ -222,21 +237,19 @@ The `ziti-quickstart` and `caddy` containers publish ports to all devices that u
docker compose exec caddy curl http://localhost:2019/config/ | jq
```
1. My provider, e.g., Route53 doesn't give me a single API token.
1. My DNS provider credential is composed of several values, not a single API token.
As long as your DNS provider is supported by Caddy then it will work. You can modify the Caddyfile to use a different set of properties than the example. Here's how the `tls` section should look for Route53. You must declare any environment variables introduced in the `.env` file in `docker.compose.override` on the `caddy` service to ensure they are passed through to the Caddy container.
As long as your DNS provider is supported by Caddy then it will work. Here's a checklist for DNS providers like Route53 with credentials expressed as multiple values, e.g., `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`.
```json
tls {
dns {$CADDY_DNS_PLUGIN} {
access_key_id {$AWS_ACCESS_KEY_ID}
secret_access_key {$AWS_SECRET_ACCESS_KEY}
}
}
```
1. Define env vars in `.env` file.
1. Declare env vars in `compose.override.yml` file on `caddy`'s `environment`.
1. Modify `Caddyfile` according to the DNS plugin author's instructions ([link to Route53 README](https://github.com/caddy-dns/route53)). This means modifying the `Caddyfile` to reference the env vars. The provided file `route53.Caddyfile` serves as an example.
1. My internet connection can only send traffic to common ports like 80, 443, and 3389.
You can change the required ports in the `.env` file. Caddy will still use port 443 for zrok shares and API if you renamed `compose.caddy.yml` as `compose.override.yml` to enable Caddy.
```bash title=".env"
CADDY_DNS_PLUGIN=route53
AWS_ACCESS_KEY_ID=abcd1234
AWS_SECRET_ACCESS_KEY=abcd1234
ZITI_CTRL_ADVERTISED_PORT=80
ZITI_ROUTER_PORT=3389
```

View File

@ -8,8 +8,21 @@ services:
CADDY_DNS_PLUGIN: ${CADDY_DNS_PLUGIN} # e.g., "digitalocean" (see github.com/caddy-dns)
restart: unless-stopped
environment:
#
## set these in .env for providers other than Route53
#
CADDY_DNS_PLUGIN: ${CADDY_DNS_PLUGIN} # e.g., "digitalocean" (see github.com/caddy-dns)
CADDY_DNS_PLUGIN_TOKEN: ${CADDY_DNS_PLUGIN_TOKEN} # API token from DNS provider used by plugin to solve the ACME challenge
#
## for DNS providers like Route53 with multiple credential variables, you must define in .env and declare
## here before referencing them in the Caddyfile
#
# AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID}
# AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY}
# AWS_REGION: ${AWS_REGION}
# AWS_SESSION_TOKEN: ${AWS_SESSION_TOKEN} # if temporary credential, e.g., from STS
ZROK_USER_EMAIL: ${ZROK_USER_EMAIL} # email address sent to CA for ACME account and renewal notifications
CADDY_ACME_API: ${CADDY_ACME_API:-https://acme-v02.api.letsencrypt.org/directory} # ACME API endpoint
ZROK_DNS_ZONE: ${ZROK_DNS_ZONE} # e.g., "example.com" or "127.0.0.1.sslip.io"
@ -17,12 +30,12 @@ services:
ZROK_FRONTEND_PORT: ${ZROK_FRONTEND_PORT:-8080}
ZROK_OAUTH_PORT: ${ZROK_OAUTH_PORT:-8081}
expose:
- 80/tcp
# - 80/tcp
- 443/tcp
- 443/udp # Caddy's HTTP/3 (QUIC) (not published)
- 2019/tcp # Caddy's admin API (not published)
ports:
- ${CADDY_INTERFACE:-0.0.0.0}:80:80
# - ${CADDY_INTERFACE:-0.0.0.0}:80:80
- ${CADDY_INTERFACE:-0.0.0.0}:443:443
# - ${CADDY_INTERFACE:-0.0.0.0}:443:443/udp" # future: HTTP/3 (QUIC)
volumes:

View File

@ -14,7 +14,7 @@ services:
- -euc
- |
ZITI_CMD+=" --ctrl-address ziti.${ZROK_DNS_ZONE}"\
" --ctrl-port ${ZITI_CTRL_ADVERTISED_PORT:-1280}"\
" --ctrl-port ${ZITI_CTRL_ADVERTISED_PORT:-80}"\
" --router-address ziti.${ZROK_DNS_ZONE}"\
" --router-port ${ZITI_ROUTER_PORT:-3022}"\
" --password ${ZITI_PWD:-admin}"
@ -31,10 +31,10 @@ services:
# directory, ZITI_HOME
- ${ZITI_HOME:-ziti_home}:/home/ziggy
ports:
- ${ZITI_INTERFACE:-0.0.0.0}:${ZITI_CTRL_ADVERTISED_PORT:-1280}:${ZITI_CTRL_ADVERTISED_PORT:-1280}
- ${ZITI_INTERFACE:-0.0.0.0}:${ZITI_CTRL_ADVERTISED_PORT:-80}:${ZITI_CTRL_ADVERTISED_PORT:-80}
- ${ZITI_INTERFACE:-0.0.0.0}:${ZITI_ROUTER_PORT:-3022}:${ZITI_ROUTER_PORT:-3022}
expose:
- ${ZITI_CTRL_ADVERTISED_PORT:-1280}
- ${ZITI_CTRL_ADVERTISED_PORT:-80}
- ${ZITI_ROUTER_PORT:-3022}
depends_on:
ziti-quickstart-init:
@ -94,7 +94,7 @@ services:
ZROK_CLI_IMAGE: ${ZROK_CLI_IMAGE:-openziti/zrok}
ZROK_CLI_TAG: ${ZROK_CLI_TAG:-latest}
ZROK_DNS_ZONE: ${ZROK_DNS_ZONE} # e.g., "example.com" or "127.0.0.1.sslip.io"
ZITI_CTRL_ADVERTISED_PORT: ${ZITI_CTRL_ADVERTISED_PORT:-1280}
ZITI_CTRL_ADVERTISED_PORT: ${ZITI_CTRL_ADVERTISED_PORT:-80}
ZROK_ADMIN_TOKEN: ${ZROK_ADMIN_TOKEN} # zrok controller admin password
ZROK_CTRL_PORT: ${ZROK_CTRL_PORT:-18080}
ZITI_PWD: ${ZITI_PWD} # ziti controller admin password
@ -155,7 +155,7 @@ services:
ZROK_API_ENDPOINT: http://zrok-controller:${ZROK_CTRL_PORT:-18080} # bridge address of the zrok controller
ZROK_FRONTEND_SCHEME: http
ZROK_FRONTEND_PORT: ${ZROK_FRONTEND_PORT:-8080}
ZITI_CTRL_ADVERTISED_PORT: ${ZITI_CTRL_ADVERTISED_PORT:-1280}
ZITI_CTRL_ADVERTISED_PORT: ${ZITI_CTRL_ADVERTISED_PORT:-80}
ZITI_PWD: ${ZITI_PWD} # ziti controller admin password
volumes:

View File

@ -0,0 +1,51 @@
{
email {$ZROK_USER_EMAIL}
acme_ca {$CADDY_ACME_API}
admin 0.0.0.0:2019
}
# http:// {
# redir https://{host}{uri} permanent
# }
*.{$ZROK_DNS_ZONE} {
tls {
dns route53 {
access_key_id {$AWS_ACCESS_KEY_ID}
secret_access_key {$AWS_SECRET_ACCESS_KEY}
session_token {$AWS_SESSION_TOKEN}
region {$AWS_REGION}
# profile {$AWS_PROFILE}
# max_retries 10
# max_wait_dur 60
# wait_for_propagation false
# hosted_zone_id {$AWS_HOSTED_ZONE_ID}
}
propagation_timeout 60m
}
log {
output stdout
format console
level INFO
}
# ziti administration console uses :443 for the benefit of a web UI cert and accesses the ziti edge-management API
@ziti host ziti.{$ZROK_DNS_ZONE}
reverse_proxy @ziti ziti-quickstart:{$ZITI_CTRL_ADVERTISED_PORT:80} {
transport http {
tls_insecure_skip_verify
}
}
@oauth host oauth.{$ZROK_DNS_ZONE}
reverse_proxy @oauth zrok-frontend:{$ZROK_OAUTH_PORT}
@ctrl host zrok.{$ZROK_DNS_ZONE}
reverse_proxy @ctrl zrok-controller:{$ZROK_CTRL_PORT}
reverse_proxy zrok-frontend:{$ZROK_FRONTEND_PORT} {
header_up Host {http.request.host}
}
}

View File

@ -1,42 +1,10 @@
import LinuxShareInstall from './_linux-share-install.mdx'
import AnsibleRepoSetup from './install/_ansible_repo_setup.yaml'
import ConcatenateYamlSnippets from '@site/src/components/cat-yaml.jsx'
## Goal
Proxy a reserved public subdomain to a backend target with an always-on Linux system service.
## How it Works
The `zrok-share` package creates a `zrok-share.service` unit in systemd. The administrator edits the service's configuration file to specify the:
1. zrok environment enable token
1. target URL or files to be shared and backend mode, e.g. `proxy`
1. authentication options, if wanted
When the service starts it will:
1. enable the zrok environment unless `/var/lib/zrok-share/.zrok/environment.json` exists
1. reserve a public subdomain for the service unless `/var/lib/zrok-share/.zrok/reserved.json` exists
1. start sharing the target specified as `ZROK_TARGET` in the environment file
## Installation
1. Set up `zrok`'s Linux package repository by following [the Linux install guide](/guides/install/linux.mdx#install-zrok-from-the-repository), or run this one-liner to complete the repo setup and install packages.
```bash
curl -sSLf https://get.openziti.io/install.bash \
| sudo bash -s zrok-share
```
1. If you set up the repository by following the guide, then also install the `zrok-share` package. This package provides the systemd service.
```bash title="Ubuntu, Debian"
sudo apt install zrok-share
```
```bash title="Fedora, Rocky"
sudo dnf install zrok-share
```
<LinuxShareInstall />
<Details>
<summary>Ansible Playbook</summary>

View File

@ -0,0 +1,17 @@
1. Set up `zrok`'s Linux package repository by following [the Linux install guide](/guides/install/linux.mdx#install-zrok-from-the-repository), or run this one-liner to complete the repo setup and install packages.
```bash
curl -sSLf https://get.openziti.io/install.bash \
| sudo bash -s zrok-share
```
1. If you set up the repository by following the guide, then also install the `zrok-share` package. This package provides the systemd service.
```bash title="Ubuntu, Debian"
sudo apt install zrok-share
```
```bash title="Fedora, Rocky"
sudo dnf install zrok-share
```

View File

@ -94,7 +94,7 @@ Now that we have a private share we can access it with the zrok command or by ru
1. Run your Compose project to start accessing the private share:
```bash
docker compose up zrok-private-access
docker compose up zrok-access
```
1. Now your zrok private access proxy is ready on http://127.0.0.1:9191. You can visit the demo web server in your browser.

View File

@ -26,7 +26,7 @@ Let's say you have a `compose.yml` file that defines a web app known within the
restart: unless-stopped
user: "${UID}"
volumes:
- ${HOME}/.zrok:/.zrok
- ${HOME}/.zrok:/home/ziggy/.zrok
environment:
PFXLOG_NO_JSON: "true"
command: share reserved "myapp" --headless
@ -42,8 +42,8 @@ Let's say you have a web server running on the host's private network at `https:
docker run \
--rm \
--network=host \
--volume ~/.zrok:/.zrok \
--user "${UID}" \
--volume ~/.zrok:/home/ziggy/.zrok \
--user "${UID:-1000}:${GID:-1000}" \
openziti/zrok share public \
--headless \
https://10.11.12.13:8080
@ -89,8 +89,8 @@ docker.exe run ^
docker run \
--rm \
--network "host" \
--volume "/mnt/c/Users/$(powershell.exe -Command 'Write-Output $env:USERNAME' | tr -d '\r')/.zrok:/.zrok" \
--user "$UID" \
--volume "/mnt/c/Users/$(powershell.exe -Command 'Write-Output $env:USERNAME' | tr -d '\r')/.zrok:/home/ziggy/.zrok" \
--user "${UID:-1000}:${GID:-1000}" \
openziti/zrok share public \
--headless \
https://10.11.12.13:8080
@ -104,8 +104,8 @@ Let's break down those options and arguments.
1. `--rm` don't save this container because it's providing a temporary public share that's destroyed when the container stops
1. `--network=host` shares the host's network with the container so that the container can reach the web server directly. This is always necessary when the web server is listening only on the host's loopback interface, e.g., `https://::1:8080`, and may not be strictly necessary if the target is routeable from the default Docker bridge.
1. `--volume ~/.zrok:/.zrok` mounts the `zrok` configuration from the Docker host into the container.
1. `--user "${UID}:${GID}"` sets the container's user to the current user on the Docker host to avoid permission issues with reading the mounted `zrok` configuration.
1. `--volume ~/.zrok:/home/ziggy/.zrok` mounts the `zrok` configuration from the Docker host into the container.
1. `--user "${UID:-1000}:${GID:-1000}"` sets the container's user to the current user on the Docker host to avoid permission issues with reading the mounted `zrok` configuration (defaults to `1000:1000`).
1. `openziti/zrok` is the `zrok` Docker image.
1. `share public` is the `zrok` command to share the target publicly until zrok exits.
1. `--headless` runs the `zrok` command without the interactive terminal UI.

View File

@ -46,7 +46,25 @@ the detected OS of the visitor's browser */}
On Linux, zrok frontdoor is implemented natively as a system service provided by the `zrok-share` DEB or RPM package.
<LinuxService/>
## Goal
Proxy a reserved public subdomain to a backend target with an always-on Linux system service.
## How it Works
The `zrok-share` package creates a `zrok-share.service` unit in systemd. The administrator edits the service's configuration file to specify the:
1. zrok account token
1. target URL or files to be shared and backend mode, e.g. `proxy`
1. authentication options, if wanted
When the service starts it will:
1. enable the zrok environment unless `/var/lib/zrok-share/.zrok/environment.json` exists
1. reserve a public subdomain for the service unless `/var/lib/zrok-share/.zrok/reserved.json` exists
1. start sharing the target specified as `ZROK_TARGET` in the environment file
<LinuxService/>
</TabItem>

View File

@ -18,21 +18,19 @@ import styles from '@site/src/css/download-card.module.css';
</div>
</AssetsProvider>
1. Unarchive the distribution in a temporary directory:
1. In PowerShell, install in `%USERPROFILE%\bin\zrok.exe` and set the search path.
```text
New-Item -Path "$env:TEMP\zrok" -ItemType Directory -ErrorAction Stop
tar -xf .\zrok*windows*.tar.gz -C "$env:TEMP\zrok"
```
1. Install the `zrok` executable and include HOME\bin in the search PATH.
```text
$source = Join-Path -Path $env:TEMP -ChildPath "zrok\zrok.exe"
$destination = Join-Path -Path $env:USERPROFILE -ChildPath "bin\zrok.exe"
New-Item -Path $destination -ItemType Directory -ErrorAction SilentlyContinue
Copy-Item -Path $source -Destination $destination
$env:path += ";"+$destination
$binDir = Join-Path -Path $env:USERPROFILE -ChildPath "bin"
New-Item -Path $binDir -ItemType Directory -ErrorAction SilentlyContinue
$latest = Get-ChildItem -Path .\zrok*windows*.tar.gz | Sort-Object LastWriteTime | Select-Object -Last 1
tar -xf $latest.FullName -C $binDir zrok.exe
$currentPath = [System.Environment]::GetEnvironmentVariable('PATH', [System.EnvironmentVariableTarget]::User)
if ($currentPath -notlike "*$binDir*") {
$newPath = "$currentPath;$binDir"
[System.Environment]::SetEnvironmentVariable('PATH', $newPath, [System.EnvironmentVariableTarget]::User)
$env:Path = $newPath
}
```
1. With the `zrok` executable in your path, you can then execute the `zrok` directly.
@ -50,3 +48,7 @@ import styles from '@site/src/css/download-card.module.css';
v0.4.0 [c889005]
```
## Wintun for zrok VPN
On Windows, you must install Wintun to use zrok's VPN backend mode. See the [VPN guide](/guides/vpn/vpn.md) for more details.

View File

@ -0,0 +1,8 @@
{
"label": "Linux User Share",
"position": 40,
"link": {
"type": "doc",
"id": "guides/linux-user-share/index"
}
}

View File

@ -0,0 +1,44 @@
---
title: Linux User Share
---
import LinuxShareInstall from '/../docs/guides/_linux-share-install.mdx'
## Overview
You can run any number of zrok share services as `systemd --user` units with your Linux user's zrok environment in `~/.zrok`. This is like [zrok frontdoor](/guides/frontdoor.mdx) except that frontdoor is a system service managed by root separately from your user's login. Linux user shares, Linux system services, and Docker shares all use the same configuration environment variables.
## Install the Linux Package
The package provides the `zrok` executable and service unit template.
<LinuxShareInstall />
## Create a User Share Configuration File
Substitute a name for your instance in place of `my-instance` in the following example. To avoid character escaping problems, use only letters, numbers, hyphens, and underscores in the instance name, not spaces or other special characters.
```bash
ZROK_INSTANCE="my-instance"
cp /opt/openziti/etc/zrok/zrok-share.env ~/.zrok/zrok-share@${ZROK_INSTANCE}.env
```
## Edit the User Share Configuration File
Edit the configuration file in `~/.zrok/zrok-share@${ZROK_INSTANCE}.env` as you would for [zrok frontdoor](/guides/frontdoor.mdx), except ignore the first section "ZROK ENVIRONMENT" because user shares re-use `~/.zrok` and do not need a separate zrok environment.
## Start the User Share Service
```bash
systemctl --user enable --now zrok-share@${ZROK_INSTANCE}.service
```
## Check the User Share Journal
```bash
journalctl --user -lfu zrok-share@${ZROK_INSTANCE}.service
```
## Add Another User Share
To create another user share, choose another instance name, copy the `zrok-share.env` file, edit the configuration file, and start the service.

View File

@ -6,11 +6,27 @@ sidebar_label: VPN
zrok VPN backend allows for simple host-to-host VPN setup.
## Starting VPN server
## Operating System Requirements
zrok VPN requires elevated privileges to manage network devices.
### Windows
On Windows, you must run zrok VPN commands as an administrator and install Wintun by placing `wintun.dll` ([download link](https://www.wintun.net/)) in the same directory as the `zrok.exe` executable.
### Linux
On Linux, the simplest way to grant the necessary privileges is to run zrok VPN commands as root. You can enable a separate environment for root by also running `zrok enable` as the root user, or you can prefix the commands like `sudo -E` to allow zrok running as root to use the zrok environment owned by the current user. The minimum privilege is runing zrok VPN commands and the `ip` command with the `NET_ADMIN` kernel capability. The `zrok-share.service` unit has a commented example to grant `NET_ADMIN` as an Ambient Capability.
### macOS
On macOS, you must run zrok VPN commands as root. You can prefix the zrok command with `sudo -E` to allow zrok running as root to use the zrok environment owned by the current user.
## Start the VPN Server
VPN is shared through the `vpn` backend of `zrok` command.
```
```bash
eugene@hermes $ sudo -E zrok share private --headless --backend-mode vpn
[ 0.542] INFO sdk-golang/ziti.(*listenerManager).createSessionWithBackoff: {session token=[589d443c-f59d-4fc8-8c48-76609b7fb402]} new service session
[ 0.705] INFO main.(*sharePrivateCommand).run: allow other to access your share with the following command:
@ -25,8 +41,9 @@ zrok access private 3rq7torslq3n
By default `vpn` backend uses subnet `10.122.0.0/16` and assigns `10.122.0.1` to the host that stared VPN share.
```
$ ifconfig
Example output from `ifconfig`:
```text
tun0: flags=4305<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST> mtu 16384
inet 10.122.0.1 netmask 255.255.0.0 destination 10.122.0.1
inet6 fe80::705f:24e4:dcfc:a6b2 prefixlen 64 scopeid 0x20<link>
@ -39,16 +56,17 @@ tun0: flags=4305<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST> mtu 16384
```
Default IP/subnet setting can be overridden by adding `<target>` parameter:
```
$ sudo -E zrok share private --headless --backend-mode vpn 192.168.42.12/24
```bash
sudo -E zrok share private --headless --backend-mode vpn 192.168.42.12/24
```
## VPN share reservation
## Reserve a VPN Share Token
Share reservation works the same as with other backend types:
As with all backend modes, you can reserve a share token for a VPN share.
```
eugene@hermes $ zrok reserve private -b vpn
```bash
eugene@hermes $ zrok reserve private --backend-mode vpn
[ 0.297] INFO main.(*reserveCommand).run: your reserved share token is 'k77y2cl7jmjl'
eugene@hermes $ sudo -E zrok share reserved k77y2cl7jmjl --headless
@ -57,14 +75,11 @@ eugene@hermes $ sudo -E zrok share reserved k77y2cl7jmjl --headless
[ 0.463] INFO sdk-golang/ziti.(*listenerManager).createSessionWithBackoff: {session token=[22c5708d-e2f2-41aa-a507-454055f8bfcc]} new service session
[ 0.641] INFO main.(*shareReservedCommand).run: use this command to access your zrok share: 'zrok access private k77y2cl7jmjl'
[
```
## Accessing VPN share
## Access the VPN Share
Accessing a VPN share works similar to other backends.
```
```bash
eugene@calculon % sudo -E zrok access private --headless k77y2cl7jmjl
[ 0.201] INFO main.(*accessPrivateCommand).run: allocated frontend '50B5hloP1s1X'
[ 0.662] INFO main.(*accessPrivateCommand).run: access the zrok share at the following endpoint: VPN:
@ -72,23 +87,22 @@ eugene@calculon % sudo -E zrok access private --headless k77y2cl7jmjl
[ 0.662] INFO zrok/endpoints/vpn.(*Frontend).Run: connected:Welcome to zrok VPN
```
Starting `zrok access` to a VPN share creates virtual network device/interface:
zrok creates a virtual network device, i.e., a "tun" interface, when you run `zrok access`.
```
eugene@calculon ~ % ifconfig
...
Example output from `ifconfig` run on a VPN client device:
```bash
utun5: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> mtu 1500
inet 10.122.0.3 --> 10.122.0.1 netmask 0xff000000
inet6 fe80::ce08:faff:fe8a:7b25%utun5 prefixlen 64 scopeid 0x14
nd6 options=201<PERFORMNUD,DAD>
...
```
At this point a VPN tunnel is active between your server and client.
In the example above server is `hermes(10.122.0.1)` and client is `calculon(10.122.0.3)`.
You can access server from client by using assigned IP address.
At this point a VPN tunnel is active between your server and client.
In the example above server is `hermes(10.122.0.1)` and client is `calculon(10.122.0.3)`.
All devices in the VPN can access one another by IP address.
```
```bash
eugene@calculon ~ % ssh eugene@10.122.0.1
Welcome to Ubuntu 23.10 (GNU/Linux 6.5.0-27-generic x86_64)
@ -107,14 +121,11 @@ eugene@hermes:~$
```
You can also make a reverse(server-to-client) connection:
```
```bash
eugene@hermes:~$ ssh 10.122.0.3
The authenticity of host '10.122.0.3 (10.122.0.3)' can't be established.
<..snip..>
Warning: Permanently added '10.122.0.3' (ED25519) to the list of known hosts.
(eugene@10.122.0.3) Password:
Last login: Tue Apr 16 09:57:28 2024
eugene@calculon ~ % who am i
eugene ttys008 Apr 16 10:06 (10.122.0.1)
eugene@calculon ~ %
```
```

View File

@ -36,28 +36,20 @@ fi
echo "DEBUG: zrok state directory is ${HOME}/.zrok"
: "${ZROK_SHARE_RESERVED:=true}"
echo "DEBUG: ZROK_SHARE_RESERVED=${ZROK_SHARE_RESERVED}"
if (( $# )); then
if [[ -s "$1" ]]; then
while (( $# )); do
if [[ "${1:0:1}" == @ ]]; then
ZROK_INSTANCE="${1:1}"
shift
elif [[ -s "$1" ]]; then
echo "INFO: reading share configuration from $1"
source "$1"
shift
else
echo "ERROR: '$1' is empty or not readable" >&2
exit 1
fi
else
# TODO: consider defining a default environment file
# if [[ -s /opt/openziti/etc/zrok.env ]]; then
# source /opt/openziti/etc/zrok.env
# else
# echo "ERROR: need /opt/openziti/etc/zrok.env or filename argument to read share configuration" >&2
# exit 1
# fi
echo "INFO: reading share configuration from environment variables"
fi
done
ZROK_RESERVATION_FILE="${HOME}/.zrok/reserved${ZROK_INSTANCE:+@${ZROK_INSTANCE}}.json"
[[ -n "${ZROK_TARGET:-}" ]] || {
echo "ERROR: ZROK_TARGET is not defined." >&2
@ -70,14 +62,14 @@ if [[ "${ZROK_FRONTEND_MODE:-}" == temp-public ]]; then
ZROK_CMD="share public"
elif [[ "${ZROK_FRONTEND_MODE:-}" == temp-private ]]; then
ZROK_CMD="share private"
elif [[ -s ~/.zrok/reserved.json ]]; then
ZROK_RESERVED_TOKEN="$(jq -r '.token' ~/.zrok/reserved.json 2>/dev/null)"
if [[ -z "${ZROK_RESERVED_TOKEN}" || "${ZROK_RESERVED_TOKEN}" == null ]]; then
echo "ERROR: invalid reserved.json: '$(jq -c . ~/.zrok/reserved.json)'" >&2
elif [[ -s "${ZROK_RESERVATION_FILE}" ]]; then
ZROK_RESERVATION_TOKEN="$(jq -r '.token' "${ZROK_RESERVATION_FILE}" 2>/dev/null)"
if [[ -z "${ZROK_RESERVATION_TOKEN}" || "${ZROK_RESERVATION_TOKEN}" == null ]]; then
echo "ERROR: invalid reservation file: '$(jq -c . "${ZROK_RESERVATION_FILE}")'" >&2
exit 1
else
echo "INFO: zrok backend is already reserved: ${ZROK_RESERVED_TOKEN}"
ZROK_CMD="${ZROK_RESERVED_TOKEN} ${ZROK_TARGET}"
echo "INFO: zrok backend is already reserved: ${ZROK_RESERVATION_TOKEN}"
ZROK_CMD="${ZROK_RESERVATION_TOKEN} ${ZROK_TARGET}"
if [[ "${ZROK_SHARE_RESERVED}" == true ]]; then
exec_share_reserved ${ZROK_CMD}
else
@ -141,10 +133,9 @@ case "${ZROK_BACKEND_MODE}" in
;;
vpn)
if [[ -n "${ZROK_TARGET}" ]]; then
ZROK_SVC_FILE=/etc/systemd/system/zrok-share.service.d/override.conf
if ! grep -qE '^AmbientCapabilities=CAP_NET_ADMIN' "${ZROK_SVC_FILE}"; then
echo "ERROR: you must uncomment 'AmbientCapabilities=CAP_NET_ADMIN' in '${ZROK_SVC_FILE}'"\
"and run 'systemctl daemon-reload' to enable VPN mode" >&2
if ! systemctl cat zrok-share.service | grep -qE '^AmbientCapabilities=.*CAP_NET_ADMIN' >/dev/null; then
echo "ERROR: you must 'systemctl edit zrok-share.service' and uncomment
'AmbientCapabilities=CAP_NET_ADMIN' to enable VPN mode" >&2
exit 1
fi
fi
@ -208,30 +199,30 @@ if [[ "${ZROK_FRONTEND_MODE:-}" =~ ^temp- ]]; then
exec_with_common_opts ${ZROK_CMD}
else
# reserve and continue
zrok ${ZROK_CMD} > ~/.zrok/reserved.json
zrok ${ZROK_CMD} > "${ZROK_RESERVATION_FILE}"
# share the reserved backend target until exit
if ! [[ -s ~/.zrok/reserved.json ]]; then
echo "ERROR: empty or missing $(realpath ~/.zrok)/reserved.json" >&2
if ! [[ -s "${ZROK_RESERVATION_FILE}" ]]; then
echo "ERROR: empty or missing $(realpath "${ZROK_RESERVATION_FILE}")" >&2
exit 1
elif ! jq . < ~/.zrok/reserved.json &>/dev/null; then
echo "ERROR: invalid JSON in $(realpath ~/.zrok)/reserved.json" >&2
elif ! jq . < "${ZROK_RESERVATION_FILE}" &>/dev/null; then
echo "ERROR: invalid JSON in $(realpath "${ZROK_RESERVATION_FILE}")" >&2
exit 1
else
if [[ "${ZROK_FRONTEND_MODE:-}" == reserved-public ]]; then
ZROK_PUBLIC_URLS=$(jq -cr '.frontend_endpoints' ~/.zrok/reserved.json 2>/dev/null)
ZROK_PUBLIC_URLS=$(jq -cr '.frontend_endpoints' "${ZROK_RESERVATION_FILE}" 2>/dev/null)
if [[ -z "${ZROK_PUBLIC_URLS}" || "${ZROK_PUBLIC_URLS}" == null ]]; then
echo "ERROR: frontend endpoints not defined in $(realpath ~/.zrok)/reserved.json" >&2
echo "ERROR: frontend endpoints not defined in $(realpath "${ZROK_RESERVATION_FILE}")" >&2
exit 1
else
echo "INFO: zrok public URLs: ${ZROK_PUBLIC_URLS}"
fi
fi
ZROK_RESERVED_TOKEN=$(jq -r '.token' ~/.zrok/reserved.json 2>/dev/null)
if [[ -z "${ZROK_RESERVED_TOKEN}" || "${ZROK_RESERVED_TOKEN}" == null ]]; then
echo "ERROR: zrok reservation token not defined in $(realpath ~/.zrok)/reserved.json" >&2
ZROK_RESERVATION_TOKEN=$(jq -r '.token' "${ZROK_RESERVATION_FILE}" 2>/dev/null)
if [[ -z "${ZROK_RESERVATION_TOKEN}" || "${ZROK_RESERVATION_TOKEN}" == null ]]; then
echo "ERROR: zrok reservation token not defined in $(realpath "${ZROK_RESERVATION_FILE}")" >&2
exit 1
fi
ZROK_CMD="${ZROK_RESERVED_TOKEN} ${ZROK_TARGET}"
ZROK_CMD="${ZROK_RESERVATION_TOKEN} ${ZROK_TARGET}"
if [[ "${ZROK_SHARE_RESERVED}" == true ]]; then
exec_share_reserved ${ZROK_CMD}
else

View File

@ -3,8 +3,10 @@
#
## ZROK ENVIRONMENT
#
# You MUST enable a zrok environment by setting the environment enable token here. This file must be readable by
# 'other'. Obtain the enable token from the zrok console after accepting your invitation and creating a password.
# The variables in this section are not used by user units, i.e., systemctl --user, because it is assumed the user's
# environment in ~/.zrok is already enabled. The variables in this section are required by system-wide service units.
# For system services, you MUST enable a zrok environment by setting the account token here. This file must
# be readable by 'other'. Obtain the account token from the zrok console.
#
# WARNING: changing these values has no effect if /var/lib/zrok-share/.zrok/environment.json exists. Remove that file to
# enable a new environment and /var/lib/zrok-share/.zrok/reserved.json to provision a new frontend URL for the specified
@ -67,11 +69,11 @@ ZROK_TARGET="" # e.g., http://127.0.0.1:3000
#ZROK_BACKEND_MODE="udpTunnel"
#ZROK_TARGET="127.0.0.1:53"
# you MUST grant NET_ADMIN capability to the service to enable vpn mode, e.g., run these two commands:
# sed -Ei 's/.*AmbientCapabilities=CAP_NET_ADMIN/AmbientCapabilities=CAP_NET_ADMIN/' /etc/systemd/system/zrok-share.service.d/override.conf
# systemctl daemon-reload
# you MUST grant NET_ADMIN capability to the service to enable vpn mode, e.g., run:
# systemctl edit zrok-share.service
# uncomment 'AmbientCapabilities=CAP_NET_ADMIN'
#ZROK_BACKEND_MODE="vpn"
#ZROK_TARGET="172.16.0.1/12"
#ZROK_TARGET="10.122.0.1/16"
# there is no target for socks mode because the share is only a dynamic exit for the proxy client
#ZROK_BACKEND_MODE="socks"

View File

@ -1,5 +1,5 @@
[Unit]
Description=zrok reserved public share service
Description=zrok share service
After=network-online.target
[Service]
@ -7,8 +7,9 @@ Type=simple
DynamicUser=yes
StateDirectory=zrok-share
UMask=0007
ExecStartPre=/opt/openziti/bin/zrok-enable.bash /opt/openziti/etc/zrok/zrok-share.env
ExecStart=/opt/openziti/bin/zrok-share.bash /opt/openziti/etc/zrok/zrok-share.env
EnvironmentFile=/opt/openziti/etc/zrok/zrok-share.env
ExecStartPre=/opt/openziti/bin/zrok-enable.bash
ExecStart=/opt/openziti/bin/zrok-share.bash
Restart=always
RestartSec=3

View File

@ -6,5 +6,3 @@
# allow adding tun device and IP routes and iptables rules; required when ZROK_BACKEND_MODE=vpn
# AmbientCapabilities=CAP_NET_ADMIN
# you must run 'systemctl daemon-reload' after modifying this file

17
nfpm/zrok-share@.service Normal file
View File

@ -0,0 +1,17 @@
# /usr/lib/systemd/user/zrok-share@.service
[Unit]
Description=zrok share user service unit @%i
After=network-online.target
[Service]
Type=simple
UMask=0007
EnvironmentFile=%h/.zrok/zrok-share@%i.env
ExecStart=/opt/openziti/bin/zrok-share.bash @%i
Restart=always
RestartSec=3
[Install]
WantedBy=multi-user.target