Download

Download the latest installer bundle from the official endpoint:

download.circloud.net

The bundle contains:

  • circloud-installer (single binary that installs the cluster + platform)
  • lab-config.yaml (template for VM sizing, nodes, and Cloudflare settings)
  • scripts/ (PowerShell helpers for Hyper-V VM lifecycle)
  • scripts/setup_image.sh (WSL helper to prep the base VHDX image)
  • state/template_vm-facts.json (template for physical host installs)

Self-Hosting Installation

Circloud provisions its own Kubernetes lab and networking stack on your VMs or physical machines. It includes the GUI, API, VPC/subnet routing, and Cloudflare tunnels so you can expose apps securely using your own domain.

Prerequisites

Hardware

Minimum 4 nodes: 1 control plane + 3 workers. Each node needs 4+ GB RAM, 2+ CPU cores, 50+ GB disk.

Network

All nodes must be on the same network with internet access. Static IPs recommended.

Cloudflare

A Cloudflare account with a domain, Account ID, and API Token with Tunnel and DNS permissions.

Tools

WSL2 (for Windows) or Linux, PowerShell 7 (Hyper-V only), kubectl, git.

Hyper-V Users: Clone the project to a Windows filesystem path (e.g., C:\Users\YourName\projects\circloud) accessible from both Windows PowerShell and WSL via /mnt/c/.... Do NOT use a WSL-only path like ~/projects.
Hyper-V Admin Permissions: Enable Hyper-V, add your Windows account to the Hyper-V Administrators group, and run PowerShell as Administrator when provisioning VMs.

Configuration (lab-config.yaml)

Create or edit lab-config.yaml in the project root:

base_vhdx_path: vhdx/ubuntu-22.04-server.vhdx
vm_root_path: 'C:\Hyper-V\circloud'
vswitch_name: LAN-Switch
dataplane_switch_name: K8s-dp-LAN-Switch
dataplane_cidr: 11.0.0.0/24
dataplane_gateway: 11.0.0.1
dataplane_nat_name: K8s-dp-LAN-Switch-nat
pod_dns_nameservers:
  - 4.2.2.4
pod_dns_ndots: 1
cpu_count: 4
memory_gb: 12

# Cloudflare Tunnel configuration (REQUIRED)
# Leave blank to be prompted during installation
cloudflare_account_id: your-cloudflare-account-id
cloudflare_api_token: your-cloudflare-api-token
cloudflare_domain: yourdomain.com

nodes:
  - name: cp
    role: control
  - name: w1
    role: worker
    gpu: true
  - name: w2
    role: worker
  - name: w3
    role: worker
  - name: w4
    role: worker
  - name: s1
    role: storage

Cloudflare credentials can be added to lab-config.yaml to avoid prompts; otherwise the installer will request them during setup.

Cloudflare Tunnel Configuration (Required)

Cloudflare Tunnel credentials are required for CloudManager deployment. Put them in lab-config.yaml to avoid prompts; otherwise the installer will ask for them during setup. Since lab-config.yaml is tracked, avoid committing real secrets.

How to obtain these values

  • Cloudflare Account ID: Log in to Cloudflare Dashboard, select your domain, and find the Account ID on the Overview page.
  • Cloudflare API Token: Go to API Tokens, click "Create Token", and use the "Edit Cloudflare Zero Trust" template or create a custom token with:
    • Account > Cloudflare Tunnel > Edit
    • Zone > DNS > Edit
    Copy the token (it is only shown once).
  • Cloudflare Domain: Use a domain you own and have added to Cloudflare (example: example.com).

What gets exposed after deployment

  • https://api.yourdomain.com - CloudManager API
  • https://admin.yourdomain.com - CloudManager Admin GUI
  • https://yourdomain.com - CloudUser GUI (tenant portal)

Tenants can also create tunnels for their workloads using either the global domain or custom domains assigned by the admin.

Binary Installer (WSL)

Extract the bundle and run the installer from WSL:

