Keep your installation recoverable

Backup and recovery

Save this guide before updating. It is hosted separately from Eugene, so you can read it even when your installation will not start.

Use a stopped-install checkpoint before updating. The checkpoint pairs state with the Python version, resolved packages and exact Eugene source revisions that read it. Installing an older release over newer state is not rollback.

Checkpoints require an A7-capable agent (the quarantine guard introduced in 253f612); the helper refuses older installations. For the first upgrade from an older build, keep a protected, complete cold copy of the stopped installation and its state, including Python and the virtual environment. Restoring that old copy requires its original absolute paths. After upgrading, create and rehearse the portable checkpoint described below. Alpha.1 does not have this tooling or guard; alpha.2 and A7-capable development builds do.

This is a manual recovery procedure. It never updates or starts another enrolled node. Coordinate a maintenance window for the root and workers; a checkpoint cannot include a key revocation or policy change made after it was taken.

What the checkpoint contains

scripts/recovery.py writes format 1 checkpoints. Its authenticated, encrypted manifest inventories each retained file by path, mode and SHA256. File contents are encrypted with independent SecretBox nonces; the manifest authenticates their complete digests, so truncation, reordering and substitution fail verification. The encryption key is derived from a separately chosen backup password using Argon2id. Keep that password separately; it is not recoverable from the backup.

State Treatment
Agent/component configuration, model profiles, Library folders and catalog Retained, including unknown files so an added store is not silently omitted
node.yaml, trust-root snapshot and complete replication log Retained; includes private identities, epochs, signing and recovery keys
Provider/file-server secrets Retained in their existing envelopes inside the encrypted backup; verified unlock passphrases are also encrypted in the manifest
Client-key policies, revocations, admission accounting and gateway policy caches Retained; revoked keys stay revoked at the checkpoint’s point in time
metrics.sqlite3 and related component stores Retained; restored SQLite files pass integrity checks
Managed engine builds under the state directory Retained, including build metadata, binaries and companion libraries
Model files External assets: paths, sizes and SHA256; not copied
venv, pythons, bin Reconstructed from exact Python/package versions and immutable Eugene archive URLs/hashes
logs, .cache, __pycache__ Expendable; excluded
OS Credential Manager/Keychain, service registration, firewall rules, mounts Re-create on the replacement; not portable backup files
Active requests, in-memory cooldowns and operator logout sessions Not restored; clients reconnect and operators sign in again

This procedure supports the standard installer/container state layout: component configurations, control-state, Library state and gateway databases live under the agent configuration directory. Custom store paths supplied only through service environment overrides must be consolidated there first; the backup cannot discover another process’s arbitrary environment. Record the service/container bootstrap settings before stopping it.

The source must use the normal installed packages, not editable development checkouts. Source revisions alone are insufficient because all current component package versions are 0.1.0. The tool requires immutable source URLs and locks every resolved Python dependency. Reconstruction needs network access to Python, PyPI and the recorded GitHub archives; this is not an offline distribution. Restore on the same OS and architecture. Keep compatible OS/GPU drivers and engine system libraries. A different platform is a migration, not this restore procedure.

Stop the agent and its children before backup. --stopped acknowledges that operator step; it does not stop processes for you. The tool checks for changes during copying, but cannot turn a running distributed installation into a consistent snapshot. Do not allow another root or standby to keep writing.

Pass --external PATH for model/projector folders and custom engine bundles outside the state directory. Runtime model paths and explicit binaries are discovered automatically. Keep those assets separately at their recorded paths; restore verifies their hashes. For an externally managed Python engine such as vLLM, preserve its environment and system dependencies separately. A backup of Eugene does not reconstruct an arbitrary external engine environment. Consolidate any component configuration stored outside the state directory before checkpointing; the tool refuses that layout instead of omitting it.

Windows worker

Download scripts/recovery.py from the release or development revision you are using. Keep a trusted copy outside the installation. The saved recover.py is a convenience copy, not a signed executable: if backup storage was tampered with, fetch the helper from trusted source control before entering its password. Use an Administrator PowerShell for service stop and later registration. Example paths below assume the service installation.

$installRoot = 'C:\ProgramData\EugenePlexus'
$backupRoot = 'D:\EugeneBackups\before-update'
Stop-Service EugenePlexusAgent
& "$installRoot\venv\Scripts\python.exe" .\recovery.py backup `
  --root $installRoot --destination $backupRoot --stopped

The command prompts for a backup encryption password and each required agent/control unlock passphrase. It verifies both passphrase hashes and local encrypted envelopes before reporting success. A remembered OS credential alone does not satisfy portable recovery. In unattended jobs, password-file arguments are available; restrict their ACLs and never place their contents on command lines.

The backup directory grants access only to its creator, LocalSystem and local Administrators. Copy the complete directory to protected backup storage. Preserve access restrictions there; encryption also protects files if destination storage does not preserve Windows ACLs. Test the restore before relying on the backup.

Run the normal update only after that checkpoint succeeds. If it fails after stopping the old environment, leave it stopped. Do not repair the old environment in place while depending on it for rollback. Reconstruct into a new directory:

$replacement = 'C:\ProgramData\EugenePlexus-Recovered'
& "$installRoot\venv\Scripts\python.exe" "$backupRoot\recover.py" restore `
  --checkpoint $backupRoot --destination $replacement --uv "$installRoot\bin\uv.exe"

