opnsense_tailscale_settings_set
Configure Tailscale settings on OPNsense: enable, port, auth key, routes, exit node, accept routes, DNS. Reconfigure required to apply.
Instructions
Update Tailscale plugin settings. Only provided fields are changed. Run opnsense_tailscale_service_control with action 'reconfigure' afterwards to apply.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| enabled | No | Enable (1) or disable (0) the Tailscale service | |
| port | No | UDP port for Tailscale (default: 41641) | |
| auth_key | No | Tailscale auth key for automatic enrollment | |
| advertise_routes | No | Comma-separated CIDR list to advertise as subnet routes (e.g. '10.10.0.0/24') | |
| advertise_exit_node | No | Advertise as exit node (1) or not (0) | |
| accept_routes | No | Accept routes from other nodes (1) or not (0) | |
| accept_dns | No | Accept DNS configuration from tailnet (1) or not (0) |
Implementation Reference
- src/tools/tailscale.ts:133-146 (handler)Handler for opnsense_tailscale_settings_set: parses input via Zod schema, builds a settings object with only the provided fields, then POSTs to the OPNsense API endpoint /tailscale/settings/set
case "opnsense_tailscale_settings_set": { const parsed = TailscaleSettingsSetSchema.parse(args); const settings: Record<string, string> = {}; if (parsed.enabled !== undefined) settings.enabled = parsed.enabled; if (parsed.port !== undefined) settings.port = parsed.port; if (parsed.auth_key !== undefined) settings.auth_key = parsed.auth_key; if (parsed.advertise_routes !== undefined) settings.advertise_routes = parsed.advertise_routes; if (parsed.advertise_exit_node !== undefined) settings.advertise_exit_node = parsed.advertise_exit_node; if (parsed.accept_routes !== undefined) settings.accept_routes = parsed.accept_routes; if (parsed.accept_dns !== undefined) settings.accept_dns = parsed.accept_dns; const result = await client.post("/tailscale/settings/set", { settings }); return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] }; } - src/tools/tailscale.ts:8-28 (schema)Zod schema for validating input to opnsense_tailscale_settings_set, with boolean coercion preprocessors for enabled/advertise_exit_node/accept_routes/accept_dns
const TailscaleSettingsSetSchema = z.object({ enabled: z.preprocess( (v) => (v === "true" || v === true || v === "1" ? "1" : v === "false" || v === false || v === "0" ? "0" : v), z.enum(["0", "1"]).optional(), ), port: z.string().regex(/^\d+$/, "Port must be a numeric string").optional(), auth_key: z.string().optional().describe("Tailscale auth key for automatic enrollment"), advertise_routes: z.string().optional().describe("Comma-separated CIDR list to advertise (e.g. '10.10.0.0/24,10.10.20.0/24')"), advertise_exit_node: z.preprocess( (v) => (v === "true" || v === true || v === "1" ? "1" : v === "false" || v === false || v === "0" ? "0" : v), z.enum(["0", "1"]).optional(), ), accept_routes: z.preprocess( (v) => (v === "true" || v === true || v === "1" ? "1" : v === "false" || v === false || v === "0" ? "0" : v), z.enum(["0", "1"]).optional(), ), accept_dns: z.preprocess( (v) => (v === "true" || v === true || v === "1" ? "1" : v === "false" || v === false || v === "0" ? "0" : v), z.enum(["0", "1"]).optional(), ), }); - src/tools/tailscale.ts:49-90 (registration)Tool definition registration for opnsense_tailscale_settings_set in the tailscaleToolDefinitions array, providing name, description, and JSON Schema input definition
{ name: "opnsense_tailscale_settings_set", description: "Update Tailscale plugin settings. Only provided fields are changed. Run opnsense_tailscale_service_control with action 'reconfigure' afterwards to apply.", inputSchema: { type: "object" as const, properties: { enabled: { type: "string", enum: ["0", "1"], description: "Enable (1) or disable (0) the Tailscale service", }, port: { type: "string", description: "UDP port for Tailscale (default: 41641)", }, auth_key: { type: "string", description: "Tailscale auth key for automatic enrollment", }, advertise_routes: { type: "string", description: "Comma-separated CIDR list to advertise as subnet routes (e.g. '10.10.0.0/24')", }, advertise_exit_node: { type: "string", enum: ["0", "1"], description: "Advertise as exit node (1) or not (0)", }, accept_routes: { type: "string", enum: ["0", "1"], description: "Accept routes from other nodes (1) or not (0)", }, accept_dns: { type: "string", enum: ["0", "1"], description: "Accept DNS configuration from tailnet (1) or not (0)", }, }, }, }, - src/client/opnsense-client.ts:49-83 (helper)OPNsenseClient.post() helper used by the tool handler to send settings to the /tailscale/settings/set API endpoint
async post<T>(path: string, data?: unknown): Promise<T> { try { const response = await this.http.post<T>(path, data ?? {}, { headers: { "Content-Type": "application/json" }, }); return response.data; } catch (error: unknown) { throw extractError(error, `POST ${path}`); } } async delete<T>(path: string): Promise<T> { try { const response = await this.http.delete<T>(path); return response.data; } catch (error: unknown) { throw extractError(error, `DELETE ${path}`); } } static fromEnv(): OPNsenseClient { const url = process.env["OPNSENSE_URL"]; const apiKey = process.env["OPNSENSE_API_KEY"]; const apiSecret = process.env["OPNSENSE_API_SECRET"]; if (!url) throw new Error("OPNSENSE_URL environment variable is required"); if (!apiKey) throw new Error("OPNSENSE_API_KEY environment variable is required"); if (!apiSecret) throw new Error("OPNSENSE_API_SECRET environment variable is required"); const verifySsl = process.env["OPNSENSE_VERIFY_SSL"] !== "false"; const timeout = parseInt(process.env["OPNSENSE_TIMEOUT"] ?? "30000", 10); return new OPNsenseClient({ url, apiKey, apiSecret, verifySsl, timeout }); } } - src/index.ts:69-69 (registration)Maps the opnsense_tailscale_settings_set tool name to the handleTailscaleTool handler in the central toolHandlers registry
for (const def of tailscaleToolDefinitions) toolHandlers.set(def.name, handleTailscaleTool);