import type { ActionFunctionArgs } from 'react-router'; import { data, useLoaderData } from 'react-router'; import Code from '~/components/Code'; import Notice from '~/components/Notice'; import { loadContext } from '~/utils/config/headplane'; import { loadConfig, patchConfig } from '~/utils/config/headscale'; import { getSession } from '~/utils/sessions.server'; import { useLiveData } from '~/utils/useLiveData'; import DNS from './components/dns'; import Domains from './components/domains'; import MagicModal from './components/magic'; import Nameservers from './components/nameservers'; import RenameModal from './components/rename'; // We do not want to expose every config value export async function loader() { const context = await loadContext(); if (!context.config.read) { throw new Error('No configuration is available'); } const config = await loadConfig(); const dns = { prefixes: config.prefixes, magicDns: config.dns.magic_dns, baseDomain: config.dns.base_domain, nameservers: config.dns.nameservers.global, splitDns: config.dns.nameservers.split, searchDomains: config.dns.search_domains, extraRecords: config.dns.extra_records, }; return { ...dns, ...context, }; } export async function action({ request }: ActionFunctionArgs) { const session = await getSession(request.headers.get('Cookie')); if (!session.has('hsApiKey')) { return data({ success: false }, { status: 401 }); } const context = await loadContext(); if (!context.config.write) { return data({ success: false }, { status: 403 }); } const patch = (await request.json()) as Record; await patchConfig(patch); if (context.integration?.onConfigChange) { await context.integration.onConfigChange(context.integration.context); } return data({ success: true }); } export default function Page() { useLiveData({ interval: 5000 }); const data = useLoaderData(); const allNs: Record = {}; for (const key of Object.keys(data.splitDns)) { allNs[key] = data.splitDns[key]; } allNs.global = data.nameservers; return (
{data.config.write ? undefined : ( The Headscale configuration is read-only. You cannot make changes to the configuration )}

Magic DNS

Automatically register domain names for each device on the tailnet. Devices will be accessible at{' '} [device]. {data.baseDomain} {' '} when Magic DNS is enabled.

); }