This article is largely to document how to configure a Grails application to deploy to Elastic Beanstalk successfully with some specific requirements. Note this article reflects deployments based on Amazon Linux 2, as of August 2023.
There are many ways to deploy to AWS, In this particular scenario my requirements are as such.
- I have a setup AWS Code Pipeline setup to execute whenever I push to my GitHub repository.
- I am building an executable Jar file. As such my Beanstalk configuration is pure Java, not Tomcat.
- I am using Nginx as the web proxy in front of the application.
- I want non-https traffic to redirect automatically to https.
- I also need Nginx to allow uploads from users of payloads larger than the 1MB default.
- My build instructions should use Java 17
It is assumed all AWS resources are setup, Beanstalk, CodePipeline, CodeBuild, etc. This is not a full tutorial.
Nginx Custom Configuration
In the root of the Grails application, we need to create configuration fails at very specific paths. All additional configurations can go into a single file, but I like to separate configs per their primary function, so in my case, you’ll see I have two files.
Create a folder within the root of your project, (NOT within grails-app) named
.platform/nginx/conf.d/elasticbeanstalk
My first file here is to provide the redirect behaviour. This is named 00_application.conf and contains the following:
location / {
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;
}
proxy_pass http://127.0.0.1:5000;
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;
}
The second file is named 01_client_size.conf and simply contains the following:
client_max_body_size 50M;
This as it suggests, configures Nginx to accept uploads of a maximum of 50M, this can be changed as required.
AWS CodeBuild Configuration
The next task is to configure AWS CodeBuild to correctly package our Jar file and include the configuration in the root of the produced artifact.
Create a buildspec.yml file, again in the root folder of your project. The contents of my file are as such:
version: 0.2
phases:
install:
runtime-versions:
java: corretto17
pre_build:
commands:
- echo Running tests
- sudo chmod +x ./gradlew
- ./gradlew clean --stacktrace
- ./gradlew assemble --stacktrace
- ./gradlew test --stacktrace
build:
commands:
- echo Building jar
- ./gradlew bootJar
post_build:
commands:
- echo Build completed
- mkdir deploy
- cp build/libs/*.jar deploy/
- cp -r .platform deploy/
- cd deploy
cache:
paths:
- '/root/.gradle/wrapper/**/*'
- '/root/.gradle/caches/**/*'
- '.gradle/**/*'
artifacts:
files:
- '*.jar'
- '.platform/**/*'
base-directory: 'deploy'
discard-paths: no
The majority of examples and tutorials you will probably find on this subject will instruct you to use discard-paths: yes however the key difference here is that it’s absolutely mandatory to maintain the .platform directory structure in order to configure Nginx. So therefore in the post_build section, we are creating a deploy folder to contain our compiled Jar in the root, and also the Nginx configuration in it’s expected structure.
As ever, we hope this helps someone facing this sometimes challenging task of what should be a simple deployment configuration.