Skip to content

Install

This is the 15-minute path on a fresh Ubuntu 24.04. Adapt for Debian, RHEL, etc.

What you need before starting

  • One Linux server with sudo
  • Python 3.12+
  • Outbound HTTPS to api.openrouter.ai, api.telegram.org, optionally cloudflare.com for the tunnel
  • A Telegram bot token (create one with @BotFather)
  • Optional: an OpenRouter API key for cloud LLM fallback

1. System packages

sudo apt update
sudo apt install -y python3 python3-venv python3-pip git fail2ban ufw \
                    nginx postgresql nginx-extras apache2-utils

apache2-utils is for htpasswd (used by the optional dashboard reverse-proxy basic auth, see deploy/fenrirsoc/).

2. Clone and set up the venv

sudo useradd -r -s /usr/sbin/nologin -m -d /home/p3guardian p3guardian || true
sudo usermod -a -G adm p3guardian   # so it can read /var/log/*

cd /opt
sudo git clone https://github.com/P3consultingtech/p3guardian.git
sudo chown -R p3guardian:p3guardian /opt/p3guardian
cd /opt/p3guardian

sudo -u p3guardian python3 -m venv .venv
sudo -u p3guardian .venv/bin/pip install -e .

3. Configure .env

Create /opt/p3guardian/.env with at minimum:

# Database โ€” leave empty for SQLite, fill for PostgreSQL
DATABASE_URL=postgresql://p3guardian:<password>@localhost/p3guardian

# Telegram
TELEGRAM_BOT_TOKEN=<your-telegram-bot-token>
TELEGRAM_CHAT_ID=<your-chat-id>

# AI backend โ€” at least one of:
OPENROUTER_API_KEY=<your-openrouter-key>          # cloud, faster
OPENROUTER_MODEL=qwen/qwen3.5-flash-02-23
# or:
OLLAMA_URL=http://127.0.0.1:11434
OLLAMA_MODEL=qwen3:0.6b

# Public URL (used in Telegram links, can be LAN IP for dev)
WEB_PUBLIC_URL=https://app.<your-domain>

# GDPR breach notifications (recommended)
BREACH_NOTIFICATION_ENABLED=true
BREACH_NOTIFICATION_EMAIL=<your-dpo-email>

Full reference: Environment variables.

sudo chown p3guardian:p3guardian /opt/p3guardian/.env
sudo chmod 0640 /opt/p3guardian/.env

4. Create the database (PostgreSQL path)

sudo -u postgres psql <<EOF
CREATE USER p3guardian WITH PASSWORD '<password>';
CREATE DATABASE p3guardian OWNER p3guardian;
GRANT ALL PRIVILEGES ON DATABASE p3guardian TO p3guardian;
EOF

Tables are created automatically on first start by Base.metadata.create_all. No migrations to run.

5. systemd unit

/etc/systemd/system/p3guardian.service
[Unit]
Description=P3 Guardian โ€” AI Security Monitor (Fenrir SOC)
After=network-online.target postgresql.service
Wants=network-online.target

[Service]
Type=simple
User=p3guardian
Group=p3guardian
WorkingDirectory=/opt/p3guardian
EnvironmentFile=/opt/p3guardian/.env
ExecStart=/opt/p3guardian/.venv/bin/python -m p3guardian
Restart=on-failure
RestartSec=5
StandardOutput=journal
StandardError=journal

# Hardening
ProtectSystem=full
ProtectHome=true
PrivateTmp=true
NoNewPrivileges=true

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now p3guardian.service
sudo systemctl status p3guardian.service

6. Verify

# Service is active
systemctl is-active p3guardian.service

# Logs are flowing
sudo journalctl -u p3guardian -n 30 --no-pager

# Dashboard responds
curl -s http://127.0.0.1:8443/api/stats | python3 -m json.tool

You should see all 9 monitors logged as Monitor started: in the journal:

auth     -> /var/log/auth.log
honeypot -> /var/log/nginx/honeypot.log
fail2ban -> /var/log/fail2ban.log
nginx    -> /var/log/nginx/access.log
ufw      -> /var/log/ufw.log
kernel   -> /var/log/kern.log
package  -> /var/log/dpkg.log
baseline -> [periodic:600s]
cve      -> [periodic:21600s]

And on Telegram, your bot should send a startup message:

๐Ÿ›ก P3 Guardian v0.5.0 Online
๐Ÿ“ก Monitoring 9 log sources
๐Ÿค– AI Analysis: enabled
...

7. Smoke test detection

Trigger a fake honeypot hit from outside your LAN (LAN IPs are whitelisted by default โ€” see IP_WHITELIST in env vars):

curl -A 'TestBot/1.0' https://<your-domain>/wp-admin/install.php

Within ~1 second you should see:

  • A new row in events with source='honeypot', category='honeypot_hit', severity=HIGH
  • An investigation_jobs row entering status='investigating'
  • 30-90 seconds later, a Telegram alert with the analyst's verdict
  • A new entry on the dashboard's AI Investigations panel

8. Optional: expose the dashboard publicly

The dashboard listens on 127.0.0.1:8443. To expose it via Cloudflare Tunnel + nginx with basic auth, see the bundled deploy/fenrirsoc/ recipe.

cd /opt/p3guardian
sudo bash deploy/fenrirsoc/install.sh

Then change the placeholder password:

sudo htpasswd /etc/nginx/.htpasswd-app admin

9. Optional: enable Autonomous Response (after week 1)

Out of the box, Fenrir's responder pipeline is limited to fail2ban IP banning. Sprint 2 adds five revertible host-level actions โ€” kill_process, file_quarantine, service_stop, isolate_network, package_rollback โ€” gated by analyst confidence and revertible from Telegram or /autonomous.

These are disabled by default. The recommended rollout:

# Week 1 โ€” passive observation only. The dispatcher persists everything
# it WOULD have done, but executes nothing.
AUTO_ACTION_ENABLED=true
AUTO_ACTION_DRY_RUN=true
AUTO_ACTION_MIN_CONFIDENCE=85
AUTO_ACTION_TYPES=kill_process,file_quarantine,service_stop

After 7 days, review every row on the dashboard's /autonomous page. Confirm no false positives would have hit critical processes. Add anything missing to AUTO_ACTION_PROCESS_WHITELIST. Then:

AUTO_ACTION_DRY_RUN=false   # actions now execute

Full operational checklist: Autonomous response.

Before you go internet-facing

The defaults shipped above are picked for a 15-minute first install. Several of them are intentionally permissive for development convenience and must be changed before production exposure: the IP whitelist, the dashboard authentication, the LLM model size, the auto-action confidence threshold.

Read the Hardening checklist before exposing this server to the internet. Five-minute review, prevents the obvious own-goals.

What's next