Skip to main content

Migrating from mosdns

Highly Compatible

Most mosdns v5 configuration files can be copied and used directly. If errors appear on startup, fix the affected fields based on the error messages.

OxiDNS and mosdns v5 share almost the same plugin model and configuration structure: the plugins array, sequence orchestration, jump / goto / accept / return / reject control flow, and plugins such as forward / cache / hosts / domain_set / ip_set / geosite / geoip / ipset / fallback — including their field names — are all highly compatible.

Syntax Differences to Check During Migration

env matcher

In OxiDNS, every item in the env matcher's args array is an independent environment expression.

- tag: env_profile_prod
type: env
args:
- "PROFILE=prod"
- "FEATURE_X"

Use KEY=VALUE for exact matches; KEY:VALUE is also accepted as a rule-expression-style alias. KEY, KEY:, and KEY= only check that the variable exists. Each string item in the array is a complete expression and is not split further on commas or whitespace; if an environment value contains commas or spaces, write it as its own quoted array item, such as "NO_PROXY=localhost,127.0.0.1".

Be careful with two bare items: ["PROFILE", "prod"] checks that both PROFILE and prod exist. It does not mean PROFILE == prod. If a migrated config used that two-token value form, rewrite it as "PROFILE=prod" or "PROFILE:prod".

Feature Overview

Once migration is complete, the following capabilities are available to enable on demand.

FeatureDescription
short_circuitStop the sequence immediately on a plugin hit
Log RotationBuilt-in daily/hourly splitting and cleanup, no logrotate needed
WebUI ConsoleBrowser-based config editing, query history, and live stream
HTTP Management APIREST API with hot reload, auth, and metrics scraping
query_recorderPersist queries to SQLite + SSE live push
ros_address_listSync resolved IPs to RouterOS address-list
reload_providerReload specific provider snapshots without a full restart
download + cronAuto-download rule files and schedule background tasks
Environment Variables${VAR} / ${VAR:-default} placeholders for sensitive fields
PerformanceRust + Tokio: lower memory, lower tail latency, zero GC pauses

Observability & Debugging

WebUI Console

A built-in web management interface for viewing and editing configuration, inspecting plugin state, streaming real-time queries, and browsing query history — all from a browser, no extra tools required. See WebUI.

HTTP Management API

api.http exposes a REST API for hot reload, health checks, Prometheus metrics scraping, and plugin status queries, with Basic Auth and TLS support. See Management API.

api:
http:
listen: "127.0.0.1:9088"
auth:
type: basic
username: "admin"
password: "secret"

query_recorder: Query History and Live Streaming

Persists every request, response, and sequence execution path to SQLite. Provides a history query API and SSE live-push endpoint, powering the WebUI real-time query stream panel.

- tag: recorder_main
type: query_recorder
args:
path: ./query-recorder.sqlite
memory_tail: 1024
retention_days: 7

Configuration & Runtime

short_circuit: Stop on Match

Executor plugins including forward, cache, hosts, fallback, black_hole, and dual_selector all support a short_circuit option. When enabled, the plugin immediately ends the current sequence's remaining steps upon a hit — no extra has_resp + accept needed.

- tag: cache_main
type: cache
args:
size: 8192
short_circuit: true # return immediately on cache hit, skip remaining steps
cache_negative: true

Log Rotation

log.rotation provides built-in log splitting by minute, hour, day, or week, with automatic cleanup of old files — no external tools like logrotate required.

log:
level: info
file: ./oxidns.log
rotation:
type: daily # minutely / hourly / daily / weekly / never
max_files: 7 # max historical files to keep; 0 disables auto-cleanup

Environment Variable Substitution

Configuration files support ${VAR} and ${VAR:-default} placeholders so sensitive fields like passwords and certificate paths can be injected from environment variables instead of being hardcoded.


System Integration

ros_address_list: RouterOS Route Sync

Syncs resolved IPs to a MikroTik RouterOS address-list in real time, enabling DNS-driven traffic routing alongside routing policy rules. See MikroTik Policy Routing.


Rule Maintenance

reload_provider: Targeted Reload

Refreshes the internal data snapshot of specific providers only, without triggering a full global reload. Ideal for rule subscription updates that only need to rebuild the rule set without interrupting in-flight requests.

- tag: reload_ad_rules
type: reload_provider
args:
- "$ad_rules"

download + cron: Subscription Auto-Update

download fetches files over HTTP/HTTPS and atomically replaces local copies. cron schedules tasks in the background on a fixed interval or cron expression. Together they enable fully automatic rule subscription updates without restarting the process.

- tag: rules_cron
type: cron
args:
timezone: "America/New_York"
jobs:
- name: refresh_rules
interval: 12h
executors:
- "$download_rules"
- "$reload_ad_rules"

Performance

OxiDNS is built on Rust + Tokio and has no GC pauses. Performance relative to mosdns varies by scenario:

  • Rule set matching (domain set, composite provider chain): OxiDNS has a significant advantage — several times higher QPS and much lower latency under load.
  • Concurrent upstream queries: OxiDNS leads in both throughput and latency.
  • Latency jitter: OxiDNS produces more stable latency in most scenarios.
  • Local answers, basic sequence, ip set filtering: mosdns is on par or slightly faster.
  • Basic forwarding: QPS is comparable; the gap is small.

See Benchmarks for details.


Next Steps