Merge remote-tracking branch 'origin/main' into node-sdk

This commit is contained in:
Curt Tudor 2024-05-01 06:01:32 -06:00
commit 9f071f5ec6
No known key found for this signature in database
GPG Key ID: B3CD225AF4EC8E96
53 changed files with 2063 additions and 367 deletions

View File

@ -10,6 +10,7 @@ To build, follow these steps:
* run `npm install`
* run `npm run build` (this process takes a while the first time and only needs to be run if the ui changes)
* change back to the checkout root
* make sure the dist directory exists: `mkdir -p dist`
* build the go project normally: `go build -o dist ./...`
## Documentation/Website

View File

@ -1,8 +1,20 @@
# CHANGELOG
## v0.4.28
FEATURE: A Docker Compose project for self-hosting a zrok instance and [accompanying Docker guide](https://docs.zrok.io/docs/guides/self-hosting/docker) for more information.
CHANGE: the container images run as "ziggy" (UID 2171) instead of the generic restricted user "nobody" (UID 65534). This reduces the risk of unexpected file permissions when binding the Docker host's filesystem to a zrok container.
CHANGE: the Docker sharing guides were simplified and expanded
## v0.4.27
CHANGE: Update to OpenZiti SDK (`github.com/openziti/sdk-golang`) at `v0.23.10`.
FEATURE: New `vpn` backend mode. Use `sudo zrok share private --backend-mode vpn` on the _VPN server_ host, then `sudo zrok access private <token>` on _VPN client_ machine. Works with reserved shares using `zrok reserve private --backend-mode vpn`. Use `<target>` parameter to override default VPN network settings `zrok share private -b vpn 192.168.255.42/24` -- server IP is `192.168.255.42` and VPN netmask will be `192.168.255.0/24`. Client IPs are assigned automatically from netmask range.
CHANGE: Update to OpenZiti SDK (`github.com/openziti/sdk-golang`) at `v0.23.22`.
CHANGE: Added indexes to `environments`, `shares`, and `frontends` tables to improve overall query performance on both PostgreSQL and Sqlite.
FIX: Also update the Python SDK to include the permission mode and access grants fields on the `ShareRequest` (https://github.com/openziti/zrok/issues/432)

View File

@ -8,6 +8,7 @@ import (
"github.com/openziti/zrok/endpoints/proxy"
"github.com/openziti/zrok/endpoints/tcpTunnel"
"github.com/openziti/zrok/endpoints/udpTunnel"
"github.com/openziti/zrok/endpoints/vpn"
"github.com/openziti/zrok/environment"
"github.com/openziti/zrok/rest_client_zrok"
"github.com/openziti/zrok/rest_client_zrok/share"
@ -165,6 +166,30 @@ func (cmd *accessPrivateCommand) run(_ *cobra.Command, args []string) {
}
}()
case "vpn":
endpointUrl = &url.URL{
Scheme: "VPN",
}
fe, err := vpn.NewFrontend(&vpn.FrontendConfig{
IdentityName: env.EnvironmentIdentityName(),
ShrToken: args[0],
RequestsChan: requests,
})
if err != nil {
if !panicInstead {
tui.Error("unable to create private access", err)
}
panic(err)
}
go func() {
if err := fe.Run(); err != nil {
if !panicInstead {
tui.Error("error starting access", err)
}
panic(err)
}
}()
default:
cfg := proxy.DefaultFrontendConfig(env.EnvironmentIdentityName())
cfg.ShrToken = shrToken

View File

@ -3,12 +3,14 @@ package main
import (
"encoding/json"
"fmt"
"github.com/openziti/zrok/endpoints/vpn"
"github.com/openziti/zrok/environment"
"github.com/openziti/zrok/sdk/golang/sdk"
"github.com/openziti/zrok/tui"
"github.com/openziti/zrok/util"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"net"
"slices"
"time"
)
@ -40,7 +42,7 @@ func newReserveCommand() *reserveCommand {
command := &reserveCommand{cmd: cmd}
cmd.Flags().StringVarP(&command.uniqueName, "unique-name", "n", "", "A unique name for the reserved share (defaults to generated identifier)")
cmd.Flags().StringArrayVar(&command.frontendSelection, "frontends", []string{"public"}, "Selected frontends to use for the share")
cmd.Flags().StringVarP(&command.backendMode, "backend-mode", "b", "proxy", "The backend mode (public|private: proxy, web, caddy, drive) (private: tcpTunnel, udpTunnel, socks)")
cmd.Flags().StringVarP(&command.backendMode, "backend-mode", "b", "proxy", "The backend mode (public|private: proxy, web, caddy, drive) (private: tcpTunnel, udpTunnel, socks, vpn)")
cmd.Flags().BoolVarP(&command.jsonOutput, "json-output", "j", false, "Emit JSON describing the created reserved share")
cmd.Flags().StringArrayVar(&command.basicAuth, "basic-auth", []string{}, "Basic authentication users (<username:password>,...)")
cmd.Flags().StringVar(&command.oauthProvider, "oauth-provider", "", "Enable OAuth provider [google, github]")
@ -56,7 +58,7 @@ func newReserveCommand() *reserveCommand {
func (cmd *reserveCommand) run(_ *cobra.Command, args []string) {
shareMode := sdk.ShareMode(args[0])
privateOnlyModes := []string{"tcpTunnel", "udpTunnel", "socks"}
privateOnlyModes := []string{"tcpTunnel", "udpTunnel", "socks", "vpn"}
if shareMode != sdk.PublicShareMode && shareMode != sdk.PrivateShareMode {
tui.Error("invalid sharing mode; expecting 'public' or 'private'", nil)
} else if shareMode == sdk.PublicShareMode && slices.Contains(privateOnlyModes, cmd.backendMode) {
@ -114,8 +116,20 @@ func (cmd *reserveCommand) run(_ *cobra.Command, args []string) {
tui.Error("the 'socks' backend mode does not expect <target>", nil)
}
case "vpn":
if len(args) == 2 {
_, _, err := net.ParseCIDR(args[1])
if err != nil {
tui.Error("the 'vpn' backend expect valid CIDR <target>", err)
}
target = args[1]
} else {
target = vpn.DefaultTarget()
}
default:
tui.Error(fmt.Sprintf("invalid backend mode '%v'; expected {proxy, web, tcpTunnel, udpTunnel, caddy, drive, socks}", cmd.backendMode), nil)
tui.Error(fmt.Sprintf("invalid backend mode '%v'; "+
"expected {proxy, web, tcpTunnel, udpTunnel, caddy, drive, socks, vpn}", cmd.backendMode), nil)
}
env, err := environment.LoadRoot()

View File

@ -9,12 +9,14 @@ import (
"github.com/openziti/zrok/endpoints/socks"
"github.com/openziti/zrok/endpoints/tcpTunnel"
"github.com/openziti/zrok/endpoints/udpTunnel"
"github.com/openziti/zrok/endpoints/vpn"
"github.com/openziti/zrok/environment"
"github.com/openziti/zrok/environment/env_core"
"github.com/openziti/zrok/sdk/golang/sdk"
"github.com/openziti/zrok/tui"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"net"
"os"
"os/signal"
"syscall"
@ -42,7 +44,7 @@ func newSharePrivateCommand() *sharePrivateCommand {
}
command := &sharePrivateCommand{cmd: cmd}
cmd.Flags().StringArrayVar(&command.basicAuth, "basic-auth", []string{}, "Basic authentication users (<username:password>,...")
cmd.Flags().StringVarP(&command.backendMode, "backend-mode", "b", "proxy", "The backend mode {proxy, web, tcpTunnel, udpTunnel, caddy, drive, socks}")
cmd.Flags().StringVarP(&command.backendMode, "backend-mode", "b", "proxy", "The backend mode {proxy, web, tcpTunnel, udpTunnel, caddy, drive, socks, vpn}")
cmd.Flags().BoolVar(&command.headless, "headless", false, "Disable TUI and run headless")
cmd.Flags().BoolVar(&command.insecure, "insecure", false, "Enable insecure TLS certificate validation for <target>")
cmd.Flags().BoolVar(&command.closed, "closed", false, "Enable closed permission mode (see --access-grant)")
@ -105,6 +107,17 @@ func (cmd *sharePrivateCommand) run(_ *cobra.Command, args []string) {
}
target = "socks"
case "vpn":
if len(args) == 1 {
_, _, err := net.ParseCIDR(args[0])
if err != nil {
tui.Error("the 'vpn' backend expect valid CIDR <target>", err)
}
target = args[0]
} else {
target = vpn.DefaultTarget()
}
default:
tui.Error(fmt.Sprintf("invalid backend mode '%v'; expected {proxy, web, tcpTunnel, udpTunnel, caddy, drive}", cmd.backendMode), nil)
}
@ -318,6 +331,28 @@ func (cmd *sharePrivateCommand) run(_ *cobra.Command, args []string) {
}
}()
case "vpn":
cfg := &vpn.BackendConfig{
IdentityPath: zif,
EndpointAddress: target,
ShrToken: shr.Token,
RequestsChan: requests,
}
be, err := vpn.NewBackend(cfg)
if err != nil {
if !panicInstead {
tui.Error("error creating VPN backend", err)
}
panic(err)
}
go func() {
if err := be.Run(); err != nil {
logrus.Errorf("error running VPN backend: %v", err)
}
}()
default:
tui.Error("invalid backend mode", nil)
}

View File

@ -10,6 +10,7 @@ import (
"github.com/openziti/zrok/endpoints/socks"
"github.com/openziti/zrok/endpoints/tcpTunnel"
"github.com/openziti/zrok/endpoints/udpTunnel"
"github.com/openziti/zrok/endpoints/vpn"
"github.com/openziti/zrok/environment"
"github.com/openziti/zrok/rest_client_zrok/metadata"
"github.com/openziti/zrok/rest_client_zrok/share"
@ -282,6 +283,28 @@ func (cmd *shareReservedCommand) run(_ *cobra.Command, args []string) {
}
}()
case "vpn":
cfg := &vpn.BackendConfig{
IdentityPath: zif,
EndpointAddress: target,
ShrToken: shrToken,
RequestsChan: requests,
}
be, err := vpn.NewBackend(cfg)
if err != nil {
if !panicInstead {
tui.Error("error creating VPN backend", err)
}
panic(err)
}
go func() {
if err := be.Run(); err != nil {
logrus.Errorf("error running VPN backend: %v", err)
}
}()
default:
tui.Error("invalid backend mode", nil)
}

View File

@ -0,0 +1,6 @@
-- +migrate Up
create index environments_account_id_idx on environments (account_id);
create index shares_token_perf_idx on shares (token);
create index shares_environment_id_idx on shares (environment_id);
create index frontends_environment_id_idx on frontends (environment_id);

View File

@ -0,0 +1,3 @@
-- +migrate Up
alter type backend_mode add value 'vpn';

View File

@ -0,0 +1,6 @@
-- +migrate Up
create index environments_account_id_idx on environments (account_id);
create index shares_token_perf_idx on shares (token);
create index shares_environment_id_idx on shares (environment_id);
create index frontends_environment_id_idx on frontends (environment_id);

View File

@ -0,0 +1,76 @@
-- +migrate Up
alter table shares rename to shares_old;
create table shares (
id integer primary key,
environment_id integer constraint fk_environments_shares references environments on delete cascade,
z_id string not null unique,
token string not null,
share_mode string not null,
backend_mode string not null,
frontend_selection string,
frontend_endpoint string,
backend_proxy_endpoint string,
reserved boolean not null default(false),
created_at datetime not null default(strftime('%Y-%m-%d %H:%M:%f', 'now')),
updated_at datetime not null default(strftime('%Y-%m-%d %H:%M:%f', 'now')),
deleted boolean not null default(false),
permission_mode string not null default('open'),
constraint chk_z_id check (z_id <> ''),
constraint chk_token check (token <> ''),
constraint chk_share_mode check (share_mode == 'public' or share_mode == 'private'),
constraint chk_backend_mode check (backend_mode == 'proxy' or backend_mode == 'web' or backend_mode == 'tcpTunnel' or backend_mode == 'udpTunnel' or backend_mode == 'caddy' or backend_mode == 'drive' or backend_mode == 'socks' or backend_mode == 'vpn')
);
insert into shares select * from shares_old;
drop index shares_token_idx;
create unique index shares_token_idx ON shares(token) WHERE deleted is false;
drop index shares_token_perf_idx;
create index shares_token_perf_idx on shares (token);
drop index shares_environment_id_idx;
create index shares_environment_id_idx on shares (environment_id);
alter table frontends rename to frontends_old;
create table frontends (
id integer primary key,
environment_id integer references environments(id),
token varchar(32) not null unique,
z_id varchar(32) not null,
public_name varchar(64) unique,
url_template varchar(1024),
reserved boolean not null default(false),
created_at datetime not null default(strftime('%Y-%m-%d %H:%M:%f', 'now')),
updated_at datetime not null default(strftime('%Y-%m-%d %H:%M:%f', 'now')),
deleted boolean not null default(false),
private_share_id integer references shares(id)
);
insert into frontends select * from frontends_old;
drop table frontends_old;
create index frontends_environment_id_idx on frontends (environment_id);
alter table share_limit_journal rename to share_limit_journal_old;
create table share_limit_journal (
id integer primary key,
share_id integer references shares(id),
rx_bytes bigint not null,
tx_bytes bigint not null,
action limit_action_type not null,
created_at datetime not null default(strftime('%Y-%m-%d %H:%M:%f', 'now')),
updated_at datetime not null default(strftime('%Y-%m-%d %H:%M:%f', 'now'))
);
insert into share_limit_journal select * from share_limit_journal_old;
drop table share_limit_journal_old;
alter table access_grants rename to access_grants_old;
create table access_grants (
id integer primary key,
share_id integer references shares(id),
account_id integer references accounts(id),
created_at datetime not null default(strftime('%Y-%m-%d %H:%M:%f', 'now')),
updated_at datetime not null default(strftime('%Y-%m-%d %H:%M:%f', 'now')),
deleted boolean not null default(false)
);
insert into access_grants select * from access_grants_old;
drop table access_grants_old;
drop table shares_old;

View File

@ -0,0 +1,2 @@
/.env
/compose.yml

View File

@ -0,0 +1,31 @@
{
email {$CADDY_ACME_EMAIL}
acme_ca {$CADDY_ACME_API}
admin 0.0.0.0:2019
}
http:// {
redir https://{host}{uri} permanent
}
*.{$ZROK_DNS_ZONE} {
tls {
dns {$CADDY_DNS_PLUGIN} {$CADDY_DNS_PLUGIN_TOKEN}
}
log {
output stdout
format console
level DEBUG
}
@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

@ -0,0 +1,231 @@
## Docker Quickstart
### DNS Configuration
The quickstart makes these assumptions about your global DNS configuration.
1. A Caddy DNS plugin is available for your DNS provider (see [github.com/caddy-dns](https://github.com/orgs/caddy-dns/repositories?type=all&q=sort%3Aname-asc))
1. You have designated A DNS zone for zrok, e.g. `example.com` or `share.example.com` and created (and delegated, if necessary) the zone on your DNS provider's platform.
1. A wildcard record exists for the IP address where the zrok instance will run, e.g. if your DNS zone is `share.example.com`, then your wildcard record is `*.share.example.com`.
1. You have created an API token in your DNS provider's platform and the token has permission to create DNS records in the DNS zone.
### Create the Docker Compose Project
Create a working directory on your Docker host and save these Docker Compose project files. A OpenZiti network is provided by the "quickstart" container and is managed exclusively by zrok.
#### Shortcut option
1. Run this script to download the files.
```bash
curl https://get.openziti.io/zrok-docker/fetch.bash | bash
```
Optionally, customize the install path instead of using the current directory.
```bash
curl https://get.openziti.io/zrok-docker/fetch.bash | bash -s /path/to/install
```
#### Do it Yourself
1. Fetch the ziti quickstart Compose file.
```bash
wget https://get.openziti.io/dock/all-in-one/compose.yml
```
1. Get the zrok repo ZIP file.
```bash
wget https://github.com/openziti/zrok/archive/refs/heads/main.zip
```
1. Unzip the zrok-instance files into the project directory.
```bash
unzip -j -d . main.zip '*/docker/compose/zrok-instance/*'
```
### Configure the Docker Compose Project Environment
Create an `.env` file in the working directory.
```bash title=".env required"
ZROK_DNS_ZONE=share.example.com
CADDY_DNS_PLUGIN=cloudflare
CADDY_DNS_PLUGIN_TOKEN=abcd1234
CADDY_ACME_EMAIL=me@example.com
# this must == ziti.${ZROK_DNS_ZONE}
ZITI_CTRL_ADVERTISED_ADDRESS=ziti.share.example.com
ZITI_PWD=zitiadminpw
ZROK_ADMIN_TOKEN=zroktoken
ZROK_USER_PWD=zrokuserpw
```
```bash title=".env options"
ZITI_CTRL_ADVERTISED_PORT=1280
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
# use the staging API until you're sure everything is working to avoid hitting the main CA's rate limit
CADDY_ACME_API=https://acme-staging-v02.api.letsencrypt.org/directory
```
### Start the Docker Compose Project
1. Start the ziti network. This runs `ziti edge quickstart` ([link to readme](https://github.com/openziti/ziti/tree/main/quickstart/docker/all-in-one#readme)).
```bash
docker compose --profile ziti up --detach
```
1. Start the zrok instance.
The container images for zrok (including caddy) are built in this step. This provides a simple configuration to get started. You can modify the templates named like `*.envsubst` or mount a customized configuration file to mask the one that was built in.
```bash
docker compose --profile zrok up --build --detach
```
### Set up a User Account
This step creates a user account. You will log in to the zrok web console with the account password created in this step. The CADDY_ACME_EMAIL and ZROK_USER_PWD variables are set in the `.env` file. You can create more user accounts the same way by substituting a different email and password.
```bash
docker compose exec zrok-controller bash -xc 'zrok admin create account /etc/zrok-controller/config.yml ${CADDY_ACME_EMAIL} ${ZROK_USER_PWD}'
```
```buttonless title="Example output"
+ zrok admin create account /etc/zrok-controller/config.yml me@example.com zrokuserpw
[ 0.000] INFO zrok/controller/store.Open: database connected
[ 0.002] INFO zrok/controller/store.(*Store).migrate: applied 0 migrations
heMqncCyxZcx
```
### Enable the User Environment
You must enable each device environment with the account token obtained when the account was created. This is separate from the account password that's used to log in to the web console.
Follow [the getting started guide](/docs/getting-started#installing-the-zrok-command) to install the zrok CLI on some device and enable a zrok environment.
1. Configure the environment with the zrok API. Substitute the API endpoint with the one you're using, e.g. `https://zrok.${ZROK_DNS_ZONE}`.
```bash
zrok config set apiEndpoint https://zrok.share.example.com
```
1. Enable an environment on this device with the account token from the previous step.
```bash
zrok enable heMqncCyxZcx
```
### Firewall Configuration
The `quickstart` and `caddy` containers publish ports to all devices that use zrok shares. The `zrok-controller` and `zrok-frontend` containers expose ports only to the `caddy` container and the Docker host's loopback interface.
#### 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 `quickstart`)
1. `3022/tcp` - ziti data plane (published by container `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`) -->
### Troubleshooting
1. Check the ziti and zrok logs.
You can substitute the service container name of each to check their logs individually: `quickstart` (ziti container), `zrok-controller`, `zrok-frontend`.
```bash
docker compose logs zrok-controller
```
1. Check the caddy logs.
It can take a few minutes for Caddy to obtain the wildcard certificate. You can check the logs to see if there were any errors completing the DNS challenge which involves using the Caddy DNS plugin to create a TXT record in your DNS zone. This leverages the API token you provided in the `.env` file, which must have permission to create DNS records in the zrok DNS zone.
```bash
docker compose logs caddy
```
1. `zrok enable` fails certificate verification: ensure you are not using the staging API for Let's Encrypt.
If you are using the staging API, you will see an error about the API certificate when you use the zrok CLI. You can switch to the production API by removing the overriding assignment of the `CADDY_ACME_API` variable.
```buttonless title="Example output"
there was a problem enabling your environment!
you are trying to use the zrok service at: https://zrok.share.example.com
you can change your zrok service endpoint using this command:
$ zrok config set apiEndpoint <newEndpoint>
(where newEndpoint is something like: https://some.zrok.io)
[ERROR]: error creating service client (error getting version from api endpoint 'https://zrok.share.example.com': Get "https://zrok.share.example.com/api/v1/version": tls: failed to verify certificate: x509: certificate signed by unknown authority: Get "https://zrok.share.example.com/api/v1/version": tls: failed to verify certificate: x509: certificate signed by unknown authority)
```
1. Validate the Caddyfile.
```bash
docker compose exec caddy caddy validate --config /etc/caddy/Caddyfile
```
1. Verify the correct DNS provider module was built-in to Caddy.
```bash
docker compose exec caddy caddy list-modules | grep dns.providers
```
```buttonless title="Example output"
dns.providers.cloudflare
```
1. Verify certificates.
You can check the certificates that Caddy has obtained.
```bash
docker compose exec caddy caddy list-certificates
```
1. Use the Caddy admin API.
You can use the Caddy admin API to check the status of the Caddy instance. The admin API is available on port `2019/tcp` inside the Docker Compose project. You can modify `compose.override.yml` to publish the port if you want to access the admin API from the Docker host or elsewhere.
```bash
docker compose exec caddy curl http://localhost:2019/config/ | jq
```
1. My provider, e.g., Route53 doesn't give me 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.
```json
tls {
dns {$CADDY_DNS_PLUGIN} {
access_key_id {$AWS_ACCESS_KEY_ID}
secret_access_key {$AWS_SECRET_ACCESS_KEY}
}
}
```
```bash title=".env"
CADDY_DNS_PLUGIN=route53
AWS_ACCESS_KEY_ID=abcd1234
AWS_SECRET_ACCESS_KEY=abcd1234
```

View File

@ -0,0 +1,23 @@
#!/usr/bin/env bash
set -o errexit
set -o nounset
set -o pipefail
set -o xtrace
for arg in "${@}"; do
if [[ ! "${arg}" =~ ^- && -s "${arg}" ]]; then
CONFIG="${arg}"
break
fi
done
if [[ -z "${CONFIG}" ]]; then
echo "ERROR: args '${*}' do not contain a non-empty config file" >&2
exit 1
fi
# config.yml is first param
zrok admin bootstrap --skip-frontend "${CONFIG}"
exec "$@"

View File

@ -0,0 +1,116 @@
#!/usr/bin/env bash
set -o errexit
set -o nounset
set -o pipefail
# set -o xtrace
getZitiPublicFrontend(){
local RETURNED
local -A FIELDS
FIELDS[all]=0
FIELDS[zid]=1
FIELDS[name]=2
FIELDS[type]=3
FIELDS[attributes]=4
FIELDS[policy]=5
if (( $# )); then
RETURNED="$1"
shift
else
RETURNED="all"
fi
if (( $# )); then
echo "WARN: ignoring unexpected parameters: $*" >&2
fi
if [[ -z "${FIELDS[$RETURNED]}" ]]; then
echo "ERROR: invalid return field $RETURNED" >&2
return 1
fi
ziti edge list identities 'name="public"' --csv \
| awk -F, '$'${FIELDS[name]}'=="public" {print $'${FIELDS[$RETURNED]}';}'
}
getZrokPublicFrontend(){
local RETURNED
local -A FIELDS
FIELDS[all]=0
FIELDS[token]=1
FIELDS[zid]=2
FIELDS[name]=3
FIELDS[template]=4
FIELDS[created]=5
FIELDS[updated]=6
if (( $# )); then
RETURNED="$1"
shift
else
RETURNED="all"
fi
if (( $# )); then
echo "WARN: ignoring unexpected parameters: $*" >&2
fi
if [[ -z "${FIELDS[$RETURNED]}" ]]; then
echo "ERROR: invalid return field $RETURNED" >&2
return 1
fi
# strip ANSI sequences and return the first position from the line with a name exactly matching "public"
zrok admin list frontends | sed 's/\x1b\[[0-9;]*m//g' \
| awk '$'${FIELDS[name]}'=="public" {print $'${FIELDS[$RETURNED]}'}'
}
ziti edge login "https://ziti.${ZROK_DNS_ZONE}:${ZITI_CTRL_ADVERTISED_PORT}" \
--username admin \
--password "${ZITI_PWD}" \
--yes
if ! [[ -s ~/.zrok/identities/public.json ]]; then
mkdir -p ~/.zrok/identities
ziti edge create identity "public" --jwt-output-file /tmp/public.jwt
ziti edge enroll --jwt /tmp/public.jwt --out ~/.zrok/identities/public.json
fi
# find Ziti ID of default "public" frontend
ZITI_PUBLIC_ID="$(getZitiPublicFrontend zid)"
until [[ -n "${ZITI_PUBLIC_ID}" ]]; do
echo "DEBUG: waiting for default frontend "public" Ziti identity to be created"
sleep 3
ZITI_PUBLIC_ID="$(getZitiPublicFrontend zid)"
done
echo "DEBUG: 'public' ZITI_PUBLIC_ID=$ZITI_PUBLIC_ID"
until curl -sSf "${ZROK_API_ENDPOINT}/api/v1/version"; do
echo "DEBUG: waiting for zrok controller API version endpoint to respond"
sleep 3
done
# if default "public" frontend already exists
ZROK_PUBLIC_TOKEN=$(getZrokPublicFrontend token)
if [[ -n "${ZROK_PUBLIC_TOKEN}" ]]; then
# ensure the Ziti ID of the public frontend's identity is the same in Ziti and zrok
ZROK_PUBLIC_ZID=$(getZrokPublicFrontend zid)
if [[ "${ZITI_PUBLIC_ID}" != "${ZROK_PUBLIC_ZID}" ]]; then
echo "ERROR: existing Ziti Identity named 'public' with id '$ZITI_PUBLIC_ID' is from a previous zrok"\
"instance life cycle. Delete it then re-run zrok." >&2
exit 1
fi
echo "INFO: updating frontend"
zrok admin update frontend "${ZROK_PUBLIC_TOKEN}" \
--url-template "https://{token}.${ZROK_DNS_ZONE}"
else
echo "INFO: creating frontend"
zrok admin create frontend "${ZITI_PUBLIC_ID}" public \
"https://{token}.${ZROK_DNS_ZONE}"
fi
exec "${@}"

View File

@ -0,0 +1,19 @@
# Use the official Caddy image as a parent image
FROM caddy:2-builder AS builder
# e.g., "github.com/caddy-dns/digitalocean"
ARG CADDY_DNS_PLUGIN
# Build Caddy with the specified DNS provider plugin
RUN xcaddy build \
--with github.com/caddy-dns/${CADDY_DNS_PLUGIN}
# Use the official Caddy image to create the final image
FROM caddy:2
# install curl to support using the Caddy API
RUN apk add --no-cache curl
# Copy the custom Caddy build into the final image
COPY --from=builder /usr/bin/caddy /usr/bin/caddy
COPY ./Caddyfile /etc/caddy/Caddyfile

View File

@ -0,0 +1,137 @@
# this compose file is designed to merge with the ziti all-in-one quickstart compose file by renaming
# https://get.openziti.io/dock/all-in-one/compose.yml to compose.override.yml
services:
zrok-permissions:
image: busybox
command:
- /bin/sh
- -euxc
- |
chown -Rc ${ZIGGY_UID:-2171} /var/lib/zrok-*;
chmod -Rc ug=rwX,o-rwx /var/lib/zrok-*;
volumes:
- zrok_ctrl:/var/lib/zrok-controller
- zrok_frontend:/var/lib/zrok-frontend
zrok-controller:
profiles:
- zrok
depends_on:
zrok-permissions:
condition: service_completed_successfully
build:
context: .
dockerfile: ./zrok-controller.Dockerfile
args:
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}
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
user: ${ZIGGY_UID:-2171}
command: zrok controller /etc/zrok-controller/config.yml --verbose
volumes:
- zrok_ctrl:/var/lib/zrok-controller
networks:
quickstart:
aliases:
- zrok.${ZROK_DNS_ZONE}
restart: unless-stopped
expose:
- ${ZROK_CTRL_PORT:-18080} # (not published)
# Caddy's published ports provide a TLS reverse proxy for the zrok controller
# ports:
# - 127.0.0.1:${ZROK_CTRL_PORT:-18080}:${ZROK_CTRL_PORT:-18080}
environment:
ZROK_USER_PWD: ${ZROK_USER_PWD} # admin account password (initial user account)
CADDY_ACME_EMAIL: ${CADDY_ACME_EMAIL} # login email address (initial user account)
zrok-frontend:
profiles:
- zrok
depends_on:
zrok-permissions:
condition: service_completed_successfully
build:
context: .
dockerfile: zrok-frontend.Dockerfile
args:
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"
ZROK_FRONTEND_PORT: ${ZROK_FRONTEND_PORT:-8080}
ZROK_OAUTH_PORT: ${ZROK_OAUTH_PORT:-8081}
ZROK_OAUTH_HASH_KEY: ${ZROK_OAUTH_HASH_KEY-noop}
ZROK_OAUTH_GOOGLE_CLIENT_ID: ${ZROK_OAUTH_GOOGLE_CLIENT_ID:-noop}
ZROK_OAUTH_GOOGLE_CLIENT_SECRET: ${ZROK_OAUTH_GOOGLE_CLIENT_SECRET:-noop}
ZROK_OAUTH_GITHUB_CLIENT_ID: ${ZROK_OAUTH_GITHUB_CLIENT_ID:-noop}
ZROK_OAUTH_GITHUB_CLIENT_SECRET: ${ZROK_OAUTH_GITHUB_CLIENT_SECRET:-noop}
user: ${ZIGGY_UID:-2171}
command: zrok access public /etc/zrok-frontend/config.yml --verbose
volumes:
- zrok_frontend:/var/lib/zrok-frontend
networks:
quickstart:
restart: unless-stopped
expose:
- ${ZROK_FRONTEND_PORT:-8080} # (not published)
- ${ZROK_OAUTH_PORT:-8081} # (not published)
# ports:
# - 127.0.0.1:${ZROK_FRONTEND_PORT:-8080}:${ZROK_FRONTEND_PORT:-8080}
# - 127.0.0.1:${ZROK_OAUTH_PORT:-8081}:${ZROK_OAUTH_PORT:-8081}
environment:
HOME: /var/lib/zrok-frontend
ZROK_DNS_ZONE: ${ZROK_DNS_ZONE} # e.g., "example.com" or "127.0.0.1.sslip.io"
ZROK_ADMIN_TOKEN: ${ZROK_ADMIN_TOKEN} # zrok controller admin password
ZROK_API_ENDPOINT: http://zrok-controller:${ZROK_CTRL_PORT:-18080} # bridge address of the zrok controller
ZITI_CTRL_ADVERTISED_PORT: ${ZITI_CTRL_ADVERTISED_PORT:-1280}
ZITI_PWD: ${ZITI_PWD} # ziti controller admin password
caddy:
profiles:
- zrok
build:
context: .
dockerfile: ./caddy.Dockerfile
args:
CADDY_DNS_PLUGIN: ${CADDY_DNS_PLUGIN} # e.g., "digitalocean" (see github.com/caddy-dns)
restart: unless-stopped
environment:
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
CADDY_ACME_EMAIL: ${CADDY_ACME_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"
ZROK_CTRL_PORT: ${ZROK_CTRL_PORT:-18080}
ZROK_FRONTEND_PORT: ${ZROK_FRONTEND_PORT:-8080}
ZROK_OAUTH_PORT: ${ZROK_OAUTH_PORT:-8081}
expose:
- 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}:443:443
# - ${CADDY_INTERFACE:-0.0.0.0}:443:443/udp" # future: HTTP/3 (QUIC)
volumes:
- caddy_data:/data
- caddy_config:/config
networks:
quickstart:
quickstart:
profiles:
- ziti
quickstart-check:
profiles:
- ziti
volumes:
caddy_data:
caddy_config:
zrok_ctrl:
zrok_frontend:

View File

@ -0,0 +1,42 @@
#!/usr/bin/env bash
set -o errexit
set -o nounset
set -o pipefail
# Read the shell-format template from stdin
TEMPLATE=$(cat)
# consume args as default values from a file or a list of shell commands
while (( $# )); do
if [ -s "$1" ]; then
# Read the default values from the file
# shellcheck disable=SC1090
source "$1"
else
# Use the argument as a shell command
eval "$1"
fi
shift
done
if [ -z "$TEMPLATE" ]; then
echo "Error: no template provided on stdin" >&2
exit 1
fi
# obtain the list of required variables
read -ra VARIABLES <<< "$(envsubst "$TEMPLATE" --variables)"
# Check that all required variables are set
for var in "${VARIABLES[@]}"; do
if [ -z "${!var:-}" ]; then
echo "Error: $var is null" >&2
exit 1
else
export "${var?}"
fi
done
# Render the template to stdout
envsubst <<< "$TEMPLATE"

View File

@ -0,0 +1,86 @@
#!/usr/bin/env bash
set -o errexit
set -o nounset
set -o pipefail
set -o xtrace
requireBashVersion() {
if (( "${BASH_VERSION%%.*}" < 4 )); then
echo "This script requires Bash major version 4 or greater."
echo "Detected version: $BASH_VERSION"
exit 1;
fi
}
fetchFile() {
local url="${1}"
local path="${2}"
if [[ -s "$path" ]]; then
echo "ERROR: file already exists: $path" >&2
return 1
fi
if { command -v curl > /dev/null; } 2>&1; then
curl -fLsS --output "${path}" "${url}"
elif { command -v wget > /dev/null; } 2>&1; then
wget --output-document "${path}" "${url}"
else
echo "ERROR: need one of curl or wget to fetch the artifact." >&2
return 1
fi
}
requireCommand() {
if ! command -v "$1" &>/dev/null; then
logError "this script requires command '$1'. Please install on the search PATH and try again."
$1
fi
}
setWorkingDir() {
workdir="${1}"
cd "${workdir}"
# Count non-hidden files
non_hidden_files=$(find . -maxdepth 1 -not -name '.*' | wc -l)
# Count hidden files
if ls -ld .[^.]* 2> /dev/null; then
hidden_files=0
for file in .[^.]*; do
if [[ -f "$file" ]]; then
hidden_files=$((hidden_files + 1))
fi
done
else
hidden_files=0
fi
# Calculate total number of files
total_files=$((non_hidden_files + hidden_files))
if (( total_files > 0 )); then
echo "WARN: working directory is not empty: ${workdir}" >&2
return 1
fi
}
main() {
requireBashVersion
declare -a BINS=(unzip find)
for BIN in "${BINS[@]}"; do
requireCommand "$BIN"
done
setWorkingDir "${1:-$PWD}" || {
echo "WARN: installing anyway in a few seconds...press Ctrl-C to abort" >&2
sleep 9
}
fetchFile "${ZITI_QUICK_COMPOSE:-"https://get.openziti.io/dock/all-in-one/compose.yml"}" "compose.yml"
fetchFile "${ZROK_REPO_ZIP:-"https://github.com/openziti/zrok/archive/refs/heads/main.zip"}" "zrok.zip"
unzip -j -d . zrok.zip '*/docker/compose/zrok-instance/*'
rm zrok.zip .gitignore fetch.bash
}
main "${@}"

View File

@ -0,0 +1,25 @@
# _____ __ ___ | | __
# |_ / '__/ _ \| |/ /
# / /| | | (_) | <
# /___|_| \___/|_|\_\
# controller configuration
v: 3
admin:
# generate these admin tokens from a source of randomness, e.g.
# LC_ALL=C tr -dc _A-Z-a-z-0-9 < /dev/urandom | head -c32
secrets:
- ${ZROK_ADMIN_TOKEN}
endpoint:
host: 0.0.0.0
port: ${ZROK_CTRL_PORT}
invites:
invites_open: true
token_strategy: store
store:
path: /var/lib/zrok-controller/sqlite3.db
type: sqlite3
ziti:
api_endpoint: https://ziti.${ZROK_DNS_ZONE}:${ZITI_CTRL_ADVERTISED_PORT}/edge/management/v1
username: admin
password: ${ZITI_PWD}

View File

@ -0,0 +1,37 @@
ARG ZROK_CLI_TAG=latest
ARG ZROK_CLI_IMAGE=openziti/zrok
FROM ${ZROK_CLI_IMAGE}:${ZROK_CLI_TAG}
# set up image as root
USER root
# install envsubst
RUN INSTALL_PKGS="gettext" && \
microdnf -y update --setopt=install_weak_deps=0 --setopt=tsflags=nodocs && \
microdnf -y install --setopt=install_weak_deps=0 --setopt=tsflags=nodocs ${INSTALL_PKGS}
ARG ZROK_DNS_ZONE
ARG ZROK_ADMIN_TOKEN
ARG ZROK_CTRL_PORT
ARG ZITI_CTRL_ADVERTISED_PORT
ARG ZITI_PWD
# render zrok controller config.yml
COPY ./envsubst.bash ./bootstrap-controller.bash /usr/local/bin/
RUN chmod 0755 /usr/local/bin/envsubst.bash /usr/local/bin/bootstrap-controller.bash
COPY ./zrok-controller-config.yml.envsubst /tmp/
RUN mkdir -p /etc/zrok-controller/
RUN envsubst.bash \
ZROK_DNS_ZONE=${ZROK_DNS_ZONE} \
ZROK_ADMIN_TOKEN=${ZROK_ADMIN_TOKEN} \
ZROK_CTRL_PORT=${ZROK_CTRL_PORT} \
ZITI_CTRL_ADVERTISED_PORT=${ZITI_CTRL_ADVERTISED_PORT} \
ZITI_PWD=${ZITI_PWD} \
< /tmp/zrok-controller-config.yml.envsubst > /etc/zrok-controller/config.yml
# run as ziggy (or ZIGGY_UID if set in compose project)
USER ziggy
ENV HOME=/var/lib/zrok-controller
WORKDIR /var/lib/zrok-controller
ENTRYPOINT ["bootstrap-controller.bash"]

View File

@ -0,0 +1,18 @@
v: 3
host_match: ${ZROK_DNS_ZONE}
address: 0.0.0.0:${ZROK_FRONTEND_PORT}
# delete if not using oauth for public shares
oauth:
bind_address: 0.0.0.0:${ZROK_OAUTH_PORT}
redirect_url: https://oauth.${ZROK_DNS_ZONE}
cookie_domain: ${ZROK_DNS_ZONE}
hash_key: ${ZROK_OAUTH_HASH_KEY}
providers:
- name: github
client_id: ${ZROK_OAUTH_GITHUB_CLIENT_ID}
client_secret: ${ZROK_OAUTH_GITHUB_CLIENT_SECRET}
- name: google
client_id: ${ZROK_OAUTH_GOOGLE_CLIENT_ID}
client_secret: ${ZROK_OAUTH_GOOGLE_CLIENT_SECRET}

View File

@ -0,0 +1,43 @@
ARG ZROK_CLI_TAG=latest
ARG ZROK_CLI_IMAGE=openziti/zrok
FROM ${ZROK_CLI_IMAGE}:${ZROK_CLI_TAG}
# set up image as root
USER root
# install envsubst
RUN INSTALL_PKGS="gettext" && \
microdnf -y update --setopt=install_weak_deps=0 --setopt=tsflags=nodocs && \
microdnf -y install --setopt=install_weak_deps=0 --setopt=tsflags=nodocs ${INSTALL_PKGS}
ARG ZROK_DNS_ZONE
ARG ZROK_FRONTEND_PORT
ARG ZROK_OAUTH_PORT
ARG ZROK_OAUTH_HASH_KEY
ARG ZROK_OAUTH_GOOGLE_CLIENT_ID
ARG ZROK_OAUTH_GOOGLE_CLIENT_SECRET
ARG ZROK_OAUTH_GITHUB_CLIENT_ID
ARG ZROK_OAUTH_GITHUB_CLIENT_SECRET
# render zrok frontend config.yml
COPY ./envsubst.bash ./bootstrap-frontend.bash /usr/local/bin/
RUN chmod 0755 /usr/local/bin/envsubst.bash /usr/local/bin/bootstrap-frontend.bash
COPY ./zrok-frontend-config.yml.envsubst /tmp/
RUN mkdir -p /etc/zrok-frontend/
RUN envsubst.bash \
ZROK_DNS_ZONE=${ZROK_DNS_ZONE} \
ZROK_FRONTEND_PORT=${ZROK_FRONTEND_PORT} \
ZROK_OAUTH_PORT=${ZROK_OAUTH_PORT} \
ZROK_OAUTH_HASH_KEY=${ZROK_OAUTH_HASH_KEY} \
ZROK_OAUTH_GOOGLE_CLIENT_ID=${ZROK_OAUTH_GOOGLE_CLIENT_ID} \
ZROK_OAUTH_GOOGLE_CLIENT_SECRET=${ZROK_OAUTH_GOOGLE_CLIENT_SECRET} \
ZROK_OAUTH_GITHUB_CLIENT_ID=${ZROK_OAUTH_GITHUB_CLIENT_ID} \
ZROK_OAUTH_GITHUB_CLIENT_SECRET=${ZROK_OAUTH_GITHUB_CLIENT_SECRET} \
< /tmp/zrok-frontend-config.yml.envsubst > /etc/zrok-frontend/config.yml
# run as ziggy (or ZIGGY_UID if set in compose project)
USER ziggy
ENV HOME=/var/lib/zrok-frontend
WORKDIR /var/lib/zrok-frontend
ENTRYPOINT ["bootstrap-frontend.bash"]

View File

@ -1,7 +1,7 @@
# this builds docker.io/openziti/zrok
ARG ZITI_CLI_TAG="0.32.1"
ARG ZITI_CLI_TAG="1.0.0"
ARG ZITI_CLI_IMAGE="docker.io/openziti/ziti-cli"
# this builds docker.io/openziti/ziti-controller
FROM ${ZITI_CLI_IMAGE}:${ZITI_CLI_TAG}
ARG ARTIFACTS_DIR=./dist
@ -20,16 +20,12 @@ LABEL name="openziti/zrok" \
USER root
### install packages: findutils provides xargs which is used by the zrok Helm chart's controller bootstrapping script to
#create the default account enable token
RUN INSTALL_PKGS="findutils" && \
microdnf -y update --setopt=install_weak_deps=0 --setopt=tsflags=nodocs && \
microdnf -y install --setopt=install_weak_deps=0 --setopt=tsflags=nodocs ${INSTALL_PKGS}
### add licenses to this directory
RUN mkdir -p -m0755 /licenses
COPY ./LICENSE /licenses/apache.txt
ENV PFXLOG_NO_JSON=true
RUN mkdir -p /usr/local/bin
COPY ${ARTIFACTS_DIR}/${TARGETARCH}/${TARGETOS}/zrok \
./nfpm/zrok-enable.bash \
@ -40,5 +36,5 @@ RUN chmod 0755 \
/usr/local/bin/zrok-enable.bash \
/usr/local/bin/zrok-share.bash
USER nobody
USER ziggy
ENTRYPOINT [ "zrok" ]

View File

@ -6,7 +6,7 @@ sidebar_position: 200
## Self-Hosted
`zrok` is not limited to a managed offering. You can [host your own](../guides/self-hosting/self_hosting_guide.md) instance of `zrok` as well. `zrok` is
`zrok` is not limited to a managed offering. You can [host your own](/guides/self-hosting/linux.mdx) instance of `zrok` as well. `zrok` is
also freely available as open source software hosted by GitHub under a very permissive Apache v2 license.
## Managed Service

View File

@ -10,4 +10,4 @@ sidebar_position: 25
Sharing with `zrok` can be either [`public`](./sharing-public.md) or [`private`](./sharing-private.md).
Naturally, regular web-based resources can be shared but `zrok` also includes support for sharing raw [TCP](./tunnels.md) and [UDP](./tunnels.md) network connections, and also includes a [website and file sharing](./files.md) feature.
Learn about `zrok` [hosting here](./hosting.md), including instructions on how to [install your own `zrok` instance](../guides/self-hosting/self_hosting_guide.md).
Learn about `zrok` [hosting here](./hosting.md), including instructions on how to [install your own `zrok` instance](/guides/self-hosting/linux.mdx).

View File

@ -4,7 +4,7 @@ sidebar_position: 0
# Private Shares
`zrok` was built to share and access digital resources. A `private` share allows a resource to be
accessed on another user's system as if it were local to them. Privately shared resources can only be accessed by another `zrok` user who has the details of your unique share. You are in control of who can access your `private` shares by sharing the the share token.
accessed on another user's system as if it were local to them. Privately shared resources can only be accessed by another `zrok` user who has the details of your unique share. You are in control of who can access your `private` shares by sharing the share token.
Peer-to-peer private resource sharing is one of the things that makes `zrok` unique.
@ -26,4 +26,4 @@ The shared resource can be a development web server to share with friends and co
The peer-to-peer capabilities of `zrok` are an important property of the underlying [OpenZiti](https://docs.openziti.io/docs/learn/introduction/) network that `zrok` uses to provide connectivity between users and resources.
Creating `private` shares is easy and is accomplished using the `zrok share private` command. Run `zrok share private` to see the usage output and to further learn how to use the command.
Creating `private` shares is easy and is accomplished using the `zrok share private` command. Run `zrok share private` to see the usage output and to further learn how to use the command.

View File

@ -356,7 +356,7 @@ You use the `zrok reserve` command to create _reserved shares_. Reserved shares
## Self-Hosting an Instance
Interested in self-hosting your own `zrok` instance? See the [self-hosting guide](./guides/self-hosting/self_hosting_guide.md) for details.
Interested in self-hosting your own `zrok` instance? See the [self-hosting guide](./guides/self-hosting/linux.mdx) for details.
[openziti]: https://docs.openziti.io/docs/learn/introduction/ "OpenZiti"
[ zrok-download]: https://zrok.io "zrok Download"

View File

@ -1,134 +0,0 @@
## Goal
Proxy a reserved public subdomain to a backend target with an always-on Docker Compose service.
## How it Works
The Docker Compose project uses your zrok account token to reserve a public subdomain and keep sharing the backend
target.
When the project runs it will:
1. enable a zrok environment unless `/mnt/.zrok/environment.json` exists in the `zrok_env` volume
1. reserve a public subdomain for the service unless `/mnt/.zrok/reserved.json` exists
1. start sharing the target specified in the `ZROK_TARGET` environment variable
## Create the Docker Project
1. Make a folder on your computer to use as a Docker Compose project for your zrok public share with a reserved subdomain and switch to the new directory in your terminal.
1. Download [the reserved public share `compose.yml` project file](pathname:///zrok-public-reserved/compose.yml) into the same directory.
1. Copy your zrok account's enable token from the zrok web console to your clipboard and paste it in a file named `.env` in the same folder like this:
```bash title=".env"
ZROK_ENABLE_TOKEN="8UL9-48rN0ua"
```
1. Name the Share
This unique name becomes part of the domain name of the share, e.g. `https://my-prod-app.in.zrok.io`. A random name is generated if you don't specify one.
```bash title=".env"
ZROK_UNIQUE_NAME="my-prod-app"
```
1. Run the Compose project to start sharing the built-in demo web server. Be sure to `--detach` so the project runs in the background if you want it to auto-restart when your computer reboots.
```bash
docker compose up --detach
```
1. Get the public share URL from the output of the `zrok-share` service or by peeking in the zrok console where the share will appear in the graph.
```bash
docker compose logs zrok-share
```
```buttonless title="Output"
zrok-public-share-1 | https://w6r1vesearkj.in.zrok.io/
```
This concludes the minimum steps to begin sharing the demo web server. Read on to learn how to pivot to sharing any website or web service by leveraging additional zrok backend modes.
## Proxy Any Web Server
The simplest way to share your existing HTTP server is to set `ZROK_TARGET` (e.g. `https://example.com`) in the environment of the `docker compose up` command. When you restart the share will auto-configure for that URL.
```bash title=".env"
ZROK_TARGET="http://example.com:8080"
```
```bash
docker compose down && docker compose up
```
## Require Authentication
You can require a password or an OAuth login with certain email addresses.
### OAuth Email
You can allow specific email addresses or an email domain by setting `ZROK_OAUTH_PROVIDER` to `github` or `google` and
`ZROK_SHARE_OPTS` to specify additional command-line options to `zrok reserve public`. Read more about the OAuth
features in [this blog post](https://blog.openziti.io/the-zrok-oauth-public-frontend).
```bash title=".env"
ZROK_OAUTH_PROVIDER="github"
ZROK_OAUTH_EMAILS="alice@example.com *@acme.example.com"
```
## Caddy is Powerful
The reserved public share project uses zrok's default backend mode, `proxy`. Another backend mode, `caddy`, accepts a path to [a Caddyfile](https://caddyserver.com/docs/caddyfile) as the value of `ZROK_TARGET` ([zrok Caddyfile examples](https://github.com/openziti/zrok/tree/main/etc/caddy)).
Caddy is the most powerful and flexible backend mode in zrok. You must reserve a new public subdomain whenever you switch the backend mode, so using `caddy` reduces the risk that you'll have to share a new frontend URL with your users.
With Caddy, you can balance the workload for websites or web services or share static sites and files or all of the above at the same time. You can update the Caddyfile and restart the Docker Compose project to start sharing the new configuration with the same reserved public subdomain.
1. Create a Caddyfile. This example demonstrates proxying two HTTP servers with a weighted round-robin load balancer.
```console title="Caddyfile"
http:// {
# zrok requires this bind address template
bind {{ .ZrokBindAddress }}
reverse_proxy /* {
to http://httpbin1:8080 http://httpbin2:8080
lb_policy weighted_round_robin 3 2
}
}
```
1. Create a file `compose.override.yml`. This example adds two `httpbin` containers for load balancing, and mounts the Caddyfile into the container.
```yaml title="compose.override.yml"
services:
httpbin1:
image: mccutchen/go-httpbin # 8080/tcp
httpbin2:
image: mccutchen/go-httpbin # 8080/tcp
zrok-share:
volumes:
- ./Caddyfile:/mnt/.zrok/Caddyfile
```
1. Start a new Docker Compose project or delete the existing state volume.
```bash
docker compose down --volumes
```
If you prefer to keep using the same zrok environment with the new share then delete `/mnt/.zrok/reserved.json` instead of the entire volume.
1. Run the project to load the new configuration.
```bash
docker compose up --detach
```
1. Note the new reserved share URL from the log.
```bash
docker compose logs zrok-share
```
```buttonless title="Output"
INFO: zrok public URL: https://88s803f2qvao.in.zrok.io/
```

View File

@ -2,6 +2,7 @@
"label": "Docker Share",
"position": 40,
"link": {
"type": "generated-index"
"type": "doc",
"id": "guides/docker-share/index"
}
}

View File

@ -1,12 +1,16 @@
---
title: Docker Private Share
sidebar_position: 20
sidebar_label: Private Share
---
## Goal
# Docker Private Share
Privately share a Docker Compose service with a separate zrok environment and a permanent zrok share token.
With zrok, you can privately share a server app that's running in Docker, or any server that's reachable by the zrok container. Then, a zrok private access running somewhere else can use the private share. In this guide we'll cover both sides: the private share and the private access.
## Overview
With zrok, you can privately share a service that's running in Docker. You need a zrok private share running somewhere that it can reach the service you're sharing, and a zrok private access running somewhere else where you want to use the private share. Together, the private share and private access form a private point-to-point tunnel.
Here's a short article with an overview of [private sharing with zrok](/concepts/sharing-private.md).
@ -14,6 +18,16 @@ Here's a short article with an overview of [private sharing with zrok](/concepts
<iframe width="100%" height="315" src="https://www.youtube.com/embed/HxyvtFAvwUE" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
## How it Works
The Docker Compose project uses your zrok account token to reserve a private share token and keep sharing the backend target.
When the project runs it will:
1. enable a zrok environment unless `/mnt/.zrok/environment.json` exists in the `zrok_env` volume
1. reserve a private share token for the service unless `/mnt/.zrok/reserved.json` exists
1. start sharing the target specified in the `ZROK_TARGET` environment variable
## Before You Begin
To follow this guide you will need [Docker](https://docs.docker.com/get-docker/) and [the Docker Compose plugin](https://docs.docker.com/compose/install/) for running `docker compose` commands in your terminal.

View File

@ -1,10 +1,16 @@
---
title: Docker Public Share
title: Docker Compose Public Share
sidebar_position: 10
sidebar_label: Public Share
---
With zrok and Docker, you can publicly share a web server that's running in a local container or anywhere that's reachable by the zrok container. The share can be reached through a temporary public URL that expires when the container is stopped. If you're looking for a reserved subdomain for the share, check out [zrok frontdoor](/guides/frontdoor.mdx).
## Goal
Publicly share a Docker Compose service with a separate zrok environment and a permanent zrok share URL.
## Overview
With zrok, you can publicly share a service that's running in Docker. You need a zrok public share running somewhere that it can reach the service you're sharing. As long as that public share is running and your service is available, anyone with the address can use your service.
Here's a short article with an overview of [public sharing with zrok](/concepts/sharing-public.md).
@ -12,101 +18,134 @@ Here's a short article with an overview of [public sharing with zrok](/concepts/
<iframe width="100%" height="315" src="https://www.youtube.com/embed/ycov--9ZtB4" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
## Before You Begin
## How it Works
To follow this guide you will need [Docker](https://docs.docker.com/get-docker/) and [the Docker Compose plugin](https://docs.docker.com/compose/install/) for running `docker compose` commands in your terminal.
The Docker Compose project uses your zrok account token to reserve a public subdomain and keep sharing the backend
target.
## Begin Sharing with Docker Compose
When the project runs it will:
A temporary public share is a great way to share a web server running in a container with someone else for a short time.
1. enable a zrok environment unless `/mnt/.zrok/environment.json` exists in the `zrok_env` volume
1. reserve a public subdomain for the service unless `/mnt/.zrok/reserved.json` exists
1. start sharing the target specified in the `ZROK_TARGET` environment variable
1. Make a folder on your computer to use as a Docker Compose project for your zrok public share.
1. In your terminal, change directory to the newly-created project folder.
1. Download [the temporary public share project file](pathname:///zrok-public-share/compose.yml).
1. Copy your zrok environment token from the zrok web console to your clipboard and paste it in a file named `.env` in the same folder like this:
## Create the Docker Project
```bash title=".env"
ZROK_ENABLE_TOKEN="8UL9-48rN0ua"
```
1. Make a folder on your computer to use as a Docker Compose project for your zrok public share with a reserved subdomain and switch to the new directory in your terminal.
1. Download [the reserved public share `compose.yml` project file](pathname:///zrok-public-reserved/compose.yml) into the same directory.
1. Copy your zrok account's enable token from the zrok web console to your clipboard and paste it in a file named `.env` in the same folder like this:
1. Set the zrok API endpoint if self-hosting zrok. Skip this if using zrok.io.
```bash title=".env"
ZROK_ENABLE_TOKEN="8UL9-48rN0ua"
```
```bash title=".env"
ZROK_API_ENDPOINT="https://zrok.example.com"
```
1. Name the Share
1. Run the Compose project to start sharing the built-in demo web server.
This unique name becomes part of the domain name of the share, e.g. `https://my-prod-app.in.zrok.io`. A random name is generated if you don't specify one.
```bash
docker compose up --detach
```
```bash title=".env"
ZROK_UNIQUE_NAME="my-prod-app"
```
1. Get the public share URL from the output of the `zrok-share` service or by peeking in the zrok console where the share will be graphed.
1. Run the Compose project to start sharing the built-in demo web server. Be sure to `--detach` so the project runs in the background if you want it to auto-restart when your computer reboots.
```bash
docker compose logs zrok-share
```
```bash
docker compose up --detach
```
```buttonless title="Output"
zrok-public-share-1 | https://w6r1vesearkj.in.zrok.io/
```
1. Get the public share URL from the output of the `zrok-share` service or by peeking in the zrok console where the share will appear in the graph.
This concludes sharing the demo web server. Read on to learn how to pivot to sharing any web server leveraging additional zrok backend modes.
```bash
docker compose logs zrok-share
```
```buttonless title="Output"
zrok-public-share-1 | https://w6r1vesearkj.in.zrok.io/
```
This concludes the minimum steps to begin sharing the demo web server. Read on to learn how to pivot to sharing any website or web service by leveraging additional zrok backend modes.
## Proxy Any Web Server
The simplest way to share your web server is to set `ZROK_TARGET` (e.g. `https://example.com`) in the environment file.
The simplest way to share your existing HTTP server is to set `ZROK_TARGET` (e.g. `https://example.com`) in the environment of the `docker compose up` command. When you restart the share will auto-configure for that URL.
```bash title=".env"
ZROK_TARGET="http://example.com:8080"
```
```bash
docker compose down && docker compose up
```
## Require Authentication
You can require authentication for your public share by setting `ZROK_OAUTH_PROVIDER` to `github` or `google` with zrok.io. You could parse the authenticated email address from the request cookie if you're building a custom server app. Read more about the OAuth features in [this blog post](https://blog.openziti.io/the-zrok-oauth-public-frontend).
You can require a password or an OAuth login with certain email addresses.
### OAuth Email
You can allow specific email addresse patterns by setting `ZROK_OAUTH_PROVIDER` to `github` or `google` and
`ZROK_OAUTH_EMAILS`. Read more about the OAuth features in [this blog
post](https://blog.openziti.io/the-zrok-oauth-public-frontend).
```bash title=".env"
ZROK_OAUTH_PROVIDER="github"
ZROK_OAUTH_EMAILS="alice@example.com *@acme.example.com"
```
## Customize Temporary Public Share
## Caddy is Powerful
This technique is useful for adding a containerized service to the project, or mounting a filesystem directory into the container to share as a static website or file server.
The reserved public share project uses zrok's default backend mode, `proxy`. Another backend mode, `caddy`, accepts a path to [a Caddyfile](https://caddyserver.com/docs/caddyfile) as the value of `ZROK_TARGET` ([zrok Caddyfile examples](https://github.com/openziti/zrok/tree/main/etc/caddy)).
Any additional services specified in the override file will be merged with `compose.yml` when you `up` the project.
Caddy is the most powerful and flexible backend mode in zrok. You must reserve a new public subdomain whenever you switch the backend mode, so using `caddy` reduces the risk that you'll have to share a new frontend URL with your users.
You may override individual values from in `compose.yml` by specifying them in the override file.
With Caddy, you can balance the workload for websites or web services or share static sites and files or all of the above at the same time. You can update the Caddyfile and restart the Docker Compose project to start sharing the new configuration with the same reserved public subdomain.
1. Create a file `compose.override.yml`. This example demonstrates sharing a static HTML directory `/tmp/html` from the Docker host's filesystem.
1. Create a Caddyfile. This example demonstrates proxying two HTTP servers with a weighted round-robin load balancer.
```yaml title="compose.override.yml"
services:
zrok-share:
command: share public --headless --backend-mode web /tmp/html
volumes:
- /tmp/html:/tmp/html
```
1. Re-run the project to load the new configuration.
```bash
docker compose up --force-recreate --detach
```
1. Get the new tempoary public share URL for the `zrok-share` container.
```bash
docker compose logs zrok-share
```
```buttonless title="Output"
zrok-public-share-1 | https://w6r1vesearkj.in.zrok.io/
```console title="Caddyfile"
http:// {
# zrok requires this bind address template
bind {{ .ZrokBindAddress }}
reverse_proxy /* {
to http://httpbin1:8080 http://httpbin2:8080
lb_policy weighted_round_robin 3 2
}
}
```
## Destroy the zrok Environment
1. Create a file `compose.override.yml`. This example adds two `httpbin` containers for load balancing, and mounts the Caddyfile into the container.
This destroys the Docker volumes containing the zrok environment secrets. The zrok environment can also be destroyed in the web console.
```yaml title="compose.override.yml"
services:
httpbin1:
image: mccutchen/go-httpbin # 8080/tcp
httpbin2:
image: mccutchen/go-httpbin # 8080/tcp
zrok-share:
volumes:
- ./Caddyfile:/mnt/.zrok/Caddyfile
```
```bash
docker compose down --volumes
```
1. Start a new Docker Compose project or delete the existing state volume.
```bash
docker compose down --volumes
```
If you prefer to keep using the same zrok environment with the new share then delete `/mnt/.zrok/reserved.json` instead of the entire volume.
1. Run the project to load the new configuration.
```bash
docker compose up --detach
```
1. Note the new reserved share URL from the log.
```bash
docker compose logs zrok-share
```
```buttonless title="Output"
INFO: zrok public URL: https://88s803f2qvao.in.zrok.io/
```

View File

@ -0,0 +1,112 @@
---
title: Getting Started with Docker
---
import Details from '@theme/MDXComponents/Details';
## Overview
To follow the guides in this section you will need [Docker](https://docs.docker.com/get-docker/).
You have the option to enable a `zrok` account on the Docker host and mount it on the container or you can use the provided Docker Compose project files (`compose.yml`) to enable a separate `zrok` environment for each project.
This page provides `docker` and `docker compose` examples of mounting the host's `zrok` environment on the container. You'll need to first [enable zrok on the Docker host](/docs/getting-started/#installing-the-zrok-command) to use this approach.
## Permanent Public Share
Let's say you have a `compose.yml` file that defines a web app known within the project's bridge network as `https://myapp:8080` and you want to publish it as a reliable, public site.
1. Reserve a subdomain by running `zrok reserve public --unique-name "myapp" https://myapp:8080` on the Docker host.
1. Merge this YAML with `compose.yml` or save it in the same directory as `compose.override.yml` to let `docker compose up` merge it for you.
```yaml
services:
zrok:
image: openziti/zrok
restart: unless-stopped
user: "${UID}"
volumes:
- ${HOME}/.zrok:/.zrok
environment:
PFXLOG_NO_JSON: "true"
command: share reserved "myapp" --headless
```
The reserved share will be available at `https://myapp.share.zrok.io` each time the `zrok` container starts up.
## Temporary Public Share
Let's say you have a web server running on the host's private network at `https://10.11.12.13:8080`. With one additional `docker` command, you can share the web server publicly as long as the `zrok` container stays running.
```bash title="BASH"
docker run \
--rm \
--network=host \
--volume ~/.zrok:/.zrok \
--user "${UID}" \
openziti/zrok share public \
--headless \
https://10.11.12.13:8080
```
<Details>
<summary>PowerShell</summary>
```powershell
docker.exe run `
--rm `
--network "host" `
--volume "${env:USERPROFILE}\.zrok:/.zrok" `
--user "1000" `
openziti/zrok share public `
--headless `
https://10.11.12.13:8080
```
</Details>
<Details>
<summary>Command Prompt (batch)</summary>
```cmd
docker.exe run ^
--rm ^
--network "host" ^
--volume "%USERPROFILE%\.zrok:/.zrok" ^
--user "1000" ^
openziti/zrok share public ^
--headless ^
https://10.11.12.13:8080
```
</Details>
<Details>
<summary>Windows Subsystem for Linux (WSL)</summary>
```bash
docker run \
--rm \
--network "host" \
--volume "/mnt/c/Users/$(powershell.exe -Command 'Write-Output $env:USERNAME' | tr -d '\r')/.zrok:/.zrok" \
--user "$UID" \
openziti/zrok share public \
--headless \
https://10.11.12.13:8080
```
</Details>
The public share URL appears near the beginning of the container's log.
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. `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.
1. `https://10.11.12.13:8080` is the target web server to share.

View File

@ -8,7 +8,6 @@ hide_table_of_contents: true
import OsTabs from '@theme/OsTabs';
import TabItem from '@theme/TabItem';
import LinuxService from './_frontdoor-linux.mdx';
import ReservedDocker from './_frontdoor-docker.mdx';
import ThemedImage from '@theme/ThemedImage';
import useBaseUrl from '@docusaurus/useBaseUrl';
@ -37,8 +36,7 @@ Choose between installing the Linux package or running zrok with Docker (Linux,
queryString="os"
values={[
{ label: 'Linux', value: 'Linux', },
{ label: 'macOS', value: 'Mac OS', },
{ label: 'Windows', value: 'Windows', },
{ label: 'Docker', value: 'Docker', },
]}
>
@ -46,25 +44,13 @@ Choose between installing the Linux package or running zrok with Docker (Linux,
On Linux, zrok frontdoor is implemented natively as a system service provided by the `zrok-share` DEB or RPM package.
If you'd prefer to run zrok in Docker instead of installing the package then you can follow the Docker instructions. With Docker, the steps are the same for Linux, [macOS](./?os=Mac+OS), and [Windows](./?os=Windows).
<LinuxService/>
</TabItem>
<TabItem value="Mac OS">
<TabItem value="Docker">
On macOS, zrok frontdoor is implemented as a Docker Compose project which reserves a public subdomain for your website or service.
<ReservedDocker/>
</TabItem>
<TabItem value="Windows">
On Windows, zrok frontdoor is implemented as a Docker Compose project which reserves a public subdomain for your website or service.
<ReservedDocker/>
On macOS and Windows, zrok frontdoor is implemented as a Docker Compose project which reserves a public subdomain for your website or service and manages a zrok environment that's separate from the Docker host. [Link to the Docker Public Share Guide](/guides/docker-share/docker_public_share_guide.md)
</TabItem>

View File

@ -0,0 +1,9 @@
---
title: Self-hosting guide for Docker
sidebar_label: Docker
sidebar_position: 45
---
import DockerInstance from '/../docker/compose/zrok-instance/README.md'
<DockerInstance />

View File

@ -1,10 +1,9 @@
---
sidebar_position: 40
sidebar_label: Linux VPS
title: Self-Hosting Guide for Linux
sidebar_label: Linux
---
# Self-Hosting Guide for Linux
## Walkthrough Video
<iframe width="100%" height="315" src="https://www.youtube.com/embed/870A5dke_u4" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
@ -110,7 +109,7 @@ With your OpenZiti network running and your configuration saved to a local file
Use the `zrok admin bootstrap` command to bootstrap like this:
```bash
$ zrok admin bootstrap etc/ctrl.yml
$ zrok admin bootstrap etc/ctrl.yml
[ 0.002] INFO main.(*adminBootstrap).run: {
...
}
@ -146,6 +145,8 @@ Notice this warning:
[ 0.120] WARNING zrok/controller.Bootstrap: missing public frontend for ziti id 'sqJRAINSiB'; please use 'zrok admin create frontend sqJRAINSiB public https://{token}.your.dns.name' to create a frontend instance
```
If you find it necessary to re-run the `zrok admin bootstrap` command, you may need to add the `--skip-frontend` flag to avoid re-creating the default `public` frontend's Ziti identity and router policy.
## Run zrok Controller
The `zrok` bootstrap process wants us to create a "public frontend" for our service. `zrok` uses public frontends to allow users to specify where they would like public traffic to ingress from.
@ -180,15 +181,14 @@ $ zrok admin create frontend sqJRAINSiB public http://{token}.zrok.quigley.com:8
The id of the frontend was emitted earlier in by the zrok controller when we ran the bootstrap command. If you don't have that log message the you can find the id again with the `ziti` CLI like this:
```bash
# initialize the Ziti quickstart env
source ~/.ziti/quickstart/$(hostname -s)/$(hostname -s).env
# login as admin
zitiLogin
# log in as admin (example)
ziti edge login localhost:1280 -u admin -p XO0xHp75uuyeireO2xmmVlK91T7B9fpD
# list Ziti identities created by the quickstart and bootstrap
ziti edge list identities
```
The id is shown for the "frontend" identity.
The id is shown for the frontend identity named "public."
Nice work! The `zrok` controller is fully configured now that you have created the zrok frontend.
@ -217,10 +217,10 @@ $ zrok access public etc/http-frontend.yml
[ 0.002] INFO main.(*accessPublicCommand).run: {
...
}
[ 0.002] INFO zrok/endpoints/public_frontend.newMetricsAgent: loaded 'frontend' identity
[ 0.002] INFO zrok/endpoints/public_frontend.newMetricsAgent: loaded 'public' identity
```
This process uses the `frontend` identity created during the bootstrap process to provide public access for the `zrok` deployment. It is expected that the configured listener for this `frontend` corresponds to the DNS template specified when creating the public frontend record above.
The zrok frontend uses the `public` identity created during the bootstrap process to securely access zrok backends. to provide public access for the `zrok` deployment. It is expected that the configured listener for this frontend corresponds to the DNS template specified when creating the public frontend record above.
## Invite Yourself

View File

@ -1,9 +1,9 @@
---
sidebar_position: 50
sidebar_label: Nginx TLS
sidebar_label: NGINX TLS
---
# Nginx Reverse Proxy for zrok
# NGINX Reverse Proxy for zrok
## Walkthrough Video
@ -11,7 +11,7 @@ sidebar_label: Nginx TLS
## Before You Begin
I'll assume you have a running zrok controller and public frontend and wish to front both with Nginx providing server TLS. Go back to [Self-Hosting Guide](./self_hosting_guide.md) if you still need to spin those up.
I'll assume you have a running zrok controller and frontend and wish to front both with NGINX providing server TLS. Go back to [Self-Hosting Guide](./linux.mdx) if you still need to spin those up.
## Choose a Reverse Proxy Address
@ -29,9 +29,9 @@ You must complete a DNS challenge to obtain a wildcard certificate from Let's En
sudo certbot certonly --manual
````
## [Install Nginx](https://www.nginx.com/resources/wiki/start/topics/tutorials/install/)
## [Install NGINX](https://www.nginx.com/resources/wiki/start/topics/tutorials/install/)
## Configure Nginx
## Configure NGINX
```
server {
@ -78,15 +78,15 @@ server {
}
```
## Restart Nginx
## Restart NGINX
Load the new configuration by restarting Nginx. Check the logs to make sure it's happy.
Load the new configuration by restarting NGINX. Check the logs to make sure it's happy.
> Started A high performance web server and a reverse proxy server.
## Check the Firewall
If you followed the non-TLS quickstart then you may have opened 8080,108080/tcp in your firewall. You can go ahead and replace those exceptions with 443/tcp because only Nginx needs to be reachable for zrok to function.
If you followed the non-TLS quickstart then you may have opened 8080,108080/tcp in your firewall. You can go ahead and replace those exceptions with 443/tcp because only NGINX needs to be reachable for zrok to function.
## Update the zrok Frontend
@ -99,7 +99,7 @@ $ zrok admin list frontends
2NiDTRYUww18 7DsLh9DXG public http://{token}.zrok.quigley.com:8080 2023-01-19 05:29:20.793 +0000 UTC 2023-01-19 06:17:25 +0000 UTC
```
Update the URL template to use Nginx.
Update the URL template to use NGINX.
```bash
$ zrok admin update frontend 2NiDTRYUww18 --url-template https://{token}.zrok.quigley.com:443

Binary file not shown.

After

Width:  |  Height:  |  Size: 170 KiB

120
docs/guides/vpn/vpn.md Normal file
View File

@ -0,0 +1,120 @@
---
sidebar_label: VPN
---
# zrok VPN Guide
zrok VPN backend allows for simple host-to-host VPN setup.
## Starting VPN server
VPN is shared through the `vpn` backend of `zrok` command.
```
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:
zrok access private 3rq7torslq3n
[ 0.705] INFO zrok/endpoints/vpn.(*Backend).Run: started
```
![VPN share](./vpn-share.png)
`sudo` or equivalent invocation is required because VPN mode needs to create a virtual network device (`tun`)
`-E` option allows `zrok` to find your zrok configuration files (in your `$HOME/.zrok`)
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
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>
inet6 fd00:7a72:6f6b::1 prefixlen 64 scopeid 0x0<global>
unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 txqueuelen 500 (UNSPEC)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 27 bytes 3236 (3.2 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
```
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
```
## VPN share reservation
Share reservation works the same as with other backend types:
```
eugene@hermes $ zrok reserve private -b vpn
[ 0.297] INFO main.(*reserveCommand).run: your reserved share token is 'k77y2cl7jmjl'
eugene@hermes $ sudo -E zrok share reserved k77y2cl7jmjl --headless
[ 0.211] INFO main.(*shareReservedCommand).run: sharing target: '10.122.0.1/16'
[ 0.211] INFO main.(*shareReservedCommand).run: using existing backend proxy endpoint: 10.122.0.1/16
[ 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
Accessing a VPN share works similar to other backends.
```
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:
[ 0.662] INFO main.(*accessPrivateCommand).run: 10.122.0.1 -> CONNECTED Welcome to zrok VPN
[ 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:
```
eugene@calculon ~ % ifconfig
...
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.
```
eugene@calculon ~ % ssh eugene@10.122.0.1
Welcome to Ubuntu 23.10 (GNU/Linux 6.5.0-27-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/pro
0 updates can be applied immediately.
Last login: Tue Apr 16 09:27:13 2024 from 127.0.0.1
eugene@hermes:~$ who am i
eugene pts/8 2024-04-16 10:04 (10.122.0.3)
eugene@hermes:~$
```
You can also make a reverse(server-to-client) connection:
```
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 ~ %
```

267
endpoints/vpn/backend.go Normal file
View File

@ -0,0 +1,267 @@
package vpn
import (
"encoding/json"
"github.com/google/go-cmp/cmp"
"github.com/net-byte/vtun/common/config"
"github.com/net-byte/vtun/tun"
_ "github.com/net-byte/vtun/tun"
"github.com/net-byte/water"
"github.com/openziti/sdk-golang/ziti"
"github.com/openziti/sdk-golang/ziti/edge"
"github.com/openziti/zrok/endpoints"
cmap "github.com/orcaman/concurrent-map/v2"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/songgao/water/waterutil"
"io"
"net"
"strconv"
"sync/atomic"
"time"
)
type BackendConfig struct {
IdentityPath string
EndpointAddress string
ShrToken string
RequestsChan chan *endpoints.Request
}
type client struct {
conn net.Conn
}
type Backend struct {
cfg *BackendConfig
listener edge.Listener
addr net.IP
addr6 net.IP
subnet *net.IPNet
subnet6 *net.IPNet
tun *water.Interface
mtu int
counter atomic.Uint32
clients cmap.ConcurrentMap[dest, *client]
}
func NewBackend(cfg *BackendConfig) (*Backend, error) {
options := ziti.ListenOptions{
ConnectTimeout: 5 * time.Minute,
WaitForNEstablishedListeners: 1,
}
zcfg, err := ziti.NewConfigFromFile(cfg.IdentityPath)
if err != nil {
return nil, errors.Wrap(err, "error loading config")
}
zctx, err := ziti.NewContext(zcfg)
if err != nil {
return nil, errors.Wrap(err, "error loading ziti context")
}
listener, err := zctx.ListenWithOptions(cfg.ShrToken, &options)
if err != nil {
return nil, errors.Wrap(err, "error listening")
}
addr6 := zrokIPv6Addr
addr4 := zrokIPv4Addr
sub4 := zrokIPv4
sub6 := zrokIPv6
if cfg.EndpointAddress != "" {
addr4, sub4, err = net.ParseCIDR(cfg.EndpointAddress)
if err != nil {
return nil, errors.Wrap(err, "failed to parse VPN subnet config")
}
}
b := &Backend{
cfg: cfg,
listener: listener,
mtu: ZROK_VPN_MTU,
clients: cmap.NewWithCustomShardingFunction[dest, *client](func(key dest) uint32 {
return key.toInt32()
}),
addr: addr4,
addr6: addr6,
subnet: sub4,
subnet6: sub6,
}
b.counter.Store(1)
return b, nil
}
func (b *Backend) readTun() {
buf := make([]byte, ZROK_VPN_MTU)
for {
n, err := b.tun.Read(buf)
if err != nil {
logrus.WithError(err).Error("failed to read tun device")
// handle? error
panic(err)
return
}
pkt := packet(buf[:n])
if !waterutil.IsIPv4(pkt) {
continue
}
logrus.WithField("packet", pkt).Trace("read from tun device")
dest := pkt.destination()
if clt, ok := b.clients.Get(dest); ok {
_, err := clt.conn.Write(pkt)
if err != nil {
b.cfg.RequestsChan <- &endpoints.Request{
Stamp: time.Now(),
RemoteAddr: dest.String(),
Method: "DISCONNECTED",
}
logrus.WithError(err).Errorf("failed to write packet to clt[%v]", dest)
_ = clt.conn.Close()
b.clients.Remove(dest)
}
} else {
if b.subnet.Contains(net.IP(dest.addr[:])) {
logrus.Errorf("no client with address[%v]", dest)
}
}
}
}
func (b *Backend) Run() error {
logrus.Info("started")
defer logrus.Info("exited")
bits, _ := b.subnet.Mask.Size()
bits6, _ := b.subnet6.Mask.Size()
tunCfg := config.Config{
ServerIP: b.addr.String(),
ServerIPv6: b.addr6.String(),
CIDR: b.addr.String() + "/" + strconv.Itoa(bits),
CIDRv6: b.addr6.String() + "/" + strconv.Itoa(bits6),
MTU: ZROK_VPN_MTU,
Verbose: true,
}
logrus.Infof("%+v", tunCfg)
b.tun = tun.CreateTun(tunCfg)
defer func() {
_ = b.tun.Close()
}()
go b.readTun()
for {
if conn, err := b.listener.Accept(); err == nil {
go b.handle(conn)
} else {
return err
}
}
}
func (b *Backend) handle(conn net.Conn) {
defer func(conn net.Conn) {
_ = conn.Close()
}(conn)
ipv4, ipv6 := b.nextIP()
ip := ipToDest(ipv4)
bits, _ := b.subnet.Mask.Size()
bits6, _ := b.subnet6.Mask.Size()
cfg := &ClientConfig{
Greeting: "Welcome to zrok VPN",
ServerIP: b.addr.String(),
ServerIPv6: b.addr6.String(),
CIDR: ipv4.String() + "/" + strconv.Itoa(bits),
CIDR6: ipv6.String() + "/" + strconv.Itoa(bits6),
MTU: b.mtu,
}
b.cfg.RequestsChan <- &endpoints.Request{
Stamp: time.Now(),
RemoteAddr: ipv4.String(),
Method: "CONNECTED",
Path: cfg.ServerIP,
}
j, err := json.Marshal(&cfg)
if err != nil {
logrus.WithError(err).Error("failed to write client VPN config")
return
}
_, err = conn.Write(j)
if err != nil {
logrus.WithError(err).Error("failed to write client VPN config")
return
}
clt := &client{conn: conn}
b.clients.Set(ip, clt)
buf := make([]byte, b.mtu)
for {
read, err := conn.Read(buf)
if err != nil {
if err != io.EOF {
logrus.WithError(err).Error("read error")
}
b.cfg.RequestsChan <- &endpoints.Request{
Stamp: time.Now(),
RemoteAddr: ipv4.String(),
Method: "DISCONNECTED",
}
return
}
pkt := packet(buf[:read])
logrus.WithField("packet", pkt).Trace("read from ziti")
_, err = b.tun.Write(pkt)
if err != nil {
logrus.WithError(err).Error("failed to write packet to tun")
return
}
}
}
func (b *Backend) nextIP() (net.IP, net.IP) {
ip4 := make([]byte, len(b.subnet.IP))
for {
copy(ip4, b.subnet.IP)
n := b.counter.Add(1)
if n == 0 {
continue
}
for i := 0; i < len(ip4); i++ {
b := (n >> (i * 8)) % 0xff
ip4[len(ip4)-1-i] ^= byte(b)
}
// subnet overflow
if !b.subnet.Contains(ip4) {
b.counter.Store(1)
continue
}
if cmp.Equal(b.addr, ip4) {
continue
}
if b.clients.Has(ipToDest(ip4)) {
continue
}
break
}
ip6 := append([]byte{}, b.subnet6.IP...)
copy(ip6[net.IPv6len-net.IPv4len:], ip4)
return ip4, ip6
}

131
endpoints/vpn/frontend.go Normal file
View File

@ -0,0 +1,131 @@
package vpn
import (
"encoding/json"
"github.com/net-byte/vtun/common/config"
"github.com/net-byte/vtun/tun"
"github.com/openziti/sdk-golang/ziti"
"github.com/openziti/zrok/endpoints"
"github.com/openziti/zrok/environment"
"github.com/openziti/zrok/sdk/golang/sdk"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"net"
"time"
)
type FrontendConfig struct {
IdentityName string
ShrToken string
RequestsChan chan *endpoints.Request
}
type Frontend struct {
cfg *FrontendConfig
ztx ziti.Context
conn net.Conn
}
func NewFrontend(cfg *FrontendConfig) (*Frontend, error) {
env, err := environment.LoadRoot()
if err != nil {
return nil, errors.Wrap(err, "error loading environment root")
}
zCfgPath, err := env.ZitiIdentityNamed(cfg.IdentityName)
if err != nil {
return nil, errors.Wrapf(err, "error getting ziti identity '%v' from environment", cfg.IdentityName)
}
zCfg, err := ziti.NewConfigFromFile(zCfgPath)
if err != nil {
return nil, errors.Wrap(err, "error loading config")
}
zCfg.ConfigTypes = []string{sdk.ZrokProxyConfig}
zCtx, err := ziti.NewContext(zCfg)
if err != nil {
return nil, errors.Wrap(err, "error loading ziti context")
}
zConn, err := zCtx.Dial(cfg.ShrToken)
if err != nil {
zCtx.Close()
return nil, errors.Wrap(err, "error connecting to ziti")
}
return &Frontend{
cfg: cfg,
ztx: zCtx,
conn: zConn,
}, nil
}
func (f *Frontend) Run() error {
var cltCfg ClientConfig
d := json.NewDecoder(f.conn)
if err := d.Decode(&cltCfg); err != nil {
return errors.Wrap(err, "error decoding vpn config")
}
f.cfg.RequestsChan <- &endpoints.Request{
Stamp: time.Now(),
RemoteAddr: cltCfg.ServerIP,
Method: "CONNECTED",
Path: cltCfg.Greeting,
}
logrus.Info("connected:", cltCfg.Greeting)
defer func() {
f.cfg.RequestsChan <- &endpoints.Request{
Stamp: time.Now(),
RemoteAddr: cltCfg.ServerIP,
Method: "Disconnected",
}
}()
cfg := config.Config{
ServerIP: cltCfg.ServerIP,
CIDR: cltCfg.CIDR,
ServerIPv6: cltCfg.ServerIPv6,
CIDRv6: cltCfg.CIDR6,
MTU: cltCfg.MTU,
Verbose: false,
}
iface := tun.CreateTun(cfg)
logrus.Infof("created tun device: %s", iface.Name())
go func() {
defer func() {
_ = f.conn.Close()
_ = iface.Close()
}()
b := make([]byte, cltCfg.MTU)
for {
n, err := f.conn.Read(b)
if err != nil {
logrus.WithError(err).Error("error reading from ziti")
return
}
p := packet(b[:n])
logrus.WithField("packet", p).Trace("received packet from peer")
_, err = iface.Write(p)
if err != nil {
logrus.WithError(err).Error("error writing to device")
return
}
}
}()
buf := make([]byte, cltCfg.MTU)
for {
n, err := iface.Read(buf)
if err != nil {
return errors.Wrap(err, "error reading packet")
}
pkt := packet(buf[:n])
logrus.WithField("packet", pkt).Trace("read packet from tun device")
_, err = f.conn.Write(pkt)
if err != nil {
return errors.Wrap(err, "error sending packet to ziti")
}
}
}

94
endpoints/vpn/vpn.go Normal file
View File

@ -0,0 +1,94 @@
package vpn
import (
"fmt"
"github.com/songgao/water/waterutil"
"net"
"strconv"
)
const ZROK_VPN_MTU = 16 * 1024
var (
zrokIPv4Addr = net.IPv4(10, 'z', 0, 0)
zrokIPv4 = &net.IPNet{
IP: net.IPv4(10, 'z', 0, 0),
Mask: net.CIDRMask(16, 8*net.IPv4len),
}
zrokIPv6Addr = net.IP{0xfd, 0, 'z', 'r', 'o', 'k', 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}
zrokIPv6 = &net.IPNet{
IP: net.IP{0xfd, 0, 'z', 'r', 'o', 'k', // prefix + global ID
0, 0, // subnet id
0, 0, 0, 0,
0, 0, 0, 0,
},
Mask: net.CIDRMask(64, 8*net.IPv6len),
}
)
func DefaultTarget() string {
l := len(zrokIPv4Addr)
subnet := net.IPNet{
IP: make([]byte, l),
Mask: zrokIPv4.Mask,
}
copy(subnet.IP, zrokIPv4Addr)
subnet.IP[l-1] = 1
return subnet.String()
}
type ClientConfig struct {
Greeting string
CIDR string
CIDR6 string
ServerIP string
ServerIPv6 string
Routes []string
MTU int
}
type dest struct {
addr [4]byte
}
func (d dest) String() string {
return net.IP(d.addr[:]).String()
}
func (d dest) toInt32() uint32 {
return uint32(d.addr[0])<<24 + uint32(d.addr[1])<<16 + uint32(d.addr[2])<<8 + uint32(d.addr[3])
}
func ipToDest(addr net.IP) dest {
d := dest{}
copy(d.addr[:], addr.To4())
return d
}
type packet []byte
func (p packet) destination() dest {
return ipToDest(waterutil.IPv4Destination(p))
}
func (p packet) String() string {
return fmt.Sprintf("%s %s:%d -> %s:%d %d bytes", p.proto(),
waterutil.IPv4Source(p), waterutil.IPv4SourcePort(p),
waterutil.IPv4Destination(p), waterutil.IPv4DestinationPort(p), len(waterutil.IPv4Payload(p)))
}
func (p packet) proto() string {
proto := waterutil.IPv4Protocol(p)
switch proto {
case waterutil.TCP:
return "tcp"
case waterutil.UDP:
return "udp"
case waterutil.ICMP:
return "icmp"
default:
return strconv.Itoa(int(proto))
}
}

81
go.mod
View File

@ -8,15 +8,16 @@ require (
github.com/charmbracelet/bubbles v0.14.0
github.com/charmbracelet/bubbletea v0.23.1
github.com/charmbracelet/lipgloss v0.6.0
github.com/go-openapi/errors v0.21.0
github.com/go-openapi/loads v0.21.5
github.com/go-openapi/runtime v0.27.1
github.com/go-openapi/spec v0.20.14
github.com/go-openapi/strfmt v0.22.1
github.com/go-openapi/swag v0.22.9
github.com/go-openapi/validate v0.23.0
github.com/go-openapi/errors v0.22.0
github.com/go-openapi/loads v0.22.0
github.com/go-openapi/runtime v0.28.0
github.com/go-openapi/spec v0.21.0
github.com/go-openapi/strfmt v0.23.0
github.com/go-openapi/swag v0.23.0
github.com/go-openapi/validate v0.24.0
github.com/gobwas/glob v0.2.3
github.com/golang-jwt/jwt/v5 v5.2.0
github.com/golang-jwt/jwt/v5 v5.2.1
github.com/google/go-cmp v0.6.0
github.com/google/uuid v1.6.0
github.com/gorilla/websocket v1.5.1
github.com/iancoleman/strcase v0.2.0
@ -30,28 +31,32 @@ require (
github.com/michaelquigley/cf v0.0.13
github.com/michaelquigley/pfxlog v0.6.10
github.com/muesli/reflow v0.3.0
github.com/net-byte/vtun v1.7.0
github.com/net-byte/water v0.0.7
github.com/nxadm/tail v1.4.8
github.com/openziti/channel/v2 v2.0.121
github.com/openziti/edge-api v0.26.12
github.com/openziti/channel/v2 v2.0.128
github.com/openziti/edge-api v0.26.16
github.com/openziti/fabric v0.23.26
github.com/openziti/identity v1.0.72
github.com/openziti/sdk-golang v0.23.10
github.com/openziti/transport/v2 v2.0.124
github.com/openziti/identity v1.0.75
github.com/openziti/sdk-golang v0.23.22
github.com/openziti/transport/v2 v2.0.131
github.com/orcaman/concurrent-map/v2 v2.0.1
github.com/pkg/errors v0.9.1
github.com/rabbitmq/amqp091-go v1.8.1
github.com/rubenv/sql-migrate v1.6.0
github.com/shirou/gopsutil/v3 v3.24.1
github.com/shirou/gopsutil/v3 v3.24.3
github.com/sirupsen/logrus v1.9.3
github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8
github.com/spf13/cobra v1.8.0
github.com/stretchr/testify v1.9.0
github.com/wneessen/go-mail v0.2.7
github.com/zitadel/oidc/v2 v2.12.0
go.uber.org/zap v1.25.0
golang.org/x/crypto v0.21.0
golang.org/x/net v0.21.0
golang.org/x/oauth2 v0.16.0
golang.org/x/time v0.3.0
nhooyr.io/websocket v1.8.10
golang.org/x/crypto v0.22.0
golang.org/x/net v0.24.0
golang.org/x/oauth2 v0.19.0
golang.org/x/time v0.5.0
nhooyr.io/websocket v1.8.11
)
require (
@ -75,7 +80,7 @@ require (
github.com/beorn7/perks v1.0.1 // indirect
github.com/biogo/store v0.0.0-20200525035639-8c94ae1e7c9c // indirect
github.com/caddyserver/certmagic v0.20.0 // indirect
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/cespare/xxhash v1.1.0 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/chzyer/readline v1.5.1 // indirect
@ -101,14 +106,17 @@ require (
github.com/go-logr/logr v1.4.1 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-openapi/analysis v0.22.2 // indirect
github.com/go-openapi/jsonpointer v0.20.2 // indirect
github.com/go-openapi/jsonreference v0.20.4 // indirect
github.com/go-resty/resty/v2 v2.11.0 // indirect
github.com/go-openapi/analysis v0.23.0 // indirect
github.com/go-openapi/jsonpointer v0.21.0 // indirect
github.com/go-openapi/jsonreference v0.21.0 // indirect
github.com/go-resty/resty/v2 v2.12.0 // indirect
github.com/go-sql-driver/mysql v1.7.1 // indirect
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
github.com/gobwas/httphead v0.1.0 // indirect
github.com/gobwas/pool v0.2.1 // indirect
github.com/gobwas/ws v1.1.0 // indirect
github.com/golang/glog v1.1.2 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/cel-go v0.15.1 // indirect
github.com/google/certificate-transparency-go v1.1.6 // indirect
@ -123,6 +131,7 @@ require (
github.com/imdario/mergo v0.3.13 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839 // indirect
github.com/inhies/go-bytesize v0.0.0-20210819104631-275770b98743 // indirect
github.com/jackc/chunkreader/v2 v2.0.1 // indirect
github.com/jackc/pgconn v1.14.0 // indirect
github.com/jackc/pgio v1.0.0 // indirect
@ -159,14 +168,14 @@ require (
github.com/muesli/cancelreader v0.2.2 // indirect
github.com/muesli/termenv v0.13.0 // indirect
github.com/muhlemmer/gu v0.3.1 // indirect
github.com/net-byte/go-gateway v0.0.2 // indirect
github.com/oklog/ulid v1.3.1 // indirect
github.com/onsi/ginkgo/v2 v2.9.5 // indirect
github.com/opentracing/opentracing-go v1.2.0 // indirect
github.com/openziti/foundation/v2 v2.0.39 // indirect
github.com/openziti/metrics v1.2.47 // indirect
github.com/openziti/secretstream v0.1.17 // indirect
github.com/openziti/foundation/v2 v2.0.42 // indirect
github.com/openziti/metrics v1.2.51 // indirect
github.com/openziti/secretstream v0.1.19 // indirect
github.com/openziti/storage v0.2.6 // indirect
github.com/orcaman/concurrent-map/v2 v2.0.1 // indirect
github.com/parallaxsecond/parsec-client-go v0.0.0-20221025095442-f0a77d263cf9 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b // indirect
@ -200,7 +209,7 @@ require (
github.com/x448/float16 v0.8.4 // indirect
github.com/yuin/goldmark v1.5.6 // indirect
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc // indirect
github.com/yusufpapurcu/wmi v1.2.3 // indirect
github.com/yusufpapurcu/wmi v1.2.4 // indirect
github.com/zeebo/blake3 v0.2.3 // indirect
go.etcd.io/bbolt v1.3.7 // indirect
go.mongodb.org/mongo-driver v1.14.0 // indirect
@ -215,7 +224,7 @@ require (
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0 // indirect
go.opentelemetry.io/otel/metric v1.24.0 // indirect
go.opentelemetry.io/otel/sdk v1.21.0 // indirect
go.opentelemetry.io/otel/sdk v1.24.0 // indirect
go.opentelemetry.io/otel/trace v1.24.0 // indirect
go.opentelemetry.io/proto/otlp v1.0.0 // indirect
go.step.sm/cli-utils v0.8.0 // indirect
@ -226,15 +235,17 @@ require (
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
golang.org/x/mod v0.12.0 // indirect
golang.org/x/sync v0.6.0 // indirect
golang.org/x/sys v0.18.0 // indirect
golang.org/x/term v0.18.0 // indirect
golang.org/x/sys v0.19.0 // indirect
golang.org/x/term v0.19.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/tools v0.13.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224 // indirect
golang.zx2c4.com/wireguard v0.0.0-20220703234212-c31a7b1ab478 // indirect
golang.zx2c4.com/wireguard/windows v0.5.3 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20231016165738-49dd2c1f3d0b // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20231016165738-49dd2c1f3d0b // indirect
google.golang.org/grpc v1.59.0 // indirect
google.golang.org/protobuf v1.32.0 // indirect
google.golang.org/protobuf v1.33.0 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect

163
go.sum
View File

@ -128,8 +128,8 @@ github.com/caddyserver/certmagic v0.20.0 h1:bTw7LcEZAh9ucYCRXyCpIrSAGplplI0vGYJ4
github.com/caddyserver/certmagic v0.20.0/go.mod h1:N4sXgpICQUskEWpj7zVzvWD41p3NYacrNoZYiRM2jTg=
github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM=
github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
@ -266,30 +266,30 @@ github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-openapi/analysis v0.22.2 h1:ZBmNoP2h5omLKr/srIC9bfqrUGzT6g6gNv03HE9Vpj0=
github.com/go-openapi/analysis v0.22.2/go.mod h1:pDF4UbZsQTo/oNuRfAWWd4dAh4yuYf//LYorPTjrpvo=
github.com/go-openapi/errors v0.21.0 h1:FhChC/duCnfoLj1gZ0BgaBmzhJC2SL/sJr8a2vAobSY=
github.com/go-openapi/errors v0.21.0/go.mod h1:jxNTMUxRCKj65yb/okJGEtahVd7uvWnuWfj53bse4ho=
github.com/go-openapi/analysis v0.23.0 h1:aGday7OWupfMs+LbmLZG4k0MYXIANxcuBTYUC03zFCU=
github.com/go-openapi/analysis v0.23.0/go.mod h1:9mz9ZWaSlV8TvjQHLl2mUW2PbZtemkE8yA5v22ohupo=
github.com/go-openapi/errors v0.22.0 h1:c4xY/OLxUBSTiepAg3j/MHuAv5mJhnf53LLMWFB+u/w=
github.com/go-openapi/errors v0.22.0/go.mod h1:J3DmZScxCDufmIMsdOuDHxJbdOGC0xtUynjIx092vXE=
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/jsonpointer v0.20.2 h1:mQc3nmndL8ZBzStEo3JYF8wzmeWffDH4VbXz58sAx6Q=
github.com/go-openapi/jsonpointer v0.20.2/go.mod h1:bHen+N0u1KEO3YlmqOjTT9Adn1RfD91Ar825/PuiRVs=
github.com/go-openapi/jsonreference v0.20.4 h1:bKlDxQxQJgwpUSgOENiMPzCTBVuc7vTdXSSgNeAhojU=
github.com/go-openapi/jsonreference v0.20.4/go.mod h1:5pZJyJP2MnYCpoeoMAql78cCHauHj0V9Lhc506VOpw4=
github.com/go-openapi/loads v0.21.5 h1:jDzF4dSoHw6ZFADCGltDb2lE4F6De7aWSpe+IcsRzT0=
github.com/go-openapi/loads v0.21.5/go.mod h1:PxTsnFBoBe+z89riT+wYt3prmSBP6GDAQh2l9H1Flz8=
github.com/go-openapi/runtime v0.27.1 h1:ae53yaOoh+fx/X5Eaq8cRmavHgDma65XPZuvBqvJYto=
github.com/go-openapi/runtime v0.27.1/go.mod h1:fijeJEiEclyS8BRurYE1DE5TLb9/KZl6eAdbzjsrlLU=
github.com/go-openapi/spec v0.20.14 h1:7CBlRnw+mtjFGlPDRZmAMnq35cRzI91xj03HVyUi/Do=
github.com/go-openapi/spec v0.20.14/go.mod h1:8EOhTpBoFiask8rrgwbLC3zmJfz4zsCUueRuPM6GNkw=
github.com/go-openapi/strfmt v0.22.1 h1:5Ky8cybT4576C6Ffc+8gYji/wRXCo6Ozm8RaWjPI6jc=
github.com/go-openapi/strfmt v0.22.1/go.mod h1:OfVoytIXJasDkkGvkb1Cceb3BPyMOwk1FgmyyEw7NYg=
github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY=
github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ=
github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4=
github.com/go-openapi/loads v0.22.0 h1:ECPGd4jX1U6NApCGG1We+uEozOAvXvJSF4nnwHZ8Aco=
github.com/go-openapi/loads v0.22.0/go.mod h1:yLsaTCS92mnSAZX5WWoxszLj0u+Ojl+Zs5Stn1oF+rs=
github.com/go-openapi/runtime v0.28.0 h1:gpPPmWSNGo214l6n8hzdXYhPuJcGtziTOgUpvsFWGIQ=
github.com/go-openapi/runtime v0.28.0/go.mod h1:QN7OzcS+XuYmkQLw05akXk0jRH/eZ3kb18+1KwW9gyc=
github.com/go-openapi/spec v0.21.0 h1:LTVzPc3p/RzRnkQqLRndbAzjY0d0BCL72A6j3CdL9ZY=
github.com/go-openapi/spec v0.21.0/go.mod h1:78u6VdPw81XU44qEWGhtr982gJ5BWg2c0I5XwVMotYk=
github.com/go-openapi/strfmt v0.23.0 h1:nlUS6BCqcnAk0pyhi9Y+kdDVZdZMHfEKQiS4HaMgO/c=
github.com/go-openapi/strfmt v0.23.0/go.mod h1:NrtIpfKtWIygRkKVsxh7XQMDQW5HKQl6S5ik2elW+K4=
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-openapi/swag v0.22.9 h1:XX2DssF+mQKM2DHsbgZK74y/zj4mo9I99+89xUmuZCE=
github.com/go-openapi/swag v0.22.9/go.mod h1:3/OXnFfnMAwBD099SwYRk7GD3xOrr1iL7d/XNLXVVwE=
github.com/go-openapi/validate v0.23.0 h1:2l7PJLzCis4YUGEoW6eoQw3WhyM65WSIcjX6SQnlfDw=
github.com/go-openapi/validate v0.23.0/go.mod h1:EeiAZ5bmpSIOJV1WLfyYF9qp/B1ZgSaEpHTJHtN5cbE=
github.com/go-resty/resty/v2 v2.11.0 h1:i7jMfNOJYMp69lq7qozJP+bjgzfAzeOhuGlyDrqxT/8=
github.com/go-resty/resty/v2 v2.11.0/go.mod h1:iiP/OpA0CkcL3IGt1O0+/SIItFUbkkyw5BGXiVdTu+A=
github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
github.com/go-openapi/validate v0.24.0 h1:LdfDKwNbpB6Vn40xhTdNZAnfLECL81w+VX3BumrGD58=
github.com/go-openapi/validate v0.24.0/go.mod h1:iyeX1sEufmv3nPbBdX3ieNviWnOZaJ1+zquzJEf2BAQ=
github.com/go-resty/resty/v2 v2.12.0 h1:rsVL8P90LFvkUYq/V5BTVe203WfRIU4gvcf+yfzJzGA=
github.com/go-resty/resty/v2 v2.12.0/go.mod h1:o0yGPrkS3lOe1+eFajk6kBW8ScXzwU3hD69/gt2yB/0=
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI=
@ -301,6 +301,12 @@ github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEe
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU=
github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og=
github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
github.com/gobwas/ws v1.1.0 h1:7RFti/xnNkMJnrK7D1yQ/iCIB5OrrY/54/H930kIbHA=
github.com/gobwas/ws v1.1.0/go.mod h1:nzvNcVha5eUziGrbxFCo6qFIojQHjJV5cLYIbezhfL0=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw=
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
@ -309,8 +315,8 @@ github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang-jwt/jwt/v5 v5.2.0 h1:d/ix8ftRUorsN+5eMIlF4T6J8CAt9rch3My2winC1Jw=
github.com/golang-jwt/jwt/v5 v5.2.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=
github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/glog v1.1.2 h1:DVjP2PbBOzHyzA+dn3WhHIq4NdVu3Q+pvivFICf/7fo=
github.com/golang/glog v1.1.2/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ=
@ -345,8 +351,8 @@ github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
@ -481,6 +487,8 @@ github.com/influxdata/influxdb-client-go/v2 v2.11.0/go.mod h1:YteV91FiQxRdccyJ2c
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839 h1:W9WBk7wlPfJLvMCdtV4zPulc4uCPrlywQOmbFOhgQNU=
github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo=
github.com/inhies/go-bytesize v0.0.0-20210819104631-275770b98743 h1:X3Xxno5Ji8idrNiUoFc7QyXpqhSYlDRYQmc7mlpMBzU=
github.com/inhies/go-bytesize v0.0.0-20210819104631-275770b98743/go.mod h1:KrtyD5PFj++GKkFS/7/RRrfnRhAMGQwy75GLCHWrCNs=
github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo=
github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk=
github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8=
@ -704,6 +712,12 @@ github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzE
github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
github.com/net-byte/go-gateway v0.0.2 h1:xNB7CqWh7js6PB/xOochjyJlDHl6sZthhPSoJdxwoLY=
github.com/net-byte/go-gateway v0.0.2/go.mod h1:+NvPbRjN64RUYvm6xtRBUswoAXKAe44Y/PfWtWMgwwY=
github.com/net-byte/vtun v1.7.0 h1:mt8sUKbFPbl5pc0EXeRFl5zCKXr3QCaSYZp7raGd5y0=
github.com/net-byte/vtun v1.7.0/go.mod h1:SVFWdwuyvV7BRyeyiaay7HfWor6se5894IkNsNTTo54=
github.com/net-byte/water v0.0.7 h1:wJUVq8x1AdfzZ5G8Qv61YRX+d22wx0ZgWNG0ihLqglo=
github.com/net-byte/water v0.0.7/go.mod h1:tRTm034ul8JBKkYFGN/WrnUM4cctr9laq5IpwvaVqUE=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
@ -738,26 +752,26 @@ github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxS
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
github.com/openziti/channel/v2 v2.0.121 h1:dCPNbn0VbGIOrzXHcnjp5p0XzZCbpHKRmMhi9LRex0E=
github.com/openziti/channel/v2 v2.0.121/go.mod h1:f/DLqWVAFF5pDIpse8BRm4ZwhpAFjx0gUGjPEqlPSZE=
github.com/openziti/edge-api v0.26.12 h1:5VRz0cWtfQq2rhSA7Ne6amM7YNI6pQGRfNgbKt0g6kQ=
github.com/openziti/edge-api v0.26.12/go.mod h1:tKZRUFDB9zM5J1zBS0ok2r40OhJqWykZaU9HSBQgr8w=
github.com/openziti/channel/v2 v2.0.128 h1:kRigyUmrN1q56ydRmBWzruV0DvVntYx/f2DT2P0qSh4=
github.com/openziti/channel/v2 v2.0.128/go.mod h1:ugebO2eO2CdaVQE45o20iE4R9DK0VRoJsGBZt0x3eLc=
github.com/openziti/edge-api v0.26.16 h1:oU4t2Q4f0+K/ypwdQIecgA836PJkCnDMe1glc56ovaA=
github.com/openziti/edge-api v0.26.16/go.mod h1:HTp6bC3cBKAoIwyA06aKKrrBwxFtJALfpEinmvCRgBc=
github.com/openziti/fabric v0.23.26 h1:wEPNh8m3qcq9sw1Zmg5YgFZw1FovsKGu53rRf8qzI7A=
github.com/openziti/fabric v0.23.26/go.mod h1:0MtkZqIHs3cJPP4DB88xsWUemDm77nN/GvWBBfq7peo=
github.com/openziti/foundation/v2 v2.0.39 h1:psv1cTgBErOME4K5TmxolUzz8VabJVhGygsAz6uXAQM=
github.com/openziti/foundation/v2 v2.0.39/go.mod h1:38RikdtjvzDUALm3jT3PSOrU0bHCleRty6bHGdfFyUI=
github.com/openziti/identity v1.0.72 h1:Y14nUtgDiUBWZ6WBo6S1rw5qb57QNnZGhsFnMPqfJB8=
github.com/openziti/identity v1.0.72/go.mod h1:sh1STe6K3EM3K0atBVDLq5jpUxAAFCAQZmIkD0MYIKY=
github.com/openziti/metrics v1.2.47 h1:hIp1xnqLxNc7O0yTHIp65REhYBXj7QWeOiayGDzjRrw=
github.com/openziti/metrics v1.2.47/go.mod h1:pHj/z3HCls4/+dLoQKTURNTnHmwUbjZFZOGzj2X6HeI=
github.com/openziti/sdk-golang v0.23.10 h1:ygpOt99Rd5ESoH1ExYqBHhZp47s5/DYxyfgTO6uYr7Q=
github.com/openziti/sdk-golang v0.23.10/go.mod h1:07G4gYyZzRt9fb3uxEhwdsgJwDrqEkjuvVnnRlsrfEc=
github.com/openziti/secretstream v0.1.17 h1:bcaPGGpUl0+3GzfQkshKh5slUE7QDXxFq3vyDQgHkCA=
github.com/openziti/secretstream v0.1.17/go.mod h1:gosi8ohW+dAHhz1h/MjZEcEVWO0jisWqWjEjmx7oAEs=
github.com/openziti/foundation/v2 v2.0.42 h1:cXZFql3xY92AHPCk/wqIoSUX9EHgegwPrs5bhFE2jNg=
github.com/openziti/foundation/v2 v2.0.42/go.mod h1:a+REYnK9bZ2cvmOiuBLp57MjQqn3U5cHhJcDMLMO8rE=
github.com/openziti/identity v1.0.75 h1:FDm3ZojmmGP9eoOxMvmF52RS6JzToTTeWB0pthIA+ks=
github.com/openziti/identity v1.0.75/go.mod h1:ouF+CYh5ywvvMr0Uy1+tbkILIPTdob5WZEnm3v0bPMQ=
github.com/openziti/metrics v1.2.51 h1:+RfVdEGMOmhXBcC/gFIqXeNVnpWt9+cfrbCacFV/e3w=
github.com/openziti/metrics v1.2.51/go.mod h1:qvX8EKF8I42tA4KlNFX+RBx+ywNiVRvJTS4QofDU8KU=
github.com/openziti/sdk-golang v0.23.22 h1:gGyH0tTjEZiJCbUuL4/L3NsTbajB/Aeg3rYHNSjr6d4=
github.com/openziti/sdk-golang v0.23.22/go.mod h1:+B9KFCQw9pUxleSs5L9LQCf0zq06a+j9UpFk6CmITqw=
github.com/openziti/secretstream v0.1.19 h1:qSX23lyOI5ROvYPTjy7Lo6eFsq9qBBPzaG5hvgLlw48=
github.com/openziti/secretstream v0.1.19/go.mod h1:1n/Uk8PQEREwB7iQXhUzNqt+8jYEpUZOJDGcetMI08o=
github.com/openziti/storage v0.2.6 h1:/pbIRzDwrczMWRVkN75PfwAXFbArplIqhpRsUrsUOBc=
github.com/openziti/storage v0.2.6/go.mod h1:JnjCofrnPcajwn6VIB2CgI7pVVUFBL7evbezIsQ4AgA=
github.com/openziti/transport/v2 v2.0.124 h1:84bq7vyqzGJXPek9qyc/7mtVEhp6KTQMK2msq3hwGkY=
github.com/openziti/transport/v2 v2.0.124/go.mod h1:eQ3011tfSlmBI3cIkcJOf9YP/afj+Jd2EQM6MCHoJCQ=
github.com/openziti/transport/v2 v2.0.131 h1:K1h3sl04QWQdYGSPSI1aZLufrL44Azw4WmdprzkIMxo=
github.com/openziti/transport/v2 v2.0.131/go.mod h1:N+OPeoqIuZwS72q0XnM4DLHVdKZ3ZOR37rqjOjWA0b8=
github.com/orcaman/concurrent-map/v2 v2.0.1 h1:jOJ5Pg2w1oeB6PeDurIYf6k9PQ+aTITr/6lP/L/zp6c=
github.com/orcaman/concurrent-map/v2 v2.0.1/go.mod h1:9Eq3TG2oBe5FirmYWQfYO5iH1q0Jv47PLaNK++uCdOM=
github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM=
@ -851,8 +865,8 @@ github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdh
github.com/schollz/jsonstore v1.1.0 h1:WZBDjgezFS34CHI+myb4s8GGpir3UMpy7vWoCeO0n6E=
github.com/schollz/jsonstore v1.1.0/go.mod h1:15c6+9guw8vDRyozGjN3FoILt0wpruJk9Pi66vjaZfg=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/shirou/gopsutil/v3 v3.24.1 h1:R3t6ondCEvmARp3wxODhXMTLC/klMa87h2PHUw5m7QI=
github.com/shirou/gopsutil/v3 v3.24.1/go.mod h1:UU7a2MSBQa+kW1uuDq8DeEBS8kmrnQwsv2b5O513rwU=
github.com/shirou/gopsutil/v3 v3.24.3 h1:eoUGJSmdfLzJ3mxIhmOAhgKEKgQkeOwKpz1NbhVnuPE=
github.com/shirou/gopsutil/v3 v3.24.3/go.mod h1:JpND7O217xa72ewWz9zN2eIIkPWsDN/3pl0H8Qt0uwg=
github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM=
github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ=
github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU=
@ -885,6 +899,8 @@ github.com/smallstep/truststore v0.12.1/go.mod h1:M4mebeNy28KusGX3lJxpLARIktLcyq
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8 h1:TG/diQgUe0pntT/2D9tmUCz4VNwm9MfrtPr0SU2qSX8=
github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8/go.mod h1:P5HUIBuIWKbyjl083/loAegFkfbFNx5i2qEP4CNbm7E=
github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
@ -920,6 +936,7 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
@ -966,8 +983,8 @@ github.com/yuin/goldmark v1.5.6 h1:COmQAWTCcGetChm3Ig7G/t8AFAN00t+o8Mt4cf7JpwA=
github.com/yuin/goldmark v1.5.6/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc h1:+IAOyRda+RLrxa1WC7umKOZRsGq4QrFFMYApOeHzQwQ=
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc/go.mod h1:ovIvrum6DQJA4QsJSovrkC4saKHQVs7TvcaeO8AIl5I=
github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw=
github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
github.com/zeebo/assert v1.1.0 h1:hU1L1vLTHsnO8x8c9KAR5GmM5QscxHg5RNU5z5qbUWY=
github.com/zeebo/assert v1.1.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0=
github.com/zeebo/blake3 v0.2.3 h1:TFoLXsjeXqRNFxSbk35Dk4YtszE/MQQGK10BH4ptoTg=
@ -1020,8 +1037,8 @@ go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0 h1:tIqhe
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0/go.mod h1:nUeKExfxAQVbiVFn32YXpXZZHZ61Cc3s3Rn1pDBGAb0=
go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI=
go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco=
go.opentelemetry.io/otel/sdk v1.21.0 h1:FTt8qirL1EysG6sTQRZ5TokkU8d0ugCj8htOgThZXQ8=
go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E=
go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw=
go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg=
go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI=
go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU=
go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I=
@ -1075,9 +1092,10 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@ -1169,9 +1187,10 @@ golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@ -1184,8 +1203,8 @@ golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ
golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ=
golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o=
golang.org/x/oauth2 v0.19.0 h1:9+E/EZBCbTLNrbN35fHv/a/d/mOBatymz1zbtQrXpIg=
golang.org/x/oauth2 v0.19.0/go.mod h1:vYi7skDa1x015PmRRYZ7+s1cWyPgrPiSYRe4rnsexc8=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -1254,6 +1273,7 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201207223542-d4d67f95c62d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -1280,10 +1300,10 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@ -1291,9 +1311,10 @@ golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q=
golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@ -1306,7 +1327,6 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@ -1315,8 +1335,8 @@ golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxb
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@ -1386,6 +1406,12 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224 h1:Ug9qvr1myri/zFN6xL17LSCBGFDnphBBhzmILHsM5TY=
golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI=
golang.zx2c4.com/wireguard v0.0.0-20220703234212-c31a7b1ab478 h1:vDy//hdR+GnROE3OdYbQKt9rdtNdHkDtONvpRwmls/0=
golang.zx2c4.com/wireguard v0.0.0-20220703234212-c31a7b1ab478/go.mod h1:bVQfyl2sCM/QIIGHpWbFGfHPuDvqnCNkT6MQLTCjO/U=
golang.zx2c4.com/wireguard/windows v0.5.3 h1:On6j2Rpn3OEMXqBq00QEDC7bWSZrPIHKIus8eIuExIE=
golang.zx2c4.com/wireguard/windows v0.5.3/go.mod h1:9TEe8TJmtwyQebdFwAkEWOPr3prrtqm+REGFifP60hI=
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
@ -1418,7 +1444,6 @@ google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
@ -1507,8 +1532,8 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@ -1554,8 +1579,8 @@ honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
howett.net/plist v1.0.0 h1:7CrbWYbPPO/PyNy38b2EB/+gYbjCe2DXBxgtOOZbSQM=
howett.net/plist v1.0.0/go.mod h1:lqaXoTrLY4hg8tnEzNru53gicrbv7rrk+2xJA/7hw9g=
nhooyr.io/websocket v1.8.10 h1:mv4p+MnGrLDcPlBoWsvPP7XCzTYMXP9F9eIGoKbgx7Q=
nhooyr.io/websocket v1.8.10/go.mod h1:rN9OFWIUwuxg4fR5tELlYC04bXYowCP9GX47ivo2l+c=
nhooyr.io/websocket v1.8.11 h1:f/qXNc2/3DpoSZkHt1DQu6rj4zGC8JmkkLkWss0MgN0=
nhooyr.io/websocket v1.8.11/go.mod h1:rN9OFWIUwuxg4fR5tELlYC04bXYowCP9GX47ivo2l+c=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=

View File

@ -31,7 +31,7 @@ type ShareRequest struct {
AuthUsers []*AuthUser `json:"authUsers"`
// backend mode
// Enum: [proxy web tcpTunnel udpTunnel caddy drive socks]
// Enum: [proxy web tcpTunnel udpTunnel caddy drive socks vpn]
BackendMode string `json:"backendMode,omitempty"`
// backend proxy endpoint
@ -128,7 +128,7 @@ var shareRequestTypeBackendModePropEnum []interface{}
func init() {
var res []string
if err := json.Unmarshal([]byte(`["proxy","web","tcpTunnel","udpTunnel","caddy","drive","socks"]`), &res); err != nil {
if err := json.Unmarshal([]byte(`["proxy","web","tcpTunnel","udpTunnel","caddy","drive","socks","vpn"]`), &res); err != nil {
panic(err)
}
for _, v := range res {
@ -158,6 +158,9 @@ const (
// ShareRequestBackendModeSocks captures enum value "socks"
ShareRequestBackendModeSocks string = "socks"
// ShareRequestBackendModeVpn captures enum value "vpn"
ShareRequestBackendModeVpn string = "vpn"
)
// prop value enum

View File

@ -1589,7 +1589,8 @@ func init() {
"udpTunnel",
"caddy",
"drive",
"socks"
"socks",
"vpn"
]
},
"backendProxyEndpoint": {
@ -3344,7 +3345,8 @@ func init() {
"udpTunnel",
"caddy",
"drive",
"socks"
"socks",
"vpn"
]
},
"backendProxyEndpoint": {

View File

@ -11,6 +11,8 @@ const (
UdpTunnelBackendMode BackendMode = "udpTunnel"
CaddyBackendMode BackendMode = "caddy"
DriveBackendMode BackendMode = "drive"
SocksBackendMode BackendMode = "socks"
VpnBackendMode BackendMode = "vpn"
)
type ShareMode string

View File

@ -7,6 +7,9 @@ WEB_BACKEND_MODE: BackendMode = "web"
TCP_TUNNEL_BACKEND_MODE: BackendMode = "tcpTunnel"
UDP_TUNNEL_BACKEND_MODE: BackendMode = "udpTunnel"
CADDY_BACKEND_MODE: BackendMode = "caddy"
DRIVE_BACKEND_MODE: BackendMode = "drive"
SOCKS_BACKEND_MODE: BackendMode = "socks"
VPN_BACKEND_MODE: BackendMode = "vpn"
ShareMode = str

View File

@ -194,7 +194,7 @@ class ShareRequest(object):
:param backend_mode: The backend_mode of this ShareRequest. # noqa: E501
:type: str
"""
allowed_values = ["proxy", "web", "tcpTunnel", "udpTunnel", "caddy", "drive", "socks"] # noqa: E501
allowed_values = ["proxy", "web", "tcpTunnel", "udpTunnel", "caddy", "drive", "socks", "vpn"] # noqa: E501
if backend_mode not in allowed_values:
raise ValueError(
"Invalid value for `backend_mode` ({0}), must be one of {1}" # noqa: E501

View File

@ -1039,7 +1039,7 @@ definitions:
type: string
backendMode:
type: string
enum: ["proxy", "web", "tcpTunnel", "udpTunnel", "caddy", "drive", "socks"]
enum: ["proxy", "web", "tcpTunnel", "udpTunnel", "caddy", "drive", "socks", "vpn"]
backendProxyEndpoint:
type: string
authScheme:

View File

@ -34,6 +34,10 @@ const config = {
'@docusaurus/plugin-client-redirects',
{
redirects: [
{
to: '/docs/guides/self-hosting/linux',
from: ['/docs/guides/self-hosting/self_hosting_guide'],
},
{
to: '/docs/guides/self-hosting/metrics-and-limits/configuring-limits',
from: ['/docs/guides/metrics-and-limits/configuring-limits'],

View File

@ -6,5 +6,5 @@
},
"cleanUrls": false,
"public": true,
"ignoreCommand": "grep -qE '^(gh-pages)$' <<< ${VERCEL_GIT_COMMIT_REF} || git diff --quiet HEAD^ HEAD -- ../website/ ../docs/"
"ignoreCommand": "grep -qE '^(gh-pages)$' <<< ${VERCEL_GIT_COMMIT_REF} || git diff --quiet HEAD^ HEAD -- ../website/ ../docs/ ../**/*.md"
}