惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

人人都是产品经理
人人都是产品经理
量子位
月光博客
月光博客
罗磊的独立博客
宝玉的分享
宝玉的分享
博客园_首页
酷 壳 – CoolShell
酷 壳 – CoolShell
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
WordPress大学
WordPress大学
博客园 - 叶小钗
博客园 - 聂微东
阮一峰的网络日志
阮一峰的网络日志
V
V2EX
雷峰网
雷峰网
博客园 - 三生石上(FineUI控件)
Jina AI
Jina AI
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - Franky
美团技术团队
爱范儿
爱范儿
V
Visual Studio Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Y
Y Combinator Blog

alexwlchan’s notes

What is WS11 1DB? Blocking referrers with Caddy How to type a Spanish question mark (¿) on a Mac Non-overlapping type comparisons and Python type checkers Why does t.Setenv panic after t.Parallel? Use Path.glob() and Path.rglob() for typed versions of glob.glob() Curious clocks and colourful eyes Track which templates are used by Jinja2 Archeologists distinguish between “sherds” and “shards” A single command to test all my changed Go packages Disable the new message animations in WhatsApp Finding high-churn folders that bother Backblaze Always-on SSH agent forwarding with my Git pushes Managing the caption of a photo with AppleScript (but not PhotoKit) Goodhart’s and Campbell’s Law are different Notes from The Cornishman No. 176 (Spring 2026) Notes from The Cornishman No. 176 (Spring 2026) GitUp can’t diff text files larger than 8MB Home Testing the width of a page on a mobile device using Playwright Disable AirPods charging notifications Start a Caddy server in a subprocess during a Python session Filter a list of JSON object based on a list of tags HOME_GET_ME_HOME is a Citymapper Shortcuts action The FileExistsError exception exposes a filename attribute The red-lined bubble snail Why can’t Python connect to example.com? Useful type hints for Python How to truncate the middle of long command output AirPlay Receiver can interfere with Flask apps
Setting up golink in my personal tailnet
2026-02-23 · via alexwlchan’s notes

I created a macOS LaunchAgent to start golink automatically whenever my desktop Mac restarts.

We use golink a lot at work, and I wanted to add it to my personal tailnet.

I decided to run it from my home Mac mini, because it’s always running and golink is a very lightweight service. Writing this, it occurs to me I could have also run it on my Linux web server, which doesn’t have to restart for macOS updates, but it’s set up now.

These are some notes on how I set it up:

  1. Clone the [golink repo] to my Mac.

    $ git clone git@github.com:tailscale/golink.git ~/repos/golink
  2. Authenticate golink with my tailnet. I created an auth key for my tailnet which is tagged with tag:golink, then passed it as the TS_AUTH_KEY environment variable to start golink:

    $ TS_AUTHKEY="tskey-auth-<key>" go run ./cmd/golink -sqlitedb "/Volumes/Media (Speedwell)/golink.db"

    That starts an instance of golink that I could see at http://go/, but it would only last as long as my terminal session – I want it to be an always-running service.

  3. Configure golink to start automatically. I created a macOS LaunchAgent by creating a file at ~/Library/LaunchAgents/net.alexwlchan.golinks.plist with the following contents:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
        <dict>
            <key>Label</key>
            <string>net.alexwlchan.golinks</string>
            <key>ProgramArguments</key>
            <array>
                <string>/usr/local/go/bin/go</string>
                <string>run</string>
                <string>./cmd/golink</string>
                <string>-sqlitedb</string>
                <string>/Volumes/Media (Speedwell)/golink.db</string>
            </array>
            <key>WorkingDirectory</key>
            <string>/Users/alexwlchan/repos/golink</string>
            <key>RunAtLoad</key>
            <true/>
            <key>StandardOutPath</key>
            <string>/Users/alexwlchan/Library/Logs/golinks.log</string>
            <key>StandardErrorPath</key>
            <string>/Users/alexwlchan/Library/Logs/golinks.log</string>
        </dict>
    </plist>

    I start the service by running:

    $ launchctl load ~/Library/LaunchAgents/net.alexwlchan.golinks.plist

    Now my golink service is running, and will be automatically started whenever I restart or log into my Mac.

    If I need to stop it, I run:

    $ launchctl unload ~/Library/LaunchAgents/net.alexwlchan.golinks.plist

    I can restart the service by running unload/load, for example if I’ve made changes to the LaunchAgent plist.

  4. Allow my devices to see golink. I added a grant to my policy file which allows every device in my tailnet to look up http://go/ URLs:

    "grants": [
      
      {
        "src": ["autogroup:member"],
        "dst": ["tag:golink"],
        "ip":  ["*"],
      },
    ]

    It’s also possible for me to control who’s allowed to edit links, but I’m the only user in my personal tailnet, so that’s a non-issue.

  5. Add a policy file test to ensure I can reach golinks from my devices.

    "hosts": {
      "phaenna-mac-mini":     "100.76.19.1",
      "go":                   "100.107.83.99",
      
    },
    
    "tests": [
      {
        "src":    "phaenna-mac-mini",
        "accept": ["go:80"],
      },
      
    ],

    I populated the hosts field using the output of tailscale status.

(Disclaimer: At time of writing, I’m employed by Tailscale.)