[GH-ISSUE #267] Env config loader wipes backup/force-push settings on every restart #1230

Closed
opened 2026-04-21 23:14:05 -05:00 by GiteaMirror · 1 comment
Owner

Originally created by @tiennm99 on GitHub (Apr 14, 2026).
Original GitHub issue: https://github.com/RayLabsHQ/gitea-mirror/issues/267

Originally assigned to: @arunavo4 on GitHub.

Bug

The environment config loader (src/lib/env-config-loader.ts) overwrites the entire giteaConfig JSON column on every restart, but does not include any backup-related fields. This silently erases user-configured backup settings.

Affected Fields

  • backupStrategy
  • backupBeforeSync
  • backupRetentionCount
  • backupRetentionDays
  • backupDirectory
  • blockSyncOnBackupFailure

Root Cause

env-config-loader.ts:279-311 builds the giteaConfig object without backup fields. Then at line 360, the entire column is replaced:

await db.update(configs).set({
  giteaConfig,   // replaces the whole JSON column — backup fields vanish
  ...
});

Other fields (like lfs, wiki, visibility) are preserved because they have ?? existingConfig fallbacks in the builder. Backup fields were added later (v3.11.0) but never added to the env loader.

Impact

  1. UI settings don't persist — user changes backup strategy in UI → restarts → reverts to default "on-force-push" (via mapDbToUiConfig fallback)
  2. No env var supportPRE_SYNC_BACKUP_STRATEGY env var works at runtime but is never persisted to DB or shown in UI
  3. UI/runtime mismatch — UI always shows "on-force-push" regardless of actual runtime behavior

Reproduction

  1. Set GITEA_URL, GITEA_TOKEN etc. as env vars (triggers hasEnvConfig() → true)
  2. Start app, go to Settings → change backup strategy to e.g. "Always Backup"
  3. Save successfully
  4. Restart the app
  5. Settings page shows "Smart (on-force-push)" again — the saved value is gone

Workaround

Set PRE_SYNC_BACKUP_STRATEGY env var (e.g. disabled, always, on-force-push, block-on-force-push). This is read at sync time by resolveBackupStrategy() in repo-backup.ts and takes effect because the DB field is empty. However, the UI will not reflect this value.

Suggested Fix

Add backup fields to the env loader's giteaConfig builder with ?? existingConfig fallbacks, consistent with how other fields are handled:

// In env-config-loader.ts giteaConfig builder:
backupStrategy: existingConfig?.[0]?.giteaConfig?.backupStrategy ?? "on-force-push",
backupBeforeSync: existingConfig?.[0]?.giteaConfig?.backupBeforeSync ?? true,
backupRetentionCount: existingConfig?.[0]?.giteaConfig?.backupRetentionCount ?? 5,
backupRetentionDays: existingConfig?.[0]?.giteaConfig?.backupRetentionDays ?? 30,
backupDirectory: existingConfig?.[0]?.giteaConfig?.backupDirectory ?? "data/repo-backups",
blockSyncOnBackupFailure: existingConfig?.[0]?.giteaConfig?.blockSyncOnBackupFailure ?? true,

Optionally, also add new env vars (e.g. BACKUP_STRATEGY) to parseEnvConfig() so users can configure backup strategy purely via env.

Originally created by @tiennm99 on GitHub (Apr 14, 2026). Original GitHub issue: https://github.com/RayLabsHQ/gitea-mirror/issues/267 Originally assigned to: @arunavo4 on GitHub. ## Bug The environment config loader (`src/lib/env-config-loader.ts`) overwrites the entire `giteaConfig` JSON column on every restart, but does not include any backup-related fields. This silently erases user-configured backup settings. ## Affected Fields - `backupStrategy` - `backupBeforeSync` - `backupRetentionCount` - `backupRetentionDays` - `backupDirectory` - `blockSyncOnBackupFailure` ## Root Cause `env-config-loader.ts:279-311` builds the `giteaConfig` object without backup fields. Then at line 360, the entire column is replaced: ```ts await db.update(configs).set({ giteaConfig, // replaces the whole JSON column — backup fields vanish ... }); ``` Other fields (like `lfs`, `wiki`, `visibility`) are preserved because they have `?? existingConfig` fallbacks in the builder. Backup fields were added later (v3.11.0) but never added to the env loader. ## Impact 1. **UI settings don't persist** — user changes backup strategy in UI → restarts → reverts to default `"on-force-push"` (via `mapDbToUiConfig` fallback) 2. **No env var support** — `PRE_SYNC_BACKUP_STRATEGY` env var works at runtime but is never persisted to DB or shown in UI 3. **UI/runtime mismatch** — UI always shows `"on-force-push"` regardless of actual runtime behavior ## Reproduction 1. Set `GITEA_URL`, `GITEA_TOKEN` etc. as env vars (triggers `hasEnvConfig() → true`) 2. Start app, go to Settings → change backup strategy to e.g. "Always Backup" 3. Save successfully 4. Restart the app 5. Settings page shows "Smart (on-force-push)" again — the saved value is gone ## Workaround Set `PRE_SYNC_BACKUP_STRATEGY` env var (e.g. `disabled`, `always`, `on-force-push`, `block-on-force-push`). This is read at sync time by `resolveBackupStrategy()` in `repo-backup.ts` and takes effect because the DB field is empty. However, the UI will not reflect this value. ## Suggested Fix Add backup fields to the env loader's `giteaConfig` builder with `?? existingConfig` fallbacks, consistent with how other fields are handled: ```ts // In env-config-loader.ts giteaConfig builder: backupStrategy: existingConfig?.[0]?.giteaConfig?.backupStrategy ?? "on-force-push", backupBeforeSync: existingConfig?.[0]?.giteaConfig?.backupBeforeSync ?? true, backupRetentionCount: existingConfig?.[0]?.giteaConfig?.backupRetentionCount ?? 5, backupRetentionDays: existingConfig?.[0]?.giteaConfig?.backupRetentionDays ?? 30, backupDirectory: existingConfig?.[0]?.giteaConfig?.backupDirectory ?? "data/repo-backups", blockSyncOnBackupFailure: existingConfig?.[0]?.giteaConfig?.blockSyncOnBackupFailure ?? true, ``` Optionally, also add new env vars (e.g. `BACKUP_STRATEGY`) to `parseEnvConfig()` so users can configure backup strategy purely via env.
GiteaMirror added the bug label 2026-04-21 23:14:05 -05:00
Author
Owner

@arunavo4 commented on GitHub (Apr 16, 2026):

@tiennm99 Thanks

<!-- gh-comment-id:4262729799 --> @arunavo4 commented on GitHub (Apr 16, 2026): @tiennm99 Thanks
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/gitea-mirror#1230