So, what is Mosh? It's an SSH replacement that helps with bad connections (ever tried to SSH into something in the passenger seat of a car?) and allows you to persist connections (close your laptop at work and resume it at home without losing the connection). Go read the mosh.org website.

Mosh is great, but it requires running a server on each machine you want to connect to. On linux, this works out of the box (most of the time), but on MacOS it won't work without some tweaking.

To get Mosh on MacOS, install it from homebrew:

$ brew install mosh

This installs both the client and the server. If all you are doing is connecting to other mosh servers from your Mac, you don't need to do any more configuration. But if you want to use mosh to connect to your Mac, read on.

Path Config

The first issue you will run in to is that the mosh-server binary is not on your system path by default. When you try to connect to the server you will get the following error:

command not found: mosh-server
Connection to 10.1.1.1 closed.
/usr/local/bin/mosh: Did not find mosh server startup message. (Have you installed mosh on your server?)

To fix this you can either pass in the path to the server in your connection:

$ mosh 10.1.1.1 --server=/usr/local/bin/mosh-server

Or, you can add /usr/local/bin to your non-interactive path. This requires changing your shell's rc file (~/.bashrc, ~/.zshrc, etc.) on your server.

Add the following line to your rc file to add the homebrew bin dir to your path:

export PATH=$PATH:/usr/local/bin

Firewall

Now we can get the server to run, but we can't get through the default firewall. If you run it now, you will connect but get a message about no data received on port 60001. That is, if your firewall is enabled. If not, go turn it on in System Preferences.

Unfortunately, I wasn't ever able to get mosh-server working through the very basic firewall GUI in system prefs, so the configuration has to be done through the CLI.

/usr/local/bin/mosh-server is a symlink to the actual binary in /usr/local/Cellar. You need the full path to the binary as the firewall rules don't work with symlinks. You can get the full path by running brew info mosh. You will get something like the following output:

mosh: stable 1.3.2 (bottled), HEAD
Remote terminal application
https://mosh.org
/usr/local/Cellar/mosh/1.3.2_4 (14 files, 878.9KB) *
...more...

The line right after the https://mosh.org is the full path to the binary. Copy this for use in your firewall rules below.

You now need to add the rules:

# Turn the firewall off
$ sudo /usr/libexec/ApplicationFirewall/socketfilterfw --setglobalstate off

# Enable the firewall rules (make sure you are using your actual path)
$ sudo /usr/libexec/ApplicationFirewall/socketfilterfw --add /usr/local/Cellar/mosh/1.3.2_4/bin/mosh-server

$ sudo /usr/libexec/ApplicationFirewall/socketfilterfw --unblockapp /usr/local/Cellar/mosh/1.3.2_4/bin/mosh-server

# Turn the firewall back on
$ sudo /usr/libexec/ApplicationFirewall/socketfilterfw --setglobalstate on

These 4 commands will stop the firewall, open up the ports for mosh-server and restart your firewall with the new rules.

Note, if you update mosh, this will probably need to be run again with the new version as the path will have changed. I don't currently have a better solution as symlinks do not work.

If everything worked correctly, you can now connect to your mosh-server on MacOS with your firewall intact.