<!doctype html><htmllang=enclass=no-js><head><metacharset=utf-8><metaname=viewportcontent="width=device-width,initial-scale=1"><metaname=descriptioncontent="An open source, self-hosted implementation of the Tailscale control server."><metaname=authorcontent="Headscale authors"><linkhref=https://juanfont.github.io/headscale/development/ref/remote-cli/rel=canonical><linkhref=../dns/rel=prev><linkhref=../integration/reverse-proxy/rel=next><linkrel=iconhref=../../assets/favicon.png><metaname=generatorcontent="mkdocs-1.6.1, mkdocs-material-9.5.49"><title>Remote CLI - Headscale</title><linkrel=stylesheethref=../../assets/stylesheets/main.6f8fc17f.min.css><linkrel=stylesheethref=../../assets/stylesheets/palette.06af60db.min.css><linkrel=preconnecthref=https://fonts.gstatic.comcrossorigin><linkrel=stylesheethref="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback"><style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style><script>__md_scope=newURL("../..",location),__md_hash=e=>[...e].reduce(((e,_)=>(e<<5)-e+_.charCodeAt(0)),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script><metaproperty=og:typecontent=website><metaproperty=og:titlecontent="Remote CLI - Headscale"><metaproperty=og:descriptioncontent="An open source, self-hosted implementation of the Tailscale control server."><metaproperty=og:imagecontent=https://juanfont.github.io/headscale/development/assets/images/social/ref/remote-cli.png><metaproperty=og:image:typecontent=image/png><metaproperty=og:image:widthcontent=1200><metaproperty=og:image:heightcontent=630><metacontent=https://juanfont.github.io/headscale/development/ref/remote-cli/property=og:url><metaname=twitter:cardcontent=summary_large_image><metaname=twitter:titlecontent="Remote CLI - Headscale"><metaname=twitter:descriptioncontent="An open source, self-hosted implementation of the Tailscale control server."><metaname=twitter:imagecontent=https://juanfont.github.io/headscale/development/assets/images/social/ref/remote-cli.png></head><bodydir=ltrdata-md-color-scheme=defaultdata-md-color-primary=whitedata-md-color-accent=indigo><inputclass=md-toggledata-md-toggle=drawertype=checkboxid=__drawerautocomplete=off><inputclass=md-toggledata-md-toggle=searchtype=checkboxid=__searchautocomplete=off><labelclass=md-overlayfor=__drawer></label><divdata-md-component=skip><ahref=#controlling-headscale-with-remote-cliclass=md-skip> Skip to content </a></div><divdata-md-component=announce></div><divdata-md-color-scheme=defaultdata-md-component=outdatedhidden></div><headerclass=md-headerdata-md-component=header><navclass="md-header__inner md-grid"aria-label=Header><ahref=../..title=Headscaleclass="md-header__button md-logo"aria-label=Headscaledata-md-component=logo><imgsrc=../../logo/headscale3-dots.svgalt=logo></a><labelclass="md-header__button md-icon"for=__drawer><svgxmlns=http://www.w3.org/2000/svgviewbox="0 0 24 24"><pathd="M3 6h18v2H3zm0 5h18v2H3zm0 5h18v2H3z"/></svg></label><divclass=md-header__titledata-md-component=header-title><divclass=md-header__ellipsis><divclass=md-header__topic><spanclass=md-ellipsis> Headscale </span></div><divclass=md-header__topicdata-md-component=header-topic><spanclass=md-ellipsis> Remote CLI </span></div></div></div><formclass=md-header__optiondata-md-component=palette><inputclass=md-optiondata-md-color-mediadata-md-color-scheme=defaultdata-md-color-primary=whitedata-md-color-accent=indigoaria-label="Switch to dark mode"type=radioname=__paletteid=__palette_0><labelclass="md-header__button md-icon"title="Switch to dark mode"for=__palette_1hidden><svgxmlns=http://www.w3.org/2000/svgviewbox="0 0 24 24"><pathd="M128a44000-444400044440004-444000-4-4m010a66001-6-6660016-666001
</span></code></pre></div><p>Copy the output of the command and save it for later. Please note that you can not retrieve a key again, if the key is lost, expire the old one, and create a new key.</p><p>To list the keys currently associated with the server:</p><divclass="language-shell highlight"><pre><span></span><code><spanid=__span-1-1><aid=__codelineno-1-1name=__codelineno-1-1href=#__codelineno-1-1></a>headscale<spanclass=w></span>apikeys<spanclass=w></span>list
</span></code></pre></div><p>and to expire a key:</p><divclass="language-shell highlight"><pre><span></span><code><spanid=__span-2-1><aid=__codelineno-2-1name=__codelineno-2-1href=#__codelineno-2-1></a>headscale<spanclass=w></span>apikeys<spanclass=w></span>expire<spanclass=w></span>--prefix<spanclass=w></span><spanclass=s2>"<PREFIX>"</span>
</span></code></pre></div><h2id=download-and-configure-headscale>Download and configure headscale<aclass=headerlinkhref=#download-and-configure-headscaletitle="Permanent link">¶</a></h2><ol><li><p>Download the <ahref=https://github.com/juanfont/headscale/releases><code>headscale</code> binary from GitHub's release page</a>. Make sure to use the same version as on the server.</p></li><li><p>Put the binary somewhere in your <code>PATH</code>, e.g. <code>/usr/local/bin/headscale</code></p></li><li><p>Make <code>headscale</code> executable:</p><divclass="language-shell highlight"><pre><span></span><code><spanid=__span-3-1><aid=__codelineno-3-1name=__codelineno-3-1href=#__codelineno-3-1></a>chmod<spanclass=w></span>+x<spanclass=w></span>/usr/local/bin/headscale
</span></code></pre></div></li><li><p>Provide the connection parameters for the remote headscale server either via a minimal YAML configuration file or via environment variables:</p><divclass="tabbed-set tabbed-alternate"data-tabs=1:2><inputchecked=checkedid=__tabbed_1_1name=__tabbed_1type=radio><inputid=__tabbed_1_2name=__tabbed_1type=radio><divclass=tabbed-labels><labelfor=__tabbed_1_1>Minimal YAML configuration file</label><labelfor=__tabbed_1_2>Environment variables</label></div><divclass=tabbed-content><divclass=tabbed-block><divclass="language-yaml highlight"><spanclass=filename>config.yaml</span><pre><span></span><code><spanid=__span-4-1><aid=__codelineno-4-1name=__codelineno-4-1href=#__codelineno-4-1></a><spanclass=nt>cli</span><spanclass=p>:</span>
</span></code></pre></div><divclass="admonition bug"><pclass=admonition-title>Bug</p><p>Headscale currently requires at least an empty configuration file when environment variables are used to specify connection details. See <ahref=https://github.com/juanfont/headscale/issues/2193>issue 2193</a> for more information.</p></div></div></div></div><p>This instructs the <code>headscale</code> binary to connect to a remote instance at <code><HEADSCALE_ADDRESS>:<PORT></code>, instead of connecting to the local instance.</p></li><li><p>Test the connection</p><p>Let us run the headscale command to verify that we can connect by listing our nodes:</p><divclass="language-shell highlight"><pre><span></span><code><spanid=__span-6-1><aid=__codelineno-6-1name=__codelineno-6-1href=#__codelineno-6-1></a>headscale<spanclass=w></span>nodes<spanclass=w></span>list