Portefaix docs GitHub

Deploy Portefaix on DigitalOcean

This guide shows you how to deploy a Portefaix platform on DigitalOcean using DigitalOcean Kubernetes (DOKS), Spaces (S3-compatible object storage) for Terraform state, and the DigitalOcean CLI for cluster management.

Goal: a running DOKS cluster with Portefaix stacks continuously reconciled by ArgoCD.

Prerequisites

  • DigitalOcean account with a personal access token and a Spaces access key pair
  • doctl CLI installed and authenticated (doctl auth init)
  • Terraform ≥ 1.5, kubectl, and Helm installed locally

1. Configure your environment

Add DigitalOcean credentials to your Portefaix config file at $HOME/.config/portefaix/portefaix.sh:

function setup_digitalocean() {
    export DIGITALOCEAN_TOKEN="dop_v1_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
    # Spaces credentials (from DigitalOcean → API → Spaces Keys)
    export SPACES_ENDPOINT_URL="fra1.digitaloceanspaces.com"
    export SPACES_ACCESS_KEY_ID="DOxxxxxxxxxxxxxxxxxx"
    export SPACES_SECRET_ACCESS_KEY="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
    # Terraform S3 backend uses AWS env vars for Spaces
    export AWS_ACCESS_KEY_ID="$SPACES_ACCESS_KEY_ID"
    export AWS_SECRET_ACCESS_KEY="$SPACES_SECRET_ACCESS_KEY"
    export AWS_DEFAULT_REGION="eu-west-3"
    export AWS_REGION="eu-west-3"
}
. ./portefaix.sh digitalocean

export DO_REGION="fra1"    # fra1 | nyc1 | lon1 | ams3 | sgp1
export PORTEFAIX_ENV="dev"

2. Create Terraform remote state storage

DigitalOcean Spaces is S3-compatible. Create a Space to hold Terraform state files:

# Create the Space (globally unique name required)
doctl spaces create portefaix-tfstate --region $DO_REGION

# Enable versioning via the Spaces API (S3-compatible)
aws s3api put-bucket-versioning \
  --bucket portefaix-tfstate \
  --versioning-configuration Status=Enabled \
  --endpoint-url "https://$DO_REGION.digitaloceanspaces.com"

3. Provision the DOKS cluster with Terraform

cd portefaix-infrastructure/terraform/digitalocean/doks
cp terraform.tfvars.example terraform.tfvars
region          = "fra1"
cluster_name    = "portefaix-dev"
k8s_version     = "1.31"
node_size       = "s-2vcpu-4gb"
node_count      = 3
terraform init \
  -backend-config="bucket=portefaix-tfstate" \
  -backend-config="key=doks/$PORTEFAIX_ENV.tfstate" \
  -backend-config="region=$DO_REGION" \
  -backend-config="endpoint=https://$DO_REGION.digitaloceanspaces.com"

terraform plan -out=tfplan
terraform apply tfplan

4. Fetch cluster credentials

export CLUSTER_ID="$(terraform output -raw cluster_id)"

doctl kubernetes cluster kubeconfig save "$CLUSTER_ID"

kubectl get nodes
NAME                     STATUS   ROLES    AGE   VERSION
portefaix-dev-pool-xxxx  Ready    <none>   5m    v1.31.1

5. Deploy Portefaix stacks via ArgoCD

helm repo add argo https://argoproj.github.io/argo-helm
helm repo update

helm install argocd argo/argo-cd \
  --namespace argocd --create-namespace \
  --values portefaix-kubernetes/gitops/argocd/values-digitalocean.yaml \
  --wait

kubectl apply -f portefaix-kubernetes/gitops/argocd/bootstrap/app-of-apps-digitalocean-$PORTEFAIX_ENV.yaml

argocd app wait portefaix-bootstrap --health --timeout 600

Stacks available on DigitalOcean

StackDescriptionDigitalOcean service used
ObservabilityPrometheus, Grafana, Loki, TempoSpaces for long-term storage
DNS managementExternal DNSDigitalOcean DNS
TLS certificatescert-managerDigitalOcean DNS for DNS-01 challenges
Load balancingDigitalOcean Cloud ControllerDigitalOcean Load Balancer
Policy enforcementKyverno

Tip: use the DigitalOcean Container Registry (DOCR) as a private registry for your platform images. DOKS clusters can pull from DOCR without additional credentials when the registry is integrated with the cluster: doctl kubernetes cluster registry add CLUSTER_ID