tar -xf circloud-<version>.tar.gz
cd circloud-<version>
./circloud-installer

Step 1: Prepare Base Image (Hyper-V Only)

Skip this step if using physical machines.

# From WSL (using Windows filesystem path):
cd /mnt/c/Users/YourName/projects/circloud
./scripts/setup_image.sh

This downloads Ubuntu cloud image and prepares it for VM creation.

Step 2: Provision VMs (Hyper-V Only)

Skip this step if using physical machines. Instead, create state/vm-facts.json manually.

# From Windows PowerShell (Administrator):
cd C:\path\to\circloud
.\scripts\create-vms.ps1

Creates VMs based on lab-config.yaml and outputs state/vm-facts.json.

Step 3: Configure Cluster

This is the main installation step that deploys Kubernetes and CloudManager.

# From WSL:
# For Hyper-V: use Windows filesystem path
cd /mnt/c/Users/YourName/projects/circloud

# For physical machines: can use any path
cd ~/projects/circloud

./circloud-installer

The script will:

  • Prompt for missing Cloudflare credentials if not in lab-config.yaml
  • Generate Ansible inventory from state/vm-facts.json
  • Deploy Kubernetes cluster using Kubespray
  • Deploy Harbor container registry
  • Deploy CloudManager API, GUI, and database
  • Install GPU drivers on GPU-enabled worker nodes
  • Create Cloudflare tunnels for API and GUI access

GPU Support (Optional)

To enable GPU workloads, mark specific worker nodes with gpu: true in lab-config.yaml before running the installer. The installer installs NVIDIA drivers and configures the GPU runtime automatically. Pods can then request GPU access using gpu_access: true.

Step 4: Access the Platform

After installation completes, access the platform:

Local Access

API: https://localhost:8080
Admin GUI: https://localhost:8443
User GUI: https://localhost:8444

Public Access (via Cloudflare)

API: https://api.yourdomain.com
Admin GUI: https://admin.yourdomain.com
User GUI: https://yourdomain.com

These public URLs are derived from cloudflare_domain in lab-config.yaml. For example, if you set cloudflare_domain: circloud.net, you will access the User GUI at https://circloud.net, the Admin GUI at https://admin.circloud.net, and the API at https://api.circloud.net.

# Verify installation:
export KUBECONFIG=$PWD/state/kubespray/inventory/mycluster/artifacts/admin.conf
kubectl get nodes -o wide
kubectl get pods -n cloud-manager

Physical Machine Setup

For physical machines, manually create state/vm-facts.json:

{
  "s1": {"ipv4": "192.168.1.10", "role": "control", "user": "admin", "password": "yourpass"},
  "w1": {"ipv4": "192.168.1.11", "role": "worker", "user": "admin", "password": "yourpass"},
  "w2": {"ipv4": "192.168.1.12", "role": "worker", "user": "admin", "password": "yourpass"},
  "w3": {"ipv4": "192.168.1.13", "role": "worker", "user": "admin", "password": "yourpass"}
}

Then run ./circloud-installer from WSL or Linux.

Important: Ensure all nodes have SSH access configured and the user has sudo privileges. The installer will install all required packages automatically.

Getting Started

Welcome to Circloud! This guide will help you get started with deploying and managing your cloud infrastructure. Create Virtual Private Clouds (VPCs), subnets, pods, and Cloudflare tunnels to expose your services.

Your Resources: You can manage VPCs, subnets, pods, tunnels, and registry credentials from your dashboard. All resources are isolated within your environment.

VPCs

Create isolated virtual networks with optional internet access. Each VPC is completely isolated from other tenants.

Subnets

Divide your VPC into logical network segments with custom CIDR blocks.

Pods

Deploy containerized applications with auto-scaling replicas and load balancing.

Tunnels

Expose your services securely to the internet via Cloudflare tunnels.

Persistent Pods

