Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 81 additions & 0 deletions docs/cli-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -706,6 +706,87 @@ fabricks mortar exec -e DEBUG=1 api ./debug-script.sh

These commands inspect services managed by the daemon. Services are created declaratively via `fabricks mortar up`, but these commands let you inspect their state.

### `fabricks service run`

Run a WASM module via the daemon (resolves and stores in OCI registry if needed).

**Usage:**
```bash
fabricks service run [OPTIONS] <PATH|TAG>
```

**Arguments:**
- `<PATH|TAG>` - Path to Fabrickfile directory or OCI image tag

**Options:**
```
-p, --port <HOST:CONTAINER> Publish ports (can be used multiple times)
-e, --env <KEY=VAL> Set environment variables (can be used multiple times)
--env-file <FILE> Read environment from file
-v, --volume <SRC:DEST> Mount volumes (can be used multiple times)
--name <NAME> Assign a name to the instance
--network <NETWORK> Connect to network
--rm Automatically remove when stopped
-d, --detach Run in background
--restart <POLICY> Restart policy [default: no] [possible: no, on-failure, always]
```

**How it Works:**

1. **Resolution Phase:**
- If `<PATH|TAG>` is a directory path, checks for Fabrickfile
- If Fabrickfile exists and module not built, builds it
- If `<PATH|TAG>` is an OCI tag, pulls from registry if not cached
- Stores/verifies module in local OCI storage

2. **Execution Phase:**
- Daemon loads module from OCI storage
- For interpreted runtimes (JS/Python), extracts source layer to temp directory
- Mounts source files at `/app` via WASI preopens
- Executes WASM module with specified capabilities and configuration

**Examples:**
```bash
# Run from Fabrickfile directory (builds if needed)
fabricks service run ./examples/nodejs-hello

# Run by OCI tag
fabricks service run nodejs-hello:1.0.0

# Run with port mapping
fabricks service run -p 8080:8089 ./examples/nodejs-hello

# Run with environment variables
fabricks service run -e LOG_LEVEL=debug nodejs-hello:1.0.0

# Run in background with auto-restart
fabricks service run -d --restart on-failure nodejs-hello:1.0.0
```

**Output:**
```
Resolving nodejs-hello...
✓ Found Fabrickfile at ./examples/nodejs-hello
✓ Building module (not found in OCI storage)
[1/3] Resolving runtime: javascript:20
[2/3] Packaging source files
[3/3] Storing in OCI registry as nodejs-hello:1.0.0
✓ Stored: sha256:abc123...

Starting service via daemon...
✓ Service ID: srv_xyz789
✓ Network: listen on 0.0.0.0:8089
✓ Health check passed
Service running: nodejs-hello (nodejs-hello:1.0.0)
```

**Notes:**
- This command always runs through the daemon (unlike `fabricks run` which can run standalone)
- Supports interpreted runtimes (JavaScript, Python) via multi-layer OCI images
- For build failures, see `fabricks build --help` for troubleshooting

---

### `fabricks service ls`

List all running services (across all mortar compositions).
Expand Down
49 changes: 49 additions & 0 deletions docs/daemon-api-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -573,6 +573,55 @@ curl --unix-socket /var/run/fabricks.sock \

---

### Run Module

**Endpoint:** `POST /v1/services/run-module`

Runs a module from OCI storage by tag or reference. This is the primary endpoint for running services - it loads the module from local OCI storage, handles multi-layer modules (runtime + source layers for interpreted runtimes), creates a service, and starts it.

**Request Body:**
```json
{
"reference": "hello-http:0.1.0",
"args": [],
"env_vars": [],
"no_capabilities": false
}
```

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `reference` | string | Yes | Module tag (e.g., "my-module:1.0.0") |
| `args` | array | No | Command-line arguments to pass to the module |
| `env_vars` | array | No | Environment variable overrides as `[key, value]` tuples |
| `no_capabilities` | boolean | No | Disable capability enforcement (default: false) |

**Response:**
```json
{
"status": "success",
"data": {
"id": "svc-a1b2c3d4",
"name": "hello-http"
}
}
```

**cURL Example:**
```bash
curl --unix-socket /var/run/fabricks.sock \
-X POST \
-H "Content-Type: application/json" \
-d '{"reference":"hello-http:0.1.0"}' \
http://localhost/v1/services/run-module
```

