diff --git a/404.html b/404.html index 9a5f3c15..3f1e7228 100644 --- a/404.html +++ b/404.html @@ -10,7 +10,7 @@ - + diff --git a/assets/js/cda0d2e5.e7881b13.js b/assets/js/cda0d2e5.1b2a9583.js similarity index 87% rename from assets/js/cda0d2e5.e7881b13.js rename to assets/js/cda0d2e5.1b2a9583.js index d177cd68..272b5237 100644 --- a/assets/js/cda0d2e5.e7881b13.js +++ b/assets/js/cda0d2e5.1b2a9583.js @@ -1 +1 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[846],{9836:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>k,contentTitle:()=>b,default:()=>y,frontMatter:()=>j,metadata:()=>g,toc:()=>v});var s=r(5893),i=r(1151),t=r(7294),o=r(4866),a=r(5518);const l=function(e){const[n,r]=(0,t.useState)(null);return(0,t.useEffect)((()=>{["Mac OS","Windows","Linux"].includes(a.BF)?r(a.BF):r("Linux")}),[]),(0,s.jsx)(s.Fragment,{children:(0,s.jsx)(o.Z,{...e,defaultValue:n,children:e.children})})};var c=r(5162),d=r(1326),h=r(2753);function p(e){const n={a:"a",code:"code",h2:"h2",h3:"h3",li:"li",ol:"ol",p:"p",pre:"pre",ul:"ul",...(0,i.a)(),...e.components},{Details:r}=n;return r||function(e,n){throw new Error("Expected "+(n?"component":"object")+" `"+e+"` to be defined: you likely forgot to import, pass, or provide it.")}("Details",!0),(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h2,{id:"goal",children:"Goal"}),"\n",(0,s.jsx)(n.p,{children:"Proxy a reserved public subdomain to a backend target with an always-on Linux system service."}),"\n",(0,s.jsx)(n.h2,{id:"how-it-works",children:"How it Works"}),"\n",(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.code,{children:"zrok-share"})," package creates a ",(0,s.jsx)(n.code,{children:"zrok-share.service"})," unit in systemd. The administrator edits the service's configuration file to specify the:"]}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsx)(n.li,{children:"zrok environment enable token"}),"\n",(0,s.jsxs)(n.li,{children:["target URL or files to be shared and backend mode, e.g. ",(0,s.jsx)(n.code,{children:"proxy"})]}),"\n",(0,s.jsx)(n.li,{children:"authentication options, if wanted"}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"When the service starts it will:"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:["enable the zrok environment unless ",(0,s.jsx)(n.code,{children:"/var/lib/zrok-share/.zrok/environment.json"})," exists"]}),"\n",(0,s.jsxs)(n.li,{children:["reserve a public subdomain for the service unless ",(0,s.jsx)(n.code,{children:"/var/lib/zrok-share/.zrok/reserved.json"})," exists"]}),"\n",(0,s.jsxs)(n.li,{children:["start sharing the target specified as ",(0,s.jsx)(n.code,{children:"ZROK_TARGET"})," in the environment file"]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"installation",children:"Installation"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["Set up ",(0,s.jsx)(n.code,{children:"zrok"}),"'s Linux package repository by following ",(0,s.jsx)(n.a,{href:"/docs/guides/install/linux#install-zrok-from-the-repository",children:"the Linux install guide"}),", or run this one-liner to complete the repo setup and install packages."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"curl -sSLf https://get.openziti.io/install.bash \\\n| sudo bash -s zrok-share\n"})}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["If you set up the repository by following the guide, then also install the ",(0,s.jsx)(n.code,{children:"zrok-share"})," package. This package provides the systemd service."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",metastring:'title="Ubuntu, Debian"',children:"sudo sudo apt install zrok-share\n"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",metastring:'title="Fedora, Rocky"',children:"sudo dnf install zrok-share\n"})}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(r,{children:[(0,s.jsx)("summary",{children:"Ansible Playbook"}),(0,s.jsxs)(h.Z,{title:"Set up package repository and install zrok-share",children:[d.Z,"\n- name: Install zrok-share package\n gather_facts: false\n hosts: all \n become: true\n tasks:\n - name: Install zrok-share\n ansible.builtin.package:\n name: zrok-share\n state: present\n\n - name: Copy env config from Ansible controller to target\n copy:\n dest: /opt/openziti/etc/zrok/zrok-share.env\n src: /opt/openziti/etc/zrok/zrok-share.env\n\n - name: Enable and restart service\n systemd:\n name: zrok-share\n enabled: yes\n state: restarted\n daemon_reload: yes\n\n - name: Wait for service\n systemd:\n name: zrok-share\n state: started\n register: service_status\n until: service_status.status.ActiveState == 'active'\n retries: 30\n delay: 1\n"]})]}),"\n",(0,s.jsx)(n.h2,{id:"enable",children:"Enable"}),"\n",(0,s.jsx)(n.p,{children:"Save the enable token from the zrok console in the configuration file."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",metastring:'title="/opt/openziti/etc/zrok/zrok-share.env"',children:'ZROK_ENABLE_TOKEN="14cbfca9772f"\n'})}),"\n",(0,s.jsx)(n.h2,{id:"use-cases",children:"Use Cases"}),"\n",(0,s.jsxs)(n.p,{children:["You may change the target for the current backend mode, e.g. ",(0,s.jsx)(n.code,{children:"proxy"}),", by editing the configuration file and restarting the service. The reserved subdomain will remain the same."]}),"\n",(0,s.jsxs)(n.p,{children:["You may switch between backend modes or change authentication options by deleting ",(0,s.jsx)(n.code,{children:"/var/lib/zrok-share/.zrok/reserved.json"})," and restarting the service. A new subdomain will be reserved."]}),"\n",(0,s.jsx)(n.h3,{id:"proxy-a-web-server",children:"Proxy a Web Server"}),"\n",(0,s.jsx)(n.p,{children:"Proxy a reserved subdomain to an existing web server. The web server could be on a private network or on the same host as zrok."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",metastring:'title="/opt/openziti/etc/zrok/zrok-share.env"',children:'ZROK_TARGET="http://127.0.0.1:3000"\nZROK_BACKEND_MODE="proxy"\n'})}),"\n",(0,s.jsxs)(n.p,{children:["If your HTTPS server has an unverifiable TLS server certificate then you must set ",(0,s.jsx)(n.code,{children:"--insecure"}),"."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",metastring:'title="/opt/openziti/etc/zrok/zrok-share.env"',children:'ZROK_INSECURE="--insecure"\n'})}),"\n",(0,s.jsx)(n.h3,{id:"serve-static-files",children:"Serve Static Files"}),"\n",(0,s.jsxs)(n.p,{children:["Run zrok's embedded web server to serve the files in a directory. If there's an ",(0,s.jsx)(n.code,{children:"index.html"})," file in the directory then visitors will see that web page in their browser, otherwise they'll see a generated index of the files. The directory must be readable by 'other', e.g. ",(0,s.jsx)(n.code,{children:"chmod -R o+rX /var/www/html"}),"."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",metastring:'title="/opt/openziti/etc/zrok/zrok-share.env"',children:'ZROK_TARGET="/var/www/html"\nZROK_BACKEND_MODE="web"\n'})}),"\n",(0,s.jsx)(n.h3,{id:"caddy-server",children:"Caddy Server"}),"\n",(0,s.jsx)(n.p,{children:"Use zrok's built-in Caddy server to serve static files or as a reverse proxy to multiple web servers with various HTTP routes or as a load-balanced set. A sample Caddyfile is available in the path shown."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",metastring:'title="/opt/openziti/etc/zrok/zrok-share.env"',children:'ZROK_TARGET="/opt/openziti/etc/zrok/multiple_upstream.Caddyfile"\nZROK_BACKEND_MODE="caddy"\n'})}),"\n",(0,s.jsx)(n.h3,{id:"network-drive",children:"Network Drive"}),"\n",(0,s.jsxs)(n.p,{children:["This uses zrok's ",(0,s.jsx)(n.code,{children:"drive"})," backend mode to serve a directory of static files as a virtual network drive. The directory must be readable by 'other', e.g. ",(0,s.jsx)(n.code,{children:"chmod -R o+rX /usr/share/doc"}),"."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",metastring:'title="/opt/openziti/etc/zrok/zrok-share.env"',children:'ZROK_TARGET="/usr/share/doc"\nZROK_BACKEND_MODE="drive"\n'})}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.a,{href:"https://blog.openziti.io/zrok-drives-an-early-preview",children:"Learn more about this feature in this blog post"}),"."]}),"\n",(0,s.jsx)(n.h2,{id:"authentication",children:"Authentication"}),"\n",(0,s.jsx)(n.p,{children:"You can limit access to certain email addresses with OAuth or require a password."}),"\n",(0,s.jsx)(n.h3,{id:"oauth",children:"OAuth"}),"\n",(0,s.jsx)(n.p,{children:"You can require that visitors authenticate with an email address that matches at least one of the suffixes you specify. Add the following to the configuration file."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",metastring:'title="/opt/openziti/etc/zrok/zrok-share.env"',children:'ZROK_OAUTH_PROVIDER="github" # or google\nZROK_OAUTH_EMAILS="bob@example.com @acme.example.com"\n'})}),"\n",(0,s.jsx)(n.h3,{id:"password",children:"Password"}),"\n",(0,s.jsx)(n.p,{children:"Enable HTTP basic authentication by adding the following to the configuration file."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",metastring:'title="/opt/openziti/etc/zrok/zrok-share.env"',children:'ZROK_BASIC_AUTH="user:passwd"\n'})}),"\n",(0,s.jsx)(n.h2,{id:"start-the-service",children:"Start the Service"}),"\n",(0,s.jsx)(n.p,{children:"Start the service, and check the zrok console or the service log for the reserved subdomain."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",metastring:'title="run now and at startup"',children:"sudo systemctl enable --now zrok-share.service\n"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",metastring:'title="run now"',children:"sudo systemctl restart zrok-share.service\n"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"journalctl -u zrok-share.service\n"})}),"\n",(0,s.jsx)(n.h2,{id:"compatibility",children:"Compatibility"}),"\n",(0,s.jsxs)(n.p,{children:["The Linux distribution must have a package manager that understands the ",(0,s.jsx)(n.code,{children:".deb"})," or ",(0,s.jsx)(n.code,{children:".rpm"})," format and be running systemd v232 or newer. The service was tested with:"]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"Ubuntu 20.04, 22.04, 23.04"}),"\n",(0,s.jsx)(n.li,{children:"Debian 11 12"}),"\n",(0,s.jsx)(n.li,{children:"Rocky 8, 9"}),"\n",(0,s.jsx)(n.li,{children:"Fedora 37, 38"}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"package-contents",children:"Package Contents"}),"\n",(0,s.jsxs)(n.p,{children:["The files included in the ",(0,s.jsx)(n.code,{children:"zrok-share"})," package are sourced ",(0,s.jsx)(n.a,{href:"https://github.com/openziti/zrok/tree/main/nfpm",children:"here in GitHub"}),"."]})]})}function u(e={}){const{wrapper:n}={...(0,i.a)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(p,{...e})}):p(e)}function m(e){const n={a:"a",code:"code",h2:"h2",h3:"h3",li:"li",ol:"ol",p:"p",pre:"pre",...(0,i.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h2,{id:"goal",children:"Goal"}),"\n",(0,s.jsx)(n.p,{children:"Proxy a reserved public subdomain to a backend target with an always-on Docker Compose service."}),"\n",(0,s.jsx)(n.h2,{id:"how-it-works",children:"How it Works"}),"\n",(0,s.jsx)(n.p,{children:"The Docker Compose project uses your zrok account token to reserve a public subdomain and keep sharing the backend\ntarget."}),"\n",(0,s.jsx)(n.p,{children:"When the project runs it will:"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:["enable a zrok environment unless ",(0,s.jsx)(n.code,{children:"/mnt/.zrok/environment.json"})," exists in the ",(0,s.jsx)(n.code,{children:"zrok_env"})," volume"]}),"\n",(0,s.jsxs)(n.li,{children:["reserve a public subdomain for the service unless ",(0,s.jsx)(n.code,{children:"/mnt/.zrok/reserved.json"})," exists"]}),"\n",(0,s.jsxs)(n.li,{children:["start sharing the target specified in the ",(0,s.jsx)(n.code,{children:"ZROK_TARGET"})," environment variable"]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"create-the-docker-project",children:"Create the Docker Project"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsx)(n.li,{children:"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."}),"\n",(0,s.jsxs)(n.li,{children:["Download ",(0,s.jsxs)(n.a,{href:"pathname:///zrok-public-reserved/compose.yml",children:["the reserved public share ",(0,s.jsx)(n.code,{children:"compose.yml"})," project file"]})," into the same directory."]}),"\n",(0,s.jsxs)(n.li,{children:["Copy your zrok account's enable token from the zrok web console to your clipboard and paste it in a file named ",(0,s.jsx)(n.code,{children:".env"})," in the same folder like this:"]}),"\n"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",metastring:'title=".env"',children:'ZROK_ENABLE_TOKEN="8UL9-48rN0ua"\n'})}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:["Run the Compose project to start sharing the built-in demo web server. Be sure to ",(0,s.jsx)(n.code,{children:"--detach"})," so the project runs in the background if you want it to auto-restart when your computer reboots."]}),"\n"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"docker compose up --detach\n"})}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:["Get the public share URL from the output of the ",(0,s.jsx)(n.code,{children:"zrok-share"})," service or by peeking in the zrok console where the share will appear in the graph."]}),"\n"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"docker compose logs zrok-share\n"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-buttonless",metastring:'title="Output"',children:"zrok-public-share-1 | https://w6r1vesearkj.in.zrok.io/\n"})}),"\n",(0,s.jsx)(n.p,{children:"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."}),"\n",(0,s.jsx)(n.h2,{id:"proxy-any-web-server",children:"Proxy Any Web Server"}),"\n",(0,s.jsxs)(n.p,{children:["The simplest way to share your existing HTTP server is to set ",(0,s.jsx)(n.code,{children:"ZROK_TARGET"})," (e.g. ",(0,s.jsx)(n.code,{children:"https://example.com"}),") in the environment of the ",(0,s.jsx)(n.code,{children:"docker compose up"})," command. When you restart the share will auto-configure for that URL."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",metastring:'title=".env"',children:'ZROK_TARGET="http://example.com:8080"\n'})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"docker compose down && docker compose up\n"})}),"\n",(0,s.jsx)(n.h2,{id:"require-authentication",children:"Require Authentication"}),"\n",(0,s.jsx)(n.p,{children:"You can require a password or an OAuth login with certain email addresses."}),"\n",(0,s.jsx)(n.h3,{id:"oauth-email",children:"OAuth Email"}),"\n",(0,s.jsxs)(n.p,{children:["You can allow specific email addresses or an email domain by setting ",(0,s.jsx)(n.code,{children:"ZROK_OAUTH_PROVIDER"})," to ",(0,s.jsx)(n.code,{children:"github"})," or ",(0,s.jsx)(n.code,{children:"google"})," and\n",(0,s.jsx)(n.code,{children:"ZROK_SHARE_OPTS"})," to specify additional command-line options to ",(0,s.jsx)(n.code,{children:"zrok reserve public"}),". Read more about the OAuth\nfeatures in ",(0,s.jsx)(n.a,{href:"https://blog.openziti.io/the-zrok-oauth-public-frontend",children:"this blog post"}),"."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",metastring:'title=".env"',children:'ZROK_OAUTH_PROVIDER="github"\nZROK_SHARE_OPTS="--oauth-email-domains @example.com"\n'})}),"\n",(0,s.jsx)(n.h2,{id:"caddy-is-powerful",children:"Caddy is Powerful"}),"\n",(0,s.jsxs)(n.p,{children:["The reserved public share project uses zrok's default backend mode, ",(0,s.jsx)(n.code,{children:"proxy"}),". Another backend mode, ",(0,s.jsx)(n.code,{children:"caddy"}),", accepts a path to ",(0,s.jsx)(n.a,{href:"https://caddyserver.com/docs/caddyfile",children:"a Caddyfile"})," as the value of ",(0,s.jsx)(n.code,{children:"ZROK_TARGET"})," (",(0,s.jsx)(n.a,{href:"https://github.com/openziti/zrok/tree/main/etc/caddy",children:"zrok Caddyfile examples"}),")."]}),"\n",(0,s.jsxs)(n.p,{children:["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 ",(0,s.jsx)(n.code,{children:"caddy"})," reduces the risk that you'll have to share a new frontend URL with your users."]}),"\n",(0,s.jsx)(n.p,{children:"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."}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsx)(n.li,{children:"Create a Caddyfile. This example demonstrates proxying two HTTP servers with a weighted round-robin load balancer."}),"\n"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-console",metastring:'title="Caddyfile"',children:"http:// {\n # zrok requires this bind address template\n bind {{ .ZrokBindAddress }}\n reverse_proxy /* {\n to http://httpbin1:8080 http://httpbin2:8080\n lb_policy weighted_round_robin 3 2\n }\n}\n"})}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:["Create a file ",(0,s.jsx)(n.code,{children:"compose.override.yml"}),". This example adds two ",(0,s.jsx)(n.code,{children:"httpbin"})," containers for load balancing, and mounts the Caddyfile into the container."]}),"\n"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",metastring:'title="compose.override.yml"',children:"services:\n httpbin1:\n image: mccutchen/go-httpbin # 8080/tcp\n httpbin2:\n image: mccutchen/go-httpbin # 8080/tcp\n zrok-share:\n volumes:\n - ./Caddyfile:/mnt/.zrok/Caddyfile\n"})}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsx)(n.li,{children:"Start a new Docker Compose project or delete the existing state volume."}),"\n"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"docker compose down --volumes\n"})}),"\n",(0,s.jsxs)(n.p,{children:["If you prefer to keep using the same zrok environment with the new share then delete ",(0,s.jsx)(n.code,{children:"/mnt/.zrok/reserved.json"})," instead of the entire volume."]}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsx)(n.li,{children:"Run the project to load the new configuration."}),"\n"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"docker compose up --detach\n"})}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsx)(n.li,{children:"Note the new reserved share URL from the log."}),"\n"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"docker compose logs zrok-share\n"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-buttonless",metastring:'title="Output"',children:"INFO: zrok public URL: https://88s803f2qvao.in.zrok.io/\n"})})]})}function x(e={}){const{wrapper:n}={...(0,i.a)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(m,{...e})}):m(e)}const j={title:"zrok frontdoor",sidebar_label:"frontdoor",sidebar_position:20},b=void 0,g={id:"guides/frontdoor",title:"zrok frontdoor",description:"zrok frontdoor provides a shielded entry point for your production website or service. This is useful if you want to expose it to the public internet, but not directly.",source:"@site/../docs/guides/frontdoor.mdx",sourceDirName:"guides",slug:"/guides/frontdoor",permalink:"/docs/guides/frontdoor",draft:!1,unlisted:!1,editUrl:"https://github.com/openziti/zrok/blob/main/docs/../docs/guides/frontdoor.mdx",tags:[],version:"current",sidebarPosition:20,frontMatter:{title:"zrok frontdoor",sidebar_label:"frontdoor",sidebar_position:20},sidebar:"tutorialSidebar",previous:{title:"Windows",permalink:"/docs/guides/install/windows"},next:{title:"Docker Share",permalink:"/docs/category/docker-share"}},k={},v=[{value:"Concepts",id:"concepts",level:2}];function f(e){const n={a:"a",code:"code",h2:"h2",p:"p",strong:"strong",...(0,i.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"zrok frontdoor"})," provides a shielded entry point for your production website or service. This is useful if you want to expose it to the public internet, but not directly."]}),"\n",(0,s.jsxs)(l,{queryString:"os",values:[{label:"Linux",value:"Linux"},{label:"macOS",value:"Mac OS"},{label:"Windows",value:"Windows"}],children:[(0,s.jsxs)(c.Z,{value:"Linux",children:[(0,s.jsxs)(n.p,{children:["On Linux, zrok frontdoor is implemented natively as a system service provided by the ",(0,s.jsx)(n.code,{children:"zrok-share"})," DEB or RPM package."]}),(0,s.jsxs)(n.p,{children:["If you'd prefer to run zrok in Docker, you can follow the same Docker instructions for ",(0,s.jsx)(n.a,{href:"./?os=Mac+OS",children:"macOS"})," or ",(0,s.jsx)(n.a,{href:"./?os=Windows",children:"Windows"}),"."]}),(0,s.jsx)(u,{})]}),(0,s.jsxs)(c.Z,{value:"Mac OS",children:[(0,s.jsx)(n.p,{children:"On macOS, zrok frontdoor is implemented as a Docker Compose project which reserves a public subdomain for your website or service."}),(0,s.jsx)(x,{})]}),(0,s.jsxs)(c.Z,{value:"Windows",children:[(0,s.jsx)(n.p,{children:"On Windows, zrok frontdoor is implemented as a Docker Compose project which reserves a public subdomain for your website or service."}),(0,s.jsx)(x,{})]})]}),"\n",(0,s.jsx)(n.h2,{id:"concepts",children:"Concepts"}),"\n",(0,s.jsxs)(n.p,{children:["Overview of ",(0,s.jsx)(n.a,{href:"/docs/concepts/sharing-reserved",children:"zrok reserved shares"})]})]})}function y(e={}){const{wrapper:n}={...(0,i.a)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(f,{...e})}):f(e)}},2753:(e,n,r)=>{r.d(n,{Z:()=>o});r(7294);var s=r(1272),i=r(9286),t=r(5893);const o=e=>{let{title:n,children:r}=e;const o=r.map((e=>"string"==typeof e?e.trim():s.ZP.dump(e).trim())).join("\n\n");return(0,t.jsx)("div",{children:(0,t.jsx)(i.Z,{language:"yaml",title:n,children:o})})}},1326:(e,n,r)=>{r.d(n,{Z:()=>s});const s=[{name:"Set up zrok Package Repo",gather_facts:!0,hosts:"all",become:!0,tasks:[{name:"Set up apt repo",when:'ansible_os_family == "Debian"',block:[{name:"Install playbook dependencies","ansible.builtin.package":{name:["gnupg"],state:"present"}},{name:"Fetch armored pubkey","ansible.builtin.uri":{url:"https://get.openziti.io/tun/package-repos.gpg",return_content:"yes"},register:"armored_pubkey"},{name:"Dearmor pubkey","ansible.builtin.shell":'gpg --dearmor --output /usr/share/keyrings/openziti.gpg <<< "{{ armored_pubkey.content }}"\n',args:{creates:"/usr/share/keyrings/openziti.gpg",executable:"/bin/bash"}},{name:"Set pubkey filemode","ansible.builtin.file":{path:"/usr/share/keyrings/openziti.gpg",mode:"a+rX"}},{name:"Install OpenZiti repo deb source","ansible.builtin.copy":{dest:"/etc/apt/sources.list.d/openziti-release.list",content:"deb [signed-by=/usr/share/keyrings/openziti.gpg] https://packages.openziti.org/zitipax-openziti-deb-stable debian main\n"}},{name:"Refresh Repo Sources","ansible.builtin.apt":{update_cache:"yes",cache_valid_time:3600}}]},{name:"Set up yum repo",when:'ansible_os_family == "RedHat"',block:[{name:"Install OpenZiti repo rpm source","ansible.builtin.yum_repository":{name:"OpenZitiRelease",description:"OpenZiti Release",baseurl:"https://packages.openziti.org/zitipax-openziti-rpm-stable/redhat/$basearch",enabled:"yes",gpgkey:"https://packages.openziti.org/zitipax-openziti-rpm-stable/redhat/$basearch/repodata/repomd.xml.key",repo_gpgcheck:"yes",gpgcheck:"no"}}]}]}]}}]); \ No newline at end of file +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[846],{9836:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>k,contentTitle:()=>b,default:()=>y,frontMatter:()=>j,metadata:()=>g,toc:()=>v});var s=r(5893),i=r(1151),t=r(7294),o=r(4866),a=r(5518);const l=function(e){const[n,r]=(0,t.useState)(null);return(0,t.useEffect)((()=>{["Mac OS","Windows","Linux"].includes(a.BF)?r(a.BF):r("Linux")}),[]),(0,s.jsx)(s.Fragment,{children:(0,s.jsx)(o.Z,{...e,defaultValue:n,children:e.children})})};var c=r(5162),d=r(1326),h=r(2753);function p(e){const n={a:"a",code:"code",h2:"h2",h3:"h3",li:"li",ol:"ol",p:"p",pre:"pre",ul:"ul",...(0,i.a)(),...e.components},{Details:r}=n;return r||function(e,n){throw new Error("Expected "+(n?"component":"object")+" `"+e+"` to be defined: you likely forgot to import, pass, or provide it.")}("Details",!0),(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h2,{id:"goal",children:"Goal"}),"\n",(0,s.jsx)(n.p,{children:"Proxy a reserved public subdomain to a backend target with an always-on Linux system service."}),"\n",(0,s.jsx)(n.h2,{id:"how-it-works",children:"How it Works"}),"\n",(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.code,{children:"zrok-share"})," package creates a ",(0,s.jsx)(n.code,{children:"zrok-share.service"})," unit in systemd. The administrator edits the service's configuration file to specify the:"]}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsx)(n.li,{children:"zrok environment enable token"}),"\n",(0,s.jsxs)(n.li,{children:["target URL or files to be shared and backend mode, e.g. ",(0,s.jsx)(n.code,{children:"proxy"})]}),"\n",(0,s.jsx)(n.li,{children:"authentication options, if wanted"}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"When the service starts it will:"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:["enable the zrok environment unless ",(0,s.jsx)(n.code,{children:"/var/lib/zrok-share/.zrok/environment.json"})," exists"]}),"\n",(0,s.jsxs)(n.li,{children:["reserve a public subdomain for the service unless ",(0,s.jsx)(n.code,{children:"/var/lib/zrok-share/.zrok/reserved.json"})," exists"]}),"\n",(0,s.jsxs)(n.li,{children:["start sharing the target specified as ",(0,s.jsx)(n.code,{children:"ZROK_TARGET"})," in the environment file"]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"installation",children:"Installation"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["Set up ",(0,s.jsx)(n.code,{children:"zrok"}),"'s Linux package repository by following ",(0,s.jsx)(n.a,{href:"/docs/guides/install/linux#install-zrok-from-the-repository",children:"the Linux install guide"}),", or run this one-liner to complete the repo setup and install packages."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"curl -sSLf https://get.openziti.io/install.bash \\\n| sudo bash -s zrok-share\n"})}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["If you set up the repository by following the guide, then also install the ",(0,s.jsx)(n.code,{children:"zrok-share"})," package. This package provides the systemd service."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",metastring:'title="Ubuntu, Debian"',children:"sudo sudo apt install zrok-share\n"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",metastring:'title="Fedora, Rocky"',children:"sudo dnf install zrok-share\n"})}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(r,{children:[(0,s.jsx)("summary",{children:"Ansible Playbook"}),(0,s.jsxs)(h.Z,{title:"Set up package repository and install zrok-share",children:[d.Z,"\n- name: Install zrok-share package\n gather_facts: false\n hosts: all \n become: true\n tasks:\n - name: Install zrok-share\n ansible.builtin.package:\n name: zrok-share\n state: present\n\n - name: Copy env config from Ansible controller to target\n copy:\n dest: /opt/openziti/etc/zrok/zrok-share.env\n src: /opt/openziti/etc/zrok/zrok-share.env\n\n - name: Enable and restart service\n systemd:\n name: zrok-share\n enabled: yes\n state: restarted\n daemon_reload: yes\n\n - name: Wait for service\n systemd:\n name: zrok-share\n state: started\n register: service_status\n until: service_status.status.ActiveState == 'active'\n retries: 30\n delay: 1\n"]})]}),"\n",(0,s.jsx)(n.h2,{id:"enable",children:"Enable"}),"\n",(0,s.jsx)(n.p,{children:"Save the enable token from the zrok console in the configuration file."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",metastring:'title="/opt/openziti/etc/zrok/zrok-share.env"',children:'ZROK_ENABLE_TOKEN="14cbfca9772f"\n'})}),"\n",(0,s.jsx)(n.h2,{id:"use-cases",children:"Use Cases"}),"\n",(0,s.jsxs)(n.p,{children:["You may change the target for the current backend mode, e.g. ",(0,s.jsx)(n.code,{children:"proxy"}),", by editing the configuration file and restarting the service. The reserved subdomain will remain the same."]}),"\n",(0,s.jsxs)(n.p,{children:["You may switch between backend modes or change authentication options by deleting ",(0,s.jsx)(n.code,{children:"/var/lib/zrok-share/.zrok/reserved.json"})," and restarting the service. A new subdomain will be reserved."]}),"\n",(0,s.jsx)(n.h3,{id:"proxy-a-web-server",children:"Proxy a Web Server"}),"\n",(0,s.jsx)(n.p,{children:"Proxy a reserved subdomain to an existing web server. The web server could be on a private network or on the same host as zrok."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",metastring:'title="/opt/openziti/etc/zrok/zrok-share.env"',children:'ZROK_TARGET="http://127.0.0.1:3000"\nZROK_BACKEND_MODE="proxy"\n'})}),"\n",(0,s.jsxs)(n.p,{children:["If your HTTPS server has an unverifiable TLS server certificate then you must set ",(0,s.jsx)(n.code,{children:"--insecure"}),"."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",metastring:'title="/opt/openziti/etc/zrok/zrok-share.env"',children:'ZROK_INSECURE="--insecure"\n'})}),"\n",(0,s.jsx)(n.h3,{id:"serve-static-files",children:"Serve Static Files"}),"\n",(0,s.jsxs)(n.p,{children:["Run zrok's embedded web server to serve the files in a directory. If there's an ",(0,s.jsx)(n.code,{children:"index.html"})," file in the directory then visitors will see that web page in their browser, otherwise they'll see a generated index of the files. The directory must be readable by 'other', e.g. ",(0,s.jsx)(n.code,{children:"chmod -R o+rX /var/www/html"}),"."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",metastring:'title="/opt/openziti/etc/zrok/zrok-share.env"',children:'ZROK_TARGET="/var/www/html"\nZROK_BACKEND_MODE="web"\n'})}),"\n",(0,s.jsx)(n.h3,{id:"caddy-server",children:"Caddy Server"}),"\n",(0,s.jsx)(n.p,{children:"Use zrok's built-in Caddy server to serve static files or as a reverse proxy to multiple web servers with various HTTP routes or as a load-balanced set. A sample Caddyfile is available in the path shown."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",metastring:'title="/opt/openziti/etc/zrok/zrok-share.env"',children:'ZROK_TARGET="/opt/openziti/etc/zrok/multiple_upstream.Caddyfile"\nZROK_BACKEND_MODE="caddy"\n'})}),"\n",(0,s.jsx)(n.h3,{id:"network-drive",children:"Network Drive"}),"\n",(0,s.jsxs)(n.p,{children:["This uses zrok's ",(0,s.jsx)(n.code,{children:"drive"})," backend mode to serve a directory of static files as a virtual network drive. The directory must be readable by 'other', e.g. ",(0,s.jsx)(n.code,{children:"chmod -R o+rX /usr/share/doc"}),"."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",metastring:'title="/opt/openziti/etc/zrok/zrok-share.env"',children:'ZROK_TARGET="/usr/share/doc"\nZROK_BACKEND_MODE="drive"\n'})}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.a,{href:"https://blog.openziti.io/zrok-drives-an-early-preview",children:"Learn more about this feature in this blog post"}),"."]}),"\n",(0,s.jsx)(n.h2,{id:"authentication",children:"Authentication"}),"\n",(0,s.jsx)(n.p,{children:"You can limit access to certain email addresses with OAuth or require a password."}),"\n",(0,s.jsx)(n.h3,{id:"oauth",children:"OAuth"}),"\n",(0,s.jsx)(n.p,{children:"You can require that visitors authenticate with an email address that matches at least one of the suffixes you specify. Add the following to the configuration file."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",metastring:'title="/opt/openziti/etc/zrok/zrok-share.env"',children:'ZROK_OAUTH_PROVIDER="github" # or google\nZROK_OAUTH_EMAILS="bob@example.com @acme.example.com"\n'})}),"\n",(0,s.jsx)(n.h3,{id:"password",children:"Password"}),"\n",(0,s.jsx)(n.p,{children:"Enable HTTP basic authentication by adding the following to the configuration file."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",metastring:'title="/opt/openziti/etc/zrok/zrok-share.env"',children:'ZROK_BASIC_AUTH="user:passwd"\n'})}),"\n",(0,s.jsx)(n.h2,{id:"start-the-service",children:"Start the Service"}),"\n",(0,s.jsx)(n.p,{children:"Start the service, and check the zrok console or the service log for the reserved subdomain."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",metastring:'title="run now and at startup"',children:"sudo systemctl enable --now zrok-share.service\n"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",metastring:'title="run now"',children:"sudo systemctl restart zrok-share.service\n"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"journalctl -u zrok-share.service\n"})}),"\n",(0,s.jsx)(n.h2,{id:"compatibility",children:"Compatibility"}),"\n",(0,s.jsxs)(n.p,{children:["The Linux distribution must have a package manager that understands the ",(0,s.jsx)(n.code,{children:".deb"})," or ",(0,s.jsx)(n.code,{children:".rpm"})," format and be running systemd v232 or newer. The service was tested with:"]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"Ubuntu 20.04, 22.04, 23.04"}),"\n",(0,s.jsx)(n.li,{children:"Debian 11 12"}),"\n",(0,s.jsx)(n.li,{children:"Rocky 8, 9"}),"\n",(0,s.jsx)(n.li,{children:"Fedora 37, 38"}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"package-contents",children:"Package Contents"}),"\n",(0,s.jsxs)(n.p,{children:["The files included in the ",(0,s.jsx)(n.code,{children:"zrok-share"})," package are sourced ",(0,s.jsx)(n.a,{href:"https://github.com/openziti/zrok/tree/main/nfpm",children:"here in GitHub"}),"."]})]})}function u(e={}){const{wrapper:n}={...(0,i.a)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(p,{...e})}):p(e)}function m(e){const n={a:"a",code:"code",h2:"h2",h3:"h3",li:"li",ol:"ol",p:"p",pre:"pre",...(0,i.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h2,{id:"goal",children:"Goal"}),"\n",(0,s.jsx)(n.p,{children:"Proxy a reserved public subdomain to a backend target with an always-on Docker Compose service."}),"\n",(0,s.jsx)(n.h2,{id:"how-it-works",children:"How it Works"}),"\n",(0,s.jsx)(n.p,{children:"The Docker Compose project uses your zrok account token to reserve a public subdomain and keep sharing the backend\ntarget."}),"\n",(0,s.jsx)(n.p,{children:"When the project runs it will:"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:["enable a zrok environment unless ",(0,s.jsx)(n.code,{children:"/mnt/.zrok/environment.json"})," exists in the ",(0,s.jsx)(n.code,{children:"zrok_env"})," volume"]}),"\n",(0,s.jsxs)(n.li,{children:["reserve a public subdomain for the service unless ",(0,s.jsx)(n.code,{children:"/mnt/.zrok/reserved.json"})," exists"]}),"\n",(0,s.jsxs)(n.li,{children:["start sharing the target specified in the ",(0,s.jsx)(n.code,{children:"ZROK_TARGET"})," environment variable"]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"create-the-docker-project",children:"Create the Docker Project"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsx)(n.li,{children:"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."}),"\n",(0,s.jsxs)(n.li,{children:["Download ",(0,s.jsxs)(n.a,{href:"pathname:///zrok-public-reserved/compose.yml",children:["the reserved public share ",(0,s.jsx)(n.code,{children:"compose.yml"})," project file"]})," into the same directory."]}),"\n",(0,s.jsxs)(n.li,{children:["Copy your zrok account's enable token from the zrok web console to your clipboard and paste it in a file named ",(0,s.jsx)(n.code,{children:".env"})," in the same folder like this:"]}),"\n"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",metastring:'title=".env"',children:'ZROK_ENABLE_TOKEN="8UL9-48rN0ua"\n'})}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:["Run the Compose project to start sharing the built-in demo web server. Be sure to ",(0,s.jsx)(n.code,{children:"--detach"})," so the project runs in the background if you want it to auto-restart when your computer reboots."]}),"\n"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"docker compose up --detach\n"})}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:["Get the public share URL from the output of the ",(0,s.jsx)(n.code,{children:"zrok-share"})," service or by peeking in the zrok console where the share will appear in the graph."]}),"\n"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"docker compose logs zrok-share\n"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-buttonless",metastring:'title="Output"',children:"zrok-public-share-1 | https://w6r1vesearkj.in.zrok.io/\n"})}),"\n",(0,s.jsx)(n.p,{children:"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."}),"\n",(0,s.jsx)(n.h2,{id:"proxy-any-web-server",children:"Proxy Any Web Server"}),"\n",(0,s.jsxs)(n.p,{children:["The simplest way to share your existing HTTP server is to set ",(0,s.jsx)(n.code,{children:"ZROK_TARGET"})," (e.g. ",(0,s.jsx)(n.code,{children:"https://example.com"}),") in the environment of the ",(0,s.jsx)(n.code,{children:"docker compose up"})," command. When you restart the share will auto-configure for that URL."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",metastring:'title=".env"',children:'ZROK_TARGET="http://example.com:8080"\n'})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"docker compose down && docker compose up\n"})}),"\n",(0,s.jsx)(n.h2,{id:"require-authentication",children:"Require Authentication"}),"\n",(0,s.jsx)(n.p,{children:"You can require a password or an OAuth login with certain email addresses."}),"\n",(0,s.jsx)(n.h3,{id:"oauth-email",children:"OAuth Email"}),"\n",(0,s.jsxs)(n.p,{children:["You can allow specific email addresses or an email domain by setting ",(0,s.jsx)(n.code,{children:"ZROK_OAUTH_PROVIDER"})," to ",(0,s.jsx)(n.code,{children:"github"})," or ",(0,s.jsx)(n.code,{children:"google"})," and\n",(0,s.jsx)(n.code,{children:"ZROK_SHARE_OPTS"})," to specify additional command-line options to ",(0,s.jsx)(n.code,{children:"zrok reserve public"}),". Read more about the OAuth\nfeatures in ",(0,s.jsx)(n.a,{href:"https://blog.openziti.io/the-zrok-oauth-public-frontend",children:"this blog post"}),"."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",metastring:'title=".env"',children:'ZROK_OAUTH_PROVIDER="github"\nZROK_SHARE_OPTS="--oauth-email-domains @example.com"\n'})}),"\n",(0,s.jsx)(n.h2,{id:"caddy-is-powerful",children:"Caddy is Powerful"}),"\n",(0,s.jsxs)(n.p,{children:["The reserved public share project uses zrok's default backend mode, ",(0,s.jsx)(n.code,{children:"proxy"}),". Another backend mode, ",(0,s.jsx)(n.code,{children:"caddy"}),", accepts a path to ",(0,s.jsx)(n.a,{href:"https://caddyserver.com/docs/caddyfile",children:"a Caddyfile"})," as the value of ",(0,s.jsx)(n.code,{children:"ZROK_TARGET"})," (",(0,s.jsx)(n.a,{href:"https://github.com/openziti/zrok/tree/main/etc/caddy",children:"zrok Caddyfile examples"}),")."]}),"\n",(0,s.jsxs)(n.p,{children:["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 ",(0,s.jsx)(n.code,{children:"caddy"})," reduces the risk that you'll have to share a new frontend URL with your users."]}),"\n",(0,s.jsx)(n.p,{children:"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."}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsx)(n.li,{children:"Create a Caddyfile. This example demonstrates proxying two HTTP servers with a weighted round-robin load balancer."}),"\n"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-console",metastring:'title="Caddyfile"',children:"http:// {\n # zrok requires this bind address template\n bind {{ .ZrokBindAddress }}\n reverse_proxy /* {\n to http://httpbin1:8080 http://httpbin2:8080\n lb_policy weighted_round_robin 3 2\n }\n}\n"})}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:["Create a file ",(0,s.jsx)(n.code,{children:"compose.override.yml"}),". This example adds two ",(0,s.jsx)(n.code,{children:"httpbin"})," containers for load balancing, and mounts the Caddyfile into the container."]}),"\n"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",metastring:'title="compose.override.yml"',children:"services:\n httpbin1:\n image: mccutchen/go-httpbin # 8080/tcp\n httpbin2:\n image: mccutchen/go-httpbin # 8080/tcp\n zrok-share:\n volumes:\n - ./Caddyfile:/mnt/.zrok/Caddyfile\n"})}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsx)(n.li,{children:"Start a new Docker Compose project or delete the existing state volume."}),"\n"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"docker compose down --volumes\n"})}),"\n",(0,s.jsxs)(n.p,{children:["If you prefer to keep using the same zrok environment with the new share then delete ",(0,s.jsx)(n.code,{children:"/mnt/.zrok/reserved.json"})," instead of the entire volume."]}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsx)(n.li,{children:"Run the project to load the new configuration."}),"\n"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"docker compose up --detach\n"})}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsx)(n.li,{children:"Note the new reserved share URL from the log."}),"\n"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"docker compose logs zrok-share\n"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-buttonless",metastring:'title="Output"',children:"INFO: zrok public URL: https://88s803f2qvao.in.zrok.io/\n"})})]})}function x(e={}){const{wrapper:n}={...(0,i.a)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(m,{...e})}):m(e)}const j={title:"zrok frontdoor",sidebar_label:"frontdoor",sidebar_position:20},b=void 0,g={id:"guides/frontdoor",title:"zrok frontdoor",description:"zrok frontdoor provides a shielded entry point for your production website or service. This is useful if you want to expose it to the public internet, but not directly.",source:"@site/../docs/guides/frontdoor.mdx",sourceDirName:"guides",slug:"/guides/frontdoor",permalink:"/docs/guides/frontdoor",draft:!1,unlisted:!1,editUrl:"https://github.com/openziti/zrok/blob/main/docs/../docs/guides/frontdoor.mdx",tags:[],version:"current",sidebarPosition:20,frontMatter:{title:"zrok frontdoor",sidebar_label:"frontdoor",sidebar_position:20},sidebar:"tutorialSidebar",previous:{title:"Windows",permalink:"/docs/guides/install/windows"},next:{title:"Docker Share",permalink:"/docs/category/docker-share"}},k={},v=[{value:"Concepts",id:"concepts",level:2}];function f(e){const n={a:"a",code:"code",h2:"h2",p:"p",strong:"strong",...(0,i.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"zrok frontdoor"})," provides a shielded entry point for your production website or service. This is useful if you want to expose it to the public internet, but not directly."]}),"\n",(0,s.jsxs)(l,{queryString:"os",values:[{label:"Linux",value:"Linux"},{label:"macOS",value:"Mac OS"},{label:"Windows",value:"Windows"}],children:[(0,s.jsxs)(c.Z,{value:"Linux",children:[(0,s.jsxs)(n.p,{children:["On Linux, zrok frontdoor is implemented natively as a system service provided by the ",(0,s.jsx)(n.code,{children:"zrok-share"})," DEB or RPM package."]}),(0,s.jsxs)(n.p,{children:["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, ",(0,s.jsx)(n.a,{href:"./?os=Mac+OS",children:"macOS"}),", and ",(0,s.jsx)(n.a,{href:"./?os=Windows",children:"Windows"}),"."]}),(0,s.jsx)(u,{})]}),(0,s.jsxs)(c.Z,{value:"Mac OS",children:[(0,s.jsx)(n.p,{children:"On macOS, zrok frontdoor is implemented as a Docker Compose project which reserves a public subdomain for your website or service."}),(0,s.jsx)(x,{})]}),(0,s.jsxs)(c.Z,{value:"Windows",children:[(0,s.jsx)(n.p,{children:"On Windows, zrok frontdoor is implemented as a Docker Compose project which reserves a public subdomain for your website or service."}),(0,s.jsx)(x,{})]})]}),"\n",(0,s.jsx)(n.h2,{id:"concepts",children:"Concepts"}),"\n",(0,s.jsxs)(n.p,{children:["Overview of ",(0,s.jsx)(n.a,{href:"/docs/concepts/sharing-reserved",children:"zrok reserved shares"})]})]})}function y(e={}){const{wrapper:n}={...(0,i.a)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(f,{...e})}):f(e)}},2753:(e,n,r)=>{r.d(n,{Z:()=>o});r(7294);var s=r(1272),i=r(9286),t=r(5893);const o=e=>{let{title:n,children:r}=e;const o=r.map((e=>"string"==typeof e?e.trim():s.ZP.dump(e).trim())).join("\n\n");return(0,t.jsx)("div",{children:(0,t.jsx)(i.Z,{language:"yaml",title:n,children:o})})}},1326:(e,n,r)=>{r.d(n,{Z:()=>s});const s=[{name:"Set up zrok Package Repo",gather_facts:!0,hosts:"all",become:!0,tasks:[{name:"Set up apt repo",when:'ansible_os_family == "Debian"',block:[{name:"Install playbook dependencies","ansible.builtin.package":{name:["gnupg"],state:"present"}},{name:"Fetch armored pubkey","ansible.builtin.uri":{url:"https://get.openziti.io/tun/package-repos.gpg",return_content:"yes"},register:"armored_pubkey"},{name:"Dearmor pubkey","ansible.builtin.shell":'gpg --dearmor --output /usr/share/keyrings/openziti.gpg <<< "{{ armored_pubkey.content }}"\n',args:{creates:"/usr/share/keyrings/openziti.gpg",executable:"/bin/bash"}},{name:"Set pubkey filemode","ansible.builtin.file":{path:"/usr/share/keyrings/openziti.gpg",mode:"a+rX"}},{name:"Install OpenZiti repo deb source","ansible.builtin.copy":{dest:"/etc/apt/sources.list.d/openziti-release.list",content:"deb [signed-by=/usr/share/keyrings/openziti.gpg] https://packages.openziti.org/zitipax-openziti-deb-stable debian main\n"}},{name:"Refresh Repo Sources","ansible.builtin.apt":{update_cache:"yes",cache_valid_time:3600}}]},{name:"Set up yum repo",when:'ansible_os_family == "RedHat"',block:[{name:"Install OpenZiti repo rpm source","ansible.builtin.yum_repository":{name:"OpenZitiRelease",description:"OpenZiti Release",baseurl:"https://packages.openziti.org/zitipax-openziti-rpm-stable/redhat/$basearch",enabled:"yes",gpgkey:"https://packages.openziti.org/zitipax-openziti-rpm-stable/redhat/$basearch/repodata/repomd.xml.key",repo_gpgcheck:"yes",gpgcheck:"no"}}]}]}]}}]); \ No newline at end of file diff --git a/assets/js/f888b719.d6459e38.js b/assets/js/f888b719.d6459e38.js deleted file mode 100644 index e789464f..00000000 --- a/assets/js/f888b719.d6459e38.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[938],{2800:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>h,contentTitle:()=>d,default:()=>x,frontMatter:()=>c,metadata:()=>l,toc:()=>m});var r=s(5893),i=s(1151),o=s(4908),t=s(3298),a=s(7597);const c={title:"Getting Started with zrok",sidebar_label:"Getting Started",sidebar_position:10},d=void 0,l={id:"getting-started",title:"Getting Started with zrok",description:"What's a zrok?",source:"@site/../docs/getting-started.mdx",sourceDirName:".",slug:"/getting-started",permalink:"/docs/getting-started",draft:!1,unlisted:!1,editUrl:"https://github.com/openziti/zrok/blob/main/docs/../docs/getting-started.mdx",tags:[],version:"current",sidebarPosition:10,frontMatter:{title:"Getting Started with zrok",sidebar_label:"Getting Started",sidebar_position:10},sidebar:"tutorialSidebar",next:{title:"Concepts",permalink:"/docs/concepts/"}},h={},m=[{value:"What's a zrok?",id:"whats-a-zrok",level:2},{value:"Open Source",id:"open-source",level:2},{value:"Ziti native",id:"ziti-native",level:3},{value:"What's it for?",id:"whats-it-for",level:2},{value:"Installing the zrok Command",id:"installing-the-zrok-command",level:2},{value:"Generating an Invitation",id:"generating-an-invitation",level:2},{value:"Enabling Your zrok Environment",id:"enabling-your-zrok-environment",level:2},{value:"Sharing",id:"sharing",level:2},{value:"Ephemeral by Default",id:"ephemeral-by-default",level:3},{value:"Public Shares and Frontends",id:"public-shares-and-frontends",level:3},{value:"Private Shares",id:"private-shares",level:3},{value:"Proxy Backend Mode",id:"proxy-backend-mode",level:3},{value:"Web Backend Mode",id:"web-backend-mode",level:3},{value:"Reserved Shares",id:"reserved-shares",level:3},{value:"Concepts Review",id:"concepts-review",level:2},{value:"Instance and Account",id:"instance-and-account",level:3},{value:"Environment",id:"environment",level:3},{value:"Shares",id:"shares",level:3},{value:"Reserved Shares",id:"reserved-shares-1",level:3},{value:"Self-Hosting an Instance",id:"self-hosting-an-instance",level:2}];function u(e){const n={a:"a",admonition:"admonition",code:"code",em:"em",h2:"h2",h3:"h3",img:"img",p:"p",pre:"pre",...(0,i.a)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h2,{id:"whats-a-zrok",children:"What's a zrok?"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"zrok"})," ",(0,r.jsx)(n.em,{children:'/zi\u02d0\u0279\u0252k/ ("zee-rock")'})," is a secure, open-source, self-hostable sharing platform that simplifies shielding and sharing network services or files. There's a hardened zrok-as-a-service offering available at ",(0,r.jsx)(n.a,{href:"https://zrok.io",children:"zrok.io"})," with a generous free tier."]}),"\n",(0,r.jsx)(n.h2,{id:"open-source",children:"Open Source"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"zrok"})," is licensed under Apache 2.0."]}),"\n",(0,r.jsxs)(n.p,{children:["Check ",(0,r.jsx)(n.a,{href:"https://github.com/orgs/openziti/projects/16",children:"the roadmap"})," if you're thinking about the future. We would love to hear your ideas for ",(0,r.jsx)(n.code,{children:"zrok"}),"!"]}),"\n",(0,r.jsxs)(n.p,{children:["The best ways to engage are ",(0,r.jsx)(n.a,{href:"https://openziti.discourse.group/",children:"Discourse"})," for questions and ",(0,r.jsx)(n.a,{href:"https://github.com/openziti/zrok/issues",children:"GitHub Issues"})," for documenting problems."]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.a,{href:"/docs/concepts/opensource",children:"Read more about zrok open source"}),"."]}),"\n",(0,r.jsx)(n.h3,{id:"ziti-native",children:"Ziti native"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"zrok"})," is a ",(0,r.jsx)(n.em,{children:"Ziti Native Application"}),", built on the ",(0,r.jsx)(n.a,{href:"https://openziti.io",children:"OpenZiti"})," platform, and supported by the OpenZiti community and NetFoundry team."]}),"\n",(0,r.jsx)(n.h2,{id:"whats-it-for",children:"What's it for?"}),"\n",(0,r.jsxs)(n.p,{children:["Use ",(0,r.jsx)(n.code,{children:"zrok"})," to share a running service, like a web server or a network socket, or to share a directory of static files."]}),"\n",(0,r.jsxs)(n.p,{children:["If ",(0,r.jsx)(n.a,{href:"/docs/concepts/sharing-public",children:"sharing publicly"}),", you can reserve a subdomain, enable authentication options, or both. Public shares proxy HTTPS to your service or files."]}),"\n",(0,r.jsxs)(n.p,{children:["If ",(0,r.jsx)(n.a,{href:"/docs/concepts/sharing-private",children:"sharing privately"}),", only users with the share token can access your share. In addition to what you can share publicly, private shares can include TCP and UDP services."]}),"\n",(0,r.jsx)(n.h2,{id:"installing-the-zrok-command",children:"Installing the zrok Command"}),"\n",(0,r.jsx)(o.N,{children:(0,r.jsxs)("div",{className:a.Z.downloadContainer,children:[(0,r.jsx)(t.Z,{osName:"Windows",osLogo:"/img/logo-windows.svg",infoText:"Binary executable",guideLink:"/docs/guides/install/windows"}),(0,r.jsx)(t.Z,{osName:"macOS",osLogo:"/img/logo-apple.svg",infoText:"Binary executable",guideLink:"/docs/guides/install/macos"}),(0,r.jsx)(t.Z,{osName:"Linux",osLogo:"/img/logo-linux.svg",infoText:"DEB, RPM packages",guideLink:"/docs/guides/install/linux"})]})}),"\n",(0,r.jsx)(n.h2,{id:"generating-an-invitation",children:"Generating an Invitation"}),"\n",(0,r.jsx)(n.admonition,{type:"note",children:(0,r.jsxs)(n.p,{children:["If not using ",(0,r.jsx)(n.code,{children:"zrok.io"})," (zrok-as-a-service), you must configure the ",(0,r.jsx)(n.code,{children:"zrok"})," command to use your instance. See the ",(0,r.jsx)(n.a,{href:"/docs/guides/self-hosting/instance-configuration",children:"instance configuration guide"})," in the self-hosting section for details."]})}),"\n",(0,r.jsxs)(n.p,{children:["Invite yourself to ",(0,r.jsx)(n.code,{children:"zrok"})," by running the ",(0,r.jsx)(n.code,{children:"zrok invite"})," command:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-text",children:"zrok invite\n"})}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-buttonless",metastring:'title="Output"',children:"enter and confirm your email address...\n\n> user@domain.com\n> user@domain.com\n\n[ Submit ]\n\ninvitation sent to 'user@domain.com'!\n"})}),"\n",(0,r.jsxs)(n.p,{children:["The ",(0,r.jsx)(n.code,{children:"zrok invite"})," command presents a small form that allows you to enter (and then confirm) your email address. Tabbing to the ",(0,r.jsx)(n.code,{children:"[ Submit ]"})," button will send the request to your configured ",(0,r.jsx)(n.code,{children:"zrok"})," service."]}),"\n",(0,r.jsxs)(n.p,{children:["Next, check the email where you sent the invite. You should receive a message asking you to click a link to create your ",(0,r.jsx)(n.code,{children:"zrok"})," account. When you click that link, you will be brought to a web page that will allow you to set a password for your new account:"]}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"Enter a Password",src:s(9744).Z+"",width:"1791",height:"1362"})}),"\n",(0,r.jsxs)(n.p,{children:["Enter a password and its confirmation, and click the ",(0,r.jsx)(n.code,{children:"Register Account"})," button. You'll see the following:"]}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"Successful Registration",src:s(242).Z+"",width:"1791",height:"1369"})}),"\n",(0,r.jsxs)(n.p,{children:['For now, we\'ll ignore the "enable your shell for zrok" section. Just click the ',(0,r.jsx)(n.code,{children:"zrok web portal"})," link:"]}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"Web Login",src:s(9509).Z+"",width:"1791",height:"1362"})}),"\n",(0,r.jsxs)(n.p,{children:["After clicking the ",(0,r.jsx)(n.code,{children:"Log In"})," button, you'll be brought into the ",(0,r.jsx)(n.code,{children:"zrok"})," ",(0,r.jsx)(n.em,{children:"web console"}),":"]}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"Web Console; Empty",src:s(2945).Z+"",width:"1791",height:"1362"})}),"\n",(0,r.jsxs)(n.p,{children:["Congratulations! Your ",(0,r.jsx)(n.code,{children:"zrok"})," account is ready to go!"]}),"\n",(0,r.jsx)(n.h2,{id:"enabling-your-zrok-environment",children:"Enabling Your zrok Environment"}),"\n",(0,r.jsxs)(n.p,{children:["When your ",(0,r.jsx)(n.code,{children:"zrok"})," account was created, the service generated a ",(0,r.jsx)(n.em,{children:"secret token"})," that identifies and authenticates in a single step. Protect your secret token as if it were a password, or an important account number; it's a ",(0,r.jsx)(n.em,{children:"secret"}),", protect it."]}),"\n",(0,r.jsxs)(n.p,{children:["When we left off you had downloaded, extracted, and configured your ",(0,r.jsx)(n.code,{children:"zrok"})," environment. In order to use that environment with your account, you'll need to ",(0,r.jsx)(n.code,{children:"enable"})," it. Enabling an environment generates a secure identity and the necessary underlying security policies with the OpenZiti network hosting the ",(0,r.jsx)(n.code,{children:"zrok"})," service."]}),"\n",(0,r.jsxs)(n.p,{children:["From the web console, click on your email address in the upper right corner of the header. That drop down menu contains an ",(0,r.jsx)(n.code,{children:"Enable Your Environment"})," link. Click that link and a modal dialog will be shown like this:"]}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"Enable Modal Dialog",src:s(9042).Z+"",width:"1791",height:"1369"})}),"\n",(0,r.jsxs)(n.p,{children:["This dialog box shows you the ",(0,r.jsx)(n.code,{children:"zrok enable"})," command that you can use to enable any shell to work with your ",(0,r.jsx)(n.code,{children:"zrok"})," account with a single command."]}),"\n",(0,r.jsx)(n.p,{children:"Let's copy that command and paste it into your shell:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-buttonless",metastring:'title="Example"',children:"$ zrok enable klFEoIi0QAg7 \n\u28fb contacting the zrok service...\n"})}),"\n",(0,r.jsx)(n.p,{children:"After a few seconds, the message will change and indicate that the enable operation succeeded:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-buttonless",metastring:'title="Example"',children:"$ zrok enable klFEoIi0QAg7 \n\u28fb the zrok environment was successfully enabled...\n"})}),"\n",(0,r.jsxs)(n.p,{children:["Now, if we run a ",(0,r.jsx)(n.code,{children:"zrok status"})," command, you will see the details of your environment:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-txt",children:"zrok status\n"})}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-buttonless",metastring:'title="Output"',children:"Config:\n\n CONFIG VALUE SOURCE\n apiEndpoint https://api.staging.zrok.io env\n\nEnvironment:\n\n PROPERTY VALUE\n Secret Token <>\n Ziti Identity <>\n"})}),"\n",(0,r.jsx)(n.p,{children:"Excellent... our environment is now fully enabled."}),"\n",(0,r.jsxs)(n.p,{children:["If we return to the ",(0,r.jsx)(n.em,{children:"web console"}),", we'll now see the new environment reflected in the explorer view:"]}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"New Environment in Web UI",src:s(5546).Z+"",width:"1791",height:"1369"})}),"\n",(0,r.jsxs)(n.p,{children:["In my case, the environment is named ",(0,r.jsx)(n.code,{children:"michael@ziti-lx"}),", which is the username of my shell and the hostname of the system the shell is running on."]}),"\n",(0,r.jsx)(n.admonition,{type:"note",children:(0,r.jsxs)(n.p,{children:["Should you want to use a non-default name for your environment, you can pass the ",(0,r.jsx)(n.code,{children:"-d"})," option to the ",(0,r.jsx)(n.code,{children:"zrok enable"})," command. See ",(0,r.jsx)(n.code,{children:"zrok enable --help"})," for details."]})}),"\n",(0,r.jsxs)(n.p,{children:["If you click on the environment node in the explorer in the ",(0,r.jsx)(n.em,{children:"web console"}),", the details panel shown at the bottom of the page will change:"]}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"Empty Environment",src:s(3858).Z+"",width:"1791",height:"1369"})}),"\n",(0,r.jsxs)(n.p,{children:["The explorer supports clicking, dragging, mouse wheel zooming, and selecting the nodes in the graph for more information (and available actions) for the selected node. If you ever get lost in the explorer, click the ",(0,r.jsx)(n.img,{alt:"Zoom to Fit",src:s(3843).Z+"",width:"30",height:"25"})," ",(0,r.jsx)(n.em,{children:"zoom to fit"})," icon in the lower right corner of the explorer."]}),"\n",(0,r.jsxs)(n.p,{children:["If we click on the ",(0,r.jsx)(n.code,{children:"Detail"})," tab for our environment, we'll see something like:"]}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"Environment Detail",src:s(2534).Z+"",width:"1791",height:"1369"})}),"\n",(0,r.jsx)(n.admonition,{type:"note",children:(0,r.jsxs)(n.p,{children:["With your ",(0,r.jsx)(n.code,{children:"zrok"})," account you can ",(0,r.jsx)(n.code,{children:"zrok enable"})," multiple environments. This will allow you to run ",(0,r.jsx)(n.code,{children:"zrok share"})," in one environment, and ",(0,r.jsx)(n.code,{children:"zrok access"})," in other environments."]})}),"\n",(0,r.jsx)(n.p,{children:"Your environment is fully ready to go. Now we can move on to the fun stuff..."}),"\n",(0,r.jsx)(n.h2,{id:"sharing",children:"Sharing"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"zrok"})," is designed to make sharing resources as effortless as possible, while providing a high degree of security and control."]}),"\n",(0,r.jsx)(n.h3,{id:"ephemeral-by-default",children:"Ephemeral by Default"}),"\n",(0,r.jsxs)(n.p,{children:["Shared resources are ",(0,r.jsx)(n.em,{children:"ephemeral"})," by default; as soon as you terminate the ",(0,r.jsx)(n.code,{children:"zrok share"})," command, the entire share is removed and is no longer available to any users. Identifiers for shared resources are randomly allocated when the share is created."]}),"\n",(0,r.jsx)(n.h3,{id:"public-shares-and-frontends",children:"Public Shares and Frontends"}),"\n",(0,r.jsxs)(n.p,{children:["Resources that are shared ",(0,r.jsx)(n.em,{children:"publicly"})," are exposed to any users on the internet who have access to the ",(0,r.jsx)(n.code,{children:"zrok"}),' instance\'s "frontend".']}),"\n",(0,r.jsx)(n.p,{children:"A frontend is an HTTPS listener exposed to the internet, that lets any user with your ephemeral share token access your publicly shared resources."}),"\n",(0,r.jsxs)(n.p,{children:["For example, I might create a public share using the ",(0,r.jsx)(n.code,{children:"zrok share public"})," command, which results in my ",(0,r.jsx)(n.code,{children:"zrok"})," instance exposing a URL like ",(0,r.jsx)(n.code,{children:"https://2ptgbr8tlfvk.share.zrok.io"})," to access my resources."]}),"\n",(0,r.jsxs)(n.p,{children:['In this case, my share was given the "share token" of ',(0,r.jsx)(n.code,{children:"2ptgbr8tlfvk"}),". That URL can be given to any user, allowing them to immediately access the shared resources directly from my local environment, all without exposing any access to my private, secure environment. The physical network location of my environment is not exposed to anonymous consumers of my resources."]}),"\n",(0,r.jsxs)(n.admonition,{type:"note",children:[(0,r.jsxs)(n.p,{children:["Here is the ",(0,r.jsx)(n.code,{children:"--help"})," output from ",(0,r.jsx)(n.code,{children:"zrok share public"}),":"]}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-text",children:"zrok share public\n"})}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-buttonless",metastring:'title="Output"',children:'Error: accepts 1 arg(s), received 0\nUsage:\n zrok share public [flags]\n\nFlags:\n --backend-mode string The backend mode {proxy, web, caddy, drive} (default "proxy")\n --basic-auth stringArray Basic authentication users (,...)\n --frontends stringArray Selected frontends to use for the share (default [public])\n --headless Disable TUI and run headless\n -h, --help help for public\n --insecure Enable insecure TLS certificate validation for \n\nGlobal Flags:\n -p, --panic Panic instead of showing pretty errors\n -v, --verbose Enable verbose logging\n\n[ERROR]: an error occurred (accepts 1 arg(s), received 0)\n'})}),(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:""})," defines the path to the local resource that you intend to share. The form of ",(0,r.jsx)(n.code,{children:""})," depends on the ",(0,r.jsx)(n.code,{children:"--backend-mode"})," that you're using."]}),(0,r.jsxs)(n.p,{children:["In the case of ",(0,r.jsx)(n.code,{children:"--backend-mode proxy"}),", ",(0,r.jsx)(n.code,{children:""})," should be a URL to an HTTP endpoint."]}),(0,r.jsxs)(n.p,{children:["In the case of ",(0,r.jsx)(n.code,{children:"--backend-mode web"}),", ",(0,r.jsx)(n.code,{children:""}),' is the path to a file on disk that serves as the "root" of the file tree to be shared.']})]}),"\n",(0,r.jsx)(n.p,{children:"If we return to the web console, we see our share in the explorer:"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"Web Console Share",src:s(6097).Z+"",width:"1791",height:"1369"})}),"\n",(0,r.jsxs)(n.p,{children:["If we click on our new share in the explorer, we can see the share details:\n",(0,r.jsx)(n.img,{alt:"Share Details",src:s(4647).Z+"",width:"1791",height:"1369"})]}),"\n",(0,r.jsxs)(n.p,{children:["If we click on the ",(0,r.jsx)(n.em,{children:"frontend endpoint"})," a new browser tab opens and we see the content of our share:\n",(0,r.jsx)(n.img,{alt:"Share Frontend",src:s(6254).Z+"",width:"1669",height:"1033"})]}),"\n",(0,r.jsx)(n.p,{children:"If we click on the environment in the explorer, we're shown all of the shares for that environment (including our new share), along with a spark line that shows the activity:"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"Environment Spark Line",src:s(9737).Z+"",width:"1791",height:"1369"})}),"\n",(0,r.jsxs)(n.p,{children:["And as soon as I terminate the ",(0,r.jsx)(n.code,{children:"zrok share"})," client, the resources are removed from the ",(0,r.jsx)(n.code,{children:"zrok"})," environment."]}),"\n",(0,r.jsx)(n.p,{children:"If we try to reload the frontend endpoint in our web browser, we'll see:"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"Not Found",src:s(5724).Z+"",width:"1556",height:"1229"})}),"\n",(0,r.jsx)(n.h3,{id:"private-shares",children:"Private Shares"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"zrok"})," also provides a powerful ",(0,r.jsx)(n.em,{children:"private"})," sharing model. If I execute the following command:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-buttonless",metastring:'title="Example"',children:"$ zrok share private http://localhost:8080\n"})}),"\n",(0,r.jsxs)(n.p,{children:["The ",(0,r.jsx)(n.code,{children:"zrok"})," service will respond with the following:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-buttonless",metastring:'title="Output"',children:"access your share with: zrok access private wvszln4dyz9q\n"})}),"\n",(0,r.jsxs)(n.p,{children:["Rather than allowing access to your service through a public frontend, a ",(0,r.jsx)(n.em,{children:"private"})," share is only exposed to the underlying OpenZiti network, and can only be accessed using the ",(0,r.jsx)(n.code,{children:"zrok access"})," command."]}),"\n",(0,r.jsxs)(n.p,{children:["The ",(0,r.jsx)(n.code,{children:"zrok access private wvszln4dyz9q"})," command can be run by any ",(0,r.jsx)(n.code,{children:"zrok"})," user, allowing them to create and bind a local HTTP listener, that allows for private access to your shared resources."]}),"\n",(0,r.jsx)(n.h3,{id:"proxy-backend-mode",children:"Proxy Backend Mode"}),"\n",(0,r.jsxs)(n.p,{children:["Without specifying a ",(0,r.jsx)(n.em,{children:"backend mode"}),", the ",(0,r.jsx)(n.code,{children:"zrok share"})," command will assume that you're trying to share a ",(0,r.jsx)(n.code,{children:"proxy"})," resource. A ",(0,r.jsx)(n.code,{children:"proxy"})," resource is usually some private HTTP/HTTPS endpoint (like a development server, or a private application) running in your local environment. Usually such an endpoint would have no inbound connectivity except for however it is reachable from your local environment. It might be running on ",(0,r.jsx)(n.code,{children:"localhost"}),", or only listening on a private LAN segment behind a firewall."]}),"\n",(0,r.jsxs)(n.p,{children:["For these services a ",(0,r.jsx)(n.code,{children:"proxy"})," share will allow those endpoints to be reached, either ",(0,r.jsx)(n.em,{children:"publicly"})," or ",(0,r.jsx)(n.em,{children:"privately"})," through the ",(0,r.jsx)(n.code,{children:"zrok"})," service."]}),"\n",(0,r.jsx)(n.h3,{id:"web-backend-mode",children:"Web Backend Mode"}),"\n",(0,r.jsxs)(n.p,{children:["The ",(0,r.jsx)(n.code,{children:"zrok share"})," command accepts a ",(0,r.jsx)(n.code,{children:"--backend-mode"})," option. Besides ",(0,r.jsx)(n.code,{children:"proxy"}),", the current ",(0,r.jsx)(n.code,{children:"v0.3"})," release (as of this writing) also supports a ",(0,r.jsx)(n.code,{children:"web"})," mode. The ",(0,r.jsx)(n.code,{children:"web"})," mode allows you to specify a local folder on your filesystem, and instantly turns your ",(0,r.jsx)(n.code,{children:"zrok"})," client into a web server, exposing your web content either ",(0,r.jsx)(n.em,{children:"publicly"})," or ",(0,r.jsx)(n.em,{children:"privately"})," without having to a configure a web server."]}),"\n",(0,r.jsx)(n.h3,{id:"reserved-shares",children:"Reserved Shares"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"zrok"})," shares are ",(0,r.jsx)(n.em,{children:"ephemeral"}),' unless you specifically create a "reserved" share.']}),"\n",(0,r.jsxs)(n.p,{children:["A reserved share can be re-used multiple times; it will survive termination of the ",(0,r.jsx)(n.code,{children:"zrok share"})," command, allowing for longer-lasting semi-permanent access to shared resources."]}),"\n",(0,r.jsx)(n.p,{children:"The first step is to create the reserved share:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-txt",metastring:'title="Example"',children:"$ zrok reserve public --backend-mode web v0.3_getting_started\n[ 0.275] INFO main.(*reserveCommand).run: your reserved share token is 'mltwsinym1s2'\n[ 0.275] INFO main.(*reserveCommand).run: reserved frontend endpoint: https://mltwsinym1s2.share.zrok.io\n"})}),"\n",(0,r.jsxs)(n.p,{children:["I'm asking the ",(0,r.jsx)(n.code,{children:"zrok"})," service to reserve a share with a ",(0,r.jsx)(n.code,{children:"web"})," backend mode, pointing at my local ",(0,r.jsx)(n.code,{children:"docs"})," folder."]}),"\n",(0,r.jsxs)(n.p,{children:["You'll want to remember the share token (",(0,r.jsx)(n.code,{children:"mltwsinym1s2"})," in this case), and the frontend endpoint URL. If this were a ",(0,r.jsx)(n.em,{children:"private"})," reserved share, there would not be a frontend URL."]}),"\n",(0,r.jsx)(n.p,{children:"If we do nothing else, and then point a web browser at the frontend endpoint, we get:"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"Not Found",src:s(7369).Z+"",width:"1556",height:"1229"})}),"\n",(0,r.jsxs)(n.p,{children:["This is the ",(0,r.jsx)(n.code,{children:"404"})," error message returned by the ",(0,r.jsx)(n.code,{children:"zrok"})," frontend. We're getting this because we haven't yet started up a ",(0,r.jsx)(n.code,{children:"zrok share"})," for the service. Let's do that:"]}),"\n",(0,r.jsx)(n.p,{children:"This command:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-txt",metastring:'title="Example"',children:"$ zrok share reserved mltwsinym1s2\n"})}),"\n",(0,r.jsx)(n.p,{children:"...results in a new share backend starting up and connecting to the existing reserved share:"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"zrok share reserved",src:s(1577).Z+"",width:"951",height:"706"})}),"\n",(0,r.jsxs)(n.p,{children:["And now if we refresh the frontend endpoint URL in the web browser, we'll see an index of the ",(0,r.jsx)(n.code,{children:"docs"})," directory:"]}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"zrok docs share",src:s(6254).Z+"",width:"1669",height:"1033"})}),"\n",(0,r.jsxs)(n.p,{children:["With the reserved share, we're free to stop and restart the ",(0,r.jsx)(n.code,{children:"zrok share reserved"})," command as many times as we want, without losing the token for our share."]}),"\n",(0,r.jsxs)(n.p,{children:["When we're done with the reserved share, we can ",(0,r.jsx)(n.em,{children:"release"})," it using this command:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-txt",metastring:'title="Example"',children:"$ zrok release mltwsinym1s2\n[ 0.230] INFO main.(*releaseCommand).run: reserved share 'mltwsinym1s2' released\n"})}),"\n",(0,r.jsx)(n.h2,{id:"concepts-review",children:"Concepts Review"}),"\n",(0,r.jsxs)(n.p,{children:["In summary, ",(0,r.jsx)(n.code,{children:"zrok"})," lets you easily and securely share resources with both general internet users (through ",(0,r.jsx)(n.em,{children:"public"})," sharing) and also with other ",(0,r.jsx)(n.code,{children:"zrok"})," users (through ",(0,r.jsx)(n.em,{children:"private"})," sharing)."]}),"\n",(0,r.jsxs)(n.p,{children:["Here's a quick review of the ",(0,r.jsx)(n.code,{children:"zrok"})," mental model and the vocabulary."]}),"\n",(0,r.jsx)(n.h3,{id:"instance-and-account",children:"Instance and Account"}),"\n",(0,r.jsxs)(n.p,{children:["You create an ",(0,r.jsx)(n.em,{children:"account"})," with a ",(0,r.jsx)(n.code,{children:"zrok"})," ",(0,r.jsx)(n.em,{children:"instance"}),". Your account is identified by a username and a password, which you use to log into the ",(0,r.jsx)(n.em,{children:"web console"}),". Your account also has a ",(0,r.jsx)(n.em,{children:"secret token"}),", which you will use to authenticate from the ",(0,r.jsx)(n.code,{children:"zrok"})," command-line to interact with the ",(0,r.jsx)(n.em,{children:"instance"}),"."]}),"\n",(0,r.jsxs)(n.p,{children:["You create a new ",(0,r.jsx)(n.em,{children:"account"})," with a ",(0,r.jsx)(n.code,{children:"zrok"})," ",(0,r.jsx)(n.em,{children:"instance"})," through the ",(0,r.jsx)(n.code,{children:"zrok invite"})," command."]}),"\n",(0,r.jsx)(n.h3,{id:"environment",children:"Environment"}),"\n",(0,r.jsxs)(n.p,{children:["Using your ",(0,r.jsx)(n.em,{children:"secret token"})," you use the ",(0,r.jsx)(n.code,{children:"zrok"})," command-line interface to create an ",(0,r.jsx)(n.em,{children:"environment"}),". An ",(0,r.jsx)(n.em,{children:"environment"})," corresponds to a single command-line user on a specific ",(0,r.jsx)(n.em,{children:"host system"}),"."]}),"\n",(0,r.jsxs)(n.p,{children:["You create a new ",(0,r.jsx)(n.em,{children:"environment"})," by using the ",(0,r.jsx)(n.code,{children:"zrok enable"})," command."]}),"\n",(0,r.jsx)(n.h3,{id:"shares",children:"Shares"}),"\n",(0,r.jsxs)(n.p,{children:["Once you've enabled an ",(0,r.jsx)(n.em,{children:"environment"}),", you then create one or more ",(0,r.jsx)(n.em,{children:"shares"}),". Shares have either a ",(0,r.jsx)(n.em,{children:"public"})," or ",(0,r.jsx)(n.em,{children:"private"})," ",(0,r.jsx)(n.em,{children:"sharing mode"}),". ",(0,r.jsx)(n.em,{children:"Shares"})," share a specific type of resource using a ",(0,r.jsx)(n.em,{children:"backend mode"}),". As of this writing ",(0,r.jsx)(n.code,{children:"zrok"})," supports a ",(0,r.jsx)(n.code,{children:"proxy"})," ",(0,r.jsx)(n.em,{children:"backend mode"})," to share local HTTP resources as a ",(0,r.jsx)(n.em,{children:"reverse proxy"}),". ",(0,r.jsx)(n.code,{children:"zrok"})," also supports a ",(0,r.jsx)(n.code,{children:"web"})," ",(0,r.jsx)(n.em,{children:"backend mode"})," to share local file and HTML resources by enabling a basic HTTP server."]}),"\n",(0,r.jsxs)(n.p,{children:["Every ",(0,r.jsx)(n.em,{children:"share"})," is identified by a ",(0,r.jsx)(n.em,{children:"share token"}),". ",(0,r.jsx)(n.em,{children:"Public shares"})," can be accessed through either a ",(0,r.jsx)(n.em,{children:"frontend"})," instance offered through the ",(0,r.jsx)(n.code,{children:"zrok"})," ",(0,r.jsx)(n.em,{children:"instance"}),", or through the ",(0,r.jsx)(n.code,{children:"zrok access"})," command. ",(0,r.jsx)(n.em,{children:"Private shares"})," can only be accessed through the ",(0,r.jsx)(n.code,{children:"zrok access"})," command."]}),"\n",(0,r.jsxs)(n.p,{children:["You use the ",(0,r.jsx)(n.code,{children:"zrok share"})," command to create and enable ",(0,r.jsx)(n.em,{children:"ephemeral shares"}),"."]}),"\n",(0,r.jsx)(n.h3,{id:"reserved-shares-1",children:"Reserved Shares"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"zrok"})," supports creating ",(0,r.jsx)(n.em,{children:"shares"})," that have a consistent ",(0,r.jsx)(n.em,{children:"share token"})," that survives restarts of the ",(0,r.jsx)(n.code,{children:"zrok share"})," command. These are considered ",(0,r.jsx)(n.em,{children:"non-ephemeral"}),", and is callled a ",(0,r.jsx)(n.em,{children:"reserved share"}),"."]}),"\n",(0,r.jsxs)(n.p,{children:["You use the ",(0,r.jsx)(n.code,{children:"zrok reserve"})," command to create ",(0,r.jsx)(n.em,{children:"reserved shares"}),". Reserved shares last until you use the ",(0,r.jsx)(n.code,{children:"zrok release"})," command to delete them."]}),"\n",(0,r.jsx)(n.h2,{id:"self-hosting-an-instance",children:"Self-Hosting an Instance"}),"\n",(0,r.jsxs)(n.p,{children:["Interested in self-hosting your own ",(0,r.jsx)(n.code,{children:"zrok"})," instance? See the ",(0,r.jsx)(n.a,{href:"/docs/guides/self-hosting/self_hosting_guide",children:"self-hosting guide"})," for details."]})]})}function x(e={}){const{wrapper:n}={...(0,i.a)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(u,{...e})}):u(e)}},4908:(e,n,s)=>{s.d(n,{L:()=>t,N:()=>a});var r=s(7294),i=s(5893);const o=(0,r.createContext)([]),t=()=>(0,r.useContext)(o),a=e=>{let{children:n}=e;const[s,t]=(0,r.useState)([]);return(0,r.useEffect)((()=>{(async()=>{try{const e=await fetch("https://api.github.com/repos/openziti/zrok/releases/latest");if(!e.ok)throw new Error(`HTTP error! status: ${e.status}`);const n=(await e.json()).assets.map((e=>({name:e.name,url:e.browser_download_url,arch:e.name.replace(".tar.gz","").split("_")[3]})));console.log("Fetched assets:",n),t(n)}catch(e){console.error("Error fetching the release assets:",e)}})()}),[]),(0,i.jsx)(o.Provider,{value:s,children:n})}},3298:(e,n,s)=>{s.d(n,{Z:()=>c});s(7294);var r=s(4908),i=s(7597),o=s(2949),t=s(5893);const a=e=>{switch(e){case"amd64":return"x86_64";case"arm64":return"ARM64";case"armv7":return"ARM";default:return e.toUpperCase()}},c=e=>{let{osName:n,osLogo:s,infoText:c,guideLink:d}=e;const{colorMode:l}=(0,o.I)(),h=(0,r.L)();console.log("Assets in DownloadCard:",h);const m=(e=>{switch(e){case"Windows":return"windows";case"macOS":return"darwin";case"Linux":return"linux";default:return""}})(n),u=h.filter((e=>e.name.includes(m)));return console.log("Filtered assets for",n,"in DownloadCard:",u),(0,t.jsxs)("div",{className:i.Z.downloadCard,children:[(0,t.jsx)("div",{className:i.Z.imgContainer,children:(0,t.jsx)("img",{src:s,alt:`${n} logo`})}),(0,t.jsx)("h3",{children:n}),u.length>0&&(0,t.jsx)("ul",{children:u.map(((e,n)=>(0,t.jsx)("li",{className:i.Z.downloadButtons,children:(0,t.jsx)("a",{href:e.url,className:i.Z.downloadLinks,children:a(e.arch)})},n)))}),d&&(0,t.jsxs)("div",{className:i.Z.cardFooter,children:[(0,t.jsx)("p",{children:c}),(0,t.jsx)("a",{href:d,children:"GUIDE"}),(0,t.jsx)("p",{})]})]})}},7597:(e,n,s)=>{s.d(n,{Z:()=>r});const r={downloadContainer:"downloadContainer_nNgj",downloadCard:"downloadCard_D_EY",cardFooter:"cardFooter_Rhom",downloadButtons:"downloadButtons_NPAP",downloadLinks:"downloadLinks_thSu",imgContainer:"imgContainer_r0QA"}},9042:(e,n,s)=>{s.d(n,{Z:()=>r});const r=s.p+"assets/images/zrok_enable_modal-45da63a6907e930daaa4c798272ce5fa.png"},5724:(e,n,s)=>{s.d(n,{Z:()=>r});const r=s.p+"assets/images/zrok_not_found-fa3415937c341eb10e1eb98c9b063583.png"},242:(e,n,s)=>{s.d(n,{Z:()=>r});const r=s.p+"assets/images/zrok_registration_success-05e7e328284f6dc38cd993322698d38b.png"},7369:(e,n,s)=>{s.d(n,{Z:()=>r});const r=s.p+"assets/images/zrok_reserved_not_found-2519707e5cc3e635b7a6feb381c1d040.png"},1577:(e,n,s)=>{s.d(n,{Z:()=>r});const r=s.p+"assets/images/zrok_share_reserved-6bce67775ce2c41abb0ef13ee1fad972.png"},9744:(e,n,s)=>{s.d(n,{Z:()=>r});const r=s.p+"assets/images/zrok_verify-22a26d401b9a77a4278f3c0f54d2a981.png"},2945:(e,n,s)=>{s.d(n,{Z:()=>r});const r=s.p+"assets/images/zrok_web_console_empty-cce147eaf8e7bc83abe556336a4aea98.png"},9737:(e,n,s)=>{s.d(n,{Z:()=>r});const r=s.p+"assets/images/zrok_web_console_environment_spark-925c0709ed7a42f0a708ab0523cdeb5f.png"},6097:(e,n,s)=>{s.d(n,{Z:()=>r});const r=s.p+"assets/images/zrok_web_console_explorer_share-11236f68819da60014d5444e7429c189.png"},4647:(e,n,s)=>{s.d(n,{Z:()=>r});const r=s.p+"assets/images/zrok_web_console_share_detail-efeaa472d5e5c225a160f6d5647086b3.png"},6254:(e,n,s)=>{s.d(n,{Z:()=>r});const r=s.p+"assets/images/zrok_web_console_share_frontend-d7c0d6495493c00b94ae237339f2dc2d.png"},9509:(e,n,s)=>{s.d(n,{Z:()=>r});const r=s.p+"assets/images/zrok_web_login-a6161cc79e66932fab76994bdfb8f9c1.png"},2534:(e,n,s)=>{s.d(n,{Z:()=>r});const r=s.p+"assets/images/zrok_web_ui_empty_environment_detail-153c921ade86f924079947b0f734e3ff.png"},3858:(e,n,s)=>{s.d(n,{Z:()=>r});const r=s.p+"assets/images/zrok_web_ui_empty_shares-048c08c18477bcabb9fa8c1b58537012.png"},5546:(e,n,s)=>{s.d(n,{Z:()=>r});const r=s.p+"assets/images/zrok_web_ui_new_environment-414d8e8fc25b09f257cb40ba47d6acbb.png"},3843:(e,n,s)=>{s.d(n,{Z:()=>r});const r="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAZCAIAAACpVwlNAAAEr2lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNS41LjAiPgogPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iCiAgICB4bWxuczpleGlmPSJodHRwOi8vbnMuYWRvYmUuY29tL2V4aWYvMS4wLyIKICAgIHhtbG5zOnBob3Rvc2hvcD0iaHR0cDovL25zLmFkb2JlLmNvbS9waG90b3Nob3AvMS4wLyIKICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIKICAgIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIgogICAgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIKICAgdGlmZjpJbWFnZUxlbmd0aD0iMjUiCiAgIHRpZmY6SW1hZ2VXaWR0aD0iMzAiCiAgIHRpZmY6UmVzb2x1dGlvblVuaXQ9IjIiCiAgIHRpZmY6WFJlc29sdXRpb249Ijk2LzEiCiAgIHRpZmY6WVJlc29sdXRpb249Ijk2LzEiCiAgIGV4aWY6UGl4ZWxYRGltZW5zaW9uPSIzMCIKICAgZXhpZjpQaXhlbFlEaW1lbnNpb249IjI1IgogICBleGlmOkNvbG9yU3BhY2U9IjEiCiAgIHBob3Rvc2hvcDpDb2xvck1vZGU9IjMiCiAgIHBob3Rvc2hvcDpJQ0NQcm9maWxlPSJzUkdCIElFQzYxOTY2LTIuMSIKICAgeG1wOk1vZGlmeURhdGU9IjIwMjMtMDEtMTlUMTA6NTY6NTYtMDU6MDAiCiAgIHhtcDpNZXRhZGF0YURhdGU9IjIwMjMtMDEtMTlUMTA6NTY6NTYtMDU6MDAiPgogICA8eG1wTU06SGlzdG9yeT4KICAgIDxyZGY6U2VxPgogICAgIDxyZGY6bGkKICAgICAgc3RFdnQ6YWN0aW9uPSJwcm9kdWNlZCIKICAgICAgc3RFdnQ6c29mdHdhcmVBZ2VudD0iQWZmaW5pdHkgUGhvdG8gMi4wLjMiCiAgICAgIHN0RXZ0OndoZW49IjIwMjMtMDEtMTlUMTA6NTY6NTYtMDU6MDAiLz4KICAgIDwvcmRmOlNlcT4KICAgPC94bXBNTTpIaXN0b3J5PgogIDwvcmRmOkRlc2NyaXB0aW9uPgogPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KPD94cGFja2V0IGVuZD0iciI/Pq+HLHgAAAGBaUNDUHNSR0IgSUVDNjE5NjYtMi4xAAAokXWRy0tCQRSHP7UwemBQixYtJKyVRg8Q27RQyoJqYQZZbfTmI/BxuVcJaRu0FQqiNr0W9RfUNmgdBEURRNtaF7UpuZ2rghF5hjnzzW/OOcycAWs4rWT0piHIZPNaKOh3LkaWnPYXLHThwIclqujq7PxkmIb2eS/RYrces1bjuH+tbTWuK2BpER5XVC0vPCU8s55XTd4R7lZS0VXhM2G3JhcUvjP1WJVfTU5W+dtkLRwKgLVT2Jn8xbFfrKS0jLC8HFcmXVBq9zFf0h7PLszL2iezF50QQfw4mWaCAF6GGRPvxcMIg7KjQf5QJX+OnOQq4lWKaKyRJEUet6gFqR6XNSF6XEaaotn/v33VE6Mj1ertfmh+Noz3frBvQ7lkGF9HhlE+BtsTXGbr+blD8H2IXqprrgNwbML5VV2L7cLFFvQ8qlEtWpFsMq2JBLydQkcEum6gdbnas9o5Jw8Q3pCvuoa9fRiQeMfKD2DYZ+PDGzxnAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABZklEQVRIie2VvW7CMBDHr1UfwE5fII7lvahIWUEiQ7qxMLEwsVQMSB0YKsTExsDGxFs0QyqlYyMVld3k4wWw/QgMlqp+JXFQGZB649n3k+9/f9sX9w+PcJq4PBH3H/0zrkrWfK99jVF5/V6qIIzqod1m485rC6nK0S5GAPArvRDNHFtINZ0vviQp4Un2OTObjIs6q6G122yMhgPfaxvuN0VbGDHHBgDm2FbVAGqgLYyEVPFmCwDB84uQilHyB2i32ej3uoySvZDT+YInGaPE77QqlSkznz5vv9cFAEbJdL4QUlkYjYYDnYnf3o9HC6mewog5ttZBq7xcrf1OK95sy61ZgQaAIIx2lGgdRsPBcrXmSbYXstLyRmPkSWZh5HdaAODe3uipVlaZmk9IxdMcAHiam3DBRJCPCMJol+bfbuMxaJ7mjJLZZFxeb2Gku6mDTrJXjExeviILFqJF8WtpGOf5y5wn+gBcXI4F9z6rgwAAAABJRU5ErkJggg=="},1151:(e,n,s)=>{s.d(n,{Z:()=>a,a:()=>t});var r=s(7294);const i={},o=r.createContext(i);function t(e){const n=r.useContext(o);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:t(e.components),r.createElement(o.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/f888b719.f45e9c0f.js b/assets/js/f888b719.f45e9c0f.js new file mode 100644 index 00000000..842cecec --- /dev/null +++ b/assets/js/f888b719.f45e9c0f.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[938],{2800:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>h,contentTitle:()=>d,default:()=>x,frontMatter:()=>c,metadata:()=>l,toc:()=>m});var r=s(5893),i=s(1151),o=s(4908),t=s(3298),a=s(7597);const c={title:"Getting Started with zrok",sidebar_label:"Getting Started",sidebar_position:10},d=void 0,l={id:"getting-started",title:"Getting Started with zrok",description:"What's a zrok?",source:"@site/../docs/getting-started.mdx",sourceDirName:".",slug:"/getting-started",permalink:"/docs/getting-started",draft:!1,unlisted:!1,editUrl:"https://github.com/openziti/zrok/blob/main/docs/../docs/getting-started.mdx",tags:[],version:"current",sidebarPosition:10,frontMatter:{title:"Getting Started with zrok",sidebar_label:"Getting Started",sidebar_position:10},sidebar:"tutorialSidebar",next:{title:"Concepts",permalink:"/docs/concepts/"}},h={},m=[{value:"What's a zrok?",id:"whats-a-zrok",level:2},{value:"Open Source",id:"open-source",level:2},{value:"Ziti native",id:"ziti-native",level:3},{value:"What's it for?",id:"whats-it-for",level:2},{value:"Installing the zrok Command",id:"installing-the-zrok-command",level:2},{value:"Generating an Invitation",id:"generating-an-invitation",level:2},{value:"Enabling Your zrok Environment",id:"enabling-your-zrok-environment",level:2},{value:"Sharing",id:"sharing",level:2},{value:"Ephemeral by Default",id:"ephemeral-by-default",level:3},{value:"Public Shares and Frontends",id:"public-shares-and-frontends",level:3},{value:"Private Shares",id:"private-shares",level:3},{value:"Proxy Backend Mode",id:"proxy-backend-mode",level:3},{value:"Web Backend Mode",id:"web-backend-mode",level:3},{value:"Reserved Shares",id:"reserved-shares",level:3},{value:"Concepts Review",id:"concepts-review",level:2},{value:"Instance and Account",id:"instance-and-account",level:3},{value:"Environment",id:"environment",level:3},{value:"Shares",id:"shares",level:3},{value:"Reserved Shares",id:"reserved-shares-1",level:3},{value:"Self-Hosting an Instance",id:"self-hosting-an-instance",level:2}];function u(e){const n={a:"a",admonition:"admonition",code:"code",em:"em",h2:"h2",h3:"h3",img:"img",p:"p",pre:"pre",...(0,i.a)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h2,{id:"whats-a-zrok",children:"What's a zrok?"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"zrok"})," (",(0,r.jsx)(n.em,{children:"/zi\u02d0\u0279\u0252k/ ZEE-rock"}),") is a secure, open-source, self-hostable sharing platform that simplifies shielding and sharing network services or files. There's a hardened zrok-as-a-service offering available at ",(0,r.jsx)(n.a,{href:"https://zrok.io",children:"zrok.io"})," with a generous free tier."]}),"\n",(0,r.jsx)(n.h2,{id:"open-source",children:"Open Source"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"zrok"})," is licensed under Apache 2.0."]}),"\n",(0,r.jsxs)(n.p,{children:["Check ",(0,r.jsx)(n.a,{href:"https://github.com/orgs/openziti/projects/16",children:"the roadmap"})," if you're thinking about the future. We would love to hear your ideas for ",(0,r.jsx)(n.code,{children:"zrok"}),"!"]}),"\n",(0,r.jsxs)(n.p,{children:["The best ways to engage are ",(0,r.jsx)(n.a,{href:"https://openziti.discourse.group/",children:"Discourse"})," for questions and ",(0,r.jsx)(n.a,{href:"https://github.com/openziti/zrok/issues",children:"GitHub Issues"})," for documenting problems."]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.a,{href:"/docs/concepts/opensource",children:"Read more about zrok open source"}),"."]}),"\n",(0,r.jsx)(n.h3,{id:"ziti-native",children:"Ziti native"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"zrok"})," is a ",(0,r.jsx)(n.em,{children:"Ziti Native Application"}),", built on the ",(0,r.jsx)(n.a,{href:"https://openziti.io",children:"OpenZiti"})," platform, and supported by the OpenZiti community and NetFoundry team."]}),"\n",(0,r.jsx)(n.h2,{id:"whats-it-for",children:"What's it for?"}),"\n",(0,r.jsxs)(n.p,{children:["Use ",(0,r.jsx)(n.code,{children:"zrok"})," to share a running service, like a web server or a network socket, or to share a directory of static files."]}),"\n",(0,r.jsxs)(n.p,{children:["If ",(0,r.jsx)(n.a,{href:"/docs/concepts/sharing-public",children:"sharing publicly"}),", you can reserve a subdomain, enable authentication options, or both. Public shares proxy HTTPS to your service or files."]}),"\n",(0,r.jsxs)(n.p,{children:["If ",(0,r.jsx)(n.a,{href:"/docs/concepts/sharing-private",children:"sharing privately"}),", only users with the share token can access your share. In addition to what you can share publicly, private shares can include TCP and UDP services."]}),"\n",(0,r.jsx)(n.h2,{id:"installing-the-zrok-command",children:"Installing the zrok Command"}),"\n",(0,r.jsx)(o.N,{children:(0,r.jsxs)("div",{className:a.Z.downloadContainer,children:[(0,r.jsx)(t.Z,{osName:"Windows",osLogo:"/img/logo-windows.svg",infoText:"Binary executable",guideLink:"/docs/guides/install/windows"}),(0,r.jsx)(t.Z,{osName:"macOS",osLogo:"/img/logo-apple.svg",infoText:"Binary executable",guideLink:"/docs/guides/install/macos"}),(0,r.jsx)(t.Z,{osName:"Linux",osLogo:"/img/logo-linux.svg",infoText:"DEB, RPM packages",guideLink:"/docs/guides/install/linux"})]})}),"\n",(0,r.jsx)(n.h2,{id:"generating-an-invitation",children:"Generating an Invitation"}),"\n",(0,r.jsx)(n.admonition,{type:"note",children:(0,r.jsxs)(n.p,{children:["If not using ",(0,r.jsx)(n.code,{children:"zrok.io"})," (zrok-as-a-service), you must configure the ",(0,r.jsx)(n.code,{children:"zrok"})," command to use your instance. See the ",(0,r.jsx)(n.a,{href:"/docs/guides/self-hosting/instance-configuration",children:"instance configuration guide"})," in the self-hosting section for details."]})}),"\n",(0,r.jsxs)(n.p,{children:["Invite yourself to ",(0,r.jsx)(n.code,{children:"zrok"})," by running the ",(0,r.jsx)(n.code,{children:"zrok invite"})," command:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-text",children:"zrok invite\n"})}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-buttonless",metastring:'title="Output"',children:"enter and confirm your email address...\n\n> user@domain.com\n> user@domain.com\n\n[ Submit ]\n\ninvitation sent to 'user@domain.com'!\n"})}),"\n",(0,r.jsxs)(n.p,{children:["The ",(0,r.jsx)(n.code,{children:"zrok invite"})," command presents a small form that allows you to enter (and then confirm) your email address. Tabbing to the ",(0,r.jsx)(n.code,{children:"[ Submit ]"})," button will send the request to your configured ",(0,r.jsx)(n.code,{children:"zrok"})," service."]}),"\n",(0,r.jsxs)(n.p,{children:["Next, check the email where you sent the invite. You should receive a message asking you to click a link to create your ",(0,r.jsx)(n.code,{children:"zrok"})," account. When you click that link, you will be brought to a web page that will allow you to set a password for your new account:"]}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"Enter a Password",src:s(9744).Z+"",width:"1791",height:"1362"})}),"\n",(0,r.jsxs)(n.p,{children:["Enter a password and its confirmation, and click the ",(0,r.jsx)(n.code,{children:"Register Account"})," button. You'll see the following:"]}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"Successful Registration",src:s(242).Z+"",width:"1791",height:"1369"})}),"\n",(0,r.jsxs)(n.p,{children:['For now, we\'ll ignore the "enable your shell for zrok" section. Just click the ',(0,r.jsx)(n.code,{children:"zrok web portal"})," link:"]}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"Web Login",src:s(9509).Z+"",width:"1791",height:"1362"})}),"\n",(0,r.jsxs)(n.p,{children:["After clicking the ",(0,r.jsx)(n.code,{children:"Log In"})," button, you'll be brought into the ",(0,r.jsx)(n.code,{children:"zrok"})," ",(0,r.jsx)(n.em,{children:"web console"}),":"]}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"Web Console; Empty",src:s(2945).Z+"",width:"1791",height:"1362"})}),"\n",(0,r.jsxs)(n.p,{children:["Congratulations! Your ",(0,r.jsx)(n.code,{children:"zrok"})," account is ready to go!"]}),"\n",(0,r.jsx)(n.h2,{id:"enabling-your-zrok-environment",children:"Enabling Your zrok Environment"}),"\n",(0,r.jsxs)(n.p,{children:["When your ",(0,r.jsx)(n.code,{children:"zrok"})," account was created, the service generated a ",(0,r.jsx)(n.em,{children:"secret token"})," that identifies and authenticates in a single step. Protect your secret token as if it were a password, or an important account number; it's a ",(0,r.jsx)(n.em,{children:"secret"}),", protect it."]}),"\n",(0,r.jsxs)(n.p,{children:["When we left off you had downloaded, extracted, and configured your ",(0,r.jsx)(n.code,{children:"zrok"})," environment. In order to use that environment with your account, you'll need to ",(0,r.jsx)(n.code,{children:"enable"})," it. Enabling an environment generates a secure identity and the necessary underlying security policies with the OpenZiti network hosting the ",(0,r.jsx)(n.code,{children:"zrok"})," service."]}),"\n",(0,r.jsxs)(n.p,{children:["From the web console, click on your email address in the upper right corner of the header. That drop down menu contains an ",(0,r.jsx)(n.code,{children:"Enable Your Environment"})," link. Click that link and a modal dialog will be shown like this:"]}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"Enable Modal Dialog",src:s(9042).Z+"",width:"1791",height:"1369"})}),"\n",(0,r.jsxs)(n.p,{children:["This dialog box shows you the ",(0,r.jsx)(n.code,{children:"zrok enable"})," command that you can use to enable any shell to work with your ",(0,r.jsx)(n.code,{children:"zrok"})," account with a single command."]}),"\n",(0,r.jsx)(n.p,{children:"Let's copy that command and paste it into your shell:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-buttonless",metastring:'title="Example"',children:"$ zrok enable klFEoIi0QAg7 \n\u28fb contacting the zrok service...\n"})}),"\n",(0,r.jsx)(n.p,{children:"After a few seconds, the message will change and indicate that the enable operation succeeded:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-buttonless",metastring:'title="Example"',children:"$ zrok enable klFEoIi0QAg7 \n\u28fb the zrok environment was successfully enabled...\n"})}),"\n",(0,r.jsxs)(n.p,{children:["Now, if we run a ",(0,r.jsx)(n.code,{children:"zrok status"})," command, you will see the details of your environment:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-txt",children:"zrok status\n"})}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-buttonless",metastring:'title="Output"',children:"Config:\n\n CONFIG VALUE SOURCE\n apiEndpoint https://api.staging.zrok.io env\n\nEnvironment:\n\n PROPERTY VALUE\n Secret Token <>\n Ziti Identity <>\n"})}),"\n",(0,r.jsx)(n.p,{children:"Excellent... our environment is now fully enabled."}),"\n",(0,r.jsxs)(n.p,{children:["If we return to the ",(0,r.jsx)(n.em,{children:"web console"}),", we'll now see the new environment reflected in the explorer view:"]}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"New Environment in Web UI",src:s(5546).Z+"",width:"1791",height:"1369"})}),"\n",(0,r.jsxs)(n.p,{children:["In my case, the environment is named ",(0,r.jsx)(n.code,{children:"michael@ziti-lx"}),", which is the username of my shell and the hostname of the system the shell is running on."]}),"\n",(0,r.jsx)(n.admonition,{type:"note",children:(0,r.jsxs)(n.p,{children:["Should you want to use a non-default name for your environment, you can pass the ",(0,r.jsx)(n.code,{children:"-d"})," option to the ",(0,r.jsx)(n.code,{children:"zrok enable"})," command. See ",(0,r.jsx)(n.code,{children:"zrok enable --help"})," for details."]})}),"\n",(0,r.jsxs)(n.p,{children:["If you click on the environment node in the explorer in the ",(0,r.jsx)(n.em,{children:"web console"}),", the details panel shown at the bottom of the page will change:"]}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"Empty Environment",src:s(3858).Z+"",width:"1791",height:"1369"})}),"\n",(0,r.jsxs)(n.p,{children:["The explorer supports clicking, dragging, mouse wheel zooming, and selecting the nodes in the graph for more information (and available actions) for the selected node. If you ever get lost in the explorer, click the ",(0,r.jsx)(n.img,{alt:"Zoom to Fit",src:s(3843).Z+"",width:"30",height:"25"})," ",(0,r.jsx)(n.em,{children:"zoom to fit"})," icon in the lower right corner of the explorer."]}),"\n",(0,r.jsxs)(n.p,{children:["If we click on the ",(0,r.jsx)(n.code,{children:"Detail"})," tab for our environment, we'll see something like:"]}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"Environment Detail",src:s(2534).Z+"",width:"1791",height:"1369"})}),"\n",(0,r.jsx)(n.admonition,{type:"note",children:(0,r.jsxs)(n.p,{children:["With your ",(0,r.jsx)(n.code,{children:"zrok"})," account you can ",(0,r.jsx)(n.code,{children:"zrok enable"})," multiple environments. This will allow you to run ",(0,r.jsx)(n.code,{children:"zrok share"})," in one environment, and ",(0,r.jsx)(n.code,{children:"zrok access"})," in other environments."]})}),"\n",(0,r.jsx)(n.p,{children:"Your environment is fully ready to go. Now we can move on to the fun stuff..."}),"\n",(0,r.jsx)(n.h2,{id:"sharing",children:"Sharing"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"zrok"})," is designed to make sharing resources as effortless as possible, while providing a high degree of security and control."]}),"\n",(0,r.jsx)(n.h3,{id:"ephemeral-by-default",children:"Ephemeral by Default"}),"\n",(0,r.jsxs)(n.p,{children:["Shared resources are ",(0,r.jsx)(n.em,{children:"ephemeral"})," by default; as soon as you terminate the ",(0,r.jsx)(n.code,{children:"zrok share"})," command, the entire share is removed and is no longer available to any users. Identifiers for shared resources are randomly allocated when the share is created."]}),"\n",(0,r.jsx)(n.h3,{id:"public-shares-and-frontends",children:"Public Shares and Frontends"}),"\n",(0,r.jsxs)(n.p,{children:["Resources that are shared ",(0,r.jsx)(n.em,{children:"publicly"})," are exposed to any users on the internet who have access to the ",(0,r.jsx)(n.code,{children:"zrok"}),' instance\'s "frontend".']}),"\n",(0,r.jsx)(n.p,{children:"A frontend is an HTTPS listener exposed to the internet, that lets any user with your ephemeral share token access your publicly shared resources."}),"\n",(0,r.jsxs)(n.p,{children:["For example, I might create a public share using the ",(0,r.jsx)(n.code,{children:"zrok share public"})," command, which results in my ",(0,r.jsx)(n.code,{children:"zrok"})," instance exposing a URL like ",(0,r.jsx)(n.code,{children:"https://2ptgbr8tlfvk.share.zrok.io"})," to access my resources."]}),"\n",(0,r.jsxs)(n.p,{children:['In this case, my share was given the "share token" of ',(0,r.jsx)(n.code,{children:"2ptgbr8tlfvk"}),". That URL can be given to any user, allowing them to immediately access the shared resources directly from my local environment, all without exposing any access to my private, secure environment. The physical network location of my environment is not exposed to anonymous consumers of my resources."]}),"\n",(0,r.jsxs)(n.admonition,{type:"note",children:[(0,r.jsxs)(n.p,{children:["Here is the ",(0,r.jsx)(n.code,{children:"--help"})," output from ",(0,r.jsx)(n.code,{children:"zrok share public"}),":"]}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-text",children:"zrok share public\n"})}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-buttonless",metastring:'title="Output"',children:'Error: accepts 1 arg(s), received 0\nUsage:\n zrok share public [flags]\n\nFlags:\n --backend-mode string The backend mode {proxy, web, caddy, drive} (default "proxy")\n --basic-auth stringArray Basic authentication users (,...)\n --frontends stringArray Selected frontends to use for the share (default [public])\n --headless Disable TUI and run headless\n -h, --help help for public\n --insecure Enable insecure TLS certificate validation for \n\nGlobal Flags:\n -p, --panic Panic instead of showing pretty errors\n -v, --verbose Enable verbose logging\n\n[ERROR]: an error occurred (accepts 1 arg(s), received 0)\n'})}),(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:""})," defines the path to the local resource that you intend to share. The form of ",(0,r.jsx)(n.code,{children:""})," depends on the ",(0,r.jsx)(n.code,{children:"--backend-mode"})," that you're using."]}),(0,r.jsxs)(n.p,{children:["In the case of ",(0,r.jsx)(n.code,{children:"--backend-mode proxy"}),", ",(0,r.jsx)(n.code,{children:""})," should be a URL to an HTTP endpoint."]}),(0,r.jsxs)(n.p,{children:["In the case of ",(0,r.jsx)(n.code,{children:"--backend-mode web"}),", ",(0,r.jsx)(n.code,{children:""}),' is the path to a file on disk that serves as the "root" of the file tree to be shared.']})]}),"\n",(0,r.jsx)(n.p,{children:"If we return to the web console, we see our share in the explorer:"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"Web Console Share",src:s(6097).Z+"",width:"1791",height:"1369"})}),"\n",(0,r.jsxs)(n.p,{children:["If we click on our new share in the explorer, we can see the share details:\n",(0,r.jsx)(n.img,{alt:"Share Details",src:s(4647).Z+"",width:"1791",height:"1369"})]}),"\n",(0,r.jsxs)(n.p,{children:["If we click on the ",(0,r.jsx)(n.em,{children:"frontend endpoint"})," a new browser tab opens and we see the content of our share:\n",(0,r.jsx)(n.img,{alt:"Share Frontend",src:s(6254).Z+"",width:"1669",height:"1033"})]}),"\n",(0,r.jsx)(n.p,{children:"If we click on the environment in the explorer, we're shown all of the shares for that environment (including our new share), along with a spark line that shows the activity:"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"Environment Spark Line",src:s(9737).Z+"",width:"1791",height:"1369"})}),"\n",(0,r.jsxs)(n.p,{children:["And as soon as I terminate the ",(0,r.jsx)(n.code,{children:"zrok share"})," client, the resources are removed from the ",(0,r.jsx)(n.code,{children:"zrok"})," environment."]}),"\n",(0,r.jsx)(n.p,{children:"If we try to reload the frontend endpoint in our web browser, we'll see:"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"Not Found",src:s(5724).Z+"",width:"1556",height:"1229"})}),"\n",(0,r.jsx)(n.h3,{id:"private-shares",children:"Private Shares"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"zrok"})," also provides a powerful ",(0,r.jsx)(n.em,{children:"private"})," sharing model. If I execute the following command:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-buttonless",metastring:'title="Example"',children:"$ zrok share private http://localhost:8080\n"})}),"\n",(0,r.jsxs)(n.p,{children:["The ",(0,r.jsx)(n.code,{children:"zrok"})," service will respond with the following:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-buttonless",metastring:'title="Output"',children:"access your share with: zrok access private wvszln4dyz9q\n"})}),"\n",(0,r.jsxs)(n.p,{children:["Rather than allowing access to your service through a public frontend, a ",(0,r.jsx)(n.em,{children:"private"})," share is only exposed to the underlying OpenZiti network, and can only be accessed using the ",(0,r.jsx)(n.code,{children:"zrok access"})," command."]}),"\n",(0,r.jsxs)(n.p,{children:["The ",(0,r.jsx)(n.code,{children:"zrok access private wvszln4dyz9q"})," command can be run by any ",(0,r.jsx)(n.code,{children:"zrok"})," user, allowing them to create and bind a local HTTP listener, that allows for private access to your shared resources."]}),"\n",(0,r.jsx)(n.h3,{id:"proxy-backend-mode",children:"Proxy Backend Mode"}),"\n",(0,r.jsxs)(n.p,{children:["Without specifying a ",(0,r.jsx)(n.em,{children:"backend mode"}),", the ",(0,r.jsx)(n.code,{children:"zrok share"})," command will assume that you're trying to share a ",(0,r.jsx)(n.code,{children:"proxy"})," resource. A ",(0,r.jsx)(n.code,{children:"proxy"})," resource is usually some private HTTP/HTTPS endpoint (like a development server, or a private application) running in your local environment. Usually such an endpoint would have no inbound connectivity except for however it is reachable from your local environment. It might be running on ",(0,r.jsx)(n.code,{children:"localhost"}),", or only listening on a private LAN segment behind a firewall."]}),"\n",(0,r.jsxs)(n.p,{children:["For these services a ",(0,r.jsx)(n.code,{children:"proxy"})," share will allow those endpoints to be reached, either ",(0,r.jsx)(n.em,{children:"publicly"})," or ",(0,r.jsx)(n.em,{children:"privately"})," through the ",(0,r.jsx)(n.code,{children:"zrok"})," service."]}),"\n",(0,r.jsx)(n.h3,{id:"web-backend-mode",children:"Web Backend Mode"}),"\n",(0,r.jsxs)(n.p,{children:["The ",(0,r.jsx)(n.code,{children:"zrok share"})," command accepts a ",(0,r.jsx)(n.code,{children:"--backend-mode"})," option. Besides ",(0,r.jsx)(n.code,{children:"proxy"}),", the current ",(0,r.jsx)(n.code,{children:"v0.3"})," release (as of this writing) also supports a ",(0,r.jsx)(n.code,{children:"web"})," mode. The ",(0,r.jsx)(n.code,{children:"web"})," mode allows you to specify a local folder on your filesystem, and instantly turns your ",(0,r.jsx)(n.code,{children:"zrok"})," client into a web server, exposing your web content either ",(0,r.jsx)(n.em,{children:"publicly"})," or ",(0,r.jsx)(n.em,{children:"privately"})," without having to a configure a web server."]}),"\n",(0,r.jsx)(n.h3,{id:"reserved-shares",children:"Reserved Shares"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"zrok"})," shares are ",(0,r.jsx)(n.em,{children:"ephemeral"}),' unless you specifically create a "reserved" share.']}),"\n",(0,r.jsxs)(n.p,{children:["A reserved share can be re-used multiple times; it will survive termination of the ",(0,r.jsx)(n.code,{children:"zrok share"})," command, allowing for longer-lasting semi-permanent access to shared resources."]}),"\n",(0,r.jsx)(n.p,{children:"The first step is to create the reserved share:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-txt",metastring:'title="Example"',children:"$ zrok reserve public --backend-mode web v0.3_getting_started\n[ 0.275] INFO main.(*reserveCommand).run: your reserved share token is 'mltwsinym1s2'\n[ 0.275] INFO main.(*reserveCommand).run: reserved frontend endpoint: https://mltwsinym1s2.share.zrok.io\n"})}),"\n",(0,r.jsxs)(n.p,{children:["I'm asking the ",(0,r.jsx)(n.code,{children:"zrok"})," service to reserve a share with a ",(0,r.jsx)(n.code,{children:"web"})," backend mode, pointing at my local ",(0,r.jsx)(n.code,{children:"docs"})," folder."]}),"\n",(0,r.jsxs)(n.p,{children:["You'll want to remember the share token (",(0,r.jsx)(n.code,{children:"mltwsinym1s2"})," in this case), and the frontend endpoint URL. If this were a ",(0,r.jsx)(n.em,{children:"private"})," reserved share, there would not be a frontend URL."]}),"\n",(0,r.jsx)(n.p,{children:"If we do nothing else, and then point a web browser at the frontend endpoint, we get:"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"Not Found",src:s(7369).Z+"",width:"1556",height:"1229"})}),"\n",(0,r.jsxs)(n.p,{children:["This is the ",(0,r.jsx)(n.code,{children:"404"})," error message returned by the ",(0,r.jsx)(n.code,{children:"zrok"})," frontend. We're getting this because we haven't yet started up a ",(0,r.jsx)(n.code,{children:"zrok share"})," for the service. Let's do that:"]}),"\n",(0,r.jsx)(n.p,{children:"This command:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-txt",metastring:'title="Example"',children:"$ zrok share reserved mltwsinym1s2\n"})}),"\n",(0,r.jsx)(n.p,{children:"...results in a new share backend starting up and connecting to the existing reserved share:"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"zrok share reserved",src:s(1577).Z+"",width:"951",height:"706"})}),"\n",(0,r.jsxs)(n.p,{children:["And now if we refresh the frontend endpoint URL in the web browser, we'll see an index of the ",(0,r.jsx)(n.code,{children:"docs"})," directory:"]}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"zrok docs share",src:s(6254).Z+"",width:"1669",height:"1033"})}),"\n",(0,r.jsxs)(n.p,{children:["With the reserved share, we're free to stop and restart the ",(0,r.jsx)(n.code,{children:"zrok share reserved"})," command as many times as we want, without losing the token for our share."]}),"\n",(0,r.jsxs)(n.p,{children:["When we're done with the reserved share, we can ",(0,r.jsx)(n.em,{children:"release"})," it using this command:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-txt",metastring:'title="Example"',children:"$ zrok release mltwsinym1s2\n[ 0.230] INFO main.(*releaseCommand).run: reserved share 'mltwsinym1s2' released\n"})}),"\n",(0,r.jsx)(n.h2,{id:"concepts-review",children:"Concepts Review"}),"\n",(0,r.jsxs)(n.p,{children:["In summary, ",(0,r.jsx)(n.code,{children:"zrok"})," lets you easily and securely share resources with both general internet users (through ",(0,r.jsx)(n.em,{children:"public"})," sharing) and also with other ",(0,r.jsx)(n.code,{children:"zrok"})," users (through ",(0,r.jsx)(n.em,{children:"private"})," sharing)."]}),"\n",(0,r.jsxs)(n.p,{children:["Here's a quick review of the ",(0,r.jsx)(n.code,{children:"zrok"})," mental model and the vocabulary."]}),"\n",(0,r.jsx)(n.h3,{id:"instance-and-account",children:"Instance and Account"}),"\n",(0,r.jsxs)(n.p,{children:["You create an ",(0,r.jsx)(n.em,{children:"account"})," with a ",(0,r.jsx)(n.code,{children:"zrok"})," ",(0,r.jsx)(n.em,{children:"instance"}),". Your account is identified by a username and a password, which you use to log into the ",(0,r.jsx)(n.em,{children:"web console"}),". Your account also has a ",(0,r.jsx)(n.em,{children:"secret token"}),", which you will use to authenticate from the ",(0,r.jsx)(n.code,{children:"zrok"})," command-line to interact with the ",(0,r.jsx)(n.em,{children:"instance"}),"."]}),"\n",(0,r.jsxs)(n.p,{children:["You create a new ",(0,r.jsx)(n.em,{children:"account"})," with a ",(0,r.jsx)(n.code,{children:"zrok"})," ",(0,r.jsx)(n.em,{children:"instance"})," through the ",(0,r.jsx)(n.code,{children:"zrok invite"})," command."]}),"\n",(0,r.jsx)(n.h3,{id:"environment",children:"Environment"}),"\n",(0,r.jsxs)(n.p,{children:["Using your ",(0,r.jsx)(n.em,{children:"secret token"})," you use the ",(0,r.jsx)(n.code,{children:"zrok"})," command-line interface to create an ",(0,r.jsx)(n.em,{children:"environment"}),". An ",(0,r.jsx)(n.em,{children:"environment"})," corresponds to a single command-line user on a specific ",(0,r.jsx)(n.em,{children:"host system"}),"."]}),"\n",(0,r.jsxs)(n.p,{children:["You create a new ",(0,r.jsx)(n.em,{children:"environment"})," by using the ",(0,r.jsx)(n.code,{children:"zrok enable"})," command."]}),"\n",(0,r.jsx)(n.h3,{id:"shares",children:"Shares"}),"\n",(0,r.jsxs)(n.p,{children:["Once you've enabled an ",(0,r.jsx)(n.em,{children:"environment"}),", you then create one or more ",(0,r.jsx)(n.em,{children:"shares"}),". Shares have either a ",(0,r.jsx)(n.em,{children:"public"})," or ",(0,r.jsx)(n.em,{children:"private"})," ",(0,r.jsx)(n.em,{children:"sharing mode"}),". ",(0,r.jsx)(n.em,{children:"Shares"})," share a specific type of resource using a ",(0,r.jsx)(n.em,{children:"backend mode"}),". As of this writing ",(0,r.jsx)(n.code,{children:"zrok"})," supports a ",(0,r.jsx)(n.code,{children:"proxy"})," ",(0,r.jsx)(n.em,{children:"backend mode"})," to share local HTTP resources as a ",(0,r.jsx)(n.em,{children:"reverse proxy"}),". ",(0,r.jsx)(n.code,{children:"zrok"})," also supports a ",(0,r.jsx)(n.code,{children:"web"})," ",(0,r.jsx)(n.em,{children:"backend mode"})," to share local file and HTML resources by enabling a basic HTTP server."]}),"\n",(0,r.jsxs)(n.p,{children:["Every ",(0,r.jsx)(n.em,{children:"share"})," is identified by a ",(0,r.jsx)(n.em,{children:"share token"}),". ",(0,r.jsx)(n.em,{children:"Public shares"})," can be accessed through either a ",(0,r.jsx)(n.em,{children:"frontend"})," instance offered through the ",(0,r.jsx)(n.code,{children:"zrok"})," ",(0,r.jsx)(n.em,{children:"instance"}),", or through the ",(0,r.jsx)(n.code,{children:"zrok access"})," command. ",(0,r.jsx)(n.em,{children:"Private shares"})," can only be accessed through the ",(0,r.jsx)(n.code,{children:"zrok access"})," command."]}),"\n",(0,r.jsxs)(n.p,{children:["You use the ",(0,r.jsx)(n.code,{children:"zrok share"})," command to create and enable ",(0,r.jsx)(n.em,{children:"ephemeral shares"}),"."]}),"\n",(0,r.jsx)(n.h3,{id:"reserved-shares-1",children:"Reserved Shares"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"zrok"})," supports creating ",(0,r.jsx)(n.em,{children:"shares"})," that have a consistent ",(0,r.jsx)(n.em,{children:"share token"})," that survives restarts of the ",(0,r.jsx)(n.code,{children:"zrok share"})," command. These are considered ",(0,r.jsx)(n.em,{children:"non-ephemeral"}),", and is callled a ",(0,r.jsx)(n.em,{children:"reserved share"}),"."]}),"\n",(0,r.jsxs)(n.p,{children:["You use the ",(0,r.jsx)(n.code,{children:"zrok reserve"})," command to create ",(0,r.jsx)(n.em,{children:"reserved shares"}),". Reserved shares last until you use the ",(0,r.jsx)(n.code,{children:"zrok release"})," command to delete them."]}),"\n",(0,r.jsx)(n.h2,{id:"self-hosting-an-instance",children:"Self-Hosting an Instance"}),"\n",(0,r.jsxs)(n.p,{children:["Interested in self-hosting your own ",(0,r.jsx)(n.code,{children:"zrok"})," instance? See the ",(0,r.jsx)(n.a,{href:"/docs/guides/self-hosting/self_hosting_guide",children:"self-hosting guide"})," for details."]})]})}function x(e={}){const{wrapper:n}={...(0,i.a)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(u,{...e})}):u(e)}},4908:(e,n,s)=>{s.d(n,{L:()=>t,N:()=>a});var r=s(7294),i=s(5893);const o=(0,r.createContext)([]),t=()=>(0,r.useContext)(o),a=e=>{let{children:n}=e;const[s,t]=(0,r.useState)([]);return(0,r.useEffect)((()=>{(async()=>{try{const e=await fetch("https://api.github.com/repos/openziti/zrok/releases/latest");if(!e.ok)throw new Error(`HTTP error! status: ${e.status}`);const n=(await e.json()).assets.map((e=>({name:e.name,url:e.browser_download_url,arch:e.name.replace(".tar.gz","").split("_")[3]})));console.log("Fetched assets:",n),t(n)}catch(e){console.error("Error fetching the release assets:",e)}})()}),[]),(0,i.jsx)(o.Provider,{value:s,children:n})}},3298:(e,n,s)=>{s.d(n,{Z:()=>c});s(7294);var r=s(4908),i=s(7597),o=s(2949),t=s(5893);const a=e=>{switch(e){case"amd64":return"x86_64";case"arm64":return"ARM64";case"armv7":return"ARM";default:return e.toUpperCase()}},c=e=>{let{osName:n,osLogo:s,infoText:c,guideLink:d}=e;const{colorMode:l}=(0,o.I)(),h=(0,r.L)();console.log("Assets in DownloadCard:",h);const m=(e=>{switch(e){case"Windows":return"windows";case"macOS":return"darwin";case"Linux":return"linux";default:return""}})(n),u=h.filter((e=>e.name.includes(m)));return console.log("Filtered assets for",n,"in DownloadCard:",u),(0,t.jsxs)("div",{className:i.Z.downloadCard,children:[(0,t.jsx)("div",{className:i.Z.imgContainer,children:(0,t.jsx)("img",{src:s,alt:`${n} logo`})}),(0,t.jsx)("h3",{children:n}),u.length>0&&(0,t.jsx)("ul",{children:u.map(((e,n)=>(0,t.jsx)("li",{className:i.Z.downloadButtons,children:(0,t.jsx)("a",{href:e.url,className:i.Z.downloadLinks,children:a(e.arch)})},n)))}),d&&(0,t.jsxs)("div",{className:i.Z.cardFooter,children:[(0,t.jsx)("p",{children:c}),(0,t.jsx)("a",{href:d,children:"GUIDE"}),(0,t.jsx)("p",{})]})]})}},7597:(e,n,s)=>{s.d(n,{Z:()=>r});const r={downloadContainer:"downloadContainer_nNgj",downloadCard:"downloadCard_D_EY",cardFooter:"cardFooter_Rhom",downloadButtons:"downloadButtons_NPAP",downloadLinks:"downloadLinks_thSu",imgContainer:"imgContainer_r0QA"}},9042:(e,n,s)=>{s.d(n,{Z:()=>r});const r=s.p+"assets/images/zrok_enable_modal-45da63a6907e930daaa4c798272ce5fa.png"},5724:(e,n,s)=>{s.d(n,{Z:()=>r});const r=s.p+"assets/images/zrok_not_found-fa3415937c341eb10e1eb98c9b063583.png"},242:(e,n,s)=>{s.d(n,{Z:()=>r});const r=s.p+"assets/images/zrok_registration_success-05e7e328284f6dc38cd993322698d38b.png"},7369:(e,n,s)=>{s.d(n,{Z:()=>r});const r=s.p+"assets/images/zrok_reserved_not_found-2519707e5cc3e635b7a6feb381c1d040.png"},1577:(e,n,s)=>{s.d(n,{Z:()=>r});const r=s.p+"assets/images/zrok_share_reserved-6bce67775ce2c41abb0ef13ee1fad972.png"},9744:(e,n,s)=>{s.d(n,{Z:()=>r});const r=s.p+"assets/images/zrok_verify-22a26d401b9a77a4278f3c0f54d2a981.png"},2945:(e,n,s)=>{s.d(n,{Z:()=>r});const r=s.p+"assets/images/zrok_web_console_empty-cce147eaf8e7bc83abe556336a4aea98.png"},9737:(e,n,s)=>{s.d(n,{Z:()=>r});const r=s.p+"assets/images/zrok_web_console_environment_spark-925c0709ed7a42f0a708ab0523cdeb5f.png"},6097:(e,n,s)=>{s.d(n,{Z:()=>r});const r=s.p+"assets/images/zrok_web_console_explorer_share-11236f68819da60014d5444e7429c189.png"},4647:(e,n,s)=>{s.d(n,{Z:()=>r});const r=s.p+"assets/images/zrok_web_console_share_detail-efeaa472d5e5c225a160f6d5647086b3.png"},6254:(e,n,s)=>{s.d(n,{Z:()=>r});const r=s.p+"assets/images/zrok_web_console_share_frontend-d7c0d6495493c00b94ae237339f2dc2d.png"},9509:(e,n,s)=>{s.d(n,{Z:()=>r});const r=s.p+"assets/images/zrok_web_login-a6161cc79e66932fab76994bdfb8f9c1.png"},2534:(e,n,s)=>{s.d(n,{Z:()=>r});const r=s.p+"assets/images/zrok_web_ui_empty_environment_detail-153c921ade86f924079947b0f734e3ff.png"},3858:(e,n,s)=>{s.d(n,{Z:()=>r});const r=s.p+"assets/images/zrok_web_ui_empty_shares-048c08c18477bcabb9fa8c1b58537012.png"},5546:(e,n,s)=>{s.d(n,{Z:()=>r});const r=s.p+"assets/images/zrok_web_ui_new_environment-414d8e8fc25b09f257cb40ba47d6acbb.png"},3843:(e,n,s)=>{s.d(n,{Z:()=>r});const r="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAZCAIAAACpVwlNAAAEr2lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNS41LjAiPgogPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iCiAgICB4bWxuczpleGlmPSJodHRwOi8vbnMuYWRvYmUuY29tL2V4aWYvMS4wLyIKICAgIHhtbG5zOnBob3Rvc2hvcD0iaHR0cDovL25zLmFkb2JlLmNvbS9waG90b3Nob3AvMS4wLyIKICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIKICAgIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIgogICAgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIKICAgdGlmZjpJbWFnZUxlbmd0aD0iMjUiCiAgIHRpZmY6SW1hZ2VXaWR0aD0iMzAiCiAgIHRpZmY6UmVzb2x1dGlvblVuaXQ9IjIiCiAgIHRpZmY6WFJlc29sdXRpb249Ijk2LzEiCiAgIHRpZmY6WVJlc29sdXRpb249Ijk2LzEiCiAgIGV4aWY6UGl4ZWxYRGltZW5zaW9uPSIzMCIKICAgZXhpZjpQaXhlbFlEaW1lbnNpb249IjI1IgogICBleGlmOkNvbG9yU3BhY2U9IjEiCiAgIHBob3Rvc2hvcDpDb2xvck1vZGU9IjMiCiAgIHBob3Rvc2hvcDpJQ0NQcm9maWxlPSJzUkdCIElFQzYxOTY2LTIuMSIKICAgeG1wOk1vZGlmeURhdGU9IjIwMjMtMDEtMTlUMTA6NTY6NTYtMDU6MDAiCiAgIHhtcDpNZXRhZGF0YURhdGU9IjIwMjMtMDEtMTlUMTA6NTY6NTYtMDU6MDAiPgogICA8eG1wTU06SGlzdG9yeT4KICAgIDxyZGY6U2VxPgogICAgIDxyZGY6bGkKICAgICAgc3RFdnQ6YWN0aW9uPSJwcm9kdWNlZCIKICAgICAgc3RFdnQ6c29mdHdhcmVBZ2VudD0iQWZmaW5pdHkgUGhvdG8gMi4wLjMiCiAgICAgIHN0RXZ0OndoZW49IjIwMjMtMDEtMTlUMTA6NTY6NTYtMDU6MDAiLz4KICAgIDwvcmRmOlNlcT4KICAgPC94bXBNTTpIaXN0b3J5PgogIDwvcmRmOkRlc2NyaXB0aW9uPgogPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KPD94cGFja2V0IGVuZD0iciI/Pq+HLHgAAAGBaUNDUHNSR0IgSUVDNjE5NjYtMi4xAAAokXWRy0tCQRSHP7UwemBQixYtJKyVRg8Q27RQyoJqYQZZbfTmI/BxuVcJaRu0FQqiNr0W9RfUNmgdBEURRNtaF7UpuZ2rghF5hjnzzW/OOcycAWs4rWT0piHIZPNaKOh3LkaWnPYXLHThwIclqujq7PxkmIb2eS/RYrces1bjuH+tbTWuK2BpER5XVC0vPCU8s55XTd4R7lZS0VXhM2G3JhcUvjP1WJVfTU5W+dtkLRwKgLVT2Jn8xbFfrKS0jLC8HFcmXVBq9zFf0h7PLszL2iezF50QQfw4mWaCAF6GGRPvxcMIg7KjQf5QJX+OnOQq4lWKaKyRJEUet6gFqR6XNSF6XEaaotn/v33VE6Mj1ertfmh+Noz3frBvQ7lkGF9HhlE+BtsTXGbr+blD8H2IXqprrgNwbML5VV2L7cLFFvQ8qlEtWpFsMq2JBLydQkcEum6gdbnas9o5Jw8Q3pCvuoa9fRiQeMfKD2DYZ+PDGzxnAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABZklEQVRIie2VvW7CMBDHr1UfwE5fII7lvahIWUEiQ7qxMLEwsVQMSB0YKsTExsDGxFs0QyqlYyMVld3k4wWw/QgMlqp+JXFQGZB649n3k+9/f9sX9w+PcJq4PBH3H/0zrkrWfK99jVF5/V6qIIzqod1m485rC6nK0S5GAPArvRDNHFtINZ0vviQp4Un2OTObjIs6q6G122yMhgPfaxvuN0VbGDHHBgDm2FbVAGqgLYyEVPFmCwDB84uQilHyB2i32ej3uoySvZDT+YInGaPE77QqlSkznz5vv9cFAEbJdL4QUlkYjYYDnYnf3o9HC6mewog5ttZBq7xcrf1OK95sy61ZgQaAIIx2lGgdRsPBcrXmSbYXstLyRmPkSWZh5HdaAODe3uipVlaZmk9IxdMcAHiam3DBRJCPCMJol+bfbuMxaJ7mjJLZZFxeb2Gku6mDTrJXjExeviILFqJF8WtpGOf5y5wn+gBcXI4F9z6rgwAAAABJRU5ErkJggg=="},1151:(e,n,s)=>{s.d(n,{Z:()=>a,a:()=>t});var r=s(7294);const i={},o=r.createContext(i);function t(e){const n=r.useContext(o);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:t(e.components),r.createElement(o.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/runtime~main.9d1d99d1.js b/assets/js/runtime~main.864ff98b.js similarity index 96% rename from assets/js/runtime~main.9d1d99d1.js rename to assets/js/runtime~main.864ff98b.js index 7ed9a79a..f0922446 100644 --- a/assets/js/runtime~main.9d1d99d1.js +++ b/assets/js/runtime~main.864ff98b.js @@ -1 +1 @@ -(()=>{"use strict";var e,a,t,r,b,f={},d={};function c(e){var a=d[e];if(void 0!==a)return a.exports;var t=d[e]={id:e,loaded:!1,exports:{}};return f[e].call(t.exports,t,t.exports,c),t.loaded=!0,t.exports}c.m=f,c.c=d,c.amdO={},e=[],c.O=(a,t,r,b)=>{if(!t){var f=1/0;for(i=0;i=b)&&Object.keys(c.O).every((e=>c.O[e](t[o])))?t.splice(o--,1):(d=!1,b0&&e[i-1][2]>b;i--)e[i]=e[i-1];e[i]=[t,r,b]},c.n=e=>{var a=e&&e.__esModule?()=>e.default:()=>e;return c.d(a,{a:a}),a},t=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,c.t=function(e,r){if(1&r&&(e=this(e)),8&r)return e;if("object"==typeof e&&e){if(4&r&&e.__esModule)return e;if(16&r&&"function"==typeof e.then)return e}var b=Object.create(null);c.r(b);var f={};a=a||[null,t({}),t([]),t(t)];for(var d=2&r&&e;"object"==typeof d&&!~a.indexOf(d);d=t(d))Object.getOwnPropertyNames(d).forEach((a=>f[a]=()=>e[a]));return f.default=()=>e,c.d(b,f),b},c.d=(e,a)=>{for(var t in a)c.o(a,t)&&!c.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:a[t]})},c.f={},c.e=e=>Promise.all(Object.keys(c.f).reduce(((a,t)=>(c.f[t](e,a),a)),[])),c.u=e=>"assets/js/"+({22:"0654c903",53:"935f2afb",55:"613b9d03",76:"2e812224",108:"288b1075",142:"1ba5bc99",176:"6272ba0e",182:"6e881e32",195:"c4f5d8e4",196:"bbbe662c",198:"50ef9c44",209:"881eafa3",212:"8ae7f3b1",318:"8ef4b25e",327:"c304be44",360:"34e1d3b9",364:"60d45520",368:"a94703ab",402:"5b30ef33",518:"a7bd4aaa",661:"5e95c892",711:"9a9d4214",732:"c015c796",817:"14eb3368",826:"47881d5c",828:"48230885",838:"75b20590",846:"cda0d2e5",848:"e6ffb4b4",889:"339d500a",900:"600b2345",905:"07d0b302",913:"b6569025",918:"17896441",920:"1a4e3797",938:"f888b719",945:"bc747cac",992:"f2348458",993:"5cd0a723"}[e]||e)+"."+{22:"ac088efe",53:"f51daa1e",55:"70520b78",76:"cf9aefef",108:"eff043f2",142:"b4a62798",174:"fe0b453b",176:"ec9db412",182:"b57731c8",195:"de5bd68b",196:"04415d84",198:"5f645387",209:"b2106c29",212:"e3f6a489",272:"4ca67fd7",312:"6bef50b5",318:"6f594527",327:"2d7a313b",360:"d227e965",364:"b80527ca",368:"39fcc647",402:"60970f99",426:"2f87c2a8",518:"f24b7b2f",661:"60e060ab",711:"1eaae2f3",732:"c8651f34",772:"d157f111",817:"a4d63d2b",826:"ae1dcb33",828:"4fdb4d08",838:"10625895",846:"e7881b13",848:"45c4cedd",889:"5d4c822f",894:"e787cecf",900:"d3eef0d4",905:"2ee3176b",913:"a6bd5acc",918:"498f0659",920:"f84acc88",938:"d6459e38",945:"94614e47",969:"ba5129f7",992:"46b5aa6d",993:"89693635"}[e]+".js",c.miniCssF=e=>{},c.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),c.o=(e,a)=>Object.prototype.hasOwnProperty.call(e,a),r={},b="website:",c.l=(e,a,t,f)=>{if(r[e])r[e].push(a);else{var d,o;if(void 0!==t)for(var n=document.getElementsByTagName("script"),i=0;i{d.onerror=d.onload=null,clearTimeout(s);var b=r[e];if(delete r[e],d.parentNode&&d.parentNode.removeChild(d),b&&b.forEach((e=>e(t))),a)return a(t)},s=setTimeout(l.bind(null,void 0,{type:"timeout",target:d}),12e4);d.onerror=l.bind(null,d.onerror),d.onload=l.bind(null,d.onload),o&&document.head.appendChild(d)}},c.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},c.p="/",c.gca=function(e){return e={17896441:"918",48230885:"828","0654c903":"22","935f2afb":"53","613b9d03":"55","2e812224":"76","288b1075":"108","1ba5bc99":"142","6272ba0e":"176","6e881e32":"182",c4f5d8e4:"195",bbbe662c:"196","50ef9c44":"198","881eafa3":"209","8ae7f3b1":"212","8ef4b25e":"318",c304be44:"327","34e1d3b9":"360","60d45520":"364",a94703ab:"368","5b30ef33":"402",a7bd4aaa:"518","5e95c892":"661","9a9d4214":"711",c015c796:"732","14eb3368":"817","47881d5c":"826","75b20590":"838",cda0d2e5:"846",e6ffb4b4:"848","339d500a":"889","600b2345":"900","07d0b302":"905",b6569025:"913","1a4e3797":"920",f888b719:"938",bc747cac:"945",f2348458:"992","5cd0a723":"993"}[e]||e,c.p+c.u(e)},(()=>{var e={303:0,532:0};c.f.j=(a,t)=>{var r=c.o(e,a)?e[a]:void 0;if(0!==r)if(r)t.push(r[2]);else if(/^(303|532)$/.test(a))e[a]=0;else{var b=new Promise(((t,b)=>r=e[a]=[t,b]));t.push(r[2]=b);var f=c.p+c.u(a),d=new Error;c.l(f,(t=>{if(c.o(e,a)&&(0!==(r=e[a])&&(e[a]=void 0),r)){var b=t&&("load"===t.type?"missing":t.type),f=t&&t.target&&t.target.src;d.message="Loading chunk "+a+" failed.\n("+b+": "+f+")",d.name="ChunkLoadError",d.type=b,d.request=f,r[1](d)}}),"chunk-"+a,a)}},c.O.j=a=>0===e[a];var a=(a,t)=>{var r,b,f=t[0],d=t[1],o=t[2],n=0;if(f.some((a=>0!==e[a]))){for(r in d)c.o(d,r)&&(c.m[r]=d[r]);if(o)var i=o(c)}for(a&&a(t);n{"use strict";var e,a,t,r,b,f={},d={};function c(e){var a=d[e];if(void 0!==a)return a.exports;var t=d[e]={id:e,loaded:!1,exports:{}};return f[e].call(t.exports,t,t.exports,c),t.loaded=!0,t.exports}c.m=f,c.c=d,c.amdO={},e=[],c.O=(a,t,r,b)=>{if(!t){var f=1/0;for(i=0;i=b)&&Object.keys(c.O).every((e=>c.O[e](t[o])))?t.splice(o--,1):(d=!1,b0&&e[i-1][2]>b;i--)e[i]=e[i-1];e[i]=[t,r,b]},c.n=e=>{var a=e&&e.__esModule?()=>e.default:()=>e;return c.d(a,{a:a}),a},t=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,c.t=function(e,r){if(1&r&&(e=this(e)),8&r)return e;if("object"==typeof e&&e){if(4&r&&e.__esModule)return e;if(16&r&&"function"==typeof e.then)return e}var b=Object.create(null);c.r(b);var f={};a=a||[null,t({}),t([]),t(t)];for(var d=2&r&&e;"object"==typeof d&&!~a.indexOf(d);d=t(d))Object.getOwnPropertyNames(d).forEach((a=>f[a]=()=>e[a]));return f.default=()=>e,c.d(b,f),b},c.d=(e,a)=>{for(var t in a)c.o(a,t)&&!c.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:a[t]})},c.f={},c.e=e=>Promise.all(Object.keys(c.f).reduce(((a,t)=>(c.f[t](e,a),a)),[])),c.u=e=>"assets/js/"+({22:"0654c903",53:"935f2afb",55:"613b9d03",76:"2e812224",108:"288b1075",142:"1ba5bc99",176:"6272ba0e",182:"6e881e32",195:"c4f5d8e4",196:"bbbe662c",198:"50ef9c44",209:"881eafa3",212:"8ae7f3b1",318:"8ef4b25e",327:"c304be44",360:"34e1d3b9",364:"60d45520",368:"a94703ab",402:"5b30ef33",518:"a7bd4aaa",661:"5e95c892",711:"9a9d4214",732:"c015c796",817:"14eb3368",826:"47881d5c",828:"48230885",838:"75b20590",846:"cda0d2e5",848:"e6ffb4b4",889:"339d500a",900:"600b2345",905:"07d0b302",913:"b6569025",918:"17896441",920:"1a4e3797",938:"f888b719",945:"bc747cac",992:"f2348458",993:"5cd0a723"}[e]||e)+"."+{22:"ac088efe",53:"f51daa1e",55:"70520b78",76:"cf9aefef",108:"eff043f2",142:"b4a62798",174:"fe0b453b",176:"ec9db412",182:"b57731c8",195:"de5bd68b",196:"04415d84",198:"5f645387",209:"b2106c29",212:"e3f6a489",272:"4ca67fd7",312:"6bef50b5",318:"6f594527",327:"2d7a313b",360:"d227e965",364:"b80527ca",368:"39fcc647",402:"60970f99",426:"2f87c2a8",518:"f24b7b2f",661:"60e060ab",711:"1eaae2f3",732:"c8651f34",772:"d157f111",817:"a4d63d2b",826:"ae1dcb33",828:"4fdb4d08",838:"10625895",846:"1b2a9583",848:"45c4cedd",889:"5d4c822f",894:"e787cecf",900:"d3eef0d4",905:"2ee3176b",913:"a6bd5acc",918:"498f0659",920:"f84acc88",938:"f45e9c0f",945:"94614e47",969:"ba5129f7",992:"46b5aa6d",993:"89693635"}[e]+".js",c.miniCssF=e=>{},c.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),c.o=(e,a)=>Object.prototype.hasOwnProperty.call(e,a),r={},b="website:",c.l=(e,a,t,f)=>{if(r[e])r[e].push(a);else{var d,o;if(void 0!==t)for(var n=document.getElementsByTagName("script"),i=0;i{d.onerror=d.onload=null,clearTimeout(s);var b=r[e];if(delete r[e],d.parentNode&&d.parentNode.removeChild(d),b&&b.forEach((e=>e(t))),a)return a(t)},s=setTimeout(l.bind(null,void 0,{type:"timeout",target:d}),12e4);d.onerror=l.bind(null,d.onerror),d.onload=l.bind(null,d.onload),o&&document.head.appendChild(d)}},c.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},c.p="/",c.gca=function(e){return e={17896441:"918",48230885:"828","0654c903":"22","935f2afb":"53","613b9d03":"55","2e812224":"76","288b1075":"108","1ba5bc99":"142","6272ba0e":"176","6e881e32":"182",c4f5d8e4:"195",bbbe662c:"196","50ef9c44":"198","881eafa3":"209","8ae7f3b1":"212","8ef4b25e":"318",c304be44:"327","34e1d3b9":"360","60d45520":"364",a94703ab:"368","5b30ef33":"402",a7bd4aaa:"518","5e95c892":"661","9a9d4214":"711",c015c796:"732","14eb3368":"817","47881d5c":"826","75b20590":"838",cda0d2e5:"846",e6ffb4b4:"848","339d500a":"889","600b2345":"900","07d0b302":"905",b6569025:"913","1a4e3797":"920",f888b719:"938",bc747cac:"945",f2348458:"992","5cd0a723":"993"}[e]||e,c.p+c.u(e)},(()=>{var e={303:0,532:0};c.f.j=(a,t)=>{var r=c.o(e,a)?e[a]:void 0;if(0!==r)if(r)t.push(r[2]);else if(/^(303|532)$/.test(a))e[a]=0;else{var b=new Promise(((t,b)=>r=e[a]=[t,b]));t.push(r[2]=b);var f=c.p+c.u(a),d=new Error;c.l(f,(t=>{if(c.o(e,a)&&(0!==(r=e[a])&&(e[a]=void 0),r)){var b=t&&("load"===t.type?"missing":t.type),f=t&&t.target&&t.target.src;d.message="Loading chunk "+a+" failed.\n("+b+": "+f+")",d.name="ChunkLoadError",d.type=b,d.request=f,r[1](d)}}),"chunk-"+a,a)}},c.O.j=a=>0===e[a];var a=(a,t)=>{var r,b,f=t[0],d=t[1],o=t[2],n=0;if(f.some((a=>0!==e[a]))){for(r in d)c.o(d,r)&&(c.m[r]=d[r]);if(o)var i=o(c)}for(a&&a(t);n