Skip to main content

SecurityV0 Infrastructure Strategy

Date: 2026-03-31 Status: Active

Update 2026-04-23: The platform-hosting target for T3 cutover is Azure VM (not "AWS Lambda → ECS Fargate" as written in §8 Phases 3–4). See 2026-04-23-autonomous-scans-and-built-in-validation.md Pillar C for rationale. The AWS Organization + SCP + sandbox-account scheme in §4–§6 of this doc remains fully valid — it concerns accounts the AWS connector scans, not where the platform runs. Docker Compose on a plain Linux VM stays as the deploy shape across any cloud cutover.


Executive Summary

SecurityV0 currently runs on a single Hetzner VPS (Docker Compose: API + UI + MongoDB). Connectors are manual CLI scripts. This is fine for development but blocks three things:

  1. Temporal findings — connectors must run continuously to detect drift and ownership decay
  2. AWS integration development — we need real AWS infrastructure to build and test the AWS connector
  3. Demo environments — we need ephemeral AWS accounts to simulate customer infrastructure

The strategy:

  • Phase 1 (now): Activate $5,000 AWS credits and 1Password Business (both free via Mercury perks). Automate connectors on Hetzner with systemd timers + tiered secret management (1Password Service Accounts → SOPS+age fallback). Set up AWS Organization (4 accounts) for demos and connector testing.
  • Phase 2 (when needed): Move connectors to AWS Lambda for per-customer isolation and scaling.
  • Phase 3 (when revenue): Migrate platform to AWS if warranted by customer requirements.

1. Current State

Hetzner VPS (CX31/CX41, EUR 10-40/mo)
├── Docker Compose (always running)
│ ├── ui (React + nginx) :80
│ ├── api (Node/Express) :3000
│ └── mongo (MongoDB 7.0) :27017
├── Caddy (TLS termination) :443
└── Connectors: manual CLI runs (not scheduled)
├── entra-servicenow (Python)
└── azure-foundry (Python)

Domains: app.securityv0.com (prod), dev.securityv0.com (dev)
CI/CD: GitHub Actions → GHCR → docker-compose.deploy.yml

Problems:

ProblemImpact
Connectors run manuallyCannot detect temporal drift — findings are point-in-time snapshots, not continuous monitoring
No secret managementCredentials in .env files on disk — no rotation, no audit trail
Single serverNo fault isolation — a runaway connector can crash the platform
No AWS environmentCannot develop/test the AWS connector against real infrastructure
No demo infrastructureCannot simulate customer environments with real cross-account trust

Update (2026-04-01): Cloudflare Access (Zero Trust) has been enabled on both app.securityv0.com and dev.securityv0.com. All HTTP traffic is now authenticated at the Cloudflare edge before reaching the Hetzner VPS. See Access Protection for configuration details.


2. AWS Credits: Available Funding

Confirmed Available

ProgramCreditsHow to ActivateExpiration
Mercury → AWS Activate Portfolio$5,000Mercury dashboard → Perks → AWS Activate. Mercury provides Org ID for Activate application.2 years from activation

Additional Opportunities (Apply in Parallel)

ProgramCreditsEffortNotes
Azure Founders Hub (self-service)Up to $150,000Low — self-service applicationNo accelerator required. Free optionality for Azure-specific services.
GCP for StartupsUp to $100,000Medium — application reviewWorth applying; GKE is best-in-class if we ever need K8s
AWS Startup SA outreach$10-25K PoC creditsMedium — request meetingExplain Hetzner → AWS migration evaluation. Separate from Activate.
AWS Generative AI ProgramUp to $300,000Medium — if applicableRequires AI/ML product angle. Potentially applicable for Bedrock demo scenarios.

Credit Rules

  • One Activate grant per account. Mercury's $5,000 is the baseline. If we later join an accelerator with a higher-tier partnership ($25K-$100K), the grant can be upgraded.
  • Consolidated billing — Credits in the management account are shared across all Organization member accounts automatically.
  • Credits cover most services — EC2, Lambda, ECS, Bedrock, S3, Secrets Manager, etc. Excludes Marketplace purchases, RI upfront payments, domain registration.
  • Cannot stack multiple Activate grants on the same account. But Azure/GCP credits are entirely separate programs.

