$ cdk deploy --all

Deploy your own Filedrop

Every line of Filedrop is open source under the MIT license at github.com/kunal-kejriwal/filedrop-aws. This page walks through standing up your own copy in your own AWS account. Estimated time: ~20 minutes of active work (plus ~24h if SES needs to leave sandbox and you want to email arbitrary recipients).

Prerequisites

Step 1 — Clone the repo

git clone https://github.com/kunal-kejriwal/filedrop-aws.git
cd filedrop-aws

Step 2 — Install dependencies

Filedrop uses a Python virtualenv for the CDK app + Lambda bundling, plus the CDK CLI globally via npm.

python3.12 -m venv .venv
# macOS / Linux
source .venv/bin/activate
# Windows PowerShell
# .venv\Scripts\Activate.ps1

pip install -e ".[dev]"
npm install -g aws-cdk@2

Sanity-check the toolchain:

ruff check .
mypy shared functions infra
pytest tests/unit -v
cdk --version

Step 3 — Verify your SES sender identity

Filedrop imports an existing SES identity rather than creating one — so you need to verify your sender address before deploying.

  1. Go to the SES console → Verified identities in your target region (Filedrop defaults to ap-south-1).
  2. Click Create identity → Email address → enter your sender (e.g. hello@your-domain.com).
  3. Click the confirmation link SES emails you. The identity's status should flip to Verified.

SES sandbox note: new AWS accounts start with SES in sandbox mode — you can only send email to verified addresses too, and are capped at 200 emails/day. To send to arbitrary recipients, submit a production-access request from the SES console. Approval typically takes 24h. In the meantime, the pipeline still works — the flow doesn't require email delivery to succeed because a status endpoint at GET /uploads/{id}/status can hand back the download link once process flips the row to UPLOADED.

Step 4 — Configure CDK context

Copy the example context file and fill in your details:

cp cdk.context.json.example cdk.context.json

Then edit cdk.context.json:

{
  "region": "ap-south-1",
  "senderEmail": "hello@your-domain.com",
  "alarmEmail": "you@your-domain.com"
}

senderEmail must match the identity you verified in Step 3. alarmEmail receives CloudWatch alarms when a DLQ has messages (optional — you can leave it out and subscribe later from the SNS console).

Step 5 — Bootstrap CDK (one-time per account/region)

CDK needs a small "toolkit" stack in your account to store deployment assets:

cdk bootstrap aws://YOUR-ACCOUNT-ID/ap-south-1

Replace YOUR-ACCOUNT-ID with your 12-digit AWS account ID (from aws sts get-caller-identity). This creates the CDKToolkit stack — do it once and forget about it.

Step 6 — Deploy the stacks

export SENDER_EMAIL=hello@your-domain.com
make deploy
# or, without make:
cdk deploy --all --require-approval never \
  --context senderEmail=$SENDER_EMAIL

Two stacks land in CloudFormation:

First deploy takes ~10 minutes (CFN provisions ~35 resources). CDK prints the API URL on completion:

Outputs:
FiledropApiStack.ApiUrl = https://xxxxxxxxx.execute-api.ap-south-1.amazonaws.com

Step 7 — Test it end-to-end

Grab the outputs, then run the load-test script:

export FILEDROP_API_URL=https://xxxxxxxxx.execute-api.ap-south-1.amazonaws.com
export TEST_EMAIL=you@your-domain.com  # must be SES-verified while in sandbox

# Grab the audit table name from the CoreStack outputs
AUDIT_TABLE=$(aws cloudformation describe-stacks \
  --stack-name FiledropCoreStack \
  --query "Stacks[0].Outputs[?OutputKey=='AuditTableName'].OutputValue" \
  --output text)

python scripts/load_test.py \
  --count 5 \
  --api-url $FILEDROP_API_URL \
  --email $TEST_EMAIL \
  --audit-table $AUDIT_TABLE

If everything is wired correctly you'll see something like:

running 5 uploads against https://xxx.execute-api.ap-south-1.amazonaws.com
uploads complete; polling audit table for up to 120s
results: ok=5/5 p50=1.17 p95=2.10 p99=2.10

Step 8 — Set up GitHub OIDC deploy (optional)

The repo includes a GitHub Actions workflow that redeploys on every push to main via OIDC — no long-lived access keys. To wire it up:

  1. In IAM → Identity providers, add an OIDC provider for https://token.actions.githubusercontent.com with audience sts.amazonaws.com.
  2. Create an IAM role with the trust policy in docs/architecture.md (edit the placeholder account ID and repo path).
  3. Attach a policy that lets CDK deploy (broad: PowerUserAccess + IAMFullAccess; tighter: the actual services Filedrop touches).
  4. Add the role ARN to your GitHub repo secrets as AWS_DEPLOY_ROLE_ARN, plus SENDER_EMAIL (and optionally ALARM_EMAIL).
  5. Copy filedrop-aws/.github-workflows-templates/filedrop-deploy.yml to .github/workflows/.

Cost sketch

At portfolio-scale traffic (a few dozen uploads a day) Filedrop costs basically nothing — under $1/month, most of it CloudWatch logs. All services are on-demand billed:

Teardown

When you're done, one command evicts everything:

cdk destroy --all --force

Both stacks are RemovalPolicy.DESTROY, including the S3 bucket (auto_delete_objects=True) and the DynamoDB tables — no lingering resources. The SES identity survives (Filedrop imports it, doesn't manage it) — delete it manually from the SES console if you want.

Where to poke around next

Something broken?

Open an issue on GitHub or ping me at hello@kunalships.dev. If a step here doesn't work end-to-end for you, that's a bug I want to fix.