Skip to content

feat(cli): Add setup command for infrastructure deployment#98

Merged
nfebe merged 3 commits intomainfrom
feat/setup-command
Mar 23, 2026
Merged

feat(cli): Add setup command for infrastructure deployment#98
nfebe merged 3 commits intomainfrom
feat/setup-command

Conversation

@nfebe
Copy link
Contributor

@nfebe nfebe commented Mar 23, 2026

Adds flatrun-agent setup infra <service> CLI command that deploys infrastructure services from embedded templates. Validates that the requested template is a valid infrastructure type, uses programmatic Docker and network APIs, and creates all required config files.

Currently supports nginx. Extensible for future services.

Adds `flatrun-agent setup infra <service>` CLI command that deploys
infrastructure services from embedded templates. Validates that the
requested template is a valid infrastructure type, uses programmatic
Docker and network APIs, and creates all required config files.

Currently supports nginx. Extensible for future services.

Signed-off-by: nfebe <fenn25.fn@gmail.com>
@sourceant
Copy link

sourceant bot commented Mar 23, 2026

Code Review Summary

This PR introduces a robust setup command for the FlatRun agent, enabling automated deployment of infrastructure services like Nginx using embedded templates. It also refactors the web-based setup handlers into the internal/setup package for better modularity.

🚀 Key Improvements

  • Implemented a metadata-driven setup system for infrastructure services in cmd/agent/setup.go.
  • Unified setup state management using a Manager struct and persistent JSON state.
  • Cleanly separated CLI handlers from API handlers.

💡 Minor Suggestions

  • Simplified port availability checks.
  • Improved deduplication logic for CORS origins.

Copy link

@sourceant sourceant bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review complete. See the overview comment for a summary.

Move setup wizard logic from internal/api/setup_handlers.go into a
clean internal/setup/ package with proper separation of concerns:
- manager.go: state management, IP resolution, config access
- validation.go: system checks (Docker, disk, memory, ports)
- handlers.go: HTTP handlers wrapping Manager + auth.Manager

All 15 tests pass. Server routes rewired to use new package.

Signed-off-by: nfebe <fenn25.fn@gmail.com>
Copy link

@sourceant sourceant bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review complete. See the overview comment for a summary.

return check
}

func IsPortAvailable(port int) bool {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Testing port availability by attempting to bind to 0.0.0.0 and 127.0.0.1 sequentially might fail if the OS considers 0.0.0.0 as covering 127.0.0.1. It's more reliable to check 0.0.0.0 (all interfaces) or use a library that checks netstat/ss state if accuracy across all interfaces is needed without race conditions.

Suggested change
func IsPortAvailable(port int) bool {
func IsPortAvailable(port int) bool {
ln, err := net.Listen("tcp", ":"+strconv.Itoa(port))
if err != nil {
return false
}
_ = ln.Close()
return true
}

Replace hardcoded writeNginxFiles/writeInfraTemplateFiles with a
generic writeSetupFiles that reads dirs and files from metadata.yml.
New infra templates only need metadata — no per-template Go code.

Port checks now handle systems with IPv6 disabled by testing IPv6
support before treating bind failures as "port in use."

Signed-off-by: nfebe <fenn25.fn@gmail.com>
Copy link

@sourceant sourceant bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review complete. See the overview comment for a summary.

if req.AutoSSL != nil {
cfg.Domain.AutoSSL = *req.AutoSSL
}
if len(req.CORSOrigins) > 0 {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When appending new CORS origins, it's safer to ensure they are valid URLs and handled in a way that doesn't create duplicate entries if the config is already partially populated. The current implementation uses a map to deduplicate within the request, which is good, but doesn't check for URL validity.

Suggested change
if len(req.CORSOrigins) > 0 {
if len(req.CORSOrigins) > 0 {
originMap := make(map[string]bool)
for _, e := range cfg.API.AllowedOrigins {
originMap[e] = true
}
for _, origin := range req.CORSOrigins {
origin = strings.TrimRight(origin, "/")
if !originMap[origin] {
cfg.API.AllowedOrigins = append(cfg.API.AllowedOrigins, origin)
originMap[origin] = true
}
}
}

@nfebe nfebe merged commit 342e5d4 into main Mar 23, 2026
5 checks passed
@nfebe nfebe deleted the feat/setup-command branch March 23, 2026 14:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant