TurboPanel Docs
Database

Storage and secrets

Storage volumes, their copies and mounts, and the sealed secret envelopes.

Tables on this page: copy · mount · secret · storage. Generated from migration 0004_schema_comments; see How to read this.

copy

One physical copy of a storage identity (docker volume or host path today); one primary per storage, local copies pin server_id, remote ones leave it null.

ColumnTypeNullDefaultDescription
id (PK)uuidnouuidv7()Primary key (uuidv7(), time-ordered).
created_attimestamp(3) with time zonenonow()Row creation time.
updated_attimestamp(3) with time zonenonow()Last write time; the ORM sets it to now() on every update.
metadatajsonbyesFree-form jsonb passed through from the copy API; no keys are read by the platform today.
optionsjsonbyesProvider options: compose-registered docker copies carry managed (true when Compose owns the volume) and externalName for external volumes.
storage_iduuidnoFK → storage.id (on delete cascade).
server_iduuidyesFK → server.id (on delete restrict). Host holding a local docker or path copy, unique with storage and provider; null for remote/shared providers; ON DELETE RESTRICT.
secret_iduuidyesFK → secret.id (on delete restrict). Optional provider credential from secret for remote providers; ON DELETE RESTRICT; unused by the docker and path providers.
providertextnodocker or path today; block, nfs, cifs, s3, s3_compatible, sftp, ftp and webdav are reserved and not accepted by the API.
roletextno'primary'primary (one per storage; anchors the access-mode placement check), replica, scratch (never mountable) or archive.
statetextno'pending'Materialization state: pending, materializing, ready, syncing, stale, failed or retiring; set via the API, defaults to pending.
pathtextyesHost filesystem path for a path copy; null means the platform layout or the principal's volumes directory is resolved at deploy and never persisted.
endpointtextyesRemote endpoint for network providers; API passthrough, unused by docker and path copies.
generationintegerno0Reserved generation counter, default 0; no current code path increments it.

Constraints and indexes

  • Index idx_copy_storage_id: (storage_id)
  • Index idx_copy_server_id: (server_id)
  • Index idx_copy_secret_id: (secret_id)
  • Unique index uniq_copy_storage_primary: (storage_id) where "copy"."role" = 'primary'
  • Unique index uniq_copy_storage_server_provider: (storage_id, server_id, provider) where "copy"."server_id" IS NOT NULL
  • Check copy_provider_check: provider IN ('docker', 'path', 'block', 'nfs', 'cifs', 's3', 's3_compatible', 'sftp', 'ftp', 'webdav')
  • Check copy_role_check: role IN ('primary', 'replica', 'scratch', 'archive')
  • Check copy_state_check: state IN ('pending', 'materializing', 'ready', 'syncing', 'stale', 'failed', 'retiring')

mount

Attachment of a storage identity inside one compose service at a container path; unique (service_id, destination_path), written by the storage API and compose.

ColumnTypeNullDefaultDescription
id (PK)uuidnouuidv7()Primary key (uuidv7(), time-ordered).
created_attimestamp(3) with time zonenonow()Row creation time.
updated_attimestamp(3) with time zonenonow()Last write time; the ORM sets it to now() on every update.
metadatajsonbyesFree-form jsonb settable through the mount API; no keys are read by the platform today.
optionsjsonbyesReserved jsonb; no current code path writes it.
storage_iduuidnoFK → storage.id (on delete cascade).
service_iduuidnoFK → service.id (on delete restrict). Consuming compose service; ON DELETE RESTRICT, so compose unregister clears mounts in the same transaction as the service reconcile.
destination_pathtextnoContainer path the storage is mounted at, unique per service.
subpathtextyesOptional subdirectory of the storage to mount instead of its root; forwarded to the daemon when non-empty.
is_read_onlybooleannofalseMount the storage read-only in the container (API field readOnly); default false.

Constraints and indexes

  • Unique uniq_mount_service_destination: (service_id, destination_path)
  • Index idx_mount_storage_id: (storage_id)
  • Index idx_mount_service_id: (service_id)

secret

Org-owned sealed secret for storage providers and git deploy keys; secret_envelope is one tpsecret payload, written today only by the deploy-key route.

