from __future__ import annotations from ..ddns_models import DdnsSettings from ..ddns_service import DdnsService from .html_utils import escape, trusted from .templates import _code_window, _message_band, _page, _top_nav from .templates_public_sections import _credentials_panel, _linux_installer_section def _render_public_home( service: DdnsService, settings: DdnsSettings, created_account: dict[str, str] | None, message: str | None, ) -> str: base_url = settings.public_base_url.rstrip("/") hostname_suffix = settings.hostname_suffix or "your KarlDNS suffix" suffix = escape(hostname_suffix) demo_update_url = escape(f"{base_url}/u/?myip=") cname_example = f"home.example.com. CNAME your-name.{hostname_suffix}." create_demo = "$ curl -sS 'https://karldns.de/u/?myip=203.0.113.10'\ngood 203.0.113.10" manual_demo = "\n".join( [ "# explicit IPv4", "curl -sS 'https://karldns.de/u/?myip=203.0.113.10'", "# source IP fallback", "curl -sS 'https://karldns.de/u/'", ] ) created_html = _credentials_panel(service, created_account) message_html = _message_band(message) if message else "" description = "KarlDNS is a free self-hosted Dynamic DNS service for FRITZ!Box routers, generated KarlDNS hostnames, Linux cron jobs, and home networks." return _page( "KarlDNS", trusted(f"""
{_top_nav()}

Dynamic DNS for home routers.

{demo_update_url}

KarlDNS gives you a generated DynDNS hostname under {suffix}. Add the private update URL to your router, or use it from a script.

{message_html} {created_html}

Hostname

No account needed.

Create a KarlDNS hostname. Use it directly, or point your own DNS name at it with a CNAME.

KarlDNS hostname

Create a hostname

You get a hostname, a private update URL, and router fields if your router needs them.

Optional DNS alias

Add a CNAME

After creation, add a CNAME at your DNS provider:

{_code_window(cname_example, copy_label="CNAME example")}

KarlDNS updates only the generated hostname. The external DNS name follows it through CNAME.

{_code_window(create_demo, copy_label="update example", class_name="mt-4")}

Update from a router or script.

Works with FRITZ!Box, curl, cron, Home Assistant, OpenWrt, pfSense, OPNsense, UniFi, MikroTik, and custom tools.

{_code_window(manual_demo, copy_label="manual update examples", class_name="text-start mt-4")}
{_linux_installer_section()}
"""), description=description, preload_logo=True, canonical_url=f"{base_url}/", image_url=f"{base_url}/social-preview.png", image_alt="KarlDNS landing page with private Dynamic DNS update URL", structured_data={ "@context": "https://schema.org", "@type": "SoftwareApplication", "name": "KarlDNS", "applicationCategory": "NetworkingApplication", "operatingSystem": "Linux", "url": f"{base_url}/", "description": description, "image": f"{base_url}/social-preview.png", "offers": {"@type": "Offer", "price": "0", "priceCurrency": "EUR"}, "featureList": [ "Dynamic DNS for FRITZ!Box routers", "Accountless private update URLs", "CNAME target for external DNS names", "Linux cron updater", ], }, ) def _render_privacy_page(settings: DdnsSettings) -> str: base_url = settings.public_base_url.rstrip("/") description = "Privacy and legal information for KarlDNS, including stored hostnames, update links, IP history, and cleanup behavior." return _page( "Legal and Privacy", trusted(f"""
{_top_nav()}

Legal and privacy

Privacy basics.

KarlDNS stores only the data needed to keep your hostname updated.

Data processed

KarlDNS stores hostnames, update links, protected dashboard tokens, protected router passwords, recent IP history, timestamps, and service events.

Secrets

Dashboard links, update URLs, router passwords, and full update URLs are secrets. Anyone with them may update or manage the hostname. Passwords and dashboard lookup values are not stored as readable text.

Logs and retention

KarlDNS keeps recent update events for troubleshooting. Cleanup removes unused hostnames. Server logs may also include IP addresses and request details.

Contact

For the public KarlDNS instance, contact Karl through karl.fail or karlcom.de.

"""), description=description, canonical_url=f"{base_url}/privacy", image_url=f"{base_url}/social-preview.png", image_alt="KarlDNS legal and privacy information", structured_data={ "@context": "https://schema.org", "@type": "WebPage", "name": "KarlDNS Legal and Privacy", "url": f"{base_url}/privacy", "description": description, "isPartOf": { "@type": "WebSite", "name": "KarlDNS", "url": f"{base_url}/", }, }, )