Pods can request node-local persistent storage by setting persistent: true (and optional persistent_mount_path). Storage is created under /storage/<tenant-id>/<pod-id> and mounted into the container (default mount path is /storage).

  • Persistent pods are pinned to a single worker node selected by available storage.
  • All replicas for a persistent pod stay on the same node (no cross-node replication).
  • Storage is deleted when the pod is deleted, including cascade deletes via subnet/VPC/tenant removal.

Login

Use your tenant name and password to access the CloudUser dashboard. Your admin can provide the credentials, or you can create your own account if self-signup is enabled.

CloudUser login screen
CloudUser Login

Create Account

If self-service signup is enabled by the admin, you can create a tenant directly from the login page. This option is hidden when self-signup is disabled.

CloudUser create account screen
Create Tenant Account

Architecture

Circloud combines a FastAPI control plane with Kubernetes and Kube-OVN networking. The GUIs call the CloudManager API, which stores state in PostgreSQL and provisions VPC networking, pods, VIP services, DNS, and tunnels inside the cluster.

It is designed for independent developers, students, and startups who want cloud capabilities without hyperscale costs: run Circloud on local desktops (VMs) or on-prem servers, then expose apps securely through Cloudflare tunnels using a domain you own. For many workloads this is about 5% of the price of cloud infrastructure software on the market, making it practical for smaller teams.

Control Plane

Browser
  |
  |-- CloudManager GUI (admin)
  |-- CloudUser GUI (tenant)
          |
          v
     CloudManager API (FastAPI)
        |-- PostgreSQL (state)
        |-- Kubernetes + Kube-OVN (VPCs, subnets, pods, VIPs)
        |-- Tunnel Manager (Cloudflare API + DNS)
        |-- Harbor Registry (optional, internal images)

Tenant Data Plane

Tenant Namespace
  VPC
    + Core Subnet (12.0.0.0/16)
      - tenant-dns (2 replicas)
      - tunnel-service pods (cloudflared)
    + Workload Subnets
      - pods (replicas)
      - VIP Service (stable IP)
      - optional EIP + SNAT/FIP for internet
Status pipeline: A monitoring job runs every minute to read Kubernetes pod state and write it into the CloudManager database so the GUIs can show status without direct cluster access.

Setup & API Access

To use Circloud, you need your Tenant ID and API Token. These are available from your dashboard after logging in.

Step 1: Get Your Credentials

1

Log into the Dashboard

Visit the Circloud portal and log in with your tenant credentials.

2

Copy Your Tenant ID and API Token

Your credentials are displayed at the top of the dashboard. Click to copy them.

CloudUser Authentication tab with tenant credentials
Tenant Authentication (ID + API Token)

Step 2: Configure API Access

Use your API token with any HTTP client (curl, Postman, Python requests, etc.):

# Set your credentials
export TENANT_ID="your-tenant-id"
export API_TOKEN="your-api-token"
export API_URL="https://api.circloud.net"

# Test API access
curl -k -X GET "$API_URL/tenants/$TENANT_ID/vpcs" \
  -H "X-Auth-Token: $API_TOKEN"

API Roles and Tokens

Circloud exposes two authentication scopes:

Scope Header Used For
Admin X-Admin-Token Tenant lifecycle, domains, provider config, service tunnels
Tenant X-Auth-Token VPCs, subnets, pods, tunnels, topology

Many create endpoints also expect the token field in the JSON body. The header is still required and is the primary authentication check.

Step 3: Deploy Using Topology JSON

Create a topology.json file to define your infrastructure:

{
  "token": "YOUR_API_TOKEN",
  "vpcs": [
    {
      "name": "my-vpc",
      "description": "My VPC",
      "enable_internet": true
    }
  ],
  "subnets": [
    {
      "name": "my-subnet",
      "vpc_name": "my-vpc",
      "cidr": "10.100.1.0/24",
      "gateway_ip": "10.100.1.1"
    }
  ],
  "pods": [
    {
      "name": "my-app",
      "vpc_name": "my-vpc",
      "subnet_name": "my-subnet",
      "container_image": "nginx:latest",
      "replica_count": 2,
      "service_port": 80,
      "external_access": true,
      "auto_scaling": true,
      "autoscale_max_replicas": 6,
      "autoscale_cpu_target_millicores": 250
    }
  ]
}

