fix: fall back to lan mode in pic_ngo Caddyfile when token is empty
Unit Tests / test (push) Successful in 7m42s
Unit Tests / test (push) Successful in 7m42s
On a fresh install before DDNS registration completes, ddns.token is empty. Writing `token ` (bare keyword, no value) causes Caddy to reject the Caddyfile at startup with "wrong argument count or unexpected line ending after 'token'". Guard added: if the token is empty, generate a LAN-mode Caddyfile so Caddy starts cleanly. The Caddyfile is regenerated automatically once registration completes and the token is persisted to cell_config.json. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -319,6 +319,18 @@ class CaddyManager(BaseServiceManager):
|
|||||||
# Strip legacy /api/v1 suffix — the pic_ngo plugin appends /api/v1 itself.
|
# Strip legacy /api/v1 suffix — the pic_ngo plugin appends /api/v1 itself.
|
||||||
ddns_api = _raw_api.rstrip('/').removesuffix('/api/v1')
|
ddns_api = _raw_api.rstrip('/').removesuffix('/api/v1')
|
||||||
|
|
||||||
|
# No token yet (fresh install, pre-registration) — Caddy would reject a
|
||||||
|
# bare `token` keyword with no value. Fall back to LAN mode so Caddy
|
||||||
|
# starts cleanly; the Caddyfile is regenerated once registration completes.
|
||||||
|
if not ddns_token:
|
||||||
|
logger.warning(
|
||||||
|
'pic_ngo mode configured but no DDNS token available; '
|
||||||
|
'falling back to lan mode until registration completes'
|
||||||
|
)
|
||||||
|
cert_path, key_path = self._tls_cert_pair()
|
||||||
|
return self._caddyfile_lan(cell_name, service_routes, core_routes,
|
||||||
|
cert_path, key_path)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
f"{self._global_acme_block(email)}\n"
|
f"{self._global_acme_block(email)}\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
|||||||
@@ -640,6 +640,31 @@ class TestCaddyfileLanCustomCert(unittest.TestCase):
|
|||||||
self.assertNotIn('/etc/caddy/internal/cert.pem', out)
|
self.assertNotIn('/etc/caddy/internal/cert.pem', out)
|
||||||
|
|
||||||
|
|
||||||
|
class TestPicNgoNoTokenFallback(unittest.TestCase):
|
||||||
|
"""pic_ngo mode with no token falls back to lan so Caddy starts cleanly."""
|
||||||
|
|
||||||
|
def test_empty_token_generates_lan_caddyfile(self):
|
||||||
|
mgr = _mgr()
|
||||||
|
mgr.config_manager.configs = {'ddns': {'token': '', 'url': 'https://ddns.pic.ngo'}}
|
||||||
|
with patch.dict(os.environ, {}, clear=False):
|
||||||
|
os.environ.pop('DDNS_TOKEN', None)
|
||||||
|
os.environ.pop('DDNS_URL', None)
|
||||||
|
out = mgr.generate_caddyfile({'cell_name': 'x', 'domain_mode': 'pic_ngo'}, [])
|
||||||
|
self.assertIn('auto_https off', out)
|
||||||
|
self.assertNotIn('dns pic_ngo', out)
|
||||||
|
self.assertNotIn('token', out)
|
||||||
|
|
||||||
|
def test_missing_ddns_config_generates_lan_caddyfile(self):
|
||||||
|
mgr = _mgr()
|
||||||
|
mgr.config_manager.configs = {}
|
||||||
|
with patch.dict(os.environ, {}, clear=False):
|
||||||
|
os.environ.pop('DDNS_TOKEN', None)
|
||||||
|
os.environ.pop('DDNS_URL', None)
|
||||||
|
out = mgr.generate_caddyfile({'cell_name': 'x', 'domain_mode': 'pic_ngo'}, [])
|
||||||
|
self.assertIn('auto_https off', out)
|
||||||
|
self.assertNotIn('dns pic_ngo', out)
|
||||||
|
|
||||||
|
|
||||||
class TestDdnsApiStripsLegacySuffix(unittest.TestCase):
|
class TestDdnsApiStripsLegacySuffix(unittest.TestCase):
|
||||||
"""_caddyfile_pic_ngo strips /api/v1 from ddns_api so the plugin doesn't double it."""
|
"""_caddyfile_pic_ngo strips /api/v1 from ddns_api so the plugin doesn't double it."""
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user