Skip to content

Add git backup to remote repository (closes #996)#1018

Merged
perber merged 51 commits into
perber:mainfrom
EduardSchwarzkopf:main
Jun 2, 2026
Merged

Add git backup to remote repository (closes #996)#1018
perber merged 51 commits into
perber:mainfrom
EduardSchwarzkopf:main

Conversation

@EduardSchwarzkopf

@EduardSchwarzkopf EduardSchwarzkopf commented May 22, 2026

Copy link
Copy Markdown
Contributor

Closes: #996

What: Automated git backup to a remote repository via SSH with configurable schedule.

Why: Addresses the feature request in #996 — users wanted an optional way to auto-commit page saves and push them to a remote git repository for backup purposes, similar to Otterwiki's experimental repository management feature.

Changes:

  • New internal/backup/ package — Git repository operations, scheduled backup runner, configuration, status tracking, and gitignore handling
  • Admin API routesGET /api/admin/backup/status and POST /api/admin/backup/push endpoints
  • Frontend UI — Backup settings page accessible from user dropdown
  • Documentation — README updated, docs/docker-backup.md added
  • Configuration — CLI flags and env variables for remote URL, branch, SSH key, interval, author

Configuration

CLI Flags

Flag Description Default
--git-backup Enable automated git backup false
--git-backup-remote SSH remote URL for the backup repository ""
--git-backup-branch Git branch to push to main
--git-backup-author-name Git commit author name LeafWiki Backup
--git-backup-author-email Git commit author email [email protected]
--git-backup-interval Backup interval in minutes 60
--git-backup-ssh-key-path Path to SSH private key file ""
--git-backup-ssh-key Raw SSH private key (PEM) ""
(new) --git-backup-ssh-known-hosts Known hosts for MITM protection ""

Environment Variables

Variable Description
LEAFWIKI_GIT_BACKUP Enable automated git backup
LEAFWIKI_GIT_BACKUP_REMOTE SSH remote URL for the backup repository
LEAFWIKI_GIT_BACKUP_BRANCH Git branch to push to
LEAFWIKI_GIT_BACKUP_AUTHOR_NAME Git commit author name
LEAFWIKI_GIT_BACKUP_AUTHOR_EMAIL Git commit author email
LEAFWIKI_GIT_BACKUP_INTERVAL Backup interval in minutes
LEAFWIKI_GIT_BACKUP_SSH_KEY_PATH Path to SSH private key file
LEAFWIKI_GIT_BACKUP_SSH_KEY Raw SSH private key (PEM)
LEAFWIKI_GIT_BACKUP_SSH_KNOWN_HOSTS Known hosts for MITM protection

Example usage

./leafwiki \
  --git-backup=true \
  [email protected]:user/leafwiki-backup.git \
  --git-backup-branch=main \
  --git-backup-author-name="LeafWiki Backup" \
  [email protected] \
  --git-backup-interval=60 \
  --git-backup-ssh-key-path=/path/to/id_rsa

Or via environment variables:

LEAFWIKI_GIT_BACKUP=true
[email protected]:user/leafwiki-backup.git
LEAFWIKI_GIT_BACKUP_SSH_KEY_PATH=/path/to/id_rsa

Admin API

When git backup is enabled, two admin-only REST endpoints are available:

Method Endpoint Description
GET /api/admin/backup/status Returns backup status: lastBackupAt, lastError
POST /api/admin/backup/push Triggers an immediate backup push (returns 202 Accepted)

Restoring from backup

To restore your wiki from a git backup:

  1. Stop the LeafWiki server
  2. Navigate to your data directory
  3. Use git log to view backup history and git checkout <commit> to restore
  4. Restart the LeafWiki server

Note: Only root/ and assets/ are backed up. The SQLite database is not included.

@EduardSchwarzkopf
EduardSchwarzkopf requested a review from perber as a code owner May 22, 2026 15:23
@perber

perber commented May 22, 2026

Copy link
Copy Markdown
Owner

@EduardSchwarzkopf Thanks for this PR.
I think this will improve LeafWiki a lot.

Currently the build throws following error could you investigate?

  Error: cmd/leafwiki/main.go:344:53: cannot use time.Duration(gitBackupInterval) * time.Minute (value of int64 type time.Duration) as *backup.Config value in argument to backup.NewScheduler (typecheck)

@EduardSchwarzkopf

EduardSchwarzkopf commented May 22, 2026

Copy link
Copy Markdown
Contributor Author

Yes, I will check and resolve.

  • Error: cmd/leafwiki/main.go:344:53: cannot use time.Duration(gitBackupInterval) * time.Minute (value of int64 type time.Duration) as *backup.Config value in argument to backup.NewScheduler (typecheck)

@EduardSchwarzkopf

Copy link
Copy Markdown
Contributor Author

Ok, have updated the code. Before I only tested it with docker compose --build -d. But seems to be working now.

@EduardSchwarzkopf

EduardSchwarzkopf commented May 22, 2026

Copy link
Copy Markdown
Contributor Author
  • fix: linter tasks

@perber

perber commented May 22, 2026

Copy link
Copy Markdown
Owner

I let Co-Pilot running a review as well. Lets see what the AI is finding :) - Actually for me it looks already good for first version.
I'm just thinking about to move the startup code into tools (https://github.com/perber/leafwiki/tree/main/internal/core/tools). Let me know what you are thinking. I've added the admin-reset there.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an automated Git-based backup system that periodically commits wiki content and (optionally) pushes it to a configured SSH remote, plus admin endpoints and UI to view status and trigger manual pushes.

Changes:

  • Introduces internal/backup (git repo init/commit/push, scheduler, status, gitignore management) and wires it into the server.
  • Adds admin-only API routes for backup status and manual push triggers.
  • Adds a frontend “Backup Settings” page + Zustand store + API client for status/push.

Reviewed changes

Copilot reviewed 20 out of 21 changed files in this pull request and generated 15 comments.

Show a summary per file
File Description
ui/leafwiki-ui/src/stores/backup.ts Zustand store for backup status + push trigger state
ui/leafwiki-ui/src/lib/api/backup.ts Frontend API client for backup status + push
ui/leafwiki-ui/src/features/router/router.tsx Adds /settings/backup route
ui/leafwiki-ui/src/features/backup/useToolbarActions.ts Clears toolbar buttons on Backup Settings mount
ui/leafwiki-ui/src/features/backup/BackupSettings.tsx Backup Settings UI incl. status polling + manual push
ui/leafwiki-ui/src/components/UserToolbar.tsx Adds “Backup Settings” link for admins
readme.md Documents git backup feature + config + usage
internal/wiki/wiki.go Allows optionally registering backup routes
internal/wiki/backup/routes.go Admin API endpoints for backup status + manual trigger
internal/backup/status.go Status tracking for last backup + error
internal/backup/scheduler.go Background scheduler + manual trigger channel
internal/backup/scheduler_test.go Tests for scheduler behavior
internal/backup/repo.go Git repository init/commit/push implementation
internal/backup/repo_test.go Tests for repo init + commit behavior
internal/backup/gitignore.go Writes .gitignore into the repo root
internal/backup/gitignore_test.go Tests .gitignore creation/non-overwrite
internal/backup/config.go Backup config (paths, author, remote, SSH, interval)
cmd/leafwiki/main.go CLI/env wiring, scheduler startup, routes registration
.env.example Documents git backup environment variables
go.mod Adds go-git and other deps
go.sum Updates checksums for new deps

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread ui/leafwiki-ui/src/features/backup/BackupSettings.tsx
Comment thread ui/leafwiki-ui/src/lib/api/backup.ts Outdated
Comment thread internal/backup/repo.go
Comment thread internal/backup/repo.go
Comment thread internal/backup/gitignore.go
Comment thread cmd/leafwiki/main.go
Comment thread .env.example Outdated
Comment thread go.mod Outdated
Comment thread readme.md Outdated
Comment thread readme.md Outdated
@perber

perber commented May 22, 2026

Copy link
Copy Markdown
Owner

Could you go through the Co-Pilot mentions.

@EduardSchwarzkopf

Copy link
Copy Markdown
Contributor Author

oh wow, I'm impressed by the findings. I will check them out.

@perber

perber commented May 23, 2026

Copy link
Copy Markdown
Owner

oh wow, I'm impressed by the findings. I will check them out.

Yes, I’m often shocked too :)
But you really need to go through it, because sometimes not all of it is true.

