Last modified July 7, 2026

Install an application using the app platform

Giant Swarm runs Flux on every management cluster, and Flux HelmRelease is the recommended way to deploy applications to your workload clusters. This guide walks you through installing a hello-world demo and exposing it through Envoy Gateway (the Giant Swarm default for ingress traffic) with a Gateway API HTTPRoute.

Note: If you have existing deployments using the legacy Giant Swarm App custom resource, migration guidance is coming soon. For new deployments, follow this guide.

For a deeper reference covering every Flux flag and option, see Deploying an application via a Flux HelmRelease.

Requirements

You need:

List the organizations you have access to:

kubectl gs get organizations

Then set environment variables for the org, namespace, and cluster name. We use these in every command below:

export ORGANIZATION=testing
export NAMESPACE=org-${ORGANIZATION}
export CLUSTER=test01

Step 1: Check what’s already installed

Before adding anything, list the Helm releases already running in your organization namespace, filtered to your cluster:

flux get helmreleases \
  --namespace ${NAMESPACE} \
  --label-selector giantswarm.io/cluster=${CLUSTER}

You’ll see the apps that ship with the cluster: the default-apps bundle, observability tooling, and other managed components. Confirm the Gateway API bundle is among them. If it isn’t, install it first using the Gateway API installation guide.

You can also confirm the default Gateway is ready, from your workload cluster:

kubectl get gateway --namespace envoy-gateway-system giantswarm-default

The PROGRAMMED column should read True once the Gateway is reconciled.

Step 2: Find your cluster’s base domain

Every workload cluster comes with a wildcard DNS record, so apps you expose are reachable at <name>.${CLUSTER}.<base-domain>. Read the base domain from the cluster values ConfigMap:

kubectl get configmap \
  --namespace ${NAMESPACE} \
  ${CLUSTER}-cluster-values \
  -o jsonpath="{.data.values}" | grep baseDomain

You’ll see something like baseDomain: test01.capi.aws.k8s.gigantic.io. Save that for the next step.

Step 3: Deploy the hello-world app

The hello-world chart includes an Ingress resource by default. Since we’re routing through Gateway API instead, disable that with a small values.yaml. Save the following as values.yaml in your current directory:

ingress:
  enabled: false

Then create the OCIRepository for the chart:

flux create source oci ${CLUSTER}-hello-world \
  --url oci://gsoci.azurecr.io/charts/giantswarm/hello-world \
  --tag 3.0.2 \
  --namespace ${NAMESPACE} \
  --interval 60m

Then the HelmRelease, pointing at your values.yaml:

flux create helmrelease ${CLUSTER}-hello-world \
  --namespace ${NAMESPACE} \
  --chart-ref OCIRepository/${CLUSTER}-hello-world \
  --values ./values.yaml \
  --kubeconfig-secret-ref ${CLUSTER}-kubeconfig \
  --target-namespace default \
  --label giantswarm.io/cluster=${CLUSTER} \
  --release-name hello-world \
  --interval 60m

What each flag does:

  • --chart-ref points at the OCIRepository created in the previous command.
  • --kubeconfig-secret-ref tells Flux which workload cluster to install into. The Secret is created for you alongside the cluster and follows the <cluster>-kubeconfig naming convention.
  • --target-namespace is the namespace in the workload cluster where the chart’s resources are created.
  • --label giantswarm.io/cluster=${CLUSTER} makes the resource show up under the correct cluster in the developer portal.

Wait for the HelmRelease to report Ready=True:

flux get helmrelease \
  --namespace ${NAMESPACE} \
  ${CLUSTER}-hello-world

At this point, the hello-world Service is running in the workload cluster but isn’t reachable from outside yet.

Step 4: Create an HTTPRoute

Apply an HTTPRoute to the workload cluster that attaches to the default Gateway and routes hello.<base-domain> to the hello-world Service. Replace the base domain with yours:

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: hello-world
  namespace: default
spec:
  parentRefs:
    - name: giantswarm-default
      namespace: envoy-gateway-system
  hostnames:
    - hello.test01.capi.aws.k8s.gigantic.io
  rules:
    - matches:
        - path:
            type: PathPrefix
            value: /
      backendRefs:
        - name: hello-world
          port: 80

Save it as hello-world-route.yaml and apply it against the workload cluster:

kubectl apply -f hello-world-route.yaml

Check that the route is accepted by the Gateway:

kubectl describe httproute --namespace default hello-world

Look for Condition: Accepted, Status: True in the output.

Step 5: Try it out

Curl the hello-world endpoint over HTTP:

curl -Is http://hello.test01.capi.aws.k8s.gigantic.io

You should get back HTTP/1.1 200 OK. To enable HTTPS, add the hello subdomain to your Gateway’s HTTPS listener and configure cert-manager for Gateway API. See Installing Gateway API with Envoy Gateway.

Hello world page

Step 6: Clean up

To remove the demo, delete the HTTPRoute from the workload cluster, then the HelmRelease and OCIRepository from the management cluster:

kubectl delete -f hello-world-route.yaml

flux delete helmrelease --namespace ${NAMESPACE} ${CLUSTER}-hello-world
flux delete source oci  --namespace ${NAMESPACE} ${CLUSTER}-hello-world

Next step

After learning how to deploy an application in the workload cluster, dive into how networking works in your cluster and how to configure security hardening of your application.