Building a full DevSecOps pipeline for a fictional VFX studio on AWS, from scratch, inside the free tier. New to Terraform, Docker, Kubernetes and CI/CD, so I’m learning hands-on: I make the architecture decisions and document the why behind each tool, using Claude AI to generate the heavier code and commands, which I then run, break and own. All tested locally with Floci (a local AWS emulator) before touching a real AWS account. Building in public as I go.
TECHNICAL BLOCKS
Core pipeline (7 blocks):
✅ 01. Network – VPC, per-department subnets, VPN, NACLs
✅ 02. Storage – S3 + DynamoDB, versioning, encryption
✅ 03. Identity – Cognito (MFA, 3 user pools), IAM with time/IP-based access policies
✅ 04. Automation – Step Functions, SNS, Lambda (FFmpeg), SyncSketch integration
⬜ 05. Render Farm – SQS, EC2 Spot + Auto Scaling
⬜ 06. Audit Logging – CloudTrail, CloudWatch alarms
⬜ 07. Client Review – CloudFront signed URLs, guest access for Recruiters
Cross-cutting topics (not tied to a single block):
– Governance amp; cost control (Budgets, tagging, Cost Explorer)
– Tool comparisons amp; trade-offs (Terraform vs CloudFormation, etc.)
– Multi-project isolation setup in Floci – Public documentation amp; architecture diagrams
—
BLOCKS 01-03 DETAIL (done so far):
01. Network
– VPC with one dedicated subnet per department, so no cross-department access.
– VPN for remote access, simulating a real studios internal network.
– NACLs as a second defense layer per subnet, on top of Security Groups.
02. Storage
– S3 buckets per department (Input / Output / Dailies) with native versioning on.
– DynamoDB for human-readable metadata per asset version (who uploaded, when, approval status).
– Encryption at rest by default, automatic version naming handled by Lambda (no manual versioning).
03. Identity
– Amazon Cognito: 3 separate user pools (internal team, clients, guests), MFA enforced for the internal team via software token.
– Guest pool uses passwordless EMAIL_OTP login with short-lived sessions, for sharing read-only access with recruiters/interviewers without exposing write permissions.
– IAM: 4 roles (Artist, Lead, Department Supervisor, VFX Supervisor) with layered access policies – time-based restrictions (deny outside business hours) and source-IP restrictions (VPN range only).
Supervisors aren’t hard-blocked after hours, they’re required to step up with MFA instead, with the access still logged and alerted.
– Built an `overtime-access` IAM group with automatic cleanup: EventBridge + Lambda remove users from the group every Monday morning, so temporary weekend/after-hours access doesn’t linger.
All tested and verified end-to-end against Floci (local AWS emulator) before anything touches a real AWS account.
Block 04: Automation (Part 1 of 2) — Architecture decisions
Continuing my DevSecOps pipeline for a fictional VFX studio on AWS, built inside the free tier. I make the architecture decisions and document the why behind each tool, using Claude AI to generate the heavier code and commands, which I then run, break and own. All tested locally with Floci (a local AWS emulator) before touching a real AWS account.
Block 04 is the automation brain of the pipeline — how an asset moves from uploaded to approved. The key design calls:
→ Orchestration: AWS Step Functions, not a chain of loose Lambdas. The whole approval journey of an asset is visible in one place, and if a step fails you see exactly where. A DynamoDB update Item step stamps each assets approval status, who reviewed it and when, before notifying.
→ Notifications: Amazon SNS to alert leads/supervisors on approval or rejection (SES kept as a simpler mail-only alternative).
→ Video generation: FFmpeg on Lambda, NOT AWS MediaConvert. MediaConvert has no real free tier (charged per output minute); FFmpeg on a Lambda layer is up to ~98% cheaper and fits the Lambda free tier. It burns in time-code and absolute frame number in a single pass.
→ Review tool: SyncSketch (industry standard, used by studios like Riot Games), over Frame.io / QuickReviewer, and over building my own mini Frame.io — out of scope for an infrastructure project.
→ Security detail — watermark as a security layer: the studio logo is burned in only when material leaves the circle of reviewers/approvers toward outside people. Every approval review (internal AND client) travels clean, so a logo-stamped file outside that circle is a signal it escaped the approval flow.
What I built in Block 04:
→ Reusable Terraform modules, not one giant file per department. A storage-base module (Input/Output buckets, versioning, encryption) and a video module (IAM role, least-privilege policies, the FFmpeg Lambda). Departments aren’t identical copies — Modelado doesn’t export video, so it only pulls the base module; Animation/FX pull both. The department is just a parameter.
→ The FFmpeg Lambda running end-to-end in Floci, burning in shot name, time-code and frame counter, dropping the result into a shared vfx-dailies bucket. Getting there meant chasing 3 chained bugs: a localhost that pointed at the wrong container, a layer zip with Windows backslash paths (a known Compress-Archive bug — rebuilt with tar), and an FFmpeg build with no drawtext filter (swapped for a static build that ships freetype).
→ SAST on my own code with Bandit — the Sec in DevSecOps. I chose Bandit over Semgrep (Python-specific, zero-config, right-sized for a few Lambdas; Semgrep noted as the next step if it grows multi-language). First run flagged 4 findings — all false positives of the Lambda context (subprocess use, hardcoded /tmp). I analyzed each, justified it in the code itself, marked them accepted, and the final run came back clean: zero findings.
→ Least-privilege pass over my own Terraform: I caught a log policy still using Resource: * and scoped it down to that functions own log group — exactly the kind of over-permissive default worth hunting down.
Block 04 done. Next up: Block 05 — the render farm (SQS + EC2 Spot + Auto Scaling).
All tested and verified end-to-end against Floci (local AWS emulator) before anything touches a real AWS account.












