## Summary
- Integrates Desec into the AIO interface which simplifies the domain
registration and domain setup.
- You can either create a new account directly or use an existing
account.
- You have a button that you can open where the process will be done.
After the process is done, the whole page reloads and you can continue
with the setup.
- Caddy and dnsmasq community containers will be activated during the
process which will take over the cert generation and enable split-brain
dns.
- Community containers will work automatically for example Vaultwarden
as the subdomains of the desec domain point automatically via a wildcard
dns entry towards the main desec domain.
- Playwright tests are added to ensure that the system works as expected
in the future
- the desec api is mocked via a small node js based file.
- the qa and other docs were updated to mention desec
A slug typed into the deSEC form was lost when the form re-rendered after a
201 redirect (e.g. on the awaiting-verification step), forcing the user to
re-enter it. Persist the requested slug in the AIO config when register()
runs and pre-fill the slug input from it on every step, then clear it once a
domain is set. Stored in configuration.json rather than a URL parameter so it
survives the multi-step flow without leaking into the iframe address.
Signed-off-by: Simon L. <szaimen@e.mail.de>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The containers page showed "Reveal deSEC password" for every deSEC domain,
but when the user logs in with their own existing account AIO stores an
empty password, so the reveal exposed nothing useful. Gate the reveal on a
stored password: AIO-created accounts show the generated credentials as
before; existing accounts now just say the domain is managed via that
account and to log in at desec.io with your own password.
Also clear the stored generated password in the awaiting-verification path
when the user logs in with their own password (the email already had an
account), so a non-empty stored password reliably means "AIO generated this
account" — and report the account as not-new so no wildcard CNAME is created
on a domain the user manages themselves.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Simon L. <szaimen@e.mail.de>
Logging in with an existing deSEC account and entering a slug you already
own failed with "Domain limit exceeded": registerDomain() always tried to
POST /domains/, which deSEC rejects (403 when the account is at its quota,
400/409 when the name is taken) even though the domain belongs to you.
Now, for a user-specified slug, a 400/403/409 triggers an ownership check
(GET /domains/{name}/); if the account already owns the domain it is reused
and registration completes. Otherwise a clear message is shown (over-limit
vs. taken by someone else). Random-slug registration is unchanged.
Update the deSEC mock to mirror the real status codes (per-account ownership,
domain limit -> 403, taken name -> 400, GET /domains/{name}/) and add a spec
that exercises the over-limit ownership-recovery path.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Simon L. <szaimen@e.mail.de>
dnsmasq runs in host network mode and auto-detects the host's LAN IP. On
Docker Desktop (Windows/macOS) containers run inside a Linux VM isolated
from the real host LAN, so detection yields the wrong IP and local DNS
resolution does not work. Call this out in the dnsmasq readme and the
in-app deSEC domain notice.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Simon L. <szaimen@e.mail.de>
The deSEC registration entry point now renders regardless of
SKIP_DOMAIN_VALIDATION (it was moved out of the skip-validation guard), and
the deSEC flow already sets the domain with validation skipped internally.
Remove the now-unnecessary SKIP_DOMAIN_VALIDATION=false override from the
deSEC Playwright steps in both workflows and update the stale spec comment.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Simon L. <szaimen@e.mail.de>
The deSEC entry <details> was moved up above the domain submit form, but the
#desec-modal container and desec-modal.js were left behind inside the
skip_domain_validation block. Move them up to sit directly after the entry
block so the open button, modal, and wiring script are always rendered
together (and present even when domain validation is skipped). This restores
the modal flow the Playwright tests drive via #desec-frame.
Signed-off-by: Simon L. <szaimen@e.mail.de>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Simon L. <szaimen@e.mail.de>
Hide the "Your deSEC login credentials" block during the in-flight
register/verify steps — the credentials are still shown in the dedicated
"deSEC account credentials" section once the domain is registered.
Extract the deSEC domain info/dnsmasq-caution notice into a reusable include
and also show it at the top of the initial-install flow, directly above the
"download and start containers" explanation, while keeping it in the
Community Containers section where it already appeared.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Simon L. <szaimen@e.mail.de>
The email input was unstyled because input[type="email"] was missing from
the text/password input rules, and the deSEC form's inline-block inputs
flowed side by side. Add the email type to the input styling rules and lay
the deSEC modal form out as a vertical stack with full-width inputs.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Simon L. <szaimen@e.mail.de>
Move the deSEC "register a free domain" flow out of the inline containers
page form and into a modal backed by a dedicated /desec view loaded in an
iframe. The multi-step register -> verify -> domain process now re-renders
inside the modal, so the user can adjust the details and complete email
verification without reloading the whole page each step. Only once the
domain is fully registered does the view reload the parent containers page.
- add /desec route + desec.twig standalone view
- add desec-modal.js (open/close, backdrop + Escape) and desec-done.js
(parent reload on completion)
- redirect register POST to the /desec view so steps stay in the modal
- drop the redundant <details> wrapper in desec-register.twig, add heading
- style the modal and let <button class="button"> pick up button styles
- drive the modal iframe in the Playwright specs and update the QA checklist
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Simon L. <szaimen@e.mail.de>
Mention and recommend the built-in deSEC free domain registration across the
readme, reverse-proxy and local-instance guides, and add a deSEC step to the
new-instance QA checklist.
Co-Authored-By: szaimen <42591237+szaimen@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Simon L. <szaimen@e.mail.de>
desec-api-version-watch.yml is a scheduled workflow that watches the public
desec-stack "API Versions and Roadmap" table (no calls to the live deSEC API, so
it respects their ToS) and fails if it changes, prompting a review of the mock
and DesecManager against any new API version.
Co-Authored-By: szaimen <42591237+szaimen@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Simon L. <szaimen@e.mail.de>
- desec-mock.mjs: a dependency-free Node mock of the deSEC API endpoints the code
uses, with the real status-code semantics (202 on account creation, 403 until
verified then 200 + token, 201/409 on domain creation) plus /__control hooks to
verify and reset state.
- desec-register.spec.js / desec-existing.spec.js drive the real AIO UI through
the register -> verify -> domain flow and the existing-account login flow;
desec-helpers.js holds the shared login helper. Each scenario ends by setting a
domain, so they run as separate CI steps with a re-seed in between.
- seed-desec-mock-config.php points desec_api_base / desec_update_url at the mock
(config key only, no env override, so production is unaffected) and seeds a
known master password, since seeding configuration.json makes AIO consider
itself already installed and /setup no longer shows a generated password.
- Both Playwright workflows start the mock, mount ./community-containers so the
caddy/dnsmasq definitions enabled by the flow are present, seed the config, and
run the two deSEC specs with a re-seed between them.
Co-Authored-By: szaimen <42591237+szaimen@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Simon L. <szaimen@e.mail.de>
- caddy.json: pass DESEC_TOKEN to the caddy container so it can solve the DNS-01
challenge for the registered dedyn.io domain.
- community-containers.twig: when the domain was registered via deSEC, explain
that caddy and dnsmasq were enabled automatically and link the required dnsmasq
router change, with a caution to disable dnsmasq on publicly reachable hosts.
- compose.yaml: mention the built-in deSEC free domain option alongside Tailscale
in the reverse-proxy hint.
Co-Authored-By: szaimen <42591237+szaimen@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Simon L. <szaimen@e.mail.de>
- includes/desec-register.twig renders the multi-step deSEC flow: enter email
(optionally an existing password), the awaiting-verification step, and the
account-registered step, with friendly messaging for the ambiguous "email
already registered" case (deSEC returns 202 either way to prevent enumeration).
- containers.twig includes the deSEC section under the domain-entry UI; index.php
passes the deSEC config/state (email, password, registered/awaiting flags) to
the view.
- Move the deSEC password reveal from an inline style to a CSS class (no inline
CSS/JS in templates) and bump the style.css cache-buster to v13 in layout.twig
and log.twig.
Co-Authored-By: szaimen <42591237+szaimen@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Simon L. <szaimen@e.mail.de>