Introduction
Static WordPress websites are fast, cheap, and secure. By exporting your site into static files and hosting them on Amazon S3 + Amazon CloudFront, you remove PHP/MySQL overhead and drastically shrink the attack surface.
But there’s a catch: once your site is static, the native WordPress authentication no longer works. How do you secure premium downloads, member dashboards, or course pages?
Solution: the WordPress Static Site Guardian, deployed from the AWS Serverless Application Repository (SAR). It provides:
- CloudFront signed cookie protection for selected URL paths
- API Gateway + Lambda endpoints to issue and clear cookies
- KMS + SSM backed key management
- No-code integration with the Gatey plugin for Amazon Cognito login
What this stack does
- Hosts your static export on S3/CloudFront and restricts paths using CloudFront signed cookies.
- Issues/clears cookies via API Gateway + AWS Lambda.
- Automatically provisions Route 53 DNS records (when enabled) — so you don’t have to edit DNS manually.
- Integrates with Gatey so Sign-In/Sign-Out call the cookie endpoints — no JavaScript needed.
Static vs Dynamic WordPress
Feature | Dynamic WP (PHP/MySQL) | Static WP (S3 + CloudFront) |
---|---|---|
Speed | Server-rendered, depends on PHP/DB | CDN edge-cached, ultra-fast |
Security | Core/plugins = larger attack surface | Minimal surface (static files) |
Scalability | Bound by server resources | Virtually unlimited via CloudFront |
Authentication | Built-in WP login | SAR + Gatey (signed cookies) |
Maintenance | Patching, DB backups | File sync + cache invalidation |
Generate the CloudFront key pair
Use the provided script to generate an RSA key pair and store the private key securely in SSM (KMS-encrypted). You’ll get theKmsKeyId
and PublicKeyContent
to pass into the stack.
# Download the key generation script
curl -O https://raw.githubusercontent.com/smartcloudsol/wordpress-static-site-guardian/refs/heads/main/scripts/generate-cloudfront-keypair.sh
chmod +x generate-cloudfront-keypair.sh
# Generate keys and store in AWS
./generate-cloudfront-keypair.sh --name my-wordpress-keys --region us-east-1
Deploy from AWS SAR
- Open AWS Console → Serverless Application Repository and search for WordPress Static Site Guardian or follow this link.
- Fill parameters:
DomainName
→ example.comApiDomainName
→ api.example.comCertificateArn
(ACM in us-east-1)KmsKeyId
andPublicKeyContent
from the scriptProtectedPaths
→ e.g./members,/downloads
SigninPagePath
→ e.g./sign-in
CreateDNSRecords
→ true to auto-create Route 53 DNS records
- Click Deploy. The stack provisions S3, CloudFront, API Gateway, Lambda, KMS/SSM, and (optionally) Route 53 records.
Upload the static WordPress export
- Export your site (Simply Static, WP2Static, etc.).
- Upload to the provisioned S3 bucket under the configured
wwwroot
prefix (e.g. with AWS CLIs3 sync
). - Invalidate CloudFront after updates (docs).
Heads-up: The stack expects the static site under a non-empty S3 prefix (e.g.
wwwroot/
). Upload content to s3://<bucket>/wwwroot/
, not the bucket root.Integrate with Gatey (no JavaScript required)
In WordPress open Gatey → Settings → API and configure:- API:
backend
- Sign In Path:
/issue-cookie
- Sign Out Path:
/issue-cookie?action=signout
- With Credentials: enabled
/issue-cookie
to set CloudFront signed cookies; on sign-out it calls /issue-cookie?action=signout
to clear them. No custom JS is needed — hooks run from the admin UI.
Helpful: Gatey product page
End-to-end test
- Visit a public page → loads normally.
- Visit a protected path → redirects to your
/sign-in
page. - Sign in via Gatey (Cognito) → the API issues the cookie → reload grants access.
- Open a protected download → served with CloudFront signed cookies.
- Sign out → cookie cleared → access revoked.
Cookie lifetime, domain & CORS
- Align cookie TTL with your Cognito refresh token policy (commonly ~30 days).
- Scope cookies to the apex domain so they’re valid for the site and API subdomain.
- API Gateway should allow credentials and your site origin in CORS (guide).
Monitoring & rollback
- Inspect CloudWatch Logs for Lambda + API Gateway.
- Watch CloudFront metrics (hit/miss, spikes in 403).
- Rollback by redeploying a previous template version if needed.
Pro Tips & Common Mistakes
Pro tips
- Automate export → S3 sync → CloudFront invalidation via CI/CD (CodePipeline or GitHub Actions).
- Add custom 403/404 pages for a polished UX.
- Alert on 401/403 spikes using CloudWatch alarms.
- Keep separate stacks for staging vs production.
Common mistakes
- Uploading files to the bucket root instead of
wwwroot/
. - ACM certificate not in
us-east-1
(CloudFront requires it). - Mismatched cookie TTL vs Cognito refresh token lifetime.
- Forgetting to enable “With Credentials” in Gatey API settings.
Pre-publish checklist
- ACM certificate issued in
us-east-1
for domain + API subdomain. - CloudFront key pair generated;
KmsKeyId
+PublicKeyContent
recorded. - SAR stack deployed with
CreateDNSRecords=true
(or DNS mapped manually). - Static site uploaded under
wwwroot/
; CloudFront invalidated. - Gatey API hooks set to
/issue-cookie
and/issue-cookie?action=signout
with credentials. - E2E test: login → cookie → protected access → logout → revoked.
Key takeaways
- Static WordPress keeps speed and security — SAR + signed cookies bring back access control.
- One deploy: S3, CloudFront, API Gateway, Lambda, KMS/SSM, and optional Route 53 auto-DNS.
- Gatey connects Cognito to cookie issuance with admin-configured hooks — no custom JS.