--- title: Networking --- # Networking This page describes how traffic reaches Themelio's services and how deployed workloads (model inference endpoints, spaces) get routable URLs. ## Ingress Architecture Themelio uses Istio as its service mesh and ingress layer. Traffic enters through two separate Istio IngressGateways, each handling a distinct class of requests: ```mermaid graph LR Browser([Browser]) --> WebGW[Web Gateway] GitClient([Git Client]) --> WebGW APIClient([API Client]) --> SvcGW[Service Gateway] subgraph Istio["Istio Ingress Layer"] WebGW --> WebVS[Web VirtualService] SvcGW --> SvcVS[Workload VirtualServices] end WebVS --> Web[Themelio Web :3000] WebVS --> GitLab[GitLab :8929] SvcVS --> Space1[Space Pod] SvcVS --> Inf1[Inference Pod] SvcVS --> Action1[Action Pod] ``` ### Web Gateway Handles all platform traffic — the web UI, API routes, and git operations: - **Web requests** route to the Themelio Web service (Next.js on port 3000) - **Git smart HTTP** requests (`*.git/git-receive-pack`, `*.git/git-upload-pack`, `*.git/info/refs`) route to GitLab The split happens at the VirtualService level based on URI pattern matching. ### Service Gateway A dedicated gateway for user-deployed workloads — spaces, inference endpoints, and custom action deployments. This gateway runs as a separate Istio IngressGateway (`istio-ingressgateway-service`) in the `istio-system` namespace. Keeping workload traffic on its own gateway means platform traffic and user workload traffic scale independently. ## How Deployed Workloads Get URLs When `k8s-root-actor` deploys a space, inference endpoint, or custom action, it creates three Kubernetes resources: 1. **A Pod or Deployment** running the workload 2. **A ClusterIP Service** exposing the pod internally 3. **A VirtualService + Gateway** routing external traffic to the service ### URL Generation Each deployment gets a deterministic URL based on its identity: - **Spaces**: `https:///-/iframe////` - **Inference endpoints**: `https:////` - **Custom actions**: `https:////` The stable action name is derived from the action's identity (repo, namespace, action name) with a short hash suffix to avoid collisions while keeping names readable and deterministic across redeployments. ### Internal Routing Inside the cluster, services reach each other via standard Kubernetes DNS: ``` http://..svc.cluster.local/ ``` This is used when a space needs to call a linked inference endpoint — the space receives the internal URL as an environment variable, avoiding external roundtrips. ## Git Traffic Git operations (clone, push, pull) are proxied through an OpenResty/Nginx layer that handles authentication: 1. The user authenticates with a Personal Access Token via HTTP Basic Auth (`username:token`) 2. OpenResty extracts the Authorization header, logs the username for audit, and forwards the request to GitLab 3. GitLab validates the token and serves the git operation Git [LFS](../../terms/lfs) objects are stored in MinIO (S3-compatible object storage) in production. The LFS client resolves pointer files to download URLs via GitLab's LFS API. ## Mutual TLS Istio enforces mutual TLS between all services in the mesh. Traffic between Themelio Web, the root actors, and GitLab is encrypted and authenticated at the transport layer without application-level changes. ## Environment Domains Each environment uses its own domain: | Environment | Domain Pattern | |-------------|---------------| | Local (minikube) | `*.localtest.me` (resolves to 127.0.0.1) | | Local (Docker Compose) | `localhost` via OpenResty reverse proxy | | Dev | `dev.themelio.pharos.grnet.gr` | | Staging | `staging.themelio.pharos.grnet.gr` | | Production | `themelio.pharos.grnet.gr` | The minikube setup uses `localtest.me` domains, which resolve to `127.0.0.1` without requiring `/etc/hosts` changes. Docker Compose uses OpenResty as a reverse proxy on ports 80/443.