⚡ Quick Start: For automated installation, use
sudo ./scripts/deploy.shinstead! See QUICK-START.md for the fastest deployment method.This guide provides manual step-by-step instructions for advanced users who want to understand or customize the deployment process, or for troubleshooting purposes.
Before proceeding, ensure you have completed PREREQUISITES.md:
- RHEL 10 (or RHEL 9)
- Podman installed
- SELinux enforcing
- Required packages installed
- Firewall configured
- 10 GB free space in
/var/lib - Created
.envfile fromenv.example
# Copy template
cp env.example .env
# Edit configuration
vim .env
# Secure the file
chmod 600 .env.env:
OXIDIZED_PASSWORD- Change from default!OXIDIZED_USERNAME- Your device login username- Review all other settings for your environment
Install all required packages:
sudo dnf install -y \
podman \
policycoreutils-python-utils \
git \
logrotate \
curl \
jqVerify installation:
podman --version
git --version
getenforce # Should show: EnforcingCreate the persistent storage directory structure on the host:
# Create main directory
sudo mkdir -p /srv/oxidized
# Create subdirectories
sudo mkdir -p /srv/oxidized/config
sudo mkdir -p /var/lib/oxidized/config
sudo mkdir -p /srv/oxidized/data
sudo mkdir -p /srv/oxidized/git
sudo mkdir -p /srv/oxidized/logs
# Set ownership (root owns host directories)
sudo chown -R root:root /srv/oxidized
# Set permissions
sudo chmod 755 /srv/oxidized
sudo chmod 755 /srv/oxidized/config
sudo chmod 750 /var/lib/oxidized/config
sudo chmod 755 /srv/oxidized/data
sudo chmod 755 /srv/oxidized/git
sudo chmod 755 /srv/oxidized/logsVerify directory structure:
tree /srv/oxidized
# Expected output:
# /srv/oxidized/
# ├── config/
# ├── config/
# ├── data/
# ├── git/
# └── logs/Copy the Oxidized configuration file:
# From this repository
sudo cp config/oxidized/config /srv/oxidized/config/config
# Verify
ls -la /srv/oxidized/config/configCreate your device inventory file (router.db):
# Copy template
sudo cp inventory/router.db.template /var/lib/oxidized/config/router.db
# Edit with your devices
sudo vim /var/lib/oxidized/config/router.db
# Set secure permissions
sudo chown 2000:2000 /var/lib/oxidized/config/router.db
sudo chmod 600 /var/lib/oxidized/config/router.dbFormat: Colon-delimited CSV (:)
name:ip:model:group:username:password
core-router01:10.1.1.1:ios:core::
edge-switch01:10.1.2.1:procurve:distribution::
firewall01:10.1.3.1:fortios:firewalls::
Supported Models: ios, iosxr, nxos, asa, junos, eos, and many more.
IMPORTANT: Update the credentials in /srv/oxidized/config/config:
sudo vim /srv/oxidized/config/configModify these lines:
username: your_device_username
password: your_device_passwordSecurity Note: For production, consider using environment variables or a secrets manager instead of plaintext passwords.
Install the logrotate configuration:
sudo cp config/logrotate/oxidized /etc/logrotate.d/oxidized
# Verify
ls -la /etc/logrotate.d/oxidized
# Test logrotate configuration
sudo logrotate -d /etc/logrotate.d/oxidizedInitialize the Git repository where Oxidized will store device configurations:
Option A: Regular Git Repository (Recommended)
# Initialize regular Git repository
sudo git init /srv/oxidized/git/configs.git
# Configure Git
cd /srv/oxidized/git/configs.git
sudo git config user.name "Oxidized"
sudo git config user.email "oxidized@example.com"
# Create initial commit
sudo touch README.md
echo "# Network Device Configurations" | sudo tee README.md
sudo git add README.md
sudo git commit -m "Initial commit"Option B: Bare Git Repository (Alternative)
# Initialize bare repository (if you prefer)
sudo git init --bare /srv/oxidized/git/configs.git
# Configure repository
cd /srv/oxidized/git/configs.git
sudo git config user.name "Oxidized"
sudo git config user.email "oxidized@example.com"Why Regular vs Bare?
- Regular repository: Easier to inspect, view files directly, better for single-server setups
- Bare repository: More traditional for Git output, required if pushing to remotes
This deployment uses regular repository by default for simplicity.
Verify Git initialization:
ls -la /srv/oxidized/git/configs.git
# Should show .git directory (regular) or Git objects (bare)Install the Quadlet configuration file for systemd:
# Copy Quadlet file to systemd directory
sudo cp containers/quadlet/oxidized.container \
/etc/containers/systemd/oxidized.container
# Verify
ls -la /etc/containers/systemd/oxidized.container
# Display contents
cat /etc/containers/systemd/oxidized.containerThe Quadlet file defines:
- Container image and version
- Port bindings (8888)
- Volume mounts with SELinux context
- Restart policies
- Resource limits
Reload systemd to detect the new Quadlet configuration:
# Reload systemd daemon
sudo systemctl daemon-reloadThe Quadlet will automatically generate a systemd service file. Verify it was created:
# Check generated service file
sudo systemctl cat oxidized.serviceEnable the service to start on boot:
# Enable service
sudo systemctl enable oxidized.serviceStart the service:
# Start Oxidized
sudo systemctl start oxidized.serviceCheck service status:
# View status
sudo systemctl status oxidized.service
# Expected output:
# ● oxidized.service - Oxidized Network Configuration Backup Service
# Loaded: loaded (/etc/containers/systemd/oxidized.container; enabled)
# Active: active (running) since ...# List running containers
podman ps
# Expected output should show oxidized container running
# CONTAINER ID IMAGE COMMAND CREATED
# abc123def456 docker.io/oxidized/oxidized:0.35.0 2 minutes ago
# STATUS PORTS NAMES
# Up 2 minutes 0.0.0.0:8888->8888/tcp oxidized# View container logs
podman logs oxidized
# Follow logs in real-time
podman logs -f oxidized
# Check for initialization messages
podman logs oxidized | grep -i "oxidized"# Check API health
curl -s http://localhost:8888/
# List all nodes
curl -s http://localhost:8888/nodes.json | jq '.'
# Expected output: JSON array of devicesOpen a web browser and navigate to:
http://<your-server-ip>:8888
You should see the Oxidized web interface with your device list.
Wait for the first polling interval (up to 1 hour for hourly polling), or trigger a manual backup:
# Trigger manual backup via API
curl -X POST http://localhost:8888/reload
# Check node status
curl -s http://localhost:8888/nodes.json | jq '.[] | {name, last: .last}'# List Git commits
cd /srv/oxidized/git/configs.git
sudo git log --oneline
# Expected output: commits for each device backup# Check log file exists
ls -la /srv/oxidized/logs/oxidized.log
# View log contents
sudo tail -f /srv/oxidized/logs/oxidized.log# Allow port 8888 for internal zone
sudo firewall-cmd --zone=internal --add-port=8888/tcp --permanent
sudo firewall-cmd --reload# Manually test log rotation
sudo logrotate -f /etc/logrotate.d/oxidized
# Verify rotated logs
ls -la /srv/oxidized/logs/Set up monitoring using the Oxidized API. See docs/monitoring/ZABBIX.md for details.
Create periodic backups of the configuration and Git repository:
# Create backup script (example)
sudo tee /usr/local/bin/backup-oxidized.sh > /dev/null <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
BACKUP_DIR="/var/backups/oxidized"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
mkdir -p "${BACKUP_DIR}"
# Backup Git repository
tar -czf "${BACKUP_DIR}/oxidized-git-${TIMESTAMP}.tar.gz" \
-C /srv/oxidized git/
# Backup configuration
tar -czf "${BACKUP_DIR}/oxidized-config-${TIMESTAMP}.tar.gz" \
-C /var/lib/oxidized config/
# Keep only last 7 days
find "${BACKUP_DIR}" -type f -mtime +7 -delete
echo "Backup completed: ${TIMESTAMP}"
EOF
sudo chmod +x /usr/local/bin/backup-oxidized.sh
# Test backup
sudo /usr/local/bin/backup-oxidized.sh# Check systemd status
sudo systemctl status oxidized.service
# Check journal logs
sudo journalctl -u oxidized.service -n 50
# Check Podman logs
podman logs oxidized# Check what's using port 8888
sudo netstat -tulpn | grep 8888
# Or with ss
sudo ss -tulpn | grep 8888
# Stop conflicting service or change port in Quadlet# Check for SELinux denials
sudo ausearch -m avc -ts recent
# If denials exist, verify :Z flag is set in Quadlet mounts
grep "Volume=" /etc/containers/systemd/oxidized.container# Check directory permissions
ls -laZ /srv/oxidized/
# Verify SELinux context
ls -ldZ /srv/oxidized/*
# Restart container to reapply context
sudo systemctl restart oxidized.service# Check device inventory
cat /var/lib/oxidized/config/router.db
# Verify credentials in config
sudo cat /srv/oxidized/config/config | grep -A2 username
# Test device connectivity
ping <device-ip>
ssh <username>@<device-ip>
# Check Oxidized logs
sudo tail -f /srv/oxidized/logs/oxidized.log# Verify Git repo initialization
ls -la /srv/oxidized/git/configs.git/.git
# Check Git configuration
cd /srv/oxidized/git/configs.git
sudo git config --list
# Check Git logs
sudo git log- ✅ Installation complete!
- 📖 Read UPGRADE.md for upgrade procedures
- 🔍 Set up monitoring/ZABBIX.md for alerting
- 📋 Review requirements.md for design details
# Start service
sudo systemctl start oxidized.service
# Stop service
sudo systemctl stop oxidized.service
# Restart service
sudo systemctl restart oxidized.service
# Check status
sudo systemctl status oxidized.service
# View logs
podman logs -f oxidized# List all nodes
curl -s http://localhost:8888/nodes.json | jq '.'
# Get specific node
curl -s http://localhost:8888/node/show/switch-01
# Reload inventory
curl -X POST http://localhost:8888/reload
# Trigger backup for specific node
curl -X GET http://localhost:8888/node/fetch/switch-01| Purpose | Host Path | Container Path |
|---|---|---|
| Config | /srv/oxidized/config |
/etc/oxidized |
| Inventory | /var/lib/oxidized/config |
/home/oxidized/.config/oxidized |
| Data | /srv/oxidized/data |
/var/lib/oxidized |
| Git Repo | /srv/oxidized/git |
/var/lib/oxidized/configs.git |
| Logs | /srv/oxidized/logs |
/var/lib/oxidized/logs |
| Quadlet | /etc/containers/systemd/oxidized.container |
N/A |
| Logrotate | /etc/logrotate.d/oxidized |
N/A |
Installation Complete! 🎉
Your Oxidized deployment is now running and will automatically start on boot.