Helm chart for deploying Hikma Health Server to a DigitalOcean Kubernetes cluster with GitHub Actions CI/CD.
- DigitalOcean Kubernetes cluster with Gateway API installed
- GitHub repository access for
hikmahealth/hikma-health-server - GitHub Packages (GHCR) access
- PostgreSQL database (DigitalOcean Managed Database recommended)
Set up the following secrets in your gliax/helm-hikma repository:
| Secret Name | Description | Example |
|---|---|---|
DATABASE_URL |
PostgreSQL connection string | postgresql://user:***@host:5432/dbname?sslmode=require |
KUBE_CONFIG |
Base64-encoded Kubernetes kubeconfig | See below |
DIGITALOCEAN_TOKEN |
DO API token with cluster access | See below |
GHCR_PAT |
GitHub PAT for pulling images from GHCR | See below |
HIKMA_REPO_TOKEN |
GitHub token with access to hikma-health-server | Personal Access Token (classic) with repo scope |
GATEWAY_HOST (optional) |
Domain for Gateway API | hikma.yourdomain.com |
# Get your DO kubeconfig
doctl kubernetes cluster kubeconfig save your-cluster-name
# Base64 encode it for GitHub secret
cat ~/.kube/config | base64 -w 0Copy the output and add it as the KUBE_CONFIG secret.
- Go to DigitalOcean Control Panel → API → Generate New Token
- Name it something like "GitHub Actions - helm-hikma"
- Select these scopes:
- ✅ access cluster - View and download Kubernetes cluster credentials (REQUIRED)
- ✅ read - View Kubernetes clusters (optional, for troubleshooting)
- Click Generate Token
- Copy the token and add it as
DIGITALOCEAN_TOKENsecret
Important: The access cluster scope is required for doctl to authenticate with your Kubernetes cluster.
- Go to GitHub Settings > Developer Settings > Personal access tokens > Tokens (classic)
- Generate new token with
reposcope - Add it as
HIKMA_REPO_TOKENsecret
Create a PostgreSQL database on DigitalOcean Managed Databases:
- Go to DigitalOcean Control Panel > Databases
- Create new PostgreSQL database
- Note the connection string (DATABASE_URL format):
postgresql://doadmin:password@host:25060/defaultdb?sslmode=require - Add this as the
DATABASE_URLGitHub secret
Simply push to the main branch of this repository. The workflow will:
- Clone hikma-health-server source
- Build Docker image
- Push to GHCR
- Deploy to your Kubernetes cluster
# Clone this repo
git clone https://github.com/gliax/helm-hikma.git
cd helm-hikma
# Create namespace
kubectl create namespace hikma
# Create database secret
kubectl create secret generic hikma-db-credentials \
--from-literal=DATABASE_URL="postgresql://user:password@host:5432/db?sslmode=require" \
-n hikma
# Create image pull secret for GHCR
kubectl create secret docker-registry ghcr-credentials \
--docker-server=ghcr.io \
--docker-username=gliax \
--docker-password=$YOUR_GITHUB_TOKEN \
-n hikma
# Deploy with Helm
helm upgrade --install hikma . \
--namespace hikma \
--set gateway.host=hikma.yourdomain.com \
--wait| Parameter | Description | Default |
|---|---|---|
image.registry |
Container registry | ghcr.io |
image.repository |
Image repository | gliax/hikma-health-server |
image.tag |
Image tag | latest |
replicaCount |
Number of replicas | 1 |
service.port |
Service port | 3000 |
gateway.enabled |
Enable Gateway API HTTPRoute | true |
gateway.host |
Domain for Gateway API | hikma.example.com |
resources.limits.memory |
Memory limit | 6Gi |
resources.limits.cpu |
CPU limit | 2000m |
database.secretName |
Kubernetes secret name for DB | hikma-db-credentials |
namespace |
Kubernetes namespace | hikma |
Create a values-custom.yaml:
replicaCount: 2
resources:
limits:
memory: 8Gi
cpu: 4000m
gateway:
host: hikma.production.comDeploy with:
helm upgrade --install hikma . -f values-custom.yaml -n hikma┌─────────────────────────────────────────────────────────────┐
│ DigitalOcean K8s │
│ │
│ ┌──────────────┐ ┌──────────────────────────────┐ │
│ │ Gateway │────────▶│ hikma-hikma Service │ │
│ │ (Public) │ │ (ClusterIP) │ │
│ └──────────────┘ └──────────────┬───────────────┘ │
│ │ │
│ ▼ │
│ ┌───────────────────────┐ │
│ │ Deployment (Pods) │ │
│ │ - Hikma Health App │ │
│ │ - Port 3000 │ │
│ └──────────┬────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────┐ │
│ │ Image: GHCR │ │
│ │ ghcr.io/gliax/ │ │
│ │ hikma-health-server │ │
│ └──────────────────────┘ │
└──────────────────────────────┬──────────────────────────────┘
│
▼
┌──────────────────────┐
│ DigitalOcean │
│ Managed PostgreSQL │
└──────────────────────┘
# Check pods
kubectl get pods -n hikma
# Check deployment
kubectl get deployment hikma-hikma -n hikma
# View logs
kubectl logs -n hikma -l app.kubernetes.io/name=hikma -f
# Describe pod for events
kubectl describe pod -n hikma -l app.kubernetes.io/name=hikmaIssue: ImagePullBackOff
# Verify image pull secret
kubectl get secret ghcr-credentials -n hikma -o yaml
# Check image tag exists
docker pull ghcr.io/gliax/hikma-health-server:latestIssue: CrashLoopBackOff
# Check logs for database connection errors
kubectl logs -n hikma -l app.kubernetes.io/name=hikma
# Verify DATABASE_URL secret
kubectl get secret hikma-db-credentials -n hikma -o yamlIssue: Gateway not routing
# Check HTTPRoute
kubectl get httproute -n hikma
kubectl describe httproute hikma-hikma -n hikma
# Check Gateway
kubectl get gateway gateway-public# Uninstall release
helm uninstall hikma -n hikma
# Delete namespace (optional)
kubectl delete namespace hikmaThe GitHub Actions workflow (build-and-deploy.yaml) handles:
- Build Phase: Clones hikma-health-server, builds Docker image, pushes to GHCR
- Deploy Phase: Updates Helm values, deploys to Kubernetes via helm upgrade
- Push to main: Full build and deploy
- Pull requests: Build only (no deploy)
Go to Actions tab > Build and Deploy Hikma Health Server > Run workflow
- Never commit DATABASE_URL or kubeconfig to the repository
- Use GitHub secrets for all sensitive values
- Consider using a dedicated GitHub token with minimal required scopes
- Rotate database credentials regularly
- Enable GitHub repository protection rules for main branch
See the hikma-health-server repository for licensing information.