From d865eb69202785bf1fae37d4ea54b026fd640114 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 12 May 2026 08:09:23 +0000 Subject: [PATCH 1/2] Initial plan From 56a5f6a112a81b5c34aac911718e2c7766dc6898 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 12 May 2026 08:18:03 +0000 Subject: [PATCH 2/2] Fix: global stop/start loads and unloads macOS port-forwarding LaunchDaemon Agent-Logs-Url: https://github.com/qoliber/magebox/sessions/c8a7a7f8-1c35-4f6d-8689-6f05f05fb23f Co-authored-by: peterjaap <431360+peterjaap@users.noreply.github.com> --- cmd/magebox/global.go | 23 +++++++++++++++++++ internal/portforward/pf.go | 39 +++++++++++++++++++++++++++++++++ vitepress/reference/commands.md | 4 ++-- 3 files changed, 64 insertions(+), 2 deletions(-) diff --git a/cmd/magebox/global.go b/cmd/magebox/global.go index 9193606..8c4ff63 100644 --- a/cmd/magebox/global.go +++ b/cmd/magebox/global.go @@ -12,6 +12,7 @@ import ( "qoliber/magebox/internal/nginx" "qoliber/magebox/internal/php" "qoliber/magebox/internal/platform" + "qoliber/magebox/internal/portforward" ) var globalCmd = &cobra.Command{ @@ -105,6 +106,17 @@ func runGlobalStart(cmd *cobra.Command, args []string) error { } } + // Load port forwarding daemon on macOS so that ports 80/443 are forwarded + pfMgr := portforward.NewManager() + if pfMgr.IsInstalled() { + fmt.Print(" Port forwarding... ") + if err := pfMgr.StartDaemon(); err != nil { + fmt.Println(cli.Error("failed: " + err.Error())) + } else { + fmt.Println(cli.Success("started")) + } + } + fmt.Println() cli.PrintSuccess("Global services started!") fmt.Println() @@ -143,6 +155,17 @@ func runGlobalStop(cmd *cobra.Command, args []string) error { } } + // Unload port forwarding daemon on macOS to free ports 80/443 + pfMgr := portforward.NewManager() + if pfMgr.IsInstalled() { + fmt.Print(" Port forwarding... ") + if err := pfMgr.StopDaemon(); err != nil { + fmt.Printf("failed: %v\n", err) + } else { + fmt.Println("stopped") + } + } + fmt.Println("\nGlobal services stopped!") return nil } diff --git a/internal/portforward/pf.go b/internal/portforward/pf.go index 6e91451..1ed3b7a 100644 --- a/internal/portforward/pf.go +++ b/internal/portforward/pf.go @@ -161,6 +161,45 @@ func (m *Manager) needsUpgrade() bool { return false } +// StopDaemon unloads the LaunchDaemon to free web ports without removing the +// plist file. The daemon can be restarted with StartDaemon. +func (m *Manager) StopDaemon() error { + if m.platform != "darwin" { + return nil + } + + if !m.IsInstalled() { + return nil + } + + if !m.isDaemonLoaded() { + return nil + } + + return m.unloadLaunchDaemon() +} + +// StartDaemon loads the LaunchDaemon so that web ports are forwarded again. +func (m *Manager) StartDaemon() error { + if m.platform != "darwin" { + return nil + } + + if !m.IsInstalled() { + return fmt.Errorf("port forwarding not configured — run 'magebox bootstrap' first") + } + + if m.isDaemonLoaded() { + // Already loaded; make sure it is actually listening + if !m.AreRulesActive() { + return m.kickstartDaemon() + } + return nil + } + + return m.loadLaunchDaemon() +} + // Remove uninstalls port forwarding func (m *Manager) Remove() error { if m.platform != "darwin" { diff --git a/vitepress/reference/commands.md b/vitepress/reference/commands.md index fa4f8c6..8023bc3 100644 --- a/vitepress/reference/commands.md +++ b/vitepress/reference/commands.md @@ -1251,7 +1251,7 @@ Start global services. magebox global start ``` -Starts Nginx and Docker services. +Starts Nginx and Docker services. On macOS, also loads the port-forwarding LaunchDaemon so that ports 80 and 443 are forwarded to Nginx. --- @@ -1263,7 +1263,7 @@ Stop all MageBox services. magebox global stop ``` -Stops all Docker containers and Nginx. +Stops all Docker containers and Nginx. On macOS, also unloads the port-forwarding LaunchDaemon so that ports 80 and 443 are released back to the system. ---