This guide documents how to enable SSH access from OrbStack Linux guest VMs to the macOS host. The standard "Remote Login" toggle in System Settings is necessary but not sufficient — macOS uses launchd socket activation for sshd which only binds to the loopback interface, making it unreachable from guest VMs on the OrbStack bridge network.
The solution is to run a second sshd instance via a custom LaunchDaemon that binds to all interfaces.
- macOS with OrbStack installed and at least one Linux VM
- An SSH key pair on the guest (OrbStack shares the host's SSH agent by default)
- The guest's public key in
~/.ssh/authorized_keyson the macOS host
Open System Settings > General > Sharing and enable Remote Login.
This activates the system com.openssh.sshd launchd service, which uses
inetd-style socket activation. launchd holds the listening socket on port 22 and
spawns sshd on demand. However, this socket only binds to the loopback
interface, so only ssh localhost works.
macOS uses a Service Access Control List (SACL) via the PAM module
pam_sacl.so in /etc/pam.d/sshd. If the SACL denies the user, the
connection is accepted and authenticated but then immediately closed — a
confusing failure mode.
In the Remote Login settings, click the (i) button. You have two options:
Option A: Allow all users
Select "Allow access for: All users". This is the simplest option.
Option B: Allow specific users
Select "Allow access for: Only these users", then click + and add your user account. Equivalently, from the command line:
sudo dseditgroup -o edit -a YOUR_USERNAME -t user com.apple.access_sshYou can verify membership with:
dseditgroup -o checkmember -m YOUR_USERNAME com.apple.access_sshEither option works. The key point is that the SACL must permit the connecting user, otherwise sshd will reject the connection after authentication with the log message:
Access denied for user ... by PAM account configuration
The system sshd service uses launchd socket activation (inetdCompatibility mode
in /System/Library/LaunchDaemons/ssh.plist). This means launchd owns the
listening socket and only binds to loopback. The system plist is SIP-protected
and cannot be modified.
The workaround is to create a custom LaunchDaemon that runs sshd as a standalone daemon, managing its own sockets and binding to all interfaces:
sudo tee /Library/LaunchDaemons/local.sshd.plist << 'EOF'
<?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>local.sshd</string>
<key>Program</key>
<string>/usr/sbin/sshd</string>
<key>ProgramArguments</key>
<array>
<string>/usr/sbin/sshd</string>
<string>-D</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
</dict>
</plist>
EOFKey details:
-D: Runs sshd in the foreground (no daemonize), which is required for launchd to manage the process lifecycle.KeepAlive: Restarts sshd if it exits unexpectedly.RunAtLoad: Starts sshd at boot.- No inetdCompatibility: sshd manages its own sockets and binds to all
interfaces (both
0.0.0.0and::on port 22).
Load the service:
sudo launchctl bootstrap system /Library/LaunchDaemons/local.sshd.plistThis persists across reboots.
From the macOS host:
ssh localhost echo testFrom an OrbStack guest:
ssh YOUR_USERNAME@host.orb.internal echo testOrbStack exposes the macOS host to guest VMs via host.orb.internal, which
resolves to an IPv6 address on the OrbStack bridge network (e.g.,
fd07:b51a:cc66:f0::fe). The macOS bridge interfaces (bridge100,
bridge101) carry this traffic.
The system sshd (via launchd socket activation) only listens on loopback, so connections from the bridge network never reach it. The custom LaunchDaemon runs sshd in standalone mode, which binds to all interfaces — including the OrbStack bridge — allowing guest VMs to connect.
Both sshd instances coexist: the system one handles loopback connections via socket activation, and the custom one handles connections on all interfaces.
"Connection closed" immediately after connecting: This is almost always the
SACL. Verify with dseditgroup -o checkmember -m YOUR_USERNAME com.apple.access_ssh, or check the Remote Login settings in System Settings.
Diagnosing server-side issues: Run sshd in debug mode on a test port to see detailed logs:
sudo /usr/sbin/sshd -d -p 2201
# Then connect from the guest:
ssh YOUR_USERNAME@host.orb.internal -p 2201 echo testApplication Firewall: The macOS Application Firewall does not appear to
affect this setup. In testing, connections from OrbStack guests succeeded
regardless of whether /usr/sbin/sshd and /usr/libexec/sshd-keygen-wrapper
were set to allow or block incoming connections in the firewall rules. The
firewall likely does not filter traffic on the virtual bridge interfaces used by
OrbStack.
To remove the custom sshd service:
sudo launchctl bootout system/local.sshd
sudo rm /Library/LaunchDaemons/local.sshd.plist