From f88a28b3dff96e3f1834f7e0fbdd8e0925bb2012 Mon Sep 17 00:00:00 2001 From: anonpenguin23 Date: Tue, 11 Nov 2025 09:17:45 +0200 Subject: [PATCH] feat: enhance binary installation and ownership management - Improved the binary installation process by adding checks for the existence and contents of the source binary directory, ensuring a successful build. - Implemented individual file copying to avoid issues with wildcard expansion, enhancing reliability during the installation. - Added ownership correction for directories and files created during service initialization, ensuring proper permissions for the debros user. - Enhanced error handling for ownership changes, providing detailed output in case of failures. --- CHANGELOG.md | 15 ++++++++ Makefile | 2 +- pkg/environments/production/installers.go | 37 +++++++++++++++++-- pkg/environments/production/orchestrator.go | 6 ++++ pkg/environments/production/provisioner.go | 40 +++++++++++++++++---- 5 files changed, 89 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7525917..0eb8227 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,21 @@ The format is based on [Keep a Changelog][keepachangelog] and adheres to [Semant ### Deprecated ### Fixed +## [0.68.1] - 2025-11-11 + +### Added +- Pre-create log files during setup to ensure correct permissions for systemd logging. + +### Changed +- Improved binary installation process to handle copying files individually, preventing potential shell wildcard issues. +- Enhanced ownership fixing logic during installation to ensure all files created by root (especially during service initialization) are correctly owned by the 'debros' user. + +### Deprecated + +### Removed + +### Fixed +\n ## [0.68.0] - 2025-11-11 ### Added diff --git a/Makefile b/Makefile index d5b63d0..a393ea9 100644 --- a/Makefile +++ b/Makefile @@ -19,7 +19,7 @@ test-e2e: .PHONY: build clean test run-node run-node2 run-node3 run-example deps tidy fmt vet lint clear-ports install-hooks kill -VERSION := 0.68.0 +VERSION := 0.68.1 COMMIT ?= $(shell git rev-parse --short HEAD 2>/dev/null || echo unknown) DATE ?= $(shell date -u +%Y-%m-%dT%H:%M:%SZ) LDFLAGS := -X 'main.version=$(VERSION)' -X 'main.commit=$(COMMIT)' -X 'main.date=$(DATE)' diff --git a/pkg/environments/production/installers.go b/pkg/environments/production/installers.go index a62e63c..b9e3514 100644 --- a/pkg/environments/production/installers.go +++ b/pkg/environments/production/installers.go @@ -322,9 +322,40 @@ func (bi *BinaryInstaller) InstallDeBrosBinaries(branch string, debrosHome strin // Copy binaries fmt.Fprintf(bi.logWriter.(interface{ Write([]byte) (int, error) }), " Copying binaries...\n") - cmd = exec.Command("sh", "-c", fmt.Sprintf("cp -r %s/bin/* %s/", srcDir, binDir)) - if err := cmd.Run(); err != nil { - return fmt.Errorf("failed to copy binaries: %w", err) + srcBinDir := filepath.Join(srcDir, "bin") + + // Check if source bin directory exists + if _, err := os.Stat(srcBinDir); os.IsNotExist(err) { + return fmt.Errorf("source bin directory does not exist at %s - build may have failed", srcBinDir) + } + + // Check if there are any files to copy + entries, err := os.ReadDir(srcBinDir) + if err != nil { + return fmt.Errorf("failed to read source bin directory: %w", err) + } + if len(entries) == 0 { + return fmt.Errorf("source bin directory is empty - build may have failed") + } + + // Copy each binary individually to avoid wildcard expansion issues + for _, entry := range entries { + if entry.IsDir() { + continue + } + srcPath := filepath.Join(srcBinDir, entry.Name()) + dstPath := filepath.Join(binDir, entry.Name()) + + // Read source file + data, err := os.ReadFile(srcPath) + if err != nil { + return fmt.Errorf("failed to read binary %s: %w", entry.Name(), err) + } + + // Write destination file + if err := os.WriteFile(dstPath, data, 0755); err != nil { + return fmt.Errorf("failed to write binary %s: %w", entry.Name(), err) + } } exec.Command("chmod", "-R", "755", binDir).Run() diff --git a/pkg/environments/production/orchestrator.go b/pkg/environments/production/orchestrator.go index 4231221..7f191a0 100644 --- a/pkg/environments/production/orchestrator.go +++ b/pkg/environments/production/orchestrator.go @@ -285,6 +285,12 @@ func (ps *ProductionSetup) Phase2cInitializeServices(nodeType string) error { ps.logf(" ⚠️ RQLite initialization warning: %v", err) } + // Ensure all directories and files created during service initialization have correct ownership + // This is critical because directories/files created as root need to be owned by debros user + if err := ps.fsProvisioner.FixOwnership(); err != nil { + return fmt.Errorf("failed to fix ownership after service initialization: %w", err) + } + ps.logf(" ✓ Services initialized") return nil } diff --git a/pkg/environments/production/provisioner.go b/pkg/environments/production/provisioner.go index 960e862..ee19fe3 100644 --- a/pkg/environments/production/provisioner.go +++ b/pkg/environments/production/provisioner.go @@ -45,7 +45,32 @@ func (fp *FilesystemProvisioner) EnsureDirectoryStructure() error { for _, dir := range dirs { if err := os.MkdirAll(dir, 0755); err != nil { - return fmt.Errorf("failed to create directory %s: %w", dir, err) + return fmt.Errorf("failed to create directory %s: %w", dir) + } + } + + // Create log files with correct permissions so systemd can write to them + logsDir := filepath.Join(fp.debrosDir, "logs") + logFiles := []string{ + "olric.log", + "gateway.log", + "ipfs-bootstrap.log", + "ipfs-cluster-bootstrap.log", + "rqlite-bootstrap.log", + "node-bootstrap.log", + "ipfs-node.log", + "ipfs-cluster-node.log", + "rqlite-node.log", + "node-node.log", + } + + for _, logFile := range logFiles { + logPath := filepath.Join(logsDir, logFile) + // Create empty file if it doesn't exist + if _, err := os.Stat(logPath); os.IsNotExist(err) { + if err := os.WriteFile(logPath, []byte{}, 0644); err != nil { + return fmt.Errorf("failed to create log file %s: %w", logPath, err) + } } } @@ -54,22 +79,23 @@ func (fp *FilesystemProvisioner) EnsureDirectoryStructure() error { // FixOwnership changes ownership of .debros directory to debros user func (fp *FilesystemProvisioner) FixOwnership() error { + // Fix entire .debros directory recursively (includes all data, configs, logs, etc.) cmd := exec.Command("chown", "-R", "debros:debros", fp.debrosDir) - if err := cmd.Run(); err != nil { - return fmt.Errorf("failed to set ownership for %s: %w", fp.debrosDir, err) + if output, err := cmd.CombinedOutput(); err != nil { + return fmt.Errorf("failed to set ownership for %s: %w\nOutput: %s", fp.debrosDir, err, string(output)) } // Also fix home directory ownership cmd = exec.Command("chown", "debros:debros", fp.debrosHome) - if err := cmd.Run(); err != nil { - return fmt.Errorf("failed to set ownership for %s: %w", fp.debrosHome, err) + if output, err := cmd.CombinedOutput(); err != nil { + return fmt.Errorf("failed to set ownership for %s: %w\nOutput: %s", fp.debrosHome, err, string(output)) } // Fix bin directory binDir := filepath.Join(fp.debrosHome, "bin") cmd = exec.Command("chown", "-R", "debros:debros", binDir) - if err := cmd.Run(); err != nil { - return fmt.Errorf("failed to set ownership for %s: %w", binDir, err) + if output, err := cmd.CombinedOutput(); err != nil { + return fmt.Errorf("failed to set ownership for %s: %w\nOutput: %s", binDir, err, string(output)) } return nil