How to Expose HTTP/HTTPS Ports

How and Why to Expose HTTP/HTTPS Ports

You can expose HTTP and HTTPS applications running in a playground VM to the public internet. An exposed application becomes accessible via a unique URL that can be used either by you (from a browser or another device) or shared with others.

Typical use cases are:

  • Experimenting with Kubernetes Dashboard Headlamp, Grafana, or any other web application deployed in a playground
  • Sharing a web application you're working on with friends or colleagues
  • Exposing an API service running in a playground to the public internet
  • Running a (graphical) remote desktop in a playground VM (example)
The `labctl expose port` command generates a unique URL that can be used to access the application from anywhere in the world.

The labctl expose port command generates a unique URL that can be used to access the application from anywhere in the world.

What ports can be exposed?

⚠️  Only applications listening on the machine's main network interface (usually eth1 with an IP address in the 172.16.0.0/24 subnet) or all interfaces (0.0.0.0) can be exposed.

Applications listening on the VM's localhost or internal interfaces (e.g., created by a Kubernetes networking plugin) cannot be exposed directly. As a workaround, you can forward such ports from a local to the main interface using socat or a similar tool and then expose the forwarded port instead.

Private vs. public exposed ports

Exposed HTTP(S) ports are private by default, meaning only the playground owner can access them. If you want to share an exposed port with others, you need to set the access control to public before exposing the port. Note that public exposed ports are visible to everyone, including anonymous users, so be mindful and avoid exposing sensitive ports to the public.

HTTP vs. HTTPS ports

Generated URLs always use the HTTPS protocol. However, the exposed application can be either HTTP or HTTPS (defaults to HTTP). If the target application serves traffic over HTTPS, you need to set the HTTPS option to Yes in the Expose HTTP(S) Ports dialog. This will inform the ingress proxy to access the application using the HTTPS protocol. The target application MAY use a self-signed certificate or a certificate from a private CA.

How to Expose HTTP/HTTPS Ports using the Web UI

To expose a port, simply click the Expose Port button in the top right corner of a running playground and select the VM and the port to expose:

The **Expose HTTP(S) Ports** dialog.

The Expose HTTP(S) Ports dialog.

The Expose HTTP(S) Ports dialog provides a test curl command to verify the port is accessible on machine's main interface. Run it from your playground VM to verify the port can be reached by the ingress proxy. Example:

curl http://node-01:8080

How to Expose HTTP/HTTPS Ports using the CLI

You can also expose a port using labctl:

labctl expose port --help
Expose an HTTP(s) service running in the playground

Usage:
  labctl expose port <playground> <port> [flags]

Flags:
  -h, --help                  help for port
      --host-rewrite string   Rewrite the host header passed to the target service
  -s, --https                 Enable if the target service uses HTTPS (including self-signed certificates)
  -m, --machine string        Target machine (default: the first machine in the playground)
  -o, --open                  Open the exposed service in browser
      --path-rewrite string   Rewrite the path part of the URL passed to the target service
  -p, --public                Make the exposed service publicly accessible

Below are a few practical examples of how to use the labctl expose port command.

Exposing a Docker container's published port

  1. Start a new Docker playground:
PLAY_ID=$(labctl playground start docker)
  1. Start a new Nginx container making it available on the playground VM's 0.0.0.0:8080 address:
labctl ssh $PLAY_ID -- docker run -d -p 8080:80 nginx:alpine
  1. Expose the published port 8080 with a public URL:
labctl expose port $PLAY_ID 8080 --public
HTTP port docker-01:8080 exposed as https://69a724cd1fce5dfccd59988d-b605c8.node-eu-d241.iximiuz.com
https://69a724cd1fce5dfccd59988d-b605c8.node-eu-d241.iximiuz.com
  1. Verify that the Nginx server is accessible from the public URL:
curl https://69a724cd1fce5dfccd59988d-b605c8.node-eu-d241.iximiuz.com

The output should be the Nginx welcome page.

Exposing a Kubernetes application via a NodePort service

  1. Start a new Kubernetes playground:
PLAY_ID=$(labctl playground start k3s)
  1. Deploy a sample Kubernetes application (a single Pod would do the trick):
labctl ssh $PLAY_ID -- kubectl run nginx-01 --image=nginx:alpine
  1. Expose the application with a NodePort service:
labctl ssh $PLAY_ID -- kubectl expose pod nginx-01 --port=80 --type=NodePort
  1. Find the application's NodePort:
labctl ssh $PLAY_ID -- kubectl get svc nginx-01
NAME       TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
nginx-01   NodePort   10.43.195.70   <none>        80:30762/TCP   42s
  1. Expose the NodePort service using the right port number and one of the cluster's nodes:
labctl expose port $PLAY_ID 30762 --machine node-01 --public
HTTP port node-01:30762 exposed as https://69a725671fce5dfccd59a92f-026f01.node-eu-d241.iximiuz.com
https://69a725671fce5dfccd59a92f-026f01.node-eu-d241.iximiuz.com
  1. Verify that the Nginx server is accessible by opening the generated URL in a browser.

Exposing a Kubernetes application via kubectl port-forward

  1. Start a new Kubernetes playground:
PLAY_ID=$(labctl playground start k3s)
  1. Deploy a sample Kubernetes application (a single Pod would do the trick):
labctl ssh $PLAY_ID -- kubectl run nginx-01 --image=nginx:alpine
  1. Forward the application's port 80 to the dev-machine VM of the playground using the kubectl port-forward command:
labctl ssh -m dev-machine $PLAY_ID -- \
    kubectl port-forward --address 0.0.0.0 pod/nginx-01 8080:80
Forwarding from 0.0.0.0:8080 -> 80

Note that the kubectl port-forward command must use the --address 0.0.0.0 flag to forward the port to all interfaces on the dev-machine VM. Otherwise, the forwarded port will only be accessible on the VM's localhost, which will make it impossible to expose with a generated URL.

  1. Expose the forwarded port with a generated URL:
labctl expose port $PLAY_ID 8080 --machine dev-machine --public
HTTP port dev-machine:8080 exposed as https://69a726071fce5dfccd59b97f-026f01.node-eu-d241.iximiuz.com
https://69a726071fce5dfccd59b97f-026f01.node-eu-d241.iximiuz.com
  1. Verify that the Nginx server is accessible by opening the generated URL in a browser.

Exposing Kubernetes API via direct access

The Kubernetes API server usually runs on port 6443 and uses a self-signed certificate. To expose it, you can use the --https flag (or the HTTPS option in the Expose HTTP(S) Ports dialog) to set the target protocol to HTTPS.

  1. Start a new Kubernetes playground:
PLAY_ID=$(labctl playground start k3s)
  1. Expose the Kubernetes API server with a generated URL on the control plane node:
labctl expose port $PLAY_ID 6443 --https --machine cplane-01 --public
HTTP port cplane-01:6443 exposed as https://69a726071fce5dfccd59b97f-026f01.node-eu-d241.iximiuz.com
https://69a726071fce5dfccd59b97f-026f01.node-eu-d241.iximiuz.com
  1. Verify that the Kubernetes API server is accessible by opening the generated URL in a browser.

Exposing Kubernetes API via kubectl proxy

If you want to bypass the API server's authentication, you can use the kubectl proxy command to forward the API server's port to the dev-machine VM of the playground combined with the --host-rewrite localhost flag of the labctl expose port command.

  1. Start a new Kubernetes playground:
PLAY_ID=$(labctl playground start k3s)
  1. Forward the API server's port 6443 to the dev-machine VM of the playground using the kubectl proxy command:
labctl ssh -m dev-machine $PLAY_ID -- \
    kubectl proxy --address 0.0.0.0 --port 8080
Starting to serve on [::]:8080
  1. Expose the forwarded port with a generated URL:
labctl expose port $PLAY_ID 8080 --public \
    --machine dev-machine --host-rewrite localhost
HTTP port dev-machine:8080 exposed as https://69a726071fce5dfccd59b97f-026f01.node-eu-d241.iximiuz.com
https://69a726071fce5dfccd59b97f-026f01.node-eu-d241.iximiuz.com
  1. Verify that the Kubernetes API server is accessible:
curl https://69a726071fce5dfccd59b97f-026f01.node-eu-d241.iximiuz.com/version
{
  "major": "1",
  "minor": "35",
  ...
}

Troubleshooting

If the generated URL is not working, check the following:

  • Is the target application up and running?
  • Do you use the correct machine and port in the Expose HTTP(S) Ports dialog (or the CLI command)?
  • Does the target application serves traffic over HTTP or HTTPS? If the latter, did you set the HTTPS option to Yes in the Expose HTTP(S) Ports dialog?
  • Does the target port appear in the ss -lntp output when run from the playground VM?
  • Is the target port open on the machine's main interface (or 0.0.0.0)?
  • Does the test curl command from the Expose HTTP(S) Ports dialog show the expected response?