Recipe Schema
OpenFactory recipes use snake_case JSON. The canonical format has a small
top-level envelope, an os object for operating-system configuration, and a
scenarios array for post-build verification.
Validation proves that recognized fields have acceptable shapes. It does not prove that every package exists, every requested behavior was represented, or the image and tests will succeed. Unknown fields may be ignored for backward compatibility, so always inspect the normalized recipe returned by the product.
Canonical Envelope
{
"name": "debian-web-check",
"display_name": "Debian Web Check",
"description": "Small Debian image with explicit smoke tests.",
"base_image": "debian-trixie",
"use_case": "Server evaluation",
"hardware": {},
"os": {},
"scenarios": [],
"publish_to": ["local"]
}Do not use camelCase fields such as baseImage or startupScripts. The
compatibility validator accepts some older flat recipes, but normalized output
nests OS fields under os. New integrations should send the canonical format.
Top-Level Fields
| Field | Type | Required/default | Meaning |
|---|---|---|---|
name | string | Required; 3–100 characters | Stable internal recipe name |
display_name | string or null | Optional; 1–100 characters | Human-facing name |
description | string | "" | Intended outcome and boundary |
base_image | string | debian-trixie | Distribution/build target; use the current console list |
task | string or null | Optional | Operational goal |
executor | string or null | Optional | Technology expected to perform the task |
use_case | string | General | Primary use case |
hardware | object | Defaults shown below | Deployment requirements |
os | object | Empty/default object | OS packages, users, services, security, desktop, installer, and scripts |
scenarios | array | [] | Test topologies and objectives |
publish_to | string array | ["local"] | Requested output destinations |
delivery | object | {} | Additional declared delivery configuration |
community | boolean | false | Request community-marketplace visibility; publication policy still applies |
Advanced target-specific fields exist for source-ISO remastering, Proxmox guest payloads, policy provenance, and delivery integrations. Use the editor or API contract for the deployed release instead of copying an old example.
Hardware
{
"hardware": {
"platform": "pc",
"architecture": "x86_64",
"gpu": null,
"min_cpu_cores": 2,
"min_memory_gb": 4,
"min_storage_gb": 16,
"nic_count": 1
}
}platform is pc, phone, or raspberry_pi; supported device values are
target-specific. architecture is x86_64 or aarch64. GPU values name a
supported vendor or vendor combination. These are declared requirements, not
proof that a resulting image was tested on matching physical hardware.
OS Object
Common os fields are:
| Field | Type | Purpose |
|---|---|---|
features | string array | Registered feature modules |
packages | string array | Native packages to request |
excluded_packages | string array | Packages that must remain absent after feature expansion |
custom_packages | array | Source repositories to package through the supported build path |
package_overrides | array | Explicit add, remove, or replace operations |
extra_repos | string array | Additional repositories; trust and key handling still require review |
services | array | Named service enablement and configuration |
users | array | Image-local accounts and groups |
security | object | Declared hardening, encryption, audit, SELinux, and fail2ban choices |
networking | object | Interface and network intent |
desktop_settings | object | Desktop appearance and behavior |
branding | object | Distribution identity and assets |
runtime | object | Init/service/package-manager identity |
boot | object | Kernel arguments and GRUB choices |
installer | object | Install-to-disk configuration |
persistence | object | Live persistence and zone policy |
integrity | object | Requested dm-verity, Secure Boot, and IMA/EVM settings |
file_attachments | array | Previously uploaded files identified by file_id |
startup_scripts | array | Bounded systemd one-shot scripts |
time_zone | string or null | Image time-zone setting |
The presence of an integrity or security field is configuration intent. It is not evidence that the mechanism was produced, enforced at runtime, or qualified for a compliance regime. Require matching build and test evidence.
Users
{
"os": {
"users": [
{
"username": "deploy",
"full_name": "Deployment Operator",
"groups": ["sudo"],
"shell": "/bin/bash"
}
]
}
}User and group names are limited to safe Linux account characters and length.
Leaving password unset creates a password-locked account for key-only or
deployment-time credential workflows. Avoid plaintext credentials in saved
recipes.
Services
{
"os": {
"services": [
{
"name": "ssh",
"enabled": true,
"config": {
"port": 22,
"disable_password_auth": true
}
}
]
}
}config is service-specific. A syntactically valid key can still be ignored by
a generator that does not implement it. Verify the normalized recipe, generated
configuration, and guest behavior.
Security and Installer
{
"os": {
"security": {
"hardening_level": "standard",
"disk_encryption": false,
"audit_logging": true,
"selinux": false,
"fail2ban": true
},
"installer": {
"enabled": false,
"type": "calamares",
"desktop_launcher": true,
"bootloader": "grub",
"delivery": [],
"user_setup": "build_time"
}
}
}Installer types are target-dependent (calamares, anaconda, or
elster-mobile). Enabling an installer must be followed by a disposable-disk
install test; an icon in a live desktop is not proof that installation works.
Startup Scripts
{
"os": {
"startup_scripts": [
{
"name": "write-build-marker",
"description": "Create a local marker after networking is available.",
"command": "install -m 0644 /dev/null /var/lib/example-ready",
"packages": [],
"run_as": "root",
"after": "network.target"
}
]
}
}At most 32 startup scripts are accepted. Commands must be nonempty and cannot
contain NUL bytes. Treat them as root-capable shell code unless run_as says
otherwise; review idempotency, quoting, network failure, and secret exposure.
Scenarios and Assertions
{
"scenarios": [
{
"id": "primary-smoke",
"name": "Primary image smoke test",
"enabled": true,
"tests": ["boot", "login", "packages"],
"custom_tests": [
{
"description": "Confirm SSH is enabled on the configured port.",
"assertions": [
{
"type": "service_enabled",
"description": "The SSH service starts at boot.",
"params": {"service": "ssh"}
},
{
"type": "port_listening",
"description": "The guest listens on TCP port 22.",
"params": {"port": 22}
}
]
}
]
}
]
}A scenario can also define a topology with VMs and networks, benchmark-format
tests, and CIS settings. An omitted topology defaults to the normal single-VM
path. Assertions need a human-readable description and type-specific params.
Unknown assertion types may survive schema parsing, so confirm the runner
supports them before treating them as evidence.
Complete Minimal Example
{
"name": "debian-web-check",
"display_name": "Debian Web Check",
"description": "Debian image with SSH, curl, and explicit smoke tests.",
"base_image": "debian-trixie",
"use_case": "Server evaluation",
"hardware": {
"platform": "pc",
"architecture": "x86_64",
"min_cpu_cores": 2,
"min_memory_gb": 4,
"min_storage_gb": 16,
"nic_count": 1
},
"os": {
"features": ["ssh"],
"packages": ["curl"],
"users": [
{
"username": "deploy",
"groups": ["sudo"],
"shell": "/bin/bash"
}
],
"services": [
{
"name": "ssh",
"enabled": true,
"config": {"port": 22, "disable_password_auth": true}
}
],
"security": {
"hardening_level": "standard",
"audit_logging": true
},
"installer": {"enabled": false}
},
"scenarios": [
{
"id": "primary-smoke",
"name": "Primary image smoke test",
"enabled": true,
"tests": ["boot", "login", "packages"]
}
],
"publish_to": ["local"]
}Validation Workflow
- Validate the JSON through the current recipe editor, API, or MCP
validate_recipetool. - Compare the returned normalized recipe with the original request.
- Treat dropped unknown fields as a defect in the recipe, not as successful configuration.
- Build only after explicit requirements are represented.
- Inspect generated evidence and run assertions against the resulting guest.
See Your First Build for failure and download recovery guidance.