- On first run,
selfsetup.Setup()checks for~/.passfile- If missing, generates a UUID passkey, writes it to
~/.passfile, and prints it to stdout - If present, reads it into memory
- If missing, generates a UUID passkey, writes it to
- The passkey is used as the
Authorizationheader for all API requests - Two Badger KV stores are opened:
runtimes-dbandcode-db - Required directories (
./runtimes,./buildcache) are expected to exist
- Every request passes through the
HandleAuthmiddleware - The middleware reads
~/.passfileand compares it to theAuthorizationheader - If they don't match, the request is rejected with
401 Unauthorized
- Client sends
POST /runtime/upload/:namewith a Dockerfile as multipart form data - Server generates a UUID filename (e.g.
abc123.dockerfile) - Stores the mapping
name -> filenameinruntimes-db - Saves the Dockerfile to
./runtimes/<filename>
- Client sends
GET /runtime/list - Server returns all keys from
runtimes-dbas a JSON array of strings
- Client sends
GET /runtime/show/:name - Server looks up the filename in
runtimes-db, reads the Dockerfile contents - Returns
{ "name": "...", "content": "..." }
- Client sends
DELETE /runtime/delete/:name - The
defaultruntime cannot be deleted (returns403) - Server removes the Dockerfile from
./runtimes/and deletes the key fromruntimes-db
- Client sends
POST /function/uploadwith multipart form data:name- function name (becomes the routing endpoint)tag- Docker image tagruntime- name of a registered runtimeport- port the function listens on (80, 8080, 9001 are reserved)volume- optional volume mounts (./data:/data,./other:/other)file- zip archive of the function code
- Server validates all required fields are present
- Server checks the runtime exists in
runtimes-db - Upsert: if a function with the same name already exists, the server tears it down first:
- Kills the running container
- Removes the container
- Removes the Docker image
- Deletes the DB entry
- Responds immediately with
"Code uploaded, build process started" - In a background goroutine:
- Extracts the zip to a build cache directory
- Copies the runtime Dockerfile into the extracted code directory
- Builds the Docker image with
docker build -t <tag> . - Runs the image in detached mode on the specified port
- Stores the function config (with container ID) in
code-db
- Client sends
GET /function/get/:name - Server scans
code-dbfor a function matching the name - Returns the full
LambdaFunJSON object, or404
- Client sends
GET /function/list - Server returns all entries from
code-dbas{ "keys": [...], "functions": [...] }
- Client sends
GET /function/listrunning - Server queries Docker for all running containers and returns the raw Docker API response
- Client sends
GET /function/listinstalled - Server queries Docker for all local images and returns their repo tags as a flat string array
- Client sends
DELETE /function/delete/:name - Server looks up the function by name in
code-db - Kills the container, removes the container, removes the Docker image
- Deletes the entry from
code-db
- Client sends
GET /function/start/:key - Server checks if the function is already running (by image tag)
- If not running, calls
RunDetachedto start it
Every deployed function automatically gets a subdomain. No per-function routing config needed.
- A wildcard DNS record (
*.yourdomain.com) points all subdomains at the server - A request arrives at
my-api.yourdomain.com/hello - The Gin middleware (
proxy.go) splits theHostheader by.and takes the first segment (my-api) - It scans
code-dbfor a function whoseNamematches - If found, it proxies the request to
http://localhost:<port>/hellousinghttputil.ReverseProxy - If no function matches, the request falls through to the next Gin handler
- Routing is subdomain-only. Path-based routing (e.g.
yourdomain.com/my-api) is not supported. - Only the first subdomain segment is matched.
v2.my-api.yourdomain.commatchesv2, notmy-api. - With
ENV=prodandALLOWLISTset, all subdomains get HTTPS automatically via Let's Encrypt.
- Runs on a timer (default 120s, configurable via
CLEANUP_INTERVAL) - Scans the
./runtimes/directory - Removes any Dockerfile that isn't referenced by a key in
runtimes-db
- Runs on a timer (default 120s, configurable via
RESTART_INTERVAL) - Iterates all functions in
code-db - If a function's container is not running, restarts it with
RunDetached
- In production (
ENV=prod), uses Let's Encrypt viagin-gonic/autotls - Domain whitelist is configured via the
ALLOWLISTenv var (comma-separated) - In development, runs plain HTTP on
:8080