From a9c87ce1fefadd2086b96a0b11018c7a60e12135 Mon Sep 17 00:00:00 2001 From: Kenneth Bingham Date: Tue, 23 Apr 2024 16:06:50 -0400 Subject: [PATCH 1/7] add docker self-hosting quickstart --- CHANGELOG.md | 2 + docker/compose/quickstart/.gitignore | 2 + docker/compose/quickstart/Caddyfile | 32 +++ docker/compose/quickstart/README.md | 192 ++++++++++++++++++ .../quickstart/bootstrap-controller.bash | 23 +++ .../quickstart/bootstrap-frontend.bash | 116 +++++++++++ docker/compose/quickstart/caddy.Dockerfile | 19 ++ .../compose/quickstart/compose.override.yml | 136 +++++++++++++ docker/compose/quickstart/envsubst.bash | 42 ++++ .../zrok-controller-config.yml.envsubst | 25 +++ .../quickstart/zrok-controller.Dockerfile | 36 ++++ .../zrok-frontend-config.yml.envsubst | 18 ++ .../quickstart/zrok-frontend.Dockerfile | 45 ++++ docker/images/zrok/Dockerfile | 8 +- docs/guides/self-hosting/docker.mdx | 9 + docs/guides/self-hosting/linux.mdx | 9 +- 16 files changed, 703 insertions(+), 11 deletions(-) create mode 100644 docker/compose/quickstart/.gitignore create mode 100644 docker/compose/quickstart/Caddyfile create mode 100644 docker/compose/quickstart/README.md create mode 100755 docker/compose/quickstart/bootstrap-controller.bash create mode 100755 docker/compose/quickstart/bootstrap-frontend.bash create mode 100644 docker/compose/quickstart/caddy.Dockerfile create mode 100644 docker/compose/quickstart/compose.override.yml create mode 100755 docker/compose/quickstart/envsubst.bash create mode 100644 docker/compose/quickstart/zrok-controller-config.yml.envsubst create mode 100644 docker/compose/quickstart/zrok-controller.Dockerfile create mode 100644 docker/compose/quickstart/zrok-frontend-config.yml.envsubst create mode 100644 docker/compose/quickstart/zrok-frontend.Dockerfile create mode 100644 docs/guides/self-hosting/docker.mdx diff --git a/CHANGELOG.md b/CHANGELOG.md index 3428d5ea..45559287 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## v0.4.28 +FEATURE: A minimal 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 diff --git a/docker/compose/quickstart/.gitignore b/docker/compose/quickstart/.gitignore new file mode 100644 index 00000000..7ee12f8c --- /dev/null +++ b/docker/compose/quickstart/.gitignore @@ -0,0 +1,2 @@ +/.env +/compose.yml \ No newline at end of file diff --git a/docker/compose/quickstart/Caddyfile b/docker/compose/quickstart/Caddyfile new file mode 100644 index 00000000..79daee81 --- /dev/null +++ b/docker/compose/quickstart/Caddyfile @@ -0,0 +1,32 @@ +{ + 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} + propagation_timeout 60m + } + + 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} + } +} diff --git a/docker/compose/quickstart/README.md b/docker/compose/quickstart/README.md new file mode 100644 index 00000000..539cd878 --- /dev/null +++ b/docker/compose/quickstart/README.md @@ -0,0 +1,192 @@ + +## Docker Quickstart + +### DNS Configuration + +The quickstart makes these assumptions about your global DNS configuration. + +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. A Caddy DNS plugin is available for your DNS provider (see [github.com/caddy-dns](https://github.com/caddy-dns)) +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 a 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. + +```bash +wget https://get.openziti.io/dock/all-in-one/compose.yml +wget -O ./compose.override.yml https://get.openziti.io/zrok-quick/compose.yml +``` + +The project files provide these service containers. + +- `compose.yml` + - `quickstart` +- `compose.override.yml` + - `zrok-controller` + - `zrok-frontend` + - `caddy` + +### Configure the Docker Compose Project Environment + +Create an `.env` file in the working directory. + +```bash title=".env required" +ZROK_DNS_ZONE=share.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 + +CADDY_DNS_PLUGIN=cloudflare +CADDY_DNS_PLUGIN_TOKEN=abcd1234 +CADDY_ACME_EMAIL=me@example.com +``` + +```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. Enable an environment on this device with the account token from the previous step. + + ```bash + zrok enable heMqncCyxZcx + ``` + +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 + ``` + +### 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`) + + +### 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 + + (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 + ``` diff --git a/docker/compose/quickstart/bootstrap-controller.bash b/docker/compose/quickstart/bootstrap-controller.bash new file mode 100755 index 00000000..6db0b151 --- /dev/null +++ b/docker/compose/quickstart/bootstrap-controller.bash @@ -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 "$@" diff --git a/docker/compose/quickstart/bootstrap-frontend.bash b/docker/compose/quickstart/bootstrap-frontend.bash new file mode 100755 index 00000000..57dbcd6d --- /dev/null +++ b/docker/compose/quickstart/bootstrap-frontend.bash @@ -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 "${@}" diff --git a/docker/compose/quickstart/caddy.Dockerfile b/docker/compose/quickstart/caddy.Dockerfile new file mode 100644 index 00000000..642932a7 --- /dev/null +++ b/docker/compose/quickstart/caddy.Dockerfile @@ -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 diff --git a/docker/compose/quickstart/compose.override.yml b/docker/compose/quickstart/compose.override.yml new file mode 100644 index 00000000..e7f83269 --- /dev/null +++ b/docker/compose/quickstart/compose.override.yml @@ -0,0 +1,136 @@ +# 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_ADMIN_PWD: ${ZROK_ADMIN_PWD} # admin account password (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} + 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}:80:80 + - ${CADDY_INTERFACE}:443:443 + # - ${CADDY_INTERFACE}: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: diff --git a/docker/compose/quickstart/envsubst.bash b/docker/compose/quickstart/envsubst.bash new file mode 100755 index 00000000..a0e793da --- /dev/null +++ b/docker/compose/quickstart/envsubst.bash @@ -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" diff --git a/docker/compose/quickstart/zrok-controller-config.yml.envsubst b/docker/compose/quickstart/zrok-controller-config.yml.envsubst new file mode 100644 index 00000000..389f4bce --- /dev/null +++ b/docker/compose/quickstart/zrok-controller-config.yml.envsubst @@ -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} diff --git a/docker/compose/quickstart/zrok-controller.Dockerfile b/docker/compose/quickstart/zrok-controller.Dockerfile new file mode 100644 index 00000000..84072daa --- /dev/null +++ b/docker/compose/quickstart/zrok-controller.Dockerfile @@ -0,0 +1,36 @@ + +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/ +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"] diff --git a/docker/compose/quickstart/zrok-frontend-config.yml.envsubst b/docker/compose/quickstart/zrok-frontend-config.yml.envsubst new file mode 100644 index 00000000..b76e273d --- /dev/null +++ b/docker/compose/quickstart/zrok-frontend-config.yml.envsubst @@ -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} diff --git a/docker/compose/quickstart/zrok-frontend.Dockerfile b/docker/compose/quickstart/zrok-frontend.Dockerfile new file mode 100644 index 00000000..4221dc46 --- /dev/null +++ b/docker/compose/quickstart/zrok-frontend.Dockerfile @@ -0,0 +1,45 @@ + +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 /usr/local/bin/ +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 + +# install bootstrapping script as entrypoint +COPY ./bootstrap-frontend.bash /usr/local/bin/ + +# 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"] diff --git a/docker/images/zrok/Dockerfile b/docker/images/zrok/Dockerfile index b8e52a3d..21c15d2a 100644 --- a/docker/images/zrok/Dockerfile +++ b/docker/images/zrok/Dockerfile @@ -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 \ diff --git a/docs/guides/self-hosting/docker.mdx b/docs/guides/self-hosting/docker.mdx new file mode 100644 index 00000000..fe87a942 --- /dev/null +++ b/docs/guides/self-hosting/docker.mdx @@ -0,0 +1,9 @@ +--- +title: Self-hosting guide for Docker +sidebar_label: Docker +sidebar_position: 45 +--- + +import DockerInstance from '/../docker/compose/quickstart/README.md' + + diff --git a/docs/guides/self-hosting/linux.mdx b/docs/guides/self-hosting/linux.mdx index bc870603..48a354f5 100644 --- a/docs/guides/self-hosting/linux.mdx +++ b/docs/guides/self-hosting/linux.mdx @@ -109,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: { ... } @@ -181,10 +181,9 @@ $ 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 ``` From 1a4c30a40e5adafbfa53abdd61a741dd26e63f93 Mon Sep 17 00:00:00 2001 From: Kenneth Bingham Date: Fri, 26 Apr 2024 11:58:14 -0400 Subject: [PATCH 2/7] correct and document Docker quickstart --- CHANGELOG.md | 2 +- docker/compose/quickstart/README.md | 20 +++++++++---------- .../compose/quickstart/compose.override.yml | 11 +++++----- .../quickstart/zrok-controller.Dockerfile | 1 + .../quickstart/zrok-frontend.Dockerfile | 6 ++---- 5 files changed, 20 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 45559287..c8546451 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ## v0.4.28 -FEATURE: A minimal 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. +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. diff --git a/docker/compose/quickstart/README.md b/docker/compose/quickstart/README.md index 539cd878..a7fd90a2 100644 --- a/docker/compose/quickstart/README.md +++ b/docker/compose/quickstart/README.md @@ -19,11 +19,11 @@ wget https://get.openziti.io/dock/all-in-one/compose.yml wget -O ./compose.override.yml https://get.openziti.io/zrok-quick/compose.yml ``` -The project files provide these service containers. +These two Compose project files provide different service containers. -- `compose.yml` +- `compose.yml` defines the service containers for Compose profile "ziti" - `quickstart` -- `compose.override.yml` +- `compose.override.yml` defines the service containers for Compose profile "zrok" - `zrok-controller` - `zrok-frontend` - `caddy` @@ -99,18 +99,18 @@ You must enable each device environment with the account token obtained when the 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. Enable an environment on this device with the account token from the previous step. - - ```bash - zrok enable heMqncCyxZcx - ``` - 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. @@ -185,7 +185,7 @@ The `quickstart` and `caddy` containers publish ports to all devices that use zr 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. + 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 diff --git a/docker/compose/quickstart/compose.override.yml b/docker/compose/quickstart/compose.override.yml index e7f83269..8c43937c 100644 --- a/docker/compose/quickstart/compose.override.yml +++ b/docker/compose/quickstart/compose.override.yml @@ -46,7 +46,8 @@ services: # ports: # - 127.0.0.1:${ZROK_CTRL_PORT:-18080}:${ZROK_CTRL_PORT:-18080} environment: - ZROK_ADMIN_PWD: ${ZROK_ADMIN_PWD} # admin account password (initial user account) + 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: @@ -63,7 +64,7 @@ services: 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} + 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} @@ -113,9 +114,9 @@ services: - 443/udp # Caddy's HTTP/3 (QUIC) (not published) - 2019/tcp # Caddy's admin API (not published) ports: - - ${CADDY_INTERFACE}:80:80 - - ${CADDY_INTERFACE}:443:443 - # - ${CADDY_INTERFACE}:443:443/udp" # future: HTTP/3 (QUIC) + - ${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 diff --git a/docker/compose/quickstart/zrok-controller.Dockerfile b/docker/compose/quickstart/zrok-controller.Dockerfile index 84072daa..6f00f934 100644 --- a/docker/compose/quickstart/zrok-controller.Dockerfile +++ b/docker/compose/quickstart/zrok-controller.Dockerfile @@ -19,6 +19,7 @@ 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 \ diff --git a/docker/compose/quickstart/zrok-frontend.Dockerfile b/docker/compose/quickstart/zrok-frontend.Dockerfile index 4221dc46..c46794a3 100644 --- a/docker/compose/quickstart/zrok-frontend.Dockerfile +++ b/docker/compose/quickstart/zrok-frontend.Dockerfile @@ -21,7 +21,8 @@ ARG ZROK_OAUTH_GITHUB_CLIENT_ID ARG ZROK_OAUTH_GITHUB_CLIENT_SECRET # render zrok frontend config.yml -COPY ./envsubst.bash /usr/local/bin/ +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 \ @@ -35,9 +36,6 @@ RUN envsubst.bash \ ZROK_OAUTH_GITHUB_CLIENT_SECRET=${ZROK_OAUTH_GITHUB_CLIENT_SECRET} \ < /tmp/zrok-frontend-config.yml.envsubst > /etc/zrok-frontend/config.yml -# install bootstrapping script as entrypoint -COPY ./bootstrap-frontend.bash /usr/local/bin/ - # run as ziggy (or ZIGGY_UID if set in compose project) USER ziggy ENV HOME=/var/lib/zrok-frontend From 4e62ec7b24ba01a724af5c47d90cc9b0be1ca4be Mon Sep 17 00:00:00 2001 From: Kenneth Bingham Date: Fri, 26 Apr 2024 14:37:20 -0400 Subject: [PATCH 3/7] add the zip commands --- docker/compose/quickstart/README.md | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/docker/compose/quickstart/README.md b/docker/compose/quickstart/README.md index a7fd90a2..0effb45a 100644 --- a/docker/compose/quickstart/README.md +++ b/docker/compose/quickstart/README.md @@ -10,23 +10,27 @@ 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/caddy-dns)) 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 a Docker Compose Project +### 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. -```bash -wget https://get.openziti.io/dock/all-in-one/compose.yml -wget -O ./compose.override.yml https://get.openziti.io/zrok-quick/compose.yml -``` +1. Get the ziti quickstart Compose file. -These two Compose project files provide different service containers. + ```bash + wget https://get.openziti.io/dock/all-in-one/compose.yml + ``` -- `compose.yml` defines the service containers for Compose profile "ziti" - - `quickstart` -- `compose.override.yml` defines the service containers for Compose profile "zrok" - - `zrok-controller` - - `zrok-frontend` - - `caddy` +1. Get the zrok quickstart ZIP file. + + ```bash + wget https://github.com/openziti/zrok/archive/refs/heads/main.zip + ``` + +1. Unzip the zrok quickstart in the project directory. + + ```bash + unzip -j -d . main.zip '*/docker/compose/quickstart/*' + ``` ### Configure the Docker Compose Project Environment From a770cbc882151b08d0b6c2854fa813b831c3a03d Mon Sep 17 00:00:00 2001 From: Kenneth Bingham Date: Fri, 26 Apr 2024 14:42:23 -0400 Subject: [PATCH 4/7] build docs when any markdown changes so we can import them in docusaurus --- website/vercel.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/vercel.json b/website/vercel.json index c3b7bf0a..4da93f9a 100644 --- a/website/vercel.json +++ b/website/vercel.json @@ -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" } From f466d2dd5c21e984893e1969634da44c278aec5e Mon Sep 17 00:00:00 2001 From: Kenneth Bingham Date: Fri, 26 Apr 2024 15:14:45 -0400 Subject: [PATCH 5/7] call the Docker self-hosting compose project 'zrok-instance' --- docker/compose/{quickstart => zrok-instance}/.gitignore | 0 docker/compose/{quickstart => zrok-instance}/Caddyfile | 0 docker/compose/{quickstart => zrok-instance}/README.md | 6 +++--- .../{quickstart => zrok-instance}/bootstrap-controller.bash | 0 .../{quickstart => zrok-instance}/bootstrap-frontend.bash | 0 .../compose/{quickstart => zrok-instance}/caddy.Dockerfile | 0 .../{quickstart => zrok-instance}/compose.override.yml | 0 docker/compose/{quickstart => zrok-instance}/envsubst.bash | 0 .../zrok-controller-config.yml.envsubst | 0 .../zrok-controller.Dockerfile | 0 .../zrok-frontend-config.yml.envsubst | 0 .../{quickstart => zrok-instance}/zrok-frontend.Dockerfile | 0 docs/guides/self-hosting/docker.mdx | 2 +- 13 files changed, 4 insertions(+), 4 deletions(-) rename docker/compose/{quickstart => zrok-instance}/.gitignore (100%) rename docker/compose/{quickstart => zrok-instance}/Caddyfile (100%) rename docker/compose/{quickstart => zrok-instance}/README.md (98%) rename docker/compose/{quickstart => zrok-instance}/bootstrap-controller.bash (100%) rename docker/compose/{quickstart => zrok-instance}/bootstrap-frontend.bash (100%) rename docker/compose/{quickstart => zrok-instance}/caddy.Dockerfile (100%) rename docker/compose/{quickstart => zrok-instance}/compose.override.yml (100%) rename docker/compose/{quickstart => zrok-instance}/envsubst.bash (100%) rename docker/compose/{quickstart => zrok-instance}/zrok-controller-config.yml.envsubst (100%) rename docker/compose/{quickstart => zrok-instance}/zrok-controller.Dockerfile (100%) rename docker/compose/{quickstart => zrok-instance}/zrok-frontend-config.yml.envsubst (100%) rename docker/compose/{quickstart => zrok-instance}/zrok-frontend.Dockerfile (100%) diff --git a/docker/compose/quickstart/.gitignore b/docker/compose/zrok-instance/.gitignore similarity index 100% rename from docker/compose/quickstart/.gitignore rename to docker/compose/zrok-instance/.gitignore diff --git a/docker/compose/quickstart/Caddyfile b/docker/compose/zrok-instance/Caddyfile similarity index 100% rename from docker/compose/quickstart/Caddyfile rename to docker/compose/zrok-instance/Caddyfile diff --git a/docker/compose/quickstart/README.md b/docker/compose/zrok-instance/README.md similarity index 98% rename from docker/compose/quickstart/README.md rename to docker/compose/zrok-instance/README.md index 0effb45a..210d6f77 100644 --- a/docker/compose/quickstart/README.md +++ b/docker/compose/zrok-instance/README.md @@ -20,16 +20,16 @@ Create a working directory on your Docker host and save these Docker Compose pro wget https://get.openziti.io/dock/all-in-one/compose.yml ``` -1. Get the zrok quickstart ZIP file. +1. Get the zrok repo ZIP file. ```bash wget https://github.com/openziti/zrok/archive/refs/heads/main.zip ``` -1. Unzip the zrok quickstart in the project directory. +1. Unzip the zrok-instance files into the project directory. ```bash - unzip -j -d . main.zip '*/docker/compose/quickstart/*' + unzip -j -d . main.zip '*/docker/compose/zrok-instance/*' ``` ### Configure the Docker Compose Project Environment diff --git a/docker/compose/quickstart/bootstrap-controller.bash b/docker/compose/zrok-instance/bootstrap-controller.bash similarity index 100% rename from docker/compose/quickstart/bootstrap-controller.bash rename to docker/compose/zrok-instance/bootstrap-controller.bash diff --git a/docker/compose/quickstart/bootstrap-frontend.bash b/docker/compose/zrok-instance/bootstrap-frontend.bash similarity index 100% rename from docker/compose/quickstart/bootstrap-frontend.bash rename to docker/compose/zrok-instance/bootstrap-frontend.bash diff --git a/docker/compose/quickstart/caddy.Dockerfile b/docker/compose/zrok-instance/caddy.Dockerfile similarity index 100% rename from docker/compose/quickstart/caddy.Dockerfile rename to docker/compose/zrok-instance/caddy.Dockerfile diff --git a/docker/compose/quickstart/compose.override.yml b/docker/compose/zrok-instance/compose.override.yml similarity index 100% rename from docker/compose/quickstart/compose.override.yml rename to docker/compose/zrok-instance/compose.override.yml diff --git a/docker/compose/quickstart/envsubst.bash b/docker/compose/zrok-instance/envsubst.bash similarity index 100% rename from docker/compose/quickstart/envsubst.bash rename to docker/compose/zrok-instance/envsubst.bash diff --git a/docker/compose/quickstart/zrok-controller-config.yml.envsubst b/docker/compose/zrok-instance/zrok-controller-config.yml.envsubst similarity index 100% rename from docker/compose/quickstart/zrok-controller-config.yml.envsubst rename to docker/compose/zrok-instance/zrok-controller-config.yml.envsubst diff --git a/docker/compose/quickstart/zrok-controller.Dockerfile b/docker/compose/zrok-instance/zrok-controller.Dockerfile similarity index 100% rename from docker/compose/quickstart/zrok-controller.Dockerfile rename to docker/compose/zrok-instance/zrok-controller.Dockerfile diff --git a/docker/compose/quickstart/zrok-frontend-config.yml.envsubst b/docker/compose/zrok-instance/zrok-frontend-config.yml.envsubst similarity index 100% rename from docker/compose/quickstart/zrok-frontend-config.yml.envsubst rename to docker/compose/zrok-instance/zrok-frontend-config.yml.envsubst diff --git a/docker/compose/quickstart/zrok-frontend.Dockerfile b/docker/compose/zrok-instance/zrok-frontend.Dockerfile similarity index 100% rename from docker/compose/quickstart/zrok-frontend.Dockerfile rename to docker/compose/zrok-instance/zrok-frontend.Dockerfile diff --git a/docs/guides/self-hosting/docker.mdx b/docs/guides/self-hosting/docker.mdx index fe87a942..2afb4a79 100644 --- a/docs/guides/self-hosting/docker.mdx +++ b/docs/guides/self-hosting/docker.mdx @@ -4,6 +4,6 @@ sidebar_label: Docker sidebar_position: 45 --- -import DockerInstance from '/../docker/compose/quickstart/README.md' +import DockerInstance from '/../docker/compose/zrok-instance/README.md' From adbbda3911b87564dbd68003ba8ca3ef25bae45b Mon Sep 17 00:00:00 2001 From: Kenneth Bingham Date: Fri, 26 Apr 2024 15:45:53 -0400 Subject: [PATCH 6/7] add troubleshooting example for route53 --- docker/compose/zrok-instance/Caddyfile | 1 - docker/compose/zrok-instance/README.md | 29 +++++++++++++++++++++----- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/docker/compose/zrok-instance/Caddyfile b/docker/compose/zrok-instance/Caddyfile index 79daee81..425b831c 100644 --- a/docker/compose/zrok-instance/Caddyfile +++ b/docker/compose/zrok-instance/Caddyfile @@ -11,7 +11,6 @@ http:// { *.{$ZROK_DNS_ZONE} { tls { dns {$CADDY_DNS_PLUGIN} {$CADDY_DNS_PLUGIN_TOKEN} - propagation_timeout 60m } log { diff --git a/docker/compose/zrok-instance/README.md b/docker/compose/zrok-instance/README.md index 210d6f77..b2aa9169 100644 --- a/docker/compose/zrok-instance/README.md +++ b/docker/compose/zrok-instance/README.md @@ -5,9 +5,9 @@ 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/caddy-dns)) 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. A Caddy DNS plugin is available for your DNS provider (see [github.com/caddy-dns](https://github.com/caddy-dns)) 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 @@ -39,16 +39,16 @@ 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 - -CADDY_DNS_PLUGIN=cloudflare -CADDY_DNS_PLUGIN_TOKEN=abcd1234 -CADDY_ACME_EMAIL=me@example.com ``` ```bash title=".env options" @@ -194,3 +194,22 @@ The `quickstart` and `caddy` containers publish ports to all devices that use zr ```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 + ``` From 1126d5e6c4317b5a3e0141869275a6cb8a61f003 Mon Sep 17 00:00:00 2001 From: Kenneth Bingham Date: Fri, 26 Apr 2024 16:51:43 -0400 Subject: [PATCH 7/7] add a docker fetch script for conveniently downloading the compose project files --- docker/compose/zrok-instance/README.md | 20 +++++- docker/compose/zrok-instance/fetch.bash | 86 +++++++++++++++++++++++++ 2 files changed, 104 insertions(+), 2 deletions(-) create mode 100755 docker/compose/zrok-instance/fetch.bash diff --git a/docker/compose/zrok-instance/README.md b/docker/compose/zrok-instance/README.md index b2aa9169..c4219998 100644 --- a/docker/compose/zrok-instance/README.md +++ b/docker/compose/zrok-instance/README.md @@ -5,7 +5,7 @@ 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/caddy-dns)) +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. @@ -14,7 +14,23 @@ The quickstart makes these assumptions about your global DNS configuration. 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. -1. Get the ziti quickstart Compose file. +#### 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 diff --git a/docker/compose/zrok-instance/fetch.bash b/docker/compose/zrok-instance/fetch.bash new file mode 100755 index 00000000..9ba80def --- /dev/null +++ b/docker/compose/zrok-instance/fetch.bash @@ -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 "${@}"