Infrastruktúra

Statikus site villámgyorsan és biztonságosan: S3 + CloudFront + OAC, cache-stratégiával és Terraformmal

A privát S3 bucket, a CloudFront CDN és az Origin Access Control hármasa a modern statikus hosting alapja. Végigépítjük OAC-vel (nem a lejárt OAI-val), okos cache-fejlécekkel és HTTPS-sel — teljes IaC-kal.

Röviden: A privát S3 bucket, a CloudFront CDN és az Origin Access Control hármasa a modern statikus hosting alapja. Végigépítjük OAC-vel (nem a lejárt OAI-val), okos cache-fejlécekkel és HTTPS-sel — teljes IaC-kal.

Statikus oldalt (SPA, dokumentáció, landing) sokféleképp lehet hosztolni, de az AWS-en a bevált, gyors és olcsó minta világos: a fájlok egy PRIVÁT S3 bucketben ülnek, a világ pedig egy CloudFront disztribúción keresztül éri el őket. A kulcs az Origin Access Control (OAC), ami engedi, hogy CSAK a CloudFront olvassa a bucketet — közvetlen S3-URL-en senki. Fontos: az OAI (Origin Access Identity) a régi, immár nem ajánlott megoldás; ma OAC-t használunk. Építsük fel Terraformmal.

A cél-architektúra

A felhasználó a CloudFronthoz csatlakozik a hozzá legközelebbi edge locationön. Ha a tartalom a cache-ben van, azonnal kap választ; ha nem, a CloudFront az OAC-vel aláírt kéréssel behúzza az S3-ból, cache-eli, és kiszolgálja. Az S3 bucket policy csak ezt a CloudFront-disztribúciót engedi be.

OAC vagy OAI? A helyes választás

Ha régi tutorialt olvasol, OAI-t (Origin Access Identity) fogsz látni. Ez elavult: nem támogat minden régiót, nem működik SSE-KMS-sel jól, és az AWS az OAC-t ajánlja helyette. Az OAC aláírja a CloudFront→S3 kéréseket (SigV4), és minden modern esetet lefed.

SzempontOAC (ajánlott)OAI (elavult)
AláírásSigV4, minden régiókorlátozott
SSE-KMS titkosítástámogatottproblémás
Új funkciókigenbefagyasztva
AWS ajánlásezne

Az S3 bucket privátra zárva, Terraformban

A bucket teljesen privát: minden publikus hozzáférés tiltva. A tartalmat csak a CloudFront látja, a bucket policyn keresztül, amit lejjebb kötünk be.

hcl
resource "aws_s3_bucket" "site" {
  bucket = var.site_bucket_name
  tags   = local.tags
}

resource "aws_s3_bucket_public_access_block" "site" {
  bucket                  = aws_s3_bucket.site.id
  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}

resource "aws_s3_bucket_versioning" "site" {
  bucket = aws_s3_bucket.site.id
  versioning_configuration {
    status = "Enabled"
  }
}

Az OAC és a CloudFront disztribúció

Az OAC egy külön erőforrás, amit a disztribúció originjéhez kötünk. A cache-viselkedést egy managed cache policy adja (CachingOptimized), és kikényszerítjük a HTTPS-t.

hcl
resource "aws_cloudfront_origin_access_control" "site" {
  name                              = "${var.project}-oac"
  origin_access_control_origin_type = "s3"
  signing_behavior                  = "always"
  signing_protocol                  = "sigv4"
}

resource "aws_cloudfront_distribution" "site" {
  enabled             = true
  default_root_object = "index.html"
  price_class         = "PriceClass_100"

  origin {
    domain_name              = aws_s3_bucket.site.bucket_regional_domain_name
    origin_id                = "s3-site"
    origin_access_control_id = aws_cloudfront_origin_access_control.site.id
  }

  default_cache_behavior {
    target_origin_id       = "s3-site"
    viewer_protocol_policy = "redirect-to-https"
    allowed_methods        = ["GET", "HEAD"]
    cached_methods         = ["GET", "HEAD"]
    # Managed-CachingOptimized policy ID
    cache_policy_id = "658327ea-f89d-4fab-a63d-7e88639e58f6"
  }

  # SPA fallback: a 403/404 az index.html-re megy, hogy a kliens-router vegye át
  custom_error_response {
    error_code         = 403
    response_code      = 200
    response_page_path = "/index.html"
  }

  restrictions {
    geo_restriction {
      restriction_type = "none"
    }
  }

  viewer_certificate {
    cloudfront_default_certificate = true
  }

  tags = local.tags
}

A bucket policy: csak ez a disztribúció

Ez zárja be a kört: a bucket CSAK akkor ad ki objektumot, ha a kérés ettől a konkrét CloudFront-disztribúciótól jön. A AWS:SourceArn feltétel a lényeg.

hcl
data "aws_iam_policy_document" "s3_oac" {
  statement {
    actions   = ["s3:GetObject"]
    resources = ["${aws_s3_bucket.site.arn}/*"]
    principals {
      type        = "Service"
      identifiers = ["cloudfront.amazonaws.com"]
    }
    condition {
      test     = "StringEquals"
      variable = "AWS:SourceArn"
      values   = [aws_cloudfront_distribution.site.arn]
    }
  }
}

resource "aws_s3_bucket_policy" "site" {
  bucket = aws_s3_bucket.site.id
  policy = data.aws_iam_policy_document.s3_oac.json
}

A cache-stratégia dönti el a sebességet

A statikus hosting sebességének és frissességének titka a helyes Cache-Control fejléc — amit az S3-ba feltöltéskor állítasz be. A trükk: a hasheléssel verziózott asseteket (pl. app.a1b2c3.js) örökre cache-eled, az index.html-t viszont sosem, hogy az új deploy azonnal látszódjon.

FájltípusCache-ControlMiért?
index.htmlno-cachemindig friss, az új build belépője
*.[hash].js/cssmax-age=31536000, immutablea hash garantálja az egyediséget
képek/fontokmax-age=604800ritkán változnak
bash
# Verziózott assetek: hosszú, immutable cache
aws s3 sync ./dist s3://my-site \
  --exclude index.html \
  --cache-control "public,max-age=31536000,immutable"

# index.html: soha ne cache-eljük tartósan
aws s3 cp ./dist/index.html s3://my-site/index.html \
  --cache-control "no-cache"

Mit jelent ez neked?

Ez a négy erőforrás — privát bucket, OAC, disztribúció, bucket policy — egy gyors, biztonságos és olcsó statikus hosting, ahol a tartalom sosem érhető el közvetlen S3-URL-en, csak a CDN-en át, HTTPS-sel. A teljesítmény kulcsa nem az infra, hanem a cache-fejlécek: verziózott asset örökre, index.html sosem. Ha ezt jól állítod be, a látogató a világ bármely pontjáról villámgyorsan kapja az oldalt, te pedig minden deploynál azonnal látod a friss verziót — invalidációs cirkusz nélkül. És mivel minden Terraformban van, a következő projekt ugyanez, három változóval.