generated from atu/saiop-infrastructure
Add saiop-git-sync-sidecar skill: reusable pattern from the Obsidian vault sync
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
---
|
||||
name: saiop-git-sync-sidecar
|
||||
description: "Pattern for keeping a container's data volume continuously synced to a Gitea repo via a small sidecar container — used for the Obsidian vault, reusable elsewhere."
|
||||
version: 1.0.0
|
||||
author: Claude Code (SAIOP ops session)
|
||||
license: MIT
|
||||
platforms: [linux]
|
||||
prerequisites:
|
||||
env_vars: []
|
||||
commands: [docker, git]
|
||||
metadata:
|
||||
hermes:
|
||||
tags: [SAIOP, git, sync, Gitea, pattern, sidecar]
|
||||
---
|
||||
|
||||
# Git-sync sidecar pattern
|
||||
|
||||
## When to use
|
||||
|
||||
Any time an app's data volume should be continuously backed by a Gitea repo
|
||||
(used for the Obsidian vault → `atu/saiop-knowledge`). Generalizes to any
|
||||
app that just reads/writes files in a directory without needing to know
|
||||
git exists.
|
||||
|
||||
## The pattern
|
||||
|
||||
A second, tiny container (`alpine/git`) mounts the **same volume** as the
|
||||
main app and loops: `git pull` → check `git status --porcelain` → if dirty,
|
||||
`add`/`commit`/`push` → `sleep`. The main app never needs to know about
|
||||
git at all.
|
||||
|
||||
## Gotchas hit building this
|
||||
|
||||
1. **`rm -rf` on the mount point itself fails** ("Resource busy") — you can't
|
||||
remove a bind-mounted directory, only its contents. Use
|
||||
`find "$DIR" -mindepth 1 -delete`, or `git clone <url> .` directly into
|
||||
the already-existing empty directory instead of removing-then-cloning.
|
||||
2. **UID mismatch silently breaks the main app's write access.** If the
|
||||
sidecar runs as root (the `alpine/git` default) and the main app runs as
|
||||
a non-root `PUID`/`PGID` (common for LinuxServer.io images), every file
|
||||
the sidecar creates is unwritable by the main app. Set `user: "UID:GID"`
|
||||
on the sidecar to match the main app's user — don't just chown once
|
||||
after the fact, the mismatch comes back on every commit.
|
||||
3. **Add a `.gitignore` for the app's own volatile state files** (Obsidian:
|
||||
`workspace.json`, `cache/`) before the first commit, or every sync cycle
|
||||
produces a noise commit even with zero real content changes.
|
||||
4. **Don't hardcode a container's internal IP for inter-container access** —
|
||||
IPs churn (confirmed twice on this stack already). Use the container
|
||||
**name** if both containers share a network (Docker's embedded DNS
|
||||
resolves it), which is why the sync sidecar talks to `gitea:3000`
|
||||
directly rather than an IP.
|
||||
Reference in New Issue
Block a user