**Notes:**
- For interpreted runtimes (Python, JavaScript), the module's runtime layer is used as the WASM binary and source layers are extracted to `/app`
- The module must exist in local OCI storage (use CLI to build and store first)

---

### List Services

**Endpoint:** `GET /v1/services`
Expand Down
107 changes: 96 additions & 11 deletions docs/fabrickfile-mortar-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -492,21 +492,90 @@ Specifies source code location and files to include.

### `[runtime]` (Optional)

Required for interpreted languages (JavaScript, Python).
Required for interpreted languages (JavaScript, Python) that don't compile directly to WASM. The runtime section specifies a base WASM runtime that will load and execute your source code at runtime.

**When to Use:**
- JavaScript/TypeScript applications (uses SpiderMonkey via jco componentize)
- Python applications (uses CPython via componentize-py)
- Any other interpreted language with a WASM runtime

**How It Works:**

For interpreted languages, Fabricks uses a **multi-layer OCI approach**:
- **Layer 0:** Runtime WASM module (e.g., `nodejs-runtime.wasm`, `python-runtime.wasm`)
- **Layer 1+:** User source code files (packaged as tar.gz)

At runtime:
1. Daemon loads the runtime WASM from Layer 0
2. Extracts source files from Layer 1+ to temporary directory
3. Mounts source at `/app` via WASI filesystem preopens
4. Runtime reads entrypoint from `/app/.fabricks.toml`
5. Runtime loads and executes your code

#### `image` (Required if using runtime)
- **Type:** String
- **Examples:** `image = "wasm://node:20"`, `image = "wasm://python:3.11"`
- **Format:** OCI image reference to the runtime
- **Examples:**
- `image = "nodejs-runtime:1.0.0"` - Local tag
- `image = "fabricks.dev/runtimes/javascript:20"` - Registry reference
- `image = "fabricks.dev/runtimes/python:3.12"` - Python runtime

#### `handler` (Required if using runtime)
- **Type:** String
- **Format:** `"file:function"` - Specifies the entrypoint for your application
- **Examples:**
- `handler = "app.js:handler"` - JavaScript function handler
- `handler = "app:handler"` - Python function handler (imports `handler` from `app.py`)
- `handler = "server:main"` - Alternative entrypoint

#### `config` (Optional)
- **Type:** Table
- **Purpose:** Runtime-specific configuration options
- **Example:**
```toml
[runtime.config]
heap_size = "512Mi"
stack_size = "2Mi"
```

**Complete Examples:**

JavaScript/Node.js Runtime:
```toml
[info]
name = "my-api"
version = "1.0.0"
type = "http"

[runtime]
image = "nodejs-runtime:1.0.0"
handler = "app.js:handler"

[source]
path = "."

[capabilities.network]
listen = [8080]
```

Python Runtime:
```toml
[info]
name = "my-python-service"
version = "1.0.0"
type = "http"

[runtime]
image = "python-runtime:3.12"
handler = "app:handler"

[source]
path = "."

[capabilities.network]
listen = [8080]
```

---

### `[build]` (Required for source builds)
Expand Down Expand Up @@ -845,7 +914,7 @@ listen = [6379]
read_write = ["./data"]
```

### Minimal Fabrickfile (JavaScript HTTP Service)
### Minimal Fabrickfile (JavaScript HTTP Service with Runtime)
```toml
fabrick_version = "1.0"

Expand All @@ -854,24 +923,40 @@ name = "api-gateway"
version = "1.0.0"
type = "http" # HTTP handler service

[from]
source = "javascript"

# Use the JavaScript runtime - no compilation needed!
[runtime]
image = "wasm://node:20"
image = "nodejs-runtime:1.0.0"
handler = "app.js:handler"

[source]
path = "."

[build]
command = "npm run build:wasm"
output = "dist/api.wasm"

[capabilities.network]
listen = [3000]
connect = ["backend:8080"]
```

### Minimal Fabrickfile (Python HTTP Service with Runtime)
```toml
fabrick_version = "1.0"

[info]
name = "python-api"
version = "1.0.0"
type = "http" # HTTP handler service

# Use the Python runtime - no compilation needed!
[runtime]
image = "python-runtime:3.12"
handler = "app:handler"

[source]
path = "."

[capabilities.network]
listen = [8080]
```

### Minimal Fabrickfile (Command/CLI Tool)
```toml
fabrick_version = "1.0"
Expand Down
Loading
Loading