Coming soon. Depotex is in active development, so features and these docs may still change.

Set up without the UI

Unattended setup from a YAML file for scripts, containers and configuration management

Everything the setup wizard asks can come from a YAML file instead, so a new installation can be set up by a script, a container entrypoint, Ansible, Terraform or a GitOps pipeline with nobody at a browser. This is passive setup. The Helm chart uses it too (setup.mode: passive or auto; see Install with Helm).

1. How it works

  1. Get the installation ID — ./server --machine-id prints it and exits. In a container, run the image with --machine-id on the host (or pod) that will run Depotex: the ID belongs to that machine.
  2. Get the license — Request it for that ID (see Get a license).
  3. Write the setup file — The same sections as the wizard; secrets as ${VARIABLE} references (below).
  4. Start the server once with it — --setup-config setup.yaml, or SETUP_CONFIG_FILE=setup.yaml. The server checks the file, sets up, and continues in normal mode.
  5. Remove the file — It's read only on a fresh installation and ignored afterwards; don't leave secrets lying around.
chmod 600 setup.yaml
export CONFIG_ENCRYPTION_KEY="$(cat /run/secrets/depotex-encryption-key)"
export DATABASE_URL='postgres://depotex:…@db.internal:5432/depotex?sslmode=verify-full&pool_max_conns=25'
export ADMIN_PASSWORD="$(cat /run/secrets/depotex-admin-password)"
./server --setup-config setup.yaml

2. The setup file

An annotated example ships as setup.example.yaml. Every key:

database:
  url: ${DATABASE_URL}           # may be left out when DATABASE_URL is set

cache:
  redis_url: ""                  # empty: single server without Redis; required for a cluster

storage:
  backend: s3                    # local | s3 | minio | azure
  local:
    path: /var/lib/depotex/artifacts
  s3:
    bucket: my-depotex-artifacts
    region: eu-west-1
    access_key: ${S3_ACCESS_KEY} # leave both keys out to use the server's IAM role
    secret_key: ${S3_SECRET_KEY}
    role_arn: ""                 # optional: a role to assume
    external_id: ""              # optional: its external ID
  minio:
    endpoint: minio.internal:9000
    bucket: depotex
    use_ssl: true
    access_key: ${MINIO_ACCESS_KEY}
    secret_key: ${MINIO_SECRET_KEY}
  azure:
    container: depotex
    account: ${AZURE_STORAGE_ACCOUNT}
    key: ${AZURE_STORAGE_KEY}

license:
  file: license.json             # relative to this file; or data: | with the JSON inline

admin:
  email: admin@example.com
  name: Administrator
  password: ${ADMIN_PASSWORD}    # at least 8 characters
KeyRequiredMeaning
database.urlWhen DATABASE_URL isn't setPostgreSQL URL. Query options such as sslmode and pool_max_conns are kept.
cache.redis_urlFor a clusterRedis URL: one server, Sentinel (redis+sentinel://) or Redis Cluster (redis+cluster://); rediss variants for TLS
storage.backendYeslocal, s3, minio or azure; only that backend's section is read
storage.local.pathWith localDirectory for artifacts (a shared volume in a cluster)
storage.s3.*With s3bucket, region; access_key and secret_key (or neither, for the IAM role); optional role_arn, external_id
storage.minio.*With minioendpoint, bucket, use_ssl, access_key, secret_key
storage.azure.*With azurecontainer, account, key
license.file or license.dataYes, one of themThe license JSON: a file (relative to the setup file) or inline
admin.email, admin.name, admin.passwordYesThe first super admin

3. Rules the server enforces

  • Private file. The file must not be readable by group or others (chmod 600); otherwise the server stops and prints the chmod to run.
  • No unknown keys. A misspelled key is an error, so a typo can't silently drop a setting.
  • Secrets from the environment. Any value may use ${NAME}; only that form is expanded, so a literal $ stays as it is. A referenced variable that isn't set stops the server with its name.
  • One license source. license.file or license.data, not both.
  • Fresh installations only. On an installed server the file is ignored.
  • Fails loudly. If a value doesn't work (database, storage, Redis, license), the server stops with an error that says what to fix; nothing is half set up.

4. In containers

docker run --rm \
  -e CONFIG_ENCRYPTION_KEY -e DATABASE_URL -e ADMIN_PASSWORD -e S3_ACCESS_KEY -e S3_SECRET_KEY \
  -e SETUP_CONFIG_FILE=/config/setup.yaml \
  -v "$PWD/setup:/config:ro" \
  -v depotex-data:/app/data \
  -p 8080:8080 \
  <your-registry>/depotex-backend:<version>

Mount the setup file read-only with mode 0600, owned by the server's user (UID 65532 in the image). The /app/data volume keeps the server's bootstrap file, search index and logs: keep it across restarts. With the Helm chart you don't write the file yourself: the chart builds it from its values and the secrets (see Install with Helm).

5. After setup, without the UI

  • Everything in the web app is also an API: GET /api/openapi.json describes every route, its permission and its license tier (see API Tokens → API description). Sign in once as the administrator to create an API token for automation, or register an OAuth application with a service account for machine access.
  • Write the configuration you script (spaces, repositories, upstreams, directories, policies) against that API, so a new installation can be rebuilt the same way.
  • Disaster recovery also works without the UI: ./server --restore-file backup.dxbak checks a backup with no server running, and --yes restores it. See Backups → Disaster recovery.

6. Command-line flags

FlagWhat it does
--setup-config <file>Set up a fresh installation from this file (overrides SETUP_CONFIG_FILE)
--machine-idPrint this machine's installation ID, for a license request, and exit
--restore-file <file>Check a backup archive (.dxbak) with no server running; with --yes, restore it, then exit
--restore-import <name>The same for a file in the backup storage's import folder (backups/import/)
--restore-key-file <file>The key of an encrypted backup: an age identity file, or the passphrase
--restore-sha256 <hex>The SHA-256 the backup must have (from its .sha256 file)
--restore-accept-foreignRestore a backup signed by another installation
--restore-forceRestore although other servers of this installation are running
--yesWith a restore flag: restore (without it only the checks run)