Creating a Custom Reverse Proxy

Indigo ships with an Nginx reverse proxy which Indigo automatically configures, to allow every stack’s sites to be accessible without appending port numbers, and with valid, locally-trusted SSL certificates.

However, sometimes you have a server running outside Indigo, and would still like to use this built-in reverse proxy. In future, Indigo will support this without any hand-built config, but until then, the following guide will show you how!

Prerequisites

This advanced tutorial assumes that the reader has a good understanding of Nginx, reverse proxies, and a rough idea of how Indigo works.

Configuring Indigo’s reverse proxy to proxy an external server

The goal

For the sake of this example, let’s say you have a server running on your Mac, but outside of Indigo, accessible at http://127.0.0.1:1313.

You’d like that to be accessible at a URL such as https://my-local-proxy.com. You’ll be wanting the https to cause no browser warnings, just like Indigo sites.

Quick start

Feel free to download the example stack file, which will instantly configure your Indigo app to proxy http://127.0.0.1:1313 to https://my-local-proxy.com.

external-rp.indigostack

You can open this config bundle file in your code editor, and might make good progress simply examining it and modifying it as needed. It will show as a folder containing three files at various folder paths.

For example to proxy a port other than 1313 simply edit the appropriate location inside rp.my-local-proxy.com.conf. Likewise the domain can of course be changed from my-local-proxy.com; don’t forget to also change the entry inside the config.json as well as the nginx config.

However if you get stuck, or would like to understand how this “External Reverse Proxy” stack file was created, feel free to follow the rest of this tutorial.

Step 1: get the domain and valid SSL certificate working

For every Apache or Nginx site, Indigo automatically creates:

  1. an entry in your /etc/hosts file for the site’s domain
  2. a valid SSL certificate for the site’s domain
  3. an nginx site configuration
  4. a reverse proxy configuration, for the System stack’s Nginx reverse proxy

We’re going to create a dummy stack, with a placeholder nginx site in it, so that Indigo does 1 and 2 from that list for us. Shortly we will remove item 3, and override item 4 with our own custom reverse proxy config.

Do this:

  1. Add a new stack. Call it anything you like.
  2. Add an nginx service into the new stack.
  3. Add a new nginx site, giving it the domain my-local-proxy.com. Point it anywhere you like; an empty folder is fine.
  4. Start up the stack. At this point, visiting https://my-local-proxy.com will attempt to serve whatever you pointed it at. That’s fine for now.

Step 2: Override the site’s System stack reverse proxy configuration

Indigo will have generated a reverse proxy configuration for that site. We want to override that with our own hand-built config instead.

Do this:

  1. go into the System stack and right-click the Nginx Reverse Proxy service and choose “Show Compiled in Finder”.
  2. in the Finder, look inside nginx_reverse_proxy/conf/sites-enabled and locate rp.my-local-proxy.com.conf. That’s where Indigo’s compiled reverse proxy config ends up and it’s what we’re about to override with our own file. Copy this file (CMD-C).
  3. back in Indigo, shut down the dummy stack.
  4. right-click the dummy stack in the Indigo stack list on the LHS. Choose “Show in Finder”.
  5. in the Finder, right-click the indigo-x.indigostack file and choose “Show Package Contents”.
  6. create the following folder heirachy inside the stack config bundle: system/nginx_reverse_proxy/conf/sites-enabled and paste the file inside it. The resulting file path will be system/nginx_reverse_proxy/conf/sites-enabled/rp.my-local-proxy.com.conf.

Step 3. Create your own reverse proxy config

We’ll replace this rp.my-local-proxy.com.conf with our own bespoke config.

Do this:

  1. using your favourite text editor, open the config bundle’s nginx_9AED/conf/sites-enabled/rp.my-local-proxy.com.conf created above.
  2. replace the contents with this configuration:
# Available template variables:
#
# user:                     {{user}}
# group:                    {{group}}
# log_path:                 {{log_path}}
# pid_file:                 {{pid_file}}
# service_path:             {{service_path}}
# backend_domain:           {{backend_domain}}
# ssl_certificate_dir:      {{ssl_certificate_dir}}
# reverse_proxies:
#   - backend_port          {{backend_port}}
#     Int: port number to access the backend
#   - rp_port               {{rp_port}}
#     Int: port number for the reverse proxy frontend
#   - rp_ssl_port           {{rp_ssl_port}}
#     Int: port number for the reverse proxy frontend on https
#   - rp_domains            {{rp_domains}}
#     Str: space-separated list of domains

server {
    # server_name  {{rp_domains}};
    server_name  my-local-proxy.com;

    listen  127.0.0.1:80;
    listen  [::1]:80;

    listen 127.0.0.1:443 ssl;
    listen [::1]:443 ssl;
    ssl_certificate     "{{ssl_certificate_dir}}/cert.pem";
    ssl_certificate_key "{{ssl_certificate_dir}}/key.pem";

    access_log  "{{log_path}}/rproxy-{{backend_domain}}-access.log";
    error_log   "{{log_path}}/rproxy-{{backend_domain}}-error.log";

    client_max_body_size 0;

    location / {
        # proxy_pass  {{backend_protocol}}://127.0.0.1:{{backend_port}};
        proxy_pass  http://127.0.0.1:1313;

        proxy_ssl_server_name on;

        proxy_set_header  Host $host;
        proxy_set_header  X-Real-IP $remote_addr;
        proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header  X-Forwarded-Host $server_name;
    }
}

You’ll notice:

  • the server_name has been hardcoded to my-local-proxy.com
  • the proxy_pass has been hardcoded to http://127.0.0.1:1313, which is the URL of our non-Indigo server

Step 4: Remove the site’s nginx configuration

As mentioned, we want to remove the site’s normal Nginx config (which is what usually tells the stack’s Nginx to host your site at port 50001 or the like). We don’t actually want our stack’s Nginx to do anything, other than to trigger Indigo’s creation of the hosts entry and the SSL certificate for the domain.

To achieve this we’re going to override the file with an empty one.

Do this:

  1. in Indigo, right-click the stack’s Nginx and “Show Compiled in Finder”. Take note of this Nginx’s UUID; in our example it was nginx_9AED. Feel free to poke around inside nginx_9AED/conf/sites-enabled. That’s where Indigo’s compiled config ends up and it’s what we’re about to override with an empty file. But don’t forget, all these files are ephemeral… they will be overwritten by Indigo every time the stack starts up.
  2. in the Finder, locate where you are viewing the contents of the indigo-x.indigostack bundle file (from step 2 above).
  3. create the following folder heirachy inside the stack config bundle: nginx_9AED/conf/sites-enabled and create an empty file inside it. The resulting file path will be nginx_9AED/conf/sites-enabled/my-local-proxy.com.conf. It might be helpful to put a comment into this file to explain why it’s there, or at least something like:
    # deliberately empty.

Step 5: You’re done!

Back in Indigo, start up the stack. Once started, you should be able to visit https://my-local-proxy.com and see the same content as at http://127.0.0.1:1313.

To see how it all came together, take a look inside these two compiled config locations:

  • right-click the dummy stack’s Nginx and choose “Show Compiled in Finder”. Your compiled file has been cloned to nginx_9AED/conf/sites-enabled/my-local-proxy.com.conf
  • right-click the System stack’s Nginx reverse proxy and choose “Show Compiled in Finder”. Your compiled file has been cloned to nginx_reverse_proxy/conf/sites-enabled/rp.my-local-proxy.com.conf