Archived
Polish KarlDNS production UI and docs
This commit is contained in:
1 parent
ca92dc211a
commit
5beee0e5c6
61 files changed
+1566
-523
No files matched your search
@@ -25,8 +25,8 @@ def _linux_installer_section() -> SafeHtml:
|
||||
<div class="container narrow">
|
||||
<div class="text-center mb-4">
|
||||
<p class="eyebrow">Linux cron updater</p>
|
||||
<h2>Install and uninstall should be boring.</h2>
|
||||
<p class="section-copy mx-auto">For a Linux server, Proxmox host, NAS, or home-lab box that is always on, the installer creates a hostname if needed, installs the updater, schedules cron, runs the first update, and prints the private dashboard URL.</p>
|
||||
<h2>Linux updater.</h2>
|
||||
<p class="section-copy mx-auto">Run this on a Linux box that is always on. It creates a hostname, installs the updater, schedules it, and prints your private dashboard link.</p>
|
||||
</div>
|
||||
<div class="card card-body gap-3">
|
||||
<div class="terminal-card">
|
||||
@@ -39,11 +39,11 @@ def _linux_installer_section() -> SafeHtml:
|
||||
{_copy_button("Copy all commands", all_commands)}
|
||||
</div>
|
||||
<div class="alert alert-info my-0 py-2 small" role="note">
|
||||
Uninstall keeps the private config by default because it may contain your only local copy of the update and dashboard URLs. Use <code>--delete-config</code> for a clean wipe.
|
||||
Uninstall keeps your private URLs by default. Use <code>--delete-config</code> only when you want to remove everything.
|
||||
</div>
|
||||
<div>
|
||||
<h3>Without sudo</h3>
|
||||
<p class="section-copy">User mode writes to <code>~/.local/bin</code>, <code>~/.config/karldns</code>, and your user crontab.</p>
|
||||
<h3>User install</h3>
|
||||
<p class="section-copy">Use this when you do not want a system-wide install.</p>
|
||||
</div>
|
||||
<div class="terminal-card">
|
||||
<code>{escape(user_install)}</code>
|
||||
@@ -69,7 +69,7 @@ def _custom_domain_flow(service: DdnsService, challenge: dict[str, str | None] |
|
||||
claim_secret = attr(challenge.get("claim_secret") or "")
|
||||
verification_name = service.verification_name(str(challenge["domain"]))
|
||||
claim_url = service.domain_claim_url(challenge)
|
||||
status = escape(message or "Add this TXT record at your DNS provider, then check when it has propagated.")
|
||||
status = escape(message or "Add this TXT record at your DNS provider, then check again. DNS can take a few minutes.")
|
||||
txt_bundle = f"TXT name: {verification_name}\nTXT value: {token}"
|
||||
challenge_html = trusted(
|
||||
f"""
|
||||
@@ -78,8 +78,8 @@ def _custom_domain_flow(service: DdnsService, challenge: dict[str, str | None] |
|
||||
<span class="badge text-bg-primary rounded-circle align-self-start">1</span>
|
||||
<h3>Add the TXT record</h3>
|
||||
<p class="small text-secondary mb-0 mt-2">{status}</p>
|
||||
<div class="alert alert-info mb-0 py-2 small">TXT name and value are public DNS records. The private claim link is secret.</div>
|
||||
{_copy_button("Copy TXT record", txt_bundle)}
|
||||
<div class="alert alert-info mb-0 py-2 small">TXT name and value are public. The private claim link is secret.</div>
|
||||
{_copy_button("Copy TXT", txt_bundle)}
|
||||
{_copy_row("TXT name", verification_name, "Public")}
|
||||
{_copy_row("TXT value", token, "Public")}
|
||||
{_copy_row("Private claim link", claim_url, "Secret")}
|
||||
@@ -99,9 +99,9 @@ def _custom_domain_flow(service: DdnsService, challenge: dict[str, str | None] |
|
||||
<section class="section" id="custom-domain">
|
||||
<div class="container narrow">
|
||||
<div class="text-center">
|
||||
<p class="eyebrow">Direct custom-domain publishing</p>
|
||||
<h2>Verify DNS ownership</h2>
|
||||
<p class="section-copy mx-auto">Use this only when KarlDNS should publish A/AAAA records directly inside your domain. If you just want your own subdomain, generate a hostname above and create a CNAME to it.</p>
|
||||
<p class="eyebrow">Custom domain</p>
|
||||
<h2>Verify your domain</h2>
|
||||
<p class="section-copy mx-auto">Use this when KarlDNS should update records inside your domain. For a simpler setup, create a KarlDNS hostname and point a CNAME to it.</p>
|
||||
</div>
|
||||
<div class="row g-3 mt-4 justify-content-center">
|
||||
{challenge_html}
|
||||
@@ -129,24 +129,24 @@ def _credentials_panel(service: DdnsService, created_account: dict[str, str] | N
|
||||
f"""
|
||||
<section class="section success-section">
|
||||
<div class="container">
|
||||
<p class="eyebrow">Hostname generated</p>
|
||||
<p class="eyebrow">Hostname ready</p>
|
||||
<h2>{escape(hostname)}</h2>
|
||||
<p class="section-copy">Use the Update-URL directly. The separate Benutzername and Kennwort values are optional compatibility fields for routers that require them.</p>
|
||||
<p class="section-copy">Use the Update-URL directly. Username and password are only for routers that require separate fields.</p>
|
||||
{_one_time_secret_notice()}
|
||||
{_secret_notice()}
|
||||
<div class="d-flex gap-2 flex-wrap my-3">
|
||||
{_copy_button("Copy complete FRITZ!Box fields", fritzbox_fields)}
|
||||
{_copy_button("Copy one-box update URL", credentialed_update_url)}
|
||||
{_copy_button("Copy CNAME record", cname_record)}
|
||||
{_copy_button("Copy router fields", fritzbox_fields)}
|
||||
{_copy_button("Copy full URL", credentialed_update_url)}
|
||||
{_copy_button("Copy CNAME", cname_record)}
|
||||
</div>
|
||||
<div class="d-grid gap-2">
|
||||
{_copy_row("Update-URL:", update_url, "Secret")}
|
||||
{_copy_row("One-box update URL:", credentialed_update_url, "Secret")}
|
||||
{_copy_row("Full update URL:", credentialed_update_url, "Secret")}
|
||||
{_copy_row("Domainnamen:", hostname, "Public")}
|
||||
{_copy_row("CNAME target:", hostname, "Public")}
|
||||
{_copy_row("Benutzername (optional):", username, "Public")}
|
||||
{_copy_row("Kennwort (optional):", password, "Secret")}
|
||||
{_copy_row("Private status page:", management_url, "Secret")}
|
||||
{_copy_row("Private dashboard:", management_url, "Secret")}
|
||||
</div>
|
||||
{_manual_update_panel(manual_commands)}
|
||||
</div>
|
||||
@@ -161,15 +161,15 @@ def _custom_hostname_form(claim_secret: str) -> SafeHtml:
|
||||
<div class="col-lg-5">
|
||||
<div class="card card-body h-100 gap-3">
|
||||
<span class="badge text-bg-primary rounded-circle align-self-start">2</span>
|
||||
<h3>Create router hostname</h3>
|
||||
<h3>Create hostname</h3>
|
||||
<form method="post" action="/accounts" class="d-grid gap-3" aria-label="Create custom-domain router credentials">
|
||||
<input type="hidden" name="mode" value="custom">
|
||||
<input type="hidden" name="claim_secret" value="{claim_secret}">
|
||||
<label>Verified hostname
|
||||
<input class="form-control" name="hostname" placeholder="home.example.com" autocomplete="off" autocapitalize="none" spellcheck="false" required>
|
||||
</label>
|
||||
<p class="section-copy mb-0">Router compatibility credentials are generated automatically after creation.</p>
|
||||
<button type="submit" class="btn btn-primary rounded-pill">Create credentials</button>
|
||||
<p class="section-copy mb-0">Router fields are created after this step.</p>
|
||||
<button type="submit" class="btn btn-primary rounded-pill">Create hostname</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@@ -183,8 +183,8 @@ def _locked_custom_hostname_card() -> SafeHtml:
|
||||
<div class="col-lg-5">
|
||||
<div class="card card-body h-100 gap-3 opacity-75">
|
||||
<span class="badge text-bg-primary rounded-circle align-self-start">2</span>
|
||||
<h3>Create router hostname</h3>
|
||||
<p class="small text-secondary mb-0 mt-2">This unlocks after the TXT record is visible in public DNS.</p>
|
||||
<h3>Create hostname</h3>
|
||||
<p class="small text-secondary mb-0 mt-2">Available after KarlDNS can see the TXT record.</p>
|
||||
</div>
|
||||
</div>
|
||||
"""
|
||||
|
||||
Reference in new issue
Block a user