A minimal project for systems monitoring, designed for cases where Grafana and Prometheus are overkill.
This is not a typical "Status Page" project. There are no alerts, incident histories, push notifications, or CRUD UIs for configuration.
Simply create a configuration file, start the service, and you're done.
- Docker (for containerized usage)
- .NET 9 SDK (for development and building)
- PowerShell (for build scripts)
- Invoke-Build (for build automation)
- GitVersion
# docker-compose.yaml
services:
deucalion:
user: root
container_name: deucalion
image: ghcr.io/fdcastel/deucalion:latest
ports:
- 80:8080
environment:
- DEUCALION__PAGETITLE=Deucalion status
volumes:
- ./example.yaml:/app/example.yaml # Rename or copy your configuration file as needed.
- ./data/:/storage/
# example.yaml
defaults:
intervalWhenUp: 00:00:03 # Default check interval when the monitor is UP
monitors:
ping-example:
!ping
host: cloudflare.com
group: Cloudflare
tcp-example:
!tcp
host: cloudflare.com
port: 443
group: Cloudflare
dns-example:
!dns
host: google.com
recordType: A
resolver: 1.1.1.1:53
group: Google
http-example:
!http
url: https://google.com
expectedStatusCode: 200
expectedResponseBodyPattern: .*
ignoreCertificateErrors: true
group: Google
Monitoring behavior is defined in a YAML configuration file (e.g., deucalion.yaml
).
This optional section allows you to define default values that apply to all monitors, or to all monitors of a specific type, unless overridden in a monitor's configuration. Example:
defaults:
intervalWhenUp: 00:01:00 # Check interval when the monitor is UP
intervalWhenDown: 00:01:00 # Check interval when the monitor is DOWN
timeout: 00:00:05
warnTimeout: 00:00:01
http:
timeout: 00:00:10
warnTimeout: 00:00:02
expectedStatusCode: 202
ignoreCertificateErrors: true
dns:
recordType: AAAA
resolver: 8.8.8.8
ping:
timeout: 00:00:05
warnTimeout: 00:00:01
You can set defaults for each monitor type as follows:
intervalWhenUp
,intervalWhenDown
,timeout
,warnTimeout
(global or for each monitor type)expectedStatusCode
,expectedResponseBodyPattern
,ignoreCertificateErrors
,method
(for http only)recordType
,resolver
(for dns only)
This section defines the individual monitors. Each monitor has a unique name (e.g., ping-example
) and a type indicated by a YAML tag (e.g., !ping
).
The following optional parameters are available for all monitors:
group
: A string to group monitors together in the UI.image
: URL for a custom icon to display for the monitor.href
: URL to link to when the monitor name is clicked.intervalWhenUp
: Check interval when the monitor is UP (except forcheckin
).intervalWhenDown
: Check interval when the monitor is DOWN (except forcheckin
).
You can use ${MONITOR_NAME}
in monitor fields to insert the monitor's name dynamically. Example:
monitors:
google: !http
url: https://${MONITOR_NAME}.com
This will set the URL to https://google.com
.
Type | Required Fields | Optional Fields |
---|---|---|
ping | host |
timeout , warnTimeout , intervalWhenUp , intervalWhenDown , group , image , href |
tcp | host , port |
timeout , warnTimeout , intervalWhenUp , intervalWhenDown , group , image , href |
dns | host , recordType , resolver |
timeout , warnTimeout , intervalWhenUp , intervalWhenDown , group , image , href |
http | url |
expectedStatusCode , expectedResponseBodyPattern , ignoreCertificateErrors , timeout , warnTimeout , intervalWhenUp , intervalWhenDown , group , image , href , method |
checkin | secret |
intervalWhenUp , group , image , href |
ping-example:
!ping
host: cloudflare.com # Required: The hostname or IP address to ping.
tcp-example:
!tcp
host: cloudflare.com # Required: The hostname or IP address to connect to.
port: 443 # Required: The TCP port to connect to.
dns-example:
!dns
host: google.com # Required: The hostname to query.
recordType: A # Required: The DNS record type (e.g., A, AAAA, MX, CNAME).
resolver: 1.1.1.1:53 # Required: The DNS resolver IP address and port.
http-example:
!http
url: https://google.com # Required: The URL to request.
expectedStatusCode: 200 # (Optional) Expected HTTP status code. Defaults to 200-299.
expectedResponseBodyPattern: .* # (Optional) Regex pattern to match against the response body.
ignoreCertificateErrors: true # (Optional) Set to true to ignore SSL/TLS certificate errors. Defaults to false.
warnTimeout: 00:00:00.250 # (Optional) Time threshold after which the monitor shows a 'Warning' state. Format: HH:MM:SS.fff.
timeout: 00:00:02 # (Optional) Time after which the request is considered failed. Format: HH:MM:SS or HH:MM:SS.fff. Defaults to 00:00:05.
A passive monitor that waits for an external system to report ("check in") via a specific URL.
checkin-example:
!checkin
secret: your-secret-key # Required: A secret key that must be provided in the check-in request.
- The check-in URL is
/api/checkin/{monitorName}/{secret}
.- For the example above, it would be
/api/checkin/checkin-example/your-secret-key
.
- For the example above, it would be
- A
GET
orPOST
request to this URL marks the monitor as UP. - If a check-in is not received within the expected interval, the monitor is marked as DOWN.
- Configuration files over CRUD forms
- Hexagonal Architecture
- K.I.S.S.
- Do One Thing And Do It Well: Not a "Status Page" (with incidents, justifications, etc)
Deucalion.Core
: Base types and events shared between servers and clients.Deucalion.Application
: Core engine and configuration.Deucalion.Network
: Base network monitors.Deucalion.Storage
: Persistence and statistics.Deucalion.Api
: Server-side ASP.NET Web API application.Deucalion.Service
: Service Host forDeucalion.Api
. Can run as a Windows Service.Deucalion.Tests
: xUnit tests.Deucalion.Cli
: Sample command-line SignalR client.deucalion-ui
: Client-side React application.
Open Deucalion.sln
with Visual Studio 2022.
Start both Deucalion.Api
and deucalion-ui
projects. You may set multiple startup projects for this.
Do not use
Deucalion.Service
for debugging. It uses a static (pre-built) version of the UI (you need to runInvoke-Build Build
first).
Run
Invoke-Build Dev
This will start both Deucalion.Api
and deucalion-ui
projects in development mode. Any changes to source files will be detected and reloaded automatically.
In the Development environment, the log level for the Deucalion.Api
namespace is set to Debug
. This generates a log entry for each message received from EngineBackgroundService
.
For Production environments, the log level is Information
(the default). To change this, you can run the application with
--Logging:LogLevel:Deucalion=Debug
in the command line, or change the appropriate value in appsettings.json
.
Install Invoke-Build
.
Invoke-Build
or Invoke-Build build
will put all artifacts in the ./publish
folder.
Invoke-Build test
will run the unit tests using dotnet test
.