@perber

perber commented May 23, 2026

Copy link
Copy Markdown
Owner

Let me know when you are done.
I think we should release this in v0.11.0. Hopefully this is fine for you.

@EduardSchwarzkopf

Copy link
Copy Markdown
Contributor Author

absolutely fine. Should I update the versions in the README from v0.10.0 to v,0.11.0 for the backup and reverse proxy features?

Flag Description Default Available since
--jwt-secret Secret used for signing JWTs (required)
--host Host/IP address the server binds to 127.0.0.1
--port Port the server listens on 8080
--data-dir Directory where data is stored ./data
--admin-password Initial admin password (used only if no admin exists) (required)
--public-access Allow public read-only access false
--hide-link-metadata-section Hide link metadata section false
--inject-code-in-header Raw HTML/JS code injected into tag (e.g., analytics, custom CSS) "" v0.6.0
--custom-stylesheet Path to a .css file inside the data dir, served publicly as /custom.css or ${base-path}/custom.css "" v0.8.5
--allow-insecure ⚠️ Allows insecure HTTP usage for auth cookies (required for plain HTTP) false v0.7.0
--access-token-timeout Access token timeout duration (e.g. 24h, 15m) 15m v0.7.0
--refresh-token-timeout Refresh token timeout duration (e.g. 168h, 7d) 7d v0.7.0
--disable-auth ⚠️ Disable authentication & authorization (internal networks only!) false v0.7.0
--base-path URL prefix when served behind a reverse proxy (e.g. /wiki) "" v0.8.2
--max-asset-upload-size Maximum size for asset uploads (e.g. 50MiB, 50MB, 52428800) 50MiB v0.8.5
--enable-revision Enable revision history / page history false v0.9.0
--enable-link-refactor Enable link refactoring dialog and rewrite flow false v0.9.0
--max-revision-history Maximum revisions kept per page; 0 means unlimited 100 v0.9.0
--enable-http-remote-user Enable reverse-proxy authentication via HTTP header false v0.10.0
--http-remote-user-header-name HTTP header carrying the username from a trusted proxy Remote-User v0.10.0
--trusted-proxy-ips Comma-separated list of trusted proxy IPs/CIDRs (e.g. 127.0.0.1,172.18.0.0/16) "" v0.10.0
--http-remote-user-logout-url URL the frontend redirects to after logout in proxy-auth mode "" v0.10.0
--git-backup Enable automated git backup to a remote repository false v0.10.0
--git-backup-remote SSH remote URL for the backup repository (optional; omit to use local-only git history) "" v0.10.0
--git-backup-branch Git branch to push to main v0.10.0
--git-backup-author-name Git commit author name LeafWiki Backup v0.10.0
--git-backup-author-email Git commit author email [email protected] v0.10.0
--git-backup-interval Backup interval in minutes 60 v0.10.0
--git-backup-ssh-key-path Path to SSH private key file "" v0.10.0
--git-backup-ssh-key Raw SSH private key (PEM) "" v0.10.0

