Amazon Web Services (AWS) Elastic Beanstalk software is a massive help for developers looking to launch and scale servers without having to touch the server infrastructure. This benefit has been the reason why I have used it for multiple projects, but whenever I have needed to re-configure the server for certain use cases, I have found the product and its YAML based configuration files, ebextensions, to be difficult to use with limited documentation available. This was certainly the case when I was setting up a reverse server proxy to my sub-directory. As a result of the limited information available, I decided to put together a tutorial on how you can write an ebextension to reverse proxy an external server to a subdirectory on your website.

To start, create a new file in the .ebextensions folder and name it something memorable, but with “00” prepended to ensure that this will be the first ebextension configuration file run. In my case, I used 00_nginx_https_rw. From there, I started in the files section of the file, by labeling the path and name of the file that I was writing and its file permissions.

files:
  /etc/nginx/conf.d/proxy.conf:
    mode: "000644"
    owner: root
    group: root

After setting the path and file attributes, it is time to configure the server and add a server block for our reverse server proxy. In the case of this example, /blog/ is that server block.

content: |
      upstream nodejs {
        server 127.0.0.1:8081;
        keepalive 256;
      }

      server {
        listen 8080;

        location / {
          proxy_pass  http://nodejs;
          proxy_set_header   Connection "";
          proxy_http_version 1.1;
          proxy_set_header        Host            $host;
          proxy_set_header        X-Real-IP	$remote_addr;
          proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
        }

        location /blog/ {
          proxy_pass http://xxx.xxx.xxx.xxx; // External Server IP Address
          proxy_set_header Connection "";
          proxy_http_version 1.1;
          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-Proto $scheme; 
        }

        gzip on;
        gzip_comp_level 4;
        gzip_types text/html text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;

}

Now what does this server block do?

First, we set the location path where the server should execute our custom server configuration. In this case I want my other server contents to load when a user goes to http://www.my-domain.com/blog.

location /blog/ {
    //Configuration Code
}

Then, we use proxy_pass to set the address of our proxied server so when a user goes to our domain subdirectory of /blog/ it will render the server content at the IP address provided.

location /blog/ {
          proxy_pass http://123.444.55.66; //Replace with your external server ip address
}

After this section we customize the header information when the request header is passed to the proxied server

location /blog/ {
          proxy_pass http://134.209.71.20;
          proxy_set_header Connection "";
          proxy_http_version 1.1;
          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-Proto $scheme; 
}

From there, a shell script must be included to remove the default configuration file (00_elastic_beanstalk_proxy.conf) provided by Elastic Beanstalk.

/opt/elasticbeanstalk/hooks/configdeploy/post/99_kill_default_nginx.sh:
    mode: "000755"
    owner: root
    group: root
    content: |
      #!/bin/bash -xe
      rm -f /etc/nginx/conf.d/00_elastic_beanstalk_proxy.conf
      service nginx stop 
      service nginx start

Finally, We need to update the container command to remove the default server configuration file created by AWS, which will be replaced by the current ebextension configuration.

container_commands:
  removeconfig:
    command: "rm -f /tmp/deployment/config/#etc#nginx#conf.d#00_elastic_beanstalk_proxy.conf /etc/nginx/conf.d/00_elastic_beanstalk_proxy.conf"

Leaving you with the following completed code:

files:
  /etc/nginx/conf.d/proxy.conf:
    mode: "000644"
    owner: root
    group: root
    content: |
      upstream nodejs {
        server 127.0.0.1:8081;
        keepalive 256;
      }

      server {
        listen 8080;

        location / {
          proxy_pass  http://nodejs;
          proxy_set_header   Connection "";
          proxy_http_version 1.1;
          proxy_set_header        Host            $host;
          proxy_set_header        X-Real-IP	$remote_addr;
          proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
        }

        location /blog/ {
          proxy_pass http://123.444.55.66;
          proxy_set_header Connection "";
          proxy_http_version 1.1;
          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-Proto $scheme; 
        }

        gzip on;
        gzip_comp_level 4;
        gzip_types text/html text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;

      }

  /opt/elasticbeanstalk/hooks/configdeploy/post/99_kill_default_nginx.sh:
    mode: "000755"
    owner: root
    group: root
    content: |
      #!/bin/bash -xe
      rm -f /etc/nginx/conf.d/00_elastic_beanstalk_proxy.conf
      service nginx stop 
      service nginx start

container_commands:
  removeconfig:
    command: "rm -f /tmp/deployment/config/#etc#nginx#conf.d#00_elastic_beanstalk_proxy.conf /etc/nginx/conf.d/00_elastic_beanstalk_proxy.conf"

As you can see from this brief tutorial, there weren't too many adjustments that were needed to add a reverse server proxy to your ElasticBeanstalk instance. Just an additional code block and IP Address to point to and you will be running various servers from your domain in no time.