Credit Burn Rate Projections

ScenarioMonthly BurnRunway ($5K)Description
Conservative$70-20025+ monthsConnectors on Hetzner, AWS for demos only (nightly cleanup), minimal Bedrock
Moderate$200-50010-25 monthsRegular demos, dev Bedrock usage, some always-on infrastructure
Aggressive$500-1,5003-10 monthsFull platform migration, heavy Bedrock, multiple concurrent demos

Recommendation: Start conservative. $5,000 at $150/mo average = 33 months. This is enough to validate the AWS strategy before committing to a migration.


3. Connector Automation

Phase 1: Hetzner + systemd timers (NOW)

The simplest path — 1-2 days to implement, zero additional cost.

Hetzner VPS
├── Docker Compose (always running)
│ ├── ui :80 → api :3000 → mongo :27017
│ │
│ └── Docker network: sv0-platform_default
│ (connectors join this network to reach API directly)

├── systemd timers (per connector)
│ ├── sv0-connector-entra.timer → every 30min
│ ├── sv0-connector-azure.timer → every 60min
│ └── sv0-connector-aws.timer → every 30min (future)

├── Connector execution:
│ docker run --rm \
│ --env-file=/etc/sv0/connectors/entra.env \
│ --network sv0-platform_default \
│ ghcr.io/securityv0/connector-entra-servicenow \
│ --all --submit --platform-url http://api:3000

└── Secrets: see "Secret Management" section below

Implementation steps:

  1. Write Dockerfiles for each connector (Python 3.11 slim, pip install, CLI entrypoint)
  2. Add CI workflow to build and push connector images to GHCR
  3. Create systemd timer + service units per connector
  4. Connectors join the Docker Compose network (--network sv0-platform_default) — API reachable at http://api:3000 without public exposure
  5. Configure secret management (see tiered options below)
  6. Health check: cron job queries GET /api/v1/syncs?limit=1 per connector, alerts if last sync > 2x interval

Cost: EUR 0/mo additional. Connectors use <256MB RAM each, run for 30s-5min, and exit.

Secret Management (Tiered Options)

Secret management for connectors on Hetzner has three tiers, depending on what's available. Choose the highest tier you can:

Tier 1: 1Password Business with Service Accounts (best)

Prerequisite: 1Password Business plan. Available free for 1 year via Mercury startup perks (Mercury dashboard → Perks → 1Password). The Business plan also includes free Family accounts for every team member, replacing any existing Family subscription.

Important: Service Accounts (headless, non-interactive API tokens) are a Business/Enterprise-only feature. They are NOT available on Family, Personal, or Teams plans. The Family plan supports op CLI with interactive authentication only.

How it works:

  1. Create a Service Account in 1Password (web UI → Developer → Service Accounts)
  2. Grant it read-only access to the sv0-connectors vault
  3. Store the service account token on Hetzner (one secret, root-only):
# /etc/sv0/op-token (chmod 600, owned by root)
OP_SERVICE_ACCOUNT_TOKEN=ops_eyJzaWduSW...
  1. Reference files contain op:// URIs — pointers, not secrets:
# /etc/sv0/connectors/entra.env (safe to store, no real credentials)
AZURE_TENANT_ID=op://sv0-connectors/entra-prod/tenant_id
AZURE_CLIENT_ID=op://sv0-connectors/entra-prod/client_id
AZURE_CLIENT_SECRET=op://sv0-connectors/entra-prod/client_secret
SERVICENOW_INSTANCE=op://sv0-connectors/servicenow-prod/instance
SERVICENOW_USER=op://sv0-connectors/servicenow-prod/username
SERVICENOW_PASSWORD=op://sv0-connectors/servicenow-prod/password
  1. systemd injects the token, op run fetches secrets at runtime:
