# X11 forwarding on macOS and docker A quick guide on how to setup X11 forwarding on macOS when using docker containers requiring a DISPLAY. This guide was tested on: - macOS Catalina 10.15.4 - docker desktop 2.2.0.5 (43884) - stable release - XQuartz 2.7.11 (xorg-server 1.18.4) ## Step-By-Step Guide 1. Install XQuartz via brew `$ brew cask install xquartz` 2. Logout and login of your Mac to activate XQuartz as default X11 server 3. Start XQuartz `$ open -a XQuartz` 4. Go to Security Settings and ensure that "Allow connections from network clients" is on ![alt XQuartz Security Stettings](https://gist.github.com/sorny/969fe55d85c9b0035b0109a31cbcb088/raw/d6eb9e8b0c20e51c46c5c9eb733b7f5e1144af4f/xquartz_preferences.png "XQuartz Security Settings") 5. Restart your Mac and start XQuartz again` `$ open -a XQuartz` 6. Check if XQuartz is setup and running correctly `$ ps aux | grep Xquartz` 7. Ensure that XQuartz is running similar to this: `/opt/X11/bin/Xquartz :0 -listen tcp` :0 means the display is running on display port 0 Important is that its not saying `–nolisten tcp` which would block any X11 forwarding to the X11 display. 8. Allow X11 forwarding via xhost `$ xhost +` This allows any client to connect. If you have security concerns you can append an IP address for a whitelist mechanism. You will always have to run `xhost +` after a restart of X11 as this is not a persistent setting. 9. Time to test X11 forwarding Pull the following docker container, set the DISPLAY env and run it... ``` $ docker pull sshipway/xclock $ ip=$(ifconfig en0 | grep inet | awk '$1=="inet" {print $2}') $ docker run -e DISPLAY=$ip:0 sshipway/xclock ``` Success, good old XClock should be displayed on your screen :) ![alt XClock](https://gist.github.com/sorny/969fe55d85c9b0035b0109a31cbcb088/raw/994ce6d6e3e12c531f535563ced45a93bc88e99a/xclock.png "XClock") ## Conclusion Your Mac is now an unsecured remote X11 server on the network, be aware of this! Stop XQuartz and X11 if you don't need it. If you want a Docker container or actually any unix client to use your Mac as X11 server, simply set the `DISPLAY` env variable to your ip-address and display-port. For Docker containers, you can pass the `DISPLAY` variable via `-e DISPLAY=ip:display-port` or enter the container and set the `DISPLAY` env accordingly. ## FAQs #### Error: Can't open display: \:0 → what to do? Ensure you ran `xhost +` If error is still present, ensure XQuartz is allowing network connections. If cli-arg `–nolisten tcp` is set it wont allow any outside connections... #### Error: No protocol specified. → what to do? When you login through some kind of a display manager, a `MIT-MAGIC-COOKIE-1` authentication cookie is created and written to your hosts `~/.Xauthority` file. That file is read by X11 clients and the cookies available there are used to authenticate the connections. Thanks to @LevZaplatin for pointing out a workaround: Map your hosts `~/.Xauthority` file into your docker container via `-v ~/.Xauthority:/root/.Xauthority` Applied to the XClock sample above: ``` $ docker run -v ~/.Xauthority:/root/.Xauthority -e DISPLAY=$ip:0 sshipway/xclock ```