From 2a9ca0577ecdbee8b5a4bc8886c112dbc4260eab Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 25 Aug 2026 21:23:04 -0500 Subject: new-app: configure jail mail relay and persist the jail's network alias Two provisioning gaps in new-app: - The jail's dma.conf inherited the base image's shared SMARTHOST/ PORT/AUTHPATH, but never got a per-app MAILNAME - without one, dma can misroute mail for recipients on the jail's own apex domain as local delivery. EnableMail appends a MAILNAME of .skiff.local, which can't collide with any real domain an app sends to or from. - A classic jail's ip4.addr is only a bind restriction, not a route, until something aliases it onto a host interface. jail.conf.tmpl never set jail(8)'s own `interface` parameter, so nothing ever created that alias - confirmed on skiff-freebsd, where the address had twice been made to work via an ad hoc `ifconfig alias` that didn't survive a reboot. Setting `interface` lets jail(8) manage the alias itself, including on every boot. --- internal/layout/layout.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'internal/layout/layout.go') diff --git a/internal/layout/layout.go b/internal/layout/layout.go index 5c2cf30..34edc32 100644 --- a/internal/layout/layout.go +++ b/internal/layout/layout.go @@ -11,6 +11,7 @@ const ( DefaultHealthPort = 8080 DefaultHealthPath = "/healthz" HealthTimeoutSecs = 10 + DefaultJailIface = "vtnet0" ) // Config is Skiff's host-wide configuration. Every field has a sane FreeBSD @@ -70,8 +71,8 @@ func (c Config) PostReceiveHookPath(app string) string { return filepath.Join(c.RepoPath(app), "hooks", "post-receive") } -// RCScriptPath and RCConfPath are paths inside the jail's own chroot, not -// the host's rc.d/rc.conf. +// RCScriptPath, RCConfPath, and DMAConfPath are paths inside the jail's own +// chroot, not the host's rc.d/rc.conf/dma.conf. func (c Config) RCScriptPath(app string) string { return filepath.Join(c.JailRoot(app), "usr", "local", "etc", "rc.d", app) } @@ -80,6 +81,10 @@ func (c Config) RCConfPath(app string) string { return filepath.Join(c.JailRoot(app), "etc", "rc.conf") } +func (c Config) DMAConfPath(app string) string { + return filepath.Join(c.JailRoot(app), "etc", "dma", "dma.conf") +} + // Everything below is Capistrano-style: each deploy gets its own immutable // releases/ checkout (built in place, inside the jail's own dataset), // `current` is a symlink to whichever release is live, and data.db/env are -- cgit v1.3