# /etc/systemd/system/sv0-connector-entra.service
[Service]
Type=oneshot
EnvironmentFile=/etc/sv0/op-token
ExecStart=/usr/local/bin/op run \
--env-file=/etc/sv0/connectors/entra.env -- \
docker run --rm --network sv0-platform_default \
ghcr.io/securityv0/connector-entra-servicenow \
--all --submit --platform-url http://api:3000

What's on disk: One service account token (gates access to everything). All actual secrets fetched over HTTPS at runtime, never written to disk.

Benefits: Centralized rotation (change secrets in 1Password web UI, no server changes), full audit trail of every secret access, one credential on disk instead of 10+.

Tier 2: SOPS + age encryption (good — no SaaS dependency)

Use when: 1Password Business is not yet activated, or you prefer no SaaS dependency for secrets.

How it works:

  1. Generate an age key pair:
age-keygen -o /etc/sv0/age-key.txt  # chmod 600, root-only
# Public key: age1... (safe to share/commit)
  1. Encrypt secrets locally (on your machine):
sops --encrypt --age age1xxxxxxxxxx connectors/entra.env > connectors/entra.env.enc
# Encrypted file is safe to commit to git or store anywhere
  1. On Hetzner, decrypt at runtime in the systemd service:
# /etc/systemd/system/sv0-connector-entra.service
[Service]
Type=oneshot
RuntimeDirectory=sv0
RuntimeDirectoryMode=0700
ExecStartPre=/bin/sh -c 'SOPS_AGE_KEY_FILE=/etc/sv0/age-key.txt sops -d /etc/sv0/connectors/entra.env.enc > /run/sv0/entra.env'
ExecStart=docker run --rm \
--env-file=/run/sv0/entra.env \
--network sv0-platform_default \
ghcr.io/securityv0/connector-entra-servicenow \
--all --submit --platform-url http://api:3000

What's on disk: One age private key (equivalent to the 1Password service account token). Encrypted .env.enc files (useless without the key). Decrypted secrets exist only briefly in /run/ (tmpfs) during execution.

Benefits: No SaaS dependency. Encrypted secrets can live in git. Free. Works with any 1Password plan (or no 1Password at all).

Tradeoff vs Tier 1: No web UI for rotation (must re-encrypt and redeploy), no audit trail of secret access.

Tier 3: Plain .env files (simplest — acceptable for dev server)

Use when: Moving fast, Hetzner is temporary, and you accept the tradeoff.

# /etc/sv0/connectors/entra.env (chmod 600, owned by root)
AZURE_TENANT_ID=actual-tenant-id-here
AZURE_CLIENT_ID=actual-client-id-here
AZURE_CLIENT_SECRET=actual-secret-here
...
# /etc/systemd/system/sv0-connector-entra.service
[Service]
Type=oneshot
ExecStart=docker run --rm \
--env-file=/etc/sv0/connectors/entra.env \
--network sv0-platform_default \
ghcr.io/securityv0/connector-entra-servicenow \
--all --submit --platform-url http://api:3000

What's on disk: All secrets in plaintext. Root-only permissions are the only protection.

This is acceptable IF:

  • The Hetzner box is a dev/staging server, not production
  • You're migrating to AWS (Phase 2) where Secrets Manager replaces this
  • Only 1-2 people have SSH access
  • You don't need an audit trail of secret access

This is NOT acceptable when: You have customer credentials, multiple team members, or compliance requirements.

Recommendation

SituationTierAction
Mercury perk availableTier 1Activate 1Password Business (free 1 year), set up Service Accounts
Business plan takes timeTier 2Use SOPS+age now, migrate to Tier 1 when activated
Moving fast, Hetzner is temporaryTier 3Plain .env files, upgrade before onboarding customers
Moved to AWS (Phase 2+)AWS Secrets ManagerReplaces all of the above

In all tiers, the systemd timer, Dockerfile, CI, and Docker network setup are identical — only the secret injection mechanism changes. You can upgrade tiers without touching the connector code.

Phase 2: Hybrid — Hetzner platform + AWS connectors (WHEN NEEDED)

Move connectors to AWS Lambda when you need per-customer isolation or >10 connectors.

