Definitions and Instances

A template is the specification of a service — abstract, reusable. To become a running container it needs two intermediate steps: a definition and an instance.

Concepts

Definition

A definition is a template + inputs + profile + instance_uid. It represents the intent of having a service configured a specific way on this host.

Template (memos)
      +
Inputs (WEB_HOSTNAME=memos.example.com)
      +
Profile (production)
      +
instance_uid (memos-blog-001)
      =
Definition "memos-blog-001"

The definition resolves every reference in the template:

  • ${input.WEB_HOSTNAME}memos.example.com
  • ${secrets.MARIADB_ROOT_PASSWORD} → generated and persisted
  • ${needs.database.host} → the MariaDB asset's container
  • ${instance.uid}memos-blog-001

Instance

An instance is the materialization of the definition: a running container in Docker, with volumes, network, healthcheck, and labels.

Definition "memos-blog-001"
      ↓
docker create + docker start
      ↓
Instance (container_id: abc123…, status: running)

The rule is simple: one instance per instance_uid. Trying to deploy the same instance_uid twice updates the existing one — it doesn't duplicate.

Inputs

Inputs come from three sources in the template's config block:

Tier When it appears in the wizard Example
config.required Always — the user must provide it WEB_HOSTNAME
config.optional Always — has a default, user can accept it MEMOS_MODE=prod
config.advanced Only with --advanced or expert mode PHP_MEMORY_LIMIT

The CLI offers two ways to supply values:

Interactive wizard — groups inputs by prefix (MAIN_DB_*, WEB_*, SMTP_*), validates the pattern, and offers inline help via ?:

deployally deploy --species memos --instance-uid memos-blog-001

Inline flags — no wizard, ideal for automation:

deployally deploy --species memos --instance-uid memos-blog-001 \
  --input WEB_HOSTNAME=memos.example.com \
  --input MEMOS_MODE=prod \
  --profile production \
  --apply

Secrets

Secrets never appear in the wizard. They're resolved through a chain of providers declared in the template:

secrets:
  MARIADB_ROOT_PASSWORD:
    kind: password
    length: 32
    providers: [local, random]
    persist: true

The chain [local, random] means: first try to read from /opt/deployally/<uid>/secrets/MARIADB_ROOT_PASSWORD (provider local); if it doesn't exist, generate a random value (provider random) and persist it. On the next redeploy of the same instance_uid, the secret is reused — no lost database password.

Other available providers include vault, env, and input (used when the user must supply the secret, e.g. an external API key).

Profile

The profile is a declarative override applied on top of the base definition. Same template, different sizing:

profiles:
  development:
    overrides:
      resources.memory.limit: 128M
      config.optional.MEMOS_MODE.default: dev
  production:
    overrides:
      resources.memory.limit: 256M
      config.optional.MEMOS_MODE.default: prod
deployally deploy --species memos --instance-uid memos-blog-001 \
  --profile development \
  --apply

Lifecycle

┌─────────────┐
│   Template  │   (catalog)
└──────┬──────┘
       │ deployally deploy --species X
       ▼
┌─────────────┐
│  Definition │   (template + inputs + profile + uid)
└──────┬──────┘
       │ --apply (resolve secrets, needs, create resources)
       ▼
┌─────────────┐
│   Instance  │   (container running)
└─────────────┘

Multi-Tenancy: Per-Instance Provisioning

When an application declares needs on an asset, the asset dispatcher provisions per-instance isolated resources. The WordPress-on-MariaDB example:

# wordpress.yaml
needs:
  database:
    class: relational
    options: [mariadb, mysql]
    per_instance:
      database: "wp_${instance.uid}"
      user:     "wp_${instance.uid}"
      password: ${secrets.WP_DB_PASSWORD}
      on_provision:    create_user_and_db
      on_decommission: drop_user_and_db

When a WordPress instance is deployed, the dispatcher calls the create_user_and_db function declared by MariaDB (in provides.functions) passing db_name=wp_<uid>, user=wp_<uid>, and password=<secret>. The result: one shared MariaDB, N isolated WordPress instances, each with its own database, user, and password.

See details in Ecology.

Cascading Auto-Provision

If the asset declared in needs doesn't yet exist on the host, the --provision-missing-assets flag tells the deploy to create it automatically — the first option in needs.options, variant default: true, same profile as the consumer:

deployally deploy --species wordpress --instance-uid wp-blog-001 \
  --input WEB_HOSTNAME=blog.example.com \
  --provision-missing-assets \
  --apply

Without that flag, the deploy aborts and asks for the asset to be present.

Commands

# List active instances
deployally list

# Details of an instance
deployally show memos-blog-001

# Live logs
deployally logs memos-blog-001 --follow

# Run an action declared in the template
deployally action memos-blog-001 restart

# Decommission (remove container + cleanup)
deployally remove memos-blog-001

Next Steps

  • Templates — The template structure that originates the definition.
  • Manifests — Where the instance persists rendered config and secrets.
  • Ecology — How needs and provides wire apps to assets.
By Borlot.com.br on 05/06/2026