MAKE87.yml Manifest Reference
The MAKE87.yml
manifest file defines how your application is built, deployed, and configured within the make87 platform. It also includes information on the interfaces it exposes or connects to. This file needs to be placed in the root of your application repository.
Schema Overview
The manifest uses version 1 of the make87 application manifest schema:
Complete Schema Reference
Top-Level Structure
version: 1 # Required: Must be 1
interfaces: [] # Optional: Communication interfaces
peripheral_requirements: [] # Optional: Hardware requirements
config: {} # Optional: Application configuration schema
container_config: {} # Optional: Container runtime configuration
build: {} # Required: Release build configuration
dev_build: {} # Optional: Development build configuration
variants: {} # Optional: Environment-specific overrides
Core Fields
version
- Type:
integer
- Required: Yes
- Value: Must be
1
- Description: Specifies the manifest schema version
interfaces
- Type:
array
- Required: No
- Default:
[]
- Description: Communication interfaces for inter-application messaging
Interface Structure
interfaces:
- name: "zenoh-data" # Required: Interface identifier
protocol: "zenoh" # Required: Protocol name (soft contract)
default_port: # Optional: Default port for all endpoints
name: "zenoh-peer"
protocol: TCP
target_port: 7447
publishers: [] # Optional: Publisher endpoints
subscribers: [] # Optional: Subscriber endpoints
providers: [] # Optional: Provider endpoints (req/reply)
requesters: [] # Optional: Requester endpoints (req/reply)
servers: [] # Optional: Server endpoints (persistent)
clients: [] # Optional: Client endpoints (persistent)
Communication Patterns
Publisher
publishers:
- name: "image_data" # Required: Publisher identifier
spec: "make87_messages.image.compressed.ImagePNG" # Required: Message type (soft contract)
encoding: "proto" # Optional: Message encoding (proto, json, msgpack, etc.)
port: # Optional: Override default port
name: "zenoh-peer"
protocol: TCP
target_port: 7447
config: # Optional: Protocol-specific configurations (JSON Schema)
type: object
properties:
congestion_control:
type: string
enum: ["DROP", "BLOCK"]
default: "DROP"
priority:
type: string
enum: ["REAL_TIME", "DATA"]
default: "DATA"
Subscriber
subscribers:
- name: "image_data"
spec: "make87_messages.image.compressed.ImagePNG"
encoding: "proto" # JSON encoding of the same message type
config: # Optional: Protocol-specific configurations (JSON Schema)
type: object
properties:
handler:
type: object
properties:
handler_type:
type: string
enum: [ FIFO, RING ]
default: RING
capacity:
type: integer
minimum: 0
description: "Capacity of the handler. For FIFO, this is the maximum number of messages it can hold. For RING, this is the size of the ring buffer."
default: 10
Provider
providers:
- name: "object_detection"
request_spec: "make87_messages.image.compressed.ImagePNG" # Required: Request message type
response_spec: "make87_messages.detection.box.Boxes2DAxisAligned" # Required: Response message type
encoding: "proto"
port:
name: "zenoh-peer"
protocol: TCP
target_port: 7447
config: # Optional: Protocol-specific configurations (JSON Schema)
type: object
properties:
timeout_ms:
type: integer
default: 5000
minimum: 1000
Requester
requesters:
- name: "object_detection"
request_spec: "make87_messages.image.compressed.ImagePNG" # Required: Request message type
response_spec: "make87_messages.detection.box.Boxes2DAxisAligned" # Required: Response message type
encoding: "proto"
config: # Optional: Protocol-specific configurations (JSON Schema)
type: object
properties:
retry_attempts:
type: integer
default: 3
Server
servers:
- name: "control_panel"
spec: "control_api:v1.2" # API specification reference
port:
name: "api"
protocol: HTTP
target_port: 8080
config: # Optional: Protocol-specific configurations (JSON Schema)
type: object
properties:
enable_cors:
type: boolean
default: true
rate_limit:
type: object
properties:
requests_per_minute:
type: integer
default: 100
Client
clients:
- name: "api_client"
spec: "control_api:v1.2"
config: # Optional: Protocol-specific configurations (JSON Schema)
type: object
properties:
timeout_ms:
type: integer
default: 30000
peripheral_requirements
- Type:
array
- Required: No
- Default:
[]
- Description: Hardware peripherals required by the application
Simple Requirements
The simplest way to configure peripheral requirements is to use one of make87's built-in peripheral types. These are:
Camera
Codec
ISP
GPIO
GPU
I2C
Keyboard
Mouse
RealSense
Just add an entry in peripheral_requirements
in your MAKE87.yml
file and use one of the value above for the
peripheral_type
key. The platform will automatically discover the peripherals on the node and let the user select
which ones to use. You also need to provide a name
for the peripheral, which is used to identify it in
the user interface.
You can also specify the type GenericDevice
which allows the user to mount any entry in /dev
or any of its
subdirectories. This is helpful for peripherals that are not automatically discovered by the platform, such as USB
devices or other hardware like new sensor types, or compute accelerators. Below is an example of how to require two
generic device mounts.
...
peripheral_requirements:
- name: RENDER
peripheral_type: GenericDevice
- name: CARD
peripheral_type: GenericDevice
Tip
If you want to learn more on how Peripherals are being discovered on Nodes, check out the Peripheral Discovery and how to configure them for your application.
Advanced Requirements
Often, application developers need to specify more complex requirements for peripherals. For example, when expecting
video codecs for a specific processor type, or a specific camera type like a USB camera. In these cases, you can use the
peripheral_requirements
section to constraints on what can be mounted.
Below is an example on how to require mounts to start with a specific prefix.
...
peripheral_requirements:
- name: RENDER
peripheral_type: GenericDevice
constraints:
type: GenericDevice
path_prefix: "/dev/dri/renderD"
path_suffix: null
contains: null
contains_not: null
- name: CARD
peripheral_type: GenericDevice
constraints:
type: GenericDevice
path_prefix: "/dev/dri/card"
path_suffix: null
contains: null
contains_not: null
Now users can mount devices like /dev/dri/renderD128
or /dev/dri/renderD129
, and /dev/dri/card0
or
/dev/dri/card1
.
config
- Type:
object
(JSON Schema) - Required: No
- Description: Application-specific configuration schema
config:
type: object
properties:
model_path:
type: string
default: "/models/default.onnx"
description: "Path to the ML model file"
confidence_threshold:
type: number
default: 0.7
minimum: 0.0
maximum: 1.0
batch_size:
type: integer
default: 1
minimum: 1
maximum: 128
container_config
- Type:
object
- Required: No
- Description: Docker container runtime configuration
container_config:
privileged: false # Run with elevated privileges
read_only: false # Mount root filesystem as read-only
# it's recommended to use `peripheral_requirements` instead of `devices` so devices
# can be discovered automatically / assigned dynamically
devices: [] # Device mappings (e.g., ["/dev/video0:/dev/video0"])
tmpfs: # Mount tmpfs (in-memory filesystem), e.g. {"/tmp": "size=64m"}
ulimits: {} # Set resource limits (e.g., nofile, nproc)
volumes: [] # Volume mounts (e.g., ["./data:/app/data"])
cap_add: [] # Add Linux capabilities
cap_drop: [] # Drop Linux capabilities
command: ["python", "main.py"] # Override container command
entrypoint: ["/bin/bash"] # Override container entrypoint
stop_grace_period: "10s" # Time to wait before force killing container
stop_signal: "SIGTERM" # Signal to stop container
user: "1000:1000" # User ID and group ID
userns_mode: "host" # User namespace mode
working_dir: "/app" # Working directory
init: false # Use init process
shm_size: "64m" # Size of /dev/shm
group_add: [] # Additional groups (e.g., ["video"])
tty: false # Allocate pseudo-TTY
sysctls: {} # Kernel parameters (e.g., {"net.core.somaxconn": "1024"})
security_opt: [] # Security options (e.g., ["seccomp=unconfined"])
cgroup_parent: "" # Optional parent cgroup for the container
mem_limit: "512m" # Memory limit
mem_reservation: "256m" # Memory soft limit
mem_swappiness: 60 # Swappiness (0-100)
environment: # Environment variables
DEBUG: "true"
LOG_LEVEL: "info"
build
- Type:
object
- Required: Yes
- Description: Release build configuration
Using Build Kits (Recommended)
build:
build_kit:
name: python3 # python3, python3_cuda, rust, rust_cuda, rust_av
platforms: ["linux/amd64", "linux/arm64"]
context: "." # Build context directory
build_additions: # Optional: Additional build layers
ssh:
ssh_server: {}
ide:
vscode_server_py3: {}
For more information about the available build kits and their capabilities, see Applications - Build Kits.
Custom Build
All keys in buid.custom
are Docker Bake Target options. This gives you full control over the Docker build process, allowing you to specify a custom Dockerfile, context, platforms, and build arguments.
build:
custom:
dockerfile: "Dockerfile" # Dockerfile path relative to context
context: "."
platforms: ["linux/amd64", "linux/arm64"]
target: "production" # Multi-stage build target
args: # Build arguments
VERSION: "1.0.0"
ENV: "production"
dev_build
- Type:
object
- Required: No
- Description: Development build configuration (enables dev mode deployment). Same structure as
build
, but with additional options for development tools.
dev_build:
build_kit:
name: python3
build_additions: # Values need to map to any subdirectory in this repository: https://github.com/make87/make87-build-kits/tree/main/additions
ide: vscode_server_py3 # Optional: VSCode server for development
ssh: ssh_server # Optional: SSH server for remote access
variants
- Type:
object
- Required: No
- Description: Environment-specific configuration overrides. Useful for supporting different compute accelerators, configurations, or deployment environments. Supports everything from top-level manifest fields.
variants:
production:
config:
type: object
properties:
log_level:
type: string
default: "warn"
container_config:
mem_limit: "2g"
development:
interfaces:
- name: debug_interface
protocol: http
servers:
- name: debug_api
spec: "debug_api:v1"
port:
name: debug
protocol: HTTP
target_port: 9999
Port Requirements
Ports are automatically exposed when defined in interface configurations:
port:
name: "api" # Required: Port identifier
protocol: HTTP # Required: Protocol (TCP, UDP, HTTP, WS, SSH)
target_port: 8080 # Required: Container port number
publish_mode: Ingress # Optional: Publishing mode
is_system_interface: false # Optional: System-level interface
is_dev_interface: false # Optional: Development-only interface
url_prefix: "/api" # Optional: URL path prefix
url_suffix: "/v1" # Optional: URL path suffix
Complete Example
version: 1
interfaces:
- name: camera_feed
protocol: zenoh
publishers:
- name: raw_images
spec: "make87_messages.image.ImageRGB"
encoding: "proto"
config:
type: object
properties:
priority:
type: string
enum: ["REAL_TIME", "DATA"]
default: "REAL_TIME"
- name: detection_api
protocol: http
servers:
- name: detect_objects
spec: "detection_api:v1"
port:
name: api
protocol: HTTP
target_port: 8080
config:
type: object
properties:
enable_cors:
type: boolean
default: true
peripheral_requirements:
- type: GPU
constraints:
vram_mb: 2048
config:
type: object
properties:
confidence_threshold:
type: number
default: 0.7
minimum: 0.0
maximum: 1.0
input_size:
type: integer
default: 640
container_config:
environment:
MODEL_PATH: "/models/yolo.onnx"
build:
build_kit:
name: python3
platforms: ["linux/amd64", "linux/arm64"]
dev_build:
build_kit:
name: python3
build_additions:
ide: vscode_server_py3
ssh: ssh_server
variants:
production:
config:
type: object
properties:
confidence_threshold:
type: number
default: 0.9
container_config:
environment:
MODEL_PATH: "/models/yolo_fast.onnx"
Runtime Configuration
At runtime, applications receive connection details via the MAKE87_CONFIG
environment variable containing a JSON object with resolved interface addresses, protocol details, and configuration values.
This manifest design provides complete flexibility for any protocol while maintaining type safety and compatibility checking through soft contracts.