Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 21 additions & 37 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -16,39 +16,14 @@ build.release: submodule

.PHONY: install/privileged
install/privileged:
sudo dseditgroup -o read tunmux >/dev/null 2>&1 || sudo dseditgroup -o create tunmux
sudo dseditgroup -o edit -a $$(id -un) -t user tunmux

@# Binary copy is a dev stand-in for the future Homebrew bottle.
sudo install -m 0755 target/release/tunmux /usr/local/bin/tunmux
sudo mkdir -p /var/log/tunmux && sudo chmod 755 /var/log/tunmux
sudo mkdir -p "/Library/Application Support/tunmux/run"
sudo chgrp tunmux "/Library/Application Support/tunmux/run"
sudo chmod 0750 "/Library/Application Support/tunmux/run"

sudo cp etc/me.pansen.tunmux.privileged.plist /Library/LaunchDaemons/
sudo chown root:wheel /Library/LaunchDaemons/me.pansen.tunmux.privileged.plist
sudo chmod 644 /Library/LaunchDaemons/me.pansen.tunmux.privileged.plist
GID=$$(dscl . -read /Groups/tunmux PrimaryGroupID | awk '{print $$2}'); \
sudo /usr/libexec/PlistBuddy -c "Delete :Sockets:Listeners:SockPathGroup" \
/Library/LaunchDaemons/me.pansen.tunmux.privileged.plist 2>/dev/null || true; \
sudo /usr/libexec/PlistBuddy -c "Add :Sockets:Listeners:SockPathGroup integer $$GID" \
/Library/LaunchDaemons/me.pansen.tunmux.privileged.plist
sudo launchctl bootout system/me.pansen.tunmux.privileged 2>/dev/null || true
@# Clear any stale "disabled" override — bootstrap of a disabled label fails with EIO (5).
sudo launchctl enable system/me.pansen.tunmux.privileged
sudo launchctl bootstrap system /Library/LaunchDaemons/me.pansen.tunmux.privileged.plist
sudo /usr/local/bin/tunmux launchd install


.PHONY: install/autostart
install/autostart:
mkdir -p $$HOME/Library/LaunchAgents
sed -e "s|__HOME__|$$HOME|g" -e "s|__PROFILE__|$(TUNMUX_PROFILE)|g" etc/me.pansen.tunmux.autoconnect.plist > $$HOME/Library/LaunchAgents/me.pansen.tunmux.autoconnect.plist
launchctl bootout gui/$$(id -u)/me.pansen.tunmux.autoconnect 2>/dev/null || true
launchctl bootstrap gui/$$(id -u) $$HOME/Library/LaunchAgents/me.pansen.tunmux.autoconnect.plist
@# test now
launchctl kickstart -k gui/$$(id -u)/me.pansen.tunmux.autoconnect
@# inspect
launchctl print gui/$$(id -u)/me.pansen.tunmux.autoconnect
/usr/local/bin/tunmux autoconnect install --file $(TUNMUX_PROFILE) --force


.PHONY: install
Expand All @@ -57,25 +32,23 @@ install: build.release install/privileged install/autostart

.PHONY: reload/privileged
reload/privileged:
sudo launchctl kickstart -k system/me.pansen.tunmux.privileged
sudo /usr/local/bin/tunmux launchd restart

.PHONY: reload/connections
reload/connections:
/usr/local/bin/tunmux --debug disconnect --provider wgconf --all

.PHONY: reload/autostart
reload/autostart:
launchctl kickstart -k gui/$$(id -u)/me.pansen.tunmux.autoconnect
launchctl print gui/$$(id -u)/me.pansen.tunmux.autoconnect
/usr/local/bin/tunmux autoconnect reload

.PHONY: reload
reload: reload/privileged reload/connections reload/autostart


.PHONY: uninstall/autostart
uninstall/autostart:
launchctl bootout gui/$$(id -u)/me.pansen.tunmux.autoconnect 2>/dev/null || true
rm -f $$HOME/Library/LaunchAgents/me.pansen.tunmux.autoconnect.plist
/usr/local/bin/tunmux autoconnect uninstall

.PHONY: uninstall/dns
uninstall/dns:
Expand All @@ -93,11 +66,19 @@ uninstall/dns:
sudo killall -HUP mDNSResponder

.PHONY: uninstall/privileged
uninstall/privileged:
sudo launchctl bootout system/me.pansen.tunmux.privileged 2>/dev/null || true
sudo launchctl disable system/me.pansen.tunmux.privileged 2>/dev/null || true
uninstall/privileged: build.release
@# Unregister the daemon only (bootout + plist/socket removal). Keeps the
@# binary, tunmux group, and logs — see purge/privileged for full teardown.
@# Prefer the installed binary; if it was already removed, fall back to the
@# freshly compiled one so `launchd uninstall` still runs.
bin=/usr/local/bin/tunmux; [ -x "$$bin" ] || bin=target/release/tunmux; \
sudo "$$bin" launchd uninstall || true

