AWS GitHub Actions OIDC Setup¶
Date: 2026-03-06 Account: 947782089822 (eu-west-2)
What was set up¶
GitHub Actions deploys to AWS without long-lived credentials using OIDC federation.
1. GitHub OIDC Identity Provider¶
ARN: arn:aws:iam::947782089822:oidc-provider/token.actions.githubusercontent.com
Client ID: sts.amazonaws.com
This tells AWS to trust JWTs issued by GitHub Actions. Created once per AWS account.
2. IAM Role: github-actions-deploy¶
SST needs both because it creates IAM roles for ECS task execution and Lambda functions. PowerUserAccess alone is not sufficient -- it excludes IAM operations.
Trust policy -- only the getreggie/reggie repo can assume this role:
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::947782089822:oidc-provider/token.actions.githubusercontent.com"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
},
"StringLike": {
"token.actions.githubusercontent.com:sub": "repo:getreggie/reggie:*"
}
}
}]
}
3. GitHub Repository Variable¶
| Variable | Value | Location |
|---|---|---|
| AWS_DEPLOY_ROLE_ARN | arn:aws:iam::947782089822:role/github-actions-deploy | Repo > Settings > Variables > Actions |
4. SST Secrets (per stage)¶
Set via: npx sst secret set NAME VALUE --stage STAGE
| Secret | Required | Notes |
|---|---|---|
| ClerkPublishableKey | Yes | pk_test_... or pk_live_... |
| ClerkSecretKey | Yes | sk_test_... or sk_live_... |
| ClerkJwtKey | Optional | PEM public key for networkless JWT verification |
| ClerkWebhookSecret | Optional | Clerk webhook signature verification |
| SecretKey | Yes | App secret key |
| R2Endpoint | Optional | Cloudflare R2 endpoint |
| R2AccessKeyId | Optional | R2 access key |
| R2SecretAccessKey | Optional | R2 secret key |
| StripeSecretKey | Optional | Stripe API key |
| StripeWebhookSecret | Optional | Stripe webhook secret |
| ResendApiKey | Optional | Email service key |
| DvlaApiKey | Optional | DVLA API key |
Troubleshooting¶
| Error | Cause | Fix |
|---|---|---|
| Locked: concurrent update | Previous deploy didn't finish | npx sst unlock --stage staging |
| iam:CreateRole AccessDenied | Missing IAMFullAccess | Attach IAMFullAccess to deploy role |
| Deploy hangs after providers | Secrets not set | npx sst secret list --stage staging |
Security notes¶
- No static AWS keys stored in GitHub
- Role scoped to repo:getreggie/reggie:* only
- PowerUserAccess + IAMFullAccess is broad -- narrow once stable
- Temporary credentials expire after 15 minutes