- Posted on
- • Artificial Intelligence
Artificial Intelligence Raspberry Pi Security
- Author
-
-
- User
- linuxbash
- Posts by this author
- Posts by this author
-
Artificial Intelligence + Raspberry Pi Security: A Practical, Bash‑First Guide
If your Raspberry Pi is always on, it’s always a target. Bots comb the internet for weak SSH passwords, misconfigured services, and exposed cameras. The good news: today’s tiny boards can run real AI at the edge. In this guide, you’ll harden your Pi and then put it to work defending your home or lab with lightweight AI—no datacenter required.
What you’ll get:
A fast baseline hardening checklist (with apt, dnf, and zypper commands)
A person-detecting “AI camera sentinel” using TensorFlow Lite and the built-in camera
A production‑friendly alternative using Frigate NVR in Docker
Sandboxing tips to secure your AI workloads
Why combine AI and Pi security?
Edge privacy: Keep raw video/logs local. Send only alerts off-device.
Low cost and low power: Pi‑class boards handle basic models 24/7 for pennies.
Resilience: AI augments simple motion or port scans with semantic detection (e.g., only alert when a person is seen).
Skills that scale: The same hardening and MLOps patterns apply to servers and fleets.
1) Baseline: Harden your Raspberry Pi before you add AI
Do these first. It’s faster than incident response.
Update everything and reboot
- apt (Raspberry Pi OS/Debian/Ubuntu):
sudo apt update && sudo apt full-upgrade -y && sudo reboot- dnf (Fedora):
sudo dnf upgrade --refresh -y && sudo systemctl reboot- zypper (openSUSE):
sudo zypper refresh && sudo zypper update -y && sudo systemctl rebootCreate a new user, lock down the default one (if it exists), and set strong passwords
sudo adduser aiadmin sudo usermod -aG sudo aiadmin # Optional: lock the 'pi' account if present sudo passwd -l pi || trueInstall and harden SSH (key‑only auth)
- apt:
sudo apt install -y openssh-server- dnf:
sudo dnf install -y openssh-server- zypper:
sudo zypper install -y opensshThen:
mkdir -p ~/.ssh && chmod 700 ~/.ssh nano ~/.ssh/authorized_keys # paste your public key chmod 600 ~/.ssh/authorized_keys sudo nano /etc/ssh/sshd_config # Set or ensure: # PasswordAuthentication no # PermitRootLogin no # PubkeyAuthentication yes sudo systemctl restart ssh || sudo systemctl restart sshdEnable a host firewall
- Debian/Ubuntu/openSUSE using UFW:
- Install
- apt:
sudo apt install -y ufw - zypper:
sudo zypper install -y ufw
- apt:
- Configure:
sudo ufw default deny incoming sudo ufw default allow outgoing sudo ufw allow OpenSSH sudo ufw enable sudo ufw status - Fedora/openSUSE using firewalld:
- Install (if needed) and enable
- dnf:
sudo dnf install -y firewalld sudo systemctl enable --now firewalld - zypper:
sudo zypper install -y firewalld sudo systemctl enable --now firewalld
- dnf:
- Allow SSH and reload:
sudo firewall-cmd --permanent --add-service=ssh sudo firewall-cmd --reload
Ban brute‑force attempts with Fail2ban
- apt:
sudo apt install -y fail2ban- dnf:
sudo dnf install -y fail2ban- zypper:
sudo zypper install -y fail2banThen:
sudo systemctl enable --now fail2ban sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local sudo nano /etc/fail2ban/jail.local # Ensure [sshd] enabled = true, adjust bantime/findtime/maxretry sudo systemctl restart fail2banSet up unattended updates (recommended)
- apt:
sudo apt install -y unattended-upgrades sudo dpkg-reconfigure --priority=low unattended-upgrades- dnf (Fedora):
sudo dnf install -y dnf-automatic sudo sed -i 's/^apply_updates = .*/apply_updates = yes/' /etc/dnf/automatic.conf sudo systemctl enable --now dnf-automatic.timer- zypper (openSUSE) via a simple cron job:
(crontab -l 2>/dev/null; echo "30 3 * * * /usr/bin/sudo /usr/bin/zypper -n refresh && /usr/bin/sudo /usr/bin/zypper -n update") | crontab -
2) Real‑world example: Build an “AI Camera Sentinel” with TensorFlow Lite
Goal: Use your Pi camera to detect people and trigger an alert—no cloud, no streaming your living room to strangers.
What this does:
Captures frames using libcamera
Runs a lightweight TFLite object detector locally
Sends a webhook when “person” is detected with a chosen confidence
Prereqs: Raspberry Pi OS (64‑bit recommended), a Pi Camera Module (libcamera era), or USB camera that works with libcamera.
Install camera tools
apt:
sudo apt install -y libcamera-apps unzipdnf (Fedora on Pi):
sudo dnf install -y libcamera libcamera-tools unzipzypper (openSUSE on Pi):
sudo zypper install -y libcamera libcamera-tools unzip
Install Python runtime and create a venv
apt:
sudo apt install -y python3 python3-venv python3-pipdnf:
sudo dnf install -y python3 python3-pipzypper:
sudo zypper install -y python3 python3-pipCreate and activate:
python3 -m venv ~/ai-sec
source ~/ai-sec/bin/activate
pip install --upgrade pip
Install minimal AI dependencies (TensorFlow Lite runtime + Pillow + NumPy)
pip install tflite-runtime==2.12.0 pillow numpy requests
Note: If tflite-runtime fails on your architecture, see Google Coral’s prebuilt wheels or switch to Raspberry Pi OS 64‑bit.
Get a quantized MobileNet SSD model and labels
mkdir -p ~/ai-sentinel && cd ~/ai-sentinel
curl -L -o model.zip https://storage.googleapis.com/download.tensorflow.org/models/tflite/coco_ssd_mobilenet_v1_1.0_quant_2018_06_29.zip
unzip model.zip
# This archive contains detect.tflite and labelmap.txt (or similar)
ls
Create the sentinel script
nano ~/ai-sentinel/sentinel.py
Paste:
#!/usr/bin/env python3
import os, subprocess, time, json
from pathlib import Path
import numpy as np
from PIL import Image
import requests
from tflite_runtime.interpreter import Interpreter
MODEL = str(Path(__file__).with_name("detect.tflite"))
LABELS_FILE = str(Path(__file__).with_name("labelmap.txt"))
THRESHOLD = float(os.getenv("PERSON_THRESHOLD", "0.55"))
CAPTURE_CMD = ["libcamera-still", "-n", "-t", "1", "-o"] # non-interactive, one shot
FRAME = str(Path("/tmp/ai_frame.jpg"))
WEBHOOK_URL = os.getenv("WEBHOOK_URL", "") # set to your endpoint, or leave empty to log only
SLEEP = float(os.getenv("SLEEP_SECONDS", "2.0"))
def load_labels(path):
labels = {}
with open(path, "r") as f:
for i, line in enumerate(f):
labels[i] = line.strip()
return labels
def notify(payload, image_path=None):
print("[AI] Alert:", payload)
if WEBHOOK_URL:
try:
if image_path and os.path.exists(image_path):
with open(image_path, "rb") as img:
requests.post(WEBHOOK_URL, data={"alert": json.dumps(payload)}, files={"image": img}, timeout=5)
else:
requests.post(WEBHOOK_URL, json=payload, timeout=5)
except Exception as e:
print("[AI] webhook error:", e)
def capture_frame(path):
subprocess.run(CAPTURE_CMD + [path], check=True)
def preprocess(path, input_shape):
im = Image.open(path).convert("RGB").resize((input_shape[1], input_shape[2]))
arr = np.asarray(im)
return np.expand_dims(arr, axis=0).astype(np.uint8)
def main():
labels = load_labels(LABELS_FILE)
interpreter = Interpreter(model_path=MODEL, num_threads=2)
interpreter.allocate_tensors()
input_details = interpreter.get_input_details()
output_details = interpreter.get_output_details()
input_shape = input_details[0]["shape"]
while True:
try:
capture_frame(FRAME)
input_data = preprocess(FRAME, input_shape)
interpreter.set_tensor(input_details[0]["index"], input_data)
interpreter.invoke()
boxes = interpreter.get_tensor(output_details[0]["index"])[0]
classes = interpreter.get_tensor(output_details[1]["index"])[0].astype(int)
scores = interpreter.get_tensor(output_details[2]["index"])[0]
for cls, score, box in zip(classes, scores, boxes):
label = labels.get(cls, str(cls))
if label.lower() == "person" and score >= THRESHOLD:
payload = {
"event": "person_detected",
"confidence": float(score),
"timestamp": time.time(),
}
notify(payload, FRAME)
time.sleep(3) # avoid flooding
break
except subprocess.CalledProcessError:
print("[AI] capture failed, retrying...")
except Exception as e:
print("[AI] error:", e)
time.sleep(SLEEP)
if __name__ == "__main__":
main()
Make it executable:
chmod +x ~/ai-sentinel/sentinel.py
Quick test:
WEBHOOK_URL="" PERSON_THRESHOLD=0.6 SLEEP_SECONDS=1.5 ~/ai-sentinel/sentinel.py
You should see console alerts when a person is in frame. Set WEBHOOK_URL to integrate with your home automation, chat, or a simple webhook catcher.
Optional: run as a systemd service (with sandboxing)
sudo useradd -r -s /usr/sbin/nologin ai
sudo install -d -o ai -g ai /var/lib/ai-sentinel
sudo nano /etc/systemd/system/ai-sentinel.service
Paste:
[Unit]
Description=AI Camera Sentinel (TFLite)
After=network-online.target
[Service]
User=ai
Group=ai
Environment=SLEEP_SECONDS=1.5
Environment=PERSON_THRESHOLD=0.6
# Set your webhook here or use an EnvironmentFile
# Environment=WEBHOOK_URL=https://example.net/webhook
ExecStart=/home/%i/ai-sentinel/sentinel.py
WorkingDirectory=/home/%i/ai-sentinel
# Security hardening
NoNewPrivileges=yes
PrivateTmp=yes
ProtectSystem=strict
ProtectHome=yes
ProtectKernelTunables=yes
ProtectKernelModules=yes
ProtectControlGroups=yes
LockPersonality=yes
MemoryDenyWriteExecute=yes
SystemCallFilter=@system-service
ReadWritePaths=/tmp
# Camera needs access to /dev/video*; allow device nodes:
DeviceAllow=/dev/video0 rw
Restart=always
RestartSec=3
[Install]
WantedBy=multi-user.target
Important: Replace ExecStart/WorkingDirectory paths for the ai user, or run as your own user and adjust permissions. Then:
sudo systemctl daemon-reload
sudo systemctl enable --now ai-sentinel.service
sudo systemctl status ai-sentinel.service
Pro tips:
Prefer Raspberry Pi OS 64‑bit for better package and wheel support.
Tune THRESHOLD to balance sensitivity and false positives.
Store frames only when an alert triggers to protect privacy.
3) Production‑ready option: Frigate NVR + Docker (with or without Coral)
If you want multi‑camera, zones, and polished alerts, Frigate NVR is a great open‑source option that runs on Pi. It uses object detection to reduce noise vs. motion‑only systems.
Install Docker Engine
apt (Debian/Ubuntu/Raspberry Pi OS):
sudo apt install -y docker.io docker-compose-plugin sudo usermod -aG docker $USER newgrp docker sudo systemctl enable --now dockerdnf (Fedora):
sudo dnf install -y moby-engine docker-compose-plugin sudo usermod -aG docker $USER newgrp docker sudo systemctl enable --now dockerzypper (openSUSE):
sudo zypper install -y docker docker-compose sudo usermod -aG docker $USER newgrp docker sudo systemctl enable --now docker
Create a minimal docker compose for Frigate
mkdir -p ~/frigate && cd ~/frigate
nano docker-compose.yml
Paste:
services:
frigate:
image: ghcr.io/blakeblackshear/frigate:stable
container_name: frigate
privileged: true
restart: unless-stopped
shm_size: "64mb"
volumes:
- ./config:/config
- /etc/localtime:/etc/localtime:ro
- /dev/bus/usb:/dev/bus/usb # needed if using Coral USB
ports:
- "5000:5000" # web UI
- "8554:8554" # RTSP restream
environment:
- FRIGATE_RTSP_PASSWORD=changeme
Create a basic config:
mkdir -p config
nano config/config.yml
Example:
mqtt: null
detectors:
coral:
type: edgetpu
device: usb
cameras:
front:
ffmpeg:
inputs:
- path: rtsp://user:pass@yourcamera/stream1
roles: [detect, record]
detect:
enabled: true
max_disappeared: 25
Start it:
docker compose up -d
Open http://
Security tips for Docker:
Don’t publish ports to the internet; keep them on your LAN or behind a VPN.
Run on a dedicated VLAN if possible and apply firewall rules (UFW/firewalld) to limit access.
Keep Frigate and OS updated.
4) Secure your AI workloads like production software
Verify model integrity
sha256sum detect.tflite > detect.tflite.sha256 # Keep the checksum under version control; verify after updates: sha256sum -c detect.tflite.sha256Least privilege: run as a non‑root user, grant only needed device access (/dev/video0).
Sandboxing: use systemd directives (ProtectSystem, PrivateTmp, NoNewPrivileges, DeviceAllow) as shown above.
Network egress control: if your AI app doesn’t need internet, block it.
- UFW example:
sudo ufw default deny outgoing sudo ufw allow out 53,123/udp # DNS/NTP if needed- firewalld example:
sudo firewall-cmd --permanent --add-rich-rule='rule family=ipv4 source address=0.0.0.0/0 drop' sudo firewall-cmd --reloadAdjust to your needs or use zones/interfaces for fine control.
Backups and logs: store configs under git, rotate logs with logrotate, and snapshot your SD/SSD periodically.
Troubleshooting quick hits
Camera errors: ensure camera is enabled and only one process owns /dev/video0. Test:
libcamera-still -n -t 1000 -o test.jpgPython wheels: if numpy/tflite wheels fail to install, switch to 64‑bit Raspberry Pi OS and retry.
Performance: reduce frame rate or inference frequency (SLEEP_SECONDS) to keep CPU temps down; add a small heatsink/fan if running 24/7.
Conclusion and next steps
You now have a hardened Raspberry Pi that can detect real‑world events with local AI. Start small with the AI Camera Sentinel, or go big with Frigate NVR. Next:
Automate alerts to your preferred system (Home Assistant, Matrix/Slack, email, or webhooks).
Add zones and schedules to reduce noise.
Expand to other AI sensors (audio anomaly detection, package detection, license plates—always respecting local laws and privacy).
Have a favorite tweak or want a follow‑up on GPU/TPU acceleration, audio anomaly detection, or multi‑Pi fleet hardening? Tell me what you’re building and I’ll tailor the next guide.