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.1or 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 rfloweksctl 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=requirerflow 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=requireExport 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 rflowUse 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: falseInstall 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 10mThe 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_JSONAdd 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:3940Leave 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/workflowsOpen 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=10mKeep 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-2Only 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.