packages/<svc>/manifest.yaml — referenceThe per-service package manifest. Declares everything PMA needs to install, configure, monitor, back up, restore, and uninstall a service. Read by bootstrap, the framework, the backup/restore code, the contract system, and the AI-callable MCP gateway.
This is PMA's manifest schema (service-level). For the asd-owned route schema (net.manifest.yaml), see /asd/reference/net-manifest.
name: redmine # service id, lowercase, no spaces
display_name: Redmine # human-readable
description: "Project management" # one-line description
category: project_management # see "Field reference" below for enum
classification: enterprise # core / enterprise / optional
containers:
- name: redmine
role: app
required: true
installation:
status: installed # installed / inactive / available / deprecated
That's the bare minimum. Most fields below are optional but recommended.
| Field | Type | Notes |
|---|---|---|
name |
string | Service id, lowercase, no spaces. Used in container names, env var prefixes, recipe names. |
version |
string | Package version. |
display_name |
string | Human-readable name. Shown in just status, dashboards. |
description |
string | One-line description. |
category |
enum | documentation/monitoring/crm/erp/automation/communication/email/ai/security/core |
classification |
enum | core/enterprise/optional — drives default profile membership |
priority |
integer | Startup priority (lower = earlier). Used for dependency ordering. |
image:
name: redmine
tag: '5-alpine'
env_var: REDMINE_IMAGE_TAG
env_vars: # optional, for multi-env-var image setups
MATTERMOST_IMAGE: mattermost-team-edition
MATTERMOST_IMAGE_TAG: '10.1'
build: false # true if locally built (Dockerfile in package)
containers:
- name: redmine # base name; CONTAINER_PREFIX prepended at runtime
env_var: REDMINE_CONTAINER_NAME # .env variable for the resolved name
role: app # app / database / cache / queue / worker / scheduler / backend / websocket
required: true # required for service to function (default true)
health_check: true # whether container has healthcheck
container_user: 1000 # UID the service runs as inside the container (used for post-restore chown)
Most services have one container; some have two (app + db). Each gets its own entry.
database:
type: postgresql # postgresql / mariadb / mysql / sqlite
name: redmine
user: redmine
container: "${CONTAINER_PREFIX}${SERVICE}-postgres"
password_env: REDMINE_DB_PASSWORD
site_database: "_1bd3e0294da19198" # for multi-site apps like ERPNext
volumes:
data:
name: "docker_${SERVICE}-data${ENV_SUFFIX}"
mount: /data
description: "Application data and SQLite database"
requirements:
ports: 1 # how many ports the service needs
storage: true # has persistent storage
internal_port: 3000 # main HTTP port inside the container
database: postgres # required external db engine
port_env:
- env: REDMINE_PORT
default: 8083
health:
endpoint: / # HTTP path probed by dynamic-service-checks.ts
expected_code: 200 # HTTP code that means healthy
sso:
type: oauth # oauth / oidc / saml / proxy / wikijs / frappe
redirect_path: /login/oauth2/callback
configured: true # false → bootstrap will configure next install
quirks: # free-text notes for operators
- Config stored in PostgreSQL database
hooks:
check: scripts/sso-check.sh
configure: scripts/configure-sso.sh
Walks the SSO model: /pma/learn/04-sso-everywhere.
backup:
enabled: true
type: database # database / volume / workspace / config
database:
user: redmine
name: redmine
volumes:
- suffix: redmine-files
data_uid: 1000 # UID for chown after volume restore
estimated_size_mb: 100
fixes:
post_restore:
script: scripts/post_restore.py
functions:
- name: fix_migration_lock
description: Unlock stuck migration table after restore
targets: database # database / volume / container / authentik
Walks the backup model: /pma/learn/05-backup-and-restore.
urls:
public:
base: "https://${ENV_PREFIX}${SERVICE}-${ASD_CLIENT_ID}.${ASD_TUNNEL_HOST}"
internal:
container: "${CONTAINER_PREFIX}${SERVICE}"
port: "${REDMINE_PORT}"
base: "http://${CONTAINER_PREFIX}${SERVICE}:${REDMINE_PORT}"
dependencies: # URLs of services this service depends on
authentik:
public: "https://${ENV_PREFIX}authentik-${ASD_CLIENT_ID}.${ASD_TUNNEL_HOST}"
internal: "http://${CONTAINER_PREFIX}authentik:9000"
migration:
url_sync: true # whether to run url_sync.py for this service
env_url_pattern: "${SERVICE}-${CLIENT_ID}"
env_containers: # extra container suffixes for .env replacement
- custom-worker
pre_hooks: # scripts to run before migration
- scripts/pre_migrate.sh
post_hooks:
- scripts/post_migrate.sh
skip_phases: # phases to skip: url_sync / post_restore / env
- env
framework:
role: service # service / sso-provider
profiles: # which profiles include this service
- development
- enterprise
- minimal
abbreviation: RM # 2-letter code
startup_priority: 100
user_management:
enabled: true
create_recipe: redmine-create-user
list_recipe: redmine-list-users
integrations:
ticket_sync: true
email_routing: false
monitoring: true
e2e:
enabled: true
selectors:
login: 'a.login'
logged_in: '#loggedas'
error: '.flash.error'
assertions:
url_not_contains: ['login']
has_element: '#top-menu'
wait_after_load: 3000
api:
smoke_endpoints:
- path: /api/method/ping
expected_code: 200
expected_body: "pong"
auth_env: REDMINE_API_KEY # env var holding bearer token (optional)
installation:
status: installed # installed / inactive / available / deprecated
name: my-app
display_name: My App
description: "Example service"
category: documentation
classification: optional
priority: 90
image:
name: my-org/my-app
tag: '1.0'
env_var: MYAPP_IMAGE_TAG
containers:
- name: my-app
env_var: MYAPP_CONTAINER_NAME
role: app
required: true
health_check: true
requirements:
ports: 1
internal_port: 8080
port_env:
- env: MYAPP_PORT
default: 8888
health:
endpoint: /health
expected_code: 200
sso:
type: oauth
redirect_path: /login/callback
configured: false
backup:
enabled: true
type: volume
volumes:
- suffix: myapp-data
framework:
profiles:
- development
- full
installation:
status: available
The authoritative schema lives at docs/schemas/manifest.schema.yaml in the asd-pma repo. Run just contract-validate to check a manifest against the schema. CI runs this on every push.
If you add a new manifest field: update docs/schemas/manifest.schema.yaml first, then add the field to the affected packages/<svc>/manifest.yaml, then update this reference page.
/pma/learn/02-add-a-service — walks through writing a manifest from scratch./pma/cookbook/install-a-new-service — recipe with Vaultwarden example./pma/reference/services-yaml — the project-wide service registry that references these manifests./asd/reference/net-manifest — the routing schema (separate file per service).