Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
Skip to content

AWS

Deploy rflow on Amazon Elastic Kubernetes Service (EKS) using the repository's Helm chart and a Postgres database, such as Amazon RDS. The chart runs the worker on port 3940, configures health probes, and mounts your project files.

Prerequisites

  • AWS CLI, authenticated to the intended account with permissions to create EKS and its networking, IAM, and EC2 resources.
  • eksctl, kubectl, Helm, Git, and Docker.
  • A reviewed rflow image from release 0.2.1 or later, pinned by digest.
  • A Postgres 14+ database dedicated to this project. The chart does not create Postgres.

The commands below create billable infrastructure. They use one AMD64 worker node as a starting point; size the cluster for your workflows and availability requirements. The published rflow release image targets linux/amd64.

1. Create an EKS cluster

Check the AWS account, then create a cluster with a managed node group:

aws sts get-caller-identity
 
eksctl create cluster \
  --name rflow-cluster \
  --region us-west-2 \
  --nodegroup-name rflow-workers \
  --node-type t3.medium \
  --nodes 1 \
  --managed
 
kubectl get nodes
kubectl create namespace rflow

eksctl writes the cluster context to your kubeconfig. If using an existing cluster, select its context and create the namespace if needed. See the eksctl cluster guide for custom VPCs and node groups.

The production chart enables an ingress NetworkPolicy. Enable network-policy enforcement in the Amazon VPC CNI or use another policy-capable CNI; creating a NetworkPolicy alone does not enforce it.

2. Prepare Postgres and the image

In RDS, create or select a PostgreSQL instance in a VPC reachable from the EKS pods. Create an rflow database and a login that can create its schemas and tables. Use a private endpoint and allow port 5432 in the database security group only from the relevant node/pod security group. Enable backups before running workflows.

Use the RDS endpoint hostname in the connection string:

postgresql://USER:URL_ENCODED_PASSWORD@YOUR-RDS-ENDPOINT:5432/rflow?sslmode=require

rflow verifies the server certificate and hostname. Download the appropriate RDS CA certificates and add them to the image's operating-system trust store using the database CA Dockerfile. If using a CA bundle, split it into one certificate per .crt file before update-ca-certificates. Do this for the image used by the worker so the core and both embedded engines trust the same CA. See RDS PostgreSQL TLS.

Build the derived image for linux/amd64, push it to a registry your nodes can pull from (for example ECR), and record its published digest. For a database whose CA is already trusted by the base image, you can use the published rflow image directly. A registry login on your laptop does not authorize Kubernetes image pulls; configure node/registry access before installing the chart.

3. Create the Kubernetes Secrets

Create a local file outside your Git repository, readable only by you, named rflow-env.production. It should contain the database URL from the previous step:

DATABASE_URL=postgresql://USER:URL_ENCODED_PASSWORD@YOUR-RDS-ENDPOINT:5432/rflow?sslmode=require

Export its path and create the Secrets. The API token is read from a file so it is not placed in a command argument:

export RFLOW_ENV_FILE=/absolute/private/path/rflow-env.production
chmod 600 "$RFLOW_ENV_FILE"
kubectl -n rflow create secret generic rflow-env --from-env-file="$RFLOW_ENV_FILE"
 
RFLOW_TOKEN_FILE=$(mktemp)
openssl rand -hex 32 | tr -d '\n' > "$RFLOW_TOKEN_FILE"
kubectl -n rflow create secret generic rflow-api \
  --from-file=rflow-api-token="$RFLOW_TOKEN_FILE"
rm "$RFLOW_TOKEN_FILE"

You can also provision these Secrets through your existing secret manager. They must exist in namespace rflow before installation. Never put resolved secrets in Helm values, rflowConfig, or projectFiles.

4. Install the Helm chart

git clone https://github.com/joshstevens19/rflow.git
cd rflow

Use a repository revision matching the release you reviewed. Create aws-values.yaml, replacing the repository and digest with your image from step 2:

replicaCount: 1
image:
  repository: YOUR_IMAGE_REPOSITORY
  digest: sha256:REPLACE_WITH_REVIEWED_DIGEST
