Add-on Manifests
Add-on Manifests
Add-ons are packaged sets of jobs distributed as OCI container images. Each add-on includes a manifest.yaml file that defines the jobs, their configurations, and runtime requirements.
What are Add-ons?
Add-ons allow you to:
- Package jobs with their dependencies in OCI images
- Pin versions using digest-based image references
- Distribute tools via container registries
- Ensure reproducibility across environments
Manifest Location
The manifest must be located at /addon/manifest.yaml inside the OCI image:
/addon/
├── manifest.yaml # Add-on manifest (required)
└── scripts/ # Job scripts and resources
├── backup.sh
└── restore.shBasic Manifest
Here’s a minimal manifest.yaml:
name: "backup-tools"
version: "1.0.0"
description: "Database backup and restore utilities"
entrypoints:
- id: "backup"
name: "Database Backup"
description: "Backs up database to S3"
command: ["/addon/scripts/backup.sh"]
- id: "restore"
name: "Database Restore"
description: "Restores database from S3"
command: ["/addon/scripts/restore.sh"]Manifest Schema
Metadata
# Add-on name (used in job IDs)
name: "backup-tools"
# Semantic version
version: "1.0.0"
# Human-readable description
description: "Database backup and restore utilities"
# Optional metadata
metadata:
author: "ops-team"
license: "MIT"
homepage: "https://github.com/org/backup-tools"Entrypoints
Each entrypoint defines a job exposed by the add-on:
entrypoints:
- id: "backup"
name: "Database Backup"
description: "Backs up PostgreSQL database"
# Command to execute (required)
command: ["/addon/scripts/backup.sh"]
# Optional: Arguments schema
argspec:
type: "object"
properties:
database:
type: "string"
description: "Database name"
s3_bucket:
type: "string"
description: "S3 bucket for backups"
required:
- "database"
- "s3_bucket"
# Optional: Resource hints
resources:
cpu: "1.0"
memory: "2GiB"
# Optional: Environment variables
env:
BACKUP_TOOL_VERSION: "2.0"
# Optional: Network access
network: "all" # or "none"Entrypoint Fields
Required Fields
id(string): Unique identifier within the add-oncommand(array): Command to execute in the container
Optional Fields
name(string): Human-readable namedescription(string): Detailed descriptionargspec(object): JSON Schema for job argumentsresources(object): Resource hints (CPU, memory)env(object): Environment variablesnetwork(string): Network access (allornone)annotations(object): Custom metadata
Job ID Resolution
Jobs from add-ons are exposed with IDs based on the source’s mountPath:
# In flwd.yaml
sources:
- name: "backup-addon"
type: "oci"
image: "ghcr.io/org/backup-tools:v1.0.0@sha256:..."
mountPath: "addons/backup"Resulting job IDs:
addons/backup/backup(from entrypointid: "backup")addons/backup/restore(from entrypointid: "restore")
Resource Hints
Specify resource requirements for jobs:
entrypoints:
- id: "heavy-job"
command: ["/app/process"]
resources:
# CPU limit (cores)
cpu: "2.0"
# Memory limit
memory: "4GiB"
# Execution timeout
timeout: "1h"Environment Variables
Define environment variables for your jobs:
entrypoints:
- id: "app"
command: ["/app/run"]
env:
APP_ENV: "production"
LOG_LEVEL: "info"
FEATURE_FLAG_X: "enabled"Network Access
Control network access for jobs:
entrypoints:
- id: "isolated-job"
command: ["/app/process"]
network: "none" # No network access
- id: "api-job"
command: ["/app/api"]
network: "all" # Full network accessAnnotations
Add custom metadata using annotations:
entrypoints:
- id: "db-backup"
command: ["/app/backup"]
annotations:
# DB Shim usage hints
flowd.db.required: "true"
flowd.db.quota: "1GiB"
# Custom metadata
team: "platform"
sla: "critical"Complete Example
name: "postgres-tools"
version: "2.1.0"
description: "PostgreSQL backup, restore, and maintenance tools"
metadata:
author: "database-team"
license: "Apache-2.0"
homepage: "https://github.com/org/postgres-tools"
entrypoints:
- id: "backup"
name: "PostgreSQL Backup"
description: "Creates compressed backup of PostgreSQL database"
command: ["/app/backup.sh"]
argspec:
type: "object"
properties:
database:
type: "string"
description: "Database name to backup"
s3_bucket:
type: "string"
description: "S3 bucket for backup storage"
compression:
type: "string"
enum: ["gzip", "zstd", "none"]
default: "zstd"
encryption_key:
type: "string"
format: "secret"
description: "Encryption key for backup"
required:
- "database"
- "s3_bucket"
- "encryption_key"
resources:
cpu: "2.0"
memory: "4GiB"
timeout: "2h"
env:
PGBACKUP_VERSION: "2.1.0"
COMPRESSION_LEVEL: "3"
network: "all"
annotations:
flowd.db.required: "true"
team: "database"
sla: "high"
- id: "restore"
name: "PostgreSQL Restore"
description: "Restores database from backup"
command: ["/app/restore.sh"]
argspec:
type: "object"
properties:
database:
type: "string"
description: "Target database name"
backup_key:
type: "string"
description: "S3 key of backup to restore"
encryption_key:
type: "string"
format: "secret"
description: "Decryption key"
required:
- "database"
- "backup_key"
- "encryption_key"
resources:
cpu: "2.0"
memory: "4GiB"
timeout: "3h"
env:
PGRESTORE_VERSION: "2.1.0"
network: "all"
- id: "vacuum"
name: "Database Maintenance"
description: "Runs VACUUM ANALYZE on database"
command: ["/app/vacuum.sh"]
argspec:
type: "object"
properties:
database:
type: "string"
description: "Database to maintain"
full:
type: "boolean"
description: "Run VACUUM FULL"
default: false
required:
- "database"
resources:
cpu: "1.0"
memory: "1GiB"
timeout: "1h"
network: "none"Building Add-on Images
Dockerfile Example
FROM alpine:3.18
# Install dependencies
RUN apk add --no-cache bash postgresql-client aws-cli
# Copy manifest
COPY manifest.yaml /addon/manifest.yaml
# Copy scripts
COPY scripts/ /addon/scripts/
RUN chmod +x /addon/scripts/*.sh
# Set working directory
WORKDIR /addonBuild and Push
# Build image
docker build -t ghcr.io/org/postgres-tools:v2.1.0 .
# Get digest
docker push ghcr.io/org/postgres-tools:v2.1.0
# Output: sha256:abc123...
# Tag with digest
docker tag ghcr.io/org/postgres-tools:v2.1.0 \
ghcr.io/org/postgres-tools:v2.1.0@sha256:abc123...Configuring Add-on Sources
Add the add-on to your flwd.yaml:
sources:
- name: "postgres-tools"
type: "oci"
# MUST use digest-pinned reference
image: "ghcr.io/org/postgres-tools:v2.1.0@sha256:abc123..."
mountPath: "tools/postgres"Security Considerations
Executor Enforcement
executor: "container". This cannot be overridden by overlays or tenants.Security Profile
Add-on jobs default to the secure security profile unless explicitly configured otherwise in the manifest.
Image Verification
- Images must be pinned by digest (
@sha256:...) - Signature verification follows the instance’s container trust policy
- Verification failures cause the source to fail-closed
Resource Limits
Resource hints from the manifest are passed through the policy engine. The effective limits may be stricter than requested but will never exceed policy ceilings.
Job Origin Metadata
Jobs from add-ons include extended origin information:
{
"origin": {
"source_kind": "oci",
"source_name": "postgres-tools",
"addon_name": "postgres-tools",
"addon_version": "2.1.0",
"addon_image_digest": "sha256:abc123..."
}
}This metadata is available in:
- Job listings (
GET /jobs) - Run records (
GET /runs/{id}) - Journal entries
Validation
Validate your manifest before building:
# Validate manifest structure
flwd addons validate /path/to/manifest.yaml
# Test add-on locally
flwd addons test /path/to/imageNext Steps
- Sources & Tree-v1 Structure - Understand source configuration
- Job Configuration - Learn about job config.yaml
- Configuration - Configure OCI sources