Simple static web hosting AWS infrastructure with protected Dev environment

Why

When working on web app development projects, it’s often useful to have a separate environment where unfinished work can be previewed without being visible to the public. This is particularly important for companies who want to keep their work confidential and secure within their network, or for developers who want to give access to specific users on the internet. In this article, we’ll explore one of the ways to create a private web app environment and how it can benefit your development process.

We will consider such a group of applications that don’t use browser routing for simplicity of hosting infrastructure. In this article a solution idea is more important than a particular website functionality.

Such applications could be:

Lets consider next URL requirements as minimal and sufficient:

How

Solution proposed here is a combination of AWS and GitHub services. AWS is used for hosting and GitHub Actions – for continuous integration and delivery.

CI/CD side

Role of GitHub Actions is to build the distribution artifact and put it to the hosting storage, which is in our case an S3 bucket.

GitHub Actions deliver artifacts to the S3 hosting origin bucket
GitHub Actions deliver artifacts to the S3 hosting origin bucket

Application artifact is a feature branch directory with files. For instance,

Hosting side

Production hosting should serve files from the /main directory, but the Development one – from the root "/". When serving from the root, all subdirectories become available for the Dev hosting, so it can serve from all of those at the same time.

The role of AWS is to implement 2 environments: Development and Production. External public can see only the production web app. When trying to open development URL’s, they see 403 error page from AWS CloudFront. Internal public and external maintainers and clients are supposed to be “whitelisted”. They should see all environments.

Separation of environments
Separation of environments

The environments can be implemented with 2 CloudFront distributions. 1 for each environment. Those will be available via human-readable domains, configured in Route53 hosted zones. S3 bucket is their common origin of files.

The difference between them is in the next things:

URLs are obviously different by design.

Cache policy sets TTL (Time To Leave) configuration, which can be longer (1 hour – 1 day) for Production and shorter (1 second – 1 minute) for Development. The longer the TTL the better, but for the frequently updated environments that becomes a problem – we need to run tests and showcase changes as we go.

Price class of distribution depends on your latency requirements for the client locations. CloudFront has edge locations all over the world. The lower class offers fewer locations than the higher one. Production usually uses the highest class. For the development, the lowest one is enough.

Viewer restrictions can be implemented in different ways. The easiest is to attach a Web Application Firewall (WAF) to the Dev CloudFront distribution. It should have a white list of IP ranges. Usually, the company offices have internal networks with gateways to the internet that have static public IP addresses. External clients and maintainers join these networks via VPN connection. That makes them also virtually present in the internet under the company IP range. So, putting this IP range to the WAF white list “authorizes” visitors to see the private hidden environment. It makes sense to enable only IPv4 support for the Dev CloudFront distribution, because IPv6 is dynamic and cannot be used for a long time in WAF IP list.

So in the end we should get the next AWS solution

Detailed AWS infrastructure of hosting
Detailed AWS infrastructure of hosting

Implementation example

Check out this GitHub repository with the implementation example https://github.com/AlexeyPopovUA/simple-hosting.

It is written with aws-cdk, following the “infrastructure as a code” idea. Deployment happens automatically with GitHub actions for the “main” branch.

Next hosting environments are deployed:

The web application was kindly generated by ChatGPT. I uploaded it manually to the origin S3 bucket.

So, for the “whitelisted” visitor IP, we can see the next results:

Public production environment
Public production environment
Private “main” development environment
Private “main” development environment
Private “test” development environment
Private “test” development environment

For any random external visitor:

Public production environment
Public production environment
Private “main” development environment
Private “main” development environment
Private “test” development environment
Private “test” development environment

Hosting environments were tested by adding home router public ip to the white list of AWS WAF. The NordVPN client was used to test the external visitor case.

Conclusions

In this article, a simple hosting environment infrastructure for web applications was suggested. Private environments are very helpful when you need feature branches during the development of web projects. Such a system is easy to understand and maintain. It can be used as a first step towards complex CI/CD and hosting setup of a growing project.

Additional requirements usually come later. For instance:

Developed by Oleksii Popov
2024