Compare commits
1
Commits
52877ffa3f
...
2a89d1dc7a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2a89d1dc7a |
@@ -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
|
||||
|
||||
### DNS Domain Monitoring (Apex Domains)
|
||||
@@ -270,48 +293,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 is loaded via [Viper](https://github.com/spf13/viper) with the
|
||||
@@ -665,6 +646,68 @@ configuration.
|
||||
|
||||
---
|
||||
|
||||
## Rationale
|
||||
|
||||
dnswatcher exists to report every change 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
|
||||
|
||||
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
|
||||
|
||||
- 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: `make fmt` and `make fmt-check` cover Markdown with prettier, run
|
||||
in Docker at the version pinned by `yarn.lock` (closes #119).
|
||||
- 2026-10-01: `make fmt-check` fails on a file `goimports` would change; both
|
||||
@@ -116,7 +118,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:
|
||||
https://git.eeqj.de/sneak/dnswatcher/issues/66
|
||||
- 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
|
||||
- review toward 1.0: https://git.eeqj.de/sneak/dnswatcher/issues/144
|
||||
|
||||
Reference in New Issue
Block a user