Deploy with a single command:

curl -k -X POST "$API_URL/tenants/$TENANT_ID/topology" \
  -H "Content-Type: application/json" \
  -d @topology.json
Tip: Store your topology.json in version control to track infrastructure changes over time.

Using Private Container Registries

To pull images from private registries (Docker Hub, Harbor, etc.), add registry credentials:

{
  "token": "YOUR_API_TOKEN",
  "registry_credentials": [
    {
      "name": "dockerhub",
      "server": "https://index.docker.io/v1/",
      "username": "your-username",
      "password": "your-access-token"
    }
  ],
  "vpcs": [...],
  "subnets": [...],
  "pods": [...]
}

Virtual Private Clouds (VPCs)

A VPC is an isolated virtual network where you deploy your resources. Each VPC has its own routing table and is completely isolated from other VPCs.

CloudUser VPCs tab
VPCs Tab

Creating a VPC

1

From the Dashboard

Navigate to the VPCs tab and click "Create VPC". Enter a name and choose whether to enable internet access.

2

Via API

curl -k -X POST https://api.circloud.net/vpcs \
  -H "X-Auth-Token: YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "tenant_id": "YOUR_TENANT_ID",
    "token": "YOUR_TOKEN",
    "name": "production-vpc",
    "enable_internet": true
  }'

Core Services Subnet

Every VPC automatically includes a managed core subnet reserved for platform services. This subnet is created and maintained by Circloud and is not intended for user workloads.

  • Hosts tenant-dns pods (2 replicas) for internal name resolution
  • Hosts tunnel-service (cloudflared) pods when you create tunnels
  • Provides stable VIP addresses used by DNS records

Internet Access

When you enable internet access on a VPC, Circloud configures external routing so pods can be granted outbound or inbound connectivity. Internet access is controlled at the VPC level and refined per pod.

Setting Scope Effect
enable_internet VPC Enables external routing so EIP, SNAT, and FIP can be allocated
external_access Pod Allocates an EIP and SNAT for outbound internet
external_inbound Pod Creates a FIP for bidirectional inbound/outbound access
Note: external_inbound requires external_access=true. For HTTP/HTTPS services, Cloudflare tunnels are often simpler than direct inbound IPs.

Subnets

Subnets divide your VPC into smaller network segments. Each subnet has its own CIDR block and can host multiple pods.

CloudUser Subnets tab
Subnets Tab

Creating a Subnet

curl -k -X POST https://api.circloud.net/subnets \
  -H "X-Auth-Token: YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "tenant_id": "YOUR_TENANT_ID",
    "token": "YOUR_TOKEN",
    "vpc_id": "VPC_ID",
    "name": "web-tier",
    "cidr": "10.100.1.0/24",
    "gateway_ip": "10.100.1.1"
  }'
CIDR Planning: Plan your CIDR blocks carefully. Subnets within the same VPC should not overlap. Common patterns include /24 subnets (254 usable IPs) for most workloads.

DNS & Service Discovery

Each VPC includes a dedicated DNS service (dnsmasq) running in the core subnet. The platform configures pod DNS settings so service names resolve inside the VPC, while external domains are forwarded to the provider DNS servers.

Resolution Flow

pod -> tenant-dns (core subnet) -> external DNS forwarder

Record Format

Pods and VIP services are registered automatically. Names are stable even when pods restart.

web.my-tenant.svc.k8s-lab
web.my-tenant
web

HA for DNS

DNS runs two replicas in the core subnet. Pods are configured with both DNS IPs when available, providing resilience if one replica is unavailable.

Provider DNS Settings

External DNS servers and the ndots setting come from provider configuration. For self-hosted labs, these map to pod_dns_nameservers and pod_dns_ndots in your configuration.