.PHONY: purge/privileged
purge/privileged: uninstall/privileged
@# Destructive: after unregistering the daemon, remove the binary, all data,
@# logs, and the tunmux group.
sudo pkill -f '/usr/local/bin/tunmux wgconf' 2>/dev/null || true
sudo rm -f /Library/LaunchDaemons/me.pansen.tunmux.privileged.plist
sudo rm -f /usr/local/bin/tunmux
sudo rm -rf "/Library/Application Support/tunmux"
sudo rm -rf /var/log/tunmux
Expand All @@ -106,6 +87,9 @@ uninstall/privileged:
.PHONY: uninstall
uninstall: uninstall/autostart uninstall/privileged uninstall/dns

.PHONY: purge
purge: uninstall purge/privileged


.PHONY: check/privileged
check/privileged:
Expand Down
22 changes: 13 additions & 9 deletions doc/launchd-socket-activation.md
Original file line number Diff line number Diff line change
Expand Up @@ -353,20 +353,24 @@ Changes from current:
> shorter `SockMode`/`SockGroup`. Confirm which the running launchd honors (see gotchas);
> the value must end up `0660 root:tunmux` on the created socket.

### 3. `Makefile` — pre-create the socket directory
### 3. `Makefile` — delegate daemon setup to the binary

Under on-demand activation the daemon may not be running to create
`/Library/Application Support/tunmux/run`; launchd needs the parent directory to exist to create the socket
file. Add to `install/privileged` (the `tunmux` group already exists by this point):
`install/privileged` now installs the binary and delegates all daemon setup to
`tunmux launchd install`:

```make
sudo mkdir -p "/Library/Application Support/tunmux/run"
sudo chgrp tunmux "/Library/Application Support/tunmux/run"
sudo chmod 0750 "/Library/Application Support/tunmux/run"
sudo install -m 0755 target/release/tunmux /usr/local/bin/tunmux
sudo /usr/local/bin/tunmux launchd install
```

The rest of `install/privileged` (group creation, binary install, log dir, plist
copy/chown, `bootout`/`bootstrap`) is unchanged.
`tunmux launchd install` handles group creation, log dir setup, socket dir
pre-creation, plist copy/chown, and launchctl bootstrap. Similarly,
`tunmux launchd restart` replaces the direct `launchctl kickstart`, and
`tunmux launchd uninstall` handles bootout/disable and plist removal.

This centralizes the entire daemon lifecycle in the binary, keeping the
Makefile simple and reducing duplication between install-time and upgrade
flows.

### 4. Unprivileged client — no change

Expand Down
10 changes: 5 additions & 5 deletions etc/me.pansen.tunmux.autoconnect.plist
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@
call the binary directly with no wrapper script. -->
<key>ProgramArguments</key>
<array>
<string>/usr/local/bin/tunmux</string>
<string>@TUNMUX_BIN@</string>
<string>--debug</string>
<string>wgconf</string>
<string>connect</string>
<string>--file</string>
<string>__PROFILE__</string>
<string>@CONNECT_FLAG@</string>
<string>@CONNECT_VALUE@</string>
<string>--if-missing</string>
</array>

Expand All @@ -32,8 +32,8 @@
<string>Aqua</string> <!-- only in a real GUI login session -->

<key>StandardOutPath</key>
<string>__HOME__/Library/Logs/tunmux-autoconnect.out.log</string>
<string>@TUNMUX_HOME@/Library/Logs/tunmux-autoconnect.out.log</string>
<key>StandardErrorPath</key>
<string>__HOME__/Library/Logs/tunmux-autoconnect.err.log</string>
<string>@TUNMUX_HOME@/Library/Logs/tunmux-autoconnect.err.log</string>
</dict>
</plist>
5 changes: 2 additions & 3 deletions etc/me.pansen.tunmux.privileged.plist
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

<key>ProgramArguments</key>
<array>
<string>/usr/local/bin/tunmux</string>
<string>@TUNMUX_BIN@</string>
<string>--debug</string>
<string>privileged</string>
<string>--serve</string>
Expand All @@ -25,8 +25,7 @@
<dict>
<key>SockPathName</key>
<string>/Library/Application Support/tunmux/run/ctl.sock</string>
<!-- SockPathGroup requires an integer GID, not a name — group is set by the
daemon via chown immediately after receiving the fd from launch_activate_socket. -->
<!-- @SOCK_PATH_GROUP@ replaced at install time with SockPathGroup = integer GID of the tunmux group; e.g. GID 20 becomes: <key>SockPathGroup</key> <integer>20</integer> -->
<!-- 0660 octal = 432 decimal; plist <integer> is base-10 -->
<key>SockPathMode</key>
<integer>432</integer>
Expand Down
Loading