Files
deploy-felhom-compose/TASK.md
T

10 KiB

TASK.md — v0.4.6: MariaDB Validation Fix + Dashboard & Protected Stack UX

Version bump: v0.4.6 Scope: Bug fix + 2 UI improvements


Overview

Three items:

  1. Bugfix: MariaDB dump validation false positive — header check fails because MariaDB 11.4+ prepends a sandbox comment before the dump header
  2. UI: Dashboard should only show deployed apps (not 47 "Nincs telepítve" entries)
  3. UI: Protected stacks (especially FileBrowser) should show subdomain URL + allow restart

Task 1: Fix MariaDB dump validation false positive

Root cause

MariaDB 11.4+ prepends a sandbox directive before the header comment:

/*M!999999\- enable the sandbox mode */
-- MariaDB dump 10.19-11.4.10-MariaDB, for debian-linux-gnu (x86_64)

The validation code checks only the first line for -- MariaDB dump or -- MySQL dump, but line 1 is now /*M!999999...*/. So the header check fails with "MariaDB dump missing comment header".

Fix

In ValidateDump() (file: internal/backup/dbdump.go), change the header check to scan the first 10 lines (not just line 1) for the expected pattern. Also accept /* and /*! lines as valid preamble.

For MariaDB/MySQL dumps, valid header patterns (any of these in the first 10 lines):

  • -- MariaDB dump
  • -- MySQL dump
  • -- mysqldump

For PostgreSQL dumps, valid header patterns:

  • -- PostgreSQL database dump

Implementation

Find the header validation logic in ValidateDump(). Replace the "first line must be" check with a loop over the first 10 lines:

// Check header — scan first 10 lines for expected dump header
scanner := bufio.NewScanner(file)
headerFound := false
linesChecked := 0
for scanner.Scan() && linesChecked < 10 {
    line := scanner.Text()
    linesChecked++
    switch dbType {
    case DBTypeMariaDB:
        if strings.HasPrefix(line, "-- MariaDB dump") ||
           strings.HasPrefix(line, "-- MySQL dump") ||
           strings.HasPrefix(line, "-- mysqldump") {
            headerFound = true
        }
    case DBTypePostgres:
        if strings.HasPrefix(line, "-- PostgreSQL database dump") {
            headerFound = true
        }
    }
    if headerFound {
        break
    }
}

Verification

After deploying, trigger a manual backup ("Mentés most") and check the Adatbázisok table on the backup page. The romm MariaDB entry should show a green validation badge with table count instead of "Hiba".


Task 2: Dashboard — show only deployed apps

Current behavior

The "Alkalmazások állapota" section on the Vezérlőpult page shows all apps (deployed + not deployed), meaning 47+ "Nincs telepítve / Telepítés" entries clutter the dashboard.

New behavior

Only show deployed apps (including protected infra stacks) on the dashboard. Non-deployed apps remain accessible via the Alkalmazások page.

Implementation

In dashboardHandler() (internal/web/handlers.go), filter the stack list before passing to the template:

// Filter to deployed-only for dashboard
stackList := s.stackMgr.GetStacks()
var deployedStacks []stacks.Stack
for _, st := range stackList {
    if st.Deployed || st.Protected {
        deployedStacks = append(deployedStacks, st)
    }
}

Pass deployedStacks as data["Stacks"] to the template instead of the full stackList.

Important: The TotalCount stat card should still show the total count of all apps (deployed + not deployed), not just the filtered list. Keep using len(stackList) for that.

Template change

In dashboard.html, update the section heading:

<h3>Telepített alkalmazások</h3>

("Telepített alkalmazások" = "Installed applications")

No other template changes needed — the {{range .Stacks}} loop just iterates over fewer items.

Edge case

If no user apps are deployed yet (fresh install), the section still shows protected infra stacks (traefik, cloudflared, felhom-controller, filebrowser) — this is reassuring to the customer.


Task 3: FileBrowser — show URL + allow restart on protected stacks

Current behavior

Protected stacks show only "Védett rendszerkomponens" badge with no actions or URL link, on both the dashboard compact list and the Alkalmazások detail cards.

New behavior

For protected stacks that are operational (running):

  • Show the subdomain URL link if configured (e.g., files.demo-felhom.eu ↗)
  • Show "Újraindítás" (Restart) button
  • Keep "Védett" badge
  • NO stop/start/delete/update buttons (still protected from destructive actions)

The subdomain problem

FileBrowser is deployed by docker-setup.sh as infrastructure — it may NOT have a .felhom.yml metadata file with the subdomain field set. Without it, the controller doesn't know FileBrowser's subdomain.

Solution: Add .felhom.yml creation to the install_filebrowser() function in scripts/docker-setup.sh.

For the demo node, create it manually after this deploy:

sudo tee /opt/docker/stacks/filebrowser/.felhom.yml << 'EOF'
display_name: Filebrowser
slug: filebrowser
description: Fájlkezelő a külső merevlemezhez
subdomain: files
category: storage
app_info:
  tagline: Web-alapú fájlkezelő a külső merevlemezhez
  use_cases:
    - Fájlok böngészése és letöltése a külső HDD-ről
    - Médiafájlok megosztása családtagokkal
    - Dokumentumok feltöltése és kezelése
  first_steps:
    - Nyisd meg a files.DOMAIN címet a böngészőben
    - Jelentkezz be az admin fiókkal
    - Tallózd a /srv mappákat
  prerequisites:
    - Külső HDD csatlakoztatva és felcsatolva
EOF

Template changes — stacks.html (Alkalmazások page)

Update the protected stack actions section in the detail card:

{{if .Protected}}
    <span class="badge badge-protected">Védett rendszerkomponens</span>
    {{if isOperational .State}}
        <button class="btn btn-warning" onclick="stackAction('{{.Name}}', 'restart')">Újraindítás</button>
    {{end}}
{{else if not .Deployed}}
    ...existing deploy button...

The subdomain URL is already shown above the actions for all stacks — it uses {{if .Meta.Subdomain}}. If .felhom.yml has subdomain: files, it should render automatically. Verify this is not gated behind {{if not .Protected}} — if it is, remove that guard.

Template changes — dashboard.html (Vezérlőpult page)

In the compact stack list, update the protected stack section similarly:

{{if .Protected}}
    <span class="badge badge-protected">Védett</span>
    {{if isOperational .State}}
        <button class="btn btn-sm btn-warning" onclick="stackAction('{{.Name}}', 'restart')"></button>
    {{end}}
{{else if not .Deployed}}

Stack action handler check

In internal/stacks/manager.go, check if the action handler blocks restart on protected stacks. If there's a guard like:

if stack.Protected {
    return fmt.Errorf("cannot perform action on protected stack")
}

Change it to only block destructive actions:

if stack.Protected && action != "restart" {
    return fmt.Errorf("cannot %s protected stack %s", action, name)
}

CRITICAL: Only restart is allowed. stop, start, update, delete must remain blocked for protected stacks.

docker-setup.sh changes

In install_filebrowser(), add .felhom.yml creation after the docker-compose.yml:

# Create .felhom.yml metadata
cat > "${FILEBROWSER_DIR}/.felhom.yml" << 'METAEOF'
display_name: Filebrowser
slug: filebrowser
description: Fájlkezelő a külső merevlemezhez
subdomain: files
category: storage
app_info:
  tagline: Web-alapú fájlkezelő a külső merevlemezhez
  use_cases:
    - Fájlok böngészése és letöltése a külső HDD-ről
    - Médiafájlok megosztása családtagokkal
    - Dokumentumok feltöltése és kezelése
  first_steps:
    - Nyisd meg a files.DOMAIN címet a böngészőben
    - Jelentkezz be az admin fiókkal
    - Tallózd a /srv mappákat
  prerequisites:
    - Külső HDD csatlakoztatva és felcsatolva
METAEOF

Implementation order

Step 1: MariaDB validation fix

  1. Fix ValidateDump() in internal/backup/dbdump.go — scan first 10 lines for header

Step 2: Dashboard deployed-only

  1. Filter stacks in dashboardHandler() in handlers.go
  2. Update heading in dashboard.html to "Telepített alkalmazások"

Step 3: Protected stack UX

  1. Update stacks.html protected section — add restart button, ensure URL link not gated
  2. Update dashboard.html protected section — same (compact form)
  3. Check internal/stacks/manager.go — allow restart on protected stacks
  4. Add .felhom.yml creation to install_filebrowser() in scripts/docker-setup.sh

Step 4: Build, deploy, verify

  1. Build v0.4.6
  2. Deploy to demo node (sync full docker-compose.yml)
  3. Manually create /opt/docker/stacks/filebrowser/.felhom.yml on demo node
  4. Trigger backup → verify MariaDB green validation
  5. Check dashboard shows only deployed apps
  6. Check FileBrowser shows URL and restart button

Step 5: Documentation

  1. Update CONTEXT.md, README
  2. Bump version

Files to modify

internal/backup/dbdump.go                    — fix ValidateDump() header check
internal/web/handlers.go                     — filter deployed-only in dashboardHandler()
internal/web/templates/dashboard.html        — heading + protected stack restart
internal/web/templates/stacks.html           — protected stack: ensure URL visible + restart button
scripts/docker-setup.sh                      — create .felhom.yml in install_filebrowser()
internal/stacks/manager.go                   — allow restart action on protected stacks

Verification checklist

  • MariaDB (romm) shows green validation badge with table count on backup page
  • Dashboard heading is "Telepített alkalmazások"
  • Dashboard shows only deployed + protected apps (no "Nincs telepítve" entries)
  • Dashboard stat cards still show correct total (52 apps)
  • FileBrowser shows files.demo-felhom.eu ↗ link on Alkalmazások page
  • FileBrowser shows "Újraindítás" button on both pages
  • Restart works on FileBrowser
  • Other protected stacks also show restart when operational
  • Stop/delete/update still blocked for all protected stacks
  • No regressions on backup page, app detail pages, deploy flow