Git sync
Git sync is optional and disabled by default.
When enabled, SimpleDeploy treats your apps_dir as a git working tree and commits every config change to a remote repository. Each deploy, env-var edit, or sidecar update triggers a commit and push within seconds. You can also pull remote changes back in, making it possible to manage deployments through git rather than (or alongside) the UI.
Git sync complements config sidecars, which write app config to local YAML files. Think of sidecars as the local source of truth and git sync as the transport layer that makes that truth portable. Sidecars are what get committed; git sync is what moves them to a remote.
Git sync is not a replacement for database backup. It does not capture metrics, deploy history, audit logs, or any file outside apps_dir. Secrets stay local: config.yml (which holds password hashes and encrypted registry credentials) and the SQLite database are never committed.
What gets committed
Section titled “What gets committed”{apps_dir}/{slug}/docker-compose.yml{apps_dir}/{slug}/.env{apps_dir}/{slug}/simpledeploy.yml(per-app sidecar: alert rules, backup configs, access){apps_dir}/_global.yml(redacted global config: users, registries, webhooks without secrets).gitignore(auto-generated allowlist that restricts commits to the above files)
Never committed:
{data_dir}/config.yml(password hashes, encrypted credentials){data_dir}/simpledeploy.db(SQLite database)- Metrics, logs, and anything outside
apps_dir
Configure from the UI
Section titled “Configure from the UI”Super admins can enable and edit git sync configuration directly on the Git Sync page without a server restart. Changes saved through the UI are written to the database and take effect immediately. DB values override the config.yml YAML block, and the API response includes a source field ("db" or "yaml") so you can tell which value is active. To reset a field back to the YAML default, remove it from the DB via the UI.
Config block
Section titled “Config block”Add a git_sync: block to your server config.yml:
git_sync: enabled: true remote: git@github.com:owner/infra.git branch: main author_name: SimpleDeploy author_email: bot@example.com ssh_key_path: /etc/simpledeploy/gitsync_id_ed25519 poll_interval: 60s webhook_secret: "your-webhook-secret" poll_enabled: true auto_push_enabled: true auto_apply_enabled: true webhook_enabled: true| Field | Required | Description |
|---|---|---|
enabled | yes | Set to true to start the sync worker. |
remote | yes | Git remote URL (SSH or HTTPS). |
branch | yes | Branch to push to and pull from. |
author_name | no | Commit author name. Defaults to SimpleDeploy. |
author_email | no | Commit author email. |
ssh_key_path | one of | Path to an SSH private key. Mutually exclusive with https_token. |
https_username | one of | HTTPS username. Used together with https_token. |
https_token | one of | HTTPS token or password. Mutually exclusive with ssh_key_path. |
poll_interval | no | How often to pull from remote. Default 60s. |
webhook_secret | no | HMAC secret for verifying GitHub-compatible webhook pushes. |
poll_enabled | no | Whether to run the poll loop. Default true. |
auto_push_enabled | no | Whether to auto-commit and push local changes. Default true. |
auto_apply_enabled | no | Whether to auto-apply fetched remote changes. Default true. |
webhook_enabled | no | Whether the webhook endpoint is active. Default true. |
Toggles
Section titled “Toggles”Four behaviour toggles let you adjust the sync mode without disabling git sync entirely. All default to true. They can be set in config.yml or changed at runtime from the UI (DB overrides YAML).
poll_enabled
Section titled “poll_enabled”Controls whether the background poll loop runs on poll_interval. Set to false if you rely exclusively on webhooks and want no background polling. The sync worker still starts; it just never fires the timer. Useful when you want tight control over when fetches happen.
auto_push_enabled
Section titled “auto_push_enabled”Controls whether local config changes (deploys, env edits, sidecar updates) are automatically committed and pushed to the remote. Set to false for a pull-only setup where the remote is the source of truth and local changes are never pushed back. This is useful when you manage config entirely through the git repo and want to prevent the server from writing back.
auto_apply_enabled
Section titled “auto_apply_enabled”Controls whether fetched remote commits are automatically rebased onto the local working tree. Set to false to enter fetch-only mode: the server fetches on each poll or webhook trigger and tracks how many commits the remote is ahead, but it does not apply those commits. A banner appears in the UI showing the number of commits behind, and you can apply them manually with the Apply button (or via POST /api/git/apply-pending). Useful when you want to review remote changes before they affect running deployments.
webhook_enabled
Section titled “webhook_enabled”Controls whether POST /api/git/webhook accepts and processes incoming webhook payloads. Set to false to temporarily block webhook-triggered syncs, for example during maintenance windows. When disabled, the endpoint returns 404 with an empty body. The HMAC secret is not exposed in the response.
Pending apply
Section titled “Pending apply”When auto_apply_enabled is false, each fetch (poll or webhook) updates an internal counter of how many commits the remote is ahead of the local HEAD. The Git Sync page shows a banner:
3 commits behind remote. Review the changes in your git repository, then click Apply to update running deployments.
Clicking Apply now (or calling POST /api/git/apply-pending) runs the full fetch, rebase with server-wins conflict resolution, sidecar import, and reconcile cycle. After a successful apply, the counter resets to zero and the banner disappears.
If the remote is already up-to-date when apply is triggered, the operation completes immediately with no changes.
Authentication
Section titled “Authentication”SSH: Set ssh_key_path to an Ed25519 or RSA private key on the server. Add the corresponding public key as a deploy key on the remote (GitHub: Settings > Deploy keys, with write access).
HTTPS: Set https_username and https_token. For GitHub, create a fine-grained personal access token with Contents: Read and write permission on the target repository.
First run and adopting existing state
Section titled “First run and adopting existing state”If the remote repository is empty, SimpleDeploy initializes a repo in apps_dir, commits current state, and pushes. This is the recommended starting point. The Git Sync config form detects this case: testing the connection shows an info banner, and the save button changes to Save & push initial commit, making it explicit that saving will push your current SimpleDeploy configs as the initial commit.
If the remote already has commits, SimpleDeploy refuses to push and surfaces an error in git status and on the Git Sync page in admin nav. You then have two options:
- Adopt local state: from an admin shell,
git push --forcefromapps_dirto overwrite the remote with current local state. - Adopt remote state: manually clone the remote, move the files into
apps_dir, and restart the server so sidecars are imported.
Start with an empty remote whenever possible to avoid this decision.
Webhook setup (optional but recommended)
Section titled “Webhook setup (optional but recommended)”A webhook lets the remote trigger an immediate pull instead of waiting for the next poll.
GitHub:
- Repository Settings > Webhooks > Add webhook.
- Payload URL:
https://<your-server>/api/git/webhook - Content type:
application/json - Secret: the value of
webhook_secretin your config. - Event: “Just the push event.”
SimpleDeploy verifies the X-Hub-Signature-256 header using your secret. Gitea and GitLab use the same header format and are also supported.
Poll and webhook coexistence
Section titled “Poll and webhook coexistence”The poll worker runs on poll_interval (default 60s) regardless of webhook configuration. When a webhook arrives, an immediate sync runs; the poll continues as a safety net. There is no harm in running both.
Conflict behavior
Section titled “Conflict behavior”Local state wins on conflict. If a remote change conflicts with a local change, SimpleDeploy logs the conflict to alert_history and surfaces it on the Git Sync page. The remote change is not applied.
Conflicts usually mean two operators edited the same file at the same time. To apply the remote change, re-enter it through the UI after reviewing what was lost.
simpledeploy git status # print worker status and last sync timesimpledeploy git sync-now # one-shot pull-and-apply against current configsync-now is useful after a credentials change or for a manual bootstrap without restarting the server.
Disabling git sync
Section titled “Disabling git sync”Set enabled: false (or remove the block). The sync worker stops. The .git directory and all local history remain in apps_dir untouched. Re-enabling picks up where it left off.
See also
Section titled “See also”- Config sidecars and sidecar-based recovery - sidecar schema and local DR recovery without git.