AWS Elastic Beanstalk: Single Container Tricky Part


When using Elastic Beanstalk from AWS we faced some behaviors that dont fit what we wanted. Before we tell you what it is and how are we deal with, as in the post title we use single container EB. Therefor we utilize Docker and Nginx provided in that single container EB (yes this EB is Nginx included). Ok its time to show what we faced.

Elastic IP

We use load balanced cluster to serve our production web. By default EB will use public EIP in a load balanced cluster. Why could this be an issue? AWS limit EIP usage. Although it could be increased via support center, but the approval could take some times. When we need more nodes in our cluster and hit the EIP limit usage thats the problem. Beside, best practice around the web suggest to use internal network in a cluster. We decided to go with no public IP in our cluster, this is what we add in our EB config through ebextensions:

Docker log driver*

We use fluentd as our log data collector via docker log driver. First, this will need fluentd agent running in host, its simple fluentd provide official script for this here http://docs.fluentd.org/v0.12/articles/install-on-beanstalk

Then we should tell docker to use fluentd for log driver. Thanks for this, so we could figure how to do it:

Nginx*

What is special about nginx here? We need some adjustment essentially for https redirect. It could be done in our application code actually, but since nginx is in EB stack we prefer to use it. We already decided to put SSL Certificate on ELB before. ELB need a health check url in every cluster node, because SSL cert is on ELB we need to exclude health check url in https redirect. Guess what? Its trivial to do with nginx. We also add other adjustment like hide nginx version and increase client maximum upload size.

Our application capture client IP Address to log several events and this is problematic at beginning. Our application keep record ELB private IP address, its because now our app is behind two reverse proxies ELB and nginx. Nginx aready provide solution to this issue by using set_real_ip_from directive, thanks for this post so we got the big picture.

This is our final ebextensions file for nginx configuration looks like:


* As we write this post we use EB stack with Docker v1.12.6, other version might need adjustment. (Update: this Nginx configuration still usable with Docker v17.03.1-ce)

Nginx Gotchas: Location and Rewrite Directive

I use Nginx for web server, reverse proxy and load balancer because of its lightweight and easier to configure than other web server application. For example, when I need to set particular vhost to be default, all I have to do is adding or moving default_server parameter at listen directive. That was much easier compared with Apache Httpd. But, sometimes I need to debug my configuration when it misconfigured or didn't run as expected. So these are some gotchas when I debug my Nginx configuration.

Location precedence
I have this experience when some location never accessed, Nginx always use other location when client access it. Turns out I didn't have any idea how Nginx read location precedence at that time, so I dig into its documentation and found out this precedence:
  • ~* uri_pattern
    This configuration will match request with uri_pattern regex case insensitive.
  • ~ uri_pattern
    This configuration will match request with uri_pattern regex case sensitive.
  • = /uri
    This configuration will match request with exact /uri
  • /uri
    This configuration will match uri with prefix /uri (eg. /uri/index.html)
  • ^~ uri_pattern
    This configuration will match with uri_pattern but if the longest matching prefix location has the ^~ modifier then regular expressions are not checked.
  • /
    All other request uri unmatched above pattern will be passed to this location

Rewrite Directive
All you have to do is pay attention on the flag parameter, as described in documentation there are four flags you can use:
  • last
    It stops processing the current set of rewrite directives and starts a search for a new location matching the changed URI;
  • break
    It stops processing the current set of rewrite directives as with the break directive;
  • redirect
    It returns a temporary redirect with the 302 code, used if a replacement string does not start with “http://” or “https://”;
  • permanent
    It returns a permanent redirect with the 301 code.
Once you know how rewrite flag work, it will make you easy to choose which one is appropriate with your situation.

Apache httpd: Default Virtual Host


I have several virtual host configuration in my httpd.conf. Today i need to one of it can be accessible in a local wifi network. I knew it will require a DNS configuration pointed my IP address to a domain name on the router. But unfortunately I have no access to the router.

Second choice is directly point my IP address in any client hosts file who want to access my virtual host. But it will be painful due to my IP address was  configured dynamically by router DHCP server, what if it change? I have to edit all client host file again? No thanks.

Based on this Apache httpd documentation, first VirtualHost block in the configuration file has the highest priority and can be seen as the default or primary server. That means that if a request is received that does not match one of the specified ServerName directives, it will be served by the first VirtualHost. Finally I use this last option, all I have to do is put desired virtual host block to the first block, then all host in my local wifi network can access it with my current IP address.

* image from : www.thetechnicalstuff.com