---
name: satellite-dl-iks-classic
title: Using IBM Cloud Kubernetes Service on classic to host the `dl-reverse-proxy`
description: Follow these steps to set up the `dl-reverse-proxy` for IBM Cloud&reg; Direct Link by using IBM Cloud Kubernetes Service on classic.
last-updated: 2026-08-27
---

> ## Documentation Index
> The table of contents for this documentation set is at https://cloud.ibm.com/docs/satellite?format=markdown
> The index for all IBM Cloud docs is at: https://cloud.ibm.com/docs/llms.txt
> Use these files to discover more information as needed.

# Using IBM Cloud Kubernetes Service on classic to host the `dl-reverse-proxy`
{: #dl-iks-classic}
{: toc-content-type="tutorial"}
{: toc-services="satellite, containers, dl"}
{: toc-completion-time="2h"}

The following steps are deprecated. For the latest steps, see [Connecting to IBM Cloud via the private network by using Satellite Connector and Direct Link 2.0](https://cloud.ibm.com/docs/satellite?topic=satellite-direct-link-vpe&format=markdown).
{: deprecated}

Follow these steps to set up the `dl-reverse-proxy` for IBM Cloud&reg; Direct Link by using IBM Cloud Kubernetes Service on classic. 
{: shortdesc}


## Create an IBM Cloud Kubernetes Service cluster
{: #dl-cluster}
{: step}

Create an IBM Cloud Kubernetes Service cluster as the private-network connection between your Satellite location and IBM Cloud.
{: shortdesc}

1. Review the networking basics of clusters. In particular, ensure that you prepare the following:
    - [VLAN management (classic clusters only)](https://cloud.ibm.com/docs/containers?topic=containers-cs_network_cluster&format=markdown): Manage and choose both a public and private VLAN for your cluster's network connectivity.
    - [Subnet routing](https://cloud.ibm.com/docs/containers?topic=containers-subnets&format=markdown): Enable a Virtual Router Function (VRF) or VLAN spanning for your IBM Cloud infrastructure account so your worker nodes can communicate with each other on the private network and communicate with private cloud service endpoints internally.
    - [IP address schema](https://cloud.ibm.com/docs/containers?topic=containers-subnets&format=markdown#finding_subnets_account): Ensure that no subnet conflicts exist between the cluster and your on-premises network.

1. Review the steps you need to take to [prepare to create a cluster](https://cloud.ibm.com/docs/containers?topic=containers-clusters&format=markdown#cluster_prepare).

1. Create a standard [classic cluster](https://cloud.ibm.com/docs/containers?topic=containers-cluster-create-classic&interface=cli&format=markdown) or [VPC cluster](https://cloud.ibm.com/docs/containers?topic=containers-cluster-create-vpc-gen2&interface=cli&format=markdown) in the CLI. Create the cluster with the following features.
    - Classic clusters:
        - Zone: Any [multizone-capable zone](https://cloud.ibm.com/docs/containers?topic=containers-regions-and-zones&format=markdown#zones-mz)
        - Worker node flavor: Any classic infrastructure flavor
        - Network connectivity: Public and private VLANs
        - Worker pool: At least 2 worker nodes
        - Version: 1.20.7 or later
        - Cloud service endpoints: Both public and private endpoints
        - Subnets: Include subnets in the `--pod-subnet` and `--service-subnet` options if the default ranges conflict with the Satellite location’s subnet that you set up in your on-premises data center or in a different cloud provider 
    - VPC clusters:
        - Zone: Any [multizone-capable VPC zone](https://cloud.ibm.com/docs/containers?topic=containers-regions-and-zones&format=markdown#zones-vpc)
        - Worker node flavor: Any VPC infrastructure flavor
        - Version: 1.20.7 or later
        - Worker pool: At least 2 worker nodes
        - Subnets: Include subnets in the `--pod-subnet` and `--service-subnet` options if the default ranges conflict with the Satellite location’s subnet that you set up in your on-premises data center or in a different cloud provider
        - Cloud service endpoints: Do _not_ specify the `--disable-public-service-endpoint` option to ensure that both public and private endpoints are created

1. Spread the default worker pool across zones to increase the availability of your [classic](https://cloud.ibm.com/docs/containers?topic=containers-add-workers-classic&format=markdown#add_zone) or [VPC](https://cloud.ibm.com/docs/containers?topic=containers-add-workers-vpc&format=markdown#vpc_add_zone) cluster. Ensure that at least 2 worker nodes exist in each zone, so that the private ALBs that you configure in subsequent steps are highly available and can properly receive version updates.

1. Set the IBM Cloud Kubernetes Service cluster as the context for this session.
    ```sh
    ibmcloud ks cluster config --cluster CLUSTER_NAME_OR_ID
    ```
    {: pre}

1. Create a namespace for the NGINX reverse proxy.
    ```sh
    kubectl create ns dl-reverse-proxy
    ```
    {: pre}

## Set up private Ingress ALBs in the cluster
{: #dl-ingress}
{: step}

Set up private Ingress ALBs for your IBM Cloud Kubernetes Service cluster to expose an NGINX reverse proxy on the private network.
{: shortdesc}

1. Verify that at least one ALB with a **Type** of `private` exists in each zone.
    ```sh
    ibmcloud ks alb ls -c CLUSTER_NAME_OR_ID
    ```
    {: pre}

2. Ensure that the private ALBs have a **Status** of `enabled`. If they are disabled, run the following command to enable each private ALB.
    ```sh
    ibmcloud ks ingress alb enable classic --alb ALB_ID -c CLUSTER_NAME_OR_ID --version 0.45.0_1228_iks
    ```
    {: pre}

3. Optional: Disable each public ALB.
    ```sh
    ibmcloud ks ingress alb disable classic --alb ALB_ID -c CLUSTER_NAME_OR_ID
    ```
    {: pre}

4. Set up a custom domain for the private ALBs that the NGINX reverse proxy is accessible through, and optionally set up TLS for the domain.
    1. Create a custom domain through your DNS service provider. Your custom domain must be 130 characters or fewer to meet Ingress requirements.
    2. Map your custom domain to the private ALBs by adding their IP addresses as A records (classic clusters) or their VPC hostname as a CNAME (VPC clusters). To find the ALB IP addresses (classic) or hostname (VPC), run `ibmcloud ks ingress alb ls -c <cluster_name_or_ID>`. In VPC clusters, a hostname is assigned to the ALBs because the `10.X.X.X` IP addresses are dynamic and change over time.
    3. To use TLS termination, create a secret in the `dl-reverse-proxy` namespace that contains a TLS certificate for your custom domain. For example, if a TLS certificate is stored in IBM Cloud Certificate Manager that you want to use, you can import its associated secret into your cluster by running the following command. For more information, see [Custom domains with Ingress](https://cloud.ibm.com/docs/containers?topic=containers-ingress-domains&format=markdown).
        ```sh
        ibmcloud ks ingress secret create --name SECRET_NAME --cluster CLUSTER_NAME_OR_ID --cert-crn CERTIFICATE_CRN --namespace dl-reverse-proxy
        ```
        {: pre}

5. Define an Ingress resource file that uses your custom domain to route incoming network traffic to an `nginxsvc` that you create in subsequent steps. Replace `<custom_ingress_domain>` with the domain that you registered, and `<secret_name>` with the secret that you created for your domain's TLS certificate.
    ```yaml
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: dl-ingress-resource
      annotations:
        nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
        nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
    spec:
      ingressClassName: "private-iks-k8s-nginx"
      tls:
      - hosts:
        - <custom_ingress_domain>
        secretName: <secret_name>
      rules:
      - host: <custom_ingress_domain>
        http:
          paths:
          - path: /
            pathType: Prefix 
            backend:
              service:
                name: nginxsvc
                port:
                  number: 80
    ```
    {: codeblock}

6. Create the Ingress resource in your cluster.
    ```sh
    kubectl apply -f dl-ingress-resource.yaml -n dl-reverse-proxy
    ```
    {: pre}

The private Ingress ALBs in your cluster are now configured to expose a reverse proxy service with your custom domain on the IBM Cloud private network.

## Deploy an NGINX reverse proxy
{: #dl-reverse-proxy}
{: step}

Deploy an NGINX reverse proxy exposed by the Ingress ALBs and configure it to point to the Satellite Link tunnel server for your location.
{: shortdesc}

The following steps include editing and using local YAML files to create a ConfigMap, an NGINX deployment, and a service. As an alternative, you can clone an NGINX HTTPS sample repository, such as the [`https-nginx` directory of the `kubernetes/examples` repository](https://github.com/kubernetes/examples/tree/master/_archived/https-nginx){: external}, and [push the Docker image to a namespace in IBM Cloud Container Registry](https://cloud.ibm.com/docs/Registry?topic=Registry-getting-started&format=markdown). If you use a sample repository, ensure that the NGINX configuration, such as in the `default.conf` file, includes the server block that is specified in step 2 of this section.
{: tip}

1. Get the private service endpoint for the Link tunnel server. In the output, look for the `Address` that is listed for an endpoint of type `location`.
    ```sh
    ibmcloud sat endpoint ls --location LOCATION_ID
    ```
    {: pre}

    In this example output, the tunnel server endpoint is `c-04.private.us-east.link.satellite.cloud.ibm.com`. Replace `c-01`, `c-02`, or `c-03` with `d-01-ws`, `d-02-ws`, or `d-02-ws`. Do not include a port.
    ```sh
    ID                           Name                                            Destination Type   Address
    c1hnscnw0h7i5uf0t8eg_zE6Nx   openshift-api-c1muom3w0kfdne2kb37g              location           TCP   c-04.private.us-east.link.satellite.cloud.ibm.com:33809
    c1hnscnw0h7i5uf0t8eg_2F3Xo   openshift-api-c2e3ishw0sdo08f5902g              location           TCP   c-04-.private.us-east.link.satellite.cloud.ibm.com:34222
    c1hnscnw0h7i5uf0t8eg_EczUw   satellite-cos-c1hnscnw0h7i5uf0t8eg              cloud              TLS   m65f0b26d6c5f695647f5-6b64a6ccc9c596bf59a86625d8fa2202-c000.us-east.satellite.appdomain.cloud:30235
    c1hnscnw0h7i5uf0t8eg_56zpT   satellite-cosCrossRegion-c1hnscnw0h7i5uf0t8eg   cloud              TLS   m65f0b26d6c5f695647f5-6b64a6ccc9c596bf59a86625d8fa2202-c000.us-east.satellite.appdomain.cloud:31774
    ...
    ```
    {: screen}

2. Create a ConfigMap for the NGINX reverse proxy and save the file as `confnginx.yaml`. In the `server` block, replace `<custom_ingress_domain>` with the domain that you registered for the private Ingress ALBs and `<tunnel_server_ep>` with the tunnel server endpoint that you found in step 1.
    ```yaml
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: confnginx
    data:
      nginx.conf: |
        user  nginx;
        worker_processes  1;
        error_log  /var/log/nginx/error.log warn;
        events {
            worker_connections  1024;
        }
        http {
          include       /etc/nginx/mime.types;
          default_type  application/octet-stream;
          log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                              '$status $body_bytes_sent "$http_referer" '
                              '"$http_user_agent" "$http_x_forwarded_for"';
          access_log  /var/log/nginx/access.log  main;
          sendfile        on;
          keepalive_timeout  65;
          server {
            listen 80;

            server_name <custom_ingress_domain>;

            proxy_connect_timeout 180;
            proxy_send_timeout 180;
            proxy_read_timeout 180;

            location / {
              proxy_pass https://<tunnel_server_ep>;
              proxy_ssl_server_name on;
              proxy_http_version 1.1;
              proxy_set_header Upgrade $http_upgrade;
              proxy_set_header Connection "upgrade";
            }
          }
        }
    ```
    {: codeblock}

3. Create the ConfigMap in your IBM Cloud Kubernetes Service cluster.
    ```sh
    kubectl apply -f confnginx.yaml -n dl-reverse-proxy
    ```
    {: pre}

4. Create a deployment configuration for the NGINX reverse proxy and a service so that the deployment is included in the private Ingress load balancing. Save the file as `nginx-app.yaml`.
    ```yaml
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      selector:
        matchLabels:
          app: nginx
      replicas: 2
      template:
        metadata:
          labels:
            app: nginx
        spec:
          containers:
            - name: nginx
              image: nginx:alpine
              ports:
              - containerPort: 80
              volumeMounts:
                - name: nginx-config
                  mountPath: /etc/nginx/nginx.conf
                  subPath: nginx.conf
          volumes:
            - name: nginx-config
              configMap:
                name: confnginx
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: nginxsvc
      labels:
        app: nginx
    spec:
      type: NodePort
      ports:
      - port: 80
        protocol: TCP
        name: http
      - port: 443
        protocol: TCP
        name: https
      - port: 8080
        protocol: TCP
        name: tcp
      selector:
        app: nginx
    ```
    {: codeblock}

5. Create the deployment and service in your IBM Cloud Kubernetes Service cluster.
    ```sh
    kubectl apply -f nginx-app.yaml -n dl-reverse-proxy
    ```
    {: pre}

The reverse proxy is now configured to terminate incoming connections to your custom Ingress subdomain, open a new connection to the Satellite Link tunnel server, and forward requests to the tunnel server.

## Configure Link to use the reverse proxy
{: #dl-config-satlink}
{: step}

Configure the Link tunnel client in your Satellite location to send traffic over the Direct Link connection to the reverse proxy.
{: shortdesc}

1. To ensure that the Satellite Link configuration change was successful, verify that the location's **State** is `normal`.
    ```sh
    ibmcloud sat location get --location <location_name_or_ID>
    ```
    {: pre}

1. Verify that traffic flows from your Satellite location to IBM Cloud by [creating a Link endpoint of type `cloud`](https://cloud.ibm.com/docs/satellite?topic=satellite-link-cloud-create&format=markdown#link-cloud). For example, create a `cloud` endpoint for the private service endpoint of an IBM Cloud service, then [test the connection to the service from a Red Hat OpenShift on IBM Cloud cluster that runs in your Satellite location](https://cloud.ibm.com/docs/satellite?topic=satellite-link-cloud-create&format=markdown#link-cloud-test).

1. Verify that traffic flows from IBM Cloud to your Satellite location by [creating a Link endpoint of type `location`](https://cloud.ibm.com/docs/satellite?topic=satellite-link-cloud-create&format=markdown#link-location). For example, create a `location` endpoint for the IP address of an app in a Satellite cluster in your location, then test the connection to the app from a service in the IBM Cloud private network.

You've successfully configured your Satellite Link setup so that all traffic that flows over Link endpoints now uses your Direct Link connection.