@EduardSchwarzkopf

Copy link
Copy Markdown
Contributor Author

alright, i have updated the code. I hope i got everything. Let me know if there is still some things missing.

@perber

perber commented May 24, 2026

Copy link
Copy Markdown
Owner

Hi @EduardSchwarzkopf,

thanks!
The proxy configuration will be in v0.10.0. I added a proxy setup with dex enabled into the hacks folder to verify if it is working as expected.

It would be could if you could create a separate PR with the flag documentation of the proxy settings. I would keep the Git configuration still in this PR, to be ready for the v0.11.0 release.

I will checkout the branch and let it run on my system and test it a bit manually before merging it. Hopefully soon ;)

If you are interested to support more let me know!

One issue I'm facing at the moment, as the flags are growing not sure if it makes sense to keep them like that. If you are interested to do a proposal and implementing it.

Let me know!

But we still need to consider how it could be started in a few seconds without providing a huge configuration file.
So, I'm not sure at the moment how to do it best and if this is a good direction either. Or just grouping the flags.

Maybe like Paperless-ngx? https://docs.paperless-ngx.com/configuration/

They allow a configuration file & flags. Maybe this is the way to go.

@EduardSchwarzkopf

Copy link
Copy Markdown
Contributor Author

It would be could if you could create a separate PR with the flag documentation of the proxy settings. I would keep the Git configuration still in this PR, to be ready for the v0.11.0 release.