service:
  type: ClusterIP
  port: 3940
ingress:
  enabled: false

Install the chart with its production defaults:

helm upgrade --install my-rflow ./helm/rflow \
  --namespace rflow \
  -f helm/rflow/values-production.yaml \
  -f aws-values.yaml \
  --wait --timeout 10m

The default project is a keyless heartbeat: it writes a console notification once a minute and only requires DATABASE_URL. Production values configure bearer authentication using rflow-api, a non-root container, resource limits, and a read-only root filesystem with writable project and temporary volumes.

Use your own workflows

Once the heartbeat is healthy, supply your project's rflow.yaml with --set-file rflowConfig=/absolute/path/to/project/rflow.yaml on the same Helm command. Before introducing a different project name, use a fresh database; the heartbeat database is already bound to my-rflow-project.

For example, a project using ${ETH_RPC} and abis/token.json also needs these entries in aws-values.yaml:

env:
  DATABASE_URL: ""
  ETH_RPC: ""
projectFiles:
  abis/token.json: |
    REPLACE_WITH_THE_COMPLETE_ABI_JSON

Add ETH_RPC to the rflow-env Secret; env lists which keys the chart reads from that Secret. Supply every required ABI and command script under its relative path in projectFiles. ConfigMap data is limited to 1 MiB; larger projects need a custom image/volume deployment. Run rflow validate --preflight and rflow doctor against the project with the intended environment before installing it. See self-hosting and the chart README for the full chart configuration.

5. Verify and monitor

kubectl -n rflow get pods
kubectl -n rflow rollout status deployment/rflow-my-rflow --timeout=10m
kubectl -n rflow logs deployment/rflow-my-rflow -c rflow --tail=100
kubectl -n rflow port-forward service/rflow-my-rflow 3940:3940

Leave the port-forward running. In another terminal:

curl --fail http://127.0.0.1:3940/live
curl --fail http://127.0.0.1:3940/health
 
RFLOW_API_TOKEN=$(kubectl -n rflow get secret rflow-api \
  -o jsonpath='{.data.rflow-api-token}' | openssl base64 -d -A)
curl --fail -H "Authorization: Bearer $RFLOW_API_TOKEN" \
  http://127.0.0.1:3940/api/workflows

Open http://127.0.0.1:3940/ for the history explorer and use the token stored in rflow-api to log in. /live is the startup/liveness probe; /health is readiness and returns 503 with reasons when degraded. The chart already configures these probes. Scrape the bearer-protected /metrics endpoint with your monitoring stack and collect container logs; see observability.

The service remains private. For external access, configure an ingress controller, TLS, and the chart's ingress values. Extend networkPolicy.ingressFrom to allow the controller and monitoring namespaces. Protect webhook routes with their own HMAC authentication.

6. Upgrade and recover

Back up Postgres, update the image digest/project files, and rerun the same helm upgrade --install command with all values and --set-file options used for your project. The chart uses Recreate, stopping the old worker before starting its replacement. Expect a short interruption. Secret changes need a restart:

kubectl -n rflow rollout restart deployment/rflow-my-rflow
kubectl -n rflow rollout status deployment/rflow-my-rflow --timeout=10m

Keep replicaCount: 1, or configure both replicaCount and ha.enabled: true for leader/standby failover. Additional replicas do not divide the workflow load. Waiting standbys are not HTTP-ready, so Helm's --wait and Deployment rollout checks can time out even with a healthy leader; check leader readiness and standby logs separately for that topology.

Project and /tmp volumes are ephemeral. Back up Postgres, retain project files separately, and store any durable script artifacts externally. Follow the production runbook before rolling back a release or restoring a database; Helm rollback does not undo database migrations.

7. Clean up

After taking any required backup, remove the application and the example cluster:

helm uninstall my-rflow --namespace rflow
eksctl delete cluster --name rflow-cluster --region us-west-2

Only delete a cluster you created for this example. RDS, registry images, backups, and separately provisioned networking are not removed by Helm; review and delete unused resources separately to stop their charges.