Published on

Hosting static website with AWS Cloudfront

  • foto
    Krzysztof Olszewski

How to host a static website with AWS services

I would like to show you step by step, how to use AWS services, to create website installation with automated manner.


I'm using OVH as domain registar, so we have to configure ovh provider for Terraform. To get API login required keys, we have to specify, which part of the API we will be using, in our case its domain/* path. For better security we can restrict access to our API, to specific IP's.

AWS Certificate Manager

Project we want to host should be available under subdomain, so we put neccessary variables into work: domain_name = "" & cert_domain_name = "" and generate certifiacate using ACM.

It's important to know, that w can create our certs only within us-east-1 AZ

resource "aws_acm_certificate" "website-cert" {
  domain_name       = var.domain_name
  subject_alternative_names = [ var.cert_domain_name]
  validation_method = "DNS"
  lifecycle {
    create_before_destroy = true

Because we have more than one domain, we have to create validation records in ovh service.

resource "ovh_domain_zone_record" "ovh_acm_record" {
    for_each = {
      for dvo in : dvo.domain_name => {
        # name = trim(dvo.resource_record_name, ".")
        name = dvo.resource_record_name
        record = dvo.resource_record_value
        type = dvo.resource_record_type

    zone      = var.domain_name
    # name of the record
    subdomain =
    fieldtype = each.value.type
    ttl       = "60"
    # value of the record
    target    = each.value.record

So we are using DNS validation method, and Terraform create for us two neccessary records, which can be seen at OVH web cloud settings panel.


Our S3 bucket will be private, and only our cloudfront distrbution intstance will have access to it, in oposite to basic public accessible website buckets.

To setup this functionality we have to use Origin Access Identity:

resource "aws_cloudfront_origin_access_identity" "origin_access_identity" {
    comment = "access-identity-${var.cert_domain_name}"

and we can define our cloudfront s3_distribution:

resource "aws_cloudfront_distribution" "s3_distribution" {
  origin {

    # Origin domain
    # domain_name = aws_s3_bucket.s3_front_website_bucket.bucket_regional_domain_name
    # FIXME: terraform return same result as for bucket_domain_name
    domain_name = "${var.cert_domain_name}"
    origin_id   = var.cert_domain_name

    s3_origin_config {
      origin_access_identity = aws_cloudfront_origin_access_identity.origin_access_identity.cloudfront_access_identity_path

  # for CNAME setting
  aliases = [var.cert_domain_name]

  enabled             = true
  is_ipv6_enabled     = true
  comment             = var.cert_domain_name
  default_root_object = "index.html"

as you can see, there is an unsolved problem with Terraform behaviour, that wont let us configure properly domain name, so wh have to hardcode it domain_name = "${var.cert_domain_name}".


After running our playbook we can access website under generated by AWS * domain name. We can simple create CNAME record in ovh dns zone settings and get fully working static website with ovh hosted custom domain.