Infrastructure Foundation - Create the Kubernetes cluster and database infrastructure that will host your self-hosted Relvy application.
Overview
This guide walks you through setting up the infrastructure for Relvy on Kubernetes. We’ll focus on AWS EKS as the primary platform, with notes for GKE and AKS. You can also use any standard Kubernetes cluster.
What You’ll Create
Kubernetes Cluster EKS, GKE, or AKS cluster running Kubernetes 1.20+
PostgreSQL Database RDS, Cloud SQL, or Azure Database for PostgreSQL
Ingress Controller AWS Load Balancer Controller or equivalent
Option 1: AWS EKS
Step 1: Create EKS Cluster
# Configure AWS credentials
aws configure
# Set your AWS region
aws configure set region us-east-1
1.1 Using eksctl
The fastest way to create an EKS cluster is using eksctl:
# Create cluster with eksctl
eksctl create cluster \
--name relvy-cluster \
--region us-east-1 \
--nodegroup-name relvy-nodes \
--node-type t3.xlarge \
--nodes 3 \
--nodes-min 1 \
--nodes-max 5 \
--managed
This command creates:
EKS cluster named relvy-cluster
Managed node group with 3 t3.xlarge instances (4 vCPU, 16 GB RAM each)
Auto-scaling between 1-5 nodes
New VPC with public and private subnets across multiple availability zones
VPC and Subnet Configuration - By default, eksctl creates a new VPC with both public and private subnets across multiple availability zones. If you have an existing VPC and want to use specific subnets, you can specify them with —vpc-public-subnets
or —vpc-private-subnets
. The ALB requires at least 2 public subnets in different availability zones.
Optional: Use existing VPC subnets
# For public subnets (at least 2 in different AZs):
eksctl create cluster \
--name relvy-cluster \
--region us-east-1 \
--nodegroup-name relvy-nodes \
--node-type t3.xlarge \
--nodes 3 \
--nodes-min 1 \
--nodes-max 5 \
--vpc-public-subnets subnet-xxx,subnet-yyy \
--managed
# For private subnets (requires NAT Gateway or VPC endpoints):
eksctl create cluster \
--name relvy-cluster \
--region us-east-1 \
--nodegroup-name relvy-nodes \
--node-type t3.xlarge \
--nodes 3 \
--nodes-min 1 \
--nodes-max 5 \
--vpc-private-subnets subnet-xxx,subnet-yyy \
--managed
1.2 Verify Cluster Access
# Update kubeconfig
aws eks update-kubeconfig --name relvy-cluster --region us-east-1
# Verify cluster access
kubectl get nodes
# You should see 3 nodes in Ready status
1.3 Using AWS Console (Alternative)
If you prefer the AWS Console:
Navigate to EKS Console → Clusters → Create cluster
Cluster Configuration :
Name : relvy-cluster
Kubernetes version : 1.28 or higher
Cluster service role : Create new or use existing
Networking :
VPC : Select your VPC or create new
Subnets : Select at least 2 subnets in different AZs (required for ALB)
Security groups : Use default or custom
Add-ons : Keep default (CoreDNS, kube-proxy, VPC CNI)
Review and Create
After cluster creation, add a node group:
Navigate to Compute → Add node group
Configuration :
Name : relvy-nodes
Node IAM role : Create new or use existing
Instance types : t3.xlarge
Disk size : 30 GB
Scaling configuration : Min 1, Max 5, Desired 3
Subnets : Select the same subnets as cluster (at least 2 in different AZs)
Step 2: Install AWS Load Balancer Controller
The AWS Load Balancer Controller is required for Ingress support and automatic ALB provisioning.
2.1 Create IAM Policy
# Download IAM policy
curl -O https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.7.0/docs/install/iam_policy.json
# Create IAM policy
aws iam create-policy \
--policy-name AWSLoadBalancerControllerIAMPolicy \
--policy-document file://iam_policy.json
2.2 Create IAM Role for Service Account
# Get your AWS account ID
export AWS_ACCOUNT_ID = $( aws sts get-caller-identity --query Account --output text )
eksctl utils associate-iam-oidc-provider --cluster=relvy-cluster --approve
# Create service account with IAM role
eksctl create iamserviceaccount \
--cluster=relvy-cluster \
--namespace=default \
--name=aws-load-balancer-controller \
--role-name AmazonEKSLoadBalancerControllerRole \
--attach-policy-arn=arn:aws:iam::${ AWS_ACCOUNT_ID }:policy/AWSLoadBalancerControllerIAMPolicy \
--approve \
--override-existing-serviceaccounts
2.3 Install Load Balancer Controller with Helm
# Add EKS Helm repository
helm repo add eks https://aws.github.io/eks-charts
helm repo update
# Install AWS Load Balancer Controller
helm install aws-load-balancer-controller eks/aws-load-balancer-controller \
-n default \
--set clusterName=relvy-cluster \
--set serviceAccount.create= false \
--set serviceAccount.name=aws-load-balancer-controller \
--set region=us-east-1 \
--set vpcId= $VPC_ID
# Verify installation
kubectl get deployment -n default aws-load-balancer-controller
Step 3: Create RDS PostgreSQL Database
3.1 Get EKS Cluster Security Group
# Get cluster security group ID
export CLUSTER_SG = $( aws eks describe-cluster \
--name relvy-cluster \
--query 'cluster.resourcesVpcConfig.clusterSecurityGroupId' \
--output text )
echo "Cluster Security Group: $CLUSTER_SG "
3.2 Create Database Security Group
Option A: Using AWS CLI
# Get your VPC ID (same VPC as EKS cluster)
VPC_ID = $( aws eks describe-cluster \
--name relvy-cluster \
--query 'cluster.resourcesVpcConfig.vpcId' \
--output text )
# Get EKS cluster security group ID
EKS_SG = $( aws eks describe-cluster \
--name relvy-cluster \
--query 'cluster.resourcesVpcConfig.clusterSecurityGroupId' \
--output text )
# Create security group for RDS
RDS_SG_ID = $( aws ec2 create-security-group \
--group-name relvy-db-sg \
--description "Database security group for Relvy" \
--vpc-id $VPC_ID \
--output text )
# Add inbound rule to allow PostgreSQL from EKS cluster
aws ec2 authorize-security-group-ingress \
--group-id $RDS_SG_ID \
--protocol tcp \
--port 5432 \
--source-group $EKS_SG \
--group-rule-description "Allow EKS cluster access"
# Verify the security group was created
aws ec2 describe-security-groups --group-ids $RDS_SG_ID
Option B: Using AWS Console
Navigate to EC2 Console → Security Groups → Create Security Group
Field Value Name relvy-db-sg
Description Database security group for Relvy VPC [Same VPC as EKS cluster]
Inbound Rules:
Type : PostgreSQL, Port : 5432, Source : [Cluster Security Group ID from Step 3.1], Description : Allow EKS cluster access
3.3 Create RDS Instance
Option A: Using AWS CLI
Create the RDS instance using AWS CLI:
# Use the security group ID from step 3.2
# If you created it via CLI, use $RDS_SG_ID
# If you created it via Console, get the ID:
RDS_SG_ID = $( aws ec2 describe-security-groups \
--filters "Name=group-name,Values=relvy-db-sg" \
--query 'SecurityGroups[0].GroupId' \
--output text )
# Create RDS instance with Relvy specifications
aws rds create-db-instance \
--db-instance-identifier relvy-app-db \
--db-instance-class db.t3.medium \
--engine postgres \
--engine-version 17.4 \
--master-username postgres \
--master-user-password your-secure-password \
--allocated-storage 100 \
--storage-type gp3 \
--max-allocated-storage 200 \
--vpc-security-group-ids $RDS_SG_ID \
--db-name relvydb \
--storage-encrypted \
--deletion-protection \
--backup-retention-period 7 \
--no-publicly-accessible
# Wait for RDS instance to be available
aws rds wait db-instance-available --db-instance-identifier relvy-app-db
Option B: Using AWS Console (Recommended)
Navigate to RDS Console → Databases → Create database
Engine Options:
Field Value Engine type PostgreSQL Version PostgreSQL 17.4 (or latest) Templates Production
Settings:
Field Value DB instance identifier relvy-app-db
Master username postgres
Master password [Generate strong password - save this!]
Instance Configuration:
Field Value DB instance class db.t3.medium (2 vCPU, 4 GB RAM) Storage type General Purpose SSD (gp3) Allocated storage 100 GB Storage autoscaling Enable (max 200 GB)
Connectivity:
Field Value VPC [Same VPC as EKS cluster] DB subnet group Default or create new Public access No VPC security groups Choose existing → relvy-db-sg
Additional Configuration:
Field Value Initial database name relvydb
Backup retention period 7 days Deletion protection Enable
Important Database Requirements
📝 Save These Values:
Database Password : You’ll need this for the installer
Database Name : Default: relvydb
Database User : Usually postgres
3.4 Get Database Endpoint
# Get RDS endpoint
aws rds describe-db-instances \
--db-instance-identifier relvy-app-db \
--query 'DBInstances[0].Endpoint.Address' \
--output text
# 📝 Save This Value: Copy the database endpoint - you'll need it for the installer
Option 2: Google Cloud GKE
Step 1: Create GKE Cluster
# Set your project and region
export PROJECT_ID = your-project-id
export REGION = us-central1
# Create GKE cluster
gcloud container clusters create relvy-cluster \
--region $REGION \
--num-nodes 1 \
--node-locations us-central1-a,us-central1-b,us-central1-c \
--machine-type n1-standard-2 \
--enable-autoscaling \
--min-nodes 2 \
--max-nodes 5 \
--enable-autorepair \
--enable-autoupgrade
# Get cluster credentials
gcloud container clusters get-credentials relvy-cluster --region $REGION
# Verify
kubectl get nodes
Step 2: Create Cloud SQL Instance
# Create PostgreSQL instance
gcloud sql instances create relvy-app-db \
--database-version=POSTGRES_17 \
--tier=db-custom-2-7680 \
--region= $REGION \
--root-password=your-secure-password \
--storage-size=100GB \
--storage-type=SSD \
--storage-auto-increase \
--storage-auto-increase-limit=200 \
--backup-start-time=02:00
# Create database
gcloud sql databases create relvydb --instance=relvy-app-db
# Get connection name (you'll need this)
gcloud sql instances describe relvy-app-db --format= "value(connectionName)"
For GKE to access Cloud SQL, you’ll need to configure the Cloud SQL Proxy or use private IP. See Google Cloud documentation for details.
Option 3: Azure AKS
Step 1: Create AKS Cluster
# Set variables
export RESOURCE_GROUP = relvy-rg
export CLUSTER_NAME = relvy-cluster
export REGION = eastus
# Create resource group
az group create --name $RESOURCE_GROUP --location $REGION
# Create AKS cluster
az aks create \
--resource-group $RESOURCE_GROUP \
--name $CLUSTER_NAME \
--node-count 3 \
--node-vm-size Standard_D2s_v3 \
--enable-cluster-autoscaler \
--min-count 2 \
--max-count 5 \
--generate-ssh-keys
# Get credentials
az aks get-credentials --resource-group $RESOURCE_GROUP --name $CLUSTER_NAME
# Verify
kubectl get nodes
Step 2: Create Azure Database for PostgreSQL
# Create PostgreSQL server
az postgres flexible-server create \
--resource-group $RESOURCE_GROUP \
--name relvy-app-db \
--location $REGION \
--admin-user postgres \
--admin-password your-secure-password \
--sku-name Standard_D2s_v3 \
--tier GeneralPurpose \
--storage-size 128 \
--version 17
# Create database
az postgres flexible-server db create \
--resource-group $RESOURCE_GROUP \
--server-name relvy-app-db \
--database-name relvydb
# Get connection string
az postgres flexible-server show \
--resource-group $RESOURCE_GROUP \
--name relvy-app-db \
--query "fullyQualifiedDomainName" \
--output tsv
Verify Cluster Setup
Check Cluster Status
# Get nodes
kubectl get nodes
# Check system pods
kubectl get pods -n default
# Verify storage classes
kubectl get storageclass
# Check cluster info
kubectl cluster-info
Test Database Connectivity
# For AWS RDS - test from a temporary pod
kubectl run pg-test --rm -it --image=postgres:17 --namespace default -- \
psql -h your-rds-endpoint.region.rds.amazonaws.com \
-U postgres -d relvydb
# Enter password when prompted
# If successful, you'll see: relvydb=>
# Type \q to exit
Checkpoint - You now have a working Kubernetes cluster with database access! Save these values:Cluster name and region Database endpoint Database password
Next Steps
Your Kubernetes cluster and database are ready! Proceed to:
Configure Domain & SSL - Set up SSL certificate and DNS in Domain Configuration
Deploy Relvy - Install Relvy using Helm charts in Application Deployment