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

推荐订阅源

S
Security Affairs
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
大猫的无限游戏
大猫的无限游戏
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
爱范儿
爱范儿
阮一峰的网络日志
阮一峰的网络日志
GbyAI
GbyAI
D
Docker
美团技术团队
N
Netflix TechBlog - Medium
罗磊的独立博客
V
Visual Studio Blog
人人都是产品经理
人人都是产品经理
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Hugging Face - Blog
Hugging Face - Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
Jina AI
Jina AI
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
M
MIT News - Artificial intelligence
腾讯CDC
MongoDB | Blog
MongoDB | Blog
Last Week in AI
Last Week in AI
博客园 - 三生石上(FineUI控件)
博客园 - 叶小钗
V
V2EX
L
LangChain Blog
博客园 - 【当耐特】
B
Blog RSS Feed
量子位
U
Unit 42
Engineering at Meta
Engineering at Meta
小众软件
小众软件
宝玉的分享
宝玉的分享
H
Help Net Security
Microsoft Azure Blog
Microsoft Azure Blog
云风的 BLOG
云风的 BLOG
博客园 - 聂微东
博客园 - 司徒正美
The Cloudflare Blog
The GitHub Blog
The GitHub Blog
T
Tailwind CSS Blog
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
The Last Watchdog
The Last Watchdog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
S
SegmentFault 最新的问题
博客园_首页
Attack and Defense Labs
Attack and Defense Labs
TaoSecurity Blog
TaoSecurity Blog
Apple Machine Learning Research
Apple Machine Learning Research
S
Security @ Cisco Blogs

alexwlchan’s notes

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 What’s the main prefix in SQLite queries? The file(1) command can read SQLite databases My randline project is tested by Crater Drawing an image with Liquid Glass using SwiftUI Previews Road signs in the Soviet union don’t have circular heads Create a file atomically in Go Get a map of IP addresses for devices in my tailnet The SQLite command line shell will count your unclosed parentheses Use SQL triggers to prevent overwriting a value Testing date formatting with date-fns-tz and different timezones The “strangler” pattern is named after a tree, not an act of violence Place with the same name, but different etymology
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.)