"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[759],{3905:(e,t,n)=>{n.d(t,{Zo:()=>c,kt:()=>m});var r=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function a(e){for(var t=1;t=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var s=r.createContext({}),p=function(e){var t=r.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):a(a({},t),e)),n},c=function(e){var t=p(e.components);return r.createElement(s.Provider,{value:t},e.children)},d="mdxType",u={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},k=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,i=e.originalType,s=e.parentName,c=l(e,["components","mdxType","originalType","parentName"]),d=p(n),k=o,m=d["".concat(s,".").concat(k)]||d[k]||u[k]||i;return n?r.createElement(m,a(a({ref:t},c),{},{components:n})):r.createElement(m,a({ref:t},c))}));function m(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var i=n.length,a=new Array(i);a[0]=k;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l[d]="string"==typeof e?e:o,a[1]=l;for(var p=2;p{n.r(t),n.d(t,{assets:()=>s,contentTitle:()=>a,default:()=>d,frontMatter:()=>i,metadata:()=>l,toc:()=>p});var r=n(7462),o=(n(7294),n(3905));const i={},a="Self-Hosting Guide",l={unversionedId:"guides/v0.3_self_hosting_guide",id:"guides/v0.3_self_hosting_guide",title:"Self-Hosting Guide",description:"OpenZiti Quickstart",source:"@site/../docs/guides/v0.3_self_hosting_guide.md",sourceDirName:"guides",slug:"/guides/v0.3_self_hosting_guide",permalink:"/docs/guides/v0.3_self_hosting_guide",draft:!1,editUrl:"https://github.com/openziti/zrok/tree/main/../docs/guides/v0.3_self_hosting_guide.md",tags:[],version:"current",frontMatter:{},sidebar:"tutorialSidebar",previous:{title:"Nginx Reverse Proxy for zrok",permalink:"/docs/guides/v0.3_nginx_tls_guide"},next:{title:"Downloads",permalink:"/docs/downloads"}},s={},p=[{value:"OpenZiti Quickstart",id:"openziti-quickstart",level:2},{value:"Configure the Controller",id:"configure-the-controller",level:2},{value:"Environment Variables",id:"environment-variables",level:2},{value:"Bootstrap OpenZiti for zrok",id:"bootstrap-openziti-for-zrok",level:2},{value:"Configure the Public Frontend",id:"configure-the-public-frontend",level:2},{value:"Start Public Frontend",id:"start-public-frontend",level:2},{value:"Invite Yourself",id:"invite-yourself",level:2},{value:"Enable Your Shell",id:"enable-your-shell",level:2}],c={toc:p};function d(e){let{components:t,...n}=e;return(0,o.kt)("wrapper",(0,r.Z)({},c,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h1",{id:"self-hosting-guide"},"Self-Hosting Guide"),(0,o.kt)("h2",{id:"openziti-quickstart"},"OpenZiti Quickstart"),(0,o.kt)("p",null,(0,o.kt)("a",{parentName:"p",href:"https://openziti.github.io/docs/quickstarts/network/"},"https://openziti.github.io/docs/quickstarts/network/")),(0,o.kt)("p",null,'I specifically used the "no docker" variant:'),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},'$ source /dev/stdin <<< "$(wget -qO- https://get.openziti.io/quick/ziti-cli-functions.sh)"; expressInstall\n$ startController\n$ startRouter\n')),(0,o.kt)("p",null,"Keep track of the generated admin password when running the ",(0,o.kt)("inlineCode",{parentName:"p"},"expressInstall")," script. The script will prompt you like this:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"Do you want to keep the generated admin password 'XO0xHp75uuyeireO2xmmVlK91T7B9fpD'? (Y/n)\n")),(0,o.kt)("p",null,"You'll need that generated password (",(0,o.kt)("inlineCode",{parentName:"p"},"XO0xHp75uuyeireO2xmmVlK91T7B9fpD"),") when building your ",(0,o.kt)("inlineCode",{parentName:"p"},"zrok")," controller configuration."),(0,o.kt)("h2",{id:"configure-the-controller"},"Configure the Controller"),(0,o.kt)("p",null,"Create a controller configuration file in ",(0,o.kt)("inlineCode",{parentName:"p"},"etc/ctrl.yml"),". The controller does not provide server TLS, but you may front the server with a reverse proxy. This example will expose the non-TLS listener for the controller."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-yaml"},'# _____ __ ___ | | __\n# |_ / \'__/ _ \\| |/ /\n# / /| | | (_) | <\n# /___|_| \\___/|_|\\_\\\n# controller configuration\n\nv: 1\n\nadmin:\n secrets:\n - f60b55fa-4dec-4c4a-9244-e3b7d6b9bb13\n\nendpoint:\n host: 0.0.0.0\n port: 18080\n\nstore:\n path: zrok.db\n type: sqlite3\n\nziti:\n api_endpoint: "https://127.0.0.1:1280"\n username: admin\n password: "XO0xHp75uuyeireO2xmmVlK91T7B9fpD"\n\n')),(0,o.kt)("p",null,"The ",(0,o.kt)("inlineCode",{parentName:"p"},"admin")," section defines privileged administrative credentials and must be set in the ",(0,o.kt)("inlineCode",{parentName:"p"},"ZROK_ADMIN_TOKEN")," environment variable in shells where you want to run ",(0,o.kt)("inlineCode",{parentName:"p"},"zrok admin"),"."),(0,o.kt)("p",null,"The ",(0,o.kt)("inlineCode",{parentName:"p"},"endpoint")," section defines where your ",(0,o.kt)("inlineCode",{parentName:"p"},"zrok")," controller will listen. "),(0,o.kt)("p",null,"The ",(0,o.kt)("inlineCode",{parentName:"p"},"store")," section defines the local ",(0,o.kt)("inlineCode",{parentName:"p"},"sqlite3")," database used by the controller."),(0,o.kt)("p",null,"The ",(0,o.kt)("inlineCode",{parentName:"p"},"ziti")," section defines how the ",(0,o.kt)("inlineCode",{parentName:"p"},"zrok")," controller should communicate with your OpenZiti installation. When using the OpenZiti quickstart, an administrative password will be generated; the ",(0,o.kt)("inlineCode",{parentName:"p"},"password")," in the ",(0,o.kt)("inlineCode",{parentName:"p"},"ziti")," stanza should reflect this password."),(0,o.kt)("h2",{id:"environment-variables"},"Environment Variables"),(0,o.kt)("p",null,"The ",(0,o.kt)("inlineCode",{parentName:"p"},"zrok")," binaries are configured to work with the global ",(0,o.kt)("inlineCode",{parentName:"p"},"zrok.io")," service, and default to using ",(0,o.kt)("inlineCode",{parentName:"p"},"api.zrok.io")," as the endpoint for communicating with the service."),(0,o.kt)("p",null,"To work with a local ",(0,o.kt)("inlineCode",{parentName:"p"},"zrok")," deployment, you'll need to set the ",(0,o.kt)("inlineCode",{parentName:"p"},"ZROK_API_ENDPOINT")," environment variable to point to the address where your ",(0,o.kt)("inlineCode",{parentName:"p"},"zrok")," controller will be listening, according to ",(0,o.kt)("inlineCode",{parentName:"p"},"endpoint")," in the configuration file above."),(0,o.kt)("p",null,"In my case, I've set:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"$ export ZROK_API_ENDPOINT=http://localhost:18080\n")),(0,o.kt)("h2",{id:"bootstrap-openziti-for-zrok"},"Bootstrap OpenZiti for zrok"),(0,o.kt)("p",null,"With your OpenZiti network running and your configuration saved to a local file (I refer to mine as ",(0,o.kt)("inlineCode",{parentName:"p"},"etc/ctrl.yml")," in these examples), you're ready to bootstrap the Ziti network."),(0,o.kt)("p",null,"Use the ",(0,o.kt)("inlineCode",{parentName:"p"},"zrok admin bootstrap")," command to bootstrap like this:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"$ zrok admin bootstrap etc/ctrl.yml \n[ 0.002] INFO main.(*adminBootstrap).run: {\n ...\n}\n[ 0.002] INFO zrok/controller/store.Open: database connected\n[ 0.006] INFO zrok/controller/store.(*Store).migrate: applied 0 migrations\n[ 0.006] INFO zrok/controller.Bootstrap: connecting to the ziti edge management api\n[ 0.039] INFO zrok/controller.Bootstrap: creating identity for controller ziti access\n[ 0.071] INFO zrok/controller.Bootstrap: controller identity: jKd8AINSz\n[ 0.082] INFO zrok/controller.assertIdentity: asserted identity 'jKd8AINSz'\n[ 0.085] INFO zrok/controller.assertErpForIdentity: asserted erps for 'ctrl' (jKd8AINSz)\n[ 0.085] INFO zrok/controller.Bootstrap: creating identity for frontend ziti access\n[ 0.118] INFO zrok/controller.Bootstrap: frontend identity: sqJRAINSiB\n[ 0.119] INFO zrok/controller.assertIdentity: asserted identity 'sqJRAINSiB'\n[ 0.120] INFO zrok/controller.assertErpForIdentity: asserted erps for 'frontend' (sqJRAINSiB)\n[ 0.120] WARNING zrok/controller.Bootstrap: missing public frontend for ziti id 'sqJRAINSiB'; please use 'zrok admin create frontend sqJRAINSiB public https://{token}.your.dns.name' to create a frontend instance\n[ 0.123] INFO zrok/controller.assertZrokProxyConfigType: found 'zrok.proxy.v1' config type with id '33CyjNbIepkXHN5VzGDA8L'\n[ 0.124] INFO zrok/controller.assertMetricsService: creating 'metrics' service\n[ 0.126] INFO zrok/controller.assertMetricsService: asserted 'metrics' service (5RpPZZ7T8bZf1ENjwGiPc3)\n[ 0.128] INFO zrok/controller.assertMetricsSerp: creating 'metrics' serp\n[ 0.130] INFO zrok/controller.assertMetricsSerp: asserted 'metrics' serp\n[ 0.134] INFO zrok/controller.assertCtrlMetricsBind: creating 'ctrl-metrics-bind' service policy\n[ 0.135] INFO zrok/controller.assertCtrlMetricsBind: asserted 'ctrl-metrics-bind' service policy\n[ 0.138] INFO zrok/controller.assertFrontendMetricsDial: creating 'frontend-metrics-dial' service policy\n[ 0.140] INFO zrok/controller.assertFrontendMetricsDial: asserted 'frontend-metrics-dial' service policy\n[ 0.140] INFO main.(*adminBootstrap).run: bootstrap complete!\n")),(0,o.kt)("p",null,"The ",(0,o.kt)("inlineCode",{parentName:"p"},"zrok admin bootstrap")," command configures the ",(0,o.kt)("inlineCode",{parentName:"p"},"zrok")," database, the necessary OpenZiti identities, and all of the OpenZiti policies required to run a ",(0,o.kt)("inlineCode",{parentName:"p"},"zrok")," service."),(0,o.kt)("p",null,"Notice this warning:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"[ 0.120] WARNING zrok/controller.Bootstrap: missing public frontend for ziti id 'sqJRAINSiB'; please use 'zrok admin create frontend sqJRAINSiB public https://{token}.your.dns.name' to create a frontend instance\n")),(0,o.kt)("p",null,"The ",(0,o.kt)("inlineCode",{parentName:"p"},"zrok"),' bootstrap process wants us to create a "public frontend" for our service. ',(0,o.kt)("inlineCode",{parentName:"p"},"zrok")," uses public frontends to allow users to specify where they would like public traffic to ingress from."),(0,o.kt)("p",null,"The ",(0,o.kt)("inlineCode",{parentName:"p"},"zrok admin create frontend")," command requires a running ",(0,o.kt)("inlineCode",{parentName:"p"},"zrok")," controller, so let's start that up first:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"$ zrok controller etc/ctrl.yml \n[ 0.003] INFO main.(*controllerCommand).run: {\n ...\n}\n[ 0.016] INFO zrok/controller.inspectZiti: inspecting ziti controller configuration\n[ 0.048] INFO zrok/controller.findZrokProxyConfigType: found 'zrok.proxy.v1' config type with id '33CyjNbIepkXHN5VzGDA8L'\n[ 0.048] INFO zrok/controller/store.Open: database connected\n[ 0.048] INFO zrok/controller/store.(*Store).migrate: applied 0 migrations\n[ 0.049] INFO zrok/controller.(*metricsAgent).run: starting\n[ 0.064] INFO zrok/rest_server_zrok.setupGlobalMiddleware: configuring\n[ 0.064] INFO zrok/ui.StaticBuilder: building\n[ 0.065] INFO zrok/rest_server_zrok.(*Server).Logf: Serving zrok at http://[::]:18080\n[ 0.085] INFO zrok/controller.(*metricsAgent).listen: started\n")),(0,o.kt)("p",null,"With our ",(0,o.kt)("inlineCode",{parentName:"p"},"ZROK_ADMIN_TOKEN")," and ",(0,o.kt)("inlineCode",{parentName:"p"},"ZROK_API_ENDPOINT")," environment variables set, we can create our public frontend like this:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"$ zrok admin create frontend sqJRAINSiB public http://{token}.zrok.quigley.com:8080\n[ 0.037] INFO main.(*adminCreateFrontendCommand).run: created global public frontend 'WEirJNHVlcW9'\n")),(0,o.kt)("p",null,"Now our ",(0,o.kt)("inlineCode",{parentName:"p"},"zrok")," controller is fully configured."),(0,o.kt)("h2",{id:"configure-the-public-frontend"},"Configure the Public Frontend"),(0,o.kt)("p",null,"Create ",(0,o.kt)("inlineCode",{parentName:"p"},"etc/http-frontend.yml"),". You must reiterate the pattern you expressed in the public frontend URL template as a ",(0,o.kt)("inlineCode",{parentName:"p"},"host_match")," pattern, and you may change the default address where the frontend will listen for public access requests. The frontend does not provide server TLS, but you may front the server with a reverse proxy. It is essential the reverse proxy forwards the ",(0,o.kt)("inlineCode",{parentName:"p"},"Host")," header supplied by the viewer. This example will expose the non-TLS listener for the frontend."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-yaml"},"host_match: zrok.quigley.com\naddress: 0.0.0.0:8080\n")),(0,o.kt)("h2",{id:"start-public-frontend"},"Start Public Frontend"),(0,o.kt)("p",null,"In another terminal window, run:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"$ zrok access public etc/http-frontend.yml\n[ 0.002] INFO main.(*accessPublicCommand).run: {\n ...\n}\n[ 0.002] INFO zrok/endpoints/public_frontend.newMetricsAgent: loaded 'frontend' identity\n")),(0,o.kt)("p",null,"This process uses the ",(0,o.kt)("inlineCode",{parentName:"p"},"frontend")," identity created during the bootstrap process to provide public access for the ",(0,o.kt)("inlineCode",{parentName:"p"},"zrok")," deployment. It is expected that the configured listener for this ",(0,o.kt)("inlineCode",{parentName:"p"},"frontend")," corresponds to the DNS template specified when creating the public frontend record above."),(0,o.kt)("h2",{id:"invite-yourself"},"Invite Yourself"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"$ zrok invite\nNew Email: user@domain.com\nConfirm Email: user@domain.com\ninvitation sent to 'user@domain.com'!\n")),(0,o.kt)("p",null,"If you look at the console output from your ",(0,o.kt)("inlineCode",{parentName:"p"},"zrok")," controller, you'll see a message like this:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"[ 238.168] INFO zrok/controller.(*inviteHandler).Handle: account request for 'user@domain.com' has registration token 'U2Ewt1UCn3ql'\n")),(0,o.kt)("p",null,"You can access your ",(0,o.kt)("inlineCode",{parentName:"p"},"zrok")," controller's registration UI by pointing a web browser at:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"http://localhost:18080/register/U2Ewt1UCn3ql\n")),(0,o.kt)("p",null,"The UI will ask you to set a password for your new account. Go ahead and do that."),(0,o.kt)("p",null,"After doing that, I see the following output in my controller console:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"[ 516.778] INFO zrok/controller.(*registerHandler).Handle: created account 'user@domain.com' with token 'SuGzRPjVDIcF'\n")),(0,o.kt)("p",null,"Keep track of the token listed above (",(0,o.kt)("inlineCode",{parentName:"p"},"SuGzRPjVDIcF"),"). We'll use this to enable our shell for this ",(0,o.kt)("inlineCode",{parentName:"p"},"zrok")," deployment."),(0,o.kt)("h2",{id:"enable-your-shell"},"Enable Your Shell"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"$ zrok enable SuGzRPjVDIcF\nzrok environment '2AS1WZ3Sz' enabled for 'SuGzRPjVDIcF'\n")),(0,o.kt)("p",null,"Congratulations. You have a working ",(0,o.kt)("inlineCode",{parentName:"p"},"zrok")," environment!"))}d.isMDXComponent=!0}}]);