Skip to content

Instance configuration reference

Practical reference for the Craftifact instance configuration edited through the Control Plane.

What this configuration controls

In Craftifact, Effective configuration is the authoritative instance configuration for your instance. It controls repositories, access, storage references, robots, and retention behavior.

The normal workflow is:

  1. Edit the YAML in Effective configuration.
  2. Add or update secrets in Secrets if the YAML references ${VAR} placeholders.
  3. Save and validate.
  4. Use Deploy Config to make the saved config the active runtime config.
Rationale: why the configuration still contains storage
Craftifact still consumes one complete runtime config. In the Control Plane flow, the storage block is seeded for you and the internal ${S3_*} values are injected automatically. For most users, the right default is to keep that block unchanged.

Minimal example

This is the practical baseline the initial Control Plane flow seeds for a new Starter instance:

storage:
  default: local-s3
  backends:
    local-s3:
      type: s3
      endpoint: ${S3_ENDPOINT}
      bucket: ${S3_BUCKET}
      credentials:
        access_key_id: ${S3_ACCESS_KEY}
        secret_access_key: ${S3_SECRET_KEY}

repositories:
  - name: oci
    type: oci

roles:
  - name: admin
    permissions:
      - "*:*:*"
  - name: developer
    permissions:
      - "oci:artifact:publish"
      - "oci:artifact:read"
      - "oci:artifact:redeploy"
      - "oci:artifact:delete"
      - "oci:composition:read"
      - "oci:findings:read"
  - name: viewer
    permissions:
      - "oci:artifact:read"
      - "oci:composition:read"
      - "oci:findings:read"
      - "oci:license_policy:read"
      - "oci:pull_gate:read"

role_assignments:
  - role: admin
    members:
      - admin@example.com

The generated instance configuration replaces admin@example.com with the initial admin email you entered during creation. On Pro and above, the seeded configuration also includes example retention_policies.

What you probably want to change next

  • Add more repositories under repositories.
  • Add proxy credentials via Secrets and reference them from ${VAR} placeholders.
  • Expand roles, groups, and role_assignments for your team structure.
  • Add retention_policies if you are on Pro or above.
  • Add license_policies and pull_policies when you want repository-level supply-chain gates.
  • Add robot_accounts for automation.
  • On Team, consider external S3-compatible storage only if you intentionally want to replace the seeded default.

Top-level keys

storage

Required. Defines the default storage backend and named backends.

Supported backend types are:

  • filesystem
  • s3
  • azure_blob
  • google_cloud_storage

Hosted note:

  • Below Team, validation only accepts the internal ${S3_ENDPOINT}, ${S3_BUCKET}, ${S3_ACCESS_KEY}, and ${S3_SECRET_KEY} pattern for S3 storage.
  • External S3-compatible storage is a Team feature.

repositories

List of repository definitions.

Supported hosted repository types are:

  • maven, python, npm, oci
  • go beta
  • maven_proxy, python_proxy, npm_proxy, oci_proxy
  • go_proxy
  • maven_group, python_group, npm_group, oci_group
  • go_group

Common fields you will use most:

  • name
  • type
  • storage
  • quota
  • read_only
  • redeploy
  • upstream_url
  • upstream_user
  • upstream_password
  • upstream_bearer_token
  • upstream_tls_verify
  • cache_ttl for proxy repositories
  • members
  • retention
  • license_policy
  • pull_policy
  • version_policy for Maven

roles

Named permission bundles. Permissions use the form <repository>:<domain>:<action>. For the meaning of each supported domain/action pair, see Permissions and access model.

artifact:* grants artifact actions only. Use <repository>:*:* for every domain in one repository, or "*:*:*" for all repo-scoped permissions.

Legacy permissions such as artifact:add, artifact:exec_elevated, artifact:manage_findings, artifact:manage_licenses, artifact:manage_policies, and sbom:* are no longer accepted. Use the domain-specific permissions above.

If you use * at the start of a permission string, wrap the full permission string in quotes in YAML, for example "*:*:*". Otherwise, a leading * is not valid unquoted YAML scalar syntax.

groups

Named group definitions used by role assignments. A group must define exactly one of:

  • mail_domain
  • members
  • idp_group

role_assignments

Binds a role to one or both of:

  • members
  • groups

robot_accounts

