Deploy a Web Application on EC2 in 1 hour

Wojciech Marusarz
February 12, 2021

Including Spring Boot app in Kotlin, Vue.js app, MongoDB, Docker containers, Traefik reverse proxy, AWS EC2 setup, configuring Domain, Cloudflare and Mailgun

Technologies used

Have you ever come up with a great idea for a web app but were held back by doubts and fear of spending lots of your precious time coding – only to learn that nobody can use it? What if the project ends up being another git repository buried somewhere in the github limbo and waiting indefinitely for it’s turn to come? If you ever had such thoughts, this skeleton app is for you.

This seed project takes care of the basic EC2 setup, deployment and hosting, allowing you to focus exclusively on your application’s requirements. For more details and source code visit Github

Ready, steady, go - 60 minutes left! #

  • 08:00 - Clone git repository
  • 08:02 - Setup you working environment [readme]
  • 08:10 - Run application on localhost, use docker or build tools [readme]
  • 08:14 - Setup EC2 and Ansible [readme]
  • 08:22 - Create configuration file with secrets and IP addresses [readme]
  • 08:32 - Run application and make it accessible by IP [readme]
  • 08:36 - Buy a domain and configure cloudflare for redirections [readme]
  • 08:46 - Configure SMTP server [readme]
  • 08:52 - Create another configuration file with secrets and domain names [readme]
  • 08:56 - Run application and make it accessible by your domain [readme]
  • 09:00 - You’re done – coffee time before you start coding on your own

To observe the effects of your efforts, visit your domain. You should be able to see the application ready for further development below. You can also visit my domain to see how it works in real life – https://wmarusarz.space

Vue.js SPA Application Main Page

The application, when opened, sends a request to verify communication between UI and API – you can see it in the browser Dev Tool in Network tab. Additionally, if you have configured SMTP, you can verify also if emails are sent.

If you would like to update your application, consecutive builds and deployments will take just 30 seconds – just run the run-redeploy-domain.sh script and wait two minutes until it’s done.

For better understanding, I recommend reading it all in a README.md file.

Package contents #

To help you make sure that the project meets your needs I’ve broken it into four parts:

  • Vue.js application
  • Spring Boot application
  • Ansible – docerizing and deployment
  • Networking

This will allow you to develop your own application with just the basic knowledge of the scope of this seed project.

Vue.js application #

The UI application is a Single Page Application written in lightweight Vue.js version 2. It was generated with vue cli with minimal configuration enabled: vue router, Vuex, Lint and scss. Additionally Vuetify is used as a Material Design components library.

Npm is used to run or build the application. This creates a dist directory during the build, ready to be served by NGinx server. Please mind that the dist directory is a set of static files served by a web server. To enable UI application configuration (API address, Basic Auth credentials) script entrypoint.sh is triggered before the app starts to replace variables in config files with values from environment variables.

Spring Boot application #

Spring Boot application is generated with Spring Initalizr and it was supplemented with some configurations, libraries and plugins, which would be helpful during further development.

The application is written in Kotlin, which empowers the best programming practices and simplifies app development compared to Java. It also uses project Reactor and has a test environment configured with testcontainers on the board – read more HERE.

The application uses MongoDB (please take care of backups), it has CORS configured and is secured by Basic Authentication.

Gradle is used as build tool, with some plugins enabled:

Spring configuration is injected during application start. You can also use application.yml files specific for the profile. To monitor the application and preview configuration, you can use Spring Actuator.

Ansible – dockerizing and deployment #

Ansible is used to automate repetitive deployment tasks. One-time operations like creating an EC2 instance, assigning elastic IP to EC2, DNS & SMTP configuration are done manually.

Ansible takes care of installing software on EC2 (playbook-ec2-configure.yml), creating docker images and pushing them to ECR (playbook-push.yml) and running applications on EC2 (playbook-run.yml). To use ansible, providing minimal configuration (pb-config.yml) described in README.md is required.

Docker is used to avoid installing java, nginx, mongo and to provide a fresh environment for each deploy. All services are wrapped into docker images, hosted on AWS ECR – ready for deployment.

Networking #

The application can be accessed in one of two ways – using IP address or Domain name.

If an IP address is used, almost nothing else has to be done. Just unlock some TCP ports for EC2 as described in README.md and you are done. Just build and push docker images and run applications.

More configuration is required when a domain name is used, but it’s still not much of a hassle.

First of all, buy a domain. Remember that domain renewal is usually more expensive than buying one, so don’t forget to disable auto-renewal.

When you own a domain, Cloudflare takes control over it. Cloudflare is responsible for:

  • redirecting requests to EC2 IP address,
  • creating a subdomain for API,
  • redirecting http to https,
  • encrypting requests between browser and Cloudflare.

When https request reaches EC2, Traefik is used as a reverse proxy. Traefik accepts all HTTPS requests (port 443), and basing on hostname (yourdomain.com, api.yourdomain.com), redirects requests to applications running in docker containers at specific ports: 8080 UI, 8081 Spring Boot. What is more, Traefik automatically challenges https certificates from letsencrypt.org so requests between Cloudflare and EC2 are also encrypted.

For sending emails, SMTP server configuration is required. Mailgun is used for this purpose.

This is what it all looks like in a big picture:

Networking scheme

Is it production ready? #

This application is great for fast prototyping, creating MVPs or even running non-demanding web apps. It also takes care of security with basic authentication, CORS, HTTPS, helping you avoid storing secrets in the repository. It also enforces some best code practices – lint and tests with testcontainers configured. The only thing that you need to take care of are database backups.

Remember there is still much to be done to make it production ready. If you expect high availability and redundancy, this application is not for you. To meet these requirements, you will probably need more infrastructure.

On an everyday basis, we take care of meeting the tiniest requirements of our customers.

The key point here is containerization, which provides lightweight containers that can be automatically deployed on multiple servers depending on traffic load - so called horizontal scaling.

How do we do this at nexocode? Let’s see below.

  • Multiple containers to run UI and API applications
  • Kubernetes for orchestration and application configuration management
  • Load balancer
  • MongoDB on remote servers with configured geo-replication
  • Logs aggregation with Elasticsearch, Kibana and Sentry
  • Terraform - for defining infrastructure as Code ( IaC), read more HERE
  • Prometheus and Grafana for monitoring
  • Gitlab as a CI/CD provider
  • Pre-production environments with e2e tests
  • Putting emphasis on communication, code reviews, code and tests quality

Clearly, it’s far from production ready, but… if you’re looking for a way to deploy a simple web application, this seed project is for you – it allows for a quick start and even faster updates, enforces best practices and is easy in use.

Now, let's talk about your project!

We don't have one standard offer.
Each project is unique, rest assured that we will approach the next one full of energy and engagement.

LET'S CONNECT