> ## Documentation Index
> Fetch the complete documentation index at: https://ngrok.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Deploy a production API and gateway with APIOps using Argo CD and ngrok

> Deploy an API with APIOps and Argo CD using ngrok.

This guide walks you through deploying a demo API to a Kubernetes cluster using an APIOps workflow.
It consolidates the backend API service, Kubernetes configurations, and API policy definitions into a single repository that defines the *desired state* of your deployment.

It covers:

* ngrok's out-of-the-box [API Gateway](https://ngrok.com/use-cases/api-gateway)
* The ngrok [Kubernetes Operator](https://github.com/ngrok/ngrok-operator/), which adds secure public ingress and middleware execution with declarative CRDs
* The [Kubernetes Gateway API](https://kubernetes.io/docs/concepts/services-networking/gateway/), for role-oriented load balancing and routing with [developer-defined](https://ngrok.com/blog-post/developer-defined-golden-path-kubernetes-gateway-api) paths to production APIs
* [Argo CD](https://argo-cd.readthedocs.io/en/stable/), a declarative GitOps tool for Kubernetes that version-controls definitions, configurations, and environments—including an API gateway

## What you'll need

* [Argo CD](https://argo-cd.readthedocs.io/en/stable/cli_installation/) installed locally.
* An existing remote or local Kubernetes cluster *OR* [minikube](https://minikube.sigs.k8s.io/docs/start/) to create a new demo cluster locally, which will be referred to as `<YOUR-CLUSTER>`.
* An [AWS EKS cluster](https://eksctl.io/usage/creating-and-managing-clusters/).
* An [ngrok account](https://ngrok.com/signup).
* [kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/) and [Helm 3.0.0+](https://helm.sh/docs/intro/install/) installed on your local workstation.
* The [ngrok Kubernetes Operator](/k8s/) installed on your cluster.
* A reserved domain, which you can get in the ngrok [dashboard](https://dashboard.ngrok.com/domains) or with the [ngrok API](/api-reference/reserveddomains/list).
  * You can choose from an ngrok subdomain or bring your own custom branded domain, like `https://api.example.com`.
  * This guide refers to this domain as `<NGROK_DOMAIN>`.

## Deploy Argo CD

Set up Argo CD on your cluster to enable GitOps.

1. Create a namespace for Argo CD:

   ```bash theme={null}
   kubectl create namespace argocd
   ```

2. Apply Argo CD's default manifest to your Kubernetes cluster.

   ```bash theme={null}
   kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
   ```

3. Verify you've deployed Argo CD successfully via a single running pod.

   ```bash theme={null}
   kubectl get pods --namespace argocd

   NAME                                               READY   STATUS    RESTARTS   AGE
   argocd-application-controller-0                    1/1     Running   0          44s
   argocd-applicationset-controller-65bb5ff89-lcmbk   1/1     Running   0          45s
   argocd-dex-server-6f898cbd9-slg8h                  1/1     Running   0          45s
   argocd-notifications-controller-64bc7c9f7-dgnfm    1/1     Running   0          45s
   argocd-redis-5df55f45b7-2sf62                      1/1     Running   0          45s
   argocd-repo-server-74d5f58dc5-dgbnr                0/1     Running   0          45s
   argocd-server-5b86767ddb-57xlj                     0/1     Running   0          44s
   ```

4. Log into the Argo CD web UI by creating a new port-forwarding session.

   ```bash theme={null}
   kubectl port-forward svc/argocd-server -n argocd 8080:443
   ```

   When you navigate to `http://<YOUR-CLUSTER>:8080`, you'll first see a warning about self-signed certificates, which you can accept to proceed.
   Finally, Argo CD prompts you to login with a username and password.
   The username is `admin`, and you can retrieve the automatically generated administrator password with the following:

   ```bash theme={null}
   argocd admin initial-password -n argocd
   ```

   Once logged in, you'll have access to the Argo CD UI.

5. Log in to Argo CD via the CLI to enable administration.

   ```bash theme={null}
   argocd login <YOUR-CLUSTER>:8080
   ```

## Set up the demo API

Next, you need to set up the Git repository for the API you'll deploy behind your ngrok API gateway.
GitOps (and thus APIOps) requires declarative and version-controlled configuration, and that includes the hostname for your deployment.
You can't simply clone the demo API repository and apply it to your cluster, as the ngrok-supplied hostname will already be in use.

If you have an existing API and GitOps configuration, you can [skip to step 4](#deploy-your-demo-api-with-argo-cd) while adopting the Argo CD CLI commands to your Git repository.

1. Create a new ngrok static domain.
   Go to the [**Domains** section](https://dashboard.ngrok.com/domains) of the ngrok dashboard and click **Create Domain** or **New Domain**.
   This static domain (for example, `example.ngrok.app`) will be your `NGROK_DOMAIN` for the remainder of this guide.

2. Fork the repository for the demo API at [ngrok-samples/apiops-demo](https://github.com/ngrok-samples/apiops-demo).

3. In your fork, open `gateway.yaml` and replace the values of lines 18 and 37 with the ngrok domain you just created (for example, `one-two-three.ngrok.app`).

4. Add, commit, and push these changes to your fork.

## Deploy your demo API with Argo CD

Now that your demo API is forked and properly configured on GitHub, you can connect it to Argo CD to sync, reconcile, and deploy.

1. Register the demo app with Argo CD, replacing `<YOUR-GITHUB-USERNAME>` with your fork of the demo API repository.

   ```bash theme={null}
   argocd app create apiops-demo \
     --repo https://github.com/<YOUR-GITHUB-USERNAME>/apiops-demo.git \
     --path . \
     --dest-server https://kubernetes.default.svc \
     --dest-namespace apiops-demo
   ```

   Refresh the Argo CD UI to see your app.
   The **Missing** and **OutOfSync** status report are not errors; they reflect that Argo CD doesn't automatically sync and deploy a newly registered app.
   You can click the app to view additional details about the deployment and the Git repository on which it is based.

2. Use the Argo CD CLI to perform a manual first sync of your registered app against your Git repository.

   ```bash theme={null}
   argocd app sync apiops-demo
   ```

   Refresh the UI to see that your demo API is properly synced and deployed.
   You can also navigate to the [**Endpoints** section](https://dashboard.ngrok.com/endpoints) of the ngrok dashboard to see the endpoint the ngrok Kubernetes Operator created via secure tunnel.
   You can `curl` your deployed API; ngrok's API gateway handles ingress and TLS automatically.
   You'll only see `null` in response, but that confirms your demo API is working.

   ```bash theme={null}
   curl \
     -X GET \
     -H "Content-Type: application/json" \
     https://<NGROK-DOMAIN>/legend
   ```

## Enable APIOps in Argo CD

A fundamental component of GitOps, and thus APIOps, is that because your Git repository contains the latest version of your desired state, your deployment toolkit should automatically update the production deployment without any manual processes.

1. Enable auto sync of your app to the Git repository that stores your desired state.

   ```
   argocd app set apiops-demo --sync-policy automated
   ```

   You can confirm this change in the Argo CD UI.

   <Note>
     The default interval at which Argo CD looks for changes to the desired state in your Git repo is 3 minutes.
     You can alter this in Argo CD's configuration.
   </Note>

2. Optionally, test auto sync by editing the number of replicas of the demo API in your cluster.
   In your Git repository, open the `deployment.yaml` file and edit the `replicas` value:

   ```yaml theme={null}
   spec:
     replicas: 5
   ```

   To push these changes to your production cluster, add, commit, and push them to your Git repository.

   ```bash theme={null}
   git add .
   git commit -m "Increase replicas to 5"
   git push origin main
   ```

   Argo CD will soon poll your repository, identify changes, and reconcile the deployed state to increase the number of replicas.

## Configure your API gateway with Traffic Policies

The [Traffic Policy module](/traffic-policy/) can be used alongside the Kubernetes Gateway API.
This lets you place all your Traffic Policy actions into a single `NgrokTrafficPolicy` CRD and control your ngrok-powered API gateway with an APIOps workflow using version-controlled, declarative manifests.

The project includes a basic example in `traffic-policy.yaml`.
[See `traffic-policy.yaml` for details](https://github.com/ngrok-samples/apiops-demo/blob/main/traffic-policy.yaml).
Because rate limiting is typically the first step in protecting any API from abuse, that process is outlined below.

1. In your fork of the demo API project, create a new file called `rate-limiting.yaml`.
   Open the file and add the following YAML:

   ```yaml theme={null}
   kind: NgrokTrafficPolicy
   apiVersion: ngrok.k8s.ngrok.com/v1alpha1
   metadata:
     name: traffic-policy-rate-limiting
   spec:
     policy:
       on_http_request:
         - actions:
             - type: "rate-limit"
               config:
                 name: "Only allow 10 requests per minute"
                 algorithm: "sliding_window"
                 capacity: 10
                 rate: "60s"
                 bucket_key:
                   - "req.headers['host']"
   ```

   This example policy includes a low limit for demonstration purposes, but you can change the `capacity` value to your needs in production.

2. Insert the YAML below into the `HTTPRoute` in your `deployment.yaml`.

   This defines a filter that runs during the request or response lifecycle, letting you inject policy into all traffic arriving at your API through your ngrok API gateway.

   ```yaml theme={null}
    apiVersion: gateway.networking.k8s.io/v1
    kind: HTTPRoute
    metadata:
      name: apiops-demo-route
      namespace: apiops-demo
    spec:
      parentRefs:
        - kind: Gateway
          name: apiops-demo-gateway
          namespace: apiops-demo
      hostnames:
        - "apiops-demo.ngrok.app"
      rules:
        - matches:
            - path:
                type: PathPrefix
                value: /
          filters:
            - type: ExtensionRef
              extensionRef:
                group: ngrok.k8s.ngrok.com
                kind: NgrokTrafficPolicy
                name: traffic-policy-rate-limiting
          backendRefs:
            - name: apiops-demo-service
              port: 80
              kind: Service
   ```

3. Add, commit, and push this change to your Git repository.
   Argo CD will auto sync and reconcile the deployed state with the changes to the `NgrokTrafficPolicy` CRD and `HTTPRoute`.
   Once the ngrok Kubernetes Operator picks up those changes, it will push them—you can verify those changes directly in your [ngrok dashboard](https://dashboard.ngrok.com/endpoints).

4. Optionally, test your new rate limiting policy by `curl`-ing your API in a quick loop.

   ```bash theme={null}
   for i in `seq 1 50`; do \
     curl -s -o /dev/null \
       -w "\n%{http_code}" \
       -X GET https://apiops-demo.ngrok.app/legend ; \
   done
   ```

   You should see [`429` response codes](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/429) as your ngrok API gateway rate-limits your IP address.

## What's next?

You've now built a proof of concept for deploying an API to production using ngrok and Argo CD.
You can use this combination to deploy real-world API behind a production-grade gateway with no arcane configurations or expensive external infrastructure.

In a real-world deployment, you would also integrate your Git repository with a proper CI/CD pipeline, which would run tests for security, governance, and code quality.
By only merging changes that pass your CI/CD pipeline, you can better guarantee the production-readiness of your API.

For more Traffic Policy options, see the [Auth0 JWT integration](/integrations/jwt-validation/auth0/) and the [Traffic Policy docs](/traffic-policy/) for the full list of actions and syntax.
The [library of "drop-in" examples](https://ngrok.com/blog-post/api-gateway-policy-management-examples) contains additional use cases like blocking traffic from specific countries, deprecating API versions, [event logging](/obs/), and more.
