docs: add the README sections policy requires (closes #173) #198
@@ -40,6 +40,29 @@ Contributions that introduce mocked, faked, or stubbed DNS will be rejected.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
You need git and Docker. This builds the image and runs dnswatcher watching
|
||||||
|
`example.com` and `www.example.com`:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
git clone https://git.eeqj.de/sneak/dnswatcher.git
|
||||||
|
cd dnswatcher
|
||||||
|
docker build -t dnswatcher .
|
||||||
|
docker run -d --name dnswatcher \
|
||||||
|
-p 8080:8080 \
|
||||||
|
-v dnswatcher-data:/var/lib/dnswatcher \
|
||||||
|
-e DNSWATCHER_TARGETS=example.com,www.example.com \
|
||||||
|
dnswatcher
|
||||||
|
```
|
||||||
|
|
||||||
|
The build also runs the linter and the test suite, which queries live DNS. Once
|
||||||
|
the container is running, the dashboard is at <http://localhost:8080/>. With no
|
||||||
|
notification endpoint set, changes show only on the dashboard; see
|
||||||
|
[Configuration](#configuration) to add one.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
### DNS Domain Monitoring (Apex Domains)
|
### DNS Domain Monitoring (Apex Domains)
|
||||||
@@ -272,48 +295,6 @@ navigation needs, and its URL may name internal hosts.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Architecture
|
|
||||||
|
|
||||||
```
|
|
||||||
cmd/dnswatcher/main.go Entry point (uber/fx bootstrap)
|
|
||||||
|
|
||||||
internal/
|
|
||||||
config/config.go Viper-based configuration
|
|
||||||
globals/globals.go Build-time variables (version)
|
|
||||||
logger/logger.go slog structured logging (TTY detection)
|
|
||||||
healthcheck/healthcheck.go Health check service
|
|
||||||
middleware/middleware.go HTTP middleware (logging, CORS, security
|
|
||||||
headers, metrics auth and rate limit)
|
|
||||||
handlers/handlers.go HTTP request handlers
|
|
||||||
server/
|
|
||||||
server.go HTTP server lifecycle
|
|
||||||
routes.go Route definitions
|
|
||||||
state/state.go JSON file state persistence
|
|
||||||
resolver/resolver.go Iterative DNS resolution engine
|
|
||||||
portcheck/portcheck.go TCP port connectivity checker
|
|
||||||
tlscheck/tlscheck.go TLS certificate inspector
|
|
||||||
notify/notify.go Notification service (Slack, Mattermost, ntfy)
|
|
||||||
watcher/watcher.go Main monitoring orchestrator and scheduler
|
|
||||||
livednstest/livednstest.go Retry and concurrency limit for tests
|
|
||||||
against live DNS (imported only by tests)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Design Principles
|
|
||||||
|
|
||||||
- **No recursive resolvers**: All DNS resolution is performed iteratively,
|
|
||||||
tracing from root nameservers through the delegation chain to authoritative
|
|
||||||
servers.
|
|
||||||
- **No external database**: State is persisted as a single JSON file.
|
|
||||||
- **Dependency injection**: All components are wired via
|
|
||||||
[uber/fx](https://github.com/uber-go/fx).
|
|
||||||
- **Structured logging**: All logs use `log/slog` with JSON output in production
|
|
||||||
(TTY detection for development).
|
|
||||||
- **Graceful shutdown**: All background goroutines respect context cancellation
|
|
||||||
and the fx lifecycle. In-flight notification deliveries are drained on
|
|
||||||
shutdown, bounded by the shutdown timeout.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
Configuration is loaded via [Viper](https://github.com/spf13/viper) with the
|
Configuration is loaded via [Viper](https://github.com/spf13/viper) with the
|
||||||
@@ -667,6 +648,68 @@ configuration.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Rationale
|
||||||
|
|
||||||
|
dnswatcher exists to report changes to the DNS records, TCP port availability
|
||||||
|
and TLS certificates of its configured domains and hostnames, failures and
|
||||||
|
recoveries included: it is designed as a real-time change feed. It queries the
|
||||||
|
authoritative nameservers directly, tracing from the root, instead of a
|
||||||
|
recursive resolver, so no resolver's cache or filtering hides a change and
|
||||||
|
nameservers that disagree with each other are seen. Its state is a single JSON
|
||||||
|
file, so it survives a restart without an external database.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Design
|
||||||
|
|
||||||
|
```
|
||||||
|
cmd/dnswatcher/main.go Entry point (uber/fx bootstrap)
|
||||||
|
|
||||||
|
internal/
|
||||||
|
config/config.go Viper-based configuration
|
||||||
|
globals/globals.go Build-time variables (version)
|
||||||
|
logger/logger.go slog structured logging (TTY detection)
|
||||||
|
healthcheck/healthcheck.go Health check service
|
||||||
|
middleware/middleware.go HTTP middleware (logging, CORS, security
|
||||||
|
headers, metrics auth and rate limit)
|
||||||
|
handlers/handlers.go HTTP request handlers
|
||||||
|
server/
|
||||||
|
server.go HTTP server lifecycle
|
||||||
|
routes.go Route definitions
|
||||||
|
state/state.go JSON file state persistence
|
||||||
|
resolver/resolver.go Iterative DNS resolution engine
|
||||||
|
portcheck/portcheck.go TCP port connectivity checker
|
||||||
|
tlscheck/tlscheck.go TLS certificate inspector
|
||||||
|
notify/notify.go Notification service (Slack, Mattermost, ntfy)
|
||||||
|
watcher/watcher.go Main monitoring orchestrator and scheduler
|
||||||
|
livednstest/livednstest.go Retry and concurrency limit for tests
|
||||||
|
against live DNS (imported only by tests)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Design Principles
|
||||||
|
|
||||||
|
- **No recursive resolvers**: All DNS resolution is performed iteratively,
|
||||||
|
tracing from root nameservers through the delegation chain to authoritative
|
||||||
|
servers.
|
||||||
|
- **No external database**: State is persisted as a single JSON file.
|
||||||
|
- **Dependency injection**: All components are wired via
|
||||||
|
[uber/fx](https://github.com/uber-go/fx).
|
||||||
|
- **Structured logging**: All logs use `log/slog` with JSON output in production
|
||||||
|
(TTY detection for development).
|
||||||
|
- **Graceful shutdown**: All background goroutines respect context cancellation
|
||||||
|
and the fx lifecycle. In-flight notification deliveries are drained on
|
||||||
|
shutdown, bounded by the shutdown timeout.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## TODO
|
||||||
|
|
||||||
|
[`TODO.md`](./TODO.md) names the next step and the steps planned after it. The
|
||||||
|
work for 1.0 is tracked as issues on the
|
||||||
|
[1.0 milestone](https://git.eeqj.de/sneak/dnswatcher/milestone/7).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
dnswatcher is released under the MIT License, Copyright (c) 2026
|
dnswatcher is released under the MIT License, Copyright (c) 2026
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ trial run of the finished image: https://git.eeqj.de/sneak/dnswatcher/issues/149
|
|||||||
|
|
||||||
# Completed Steps
|
# Completed Steps
|
||||||
|
|
||||||
|
- 2026-10-01: README has Getting Started, Rationale and TODO sections, and its
|
||||||
|
Architecture section is now Design, in the order policy sets (closes #173).
|
||||||
- 2026-10-01: a zone's server that answers SERVFAIL or a referral leading no
|
- 2026-10-01: a zone's server that answers SERVFAIL or a referral leading no
|
||||||
closer is passed over for the next, as one that times out is (closes #197).
|
closer is passed over for the next, as one that times out is (closes #197).
|
||||||
- 2026-10-01: when none of a configured name's nameservers answered, the port
|
- 2026-10-01: when none of a configured name's nameservers answered, the port
|
||||||
@@ -122,7 +124,5 @@ trial run of the finished image: https://git.eeqj.de/sneak/dnswatcher/issues/149
|
|||||||
- 1.0 readiness: run it with a real config and read the logs:
|
- 1.0 readiness: run it with a real config and read the logs:
|
||||||
https://git.eeqj.de/sneak/dnswatcher/issues/66
|
https://git.eeqj.de/sneak/dnswatcher/issues/66
|
||||||
- README accuracy sweep: https://git.eeqj.de/sneak/dnswatcher/issues/108
|
- README accuracy sweep: https://git.eeqj.de/sneak/dnswatcher/issues/108
|
||||||
- README sections required by policy:
|
|
||||||
https://git.eeqj.de/sneak/dnswatcher/issues/173
|
|
||||||
- fixed root server order: https://git.eeqj.de/sneak/dnswatcher/issues/138
|
- fixed root server order: https://git.eeqj.de/sneak/dnswatcher/issues/138
|
||||||
- review toward 1.0: https://git.eeqj.de/sneak/dnswatcher/issues/144
|
- review toward 1.0: https://git.eeqj.de/sneak/dnswatcher/issues/144
|
||||||
|
|||||||
Reference in New Issue
Block a user