Skip to content

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:

version: 1
# ... rest of configuration

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.

MAKE87.yml
...

peripheral_requirements:
  - name: CAMERA
    peripheral_type: Camera

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.

MAKE87.yml
...

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.

MAKE87.yml
...

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
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.