v0.275.0: a backup's data and its version travel together (R-696, 07 §6.6, D4 option A); R-695, R-691, R-694
gates / gates (push) Successful in 23s
gates / gates (push) Successful in 23s
The unit's data files are stamped with the versions that wrote them; the capture keeps the definition the data belongs to; a restore never starts data under another version's definition (unit restores refuse a mismatch; the off-site restore writes the snapshot's definition); every tier's time is its data's; the conversion-copy release needs a dump on the new engine. File-browser sync single-flight + no empty kept folder (R-695); the kept view joins the folder's owning group, language switch resyncs (R-691); a restore-generated login is not shown as the password (R-694). Red-proofs in felhom.eu/documentation/audits/version-travel-2026-09-26/. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
@@ -145,7 +145,17 @@ func RenderCloudflared(d CloudflaredData) (map[string]FileSpec, error) {
|
||||
// RenderFileBrowserCompose returns FileBrowser's docker-compose.yml for the given domain and storage
|
||||
// volume-mount lines. Ported verbatim from internal/web/handlers.go (the single source of truth now
|
||||
// lives here so the pinned image can't diverge between bring-up and the web storage-sync path).
|
||||
func RenderFileBrowserCompose(domain string, storageMounts []string) string {
|
||||
func RenderFileBrowserCompose(domain string, storageMounts []string, groupAdd ...int) string {
|
||||
// R-691 (v0.275.0): supplementary groups — the owning groups of kept folders the view must READ (a
|
||||
// 0770 folder another user owns, e.g. nextcloud's www-data). Their binds are `:ro`. Absent → the
|
||||
// compose is byte-for-byte what it was.
|
||||
groupSection := ""
|
||||
if len(groupAdd) > 0 {
|
||||
groupSection = "\n # Kept data's owning groups (auto-generated): the read-only view reads a folder another user owns.\n group_add:"
|
||||
for _, g := range groupAdd {
|
||||
groupSection += fmt.Sprintf("\n - \"%d\"", g)
|
||||
}
|
||||
}
|
||||
storageSection := ""
|
||||
if len(storageMounts) > 0 {
|
||||
storageSection = "\n # Storage paths (auto-generated by felhom-controller)\n" +
|
||||
@@ -165,7 +175,7 @@ services:
|
||||
# setgid), letting the content apps (group 1000) write into them. The gtstef/filebrowser image is a
|
||||
# single Go binary (entrypoint ./filebrowser) and does NOT honor a UMASK env (verified: -e UMASK=002
|
||||
# leaves PID1 at 0022), so we wrap the entrypoint to set the process umask before exec.
|
||||
entrypoint: ["sh", "-c", "umask 002; exec /home/filebrowser/filebrowser"]
|
||||
entrypoint: ["sh", "-c", "umask 002; exec /home/filebrowser/filebrowser"]%s
|
||||
environment:
|
||||
- TZ=Europe/Budapest
|
||||
- FILEBROWSER_CONFIG=/home/filebrowser/config.yaml
|
||||
@@ -198,7 +208,7 @@ volumes:
|
||||
networks:
|
||||
traefik-public:
|
||||
external: true
|
||||
`, domain, FileBrowserImage, storageSection, domain)
|
||||
`, domain, FileBrowserImage, groupSection, storageSection, domain)
|
||||
}
|
||||
|
||||
// RenderControllerRoute returns a traefik file-provider dynamic config routing the controller's own
|
||||
|
||||
Reference in New Issue
Block a user