Pods

Pods are the deployable units that run your containerized applications. Each pod can have multiple replicas for high availability and automatic load balancing.

CloudUser Pods tab
Pods Tab

Creating a Pod

curl -k -X POST https://api.circloud.net/pods \
  -H "X-Auth-Token: YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "tenant_id": "YOUR_TENANT_ID",
    "token": "YOUR_TOKEN",
    "vpc_id": "VPC_ID",
    "subnet_id": "SUBNET_ID",
    "name": "web-server",
    "container_image": "nginx:latest",
    "replica_count": 2,
    "service_port": 80,
    "external_access": true,
    "external_inbound": true,
    "auto_scaling": true,
    "autoscale_max_replicas": 6,
    "autoscale_cpu_target_millicores": 250
  }'

Pod Options

Option Description
replica_count Replica count (1-10). If auto_scaling is true, this is the initial replica count (min 2)
service_port VIP service port for load balancing and tunnels (default 80)
use_registry_credentials Use tenant registry secret for image pulls (default true)
external_access Enable outbound internet via SNAT
external_inbound Enable inbound access with external IP
auto_healing Auto-restart pods on failure
auto_scaling Enable autoscaling with HPA (CPU-based)
autoscale_max_replicas Maximum replicas when autoscaling (default 10)
autoscale_cpu_target_millicores Target average CPU usage per pod in millicores (default 200)

Pod Actions (Actions Column)

Actions appear on the first row of each pod group.

Icon Action
Start a stopped pod workload
Stop the pod workload
Restart the pod workload
+ Add a replica (up to 10)
× Remove a replica (minimum 1)
× Delete the pod and its resources (persistent storage is removed)

The amber × is for replica removal; the red × is for deleting the pod.

When autoscaling is enabled, manual replica changes are ignored and HPA controls scaling.

Service VIPs and Replicas

Circloud creates a VIP service for each pod group. For single pods, the VIP provides a stable IP. For replicas, one VIP load-balances traffic across all replicas.

The Service IP column in the GUI shows this VIP address.

replica pods: api-0, api-1, api-2
VIP service: api -> 10.x.x.x (stable VIP)

Autoscaling (HPA)

Enable auto_scaling to create a Kubernetes HorizontalPodAutoscaler based on average CPU usage. Auto-healing is implied (pods are managed by a Deployment), and manual replica changes are disabled. The replica_count is treated as the initial value and clamped to the autoscale min/max. When autoscaling is enabled, the minimum replica count is always 2.

Console Access

You can access a terminal inside your running pods using the console feature. Click the green terminal icon (>_) next to any running pod to open a web-based terminal (only available when the pod is Ready).

Console modal
Pod Console (web terminal)
# Example commands inside the console
whoami
df -h
ls -la /storage

Pod Status, Auto-Healing, and HA

Pod status is refreshed by a monitoring job that polls Kubernetes and writes status records to the CloudManager database. The dashboard displays per-replica status, IP address, and restart count.

CloudUser Monitoring tab
Monitoring & Pod Status

Status Probes (Pods + Nodes)

Probes are shown as colored emoji indicators in the Pods, System Pods, and Nodes tables. Hover a probe to see the status tooltip.

Probe Meaning
🟢 Ready / Fresh (healthy)
🟡 Pending / Not Ready / Stale
🔴 Failed / Offline
Unknown (no data yet)

Node probes are based on the last metrics update time: ≤30s = Fresh (green), ≤60s = Stale (yellow), >60s = Offline (red).

Status States

Status Meaning
ready Pod is running and Ready condition is true
not_ready Pod is running but not Ready
pending Pod is being scheduled or pulling images
failed Pod has failed or is in an Unknown phase
unknown Status has not been observed yet

Status records include the observed pod IP, Kubernetes phase, and restart count.

Auto-Healing

