Architecture & Routing
Glue2 is the central reverse proxy that sits in front of every HolaCloud service. All incoming traffic — whether from browser users, API clients, or internal services — passes through Glue2 before reaching its destination.

Reverse Proxy
Glue2 operates as a Layer-7 reverse proxy. It terminates TLS, inspects each request, authenticates the caller, and then forwards the request to the appropriate backend service. No external traffic reaches HolaCloud services directly; Glue2 is the single entry point.
1Client ──▶ Glue2 (auth check) ──▶ Backend Service
2 │
3 ├──▶ InceptionDB
4 ├──▶ Lambda
5 ├──▶ Files
6 ├──▶ Config
7 ├──▶ KVNode
8 ├──▶ Scheduler
9 └──▶ Logs
Virtual Host Routing
Glue2 routes requests based on the Host header. Each HolaCloud project is assigned a unique subdomain (<project>.hola.cloud), and Glue2 maps that subdomain to the project's backend service.
Built-in platform services use reserved subdomains:
| Host | Service |
|---|---|
inceptiondb.hola.cloud |
InceptionDB |
api.hola.cloud |
Public API (Lambda, Files, Config, etc.) |
console.hola.cloud |
HolaCloud Console |
auth.hola.cloud |
Authentication / Session service |
logs.hola.cloud |
InstantLogs |
When a request arrives for my-project.hola.cloud, Glue2 looks up the project with that slug, resolves its primary backend service, and forwards the request.
The Proxy Flow
- Client sends an HTTP request to
<project>.hola.cloud. - Glue2 terminates the TLS connection and reads the
Hostheader. - Glue2 checks authentication (session cookie, API key, or OAuth token). If the endpoint requires auth and none is provided, the request is rejected with
401 Unauthorized. - Glue2 resolves the virtual host to a project ID and backend service target.
- Glue2 injects authentication and project headers into the request.
- The request is forwarded to the backend service.
- The backend response is streamed back to the client, and Glue2 logs the transaction.
Injected Headers
When forwarding to a backend, Glue2 injects:
| Header | Description |
|---|---|
X-Glue-Authentication |
Plain JSON authentication context |
X-Holacloud-Project-Id |
The UUID of the project derived from the virtual host |
X-Holacloud-Tenant-Project-Id |
Tenant-scoped project ID for multi-tenant isolation |
X-Forwarded-For |
Original client IP address |
X-Forwarded-Proto |
Original protocol (http or https) |
Backend services use these headers to identify the caller and enforce authorization. X-Glue-Authentication is plain JSON.
V0 Admin Endpoints
Glue2 exposes a set of admin endpoints under /v0/:
List Virtual Hosts
curl "https://api.hola.cloud/v0/virtualhosts" \GET /v0/virtualhosts HTTP/1.1
Host: api.hola.cloud
package main
import (
"fmt"
"io"
"net/http"
)
func main() {
req, err := http.NewRequest("GET", "https://api.hola.cloud/v0/virtualhosts", nil)
if err != nil {
panic(err)
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
responseBody, err := io.ReadAll(resp.Body)
if err != nil {
panic(err)
}
fmt.Println(string(responseBody))
}
<?php
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => 'https://api.hola.cloud/v0/virtualhosts',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'GET',
]);
$response = curl_exec($ch);
if ($response === false) {
throw new Exception(curl_error($ch));
}
curl_close($ch);
echo $response;
import requests
response = requests.request(
"GET",
"https://api.hola.cloud/v0/virtualhosts"
)
print(response.text)
const response = await fetch("https://api.hola.cloud/v0/virtualhosts", {
method: "GET"
});
console.log(await response.text());
const response = await fetch("https://api.hola.cloud/v0/virtualhosts", {
method: "GET"
});
const text = await response.text();
console.log(text);
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class Main {
public static void main(String[] args) throws Exception {
var request = HttpRequest.newBuilder()
.uri(URI.create("https://api.hola.cloud/v0/virtualhosts"))
.method("GET", HttpRequest.BodyPublishers.noBody())
.build();
var response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}1["my-project.hola.cloud", "api.my-project.hola.cloud"]
Traffic Stats
curl "https://api.hola.cloud/v0/stats" \GET /v0/stats HTTP/1.1
Host: api.hola.cloud
package main
import (
"fmt"
"io"
"net/http"
)
func main() {
req, err := http.NewRequest("GET", "https://api.hola.cloud/v0/stats", nil)
if err != nil {
panic(err)
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
responseBody, err := io.ReadAll(resp.Body)
if err != nil {
panic(err)
}
fmt.Println(string(responseBody))
}
<?php
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => 'https://api.hola.cloud/v0/stats',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'GET',
]);
$response = curl_exec($ch);
if ($response === false) {
throw new Exception(curl_error($ch));
}
curl_close($ch);
echo $response;
import requests
response = requests.request(
"GET",
"https://api.hola.cloud/v0/stats"
)
print(response.text)
const response = await fetch("https://api.hola.cloud/v0/stats", {
method: "GET"
});
console.log(await response.text());
const response = await fetch("https://api.hola.cloud/v0/stats", {
method: "GET"
});
const text = await response.text();
console.log(text);
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class Main {
public static void main(String[] args) throws Exception {
var request = HttpRequest.newBuilder()
.uri(URI.create("https://api.hola.cloud/v0/stats"))
.method("GET", HttpRequest.BodyPublishers.noBody())
.build();
var response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}Backend Health Status
curl "https://api.hola.cloud/v0/status" \GET /v0/status HTTP/1.1
Host: api.hola.cloud
package main
import (
"fmt"
"io"
"net/http"
)
func main() {
req, err := http.NewRequest("GET", "https://api.hola.cloud/v0/status", nil)
if err != nil {
panic(err)
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
responseBody, err := io.ReadAll(resp.Body)
if err != nil {
panic(err)
}
fmt.Println(string(responseBody))
}
<?php
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => 'https://api.hola.cloud/v0/status',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'GET',
]);
$response = curl_exec($ch);
if ($response === false) {
throw new Exception(curl_error($ch));
}
curl_close($ch);
echo $response;
import requests
response = requests.request(
"GET",
"https://api.hola.cloud/v0/status"
)
print(response.text)
const response = await fetch("https://api.hola.cloud/v0/status", {
method: "GET"
});
console.log(await response.text());
const response = await fetch("https://api.hola.cloud/v0/status", {
method: "GET"
});
const text = await response.text();
console.log(text);
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class Main {
public static void main(String[] args) throws Exception {
var request = HttpRequest.newBuilder()
.uri(URI.create("https://api.hola.cloud/v0/status"))
.method("GET", HttpRequest.BodyPublishers.noBody())
.build();
var response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}1[
2 {
3 "id": "project-123",
4 "name": "My Project",
5 "host": "my-project.hola.cloud",
6 "status": 200,
7 "statusText": "200 OK"
8 }
9]
Next Steps
- Learn about authentication mechanisms in Authentication.
- Learn how to manage API keys in Managing API Keys.
Comments