Skip to content

Instantly share code, notes, and snippets.

@oNddleo
Last active December 8, 2025 10:33
Show Gist options
  • Select an option

  • Save oNddleo/ab57a89063230f4b6aacc14fa13aebc4 to your computer and use it in GitHub Desktop.

Select an option

Save oNddleo/ab57a89063230f4b6aacc14fa13aebc4 to your computer and use it in GitHub Desktop.
CloudFlare

Complete Guide: Configure Private S3 Bucket with CloudFront and Cloudflare

Overview

This guide walks through setting up a private S3 bucket with CloudFront as the content delivery layer and Cloudflare as the proxy/caching layer. This architecture provides security, performance, and cost optimization.


Phase 1: AWS S3 Configuration

Step 1.1: Create S3 Bucket

  1. Log in to AWS Management Console

  2. Navigate to S3 > Create bucket

  3. Configure bucket settings:

    · Bucket name: your-assets-bucket (choose a globally unique name)

    · AWS Region: Select nearest region (e.g., us-east-1)

    · Block Public Access: ✅ Keep all settings checked

    · Block public access through ACLs

    · Block public access through bucket policies

    · Bucket Versioning: Disabled (unless needed)

    · Tags: Optional

    · Default Encryption: Enable SSE-S3 (recommended)

  4. Click Create bucket

Step 1.2: Upload Files

  1. Navigate to your new bucket

  2. Click Upload > Add files

  3. Upload your static assets (images, CSS, JS, etc.)

  4. Set Permissions for each file (keep private)

  5. Click Upload


Phase 2: AWS CloudFront Configuration

Step 2.1: Create CloudFront Key Pair (for Signed URLs/Cookies - Optional)

Only required if you need signed URLs/cookies

  1. Navigate to IAM > Security credentials

  2. Scroll to CloudFront key pairs

  3. Click Create New Key Pair

  4. Download the private key (.pem file) - Keep this secure

  5. Note the Key Pair ID

Step 2.2: Create CloudFront Distribution

  1. Navigate to CloudFront > Distributions

  2. Click Create distribution

  3. Configure Origin settings:

    Origin domain: Select your S3 bucket

    · It should appear as: your-assets-bucket.s3.us-east-1.amazonaws.com

    Origin path: Leave blank

    Name: your-assets-bucket-origin

    Origin access: Origin access control settings (recommended)

    · Click Create control setting

    · Origin access control: Create new setting

    · Name: s3-oac-access

    · Description: Access from CloudFront to S3

    · Signing behavior: Always

    · Default settings: Leave as is

    · Click Create

  4. Configure Default cache behavior:

    Cache policy: CachingOptimized (or create custom)

    · If custom, set:

    · Min TTL: 86400 (1 day)

    · Default TTL: 604800 (7 days)

    · Max TTL: 31536000 (1 year)

    Origin request policy: CORS-S3Origin (if using CORS)

    Response headers policy:

    · Select SecurityHeadersPolicy or create custom · Recommended headers:

    Strict-Transport-Security: max-age=31536000; includeSubDomains
    X-Content-Type-Options: nosniff
    X-Frame-Options: DENY
    X-XSS-Protection: 1; mode=block
    Referrer-Policy: strict-origin-when-cross-origin
    

    Viewer protocol policy: Redirect HTTP to HTTPS Allowed HTTP methods: GET, HEAD, OPTIONS Cache key and origin requests: Cache policy and origin request policy

  5. Configure Settings:

    Price class: Use Only North America and Europe (or choose based on needs)

    Alternate domain name (CNAME): assets.yourdomain.com

    · Note: You'll configure SSL certificate later

    Custom SSL certificate:

    · Click Request certificate

    · Follow ACM wizard for *.yourdomain.com

    · Or use existing certificate

    Default root object: Leave blank (unless serving SPA)

    Logging: Enable if needed

    WAF: Enable AWS WAF if needed

  6. Click Create distribution

Step 2.3: Update S3 Bucket Policy for CloudFront Access

  1. After distribution creation, CloudFront will show a Copy Policy button

  2. Click Copy Policy

  3. Navigate to your S3 bucket

  4. Go to Permissions > Bucket Policy

  5. Paste and save the policy:

