// Package config defines the deployment configuration for OpenBoatmobile. package config import ( "strings" ) // DeploymentConfig holds all configuration gathered during the walkthrough. type DeploymentConfig struct { // Framework selection Framework string // "hermes" or "openclaw" // Cloud provider CloudProvider string // "hetzner" or "digitalocean" // Provider tokens (sensitive) HetznerToken string DOToken string // SSH configuration SSHKeyNames []string SSHKeyFingerprints []string // Server configuration ServerName string Location string // hetzner: ash, fsn1, nbg1, hel1 Region string // DO: nyc3, sfo2, ams3, etc. ServerType string // hetzner: cpx21, cx23, etc. DropletSize string // DO: s-2vcpu-4gb, etc. AgentName string AgentTimezone string // Inference InferenceProvider string // "venice", "openrouter", "openai", "anthropic", "custom" InferenceAPIKey string InferenceBaseURL string // Fallback inference FallbackProviders []InferenceProviderConfig // Model PrimaryModel string PrimaryModelName string FallbackModels []string VeniceBaseURL string // Docker (Hermes only) DockerEnabled bool // OpenClaw-specific OpenClawVersion string NodeVersion string EnableSwap bool SwapSizeGB int EnableFail2ban bool EnableUnattendedUpgrades bool // Tailscale EnableTailscale bool TailscaleAuthKey string TailnetDomain string // Discord EnableDiscord bool DiscordBotToken string DiscordServerID string DiscordUserIDs []string // Hermes-specific Discord DiscordHomeChannel string DiscordAllowedUsers string DiscordAutoThread bool // Gateway (Hermes) GatewayToken string GatewayAllowedUsers string GatewayAllowAllUsers bool // Optional integrations BraveSearchAPIKey string } // InferenceProviderConfig holds a single inference provider's config. type InferenceProviderConfig struct { Provider string APIKey string BaseURL string } // AdminUser returns the admin username based on framework selection. func (c *DeploymentConfig) AdminUser() string { return c.Framework // "hermes" or "openclaw" } // MonthlyCostEstimate returns an estimated monthly cost string. func (c *DeploymentConfig) MonthlyCostEstimate() string { switch c.CloudProvider { case "hetzner": return hetznerPrice(c.ServerType) case "digitalocean": return doPrice(c.DropletSize) default: return "unknown" } } func hetznerPrice(serverType string) string { prices := map[string]string{ "cx22": "€3.79/mo", "cx23": "€5.83/mo", "cpx21": "€4.49/mo", "cpx31": "€8.98/mo", "cpx41": "€17.96/mo", } if p, ok := prices[serverType]; ok { return p } return "see Hetzner pricing" } func doPrice(size string) string { prices := map[string]string{ "s-1vcpu-1gb": "$6/mo", "s-1vcpu-2gb": "$12/mo", "s-2vcpu-4gb": "$24/mo", "s-4vcpu-8gb": "$48/mo", "g-2vcpu-8gb": "$63/mo", } if p, ok := prices[size]; ok { return p } return "see DO pricing" } // LocationOrRegion returns the location (Hetzner) or region (DO) string. func LocationOrRegion(c *DeploymentConfig) string { if c.CloudProvider == "hetzner" { return c.Location } return c.Region } // ServerTypeOrDroplet returns the server type or droplet size string. func ServerTypeOrDroplet(c *DeploymentConfig) string { if c.CloudProvider == "hetzner" { return c.ServerType } return c.DropletSize } // SSHKeySummary returns a human-readable summary of the SSH key config. func SSHKeySummary(c *DeploymentConfig) string { if len(c.SSHKeyNames) > 0 { return strings.Join(c.SSHKeyNames, ", ") } if len(c.SSHKeyFingerprints) > 0 { return "****" + c.SSHKeyFingerprints[0][max(0, len(c.SSHKeyFingerprints[0])-4):] } return "(none)" } func max(a, b int) int { if a > b { return a } return b }