Declares automation identities. Useful fields are:

  • id
  • description
  • owners
  • roles
  • enabled
  • token_policy

For the full workflow from declaration to token usage in the Robot accounts tab, see Create a robot account and use its token.

retention_policies

Available from Pro. Defines named retention policies and optionally a default policy through retention_policies.default. Named policies live under retention_policies.<name>. Repositories reference them later through repositories[].retention.

Practical example with one general default policy and one selector-based OCI policy:

retention_policies:
  default: default-policy

  default-policy:
    max_duration_since_published: 7d
    max_duration_since_download: 7d
    min_duration_since_published: 1d
    keep_last: 3

  oci-policy:
    selectors:
      name:
        include: "^(craftifact|saas-controller)$"
      version:
        include: "^[0-9]+\\.[0-9]+\\.[0-9]+$"
        exclude: "^latest$"
    keep_last: 3

Available attributes per policy are:

  • max_duration_since_published Deletes artifacts once they are older than this duration since publication.
  • max_duration_since_download Deletes artifacts that have not been downloaded for longer than this duration.
  • min_duration_since_published Enforces a minimum lifetime since publication before deletion is allowed.
  • keep_last Keeps the last N matching artifacts regardless of the time-based rules.
  • selectors Restricts a policy to matching artifacts by name and/or version.

Under selectors, the available fields are:

  • selectors.name.include
  • selectors.name.exclude
  • selectors.version.include
  • selectors.version.exclude

All four expect regex strings. If selectors is set, at least one of those four fields must be configured.

Combination rules:

  • keep_last can be combined with all duration attributes.
  • selectors can additionally be combined with keep_last and the duration attributes.
  • If selectors is set, keep_last must be set explicitly.
  • If selectors is not set and keep_last is omitted, it defaults internally to 0.
  • retention_policies.default must point to a defined named policy.
  • If retention_policies.default is omitted, repositories without their own retention config are not automatically covered by a default policy.

Durations use the suffixes h, d, or y, for example 48h, 7d, or 1y.

license_policies

Defines named license policies and optionally a default policy through license_policies.default. Named policies live under license_policies.<name>. Repositories can use the default, reference another named policy, define an inline policy, disable policy enforcement, or delegate policy management to users with license_policy:configure.

License-policy helpers in Craftifact are informational guidance only, not legal advice. For background on identifiers and license texts, see SPDX and ChooseALicense.

Mixed-governance example:

license_policies:
  default: company-default

  company-default:
    denied_spdx_ids:
      - AGPL-3.0-only
      - AGPL-3.0-or-later
    unknown_license_action: unknown

  permissive-only:
    allowed_spdx_ids:
      - Apache-2.0
      - BSD-2-Clause
      - BSD-3-Clause
      - MIT
    unknown_license_action: unknown

repositories:
  - name: oci
    type: oci

  - name: research
    type: python
    license_policy:
      policy: permissive-only

  - name: delegated
    type: npm
    license_policy:
      managed_by_users: true

  - name: disabled
    type: maven
    license_policy: disabled

Policy rules:

  • allowed_spdx_ids creates an allowlist.
  • denied_spdx_ids creates a denylist.
  • A policy must define exactly one of those two lists.
  • unknown_license_action accepts allow, deny, or unknown; default is unknown.
  • license_policy: disabled disables policy evaluation for that repository, even when a default exists.
  • managed_by_users: true is exclusive with all concrete policy settings and named-policy references.

pull_policies

Defines named pull policies and optionally a default policy through pull_policies.default. Named policies live under pull_policies.<name>. Repositories can use the default, reference another named policy through pull_policy.policy, or define an inline pull_policy.

Pull policies apply to npm, Python, Maven, Go, and OCI pull paths. They can filter package metadata and hold or deny direct pulls depending on the enforcement mode and rule results. Group repositories cannot define their own pull policy.

Cooldown windows delay newly published packages until a configured minimum age has passed. Fast-track actions create a documented exception for a held package, so trusted releases can bypass the wait without disabling the policy for the repository.

Practical strict-gate example:

pull_policies:
  default: strict-release-gate

  strict-release-gate:
    enforcement_mode: strict
    cooldown:
      minimum_release_age: 24h
      unknown_release_time: hold
    vulnerabilities:
      max_severity: high
      unknown_analysis: hold
    licenses:
      source: repository_license_policy
      unknown_analysis: hold
    content:
      secrets: hold
      misconfig: allow
      malware: deny
    hosted:
      wait_for_required_scans: true

