# Setting Up AWS for everystack

AWS (Amazon Web Services) rents you computers on the internet. When you deploy your app, it runs on AWS servers so anyone in the world can use it. This guide walks you through creating an account and giving your computer permission to deploy.

## What does everystack use on AWS?

Your app is made up of a few building blocks. Each one is an AWS service:

| Service | What it does | Plain English | Tier | Typical cost |
|---------|-------------|---------------|------|-------------|
| **S3** | File storage | Holds your app's files (HTML, CSS, JavaScript, images) | V1+ | Pennies/month |
| **CloudFront** | Content delivery network | Makes your app load fast for users worldwide | V1+ | Free tier covers most small apps |
| **Lambda** | Serverless compute | Runs your server code only when someone visits | V1+ | Free tier: 1M requests/month |
| **RDS** | Managed database | Stores your users, posts, and data (Aurora Serverless) | V2+ | ~$15/month minimum |
| **SQS** | Message queue | Processes background tasks like sending emails | V3 | Pennies/month |

**Total cost for a small app with low traffic:** Under $5/month for V1, ~$20/month for V2+ (the database is the main cost).

AWS has a **free tier** for the first 12 months that covers most of what everystack uses at low traffic. You will not be charged anything significant while learning.

## Step 1: Create an AWS account

1. Go to https://aws.amazon.com/free
2. Click **Create a Free Account**
3. You will need:
   - An email address
   - A credit card (required for verification, but free tier usage will not be charged)
   - A phone number for verification
4. Choose the **Basic Support** plan (free)
5. After account creation, sign in to the AWS Console at https://console.aws.amazon.com to confirm it works

## Step 2: Create an IAM user for everystack

Your AWS account has a "root user" (the email you signed up with). The root user has unlimited power over your account. You should never use it for daily work. Instead, create a dedicated user just for everystack.

**IAM** stands for Identity and Access Management. It controls who can do what in your AWS account.

### Create the user

1. Sign in to the **AWS Console** at https://console.aws.amazon.com
2. In the top search bar, type **IAM** and click on it
3. Click **Users** in the left sidebar
4. Click **Create user**
5. Enter the user name: `everystack-dev`
6. Click **Next**

### Create the permissions policy

This policy gives the user the permissions SST needs to deploy your app, scoped to your app's resources. Every statement targets your app name prefix so this user can't touch other apps in the same account.

