fix: installer issues found during testing

- Remove invalid --config flag from exporter service template
- Change ReadOnlyPaths to ReadWritePaths for catalog access
- Add copyBinary() to install binary to /usr/local/bin (ProtectHome compat)
- Fix exporter status detection using direct systemctl check
- Add os/exec import for status check
This commit is contained in:
2026-01-07 11:50:51 +01:00
parent f4a0e2d82c
commit 78e10f5057
4 changed files with 55 additions and 7 deletions

Binary file not shown.

View File

@@ -4,6 +4,7 @@ import (
"context" "context"
"fmt" "fmt"
"os" "os"
"os/exec"
"os/signal" "os/signal"
"strings" "strings"
"syscall" "syscall"
@@ -198,13 +199,14 @@ func runInstallStatus(ctx context.Context) error {
// Check for exporter // Check for exporter
if _, err := os.Stat("/etc/systemd/system/dbbackup-exporter.service"); err == nil { if _, err := os.Stat("/etc/systemd/system/dbbackup-exporter.service"); err == nil {
exporterStatus, err := inst.Status(ctx, "exporter")
fmt.Println() fmt.Println()
fmt.Println("🔹 Metrics Exporter:") fmt.Println("🔹 Metrics Exporter:")
if err == nil && exporterStatus != nil { // Check if exporter is active using systemctl
fmt.Printf(" Service: %s\n", formatStatus(true, exporterStatus.Active)) cmd := exec.CommandContext(ctx, "systemctl", "is-active", "dbbackup-exporter")
if err := cmd.Run(); err == nil {
fmt.Printf(" Service: ✅ active\n")
} else { } else {
fmt.Printf(" Service: installed (status unknown)\n") fmt.Printf(" Service: ⚪ inactive\n")
} }
} }

View File

@@ -4,6 +4,7 @@ package installer
import ( import (
"context" "context"
"fmt" "fmt"
"io"
"os" "os"
"os/exec" "os/exec"
"os/user" "os/user"
@@ -105,6 +106,11 @@ func (i *Installer) Install(ctx context.Context, opts InstallOptions) error {
return err return err
} }
// Copy binary to /usr/local/bin (required for ProtectHome=yes)
if err := i.copyBinary(&opts); err != nil {
return err
}
// Write service and timer files // Write service and timer files
if err := i.writeUnitFiles(opts); err != nil { if err := i.writeUnitFiles(opts); err != nil {
return err return err
@@ -428,6 +434,46 @@ func (i *Installer) createDirectories(opts InstallOptions) error {
return nil return nil
} }
// copyBinary copies the binary to /usr/local/bin for systemd access
// This is required because ProtectHome=yes blocks access to home directories
func (i *Installer) copyBinary(opts *InstallOptions) error {
const installPath = "/usr/local/bin/dbbackup"
// Check if binary is already in a system path
if opts.BinaryPath == installPath {
return nil
}
if i.dryRun {
i.log.Info("Would copy binary", "from", opts.BinaryPath, "to", installPath)
opts.BinaryPath = installPath
return nil
}
// Read source binary
src, err := os.Open(opts.BinaryPath)
if err != nil {
return fmt.Errorf("failed to open source binary: %w", err)
}
defer src.Close()
// Create destination
dst, err := os.OpenFile(installPath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0755)
if err != nil {
return fmt.Errorf("failed to create %s: %w", installPath, err)
}
defer dst.Close()
// Copy
if _, err := io.Copy(dst, src); err != nil {
return fmt.Errorf("failed to copy binary: %w", err)
}
i.log.Info("Copied binary", "from", opts.BinaryPath, "to", installPath)
opts.BinaryPath = installPath
return nil
}
// writeUnitFiles renders and writes the systemd unit files // writeUnitFiles renders and writes the systemd unit files
func (i *Installer) writeUnitFiles(opts InstallOptions) error { func (i *Installer) writeUnitFiles(opts InstallOptions) error {
// Prepare template data // Prepare template data

View File

@@ -21,14 +21,14 @@ RestrictRealtime=yes
LockPersonality=yes LockPersonality=yes
RemoveIPC=yes RemoveIPC=yes
# Read-only access to catalog and backups # Read-write access to catalog for metrics collection
ReadOnlyPaths=/var/lib/dbbackup ReadWritePaths=/var/lib/dbbackup
# Network for HTTP server # Network for HTTP server
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6 RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
# Execution # Execution
ExecStart={{.BinaryPath}} metrics serve --port {{.MetricsPort}} --config {{.ConfigPath}} ExecStart={{.BinaryPath}} metrics serve --port {{.MetricsPort}}
ExecReload=/bin/kill -HUP $MAINPID ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure Restart=on-failure
RestartSec=5 RestartSec=5