Backup & Upgrade
Data persistence, backup and restore procedures, upgrading Sophon, and rollback.
What's Stored Where
| Data | Location | Tier |
|---|---|---|
| Configuration, agents, skills, memory, documents, logs | SOPHON_DATA (host bind mount) | All |
Encryption key (vault.key) | SOPHON_DATA/security/vault.key | All |
| SQLite database | SOPHON_DATA/data/sophon.db | Personal |
| PostgreSQL data | pgdata named volume | Pro, Enterprise |
| Qdrant vector data | qdrantdata named volume | Pro, Enterprise |
| Redis data | redisdata named volume | Enterprise |
| RabbitMQ data | rabbitmqdata named volume | Enterprise |
Backup
Sophon Data Directory
The most important backup — contains your configuration, agents, skills, documents, memory, and encryption keys.
# Stop Sophon (optional but recommended for consistency)
docker compose down
# Create a timestamped backup
tar czf sophon-backup-$(date +%Y%m%d).tar.gz -C "$SOPHON_DATA" .PostgreSQL (Pro/Enterprise)
# While running
docker compose exec postgres pg_dump -U sophon sophon \
> sophon-db-$(date +%Y%m%d).sql
# Or with compression
docker compose exec postgres pg_dump -U sophon -Fc sophon \
> sophon-db-$(date +%Y%m%d).dumpQdrant (Pro/Enterprise)
# Create a collection snapshot
curl -X POST http://localhost:6333/collections/sophon/snapshotsSnapshots are stored inside the qdrantdata volume. Copy them to your backup location.
Redis (Enterprise)
Redis with --appendonly yes persists to disk automatically. The data lives in the redisdata named volume. To back up:
# Trigger a save
docker compose exec redis redis-cli -a "$REDIS_PASSWORD" BGSAVE
# Copy the volume data
docker run --rm -v sophon_redisdata:/data -v $(pwd):/backup \
alpine tar czf /backup/redis-backup-$(date +%Y%m%d).tar.gz -C /data .Restore
Sophon Data Directory
# Stop Sophon
docker compose down
# Restore from backup
mkdir -p "$SOPHON_DATA"
tar xzf sophon-backup-20260324.tar.gz -C "$SOPHON_DATA"
# Restart
docker compose up -dPostgreSQL
# From SQL dump
docker compose exec -T postgres psql -U sophon sophon \
< sophon-db-20260324.sql
# From compressed dump
docker compose exec -T postgres pg_restore -U sophon -d sophon \
< sophon-db-20260324.dumpQdrant
Restore from the Qdrant snapshot API:
curl -X PUT "http://localhost:6333/collections/sophon/snapshots/recover" \
-H "Content-Type: application/json" \
-d '{"location": "file:///qdrant/storage/snapshots/sophon/<snapshot-name>.snapshot"}'The vault.key File
The file at SOPHON_DATA/security/vault.key contains the AES-256 encryption key used to encrypt all credentials at rest — API keys in models.json, channel tokens in channels.json, and speech-provider keys.
If you lose this file, all encrypted credentials become unrecoverable. You would need to re-enter every API key and re-authenticate every channel.
Always verify vault.key is included in your backups:
# Verify it exists in a backup archive
tar tzf sophon-backup-20260324.tar.gz | grep vault.keyUpgrading
Upgrading to v2.0.0
Back up first. The first time the v2.0.0 Gateway starts, it applies five new database migrations automatically. There is no automatic downgrade path: going back to 1.15 means restoring the backup you took before upgrading. Stop the Gateway, then back up the data directory (and, on Pro and Enterprise, the PostgreSQL database) using the Backup steps above.
On Docker, change both image tags in your compose file to 2.0.0 (images are published with exact version tags only), then follow Pull and Restart.
Data and backups
- Five migrations, applied on first start. They add storage for Sophon Graph runs, plan revisions and approval escalation, and give every conversation event a unique sequence number. If an earlier version wrote two events in one conversation with the same number, the migration renumbers the duplicates and moves them after that conversation's last event, so they appear at the end of its history. No events are removed.
- SQLite now uses write-ahead logging (Personal tier). While the Gateway runs,
sophon.db-walandsophon.db-shmmay appear next todata/sophon.db, and recent writes can sit in the-walfile until they're merged into the database. Stop the Gateway before you copy the database by hand, and keep the side files with it if they're present. Thetarcommand under Backup copies the whole data directory, so it already includes them. WAL mode is stored in the database file itself.
Behavior changes
-
Sophon Graph is on by default. Approved multi-step plans now run in Graph mode, including plans made by scheduled, heartbeat and webhook runs. To use Classic, the previous step-by-step engine:
- One conversation: the execution-mode pill in the Dashboard chat composer, or
/mode classicin the CLI (/mode defaultreturns to your default). - Your default: Settings → Execution → Execution mode.
- Everyone (admin): switch off Enabled under Settings → Execution → Graph runtime, or set
Sophon:GraphRuntime:Enabledtofalseinconfig/appsettings.user.json(environment variableSOPHON__GraphRuntime__Enabled=false). This puts every user on Classic.
Graph supports a single Gateway instance, so turn it off if you run more than one Gateway replica. Dependent sub-agent tasks also need Graph: with it off, they fail with a clear error instead of running out of order.
- One conversation: the execution-mode pill in the Dashboard chat composer, or
-
The CLI opens full screen.
sophonnow starts the full-screen chat, and its first run tells you how to switch back. Opt out for one session withSOPHON_CLI_FULLSCREEN=0 sophon, or for good with"fullScreen": falsein~/.sophon/config/cli.json. Small windows, redirected output, the Dashboard's built-in terminal and an active Windows screen reader fall back automatically; if a terminal can't switch to full screen, the CLI tells you to re-run withSOPHON_CLI_FULLSCREEN=0. In the full-screen chat a newline is Alt+Enter, not Shift+Enter. If a terminal is left in a bad state, runsophon doctor --reset-terminal. See Interactive chat. -
Prompt-injection detection defaults to Warn. In 1.15 it only annotated and logged. It now has three modes: Off, Warn (the default) and Block. In Warn, a detection shows as a notice card in the conversation and is written to the audit log; Block is opt-in. An admin changes the mode in the Dashboard under Settings → Security, or with
Sophon:PromptInjection:Mode. If you had turned detection off (Sophon:PromptInjection:EnabledorDetectionEnabledset tofalse), it stays off. The guard matches known phrasing and is not a security boundary. See Prompt injection. -
Spending budgets may trigger sooner. Usage of models newly added to the catalog used to be recorded at $0. It now carries an estimated cost based on list prices, so spending budgets count it and may trigger where they did not before. Review your budget limits if you use those models.
-
Marketplace automatic updates are new and off by default. Nothing changes until an admin turns on Settings → Marketplace → Automatic updates (
Sophon:Marketplace:AutoUpdate). When on, the regular update check also installs new versions through the verified install path and rolls back a failed update.
Integrations and APIs
- Session list.
GET /api/sessionsnow returns top-level conversations only (view=topis the default), hiding plan-step and sub-agent sessions. Passview=allfor the previous flat list, orview=children&parentId=<id>for one conversation's agent activity. The realtime session list uses the same default. - Deciding approvals.
POST /api/approvals/{id}/decidenow accepts onlyapproved,rejected,editedortimed_out(any casing); any other value returns400with the list of allowed values. Deciding an approval that already has an outcome no longer overwrites it: the response is200with the recorded outcome andalreadyDecided: true. An approval whose caller cancels the wait is now recorded ascancelledrather thantimed_out. Sender approvals are unchanged. - Node voice routes.
/api/nodes/me/voice/runtime,/stateand/wakereturn404until you setSophon:Voice:NodeWake:Enabledtotrue. No shipped client calls them, so most installs see no change. When enabled,/wakerequires the node's voice permission, is rate-limited per node, and rejects over-long transcripts. - Custom SignalR clients.
VoiceStatusis no longer sent when a speech-to-text stream opens; it now only means the reply finished. Transcript events carryutteranceId, andVoiceUtteranceStarted {sessionId, utteranceId}announces each utterance, so a client can accept a final transcript only for the utterance most recently announced to it (a client that ignores the event keeps working).ApprovalResolved {id, outcome, sessionId, escalationSessionId}is broadcast on/hubs/chatwith outcomesapproved,rejected,timed_outorcancelled,InfoRequestAnsweredgainscancelled: true, andStreamAudioaccepts a third mode value,"answer", which transcribes without starting an agent turn. See SignalR events. - Paired devices. The agent can reach only devices owned by the requesting user; launching, closing or focusing an app now asks for approval; the ungated single-command passthrough tool is gone; and desktop command results use camelCase field names, with the app-launch parameter named
name. See Node protocol.
Skills and developer tools
proxycredentials. Skills whose manifest declares the deprecated"access": "proxy"credential mode now receive the stored credential inside their sandbox, exactly like"injected". In 1.15 they received nothing, so those skills didn't work. Brokered proxy calls are not implemented. Before upgrading, check which installed skills declare credentials. See Credential vault.sophon devexit codes. Failingsophon devcommands now exit non-zero, so scripts and CI no longer treat a broken project as a success.sophon dev validatealso now fails when an entry point's source file is missing (a missing.csfile used to be only a warning).
Upgrading to v1.15.0
Upgrading to v1.15.0: this release ships 8 new database migrations that are applied automatically the first time the upgraded Gateway starts. Migrations are one-way — take a backup of the data directory and database first, using the Backup steps above. Once you're on 1.15, you can also create data-directory backups from the Dashboard at Settings → Backup (see Backup & Export).
Pull and Restart
# Pull the image tags pinned in your compose file
docker compose pull
# Restart with new images
docker compose up -dEF Core database migrations run automatically on startup. No manual migration step is needed.
Upgrade Checklist
- Back up your data directory and database (see above)
- Pull the pinned image tags
- Restart the services
- Verify the health check passes:
curl http://localhost:8081/api/health - Check logs for migration errors:
docker compose logs sophon-gateway
Pinning a Version
To avoid unexpected upgrades, pin a specific image tag:
services:
sophon-gateway:
image: buildersoftdev/sophon:2.0.0
sophon-dashboard:
image: buildersoftdev/sophon-dashboard:2.0.0Rollback
If an upgrade causes issues:
- Stop the services:
docker compose down - Restore from your backup (data directory + database)
- Pin the previous image tag in your compose file
- Restart:
docker compose up -d
# Example: rollback to 1.1.0
docker compose down
# Restore data
tar xzf sophon-backup-20260324.tar.gz -C "$SOPHON_DATA"
# Restore database (Pro/Enterprise)
docker compose up -d postgres
docker compose exec -T postgres psql -U sophon sophon < sophon-db-20260324.sql
# Update compose to pin old version
# image: buildersoftdev/sophon:1.1.0
docker compose up -d