7. Select **Attach policies directly**
8. Click **Create policy** (this opens a new tab)
9. Click the **JSON** tab
10. Delete anything in the editor and paste this (replacing the placeholders — see table below):

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "SSM",
      "Effect": "Allow",
      "Action": "ssm:*",
      "Resource": [
        "arn:aws:ssm:{REGION}:{ACCOUNT_ID}:parameter/sst/*",
        "arn:aws:ssm:{REGION}:{ACCOUNT_ID}:parameter/{APP_NAME}/*"
      ]
    },
    {
      "Sid": "S3",
      "Effect": "Allow",
      "Action": "s3:*",
      "Resource": [
        "arn:aws:s3:::{APP_NAME}-*-*",
        "arn:aws:s3:::{APP_NAME}-*-*/*",
        "arn:aws:s3:::sst-asset-*",
        "arn:aws:s3:::sst-asset-*/*",
        "arn:aws:s3:::sst-state-*",
        "arn:aws:s3:::sst-state-*/*"
      ]
    },
    {
      "Sid": "S3Protect",
      "Effect": "Deny",
      "Action": [
        "s3:DeleteBucket",
        "s3:PutBucketAcl",
        "s3:PutBucketVersioning",
        "s3:PutBucketEncryption",
        "s3:PutBucketLogging"
      ],
      "Resource": "*"
    },
    {
      "Sid": "CF",
      "Effect": "Allow",
      "Action": [
        "cloudfront:*",
        "cloudfront-keyvaluestore:*"
      ],
      "Resource": "*"
    },
    {
      "Sid": "Lambda",
      "Effect": "Allow",
      "Action": "lambda:*",
      "Resource": "arn:aws:lambda:{REGION}:{ACCOUNT_ID}:function:{APP_NAME}-*"
    },
    {
      "Sid": "LambdaGlobal",
      "Effect": "Allow",
      "Action": [
        "lambda:CreateEventSourceMapping",
        "lambda:DeleteEventSourceMapping",
        "lambda:GetEventSourceMapping",
        "lambda:ListEventSourceMappings",
        "lambda:UpdateEventSourceMapping",
        "lambda:ListFunctions",
        "lambda:GetFunctionConfiguration",
        "lambda:TagResource",
        "lambda:UntagResource",
        "lambda:ListTags"
      ],
      "Resource": "*"
    },
    {
      "Sid": "SQS",
      "Effect": "Allow",
      "Action": "sqs:*",
      "Resource": "arn:aws:sqs:{REGION}:{ACCOUNT_ID}:{APP_NAME}-*"
    },
    {
      "Sid": "IAM",
      "Effect": "Allow",
      "Action": "iam:*Role*",
      "Resource": [
        "arn:aws:iam::{ACCOUNT_ID}:role/{APP_NAME}-*",
        "arn:aws:iam::{ACCOUNT_ID}:role/SchedulerRole-*"
      ]
    },
    {
      "Sid": "Scheduler",
      "Effect": "Allow",
      "Action": [
        "scheduler:CreateScheduleGroup",
        "scheduler:DeleteScheduleGroup",
        "scheduler:GetScheduleGroup",
        "scheduler:ListTagsForResource",
        "scheduler:TagResource",
        "scheduler:UntagResource"
      ],
      "Resource": "arn:aws:scheduler:{REGION}:{ACCOUNT_ID}:schedule-group/{APP_NAME}-*"
    },
    {
      "Sid": "Logs",
      "Effect": "Allow",
      "Action": "logs:*",
      "Resource": [
        "arn:aws:logs:{REGION}:{ACCOUNT_ID}:log-group:/aws/lambda/{APP_NAME}-*",
        "arn:aws:logs:{REGION}:{ACCOUNT_ID}:log-group:/aws/lambda/{APP_NAME}-*:*"
      ]
    },
    {
      "Sid": "LogsList",
      "Effect": "Allow",
      "Action": "logs:DescribeLogGroups",
      "Resource": "arn:aws:logs:{REGION}:{ACCOUNT_ID}:log-group:*"
    },
    {
      "Sid": "Discovery",
      "Effect": "Allow",
      "Action": "s3:ListAllMyBuckets",
      "Resource": "*"
    },
    {
      "Sid": "STS",
      "Effect": "Allow",
      "Action": "sts:GetCallerIdentity",
      "Resource": "*"
    }
  ]
}
```

Replace the placeholders with your values:

| Placeholder | Example | Where to find it |
|-------------|---------|-------------------|
| `{ACCOUNT_ID}` | `123456789012` | `aws sts get-caller-identity` |
| `{REGION}` | `us-east-1` | Your default AWS region |
| `{APP_NAME}` | `myapp` | The `name` in your `sst.config.ts` |

If your app creates additional S3 buckets outside the `{APP_NAME}-*` pattern, add them to the S3 statement.

11. Click **Next**
12. Name the policy: `everystack-dev-policy`
13. Optionally add a description: "Permissions for everystack SST deploys"
14. Click **Create policy**

### Attach the policy to the user

15. Go back to the **Create user** tab in your browser
16. Click the refresh button on the policy list
17. Search for `everystack-dev-policy`
18. Check the box next to it
19. Click **Next**, then **Create user**

### Create an access key

20. Click on the user name **everystack-dev**
21. Go to the **Security credentials** tab
22. Under **Access keys**, click **Create access key**
23. Select **Command Line Interface (CLI)**
24. Check the confirmation checkbox, click **Next**, then **Create access key**
25. **Save both keys now.** You will not see the secret key again after this page:
    - **Access key ID** (looks like: `AKIAIOSFODNN7EXAMPLE`)
    - **Secret access key** (looks like: `wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY`)

## Step 3: Configure your computer

Open a terminal and run:

```bash
aws configure
```

It will ask four questions:

- **AWS Access Key ID:** Paste the access key ID from Step 2
- **AWS Secret Access Key:** Paste the secret access key from Step 2
- **Default region name:** `us-east-1` (recommended, or choose your nearest region)
- **Default output format:** `json`

## Step 4: Verify it works

Run this command:

```bash
aws sts get-caller-identity
```

You should see something like:

```json
{
    "UserId": "AIDAIOSFODNN7EXAMPLE",
    "Account": "123456789012",
    "Arn": "arn:aws:iam::123456789012:user/everystack-dev"
}
```

If you see your account number and `everystack-dev`, your credentials are working. You are ready to deploy.

### What each statement does

| Statement | Actions | Scope | Purpose |
|-----------|---------|-------|---------|
| **SSM** | `ssm:*` | `sst/*` + `{APP_NAME}/*` params | SST state management + app secrets |
| **S3** | `s3:*` | App buckets + SST state/asset buckets | Media, client bundles, OTA updates, SST state |
| **S3Protect** | Deny destructive bucket ops | `*` | Prevents `DeleteBucket`, ACL/versioning/encryption/logging changes |
| **CF** | `cloudfront:*`, `cloudfront-keyvaluestore:*` | `*` | Router distribution + KVS cache versioning |
| **Lambda** | `lambda:*` | `{APP_NAME}-*` functions | API, Image, Worker Lambdas |
| **LambdaGlobal** | Event source mappings, list, tags | `*` | SQS-to-Lambda subscriptions, resource discovery |
| **SQS** | `sqs:*` | `{APP_NAME}-*` queues | Background jobs + dead-letter queues (V3) |
| **IAM** | `iam:*Role*` | `{APP_NAME}-*` + `SchedulerRole-*` | Lambda execution roles + EventBridge Scheduler role |
| **Scheduler** | Schedule group CRUD + tags | `{APP_NAME}-*` groups | EventBridge Scheduler for delayed tasks |
| **Logs** | `logs:*` | `/aws/lambda/{APP_NAME}-*` | CloudWatch log groups for Lambda functions |
| **LogsList** | `logs:DescribeLogGroups` | `*` | Log group enumeration |
| **Discovery** | `s3:ListAllMyBuckets` | `*` | CLI resource discovery |
| **STS** | `sts:GetCallerIdentity` | `*` | Identity verification |

**V2-only apps** can omit `SQS` and `Scheduler`. **V1-only apps** can omit `SQS`, `Scheduler`, `IAM`, and `Logs`.

## Production hardening

For production, read `everystack://security` for a three-profile model that separates infrastructure creation, day-to-day operations, and CI/CD into distinct IAM users with minimal permissions.
