Commit Graph
363 Commits
Author SHA1 Message Date
1ad36a83fb feat: Add pluggable secret providers (1Password, Infisical, HashiCorp Vault) (#1360)
* Add pluggable secret provider foundation

Introduces a provider-agnostic secret backend abstraction so stacks can
pull deploy-time secrets from 1Password, Infisical or HashiCorp Vault.

Providers implement the SecretProvider contract in secretproviders/shared.ts
and advertise which of the two resolution modes they support:

  - reference interpolation: a variable's value is an inline reference in
    the backend's own syntax (e.g. 1Password's op://vault/item/field)
  - bulk pull: every secret under a provider-defined selector, fetched as
    a flat key/value map

Adding a backend means dropping a file in secretproviders/ and registering
it in the index; no caller changes.

Four providers ship here: 1Password service account (references + bulk),
1Password Connect (references), Infisical (bulk) and HashiCorp Vault KV v2
(bulk). Provider config is persisted as an encrypted JSON blob in the new
secret_providers table, mirroring the existing notification_settings
type+config pattern, and stack_sources gains a nullable secret_provider_id.

Decrypted tokens stay in the provider modules for the duration of a call
and are never written to disk or returned to the client.

Co-authored-by: GooRoo <sergey.olendarenko@gmail.com>

* Add secret provider API routes and permissions

CRUD plus two test-connection endpoints under /api/secret-providers. The
unsaved variant validates a config posted from the provider form; the
stored variant tests a persisted provider by id.

Responses only ever carry provider summaries (id, type, name, timestamps).
The decrypted config never leaves the server.

Adds a "secrets" permission resource with view/create/edit/delete actions,
wired through the permission type, the role editor and the seeded roles,
and a secret_provider audit entity type so provider changes are logged.
Config rotations are audited as a boolean rather than a value.

* Resolve provider secrets at stack deploy time

Stacks can bind a secret provider; when one is bound, its secrets are
resolved and merged into the vars handed to docker compose.

Bulk pull is triggered by a selector variable: OP_ENVIRONMENT_ID, kept for
compatibility with the original 1Password integration, or the generic
DOCKHAND_SECRET_SELECTOR for any bulk-capable provider. The selector is
consumed by the provider and stripped before the vars reach the stack.
Values the bound provider recognises as inline references are resolved in
place, and references found only in the stack's .env file are promoted into
the secret set so they are never written back as literals.

Resolution is applied on deploy, on up, on recreate and on service update.
Explicitly configured secrets always win over bulk-pulled ones. A missing
or unsupported provider warns and leaves values untouched rather than
failing the deploy; a provider that errors mid-resolution fails it.

* Add secret provider settings UI and stack binding

A Secrets tab under settings lists configured providers and drives the
create/edit modal, which switches its fields on the selected provider type
and can test a connection before saving.

Both stack modals gain a provider selector so a stack can be bound to a
provider or left unbound. When a provider is bound, the bulk selector
variables are no longer reported as unused compose variables, since they
are consumed by the provider rather than the compose file.

---------

Co-authored-by: GooRoo <sergey.olendarenko@gmail.com>
Co-authored-by: Jarek Krochmalski <jotka@users.noreply.github.com>
2026-08-13 10:08:02 +02:00
jarek 905c4a004d persist restic cache and backup restore fixes 2026-08-09 13:46:03 +02:00
jarek 091adfca35 remove backup journal, stop-recovery, and verify modal (deleted upstream) 2026-08-09 10:35:15 +02:00
jarek da8c83e20e internal cleanups and build config 2026-08-09 10:31:28 +02:00
jarek 95ee76bf97 backup engine internals - streaming, timeouts, typed snapshot layout, volume keys, route guards 2026-08-09 10:31:28 +02:00
jarek c33c404259 reusable snapshot header, field-label, and load-progress UI components 2026-08-09 10:31:28 +02:00
jarek 16451d95d7 improved restic repository operations log (prune, check, repair index etc.) 2026-08-09 10:31:28 +02:00
jarek 89b260758e more room between settings/editor content and the scrollbar 2026-08-09 10:31:28 +02:00
jarek dab6797847 dashboard pending-update count now matches the containers list 2026-08-09 10:31:28 +02:00
jarek 3859888da6 deleting a stack shows which folders will be removed, with a choice to keep/delete folders 2026-08-09 10:31:28 +02:00
jarek 4375f42415 oidc login: fall back to trailing-slash discovery url 2026-08-09 10:31:28 +02:00
jarek 045adf0cf3 fixed an LDAP filter parsing issue that could break group-based role assignment with some AD DNs 2026-08-09 10:31:28 +02:00
jarek 4e15c2677c dedupe duplicate mount points when recreating a container 2026-08-09 10:31:28 +02:00
jarek d33185d1fa container updates respect the new image's command/entrypoint 2026-08-09 10:31:28 +02:00
jarek 1c1d7979d7 activity log times now honor the configured timezone 2026-08-09 10:31:27 +02:00
jarek 8f47eef1b7 GitLab and Harbor registries no longer report a misleading auth error when browsing 2026-08-09 10:31:27 +02:00
jarek b287cee31f registry browser shows tag size and date for self-hosted registries, loaded on expand 2026-08-09 10:31:27 +02:00
jarek 5f8fc71c73 backup volume picker shows every bind mount when two containers share a container path 2026-08-09 10:31:27 +02:00
jarek 7bb688197a Google Cloud backup destinations now use a service-account JSON key 2026-08-09 10:31:27 +02:00
jarek 019bea222e S3 backup destinations take an AWS region with a region quick-pick 2026-08-09 10:31:27 +02:00
jarek 3d1b383ad7 snapshots from another Dockhand instance sharing the repo now appear as restorable orphans 2026-08-09 10:31:27 +02:00
jarek 5adac5e19e a stack restored to new locations always keeps its compose file and stays internal 2026-08-09 10:31:27 +02:00
jarek bd06b340c5 direct remote environments - remote stacks dir configurable, for putting the whole stack onto the remote 2026-08-09 10:31:27 +02:00
jarek 86ef3f743b configurable default homepage 2026-08-09 10:31:27 +02:00
jarek 1cec7d0814 release housekeeping 2026-08-09 10:31:27 +02:00
jarek a115a5f539 release housekeeping for 1.0.40 2026-07-31 10:10:56 +02:00
jarek 188331a398 bump docker-compose to 5.3.1-r3 2026-07-31 10:10:56 +02:00
jarek 31e19b57b5 center container, stack, image and network modals with consistent margins 2026-07-31 10:10:56 +02:00
jarek 766a206055 header clock falls back to the default timezone instead of utc 2026-07-31 10:10:56 +02:00
jarek 2532c69d4a default pangolin public urls to https from the ssl label 2026-07-31 10:10:56 +02:00
jarek 6a6e82a481 reach own docker daemon over tcp on socket-proxy setups; re-run host detection when an environment is added or edited; keep scanner on the host socket 2026-07-31 10:10:56 +02:00
jarek 0a9d4ad10f validate git repo urls and refs, require a secret for webhook triggers, tidy internal endpoint comments 2026-07-31 10:10:56 +02:00
jarek c18ee21a66 git stack source badge with forge-aware icons and commit hash 2026-07-31 10:10:56 +02:00
jarek 9bc4eaa47b small ui polish: loading state, relative timestamps, log-marker formatting, wider tooltips, type tidy-ups 2026-07-31 10:10:55 +02:00
jarek 8a32bc377d backups ui: group repo snapshots in a datagrid, gate cancel when unstoppable, relative timestamps 2026-07-31 10:10:55 +02:00
jarek e3c07f32da backup engine fixes: shared-repo unlock, non-root uid reads, lock release, local-path repo, backblaze key id 2026-07-31 10:10:55 +02:00
jarek e700b5b6aa restore reproduces the stack as an internal stack with its secrets 2026-07-31 10:10:55 +02:00
jarek 25f10616a5 exclude docker sockets and host system paths from volume backups 2026-07-31 10:10:55 +02:00
Björn Strausmann 36dac8b030 refactor(stacks): plumb sourceType through requireComposeFile to avoid redundant lookup
startStack, restartStack, stopStack, and downStack each ran a separate
getStackSource query just to determine isGitStack for useOverrideFile,
even though requireComposeFile -> getStackComposeFile already looks up
the same stack_sources record.

Return sourceType from getStackComposeFile (GetComposeFileResult) and
requireComposeFile (RequireComposeResult), and have all four callers
read result.sourceType instead of querying the database again. No
behavior change: useOverrideFile is still set to true exactly when the
stack's source type is 'git'.
2026-07-31 04:58:47 +02:00
Björn Strausmann 144a73a10a fix(stacks): apply env override file on stop/down for git stacks (#1313)
startStack and restartStack compute isGitStack and pass useOverrideFile
accordingly, so executeLocalCompose writes .env.dockhand with the DB
non-secret overrides before invoking docker compose. stopStack and
downStack never set this option, so whenever a .env file exists in the
stack's working directory (e.g. committed alongside compose.yaml in a
git stack), the legacy shell-env fallback in executeLocalCompose is
suppressed and .env.dockhand is never written or attached via
--env-file. Any required variable that only exists as a Dockhand panel
override then fails interpolation on stop/down, even though the same
stack deploys and starts successfully.

Mirror startStack/restartStack: compute isGitStack from the stack
source and pass useOverrideFile through in both operations.
2026-07-31 04:58:47 +02:00
Solaris-star f24f42116e fix(environments): allow deleting disconnected environments
Signed-off-by: Solaris-star <820622658@qq.com>
2026-07-29 10:49:53 +02:00
BrX 0b6305ba2c fix: remove duplicate native title from Git badge tooltip
The badge inside Tooltip.Trigger had both a native title attribute
and Tooltip.Content with the same commit info, causing two overlapping
tooltips. Remove the title; keep Tooltip.Content as the sole tooltip.
The fallback branch (no commit hash) retains its title attribute.
2026-07-27 18:09:18 +02:00
BrX a7e457bdb4 feat: display last commit hash in Git source badge
Show the short commit hash next to 'Git' in the stack source column.
When a commit hash is available, the badge reads 'Git abc1234' with
a tooltip showing the full hash, repo URL, and branch. Falls back
to the original 'Git' label when no commit is recorded yet (e.g.
before first deploy).
2026-07-27 18:09:18 +02:00
jarek 49809865dc 1.0.39 2026-07-26 10:27:12 +02:00
jarek 123e04d17f 1.0.38 2026-07-25 08:45:12 +02:00
jarek 64b6dcd744 1.0.38 2026-07-25 08:41:01 +02:00
Nenad StojanovikjandCursor 9f09d60a83 Allow viewing Git stack YAML
Open Git-sourced stack compose files in a read-only editor and graph while keeping repository settings separate.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-21 05:49:51 +02:00
jarek c718ac9a84 1.0.37 2026-07-11 15:31:52 +02:00
jarek 685132ff89 1.0.36 2026-06-27 15:15:54 +02:00
jarek ce12d7ae9f 1.0.35 2026-06-19 08:21:22 +02:00