{"id":187,"date":"2025-02-05T23:31:54","date_gmt":"2025-02-05T15:31:54","guid":{"rendered":"https:\/\/0x0.pub\/?p=187"},"modified":"2025-08-26T19:27:32","modified_gmt":"2025-08-26T11:27:32","slug":"docker%e9%83%a8%e7%bd%b2%e5%ae%89%e8%a3%85headscale-headscale-ui","status":"publish","type":"post","link":"https:\/\/0x0.pub\/?p=187","title":{"rendered":"Docker\u90e8\u7f72Headscale 0.25.0\u548cheadscale-admin"},"content":{"rendered":"\n<p><\/p>\n\n\n\n<pre class=\"wp-block-preformatted has-small-font-size\">1. \u521b\u5efadb.sqlite acl.sqlite\u6587\u4ef6\u548cdata\/ config\/\u76ee\u5f55\uff0c\u4e0b\u8f7d\u793a\u4f8b\u914d\u7f6e\u6587\u4ef6\u3002<\/pre>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code>mkdir -p \/home\/docker\/headscale\/config &amp;&amp; \\\nmkdir -p \/home\/docker\/headscale\/data &amp;&amp; \\\ntouch \/home\/docker\/headscale\/config\/acl.sqlite \\\ntouch \/home\/docker\/headscale\/data\/db.sqlite &amp;&amp; \\\nwget https:\/\/github.com\/juanfont\/headscale\/raw\/main\/config-example.yaml -O \/home\/docker\/headscale\/config\/config.yaml<\/code><\/pre>\n\n\n\n<p><\/p>\n\n\n\n<pre class=\"wp-block-preformatted has-small-font-size\">2. \u4fee\u6539config.yaml\u793a\u4f8b\u914d\u7f6e\u6587\u4ef6\u4ee5\u4e0b\u53c2\u6570\u9ad8\u4eae\u5b57\u6bb5\uff0c<\/pre>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code><strong>server_url: <mark style=\"background-color:#f2b037\" class=\"has-inline-color\">https:\/\/hs.xxx.com<\/mark> <\/strong>    #\u4fee\u6539\u670d\u52a1url\u4e3a\u914d\u7f6e\u89e3\u6790\u7684\u57df\u540d\n\n<strong>listen_addr: <mark style=\"background-color:#f2b037\" class=\"has-inline-color\">0.0.0.0<\/mark>:8080 <\/strong>         #\u9ed8\u8ba4\u670d\u52a1\u7aef\u53e3\n<strong>metrics_listen_addr: <mark style=\"background-color:#f2b037\" class=\"has-inline-color\">0.0.0.0<\/mark>:9090 <\/strong> #\u94fe\u8def\u8d28\u91cf\u9ed8\u8ba4\u76d1\u542c\u7aef\u53e3\n\n<strong>prefixes:                   <\/strong>       #\u9ed8\u8ba4\u5206\u914d\u8282\u70b9\u7684IP\u7f51\u6bb5<strong>\n  v4: 100.64.0.0\/10\n  v6: fd7a:115c:a1e0::\/48<\/strong>\n\n<strong>policy:\n  mode: <mark style=\"background-color:#f2b037\" class=\"has-inline-color\">database<\/mark>                   <\/strong>#ACL\u6a21\u5f0f\u4e3a\u6570\u636e\u5e93<strong>\n  path: \"<mark style=\"background-color:#f2b037\" class=\"has-inline-color\">.\/acl.sqlite<\/mark>\"<\/strong>             #ACL\u914d\u7f6e\u6587\u4ef6\u8def\u5f84\n\n<strong>derp:\n  server:\n  enabled: <mark style=\"background-color:#f2b037\" class=\"has-inline-color\">true<\/mark><\/strong>                     #\u542f\u7528\u5185\u5d4c\u5f0f\u4e2d\u8f6c\u670d\u52a1\u5668\n  stun_listen_addr: \"<mark style=\"background-color:#fcb900\" class=\"has-inline-color\">0.0.0.0:3478<\/mark>\"   #STUN\u7aef\u53e3\n\n<strong>dns:\n  magic_dns: <mark style=\"background-color:#f2b037\" class=\"has-inline-color\">false<\/mark>           <\/strong>       #\u5173\u95edmagic dns<strong>\n  base_domain: <mark style=\"background-color:#f2b037\" class=\"has-inline-color\">hs.xxx.com<\/mark><\/strong>           #\u52a0\u5165\u8282\u70b9\u7684\u8bbe\u5907\u4ee5\u6b64\u4e3a\u6839\u57df\n\n<strong>randomize_client_port: <mark style=\"background-color:#f2b037\" class=\"has-inline-color\">true<\/mark><\/strong>         #\u5f00\u542f\u7aef\u53e3\u968f\u673a<\/code><\/pre>\n\n\n\n<p><\/p>\n\n\n\n<pre class=\"wp-block-preformatted has-small-font-size\">3. \u542f\u52a8docker headscale 0.25.0\uff0cdocker\u73af\u5883\u81ea\u884c\u5b89\u88c5\u3002<\/pre>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code>docker run -d \\\n--name headscale \\\n--restart always \\\n-v \/home\/docker\/headscale\/config:\/etc\/headscale\/ \\\n-v \/home\/docker\/headscale\/data:\/var\/lib\/headscale \\\n-p 8080:8080 \\\n-p 9090:9090 \\\n-p 3478:3478\/udp \\\n--restart always \\\nheadscale\/headscale:0.25.0 \\\nserve<\/code><\/pre>\n\n\n\n<p><\/p>\n\n\n\n<pre class=\"wp-block-preformatted has-small-font-size\">4. \u914d\u7f6eNginx\u53cd\u5411\u4ee3\u7406headscale 8080\u7aef\u53e3\u548cHeadscale-admin webui\u9875\u9762\u3002<br>\u4e0b\u8f7d<a href=\"https:\/\/github.com\/GoodiesHQ\/headscale-admin\/releases\/tag\/v0.25.0\">headscale-admin 0.25.0<\/a> \u89e3\u538b\u5230 \/home\/docker\/headscale\/web<br>\u5b89\u88c5nginx\uff0c\u7f16\u8f91\u914d\u7f6e\u6587\u4ef6\/etc\/nginx\/conf.d\/<mark style=\"background-color:#f2b037\" class=\"has-inline-color\">hs.xxx.com.conf<\/mark><\/pre>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code>map $http_upgrade $connection_upgrade {\n    default      upgrade;\n    ''           close;\n}\n\nserver {\n    server_name <mark style=\"background-color:#f2b037\" class=\"has-inline-color\">hs.xxx.com<\/mark>;\n\n    location \/admin {\n        alias \/home\/docker\/headscale\/web;  \n        index index.html;\n    }\n\n    location \/ {\n        proxy_pass http:\/\/localhost:8080;\n        proxy_http_version 1.1;\n        proxy_set_header Upgrade $http_upgrade;\n        proxy_set_header Connection $connection_upgrade;\n        proxy_set_header Host $server_name;\n        proxy_redirect http:\/\/ https:\/\/;\n        proxy_buffering off;\n        proxy_set_header X-Real-IP $remote_addr;\n        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n        proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;\n        add_header Strict-Transport-Security \"max-age=15552000; includeSubDomains\" always;\n    }\n\n    listen 443 ssl;\n    ssl_certificate \/etc\/nginx\/ssl\/<mark style=\"background-color:#f2b037\" class=\"has-inline-color\">xxx.cer<\/mark>;      #\u57df\u540d\u8bc1\u4e66\u8def\u5f84\n    ssl_certificate_key \/etc\/nginx\/ssl\/<mark style=\"background-color:#f2b037\" class=\"has-inline-color\">xxx.key<\/mark>;  \n}\n\nserver {\n    if ($host = <mark style=\"background-color:#f2b037\" class=\"has-inline-color\">hs.xxx.com<\/mark>) {\n        return 301 https:\/\/$host$request_uri;\n    }\n\n    server_name <mark style=\"background-color:#f2b037\" class=\"has-inline-color\">hs.xxx.com<\/mark>;\n    listen 80;\n    return 404;\n}\n<\/code><\/pre>\n\n\n\n<p class=\"has-small-font-size\"><\/p>\n\n\n\n<pre class=\"wp-block-preformatted has-small-font-size\">5. \u4fdd\u5b58\u914d\u7f6e\u6587\u4ef6\uff0c\u91cd\u542fnginx\u3002 <br>\u6253\u5f00\u7ba1\u7406\u9875\u9762 https:\/\/<mark style=\"background-color:#f2b037\" class=\"has-inline-color\">hs.xxx.com<\/mark>\/admin \u8f93\u5165apikey\u4fdd\u5b58\u3002<\/pre>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code>#headscale docker\u4e2d\u751f\u6210apikey\uff0c\u6709\u6548\u671f10000\u5929\ndocker exec -it headscale headscale apikeys create -e 10000d \n\n#docker\u521b\u5efaheadscale\u7528\u6237 test\ndocker exec -it headscale headscale users create test\n\n#docker\u521b\u5efaheadscale\u7528\u6237test\u7684\u9884\u9a8c\u8bc1\u5bc6\u94a5\uff0c\u6709\u6548\u671f1000\u5929\u53ef\u590d\u7528\ndocker exec -it headscale headscale preauthkeys create -u test -e 1000d --reusable\n\n#\u67e5\u770b\u7528\u6237test\u7684\u9884\u9a8c\u8bc1\u5bc6\u94a5\ndocker exec -it headscale headscale preauthkeys list -u test<\/code><\/pre>\n\n\n\n<p><\/p>\n\n\n\n<pre class=\"wp-block-preformatted has-small-font-size\">6. \u5ba2\u6237\u7aef\u5b89\u88c5tailscale\uff0c\u4f7f\u7528\u9884\u9a8c\u8bc1\u5bc6\u94a5\u5feb\u901f\u52a0\u5165\u63a7\u5236\u5668\u7684\u547d\u4ee4\u3002<\/pre>\n\n\n\n<pre class=\"wp-block-code\" style=\"font-size:0.8rem\"><code>#--auth-key xxx \u7528\u6237\u7684\u9a8c\u8bc1\u5bc6\u94a5\uff0c--login-server https:\/\/hs.xxx.com headscale\u670d\u52a1\u5668URL\uff0c\n#--hostname \u6b64\u8282\u70b9\u4e3b\u673a\u540d\uff0c--accept-dns=false \u4e0d\u63a5\u53d7\u4e0b\u53d1\u7684dns\uff0c\n#--accept-routes \u63a5\u53d7\u5176\u5b83\u8282\u70b9\u516c\u544a\u7684\u8def\u7531\uff0c--advertise-routes ip1,ip2 \u901a\u544a\u672c\u57302\u4e2a\u5b50\u7f51\n   \n<strong>tailscale up --auth-key <mark style=\"background-color:#f2b037\" class=\"has-inline-color\">028agf492b3cf41882a1712991f42d21242892ef10h1d1a3<\/mark> --login-server https:\/\/<mark style=\"background-color:#f2b037\" class=\"has-inline-color\">hs.xxx.com<\/mark> --hostname homerouter --accept-dns=false --accept-routes --advertise-routes 10.0.1.0\/24,10.0.2.0\/24<\/strong>\n\n#\uff08\u53ef\u9009\uff09\u7981\u7528snat\uff0c\u9ed8\u8ba4\u60c5\u51b5\u4e0b\u901a\u544a\u5b50\u7f51\u8def\u7531\u65f6\u4f1a\u4f7f\u7528snat\ntailscale up --snat-subnet-routes=false<\/code><\/pre>\n\n\n\n<p>7. \u9047\u5230\u7684\u95ee\u9898<\/p>\n\n\n\n<pre class=\"wp-block-preformatted has-small-font-size\">openwrt \u5b89\u88c5tailscale\u56e0iptables-nft\u5bfc\u81f4\u65e0\u6cd5\u542f\u52a8  failed to connect to local tailscaled; it doesn't appear to be running \u53c2\u8003\u6b64\u5904\u89e3\u51b3 <a href=\"https:\/\/openwrt.org\/docs\/guide-user\/services\/vpn\/tailscale\/start\">openwrt tailscale start<\/a><br><br>docker\u542f\u52a8headscale\u53cd\u590d\u91cd\u542f\u65e5\u5fd7\u62a5\u9519\u201cdid not find expected key\u201d\u56e0\u4e3a\u91cd\u5efadocker\u624b\u52a8\u5220\u9664\u4e86\/data\u4e0b\u7684derp_server_private.key\u548cnoise_private.key\u3002<\/pre>\n\n\n\n<p>8. \u53c2\u8003\u94fe\u63a5\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-preformatted has-small-font-size\"><a href=\"https:\/\/www.nodeseek.com\/post-37577-1\">Docker \u642d\u5efa headscale \u5f02\u5730\u7ec4\u7f51\u5b8c\u6574\u6559\u7a0b<\/a><br><a href=\"https:\/\/www.cnblogs.com\/Yogile\/p\/17064031.html\">https:\/\/www.cnblogs.com\/Yogile\/p\/17064031.html<\/a><br><a href=\"https:\/\/help.sap560.com\/g-Tailscale\/20\/102.html\">https:\/\/help.sap560.com\/g-Tailscale\/20\/102.html<\/a> <br><a href=\"https:\/\/github.com\/GoodiesHQ\/headscale-admin\">https:\/\/github.com\/GoodiesHQ\/headscale-admin<\/a><\/pre>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>1. \u521b\u5efadb.sqlite acl.sqlite\u6587\u4ef6\u548cdata\/ config\/\u76ee\u5f55\uff0c\u4e0b\u8f7d\u793a\u4f8b\u914d\u7f6e\u6587\u4ef6\u3002 2 [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6],"tags":[37,39,38],"class_list":["post-187","post","type-post","status-publish","format-standard","hentry","category-study","tag-headscale","tag-headscale-ui","tag-tailscale"],"_links":{"self":[{"href":"https:\/\/0x0.pub\/index.php?rest_route=\/wp\/v2\/posts\/187","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/0x0.pub\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/0x0.pub\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/0x0.pub\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/0x0.pub\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=187"}],"version-history":[{"count":24,"href":"https:\/\/0x0.pub\/index.php?rest_route=\/wp\/v2\/posts\/187\/revisions"}],"predecessor-version":[{"id":371,"href":"https:\/\/0x0.pub\/index.php?rest_route=\/wp\/v2\/posts\/187\/revisions\/371"}],"wp:attachment":[{"href":"https:\/\/0x0.pub\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=187"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/0x0.pub\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=187"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/0x0.pub\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=187"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}