Hetzner VPS                              AWS
├── api + ui + mongo ├── EventBridge Scheduler
│ (always running) │ (cron per connector)
│ │
│ ◄── HTTPS POST ──────────────────── ├── Lambda (container images)
│ (app.securityv0.com/api/v1/ingest) │ ├── connector-entra-servicenow
│ │ ├── connector-azure-foundry
│ │ └── connector-aws
│ │
│ ├── Secrets Manager
│ │ (per-customer credentials)
│ │
│ └── CloudWatch Logs

When to graduate:

  • 10+ connectors or customer-specific connector instances
  • Need per-customer secret isolation (each customer's Azure/AWS creds separate)
  • Connector runs exceed 5 min or 512MB RAM
  • Want CloudWatch-native monitoring and alerting

Cost estimate: Lambda path for 5 connectors every 30min = ~$6-17/mo (mostly free tier for the first year).

Phase 3: Full AWS migration (WHEN REVENUE)

Not recommended now. 4-10x cost increase for equivalent workload. Only warranted when:

  • Paying customers require SLA guarantees
  • Auto-scaling needed for traffic spikes
  • Investor due diligence requires "production-grade" infrastructure
  • Team grows beyond 2 (want deploy without SSH access)

4. AWS Organization Strategy

Why Use Organizations (Even at 2 People)

  • Free — Organizations, Identity Center, SCPs cost nothing
  • Consolidated billing — $5K credits shared across all accounts automatically
  • Real cross-account testing — SecurityV0's product reads customer AWS accounts via AssumeRole. Single-account development can never test this.
  • Budget isolation — see exactly which account is burning credits
  • Blast radius — a runaway demo Lambda can't affect the platform account

Account Structure

┌──────────────────────────────────────────────────────────────┐
│ Management Account (billing + governance only) │
│ ├── AWS Budgets, Cost Explorer, Cost Anomaly Detection │
│ ├── IAM Identity Center (SSO for Ivan + CEO) │
│ ├── Service Control Policies │
│ └── Credits applied here → shared via consolidated billing │
│ │
│ OU: Platform │
│ ├── sv0-platform │
│ │ SecurityV0 SaaS infrastructure (when/if migrated) │
│ │ Currently: placeholder for future use │
│ │ │
│ OU: Sandbox │
│ ├── sv0-demo │
│ │ Ephemeral customer simulations │
│ │ Lambda, Step Functions, Bedrock, IAM roles │
│ │ Nightly cleanup via cloud-nuke │
│ │ Budget cap: $200/mo with auto-freeze SCP │
│ │ │
│ OU: Security │
│ └── sv0-security-tooling │
│ Simulates a real customer AWS environment │
│ Cross-account trust role → Platform account │
│ Persistent (not cleaned nightly) │
│ Used for: connector dev/test, integration testing │
└──────────────────────────────────────────────────────────────┘

Account Purposes

AccountPurposeEphemeral?Budget
ManagementBilling, SCPs, Identity Center. No workloads ever.No$0 (governance only)
sv0-platformSecurityV0 SaaS infrastructure (future). Placeholder now.No$300/mo cap
sv0-demoDemo customer environments. Lambda, Bedrock, IAM, Step Functions. CDK-deployed, nightly cleanup.Yes$200/mo cap + auto-freeze
sv0-security-toolingPersistent customer simulation. SecurityV0 connector reads from this account via cross-account role. Tests real AssumeRole flow.No$50/mo cap

IAM Identity Center (SSO)

Free, eliminates IAM user management:

UserManagement Accountsv0-platformsv0-demosv0-security-tooling
Ivan (CTO)BillingAccessAdministratorAccessAdministratorAccessAdministratorAccess
CEOBillingAccessReadOnlyAccess

Local credential management: granted.dev (open-source, fuzzy-find across SSO profiles):

brew install common-fate/granted/granted
assume sv0-demo-admin # Interactive or direct — sets creds in current shell

5. Budget Protection

Service Control Policies (Apply Immediately)

SCP 1: Region Lock (entire Organization)

Only allow us-east-1 and us-west-2. Prevents resources in forgotten regions.

{
"Version": "2012-10-17",
"Statement": [{
"Sid": "DenyNonApprovedRegions",
"Effect": "Deny",
"NotAction": [
"iam:*", "sts:*", "organizations:*",
"budgets:*", "ce:*", "support:*",
"health:*", "billing:*"
],
"Resource": "*",
"Condition": {
"StringNotEquals": {
"aws:RequestedRegion": ["us-east-1", "us-west-2"]
}
}
}]
}

SCP 2: Block Expensive Services (Sandbox OU)

{
"Version": "2012-10-17",
"Statement": [{
"Sid": "DenyExpensiveServices",
"Effect": "Deny",
"Action": [
"sagemaker:CreateTrainingJob",
"sagemaker:CreateEndpoint",
"redshift:CreateCluster",
"opensearch:CreateDomain",
"elasticache:CreateCacheCluster",
"emr:RunJobFlow",
"eks:CreateCluster",
"glue:CreateJob",
"kinesis:CreateStream",
"kafka:CreateCluster"
],
"Resource": "*"
}]
}

SCP 3: Instance Size Cap (Sandbox OU)

{
"Version": "2012-10-17",
"Statement": [{
"Sid": "DenyLargeEC2",
"Effect": "Deny",
"Action": "ec2:RunInstances",
"Resource": "arn:aws:ec2:*:*:instance/*",
"Condition": {
"StringNotLike": {
"ec2:InstanceType": [
"t3.micro", "t3.small", "t3.medium",
"t4g.micro", "t4g.small", "t4g.medium"
]
}
}
}]
}

SCP 4: Bedrock Model Restriction (Sandbox OU)

Only allow cheap models in demo environments:

{
"Version": "2012-10-17",
"Statement": [{
"Sid": "RestrictBedrockModels",
"Effect": "Deny",
"Action": [
"bedrock:InvokeModel",
"bedrock:InvokeModelWithResponseStream"
],
"Resource": "*",
"Condition": {
"ForAnyValue:StringNotEquals": {
"bedrock:ModelId": [
"anthropic.claude-3-haiku-20240307-v1:0",
"amazon.titan-text-lite-v1"
]
}
}
}]
}

SCP 5: Budget Freeze (Applied automatically by AWS Budget Actions)

When demo account hits $200/mo, this SCP is attached automatically:

{
"Version": "2012-10-17",
"Statement": [{
"Sid": "FreezeAccount",
"Effect": "Deny",
"Action": "*",
"Resource": "*"
}]
}

AWS Budgets

BudgetScopeAmountAlertsAction at 100%
TotalEntire org$500/mo50%, 80%, 100% emailNotify only
Demosv0-demo account$200/mo80% emailAuto-apply freeze SCP
Platformsv0-platform account$300/mo80%, 100% emailNotify only

Cost Allocation Tags

Define organization-wide, enforce via SCP:

sv0:environment = prod | dev | demo | test
sv0:project = platform | demo-acme | demo-globex | connector-test
sv0:owner = ivan | automated | demo-script
sv0:ephemeral = true | false
sv0:ttl = 2h | 4h | 24h | permanent

6. Demo Lab Environments

Strategy

Use AWS CDK v2 (TypeScript) for demo infrastructure. Each demo scenario is a CDK stack that can be deployed and destroyed cleanly.

sv0-platform/
infra/
cdk/
bin/demo-app.ts
lib/
demo-customer-stack.ts # Cross-account trust, IAM, Lambda
demo-bedrock-stack.ts # Bedrock agents, knowledge bases
demo-serverless-stack.ts # Step Functions, EventBridge, Secrets
scenarios/
cross-account-trust.yaml # Scenario definition
bedrock-support-agent.yaml
github-to-runtime.yaml

CDK Demo Stack Example

export class DemoCustomerStack extends cdk.Stack {
constructor(scope: Construct, id: string, props: DemoProps) {
super(scope, id, props);

// Cross-account trust role (simulates customer's SecurityV0 onboarding)
new iam.Role(this, 'SecurityV0ReadRole', {
roleName: 'SecurityV0-ReadOnly',
assumedBy: new iam.AccountPrincipal(props.platformAccountId),
externalIds: [props.externalId],
managedPolicies: [
iam.ManagedPolicy.fromAwsManagedPolicyName('SecurityAudit'),
],
});

// Sample Lambda (discoverable workload)
const fn = new lambda.Function(this, 'ClaimsProcessor', { ... });

// Sample Step Functions (cross-account orchestration)
const stateMachine = new sfn.StateMachine(this, 'ClaimsWorkflow', { ... });

// Tag everything as ephemeral
cdk.Tags.of(this).add('sv0:ephemeral', 'true');
cdk.Tags.of(this).add('sv0:ttl', '24');
}
}

Nightly Cleanup

EventBridge rule (2 AM UTC) → Lambda → cloud-nuke on sv0-demo account:

EventBridge: cron(0 2 * * ? *)
→ Lambda (in management or security-tooling account)
→ Assume role into sv0-demo
→ cloud-nuke: delete resources older than 12 hours
→ SNS notification with cleanup summary

Alternative: cdk destroy for known stacks if using named stacks.

Free Tier Optimization for Demos

Most demo components are within the free tier if torn down nightly:

ServiceFree TierDemo Usage
Lambda1M requests + 400K GB-seconds/moEasily within
Step Functions4,000 state transitions/moEasily within
DynamoDB25 GB + 25 WCU/RCUSample data fits
CloudTrail1 trail free/account (mgmt events)Sufficient
IAM, STS, Organizations, Identity CenterAlways freeCore to demos
EventBridgeAll events freeScheduling free

Biggest cost risk: Bedrock model invocations. Mitigated by SCP restricting to Haiku/Titan Lite only.


7. Tools

NOW (Phase 1)

ToolPurposeCost
1Password BusinessSecret management with Service Accounts for headless connector runs. Free 1 year via Mercury perks. Includes Family accounts for every team member.Free 1yr (Mercury), then $7.99/user/mo
SOPS + age (fallback)Encrypt secrets in git, decrypt at runtime. Use if 1Password Business not yet activated.Free
systemd timersConnector scheduling on HetznerFree (built into Linux)
granted.devAWS SSO credential management locallyFree, open source
cloud-nukeNightly cleanup of demo accountFree, open source
AWS CDK v2Demo infrastructure as codeFree

LATER

ToolPurposeWhen
Temporal.ioWorkflow orchestration for complex connector dependencies15+ connectors with inter-dependencies
org-formationAWS Organization as code8+ accounts
AWS Control TowerLanding zone management10+ accounts, customer onboarding
InfracostCost estimation in CI/CDMultiple CDK stacks in regular use
TerraformMulti-account infrastructureWhen CDK becomes insufficient

8. Phased Implementation Plan

Phase 1: Foundation (Week 1-2, ~$0/mo)

Day 1: Credits + Organization + 1Password

  • Activate Mercury → AWS Activate ($5,000 credits)
  • Activate Mercury → 1Password Business (free 1 year) — unlocks Service Accounts for headless connector runs. Replaces existing Family plan (Business includes Family for every team member).
  • Apply to Azure Founders Hub + GCP for Startups (parallel, free)
  • Create AWS Organization (management account)
  • Create 3 member accounts (sv0-platform, sv0-demo, sv0-security-tooling)
  • Enable IAM Identity Center, create users + permission sets
  • Install granted.dev locally

Day 2: Budget Protection

  • Apply SCPs: region lock, expensive service block, instance size cap, Bedrock model restriction
  • Create AWS Budgets with alerts + auto-freeze on demo account
  • Enable Cost Anomaly Detection
  • Activate cost allocation tags

Day 3-4: Connector Automation

  • Write Dockerfiles for entra-servicenow and azure-foundry connectors
  • Add CI workflow to build and push connector images to GHCR
  • Create systemd timer + service units on Hetzner
  • Configure secret management on Hetzner:
    • If 1Password Business activated: create Service Account, set up op run with op:// reference files (Tier 1)
    • If not yet activated: use SOPS+age encrypted .env files (Tier 2), or plain .env files as stopgap (Tier 3)
  • Test automated connector runs (verify syncs appear in platform)

Day 5: Verification

  • Verify temporal findings now work (multiple connector runs → drift detection)
  • Verify budget alerts fire (create a small test resource, check email)
  • Verify SSO login works from local machine via granted.dev

Phase 2: Demo Infrastructure (Week 3-4, ~$10-50/mo)

  • Create CDK project for demo customer environments
  • Deploy first demo scenario (cross-account serverless) in sv0-demo
  • Create cross-account trust role in sv0-security-tooling
  • Test SecurityV0 connector against sv0-security-tooling (real AssumeRole flow)
  • Set up nightly cloud-nuke Lambda for sv0-demo
  • Validate nightly cleanup works and sends notification

Phase 3: Connector Migration to AWS (When Needed)

Triggers: 10+ connectors, per-customer isolation needed, or connector runs >5min.

  • Move connectors to AWS Lambda (container images)
  • EventBridge Scheduler for cron rules
  • AWS Secrets Manager for per-customer credentials
  • CloudWatch for monitoring, alerting

Phase 4: Platform Migration (When Revenue)

Triggers: paying customers, SLA requirements, team >2 people.

  • ECS Fargate for API + UI
  • MongoDB Atlas M10 for database
  • ALB with ACM TLS
  • Full CI/CD to ECS
  • Decommission Hetzner

9. Cost Comparison

Current State vs Phased Options

ComponentCurrent (Hetzner)Phase 1 (Hetzner + AWS Org)Phase 2 (+Demos)Phase 3 (+Lambda)Phase 4 (Full AWS)
Platform hostingEUR 15-40/moEUR 15-40/moEUR 15-40/moEUR 15-40/mo$150-175/mo
Connector automation$0 (manual)$0 (systemd)$0 (systemd)$6-17/mo$6-17/mo
Secret management$0 (.env files)$0 (1Password Business free via Mercury, or SOPS+age)$0 (same)$4/mo (Secrets Mgr)$4/mo
AWS Organization$0$0$0$0
Demo infrastructure$10-50/mo$10-50/mo$10-50/mo
Databaseincludedincludedincludedincluded$57/mo (Atlas)
MonitoringDIYDIYDIY + CloudWatchCloudWatchCloudWatch
TotalEUR 15-40/moEUR 15-40/moEUR 25-90/mo$50-150/mo$230-310/mo

Credit Runway at Each Phase

PhaseMonthly Burn (AWS only)Runway ($5K credits)
Phase 1~$0Infinite (no AWS usage)
Phase 2$10-50100+ months (only demos)
Phase 3$20-7070+ months
Phase 4$230-31016-22 months

10. Decisions

Decided

DecisionChoiceRationale
Activate AWS creditsYes, via Mercury ($5K)Free money, no downside
Use AWS OrganizationsYes, 4 accounts from day oneFree, enables real cross-account testing
Connector automation (now)systemd timers + 1Password on HetznerSimplest, zero cost, 1-2 days
Secret management (now)Tiered: 1Password Business Service Accounts (best) → SOPS+age (fallback) → plain .env (stopgap)1Password Business free via Mercury perks; SOPS+age is free with no SaaS dependency; plain .env acceptable for temporary dev server
Demo infrastructureCDK v2 (TypeScript)Matches stack, clean deploy/destroy
Demo cleanupcloud-nuke via nightly LambdaSimple, proven
Budget protectionSCPs + AWS Budgets with auto-freezePrevents surprise bills
Local AWS credsgranted.dev + Identity CenterFree, best DX

Deferred

DecisionDefer UntilCurrent Alternative
Full AWS platform migrationPaying customers or SLA requirementStay on Hetzner
AWS Lambda for connectors10+ connectors or per-customer isolationsystemd timers
Temporal.io for orchestrationComplex connector dependenciesSimple cron scheduling
Control Tower10+ accountsManual org setup
Terraform for multi-accountCDK proves insufficientCDK + AWS CLI
MongoDB Atlas / DocumentDBPlatform migrationSelf-hosted MongoDB on Hetzner

Sources