TazPod: Sync Daemon Detail
Level 3 (Detail) — Background auto-save and push cycle.
Concept
The sync daemon runs as __internal_sync_daemon — a background process spawned by tazpod up. Every 5 minutes it saves the RAM vault to disk and pushes the encrypted archive to S3.
Startup
File: cmd/tazpod/lifecycle.go — up() (line 14)
exec.Command("tazpod", "__internal_sync_daemon").Start()
Spawned as a detached process by up(). The daemon shares the same tazpod binary and the same config.
Cycle
File: cmd/tazpod/sync.go — syncDaemon() (lines 14-56)
[Start] ──► log: /tmp/tazpod-sync.log ──► ticker: 5 min
│
┌─────────┴──────────┐
▼ ▼
vault unlocked? skip cycle
│
▼
vault.Save("") ──► re-encrypt RAM to disk
│
▼
pushVaultInternal() ──► upload to S3
│
▼
log result ──► wait 5 min ──► loop
Unlock detection
func isVaultUnlocked() bool {
if !utils.IsMounted(vault.MountPath) { return false }
_, err := os.Stat(vault.PassCache)
return err == nil
}
Checks both that the tmpfs is mounted AND that the passphrase cache file exists. If the vault is locked, the daemon logs a skip and continues.
Graceful Shutdown
The daemon uses signal.NotifyContext for SIGTERM and SIGINT:
ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGTERM, syscall.SIGINT)
On signal, the current cycle completes and the daemon exits cleanly.
Log Path
/tmp/tazpod-sync.log
Uses slog with a text handler writing to the log file. Each cycle logs:
- “Starting sync cycle”
- On success: “Sync completed” with elapsed time
- On failure: “Sync failed” with error
No History From Daemon
Il daemon sincronizza solo il latest vault.tar.aes. Le history copies su S3 sono create solo dal comando manuale tazpod push vault. Il daemon non ha accesso al content hash del plaintext e non produce versioni storiche.
Failure Model
- If S3 upload fails → error is logged, daemon continues
- If local save fails → error is logged, daemon continues
- The vault on local disk is always refreshed before the S3 push
- Local safety is preserved even if remote sync is broken
Code Paths
| File | Function | Line | Role |
|---|---|---|---|
lifecycle.go | up() | 14 | Spawns daemon process |
sync.go | syncDaemon() | 14 | Main loop, logging, ticker |
sync.go | isVaultUnlocked() | 58 | Unlock detection |
sync.go | pushVaultInternal() | 119 | S3 upload |
Known Issues
- TD-022:
pushVaultInternal()resolves vault path from cwd, not from canonical workspace root
See Also
- Parent hub: tazpod
- Sibling details: Vault Lifecycle Detail, S3 Detail
- Topic: Sync Daemon
- Debt: TD-022