ColumnTypeNullDefaultDescription
id (PK)uuidnouuidv7()Primary key (uuidv7(), time-ordered).
created_attimestamp(3) with time zonenonow()Row creation time.
updated_attimestamp(3) with time zonenonow()Last write time; the ORM sets it to now() on every update.
metadatajsonbyesNon-secret descriptors; for git_deploy_key rows: publicKey, fingerprint and keyType (ed25519).
optionsjsonbyesReserved jsonb; no current code path writes it.
organization_iduuidnoFK → organization.id (on delete cascade).
principal_iduuidyesFK → principal.id (on delete set null). Optional association with a principal (SET NULL on delete so a principal delete never fails on an org secret); no current writer sets it.
providertextnos3, s3_compatible, nfs, cifs, sftp, ftp, webdav (reserved storage providers) or git_deploy_key (the only one written today).
nametextnoOperator label for the secret; not an identifier and not unique.
secret_envelopetextnotpsecret envelope of provider-specific JSON; for git_deploy_key the sealed plaintext is the OpenSSH private key verbatim, resealed unopened for the daemon.

Constraints and indexes

  • Index idx_secret_organization_id: (organization_id)
  • Index idx_secret_principal_id: (principal_id)
  • Check secret_provider_check: provider IN ('s3', 's3_compatible', 'nfs', 'cifs', 'sftp', 'ftp', 'webdav', 'git_deploy_key')

storage

Logical identity of persistent data owned by an organization and scoped to at most one of workspace, project, environment or service; bytes live on copy rows.

ColumnTypeNullDefaultDescription
id (PK)uuidnouuidv7()Primary key (uuidv7(), time-ordered).
created_attimestamp(3) with time zonenonow()Row creation time.
updated_attimestamp(3) with time zonenonow()Last write time; the ORM sets it to now() on every update.
metadatajsonbyesFree-form jsonb from the API; dockerVolumeName is stamped to the storage UUID on volume create because the Docker volume name is the storage id.
optionsjsonbyesFree-form jsonb passed through from the storage API; no keys are read by the platform today.
organization_iduuidnoFK → organization.id (on delete cascade). Owning organization stored directly (an intentional exception to derived ownership); cascade-deletes the storage with the org.
workspace_iduuidyesFK → workspace.id (on delete set null). Optional workspace scope, at most one scope column may be set; SET NULL on delete so a retain row survives as org-owned storage.
project_iduuidyesFK → project.id (on delete set null). Optional project scope, at most one scope column may be set; SET NULL on delete so a retain row survives as org-owned storage.
environment_iduuidyesFK → environment.id (on delete set null). Optional environment scope (compose volumes are environment-scoped), at most one scope column set; SET NULL on delete so retain rows survive.
service_iduuidyesFK → service.id (on delete set null). Optional service scope, at most one scope column may be set; SET NULL on delete so a retain row survives as org-owned storage.
kindtextnovolume (named Docker volume), directory, file (sealed content) or object (reserved, not accepted by the API).
namevarchar(255)noOperator label, or the Compose volume key for auto-registered volumes; up to 255 chars with no charset CHECK.
access_modetextno'single_writer'single_writer (default), multi_reader or multi_writer; single_writer refuses a deploy scheduled on a server other than the primary copy's.
retentiontextno'retain'retain (default) keeps the row as org-owned when its scope parent is deleted; delete removes it with the parent.
generationintegerno0Reserved generation counter, default 0; no current code path increments it.
principal_iduuidyesFK → principal.id (on delete set null). Optional owning system principal; path copies without an explicit path resolve under that principal's volumes directory; SET NULL on delete.
content_envelopetextyesSealed file content for kind='file' entries (tpsecret at rest, resealed to tpdaemon at deploy); up to 256 KiB plaintext; null otherwise.
compose_volume_keytextyesCompose top-level volume key for auto-registered volume rows; unique per environment and the idempotency key for compose volume registration.

Constraints and indexes

  • Index idx_storage_organization_id: (organization_id)
  • Index idx_storage_workspace_id: (workspace_id)
  • Index idx_storage_project_id: (project_id)
  • Index idx_storage_environment_id: (environment_id)
  • Index idx_storage_service_id: (service_id)
  • Index idx_storage_principal_id: (principal_id)
  • Unique index uniq_storage_environment_compose_volume_key: (environment_id, compose_volume_key) where kind = 'volume' AND environment_id IS NOT NULL AND compose_volume_key IS NOT NULL
  • Check storage_kind_check: kind IN ('volume', 'directory', 'file', 'object')
  • Check storage_access_mode_check: access_mode IN ('single_writer', 'multi_reader', 'multi_writer')
  • Check storage_retention_check: retention IN ('retain', 'delete')
  • Check storage_at_most_one_parent_check: ((workspace_id IS NOT NULL)::int + (project_id IS NOT NULL)::int + (environment_id IS NOT NULL)::int + (service_id IS NOT NULL)::int) <= 1
Edit on GitHub

Last updated on

On this page