Skip to content

Instantly share code, notes, and snippets.

@henhan
Last active September 5, 2024 01:21
Show Gist options
  • Save henhan/2943013c9064606425b0ee5bb1ca8c99 to your computer and use it in GitHub Desktop.
Save henhan/2943013c9064606425b0ee5bb1ca8c99 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

@lucas-mdiniz
Copy link

For anyone using Docker platform.

Instead of uploading just the Dockerrun.aws.json with you should upload a zip file containing the Dockerrun.aws.json and the .platform directory.

@egarkavy
Copy link

@lucas-mdiniz thanks. This solution works
In my case I wanted to increase client_max_body_size so I created .platform\nginx\conf.d\elasticbeanstalk\01_client_max_body_size.conf with next contents: client_max_body_size 500M;
Then I do next:

  1. Generate json the same way but now have it's name just Dockerrun.aws.json, to satisfy default naming (before I was adding a version to this file)
  2. zip this json and .platform folder contents: zip -r <app_version>.app-name.zip Dockerrun.aws.json .platform/
  3. Push it to s3
  4. Upgrade EBT env the same way but now use .zip instead of Dockerrun.aws.json

@tfarkas86
Copy link

tfarkas86 commented Dec 8, 2023

nginx.conf

While Overriding the default location as mentioned in main gist I am receiving this error in my eb-engine.log nginx: [emerg] duplicate location "/" in /var/proxy/staging/nginx/nginx.conf:40
My EBS platform is Python 3.9 running on 64bit Amazon Linux 2023/4.0.0
How can i solve this??

From the look of this, it seems you have configured the nginx yourself from your dockerfile setup or something and it is interfrering with the EB nginx conf. try to log into the EC2 instance and inspect the issue from there because the defult nginx dosen't use the location the error is coming from and also try to change block and not the entire nginx conf as error would always occur after plaform upgrade etc. Elastic Beanstalk Nginx Configuration File nginx config for Elastic Beanstalk Amazon Linux 2 Default location (/etc/nginx/nginx.conf) not /var/proxy/staging/nginx/nginx.conf.

Are you sure about this? I'm not configuring any nginx properties other than the content in the .ebextensions folder, and I'm having exactly the same problem (duplicate "/" location). I "solved" it by overriding the nginx.conf file entirely, but I'd prefer a solution that is robust to any updates AWS might make to the default config. Could maybe try something inane like a commands key to modify the location block with sed or something ... personally I just need add a couple lines to it for basic authentication.

@ew-andriy
Copy link

nginx.conf

While Overriding the default location as mentioned in main gist I am receiving this error in my eb-engine.log nginx: [emerg] duplicate location "/" in /var/proxy/staging/nginx/nginx.conf:40
My EBS platform is Python 3.9 running on 64bit Amazon Linux 2023/4.0.0
How can i solve this??

From the look of this, it seems you have configured the nginx yourself from your dockerfile setup or something and it is interfrering with the EB nginx conf. try to log into the EC2 instance and inspect the issue from there because the defult nginx dosen't use the location the error is coming from and also try to change block and not the entire nginx conf as error would always occur after plaform upgrade etc. Elastic Beanstalk Nginx Configuration File nginx config for Elastic Beanstalk Amazon Linux 2 Default location (/etc/nginx/nginx.conf) not /var/proxy/staging/nginx/nginx.conf.

Are you sure about this? I'm not configuring any nginx properties other than the content in the .ebextensions folder, and I'm having exactly the same problem (duplicate "/" location). I "solved" it by overriding the nginx.conf file entirely, but I'd prefer a solution that is robust to any updates AWS might make to the default config. Could maybe try something inane like a commands key to modify the location block with sed or something ... personally I just need add a couple lines to it for basic authentication.

You solved problem? I have same

@vitalykarasik
Copy link

Are you sure about this? I'm not configuring any nginx properties other than the content in the .ebextensions folder, and I'm having exactly the same problem (duplicate "/" location). I "solved" it by overriding the nginx.conf file entirely, but I'd prefer a solution that is robust to any updates AWS might make to the default config. Could maybe try something inane like a commands key to modify the location block with sed or something ... personally I just need add a couple lines to it for basic authentication.

I have a similar question, regarding 'Document root' - I'd like to customize it without replacing the whole nginx.conf ().https://stackoverflow.com/questions/78232086/how-to-customize-nginx-document-root-in-aws-elastic-beanstalk-without-rewrite-wh

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