You've already forked caddy-opnsense-blocker
Expand public installation and API documentation
This commit is contained in:
229
docs/install.md
Normal file
229
docs/install.md
Normal file
@@ -0,0 +1,229 @@
|
||||
# Installation
|
||||
|
||||
This document covers both generic Linux deployments and NixOS deployments.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
You need:
|
||||
|
||||
- Linux.
|
||||
- Caddy access logs written to files in the default JSON format.
|
||||
- One readable log file per logical source you want to monitor.
|
||||
- A writable directory for the SQLite database.
|
||||
- Go 1.25 or newer if you build from source without Nix.
|
||||
- Optional: OPNsense API credentials if you want firewall alias synchronization.
|
||||
- Optional: outbound DNS and HTTPS access if you want IP investigation and bot verification.
|
||||
|
||||
## Deployment checklist
|
||||
|
||||
Before starting the daemon, decide:
|
||||
|
||||
- which Caddy log files you want to ingest
|
||||
- which heuristic profile each log file should use
|
||||
- whether the daemon should auto-block for each profile or only mark addresses for review
|
||||
- whether OPNsense integration is enabled
|
||||
- which address the web UI should listen on
|
||||
|
||||
## 1. Configure Caddy access logs
|
||||
|
||||
The daemon reads files, not stdout and not journald. Each monitored source should write to its own file.
|
||||
|
||||
An example Caddy configuration is available in [`../examples/Caddyfile`](../examples/Caddyfile).
|
||||
|
||||
Important points:
|
||||
|
||||
- Keep the default JSON log format.
|
||||
- Use one file per source.
|
||||
- Make sure the service account running `caddy-opnsense-blocker` can read those files.
|
||||
- If Caddy sits behind another proxy, make sure Caddy records the actual client IP in `request.client_ip`.
|
||||
|
||||
## 2. Prepare OPNsense credentials (optional)
|
||||
|
||||
If you want the daemon to block and unblock IP addresses on OPNsense:
|
||||
|
||||
1. Create or reuse an API key and secret.
|
||||
2. Decide which alias name should contain blocked IPs.
|
||||
3. Keep the credentials in files readable only by the service account.
|
||||
|
||||
If OPNsense integration is disabled, the daemon still ingests logs, records decisions, and supports manual review.
|
||||
|
||||
## 3. Build the binary
|
||||
|
||||
Clone the repository and build the daemon:
|
||||
|
||||
```bash
|
||||
git clone https://git.dern.ovh/infrastructure/caddy-opnsense-blocker.git
|
||||
cd caddy-opnsense-blocker
|
||||
CGO_ENABLED=0 go test ./...
|
||||
CGO_ENABLED=0 go build -o caddy-opnsense-blocker ./cmd/caddy-opnsense-blocker
|
||||
```
|
||||
|
||||
You can also use `nix-build` if you prefer the Nix package defined in this repository.
|
||||
|
||||
## 4. Create the runtime user and directories
|
||||
|
||||
Example for a non-NixOS host:
|
||||
|
||||
```bash
|
||||
useradd --system --home-dir /var/lib/caddy-opnsense-blocker --create-home --shell /usr/sbin/nologin blocker
|
||||
install -d -o blocker -g blocker -m 0750 /var/lib/caddy-opnsense-blocker
|
||||
install -d -o root -g blocker -m 0750 /etc/caddy-opnsense-blocker
|
||||
install -d -o root -g blocker -m 0750 /var/log/caddy
|
||||
install -m 0755 caddy-opnsense-blocker /usr/local/bin/caddy-opnsense-blocker
|
||||
```
|
||||
|
||||
If your Caddy logs are group-readable by a different group, either adjust permissions or grant the runtime user supplementary group access.
|
||||
|
||||
## 5. Create the configuration file
|
||||
|
||||
Start from the repository example:
|
||||
|
||||
```bash
|
||||
cp config.example.yaml /etc/caddy-opnsense-blocker/config.yaml
|
||||
chmod 0640 /etc/caddy-opnsense-blocker/config.yaml
|
||||
```
|
||||
|
||||
Then edit:
|
||||
|
||||
- `server.listen_address`
|
||||
- `storage.path`
|
||||
- `profiles`
|
||||
- `sources`
|
||||
- `opnsense.*` if OPNsense integration is enabled
|
||||
|
||||
For a field-by-field reference, see [`configuration.md`](configuration.md).
|
||||
|
||||
Store OPNsense credentials in files such as:
|
||||
|
||||
```bash
|
||||
install -m 0400 -o root -g blocker /path/to/api-key /etc/caddy-opnsense-blocker/opnsense-api-key
|
||||
install -m 0400 -o root -g blocker /path/to/api-secret /etc/caddy-opnsense-blocker/opnsense-api-secret
|
||||
```
|
||||
|
||||
Then reference those files from `config.yaml`.
|
||||
|
||||
## 6. Run the daemon manually once
|
||||
|
||||
Before installing a service unit, validate that the daemon starts correctly:
|
||||
|
||||
```bash
|
||||
sudo -u blocker /usr/local/bin/caddy-opnsense-blocker -config /etc/caddy-opnsense-blocker/config.yaml
|
||||
```
|
||||
|
||||
In another terminal:
|
||||
|
||||
```bash
|
||||
curl http://127.0.0.1:9080/healthz
|
||||
```
|
||||
|
||||
If the daemon is bound to another address, adjust the URL accordingly.
|
||||
|
||||
## 7. Install the systemd service
|
||||
|
||||
An example unit file is available in [`../examples/caddy-opnsense-blocker.service`](../examples/caddy-opnsense-blocker.service).
|
||||
|
||||
Typical installation steps:
|
||||
|
||||
```bash
|
||||
cp examples/caddy-opnsense-blocker.service /etc/systemd/system/caddy-opnsense-blocker.service
|
||||
systemctl daemon-reload
|
||||
systemctl enable --now caddy-opnsense-blocker.service
|
||||
```
|
||||
|
||||
After that:
|
||||
|
||||
```bash
|
||||
systemctl status caddy-opnsense-blocker.service
|
||||
journalctl -u caddy-opnsense-blocker.service -f
|
||||
```
|
||||
|
||||
## 8. Verify end-to-end behavior
|
||||
|
||||
Recommended checks:
|
||||
|
||||
- `GET /healthz` returns `{"status":"ok",...}`
|
||||
- the UI loads on the configured address
|
||||
- new suspicious requests appear in the dashboard
|
||||
- the IP detail page shows the full request history for one address
|
||||
- manual `Block` and `Unblock` actions produce backend actions if OPNsense is enabled
|
||||
|
||||
## 9. Log rotation and upgrades
|
||||
|
||||
- The daemon stores inode and offset per source, so it can resume after restarts.
|
||||
- File truncation or inode changes are detected automatically, which makes the common rename-based log rotation pattern safe.
|
||||
- Upgrades are usually just “replace the binary, restart the service”. The SQLite database is kept separately in the configured state directory.
|
||||
|
||||
## Nix build
|
||||
|
||||
Build the packaged binary directly from the repository root:
|
||||
|
||||
```bash
|
||||
nix-build
|
||||
```
|
||||
|
||||
The result symlink contains the packaged daemon under `result/bin/caddy-opnsense-blocker`.
|
||||
|
||||
## NixOS module
|
||||
|
||||
The repository includes a reusable NixOS module in [`../module.nix`](../module.nix).
|
||||
|
||||
### Import from a local checkout
|
||||
|
||||
```nix
|
||||
{
|
||||
imports = [ /path/to/caddy-opnsense-blocker/module.nix ];
|
||||
|
||||
services.caddy-opnsense-blocker = {
|
||||
enable = true;
|
||||
credentials.opnsenseApiKeyFile = "/run/secrets/opnsense-api-key";
|
||||
credentials.opnsenseApiSecretFile = "/run/secrets/opnsense-api-secret";
|
||||
|
||||
settings = {
|
||||
server.listen_address = "127.0.0.1:9080";
|
||||
|
||||
opnsense = {
|
||||
enabled = true;
|
||||
base_url = "https://router.example.test";
|
||||
ensure_alias = true;
|
||||
alias.name = "blocked-ips";
|
||||
};
|
||||
|
||||
profiles.public-web = {
|
||||
auto_block = true;
|
||||
block_unexpected_posts = true;
|
||||
block_php_paths = true;
|
||||
suspicious_path_prefixes = [ "/wp-admin" "/wp-login.php" "/.env" ];
|
||||
};
|
||||
|
||||
sources = [
|
||||
{
|
||||
name = "public-web";
|
||||
path = "/var/log/caddy/public-web-access.json";
|
||||
profile = "public-web";
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
### Notes about the NixOS module
|
||||
|
||||
- The module defaults the service user and group to `caddy`.
|
||||
- The generated configuration file is written from `services.caddy-opnsense-blocker.settings`.
|
||||
- OPNsense credentials can be injected through systemd credentials with `credentials.opnsenseApiKeyFile` and `credentials.opnsenseApiSecretFile`.
|
||||
- The default database path is `/var/lib/caddy-opnsense-blocker/caddy-opnsense-blocker.db`.
|
||||
|
||||
## Operating without OPNsense
|
||||
|
||||
Set `opnsense.enabled: false` to run in review-only mode.
|
||||
|
||||
In that mode the daemon still:
|
||||
|
||||
- ingests logs
|
||||
- stores events and IP state
|
||||
- runs investigations
|
||||
- serves the UI and API
|
||||
- records manual override decisions locally
|
||||
|
||||
It simply stops short of calling an external firewall API.
|
||||
Reference in New Issue
Block a user