When auto_healing is enabled, pods are created as Deployments so Kubernetes recreates them on failure. For replicated pods, each replica is managed by its own Deployment. Restart counts in the UI help identify unstable workloads.

When auto_scaling is enabled, a Kubernetes HPA manages the Deployment. The UI shows the live replica count as the HPA scales up and down based on CPU usage.

High Availability

For replica_count greater than 1, a single VIP service load-balances across replicas. DNS points to the VIP, so clients are insulated from individual pod restarts.

client -> VIP service -> replica pods

Web Terminal

The terminal opens an interactive /bin/sh session via a WebSocket connection. Terminal access is only available when the pod is running and Ready.

WebSocket endpoint: /ws/exec/<namespace>/<pod_name>.

If your image does not include /bin/sh, use a base image that provides a shell.

Registry Credentials

Registry credentials let your pods pull private images. Credentials are stored in the tenant database and synchronized to a Kubernetes secret named <tenant>-registry-creds.

CloudUser Registry tab
Registry Credentials

API Example

curl -k -X POST https://api.circloud.net/tenants/TENANT_ID/registry-credentials \
  -H "X-Auth-Token: YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "dockerhub",
    "server": "https://index.docker.io/v1/",
    "username": "myuser",
    "password": "mytoken"
  }'

Reusing a credential name updates the existing entry. Listing credentials hides passwords in responses. Pods use these credentials when use_registry_credentials is true (default).

Cloudflare Tunnels

Tunnels provide secure external access to your pods without opening inbound ports. Traffic is routed through Cloudflare's global network, providing DDoS protection, automatic SSL/TLS, and zero-trust access.

When you create a tunnel, Circloud deploys a cloudflared pod in the core subnet, allocates outbound access, and registers DNS records in Cloudflare. The tunnel origin targets the pod DNS name or VIP service.

Tunnel status is tracked as active, inactive, or failed in the dashboard.

CloudUser Tunnels tab
Tunnels Tab

Supported Protocols

HTTP

Standard web traffic for websites, REST APIs, and web applications. Cloudflare handles SSL/TLS termination automatically.

protocol_type: "http"

HTTPS

End-to-end encrypted traffic for services that handle their own TLS certificates internally.

protocol_type: "https"

SSH

Secure shell access for remote terminal and file transfer. Connect using cloudflared access ssh.

protocol_type: "ssh"

TCP

Generic TCP for databases (PostgreSQL, MySQL, Redis), RDP, and custom protocols.

protocol_type: "tcp"

UDP

UDP tunneling for gaming servers, VoIP, DNS, and real-time streaming applications.

protocol_type: "udp"

Creating Tunnels by Protocol

HTTP Tunnel (Web Applications)

For web applications, REST APIs, webhooks, and microservices:

curl -k -X POST https://api.circloud.net/pods/POD_ID/tunnel \
  -H "X-Auth-Token: YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "tunnel_name": "web-app",
    "subdomain": "app",
    "protocol_type": "http",
    "service_port": 80
  }'

# Access at: https://app.yourdomain.com
# SSL/TLS is automatic - no certificate management needed

HTTPS Tunnel (End-to-End Encryption)

For services that already handle TLS internally or require mTLS:

curl -k -X POST https://api.circloud.net/pods/POD_ID/tunnel \
  -H "X-Auth-Token: YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "tunnel_name": "secure-api",
    "subdomain": "api",
    "protocol_type": "https",
    "service_port": 443
  }'

# Traffic is encrypted end-to-end from client to your service

SSH Tunnel (Remote Terminal Access)

For remote shell access, SFTP file transfers, and development:

curl -k -X POST https://api.circloud.net/pods/POD_ID/tunnel \
  -H "X-Auth-Token: YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "tunnel_name": "ssh-access",
    "subdomain": "ssh",
    "protocol_type": "ssh",
    "service_port": 22
  }'

# Connect using cloudflared CLI:
# cloudflared access ssh --hostname ssh.yourdomain.com

