Replace service restart with in-process config reload #84
No reviewers
Labels
No labels
Bug
BuildIssue
Claude-fixed
Enhancement
In Progress
Low priority
On Hold
Rejected
Security
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
keyop-go/nfq_forwarder!84
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "issue29_config_reload"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #29.
connectionManager(internal/nfq_forwarder/connection_manager.go) tracks each running connection by queue number - the same stable identity issue #20's auto-assignment establishes.reload(newConns)diffs the currently-running set against a freshly loaded config: removed connections are torn down (SSH tunnel closed, iptables rules removed), new ones are started, changed ones are stopped and restarted with the new details, and unchanged ones are left completely untouched - so an open tunnel on an unrelated connection survives a reload.SIGHUPis wired intoinitSignalHandleralongside SIGINT/SIGTERM/SIGUSR1.POST /api/config/restart(systemctl --user restart) is removed entirely and replaced withPOST /api/config/reload, going through the exact same code path SIGHUP uses. The config-edit page's "Restart service" button is now "Apply configuration", distinct from the existing "Reload latest version" button (which discards an in-progress edit and re-fetches the on-disk file - unrelated to this feature).docs/nfq_forwarder.service'sExecReloadnow sendsSIGHUPinstead of doing a fullsystemctl restart.reloadrefuses to start anything once the manager's parent context is already cancelled, since async.WaitGroup's counter can legitimately hit zero mid-reload (stop phase before start phase) and a concurrentWait()could return right at that crossing otherwise. Covered by a direct regression test.connections:- a change toweb_ui:or any other top-level setting still needs a real restart.Note for
danny/scripts'nfqctl: no change needed there -nfqctl reloadalready just callssystemctl --user reload, which will now deliver SIGHUP instead of a full restart automatically.make lint/make testclean. Manually verified via a real httptest.Server round-trip thatPOST /api/config/reload's response shape matches whatconfig_edit.jsexpects and that the rendered page serves the new button. Real-host verification (a genuine SIGHUP/systemd reload against live iptables/SSH state) isn't exercisable in this sandbox - flagged as a new checklist item in CLAUDE.md's Known issues section.A couple of comments to resolve.
@ -29,2 +23,2 @@# a full restart converges exactly to whatever --config's connections list says - nothing from# the old configuration is left behind, even if a connection was removed entirely.# Reload (GitLab issue #29): ExecReload below sends SIGHUP, the traditional Unix signal for this# - `systemctl --user reload` (and `nfqctl reload`, which just calls that) both trigger it withnfqctlis a local script wrapper and not published to the wider audience for this. Please remove all references tonfqctlfrom this repo and PR, replacing with just the genericsystemctl --user reloadsince that is whatnfqctlcalls.@ -0,0 +44,4 @@// startup before this. A reload that changes these global settings only affects connections// that get (re)started by that same reload; a connection left unchanged keeps its// already-built pool (and any open tunnels on it) exactly as it was.sshKeyPath stringThese connection configuration values feel like they should be in their own structure?
Pushed a follow-up commit addressing both comments:
nfqctlreference (README.md, docs/README.md, docs/nfq_forwarder.service, CLAUDE.md) - replaced with the genericsystemctl --user reload nfq_forwarder.servicecommand it just calls.connectionManager's SSH-pool-construction fields (sshKeyPath,knownHostsPath,keepaliveInterval,autoAddUnknownHostKeys) into a newsshPoolSettingsstruct instead of leaving them as loose fields.make lint/make testclean.That looks better, thanks.