---
title: Simple static web hosting AWS infrastructure with protected Dev environment
slug: simple-static-web-hosting-aws-infrastructure-with-protected-dev-environment
date: 2023-04-19T00:00:00.000Z
lastMod: 2026-06-08T00:00:00.000Z
draft: false
description: >-
  Step-by-step AWS static hosting setup with public prod and protected dev
  environments—CloudFront, S3, WAF, Route53, and GitHub Actions for branch
  deployments.
thumbnail: >-
  https://oleksiipopov.com/articles/static-web-hosting/dev-and-prod-simple-hosting.png
tags:
  - AWS
  - Hosting
  - Solution design
keywords:
  - Simple static web hosting
  - AWS infrastructure
  - Protected Dev environment
  - Web app development projects
  - Preview environment
  - Confidential development
  - Secure environment
  - Private web app environment
  - HTML reports
  - Single page apps
  - UI library samples
  - Web assets
  - Hosting infrastructure
  - Dev environment protection
  - Firewall protection
  - White list IP ranges
  - AWS services
  - GitHub Actions
  - Continuous integration
  - Continuous delivery
  - CI/CD
  - S3 bucket hosting
  - Distribution artifact
  - Feature branch deployment
  - Production hosting
  - Development hosting
  - CloudFront distributions
  - Route53 hosted zones
  - Caching policy
  - Price class
  - Viewer restriction
  - Web Application Firewall (WAF)
  - Infrastructure as a code
  - Implementation example
  - GitHub repository
  - Main branch deployment
  - Test branch deployment
  - Whitelisted visitor IP
  - Public production environment
  - Private development environment
  - External visitor testing
  - Hosting environments testing
  - Basic authentication
  - Dynamic subdomains
  - Browser routing
  - Localization detection
  - Automatic redirection
  - Non-cached production clone environment
  - Pre-rendering
canonical_url: >-
  https://oleksiipopov.com/blog/simple-static-web-hosting-aws-infrastructure-with-protected-dev-environment/
markdown_url: >-
  https://oleksiipopov.com/blog/simple-static-web-hosting-aws-infrastructure-with-protected-dev-environment/index.md
---
# 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:

* HTML reports
* Single page apps without browser routing (i.e. `/my/favorite/pag`), or with routing via hash (`/#my/favorite/page`) and search parameters (`/?nav=%2Fmy%2Ffavorite%2Fpage`)
* Demo apps with UI library samples
* Web assets without the app itself
* etc.

Lets consider next URL requirements as minimal and sufficient:

* The public production environment is available at [https://simple-hosting.examples.oleksiipopov.com](https://simple-hosting.examples.oleksiipopov.com)
* The Dev environment is available privately at [https://dev.simple-hosting.examples.oleksiipopov.com](https://dev.simple-hosting.examples.oleksiipopov.com)
* Feature branches are deployed to the destination path, corresponding to the URL-safe formatted git branch name. For instance, **https://dev.simple-hosting.examples.oleksiipopov.com/[branch-name]/**
* Deployment happens with help of GitHub Actions
* For simplicity, the Dev environment is protected by a firewall that has a white list of public ip ranges

## Need a website hosting solution?

Feel free to [reach out for consultation](https://oleksiipopov.com/contact)!

## 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](https://oleksiipopov.com/articles/static-web-hosting/gha-and-simple-hosting.png "GitHub Actions deliver artifacts to the S3 hosting origin bucket")

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

* `/main/index.html`
* `/main/js/index.min.js`
* `/styling-issue-123/index.html`

## 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](https://oleksiipopov.com/articles/static-web-hosting/dev-and-prod-simple-hosting.png "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:

* URL
* Caching policy
* Price class
* Viewer restriction

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](https://oleksiipopov.com/articles/static-web-hosting/simple-hosting-with-hidden-dev.png "Detailed AWS infrastructure of hosting")

## Implementation example

Check out this GitHub repository with the implementation example [https://github.com/AlexeyPopovUA/simple-hosting](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:

* Public production: [https://simple-hosting.examples.oleksiipopov.com/](https://simple-hosting.examples.oleksiipopov.com/)
* Private development:
    * “main” branch: [https://dev.simple-hosting.examples.oleksiipopov.com/main/](https://dev.simple-hosting.examples.oleksiipopov.com/main/)
    * “test” branch: [https://dev.simple-hosting.examples.oleksiipopov.com/test/](https://dev.simple-hosting.examples.oleksiipopov.com/test/)

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](https://oleksiipopov.com/articles/static-web-hosting/public-production-environment.png "Public production environment")
![Private “main” development environment](https://oleksiipopov.com/articles/static-web-hosting/private-main-development-environment.png "Private “main” development environment")
![Private “test” development environment](https://oleksiipopov.com/articles/static-web-hosting/private-test-development-environment.png "Private “test” development environment")

**For any random external visitor:**

![Public production environment](https://oleksiipopov.com/articles/static-web-hosting/public-production-environment.png "Public production environment")
![Private “main” development environment](https://oleksiipopov.com/articles/static-web-hosting/external-visitor-test-environment.png "Private “main” development environment")
![Private “test” development environment](https://oleksiipopov.com/articles/static-web-hosting/external-visitor-main-environment.png "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:

* Public environment behind basic authentication
* Dynamic subdomains and proper browser routing
* Dynamic localization detection and automatic redirection to the route of given locale
* Non-cached hidden production clone environment for pre-rendering and automation testing

### Follow-up: many demo apps on one distribution

In 2026 I revisited this pattern for a different constraint: **many small static apps** (demo links for quick experiments and AI-assisted workflows), not one product with a private dev host. The follow-up article [Static hosting for vibe coders: one platform, many apps](https://oleksiipopov.com/blog/static-hosting-for-vibe-coders/) keeps the same S3 + CloudFront + GitHub Actions spine, but routes **subdomains per app**, uses **one shared distribution**, and ships **reusable GitHub Actions workflows** so each app repo adds only a short `deploy.yml`. Items from the list above — especially dynamic subdomains and proper browser routing — are addressed there. Private WAF-gated dev is deliberately traded for public preview URLs when the goal is “hand someone a link and iterate,” not hide work-in-progress from the internet.

## Ask me a question

If you have any questions about this article, please feel free to [contact me](https://oleksiipopov.com/contact) or create an issue in the demo app  [GitHub repository](https://github.com/AlexeyPopovUA/simple-hosting/issues/new). I will be happy to help you with your web app development projects and hosting infrastructure needs.
