Terraform IaC for a serverless Discord + Instagram bot stack on AWS Lambda.
Personal portfolio / learning project. A small but complete reference for wiring AWS Lambda, API Gateway, SNS, SQS, S3, DynamoDB, EventBridge and SSM Parameter Store together with Terraform Cloud-managed state.
A pipeline that drafts AI image prompts in Discord, renders them externally,
stores the resulting images in S3, and publishes them to Instagram on a
scheduled cron. End-to-end serverless, single region (eu-central-1).
Discord slash cmd
|
v
API Gateway (HTTP)
|
v
Lambda: pull-save-image ----> SQS: inbound-prompt-drafts
|
v
(external renderer
picks up message)
|
v
SNS: ready-prompt
|
v
Lambda: discord-prompt-poster
|
v
S3: corgi-rendered-images-ready
DynamoDB: corgi-meta-data
|
EventBridge cron (daily 16:00 UTC) --> Lambda: publish-image --> Instagram
^
|
SSM Parameter Store
(IG creds, SecureString)
| Component | Purpose |
|---|---|
discord_pull_image Lambda |
Receives Discord interaction, enqueues prompt draft to SQS |
discord_prompt_poster Lambda |
Subscribed to SNS, posts the ready prompt back into Discord |
publish_image Lambda |
Cron-triggered; reads from S3 + DynamoDB, publishes to Instagram |
extract_images Lambda |
Helper for pulling images out of the bucket (gated behind API Gateway, currently disabled in the route map) |
| API Gateway v2 (HTTP) | Public entry point for Discord interactions |
SQS inbound-prompt-drafts |
Buffers prompts awaiting render |
SNS ready-prompt |
Fan-out for rendered prompts |
S3 corgi-rendered-images-ready |
Golden source of generated images (intentionally force_destroy = false) |
DynamoDB corgi-meta-data |
Tracks which images have been posted |
| SSM Parameter Store | SecureString storage for Instagram credentials |
Lambda Layer node_modules |
Shared node_modules/ for all Node.js Lambdas |
- IaC: Terraform, state managed in Terraform Cloud (
organization = "basil-home",workspace = "corgifun") - Cloud: AWS, region
eu-central-1 - Runtime: Node.js 16.x (Lambda)
- Helper: a Python prompt generator (see
python-prompt-generator/) - CI: GitHub Actions workflow in
.github/workflows/terraform.yml
All sensitive inputs are declared in variables.tf with sensitive = true
and supplied via the Terraform Cloud workspace (never committed):
| Variable | Description |
|---|---|
discord_token |
Discord bot token |
discord_public_key |
Discord application public key (interaction verification) |
ig_username |
Instagram account username |
ig_password |
Instagram account password |
Instagram credentials are additionally written to SSM Parameter Store as
SecureString so the publishing Lambda can read them at runtime without
embedding them in environment variables.
Note on history: an early CI workflow embedded AWS credentials directly. Those credentials were rotated long ago and the history of this repo has been rewritten to remove the literal values before this README was added.
.
├── 00-infra-vpc-main.tf # (currently inert) VPC scaffolding
├── 00-lambda-nodemodules-layer.tf # Shared Lambda layer
├── 01-*.tf # Discord-side resources (Lambda, SQS, SNS, API GW)
├── 02-*.tf # Image processing Lambda + S3/DynamoDB/API GW
├── 03-publish-image-to-ig-lambda.tf# IG publisher Lambda + EventBridge cron + SSM
├── 04-extract-images-lambda.tf # Image-extraction Lambda
├── lambda/ # Node.js Lambda sources
├── lambda-layer/ # node_modules bundled into a Lambda layer
├── python-prompt-generator/ # Auxiliary prompt-generation script
├── register-discord-commands/ # One-shot helper for registering slash commands
├── variables.tf # Sensitive input declarations
├── provider.tf # AWS provider + Terraform Cloud backend
└── outputs.tf # Emits the API Gateway endpoint URL
Prerequisites: Terraform >= 1.x, an AWS account, a Terraform Cloud workspace
called corgifun under organization basil-home (or fork and adjust
provider.tf).
# 1. Authenticate against Terraform Cloud
terraform login
# 2. Initialize providers + remote state
terraform init
# 3. Set the four sensitive variables in the TFC workspace UI
# (discord_token, discord_public_key, ig_username, ig_password)
# 4. Plan / apply
terraform plan
terraform applyThe api_gateway_url output is the endpoint to register with Discord as the
interactions URL.
terraform destroyNote that the corgi-rendered-images-ready S3 bucket has force_destroy = false — generated images are treated as the golden source and must be
emptied manually before the bucket can be destroyed.
Portfolio / learning project. Not maintained for production use. Useful as a small but complete reference for a Lambda + API Gateway + SNS/SQS pipeline managed entirely from Terraform with remote state.
No license is granted; all rights reserved by the author. Open an issue if you want to reuse a piece of it.