Description
When ds2api is configured via the DS2API_CONFIG_JSON environment variable (base64-encoded config), accounts added dynamically through the Admin WebUI are not persisted and are lost upon container restart.
Root Cause
In internal/config/store.go, the saveLocked() method explicitly skips writing to disk when fromEnv is true:
func (s *Store) saveLocked() error {
if s.fromEnv {
Logger.Info("[save_config] source from env, skip write")
return nil // ← all dynamic changes are silently discarded
}
// ... write to file
}
When DS2API_CONFIG_JSON is set, fromEnv is always true (set in loadConfig() at line 45), so any accounts added via the Admin UI only exist in memory and are lost on restart.
Steps to Reproduce
- Deploy ds2api with
DS2API_CONFIG_JSON env var containing 1 account
- Open Admin UI, add 3 more accounts via the web interface
- Verify all 4 accounts are working (
/admin/accounts shows 4)
- Restart the container (
docker compose restart)
- Check accounts again — only the original 1 account from the env var remains
Expected Behavior
Either:
- Option A: Dynamically added accounts should be synced back to a persistent store (e.g., write to
config.json even in env mode, or sync env var)
- Option B: The Admin UI should clearly warn users that changes will not survive a restart when running in env-backed mode (currently
config_writable: false is returned but the UI still allows adding accounts without warning)
Current Workaround
Switch from DS2API_CONFIG_JSON env var to mounting a config.json file via Docker volume:
volumes:
- ./config.json:/app/config.json
And remove DS2API_CONFIG_JSON from the .env file. This enables fromEnv=false and allows the store to persist changes to disk.
Environment
- ds2api version: v2.5.1
- Deployment: Docker (self-hosted)
Description
When ds2api is configured via the
DS2API_CONFIG_JSONenvironment variable (base64-encoded config), accounts added dynamically through the Admin WebUI are not persisted and are lost upon container restart.Root Cause
In
internal/config/store.go, thesaveLocked()method explicitly skips writing to disk whenfromEnvistrue:When
DS2API_CONFIG_JSONis set,fromEnvis alwaystrue(set inloadConfig()at line 45), so any accounts added via the Admin UI only exist in memory and are lost on restart.Steps to Reproduce
DS2API_CONFIG_JSONenv var containing 1 account/admin/accountsshows 4)docker compose restart)Expected Behavior
Either:
config.jsoneven in env mode, or sync env var)config_writable: falseis returned but the UI still allows adding accounts without warning)Current Workaround
Switch from
DS2API_CONFIG_JSONenv var to mounting aconfig.jsonfile via Docker volume:And remove
DS2API_CONFIG_JSONfrom the.envfile. This enablesfromEnv=falseand allows the store to persist changes to disk.Environment