v0.27.0 — user-configurable app subdomains

Users can now customize the subdomain for each app during deployment
instead of using a fixed value. The deploy page shows an editable text
input with the default pre-filled and the base domain as a suffix.

New "subdomain" deploy field type with DNS-safe format validation,
reserved name blocklist, and uniqueness check across deployed stacks.
Locked after deploy — changing requires Remove + Redeploy.

Backward compatible: InjectMissingFields() auto-fills SUBDOMAIN from
.felhom.yml defaults for existing deployed apps on next sync/restart.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-22 15:06:22 +01:00
parent f7556b0dad
commit 66817709ad
9 changed files with 191 additions and 22 deletions
+3 -3
View File
@@ -60,7 +60,7 @@ type ResourceHints struct {
type DeployField struct {
EnvVar string `yaml:"env_var" json:"env_var"`
Label string `yaml:"label" json:"label"`
Type string `yaml:"type" json:"type"` // domain, secret, password, path, text, select, boolean
Type string `yaml:"type" json:"type"` // domain, subdomain, secret, password, path, text, select, boolean
Generate string `yaml:"generate" json:"generate"` // e.g., "password:24", "hex:32", "static:admin"
Default string `yaml:"default" json:"default"`
Required bool `yaml:"required" json:"required"`
@@ -112,9 +112,9 @@ func LoadMetadata(stackDir string) Metadata {
meta.Category = "tools"
}
// DOMAIN field is always auto-filled — mark it implicitly required
// DOMAIN and SUBDOMAIN fields are always auto-filled/required — mark implicitly
for i := range meta.DeployFields {
if meta.DeployFields[i].Type == "domain" {
if meta.DeployFields[i].Type == "domain" || meta.DeployFields[i].Type == "subdomain" {
meta.DeployFields[i].Required = true
meta.DeployFields[i].LockedAfterDeploy = true
}