# Or configure in ~/.ssh/config:
# Host ssh.yourdomain.com
#   ProxyCommand cloudflared access ssh --hostname %h

TCP Tunnel (Databases & Custom Protocols)

For PostgreSQL, MySQL, MongoDB, Redis, and any TCP-based service:

curl -k -X POST https://api.circloud.net/pods/POD_ID/tunnel \
  -H "X-Auth-Token: YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "tunnel_name": "postgres-db",
    "subdomain": "db",
    "protocol_type": "tcp",
    "service_port": 5432
  }'

# Step 1: Start local proxy with cloudflared
# cloudflared access tcp --hostname db.yourdomain.com --url localhost:5432

# Step 2: Connect to your database through the local proxy
# psql -h localhost -p 5432 -U myuser mydb
# mysql -h localhost -P 3306 -u myuser -p
# redis-cli -h localhost -p 6379

UDP Tunnel (Gaming, VoIP, Streaming)

For game servers, voice chat, DNS servers, and real-time applications:

curl -k -X POST https://api.circloud.net/pods/POD_ID/tunnel \
  -H "X-Auth-Token: YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "tunnel_name": "game-server",
    "subdomain": "game",
    "protocol_type": "udp",
    "service_port": 27015
  }'

# Connect directly: game.yourdomain.com:27015
# UDP traffic is tunneled through Cloudflare's global network

Using Custom Domains

If custom domains have been assigned, you can use them:

CloudUser Domains tab
Custom Domains (Tenant Domains)
curl -k -X POST https://api.circloud.net/pods/POD_ID/tunnel \
  -H "X-Auth-Token: YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "tunnel_name": "custom-tunnel",
    "subdomain": "portal",
    "protocol_type": "http",
    "service_port": 80,
    "domain": "mycompany.com"
  }'

# Access at: https://portal.mycompany.com
Protocol Use Cases:
  • HTTP: Websites, REST APIs, webhooks, microservices, admin panels
  • HTTPS: Services with internal SSL, legacy apps, mTLS requirements
  • SSH: Remote administration, SFTP file transfers, Git over SSH, dev access
  • TCP: Databases (PostgreSQL, MySQL, MongoDB, Redis), RDP, custom protocols
  • UDP: Game servers (Source, Minecraft), VoIP (SIP), DNS, QUIC, media streaming
Note: You can only create tunnels using domains that have been approved for your tenant. Contact your administrator to add new custom domains.

Tunnels in Topology JSON

You can also define tunnels inline when deploying pods via the Topology API:

{
  "pods": [
    {
      "name": "web-server",
      "vpc_name": "my-vpc",
      "subnet_name": "my-subnet",
      "container_image": "nginx:latest",
      "service_port": 80,
      "tunnels": [
        {
          "subdomain": "www",
          "protocol_type": "http",
          "service_port": 80
        },
        {
          "subdomain": "ssh",
          "protocol_type": "ssh",
          "service_port": 22
        }
      ]
    }
  ]
}

Managing Tunnels

View and delete tunnels from the Tunnels tab on your dashboard, or via API:

# List all tunnels
curl -k -X GET https://api.circloud.net/tenants/TENANT_ID/tunnels \
  -H "X-Auth-Token: YOUR_TOKEN"

# Delete a tunnel
curl -k -X DELETE https://api.circloud.net/tunnels/TUNNEL_ID \
  -H "X-Auth-Token: YOUR_TOKEN"

Topology (Infrastructure-as-Code)

The Topology feature allows you to define your entire infrastructure in JSON and deploy it with a single API call. This is ideal for version control, reproducible deployments, and automation.

CloudUser Topology tab
Topology Tab

Exporting Your Topology

From the Topology tab, you can view your current infrastructure as JSON and download it for backup or version control.

Deploying a Topology

