fix: persist host port and compat mode in config.toml

The host-side port mapping and seccomp compatibility-mode selections
were only used in-memory for docker run args and never written to
config.toml, so a re-run of the installer couldn't recover them as
form defaults (worse, the host port field silently defaulted to the
container's internal port). Add host_port and seccomp_unconfined to
[server] and decode them back via AppConfig.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-26 15:08:24 -03:00
co-authored by Claude Sonnet 5
parent a05b98fdf5
commit 7f73eaf9cc
3 changed files with 26 additions and 9 deletions
+4 -1
View File
@@ -14,10 +14,13 @@ func GenerateConfigTOML(cv ConfigValues) (string, error) {
sb.WriteString("# Server Configuration\n") sb.WriteString("# Server Configuration\n")
sb.WriteString("[server]\n") sb.WriteString("[server]\n")
// Always containerAppPort: the container listens on this port internally; the // Always containerAppPort: the container listens on this port internally; the
// user's port is the host-side mapping (see RunAppClienteContainer). // user's port is the host-side mapping (see RunAppClienteContainer). Persisted
// separately as host_port so it survives as the form default on a re-run.
sb.WriteString(fmt.Sprintf("port = %d\n", containerAppPort)) sb.WriteString(fmt.Sprintf("port = %d\n", containerAppPort))
sb.WriteString(fmt.Sprintf("host_port = %s\n", cv.Server["port"]))
sb.WriteString(fmt.Sprintf("timeout_seconds = %s\n", cv.Server["timeout"])) sb.WriteString(fmt.Sprintf("timeout_seconds = %s\n", cv.Server["timeout"]))
sb.WriteString(fmt.Sprintf("environment = %q\n", cv.Server["environment"])) sb.WriteString(fmt.Sprintf("environment = %q\n", cv.Server["environment"]))
sb.WriteString(fmt.Sprintf("seccomp_unconfined = %t\n", cv.Server["seccomp_unconfined"] == "Sim"))
sb.WriteString("\n") sb.WriteString("\n")
// [database] // [database]
+8 -2
View File
@@ -60,6 +60,12 @@ func TestGenerateConfigTOML_RoundTrip(t *testing.T) {
if cfg.Server.Environment != "production" { if cfg.Server.Environment != "production" {
t.Errorf("environment = %q, want %q", cfg.Server.Environment, "production") t.Errorf("environment = %q, want %q", cfg.Server.Environment, "production")
} }
if cfg.Server.HostPort != 9090 {
t.Errorf("host_port = %d, want 9090", cfg.Server.HostPort)
}
if cfg.Server.SeccompUnconfined {
t.Errorf("seccomp_unconfined = true, want false")
}
if cfg.Database.Type != "postgres" { if cfg.Database.Type != "postgres" {
t.Errorf("database type = %q, want %q", cfg.Database.Type, "postgres") t.Errorf("database type = %q, want %q", cfg.Database.Type, "postgres")
} }
@@ -103,8 +109,8 @@ func TestGenerateConfigTOML_PortIsAlwaysContainerPort(t *testing.T) {
if cfg.Server.Port != containerAppPort { if cfg.Server.Port != containerAppPort {
t.Errorf("config port = %d, want fixed containerAppPort %d", cfg.Server.Port, containerAppPort) t.Errorf("config port = %d, want fixed containerAppPort %d", cfg.Server.Port, containerAppPort)
} }
if strings.Contains(out, "port = 9090") { if cfg.Server.HostPort != 9090 {
t.Errorf("host port 9090 leaked into config.toml:\n%s", out) t.Errorf("host_port = %d, want 9090", cfg.Server.HostPort)
} }
} }
+11 -3
View File
@@ -62,8 +62,10 @@ type ConfigValues struct {
type AppConfig struct { type AppConfig struct {
Server struct { Server struct {
Port int64 `toml:"port"` Port int64 `toml:"port"`
HostPort int64 `toml:"host_port"`
Timeout int64 `toml:"timeout_seconds"` Timeout int64 `toml:"timeout_seconds"`
Environment string `toml:"environment"` Environment string `toml:"environment"`
SeccompUnconfined bool `toml:"seccomp_unconfined"`
} `toml:"server"` } `toml:"server"`
Database struct { Database struct {
Type string `toml:"type"` Type string `toml:"type"`
@@ -83,7 +85,8 @@ type AppConfig struct {
func loadConfig() AppConfig { func loadConfig() AppConfig {
var config AppConfig var config AppConfig
config.Server.Port = 8081 config.Server.Port = containerAppPort
config.Server.HostPort = 8081
config.Server.Timeout = 30 config.Server.Timeout = 30
config.Server.Environment = "production" config.Server.Environment = "production"
@@ -113,6 +116,11 @@ func InitialModel() Model {
s.Spinner = spinner.Dot s.Spinner = spinner.Dot
s.Style = SpinnerStyle s.Style = SpinnerStyle
seccompDefault := "Não"
if cfg.Server.SeccompUnconfined {
seccompDefault = "Sim"
}
return Model{ return Model{
currentStep: StepCheckDocker, currentStep: StepCheckDocker,
loginForm: NewFormStep("Login no Repositório Docker", []FormField{ loginForm: NewFormStep("Login no Repositório Docker", []FormField{
@@ -175,7 +183,7 @@ func InitialModel() Model {
Id: "port", Id: "port",
Label: "Porta (host)", Label: "Porta (host)",
Placeholder: "8081", Placeholder: "8081",
Default: strconv.FormatInt(cfg.Server.Port, 10), Default: strconv.FormatInt(cfg.Server.HostPort, 10),
Type: FieldTypeNumber, Type: FieldTypeNumber,
CharLimit: 4, CharLimit: 4,
}, },
@@ -197,7 +205,7 @@ func InitialModel() Model {
{ {
Id: "seccomp_unconfined", Id: "seccomp_unconfined",
Label: "Modo Compatibilidade (máquinas antigas)", Label: "Modo Compatibilidade (máquinas antigas)",
Default: "Não", Default: seccompDefault,
Type: FieldTypeSelect, Type: FieldTypeSelect,
Options: []string{"Não", "Sim"}, Options: []string{"Não", "Sim"},
}, },