Skip to content

Instantly share code, notes, and snippets.

@koorukuroo
Forked from henhan/nginx_documentation.md
Created January 10, 2022 06:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save koorukuroo/bc396aab1cee7701bdbec04914fa002b to your computer and use it in GitHub Desktop.
Save koorukuroo/bc396aab1cee7701bdbec04914fa002b to your computer and use it in GitHub Desktop.
Extend and override nginx config for Elastic Beanstalk Amazon Linux 2

Extend and override nginx config for Elastic Beanstalk Amazon Linux 2

Documentation on how to override or extend the default nginx config on Elastic Beanstalk running om Amazon Linux 2. Correct as of 2021-08-01. Also see the general documentation on how to extend linux servers.

All references to placing files refer to putting a file at this location in your application bundle. You should never modify a file directly at your Elastic Beanstalk server by ssh:ing to the server, since such a change will be wiped whenever your servers autoscale or if you rebuild your application completely.

Adding a new location block

The easiest extension is to add a new location block to the main server block. This can be done by placing a .conf file with a server block in the folder .platform/nginx/conf.d/elasticbeanstalk. Any such file is automatically included in the main server block.

Overriding the default location

The default location block is most easily overridden by placing a file in the bundle at the location .platform/nginx/conf.d/elasticbeanstalk/00_application.conf. This will simply replace the default block provided by elastic beanstalk.

The default block looks like this (for node.js code - 2021-07-25 - other languages might run on a different port):

location / {
    proxy_pass          http://127.0.0.1:8080;
    proxy_http_version  1.1;

    proxy_set_header    Connection          $connection_upgrade;
    proxy_set_header    Upgrade             $http_upgrade;
    proxy_set_header    Host                $host;
    proxy_set_header    X-Real-IP           $remote_addr;
    proxy_set_header    X-Forwarded-For     $proxy_add_x_forwarded_for;
}

Forcing HTTPS

(Note that it might be a better idea to let the application load balancer handle this by redirecting traffic on port 80 to port 443 directly: https://aws.amazon.com/premiumsupport/knowledge-center/elb-redirect-http-to-https-using-alb/).

HTTPS can be forced by adding the following to the location block (note that it allows the health checker to use HTTP):

set $redirect 0;
if ($http_x_forwarded_proto != "https") {
    set $redirect 1;
}
if ($http_user_agent ~* "ELB-HealthChecker") {
    set $redirect 0;
}
if ($redirect = 1) {
    return 301 https://$host$request_uri;
}

Using basic auth

Basic auth can be activated by adding the following to the location block:

auth_basic "Restricted";
auth_basic_user_file /etc/nginx/.htpasswd;

Note that you will then have to write the content to the .htpasswd file somehow. This can either be done by placing a files block in a config file in the .ebextensions folder (see documentation), or by running some kind of script to write the file. Such a script should be an executable file placed in either .platform/hooks/predeploy or .platform/confighooks/predeploy depending on how the content for the .htpasswd file is generated.

If you want to pass the auth basic credentials to the backend, add this as well:

proxy_set_header    Authorization       $http_authorization;

It will then be set as Authorization header in the backend. The content of this header will be Basic followed by the string username:password encoded as Base64.

Making basic auth work with health check.

To make the health check work with basic auth, you can set up a separate location block that does not require basic auth. Don't give this path access to any sensitive information, only to a basic healt check. Here's an example that allows the health check to access /elb-status, which is then passed on to a status route in the application:

location /elb-status {
    proxy_pass          http://127.0.0.1:8080/status;
}

Extending nginx configuration

The default nginx config will load any config file ending with .conf and placed in .platform/nginx/conf.d. You can use this to create new server blocks. This is the way to go if you need to do more than extend the default server block. If you create new server blocks you will have to check how nginx will prioritize the traffic. See https://www.digitalocean.com/community/tutorials/understanding-nginx-server-and-location-block-selection-algorithms.

Overriding the default nginx configuration

To get complete control of the nginx configuration, it is possible to override the whole config. This is done by placing a full nginx configuration as .platform/nginx/nginx.conf. Only do this if you have to, since you will have to manually check if there is any changes to the default config for new releases to make sure that your configuration is still valid.

If you decide to override the full config, it is a good idea to include the content of the file found in /etc/nginx/conf.d/elasticbeanstalk/health.conf to get the health checking config as well (this also goes for new server blocks).

Default nginx configuration for reference

The following is the current nginx config used for node.js applications (as of 2021-07-25). It is mainly here for reference. You should ssh to your instance and check the currrent configuration to make sure that you're manipulating the latest version.

# Elastic Beanstalk Nginx Configuration File

user                    nginx;
error_log               /var/log/nginx/error.log warn;
pid                     /var/run/nginx.pid;
worker_processes        auto;
worker_rlimit_nofile    32633;

events {
    worker_connections  1024;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    include       conf.d/*.conf;

    map $http_upgrade $connection_upgrade {
        default     "upgrade";
    }

    server {
        listen        80 default_server;
        access_log    /var/log/nginx/access.log main;

        client_header_timeout 60;
        client_body_timeout   60;
        keepalive_timeout     60;
        gzip                  off;
        gzip_comp_level       4;
        gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript;

        include conf.d/elasticbeanstalk/*.conf;
    }
}

Old invalid documentation

Much documentation provided by Amazon is invalid since the behavior has changed for Amazon Linux 2. This config (and the rest of the repo from how it looks) for example only works for Amazon Linux 1: https://github.com/awsdocs/elastic-beanstalk-samples/blob/master/configuration-files/aws-provided/security-configuration/https-redirect/nodejs/https-redirect-nodejs.config

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment