A snippet of the macOS Server documentation about web apps

Reverse Proxy with macOS Server

This post was published more than a few years ago (on 2017-05-02) and may contain inaccurate technical information, outmoded thoughts, or cringe takes. Proceed at your own risk.

Visualize this outcome:

  1. site1.example.com -> my single public IP -> Port forwarding 80 and 443 to LAN 192.168.1.10, a Mac mini running Apple macOS Server 5.3 on macOS 10.12 Sierra.
  2. site2.example.com -> my single public IP -> LAN 192.168.1.10 -> reverse proxy? -> :80 and :443 on LAN 192.168.1.15, another Mac mini running GitLab CE on Ubuntu 16.04.

This is on a network where I have no option of adding another public IP.

#1 is already up and running fine.

#2 is the hard part, mainly because I'm running macOS Server.app on #1, and the proxy setup does not seem to be the relatively straight-forward Apache one. Server has the Apache config files in odd places, and it likes to overwrite them with new changes made in the GUI, so it’s taken me a while to figure out the “right” way to do this under Server.app.

Enter Web Apps

I first had this question two years ago, and a friend of mine suggested there might be a way to do it with OS X Server's webappctl command and writing an appropriate webapp.plist, though the Work with web apps section of the OS X Server docs contains almost no detail. The docs have been updated to cover Server 5.3, but the web app documentation is still very sparse.

This new answer below is written as of macOS Server 5.3. Server 5 overhauls things in that every service in Server is now behind one master reverse proxy, so these instructions will not work with Server 4.1. However, these instructions are adapted and clarified from the instructions found at precursor.ca’s R.A.I.S page (scroll down to the “macOS Server 5 Reverse Proxy” tutorial link). Their tutorial also includes historical instructions for doing this with Server 4.1. However, since their tutorial focuses more on running multiple services from the same Mac instead of proxying to a separate machine, I’ve re-written the instructions to clarify that below.

Configuration Files

Note that in all of the files, you will need to replace the LAN IP addresses, and site2 and the other example domain and file names with the names of your own proxied domain. There are several occurrences within each configuration file.

Make a web app configuration file on the macOS Server machine, in /Library/Server/Web/Config/apache2/httpd_site2webapp.conf, pointing at the IP address of the site2 server.

Then in /Library/Server/Web/Config/apache2/webapps/com.example.site2webapp.plist, add the following, referencing the location of the .conf file above:

If you will also need SSL, put the following in /Library/Server/Web/Config/apache2/httpd_site2SSLwebapp.conf. The config differs in that LAN traffic between the servers will be unencrypted by default (this config essentially tells Server not to check if there is a valid cert), but the WAN traffic will be encrypted. I believe you can install a self-signed certificate on the site2 server for encrypted local traffic, but this config will still enable the reverse proxy without having to have matching certificates. (I grant there is likely a more correct way to secure the local traffic, but this worked for me.)

And the corresponding SSL web app plist, /Library/Server/Web/Config/apache2/webapps/com.example.site2SSLwebapp.plist, much the same as above:

For each of these four files, the permissions need to be owner: root and group: wheel, 644:

Setting up Server.app

Add the web app to Websites

  • In the Websites tab of the Server.app interface, click the + below the Websites listing to add a new site
  • Enter site2.example.com for Domain Name
  • Leave everything else at the default settings
  • Click Edit Advanced Settings…
  • Under the section “Make these web apps available on this website:” check Enable for site2WebApp
  • Click OK
  • Click Create

SSL

If you need SSL on the WAN, install a certificate in Server that covers the new domain. I used Let’s Encrypt to create a single certificate that was good for both my site1 and site2 domains. (Here's my Let’s Encrypt instructions for getting a cert while using Server.app.)

  • In the Certificates tab of Server.app, click the + at the bottom of the window, then Import a Certificate Identity…
  • Drag-and-drop the .pem files you got back from Let's Encrypt (or whatever certificate files you have), and click Import
  • In the Websites tab, create the new site almost the same as before, except change the Port to 443 and under SSL Certificate, pick the cert you just imported
  • Under Edit Advanced Settings…, instead check Enable for site2SSLWebApp

It just works!1


  1. Finally.