repositories:
  - name: npm
    type: npm_proxy

  - name: experimental
    type: python_proxy
    pull_policy:
      enforcement_mode: metadata_only
      cooldown:
        minimum_release_age: 12h

Policy rules:

  • enforcement_mode accepts observe, metadata_only, or strict; default is observe.
  • metadata_only hides held content from package metadata while direct pulls can still proceed.
  • strict can hold or deny direct pulls and returns Craftifact policy decision headers for blocked requests.
  • cooldown.minimum_release_age accepts duration values such as 12h or 7d.
  • cooldown.unknown_release_time accepts allow, hold, or use_first_seen; default is allow.
  • vulnerabilities.max_severity accepts unknown, low, medium, high, or critical.
  • vulnerabilities.unknown_analysis, licenses.unknown_analysis, content.secrets, content.misconfig, and content.malware accept allow, hold, or deny; default is allow.
  • licenses.source: repository_license_policy uses the repository license policy result as a pull-gate input.
  • hosted.wait_for_required_scans: true makes hosted artifacts wait for required analysis before release under a blocking mode.
  • provenance.required: true is reserved and currently rejected because provenance enforcement is not implemented yet.

scheduler

Optional advanced tuning for retention, quota checks, stalled-job retries, and OCI garbage collection cadence. Most users can leave this untouched.

Example:

scheduler:
  retention:
    interval: 6h
    catchup: true
    max_lateness: 30m

  quota:
    interval: 6h
    catchup: true
    max_lateness: 30m

  vulnerability_rescan:
    interval: 1d

  stalled_job_retry:
    enabled: true
    max_attempts: 1

repositories:
  - name: team-images
    type: oci
    oci:
      gc:
        interval: "*/15 * * * *"
        max_lateness: 5m

Supported top-level sections are:

  • retention
  • quota
  • vulnerability_rescan
  • stalled_job_retry

scheduler.retention

Available attributes are:

  • enabled
  • interval
  • catchup
  • max_lateness

catchup and max_lateness work together:

  • If a retention run starts later than max_lateness, it is skipped when catchup: false.
  • With catchup: true, the same late job still runs.

scheduler.quota

Available attributes are:

  • enabled
  • interval
  • catchup
  • max_lateness

Semantically this works like scheduler.retention, but for quota reconciliation instead of deletion rules.

scheduler.vulnerability_rescan

Available attributes are:

  • interval

Craftifact still starts the initial vulnerability scan after an uploaded or generated SBOM becomes ready. This setting only controls the periodic check for already stored reports that became stale because the vulnerability database, scanner version, scan state, or SBOM changed.

scheduler.stalled_job_retry

Available attributes are:

  • enabled
  • max_attempts

This is not a periodic sweep like retention or quota. The logic runs when a worker starts and retries jobs that the queue system considers stalled.

OCI garbage collection per repository

For oci and oci_proxy repositories, you can also fine-tune garbage collection per repository under repositories[].oci.gc.

Available attributes are:

  • interval
  • max_lateness

Important:

  • There is no scheduler.enabled. Scheduler registration is always active.
  • There is also no repositories[].oci.gc.enabled. For OCI repositories, GC is always active; you only tune cadence and max_lateness.
  • Other periodic platform jobs such as Procrastinate cleanup or checksum retries are wired internally and cannot be configured through this YAML.

Duration values here use the suffixes s, m, h, d, and w. Alternatively, you can provide a cron expression directly. If you use durations instead of cron, keep them aligned to sensible minute, hour, day, or week boundaries in practice.

Environment placeholders and secrets

Validation only allows ${VAR} placeholders in specific places:

  • storage backend credentials
  • repositories[].upstream_user
  • repositories[].upstream_password
  • repositories[].upstream_bearer_token

For your own secrets, add the key in the Secrets tab and reference it as ${MY_SECRET} in YAML. The control plane renders it to the prefixed runtime environment automatically. Do not keep credentials, passwords, or tokens there in plain text. Use Secrets plus ${...} references consistently.

Do not expect unrelated platform environment variables to resolve just because they exist somewhere in the infrastructure.

Where to go from here