CloudFront and Lightsail

『CloudFront and Lightsail』, the subject of this article, are the key to 『publishing』 a Drupal-built website that's been converted to HTML, structure included. Here I've put together how I use 『CloudFront and Lightsail』 to publish the HTML-converted site.

This article walks through the actual work I did: moving from a Drupal site running on Lightsail with Bitnami, over to a new Lightsail server built for serving the static files.

Notice

I'm holding back on the detailed AWS configuration this time, since it touches on security.

Attack tools that appear to be mass-produced using AI have been increasing lately. Regardless of AWS specifically, I think it's necessary to consider the possibility that AI learns from the configuration details I write, and even if the AI's own learning carries no malicious intent, the knowledge could still be put to malicious use by whoever's using it.

If information shared here in good faith ends up being used with bad intent, the impact wouldn't be limited to this site alone — that's the thinking behind this decision.

Realistically, an article of mine about configuration (essentially an extension of already-public information) isn't worth much from a training-data standpoint, but there's a real possibility that AI could learn from the concrete, specific knowledge — the practical know-how — that I write about.

Given how today's LLMs form their reasoning through probability, I can't rule out the possibility that AI could learn the defensive information I describe here — the basics of security — and then use it as a hint when answering a question aimed at the opposite: an attack. That's what led me to conclude it's better not to publish the actual configuration details in this article.

『Table of Contents』

  1. Top --- What this work involved
  2. #01 ACM --- Getting an SSL certificate through ACM for CloudFront
  3. #02 Cloud Front --- Creating a CloudFront distribution
  4. #03 Route53 --- Moving DNS from Lightsail to Route 53, and serving the existing Drupal site through CloudFront.
  5. #04 Lightsail  --- Building a new Lightsail server to host the static files
  6. #05 Switching the Origin  --- Switching the origin server. Delivery moves from Drupal to Jamstack.
  7. #06 Conclude  --- Wrapping up this round of work

Clicking the numbers in the simple navigation bar at the bottom of the page will jump to that part of the article. Feel free to use it when re-reading.

Here I've put together the AWS configuration and setup needed for going Jamstack this time.

Notes

1.  The Drupal site running on Lightsail with Bitnami has everything packaged together, DNS included. A limited-feature version of CloudFront — covering CDN and WAF — comes packaged as an option too, but I'm not using it.

2.  To use CloudFront's full feature set, I'm moving DNS from Lightsail to Route 53.

3.  Rather than the Let's Encrypt certificate Bitnami Drupal obtained, I'm getting and managing a new SSL certificate through ACM.

4.  Since I'm switching over from the Bitnami-run Drupal site to a new Lightsail server hosting the static files, I finished setting up CloudFront ahead of time and make the cutover through DNS.

Since I'm switching from the live Drupal site to serving Jamstack-converted HTML, I worked through the steps in this order.

1.  Get a new SSL certificate through ACM, since I'll be using CloudFront

2.  Create a CloudFront distribution

3.  Move DNS from Lightsail to Route 53

4.  Serve the existing Drupal site through CloudFront

5.  Build a Lightsail server for serving the static files

6.  Switch DNS to the new server (CloudFront then serves with the new server as its origin)

7.  Once the switch is done, confirm DNS propagation (roughly 48 hours), then stop Bitnami Drupal and delete the instance

This time, I built the new Jamstack site while keeping the old Bitnami Drupal running, then cut over — this article walks through that process.

ACM

Using CloudFront requires getting an SSL certificate through ACM.

ACM (AWS Certificate Manager) handles issuing, managing, and auto-renewing the SSL/TLS certificates used on AWS. Public SSL/TLS certificates can be issued and used at no extra cost, and since ACM renews them automatically, there's no manual renewal work needed.

