Deploying dotnet6 app on AWS ElasticBeanstalk Graviton2 with HTTPS termination on EC2 instance
On one of my project it was a requirement to reduce the ElasticBeanstalk hosting costs to minimum for dotnet application. The app is a kind of dashboard with limited audience and nothing heavy inside. I decided to use Graviton2 instances (ARM processors on board) in order to acheave best speed/cost ratio.
Table of content:
- Build dotnet app on Windows for arm linux environment
- Configure app to run on Linux environment in Amazon
- Configure app to terminate HTTPS connections at the instance
- Configure HTTP to HTTPS redirection
- Pack deployment package
Build dotnet app for arm linux environment
This is as easy as:
dotnet publish myproject.csproj --configuration Release --runtime linux-arm64 --output publish
That’s it. the ‘publish’ directory will contain your published app (not ready yet for Amazon EB).
Configure app to run on Linux environment in Amazon
You need to create Procfile for your application. It’s contect should look like this:
Procfile
web: dotnet ./myproject.dll
Configure app to terminate HTTPS connections at the instance
First you need to create ‘https-instance-single.config’ file that configures Amazon security group and port mapping. [reference].
https-instance-single.config
Resources:
sslSecurityGroupIngress:
Type: AWS::EC2::SecurityGroupIngress
Properties:
GroupId: {"Fn::GetAtt" : ["AWSEBSecurityGroup", "GroupId"]}
IpProtocol: tcp
ToPort: 443
FromPort: 443
CidrIp: 0.0.0.0/0
Then you need to create ‘https-instance.config’ file that describes your TLS certificates and where shoud they be placed on EB instance. [reference].
https-instance.config
files:
/etc/pki/tls/certs/server.crt:
content: |
-----BEGIN CERTIFICATE-----
..........................
-----END CERTIFICATE-----
/etc/pki/tls/certs/server.key:
content: |
-----BEGIN RSA PRIVATE KEY-----
..............................
-----END RSA PRIVATE KEY-----
container_commands:
01restart_nginx:
command: "systemctl restart nginx"
And ‘https.conf’ file to configure NGINX Web server where to find TLS certificate and how to use it.
https.conf
# HTTPS server
server {
listen 443 ssl;
server_name localhost;
ssl_certificate /etc/pki/tls/certs/server.crt;
ssl_certificate_key /etc/pki/tls/certs/server.key;
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
location / {
proxy_pass http://localhost:5000;
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 https;
}
}
Configure HTTP to HTTPS redirection
You need to create ‘00_application.conf’ file that defines http redirects [reference] + [StackOverflow thread].
00_application.conf
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;
}
Pack deployment package
Put all together:
publish
|───..Yout published dotnet app..
assets
│ Procfile
├───.ebextensions
│ https-instance-single.config
│ https-instance.config
└───.platform
└───nginx
└───conf.d
│ https.conf
└───elasticbeanstalk
00_application.conf
Finally you need to prepare the deployment artifact. If you are using Windows then you can’t use powershell ‘Compress-Archive’ to zip directories because it uses backslashes as path separators. SuperUser thread about this. We are going to use 7Zip.
."C:\Program Files\7-Zip\7z.exe" a -tzip publish.zip ".\publish\*" ".\assets\*"
Costs
AWS t4g.nano costs about $3/month.