Alright, will remove this from my PR then and provide a new PR.

If you are interested to support more let me know!

Sadly i do not have that much time to be an active maintainer, but I might provide more support in the future, when i see the need for a new feature/fix :D

One issue I'm facing at the moment, as the flags are growing not sure if it makes sense to keep them like that. If you are interested to do a proposal and implementing it.

Yes, I see the point, having this managed via a config or .env file is fine for the moment. Long term, I'd suggest moving this into a settings page, so the user can manage this via UI?

@perber

perber commented May 24, 2026

Copy link
Copy Markdown
Owner

Alright, will remove this from my PR then and provide a new PR.

Perfect, thanks!

Sadly i do not have that much time to be an active maintainer, but I might provide more support in the future, when i see the need for a new feature/fix :D

Happy to hear ;)

Yes, I see the point, having this managed via a config or .env file is fine for the moment. Long term, I'd suggest moving this into a settings page, so the user can manage this via UI?

Here I need to think a bit deeper, because as a K8s admin, I hate having my configuration not managed via GitOps. So it depends, but I need to think about it.

@EduardSchwarzkopf

Copy link
Copy Markdown
Contributor Author

Here I need to think a bit deeper, because as a K8s admin, I hate having my configuration not managed via GitOps. So it depends, but I need to think about it.

100%, considering the point that the setup itself requires some sort of technical knowledge, I'd 100% second your idea with a configuration file. Maybe to have the pluses of both worlds, the app can provide a small overview of enabled features and their values, similar to Firefox's about:config`. Another benefit of this is that it also provides a bit of a sanity check.

@perber perber added this to the v0.11.0 milestone May 24, 2026
@perber

perber commented May 26, 2026

Copy link
Copy Markdown
Owner

@EduardSchwarzkopf thanks for rebasing it. I will check it out the upcoming days. I reworked a bit the Readme. Based on your PR, regarding releases badge :)

@EduardSchwarzkopf

EduardSchwarzkopf commented May 26, 2026

Copy link
Copy Markdown
Contributor Author

No problemo. I'm just not too sure about the big backup section in README tbh.

Maybe move it into /docs?

@perber

perber commented May 26, 2026

Copy link
Copy Markdown
Owner

I need to spin up anyway a LeafWiki instance for the public documentation.
I would leave the backup in the readme for now.

If you take a look at the bitnami sealed secrets repo https://github.com/bitnami-labs/sealed-secrets. They have a pretty huge readme already.

I guess this is OK for now. I think it is already good to have it documented.

@perber

perber commented May 26, 2026

Copy link
Copy Markdown
Owner

I will work on your branch if it is ok.
Just to test things and stuff, regarding Git.

@EduardSchwarzkopf

Copy link
Copy Markdown
Contributor Author

Yes, sure, go ahead, I don't mind at all. Hit me up, when you need something from my end

@perber

perber commented May 29, 2026

Copy link
Copy Markdown
Owner

I have to do a patch release and some smaller improvements. So not sure when I will get to that, but you already have the functionality. So I guess it is not urgent to you

@EduardSchwarzkopf

Copy link
Copy Markdown
Contributor Author

gut ding will weile haben

@perber I'm not in a rush here. My backups are running anyway. This feature is nothing I'm desperate to have. You are doing great work, so don't rush anything :)

@perber

perber commented Jun 2, 2026

Copy link
Copy Markdown
Owner

I will merge the PR today. It will be part of the v0.11.0 release. It will take a bit of time until it gets rolled out to everyone.

I decided to remove the README introduction for now; otherwise, we will have it in the main README. This shouldn’t be included there yet.

@perber
perber merged commit c49f9a0 into perber:main Jun 2, 2026
8 checks passed
@vmdude vmdude mentioned this pull request Jun 23, 2026
4 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Remote Git Repository Support for Backup

3 participants