Start
Getting started
Add the flake, turn on a hub and its agents, store two tokens in the vault, unlock it. Most of the work is writing down what you expect your hosts to look like.
Requirements
- NixOS hosts joined by WireGuard (
wg0). The agent binds to the host’swg0address; the hub reaches every agent over it. - A local MTA on the hub host listening on
127.0.0.1:25for alert mail, and a local resolver on127.0.0.1:53for blocklist lookups (public resolvers are refused by most blocklists). - A reverse proxy for the status page, if it should be public.
- Optional: a Linode and a Cloudflare read-only token, a Cert Spotter API key, and a heartbeat URL (healthchecks.io or similar).
Add the flake
inputs.sitescope.url = "github:toppk/sitescope";
inputs.sitescope.inputs.nixpkgs.follows = "nixpkgs";and import inputs.sitescope.nixosModules.default on each
host.
Write the environment file
On every host, outside the Nix store and readable only by root:
# /var/lib/sitescope-secrets/sitescope.env
SITESCOPE_AGENT_TOKEN=<the same long random value on every host>
SITESCOPE_HEARTBEAT_URL=https://hc-ping.com/<uuid> # hub onlyopenssl rand -hex 32 makes a good token.
Turn on the hub
On the host that watches the others (it can watch itself too):
services.sitescope = {
enable = true;
role = "hub";
agent = { enable = true; listenAddress = "10.0.0.2"; }; # this host's wg0 address
environmentFile = "/var/lib/sitescope-secrets/sitescope.env";
settings = import ./sitescope-settings.nix { inherit lib; };
};
users.users.alice.extraGroups = [ "sitescope-admin" ];
networking.firewall.interfaces.wg0.allowedTCPPorts = [ 9105 ];Point the reverse proxy for your status hostname at
127.0.0.1:8470.
Turn on the agents
On every other host:
services.sitescope = {
enable = true;
role = "agent";
listenAddress = "10.0.0.3"; # this host's wg0 address
environmentFile = "/var/lib/sitescope-secrets/sitescope.env";
};
networking.firewall.interfaces.wg0.allowedTCPPorts = [ 9105 ];The agent turns on its postfix and Knot sections by itself when those services are enabled on the host.
Describe what you expect
settings is where the hosts, zones, certificates and
URLs go. A minimal start:
{
alerts = { enabled = true; from = "sitescope@example.org"; to = [ "ops@example.org" ]; digestTime = "08:00"; };
hub.publicURL = "https://status.example.org";
hosts.hosts = [
{ name = "a"; url = "http://10.0.0.1:9105"; knot = true; }
{ name = "b"; url = "http://10.0.0.2:9105"; postfix = true; }
];
dns = { zones = [ "example.org" ]; primary = "10.0.0.1"; };
tls.targets = [ { name = "www.example.org"; } ];
http.targets = [ { name = "www"; url = "https://www.example.org/"; } ];
}Configuration lists every key, and Checks what each section checks. Before deploying, try it:
nix build github:toppk/sitescope
nix eval --json .#nixosConfigurations.hub.config.services.sitescope.settings > /tmp/sitescope.json
./result/bin/sitescope check -config /tmp/sitescope.jsonSet up the vault
After the first deploy, on the hub host:
sudo -u sitescope sitescope vault set linode_token # creates the vault, asks for a new passphrase twice
sudo -u sitescope sitescope vault set cloudflare_token
sudo -u sitescope sitescope vault set-password # password for the detail view (user "admin")
sitescope unlockThe hub sends “vault LOCKED” email every time it starts, and the
hub.vault check warns if the vault is still locked 15
minutes later. Run sitescope unlock again after each
restart. See Vault and secrets.