If the failed environment’s Python no longer works, use a separate Python with pyyaml, pynacl and argon2-cffi installed to run the saved recover.py. It uses uv to acquire the exact recorded Python and dependencies. No old virtual environment is copied or relocated: console scripts contain absolute paths.

Restore refuses existing destinations, wrong passwords, missing/changed assets, unsupported formats and different OS/architecture. An interrupted reconstruction leaves only the new destination quarantined; keep it for diagnosis and retry into another empty location. Neither source state nor checkpoint is modified.

The replacement has state\, venv\, pythons\, requirements.lock, recover.py and private recovery.json. The latter contains recovered unlock material; protect the whole directory. Python’s base interpreter is also inside the replacement, so the service does not depend on the restoring operator’s Python cache. The quarantine prevents startup of the copied identity. Fence the original from restarting, then activate:

& "$replacement\venv\Scripts\python.exe" "$replacement\recover.py" activate `
  --destination $replacement --original-stopped
$env:EUGENE_PLEXUS_AGENT_CONFIG_FILE = "$replacement\state\agent.yaml"
$env:EUGENE_PLEXUS_AGENT_ENGINE_ROOT = "$replacement\state\engines"
& "$replacement\venv\Scripts\python.exe" -m eugene_plexus_agent --unattended

Activation validates the exact reconstructed environment and state, then relocates local component configuration paths. It does not rewrite replicated state, identities, URLs or external model paths. Sign in with the original passphrase; check profiles, a previously revoked key, and an actual inference request. Close the foreground process before registering the replacement as a service.

In an elevated shell, set the two bootstrap paths above in Machine environment using [Environment]::SetEnvironmentVariable(name, value, 'Machine'), then run the replacement Python’s -m eugene_plexus_agent.winservice update (or install if the failed update removed registration). Also update the service’s own bootstrap environment; Windows’ service manager may retain old Machine values until reboot. Keep the original bind port (8079 below is the default):

$serviceKey = 'HKLM:\SYSTEM\CurrentControlSet\Services\EugenePlexusAgent'
$bootstrap = @(
  "EUGENE_PLEXUS_AGENT_CONFIG_FILE=$replacement\state\agent.yaml",
  "EUGENE_PLEXUS_AGENT_ENGINE_ROOT=$replacement\state\engines",
  'EUGENE_PLEXUS_AGENT_BIND_PORT=8079'
)
New-ItemProperty -LiteralPath $serviceKey -Name Environment -PropertyType MultiString `
  -Value $bootstrap -Force | Out-Null
Set-Service EugenePlexusAgent -StartupType Automatic
Start-Service EugenePlexusAgent

Preserve any other deliberate bootstrap overrides, including the original Library default model folder when it was supplied through the service environment rather than saved in configuration. Record those before updating. Recreate tray/desktop shortcuts and any required service permissions separately. Sign in once under the restored service so LocalSystem can save its own unlock credential. Network share logins in configuration survive, but share availability and Windows permissions still need checking.

Container control plane

Keep the exact image digest and the Compose/Unraid settings (ports, mounts, uid, secret paths and environment) beside the encrypted checkpoint in protected storage. Pull/save that image before changing it. Do not use edge as a rollback identifier, since it moves. Image rollback must also restore its matching /data.

Stop the original container. Run a disposable helper from the recorded image, mounting the old data directory read-only and a separate backup directory writable. Use its /opt/eugene-plexus/venv/bin/python to run recovery.py backup --root /data --destination /backups/checkpoint --stopped. Mount all referenced external model and engine assets read-only at their original container paths. Supply protected passphrase files or an interactive terminal. uid 10001 must be able to read the source and write the backup parent.

For a restore rehearsal, first reconstruct into a separate data volume using the saved helper and uv. This step needs network access to download the recorded Python and packages; publish no ports and leave the replacement quarantined. Do not start the recovered agent during reconstruction. Then mount that replacement into a container using --network none, with no published ports, for activation and startup checks. Activate only while the original is stopped, or inside this disconnected container. Run the agent with its new state/agent.yaml, set the managed engine root to its restored state/engines, and perform checks inside the container over loopback. A loopback listener alone is not network isolation: an enrolled identity can make outbound announcements.

For production replacement, stop/fence the old container, use the same recorded image and mounts, and point EUGENE_PLEXUS_AGENT_CONFIG_FILE at the restored state/agent.yaml. Recreate the control passphrase secret mount when using passphrase_file; OS keyring credentials do not move between containers. Log in to both agent and control as needed. Start with the original network settings only after ensuring that no second copy of this identity can advertise.

Recovery limits and validation

After recovery verify authentication, profile settings, allowed model policy, local-only policy, revoked-key refusal, engine readiness and an actual completion. A successful HTTP health check alone is insufficient. The checkpoint predates later usage and revocations: reconcile any newer security changes before admitting clients. Restore all relevant nodes from a coordinated checkpoint or explicitly reconcile their epochs/trust state; do not restore an older root beside newer active writers and assume they agree.

Keep the old stopped directory until replacement checks pass. Never delete model folders as part of cleanup. Automatic rollback, automatic service re-registration, offline bundles and cross-platform migration are outside this procedure.