elmeg-demo/docs/AWS_SES_SETUP.md
fullsizemalt cc694ed5bb docs: Add comprehensive AWS SES setup guides
- AWS_SES_SETUP.md: Complete setup with prod/dev env separation
- AWS_SES_BROWSER_AGENT.md: Step-by-step for browser-based agent
- Explicit security notes about IAM scoping and key handling
2025-12-21 14:40:20 -08:00

3.2 KiB

AWS SES Email Setup

Environment Configuration

Production (elmeg.xyz)

AWS_ACCESS_KEY_ID=AKIA...           # IAM user with SES send-only perms
AWS_SECRET_ACCESS_KEY=...
AWS_SES_REGION=us-east-1            # Must match region where domain is verified
EMAIL_FROM=noreply@elmeg.xyz        # Must be on SES-verified domain
FRONTEND_URL=https://elmeg.xyz
NODE_ENV=production
APP_ENV=production

Development (elmeg.runfoo.run)

FRONTEND_URL=https://elmeg.runfoo.run
APP_ENV=development
# AWS keys optional in dev - emails log to console instead

SES Setup Checklist

1. Verify Domain in SES

  1. AWS Console → SES → Verified Identities → Create identity
  2. Select "Domain" → enter elmeg.xyz
  3. Add DNS records AWS provides:
    • TXT record for domain verification
    • 3 CNAME records for DKIM signing

Important

Add DKIM records or mail will get flagged as spam

2. Move Out of Sandbox

By default SES is sandboxed (can only send to verified emails).

  1. SES → Account dashboard → Request production access
  2. Fill out:
    • Mail type: Transactional
    • Website URL: https://elmeg.xyz
    • Use case: "User registration verification, password reset for live music rating platform"
  3. Wait for approval (~24hrs)

3. Create IAM User

  1. IAM → Users → Create user: elmeg-ses-sender
  2. Attach inline policy (SES send only):
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ses:SendEmail",
                "ses:SendRawEmail"
            ],
            "Resource": "*"
        }
    ]
}
  1. Security credentials → Create access key
  2. Save credentials securely

Caution

Never commit AWS keys. Use environment variables only. Never use root AWS credentials - always create a scoped IAM user.


DNS Records Required

Add these to elmeg.xyz DNS (exact values from SES console):

Type Name Value
TXT _amazonses.elmeg.xyz (provided by SES)
CNAME xxxx._domainkey.elmeg.xyz (DKIM 1)
CNAME xxxx._domainkey.elmeg.xyz (DKIM 2)
CNAME xxxx._domainkey.elmeg.xyz (DKIM 3)

Deployment

Add to production server

ssh root@tangible-aacorn
cd /srv/containers/elmeg-demo

Edit docker-compose.yml backend environment:

backend:
  environment:
    - DATABASE_URL=postgresql://elmeg:elmeg@db:5432/elmeg
    - AWS_ACCESS_KEY_ID=AKIA...
    - AWS_SECRET_ACCESS_KEY=...
    - AWS_SES_REGION=us-east-1
    - EMAIL_FROM=noreply@elmeg.xyz
    - FRONTEND_URL=https://elmeg.xyz
    - APP_ENV=production

Rebuild and restart:

docker compose build backend
docker compose restart backend

Cost

  • $0.10 per 1,000 emails
  • No monthly minimum
  • First 62,000 emails/month free if sending from EC2

Troubleshooting

Issue Solution
"Email address is not verified" Domain not verified, or still in sandbox
"Access Denied" Check IAM policy has ses:SendEmail
Emails not sending Check docker compose logs backend
Emails in spam Verify DKIM records are set correctly
Wrong links in emails Check FRONTEND_URL matches prod domain