curl -k -X POST https://api.circloud.net/tenants/TENANT_ID/topology \
  -H "Content-Type: application/json" \
  -d '{
    "token": "YOUR_TOKEN",
    "vpcs": [
      {
        "name": "production",
        "enable_internet": true
      }
    ],
    "subnets": [
      {
        "name": "web",
        "vpc_name": "production",
        "cidr": "10.100.1.0/24",
        "gateway_ip": "10.100.1.1"
      },
      {
        "name": "api",
        "vpc_name": "production",
        "cidr": "10.100.2.0/24",
        "gateway_ip": "10.100.2.1"
      }
    ],
    "pods": [
      {
        "name": "nginx",
        "vpc_name": "production",
        "subnet_name": "web",
        "container_image": "nginx:latest",
        "replica_count": 2,
        "service_port": 80,
        "external_inbound": true,
        "auto_scaling": true,
        "autoscale_max_replicas": 6,
        "autoscale_cpu_target_millicores": 250
      }
    ]
  }'
Tip: Use the visual topology diagram in the Topology tab to understand your infrastructure at a glance. The diagram updates in real-time as you make changes.

CloudManager (Admin Portal)

The CloudManager GUI is the admin control plane for the entire cluster. It provides global configuration, tenant lifecycle management, monitoring, and system visibility across all namespaces.

Access the Admin GUI locally at https://localhost:8443, or publicly at https://admin.<cloudflare_domain> based on lab-config.yaml.

Auth Tab

Displays the admin API token used for privileged endpoints. Use this token as the X-Admin-Token header when creating tenants or managing global settings.

CloudManager Auth tab
Admin Auth

Cloudflare Tab

Configure Cloudflare integration: API token, account ID, base domain, and Access policy settings. These values are used when creating tunnels and DNS records. Click Save Cloudflare Config to persist the changes.

CloudManager Cloudflare tab
Cloudflare Configuration

Provider Tab

Shows provider networking settings, including external subnet CIDR, gateway, management network, and excluded IP ranges. These values define how external access is allocated for pods.

CloudManager Provider tab
Provider Networking

T.Defaults Tab (Tenant Defaults)

Sets default resource limits for new tenants (pods, storage, VPCs, subnets, CPU, RAM). These defaults are applied when a tenant is created without explicit resource caps. Click Save Defaults to update.

CloudManager Defaults tab
Tenant Defaults

Monitoring Tab

Cluster overview for tenants, VPCs, pods, and node utilization. Includes aggregate CPU/RAM/storage metrics and highlights of high-usage pods to help identify hotspots.

CloudManager Monitoring tab
Monitoring

System Pods Tab

Shows two groups: K8s infrastructure pods (kube-ovn, coredns, etc.) and Circloud services (API, GUI, monitor). Each row includes status, node, resource usage, VIPs, tunnels, and actions. You can restart or delete workloads when actions are enabled.

CloudManager Infra pods tab
K8s Infra Pods
CloudManager Circloud pods tab
Circloud Pods

Nodes Tab

Health and utilization for every node, including CPU, RAM, storage, GPU metrics, and network traffic. Use this to confirm node capacity and detect failures.

CloudManager Nodes tab
Nodes

Service Tunnels Tab

Admin-managed tunnels for platform services. Shows protocol, hostname, origin URL, Access policy, and status. Use the delete action to remove a tunnel.

CloudManager Tunnels tab
Service Tunnels

Tenants Tab

Create, search, and delete tenants. The Allow tenant self-signup toggle controls whether the CloudUser login page shows the Create Account option.

  • Create Tenant: Provide name + password, optionally set resource caps.
  • Delete Tenant: Click the × on a tenant card to remove the tenant and all resources.
  • Resources: Set per-tenant limits (pods, storage, VPCs, subnets, CPU, RAM).
  • Domains: Add custom domains to a tenant for tunnel creation.
  • Registry: Manage tenant registry credentials.
  • Topology: View or apply tenant topology JSON.
  • VPCs / Pods: Admin view of tenant networks and workloads, including pod actions.
CloudManager Tenants tab
Tenants

Support

Support the Circloud project with a donation.