The HTTP gateway (nexus-api) is a Gin server that proxies all operations to the nexusd daemon via gRPC. It also forwards auth validation to the nexus-auth service.
Default listen address is configured in the gateway binary.
All /api/* routes require a valid JWT in the Authorization header:
Authorization: Bearer <token>
The middleware validates the token by calling AuthService.ValidateToken over gRPC on every request. On success the username claim is injected into the Gin context for downstream handlers.
Step 1 — initiate registration
POST /auth/register/init
Content-Type: application/json
{
"Username": "alice",
"Password": "hunter2",
"Email": "alice@example.com"
}
Response 200 OK:
{ "message": "OTP sent to email" }The server stores a PendingRegistration row (hashed password, 5-minute OTP) and sends the OTP by email.
Step 2 — verify OTP
POST /auth/register/verify
Content-Type: application/json
{
"Email": "alice@example.com",
"Code": "123456"
}
Response 200 OK:
{ "token": "<jwt>", "username": "alice" }JWT is valid for 24 hours.
Step 1 — initiate login
POST /auth/login/init
Content-Type: application/json
{
"Username": "alice",
"Password": "hunter2"
}
Response 200 OK:
{ "message": "OTP sent to alice@example.com" }Step 2 — verify OTP
POST /auth/login/verify
Content-Type: application/json
{
"Email": "alice@example.com",
"Code": "654321"
}
Response 200 OK:
{ "token": "<jwt>", "username": "alice" }POST /api/nodes
Authorization: Bearer <jwt>
Content-Type: application/json
{
"name": "worker1",
"memory_mb": 256,
"cpu_shares": 512,
"storage_size": "1G"
}
Response 201 Created:
{ "id": "worker1", "ip": "10.0.42.2", "status": "Running" }POST /api/files/upload
Authorization: Bearer <jwt>
Content-Type: multipart/form-data
file=@/path/to/file.tar.gz
The gateway saves the file to /tmp/nexus_uploads/<filename>, then sends the path to the daemon via UploadFile RPC.
Response 200 OK:
{
"id": "<uuid>",
"name": "file.tar.gz",
"size": 104857600,
"chunks_count": 10,
"status": "Uploaded"
}GET /api/files
Authorization: Bearer <jwt>
Response 200 OK: array of file objects.
GET /api/files/:id/download
Authorization: Bearer <jwt>
The daemon reconstructs the file to /tmp/nexus_downloads/<id> and the gateway serves it directly via c.File().
GET /api/nodes/:id/metrics
Authorization: Bearer <jwt>
Response 200 OK:
{
"node_id": "worker1",
"memory_usage": 52428800,
"memory_limit": 268435456,
"cpu_percent": 0.42
}Metrics are collected from cgroups every 5 seconds and kept in memory.
POST /api/lambda/run
Authorization: Bearer <jwt>
Content-Type: application/json
{
"Code": "print('hello from nexus')",
"Runtime": "python3"
}
Response 200 OK:
{
"stdout": "hello from nexus\n",
"stderr": "",
"exit_code": 0,
"execution_time_ms": 312
}Code runs in an ephemeral container (Alpine + python3, 128 MB RAM, isolated network namespace). The container is destroyed after execution.
All VFS routes extract username from the validated JWT.
POST /api/fs/mkdir
Authorization: Bearer <jwt>
Content-Type: application/json
{ "path": "/documents/projects" }
Response 200 OK:
{ "message": "Directory created", "path": "/documents/projects" }GET /api/fs/ls?path=/documents
Authorization: Bearer <jwt>
Response 200 OK: array of { name, type, size } objects where type is "file" or "folder".
POST /api/fs/upload
Authorization: Bearer <jwt>
Content-Type: multipart/form-data
path=/documents/report.pdf
file=@/local/report.pdf
Performs quota check. Rolls back physical chunks if quota exceeded.
DELETE /api/fs/delete?path=/documents/old.txt
Authorization: Bearer <jwt>
Recursive for directories. Deletes physical chunks.
POST /api/fs/move
Authorization: Bearer <jwt>
Content-Type: application/json
{ "old_path": "/docs/draft.txt", "new_path": "/archive/final.txt" }
All errors return JSON:
{ "error": "human readable message" }