You've already forked caddy-opnsense-blocker
230 lines
6.9 KiB
Markdown
230 lines
6.9 KiB
Markdown
# 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.
|