Skip to content

v1.3.26 -- Deploy automation (sync-prod + Makefile)

A focused single-bug release. Closes the deploy gap that v1.3.25 prod-smoke caught: the homelab dual-dir pattern (git checkout in ~/argos-edge/, operational dir in ~/argos-prod/) had no automated sync, so any release that changed crowdsec/setup-appsec.sh or Caddyfile was invisible to the running stack until the operator manually copied files between the two dirs.

The gap was real (caught mid-v1.3.25 deploy: the operational setup-appsec.sh was still pre-v1.3.19-strip while the panel image was at v1.3.25) and undocumented. v1.3.26 fixes it forward.

What ships

scripts/sync-prod.sh

rsync -a --delete from the source checkout to the operational dir, with an explicit denylist for operator- managed files + build outputs + secrets:

Excluded Why
docker-compose.override.yml Operator-managed (image pin + ports + container names)
.env, .env.local Secrets (master key, admin pass, bouncer key)
data/, backups/ Volume / data dirs
.git/, .gitignore VCS state
node_modules/, dist/, frontend/dist/, frontend/.vite/, backend/static/assets/, site/ Build outputs / caches
*.tar.gz Tarballs (phase 0 archive etc.)
.claude/, .vscode/, .idea/, .DS_Store, *.swp, *~ Editor / agent / OS noise

Everything else mirrors. Argos-shipped files including crowdsec/config.yaml.local (CrowdSec-convention .local override that argos owns directly) propagate.

The script:

  • Diff-first preview: prints itemized changes via rsync --dry-run --itemize-changes before any write. Operator sees exactly what will change.
  • Idempotent: a no-change run prints "no changes" and exits 0 without invoking rsync's apply path.
  • Refuses to run with clear errors when:
  • ARGOS_PROD_DIR doesn't exist (no auto-creation).
  • DST doesn't look like an argos checkout (no top-level docker-compose.yml).
  • SRC and DST resolve to the same path.
  • Stdin isn't a TTY and --yes wasn't passed.
  • rsync isn't installed.
  • Interactive by default: prompts for confirmation; --yes skips for the deploy-prod target + CI.
  • --dry-run mode for preview-only.

Makefile

Three operator-facing targets:

make sync-prod          rsync with interactive confirm
make sync-prod-dry      preview only (--dry-run)
make deploy-prod        sync (auto-yes) + docker compose build + up
make verify-prod        run scenarios + appsec smokes
make smoke-self         run sync-prod self-smoke against tmp dirs

make help prints the full list. ARGOS_PROD_DIR env var overrides the default ~/argos-prod.

scripts/smoke/sync-prod.sh

Self-smoke for sync-prod itself. Builds ephemeral fake repos in mktemp -d directories and exercises five gates:

  1. Refuses invalid paths with clear errors.
  2. No-op when SRC + DST are byte-identical.
  3. Drift detection: new file in SRC propagates on apply.
  4. Operator-managed files (docker-compose.override.yml, .env) survive a sync from a SRC that doesn't have them.
  5. Excludes work: frontend/dist/, backend/static/assets/, .git/, data/, node_modules/ in SRC don't land in DST.

Runs against tmp dirs only -- never touches a real operational dir, so it's safe to run on any host with a checkout of argos-edge.

docs/operations/deployment.md

New page covering both the single-dir simple case and the dual-dir homelab pattern. Documents the sync semantics, the denylist, the refuse-to-run conditions, the recovery path (diff -rq), and the release-note checklist for changes that touch bind mounts.

Linked from the v1.3.25 upgrade section + the new v1.3.26 release notes. Future releases that change crowdsec/* or Caddyfile should reference it.

Why this is a separate release

This is purely operator tooling -- zero backend code changes, zero frontend code changes, zero migration. The current panel image (v1.3.25) is unaffected.

Splitting it into v1.3.26 keeps the v1.3.25 retrospective clean: v1.3.25 was the feature work (Scenarios + AppSec UI); v1.3.26 is the deploy-tooling fix that retroactively prevents a v1.3.25-class deploy gap from recurring.

Smoke

The v1.3.26 smoke gate runs against tmp dirs (the self-smoke) plus a real make sync-prod-dry against the operator's actual dual-dir setup to confirm the rsync preview matches reality:

  1. Self-smoke: make smoke-self runs the 5 sync-prod gates green.
  2. Real preview: make sync-prod-dry against the homelab's ~/argos-edge -> ~/argos-prod shows the expected file-set diff (post-v1.3.25 work syncing to a pre-v1.3.25 operational dir).
  3. Real apply (after preview review): make sync-prod propagates the diff. Subsequent make sync-prod-dry reports no changes.
  4. Deploy idempotent: make deploy-prod against a freshly-synced operational dir runs sync (no-op) + docker compose build (cached) + up (no-op container state) without errors.

NO tag until smoke real PASSes.

Files added

  • scripts/sync-prod.sh (new)
  • scripts/smoke/sync-prod.sh (new) -- self-smoke
  • Makefile (new) -- top-level operator targets
  • docs/operations/deployment.md (new)
  • docs/release-notes/v1.3.26.md (this file)
  • CHANGELOG.md, mkdocs.yml, version bump

Upgrade

cd ~/argos-edge
git pull
make sync-prod          # first time: shows the v1.3.25-era
                        # drift; review + confirm
make deploy-prod        # subsequent releases: one command

The first make sync-prod after upgrading to v1.3.26 will show every drift between your source checkout and your operational dir as one big diff. That's the catchup; future releases produce small diffs.

Not changed

  • All 7 v1.3.23 + 6 v1.3.25 /api/security/* endpoints unchanged.
  • Migration 030 still latest.
  • Panel image, Caddyfile contents, crowdsec config -- all v1.3.25.