A certificate issued through ACM is only valid within its region (a certificate issued in Tokyo, for instance, can't be used in Osaka).

Since CloudFront is a global service, the SSL certificate must be issued in us-east-1 (US East, N. Virginia) whenever you're using CloudFront.

Here's the actual procedure.

  1. AWS Console → Certificate Manager → switch the region to us-east-1
  2. Request a certificate → Public certificate
  3. Add domain names: inter-est01.com, *.inter-est01.com
  4. Validation method: DNS validation
  5. Register the issued CNAME record in Lightsail DNS (once Route 53 is set up, register it there instead)
  6. Once the status shows "Issued," you're done

That completes issuing the SSL certificate for use with CloudFront.

CloudFront

CloudFront is AWS's CDN (content delivery network), offering a highly optimized delivery network built on caching and edge locations around the world. It comes with a firewall built in by default, and WAF is available as an option starting from the free tier, so it protects the origin server with strong security.

I wasn't using it with Bitnami Drupal, but since I'm switching to static delivery this time, I decided the benefits of using a CDN were significant enough to bring it in. It's really a full-featured CDN built for large-scale sites, flexible enough to handle clustering and more, but because everything fits together so well within AWS, it's also usable for a small site like mine — that's one of AWS's strengths.

Now I'll create a CloudFront distribution.

  • AWS Console → CloudFront → Create distribution

Origin Settings 

  • Origin type : Custom originOrigin domain : (choose any subdomain).inter-est01.com
  • Create an A record in Lightsail DNS: (choose any subdomain).inter-est01.com → 111.222.333.444 (Lightsail's static IP)
  • Protocol: HTTP only

Notice : The CloudFront console doesn't accept a bare IP address, so a DNS name is required.

Cache Settings

  • Cache policy : CachingDisabled (TTL=0, fetched from the origin every time)
  • Origin request policy : AllViewer (forwards all headers to the origin)

WAF Settings

  • Enable WAF (basic protection plus rate limiting on the free plan)

HTTPS Settings

  • Viewer protocol policy : Redirect HTTP to HTTPS
  • SSL certificate : select the ACM certificate issued in #1

CNAME Settings

  • inter-est01.com
  • [www.inter-est01.com](https://www.inter-est01.com)

That completes the basic CloudFront setup.

Route 53

Lightsail DNS can't ALIAS an apex domain to CloudFront, so I'm moving to Route 53. Once Route 53 is set up and DNS switches over, Bitnami Drupal starts being served through the CloudFront setup from #2.

Creating a Hosted Zone in Route 53

  • Route 53 → Create hosted zone → inter-est01.com

Creating Records

  • inter-est01.com | A (ALIAS) | (the alphanumeric string provided).cloudfront.net
  • [www.inter-est01.com](https://www.inter-est01.com) | CNAME | (the alphanumeric string provided).cloudfront.net
  • (any subdomain).inter-est01.com | A | 111.222.333.444 (the old Bitnami IP)
  • Mail-related | MX/TXT/CNAME | copied over from the old DNS.

I set the four Route 53 NS records at the domain registrar, then wait for DNS to propagate (anywhere from a few minutes to a few hours).

Once DNS switches over, Bitnami Drupal is served through CloudFront.

I use a custom module to restrict Drupal login by IP. Once traffic goes through CloudFront, that IP-restriction module can no longer see the real client IP, which locks me out of logging in — so I fix this by adding the following to settings.php.

Setting Drupal's reverse proxy configuration.

# sudo nano /opt/bitnami/drupal/sites/default/settings.php
Add the following:
if (PHP_SAPI !== 'cli') {
  $settings['reverse_proxy'] = TRUE;
  $settings['reverse_proxy_addresses'] = [$_SERVER['REMOTE_ADDR']];
}
Once you've added and saved that, run:
# drush cr

With that, Bitnami Drupal is served through CloudFront. Once the Lightsail setup for the incoming Jamstack site and its content upload are done, the cutover is just a matter of changing the Lightsail IP address in Route 53.

Lightsail

Now I'll build the new Lightsail server that will host the static files.

Creating the instance.

  • Region : your choice (I'm holding back on which region I actually used)
  • Blueprint : Ubuntu 24.04 LTS (OS only)
  • Plan : $12/month (2GB RAM / 2vCPU / 60GB SSD)
  • SSH key : using an existing key
  • After creation, assign a static IP (111.222.333.444)

Initial setup

# Log in
ssh -i ~/.ssh/(Any name).pem ubuntu@111.222.333.444
# Update the system
sudo apt update && sudo apt upgrade -y
# Reboot if the kernel was updated
sudo reboot

From here I go on to configure Apache, set the document root, configure the virtual host, set up security, and configure internal routing — but as I mentioned at the start, I'm holding back on posting those details here out of consideration for security.

Once Lightsail is set up, I upload the HTML content generated by Tome.

Switching the Origin

Now I actually serve, through CloudFront, the content built locally with Drupal and converted to static files with Tome.

Since Bitnami Drupal is already being served through CloudFront and DNS is managed through Route 53 at this point, the cutover is complete just by 『changing the A record set for the origin server, in Route 53, to the new server's IP』.

As covered in the #3 Route 53 section,

(any subdomain).inter-est01.com | A | 111.222.333.444 (the old Bitnami IP)

switching this to

(any subdomain).inter-est01.com | A | 555.666.777.888 (the new Lightsail IP)

is all it takes — CloudFront > Bitnami Drupal becomes CloudFront > the static files on Lightsail, and Jamstack is complete.

Since TTL is set to 0 seconds (checking for changes every time), the update happens automatically, but CloudFront is also a globally edge-cached server, so just to be safe, I clear the cache to avoid old content getting mixed in with the new during the switch.

Going to CloudFront console → Distributions → Invalidations → Create invalidation → /* (everything) clears the entire cache, ensuring the new server's content gets properly cached.

Conclude

Uploading the static files — built locally with Drupal and Tome, as covered in the previous article — to a newly spun-up Lightsail instance that has only SSH and Apache open, with internal routing configured against CloudFront, completes the Jamstack setup.

Each individual step and setting can feel like a hassle, but the work itself wraps up very quickly.

The Two Sides of AI

What I struggled with while writing this article is this: up to now, I've published information because I believed my articles could guide the people who need them, but since the start of this year, malicious use of AI — the easy mass-production of attack tools, for instance — has been on the rise.

AI projects of every size have sprung up, and AI bots are accessing websites en masse to train LLMs. If it were ordinary use, I'd be happy to contribute to that training, but LLMs as they stand right now don't account for whether the person using them has good or bad intentions, and unfortunately, malicious use has become conspicuous. I think it's necessary to work out a response to the situation where AI learns from information shared in good faith and that knowledge then gets put to malicious use.

Given that situation, I've been spending a fair amount of time just deciding what to put in an article, and it's become harder to publish tutorial-style content built around real, concrete examples.

It seems unlikely that an article of mine would directly hint at building an attack tool, but real-world server configuration examples could still end up being one of the hints or building blocks that go into one.

I myself find AI genuinely valuable — as an organic kind of tool for organizing my thinking, for translation, for broadening a technical perspective I didn't have before, and as a partner in experimenting with building this site.

Zoom out, though, and the world is full of uses that aren't like that. As one example, the string of events in the Drupal community this May — the PostgreSQL security response, the 11.4.x update, the widespread breakage that followed — I think that's also partly a consequence of the rapid spread of AI-driven attack tools, and the normalization of more sophisticated attacks that comes with it.

The direct reason I physically removed Drupal (the CMS) from the web this time, switching to a Jamstack setup that serves static files instead, was the end of support for AWS's Blueprint. But when I factor in how much more frequent CMS and framework security responses have become recently, and think through what tends to happen with update-related bugs, reducing both the risk of attacks (by going static) and the risk of update-related bugs as much as possible became one more reason behind my abrupt switch to Jamstack.

Every new technology has two sides. Not just the bright side but the dark one too — and even something like publishing information on a website, which might seem to have nothing to do with AI at first glance, requires accurately grasping what's actually happening right now around AI use and AI training, and responding to it accordingly.

Next article

The Effects of Jamstack (working title)

I'll cover the actual effects of going Jamstack this time.

Contributor
S.Takeda
Article
Tag

Powered by Drupal 11.4.6 and Bootstrap5 4.0.8

Published AWS Jamstack by Drupal