{
  "Version": "2012-10-17",
  "Statement": {
    "Sid": "AllowCloudFrontServicePrincipal",
    "Effect": "Allow",
    "Principal": {
      "Service": "cloudfront.amazonaws.com"
    },
    "Action": "s3:GetObject",
    "Resource": "arn:aws:s3:::your-assets-bucket/*",
    "Condition": {
      "StringEquals": {
        "AWS:SourceArn": "arn:aws:cloudfront::123456789012:distribution/ABCDEFGHIJKLMN"
      }
    }
  }
}

Phase 3: Cloudflare Configuration

Step 3.1: DNS Configuration

  1. Log in to Cloudflare Dashboard

  2. Select your domain

  3. Navigate to DNS > Records

  4. Add CNAME record: · Type: CNAME · Name: assets (or subdomain of choice) · Target: abc123def456.cloudfront.net (your CloudFront domain) · Proxy status: ✅ Proxied (orange cloud) · TTL: Auto

  5. Click Save

Step 3.2: SSL/TLS Configuration

  1. Navigate to SSL/TLS > Overview

  2. Set encryption mode: Full (strict)

  3. Navigate to SSL/TLS > Edge Certificates

  4. Enable:

    · ✅ Always Use HTTPS

    · ✅ Automatic HTTPS Rewrites

    · ✅ Minimum TLS Version: TLS 1.2

  5. Configure Authenticated Origin Pulls (Optional but recommended):

    · Navigate to SSL/TLS > Origin Server

    · Click Create Certificate

    · Select: Generate private key and CSR with Cloudflare

    · Hostnames: assets.yourdomain.com

    · Certificate Validity: 15 years

    · Click Create

    · Download certificate and key

    · Configure on CloudFront (upload as custom SSL)

Step 3.3: Cache Configuration

  1. Navigate to Caching > Configuration

  2. Set Caching Level: Standard

  3. Set Browser Cache TTL: 1 month

  4. Navigate to Caching > Configuration > Cache Rules

  5. Create new Cache Rule: · Rule name: S3 Assets Cache

    · When incoming requests match:

    · Field: Hostname

    · Operator: equals

    · Value: assets.yourdomain.com

    · Then set cache configuration:

    · Cache Eligibility: Eligible for cache

    · Edge TTL: 1 month

    · Browser TTL: 1 month

    · Cache Key: Custom

    · Include: Host, Path, Query string
    
    · Query string: Include all
    

    · Click Deploy

Step 3.4: Security Configuration

  1. Navigate to Security > WAF

  2. Create new rule: · Rule name: Block Direct CloudFront Access

    · When request matches:

    · Field: Host

    · Operator: does not equal

    · Value: assets.yourdomain.com

    · Then: Block

  3. Navigate to Security > Settings

    · Security Level: Medium

    · Challenge Passage: 30 minutes

    · Browser Integrity Check: On

Step 3.5: Performance Configuration

  1. Navigate to Speed > Optimization

  2. Configure:

    · ✅ Auto Minify (JS, CSS, HTML)

    · ✅ Brotli compression

    · ✅ Rocket Loader: Off

    · ✅ Mirage: Off

    · ✅ Polish: Lossless/Lossy (for images)


Phase 4: Testing & Validation

Step 4.1: Test Direct Access

  1. Try accessing S3 directly:
    https://your-assets-bucket.s3.amazonaws.com/image.jpg
    
    · Should return 403 Access Denied
  2. Try accessing CloudFront directly:
    https://abc123def456.cloudfront.net/image.jpg
    
    · Should return 200 OK (or 403 if using signed URLs)

Step 4.2: Test Through Cloudflare

  1. Access through Cloudflare:
    https://assets.yourdomain.com/image.jpg
    
    · Should return 200 OK
  2. Check headers:
    curl -I https://assets.yourdomain.com/image.jpg
    · Verify headers include: · cf-cache-status: HIT · x-amz-cf-pop (CloudFront POP) · Security headers you configured

Step 4.3: Cache Validation

  1. Check Cloudflare cache status: · First request: cf-cache-status: MISS · Subsequent requests: cf-cache-status: HIT
  2. Purge cache if needed: · Cloudflare: Caching > Configuration > Purge Cache · CloudFront: Invalidations > Create invalidation

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment