Skip to content

DEPLOYMENT

JaduSpine on AWS (ECS/Fargate + ALB + Cloudflare DNS) — Playbook

This repo’s playground expects:

  • WebSocket path: /connection/websocket
  • HTTP API path: /api
  • JWT (HS256) for client connections using JADU_SPINE_JWT_SECRET (see AUTH_README.md)

Target outcome:

  • A single JaduSpine realtime server (Centrifugo under the hood) on ECS/Fargate behind an ALB (HTTPS).
  • DNS handled by Cloudflare.
  • Admin enabled (password + secret).
  • HTTP API public (protected by API key).

0) Inputs you must decide

  • AWS region (must match your ACM certificate region)
  • JaduSpine domain (example): jaduspine.example.com
  • Allowed origin(s) for browsers (example): https://app.example.com
  • Where to deploy:
  • an existing VPC + subnets (recommended), or
  • create a new VPC (not included in this repo yet)

This repo includes a Terraform root module at infra/terraform/ which assumes you already have a VPC + subnets.


Prerequisites (local machine)

  • Terraform installed: https://developer.hashicorp.com/terraform/tutorials/aws-get-started/install-cli
  • AWS CLI installed and configured (Terraform uses your local AWS credentials)

Basic AWS CLI setup:

# 1) Install AWS CLI (macOS via Homebrew)
brew install awscli

# 2) Configure credentials (creates/updates ~/.aws/config and ~/.aws/credentials)
aws configure

# Optional: if you use profiles
aws configure --profile <profile-name>

# 3) Verify you’re authenticated to the expected AWS account
aws sts get-caller-identity

If you’re using a named profile, run Terraform with:

export AWS_PROFILE=<profile-name>

Create 4 secret values (values are up to you). These names are the runtime env var names your backend/Centrifugo will use:

  • JADU_SPINE_JWT_SECRET
  • CENTRIFUGO_API_KEY
  • CENTRIFUGO_ADMIN_PASSWORD
  • CENTRIFUGO_ADMIN_SECRET

Important:

  • In AWS Secrets Manager, the secret resource name/path can be anything. What matters is the secret value stored inside it.
  • Terraform only needs the secret ARNs and will inject those values into the right container env vars.

Naming suggestion for the AWS secret resource name (optional):

  • /jaduspine/<env>/JADU_SPINE_JWT_SECRET
  • /jaduspine/<env>/CENTRIFUGO_API_KEY
  • /jaduspine/<env>/CENTRIFUGO_ADMIN_PASSWORD
  • /jaduspine/<env>/CENTRIFUGO_ADMIN_SECRET

Paste the secret ARNs into infra/terraform/terraform.tfvars:

  • secret_arn_jadu_spine_jwt_secret → secret ARN that contains JADU_SPINE_JWT_SECRET
  • secret_arn_centrifugo_api_key → secret ARN that contains the API key value (used as CENTRIFUGO_API_KEY in your backend and injected as CENTRIFUGO_HTTP_API_KEY into Centrifugo)
  • secret_arn_centrifugo_admin_password → secret ARN that contains CENTRIFUGO_ADMIN_PASSWORD
  • secret_arn_centrifugo_admin_secret → secret ARN that contains CENTRIFUGO_ADMIN_SECRET

For our current setup (plain-text secrets), these are the values to paste:

secret_arn_jadu_spine_jwt_secret       = "arn:aws:secretsmanager:us-east-1:408921634255:secret:jaduspine/prod/jwt_secret-FBP1UO"
secret_arn_centrifugo_api_key          = "arn:aws:secretsmanager:us-east-1:408921634255:secret:jaduspine/prod/centrifugo_api_key-AjaXt1"
secret_arn_centrifugo_admin_password   = "arn:aws:secretsmanager:us-east-1:408921634255:secret:jaduspine/prod/centrifugo_admin_password-vrzc6p"
secret_arn_centrifugo_admin_secret     = "arn:aws:secretsmanager:us-east-1:408921634255:secret:jaduspine/prod/centrifugo_admin_secret-mZa8GX"

2) Create an ACM certificate (TLS) and validate it in Cloudflare

In AWS Certificate Manager (ACM), request a public certificate for:

  • jaduspine.example.com

Choose DNS validation. ACM will give you one (or more) DNS records like:

  • Name: _xxxx.jaduspine.example.com
  • Type: CNAME
  • Value: _yyyy.acm-validations.aws

In Cloudflare:

  • Add the CNAME record(s) exactly as ACM shows.
  • Set them to DNS only (grey cloud) for validation.

Wait until ACM shows the cert as Issued.


3) Configure Terraform variables

Copy the example file:

  • infra/terraform/terraform.tfvars.exampleinfra/terraform/terraform.tfvars

Fill in:

  • your VPC + subnet IDs
  • your certificate_arn
  • your secret ARNs
  • your allowed origins

4) Deploy (Terraform)

From repo root:

cd infra/terraform
terraform init
terraform plan -out tfplan
terraform apply tfplan

Terraform will output (at minimum) your ALB DNS name.


5) Point Cloudflare DNS at the ALB

In Cloudflare DNS:

  • Create CNAME record:
  • Name: jaduspine
  • Target: <alb-dns-name-from-terraform-output>

For fewer moving parts during initial setup:

  • set it to DNS only (grey cloud)

After things work end-to-end, you can decide whether to proxy it via Cloudflare (orange cloud). If you do, use Full (strict) TLS mode and keep the ALB HTTPS listener.


6) Configure your apps

Frontend

Set:

  • NEXT_PUBLIC_CENTRIFUGO_URL=wss://jaduspine.example.com/connection/websocket

Backend

Set:

  • CENTRIFUGO_API_URL=https://jaduspine.example.com/api
  • CENTRIFUGO_API_KEY=<same as secret>
  • JADU_SPINE_JWT_SECRET=<same as secret>

7) Verify

  • Open https://jaduspine.example.com and confirm you reach the server.
  • Confirm WebSocket connects from your app using:
  • wss://jaduspine.example.com/connection/websocket
  • Confirm backend publishing works via HTTP API:
  • https://jaduspine.example.com/api with CENTRIFUGO_API_KEY.

Notes (v1 constraints)

  • Keep desired_count = 1. Without Redis, multi-task scaling will cause some publishes to miss clients connected to other tasks.
  • Admin is enabled via password + secret (see infra/jaduspine.config.prod.json for the intended shape).