Automated deployment script for RANCID (Really Awesome New Cisco confIg Differ) on RHEL 10 systems. This script provides a complete, idempotent solution for installing and configuring RANCID with Git-based configuration versioning.
- π― Overview
- ποΈ Architecture
- β Requirements
- π Installation
- βοΈ Configuration
- π Usage
- π§ How It Works
- π Security Notes
- ποΈ Uninstallation
- π Troubleshooting
- π Additional Resources
- π License
RANCID (Really Awesome New Cisco confIg Differ) is a network configuration management tool that automatically collects, stores, and tracks changes to network device configurations. This deployment script automates the entire setup process on RHEL 10 systems.
- β Idempotent: Safe to run multiple times without side effects
- β
Configurable: Supports
.envfile for custom configuration - β
Preserves Data: Existing files are protected unless
--forceis used - β
Dry-Run Mode: Preview changes with
--dryrunbefore execution - β Comprehensive: Handles packages, users, directories, Git repos, and cron jobs
- β Validated: Extensive error checking and validation throughout
- β Documented: Clear logging and helpful error messages
- RANCID (compiled and installed from source)
- Build tools and dependencies (gcc, make, expect, perl-devel)
- Runtime dependencies (git, perl-Expect, perl-TermReadKey, net-snmp-utils, openssh-clients)
- RANCID user and group
- Directory structure for device groups
- Git repositories for configuration versioning
- SSH keys for device access
- Cron job for automated collection
- Configuration files with proper permissions
The deployment script follows a modular architecture with clear separation of concerns:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β deploy-rancid.sh β
β β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββ β
β β Configuration βββΆβ Installation βββΆβ Validationβ β
β β Loading β β Functions β β Checks β β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββ β
β β β β β
β βΌ βΌ βΌ β
β ββββββββββββββββββββββββββββββββββββββββββββββββ β
β β System Configuration Files β β
β β β’ /etc/rancid/rancid.conf β β
β β β’ /etc/cron.d/rancid β β
β ββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
β ββββββββββββββββββββββββββββββββββββββββββββββββ β
β β RANCID Data Directory β β
β β /var/lib/rancid/ β β
β β βββ .cloginrc (credentials) β β
β β βββ .ssh/id_rancid (SSH key) β β
β β βββ <group>/ β β
β β βββ router.db β β
β β βββ configs/ β β
β β βββ logs/ β β
β β βββ .git/ (version control) β β
β ββββββββββββββββββββββββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
.env file (optional)
β
βΌ
deploy-rancid.sh
β
βββΆ Load .env variables
β
βββΆ Validate configuration
β
βββΆ Execute installation steps
βββΆ Create group directories
βββΆ Copy router.db from template
βββΆ Copy .cloginrc from template
βββΆ Initialize Git repositories
- Operating System: RHEL 10 (or compatible)
- Architecture: x86_64
- Privileges: Root access (via
sudoor direct root login) - Network: Internet access for downloading RANCID source and dependencies
The script automatically installs these packages and builds RANCID from source:
| Package | Purpose | Status |
|---|---|---|
rancid |
Main RANCID application (installed from source) | β Required |
gcc |
C compiler for building RANCID | β Required |
make |
Build tool for compiling RANCID | β Required |
expect |
Tcl expect (required by RANCID configure) | β Required |
perl-devel |
Perl development headers | β Required |
curl |
Download tool for RANCID source | β Required |
git |
Version control for configs | β Required |
perl-Expect |
Device interaction | β Required |
perl-TermReadKey |
Terminal input handling | β Required |
net-snmp-utils |
SNMP utilities | β Required |
openssh-clients |
SSH client tools | β Required |
- System is running RHEL 10
- Root or sudo access is available
- Internet connectivity is working
-
.envfile is configured (optional, see Configuration) - Sufficient disk space available (minimum 1GB recommended)
-
Clone or download the repository:
git clone <repository-url> cd deploy-rancid
-
Configure your environment (optional):
cp .env.example .env # Edit .env with your settings -
Run the deployment script:
sudo ./deploy-rancid.sh
Copy the example environment file and customize it:
cp .env.example .env
nano .env # or use your preferred editorSee the Configuration section for details on available options.
Before executing, preview what the script will do:
sudo ./deploy-rancid.sh --dryrunThis shows all changes without modifying the system.
Run the script with appropriate privileges:
sudo ./deploy-rancid.shThe script performs automatic validation, but you can manually verify:
# Check RANCID commands are available
which rancid-run
which rancid
# Verify directory structure
ls -la /var/lib/rancid/
# Check cron job
cat /etc/cron.d/rancid
# Verify Git repositories
ls -la /var/lib/rancid/*/.gitAfter successful installation, complete these steps:
- Populate device credentials in
/var/lib/rancid/.cloginrc - Add devices to group
router.dbfiles - Distribute SSH public key to network devices
- Test manual collection:
sudo -u rancid rancid-run - Review logs:
ls -ltr /var/lib/rancid/*/logs/
The script supports configuration via a .env file in the script directory. This file is
optional - if not present, sensible defaults are used.
-
Copy the example file:
cp .env.example .env
-
Edit
.envwith your values:nano .env # or vim, emacs, etc. -
Important: Never commit
.envto version control (it's in.gitignore)
| Variable | Description | Default | Required |
|---|---|---|---|
RANCID_GROUPS |
Array of group names | ("routers" "switches") |
β |
GIT_NAME |
Git commit author name | "RANCID Automation" |
β |
GIT_EMAIL |
Git commit author email | rancid@$(hostname) |
β |
BASEDIR |
Base directory for RANCID data | "/var/lib/rancid" |
β |
ETCDIR |
Configuration directory | "/etc/rancid" |
β |
CRON_FILE |
Cron job file path | "/etc/cron.d/rancid" |
β |
CRON_LINE |
Cron schedule | "0 0 * * * rancid /usr/bin/rancid-run" |
β |
The script supports two naming conventions for flexibility:
-
Standard format (recommended):
RANCID_GROUPS=("core-switches" "tor-switches" "firewalls") GIT_NAME="RANCID" GIT_EMAIL="rancid@example.com"
-
DEFAULT suffix format (also supported):
RANCID_GROUPS_DEFAULT=("core-switches" "tor-switches" "firewalls") GIT_NAME_DEFAULT="RANCID" GIT_EMAIL_DEFAULT="rancid@example.com"
# RANCID Deployment Configuration
# Copy this file to .env and customize for your environment
# RANCID Groups - Array of group names
# Supports bash array syntax: ("group1" "group2")
# Or space-separated string: "group1 group2"
RANCID_GROUPS=("core-switches" "tor-switches" "ASAv" "firewalls")
# Git configuration for RANCID repositories
GIT_NAME="RANCID Automation"
GIT_EMAIL="rancid@example.local"
# Optional: Override system paths (usually not needed)
# BASEDIR="/var/lib/rancid"
# ETCDIR="/etc/rancid"
# CRON_FILE="/etc/cron.d/rancid"
# CRON_LINE="0 0 * * * rancid /usr/bin/rancid-run"The .env.example file serves as a template and documentation for configuration options:
- β Safe to commit: Contains no sensitive information
- β Well-documented: Includes comments explaining each variable
- β Example values: Shows expected format and syntax
- β Reference guide: Documents all available options
Usage:
- Copy
.env.exampleto.env - Customize values for your environment
- Never commit
.env(it's gitignored)
The script uses template files to create initial configuration files. These templates are copied (not inlined) to ensure consistency:
- Purpose: Template for device inventory files
- Location: Script directory
- Usage: Copied to
/var/lib/rancid/<group>/router.dbfor each group - Behavior: Never overwrites existing
router.dbfiles (idempotent) - Permissions: 640, owner rancid:rancid
- Purpose: Template for credentials file
- Location: Script directory
- Usage: Copied to
/var/lib/rancid/.cloginrc - Behavior: Never overwrites existing
.cloginrcfile (idempotent, per requirements) - Permissions: 600, owner rancid:rancid
Important: Both template files are copied as-is. The script does not modify their contents during deployment.
The script supports a --dryrun (or --dry-run) option that allows you to preview all changes
without actually modifying the system:
sudo ./deploy-rancid.sh --dryrunWhat dry-run shows:
- β Directories that would be created
- β Files that would be created or modified
- β Ownership and permission changes
- β Source installation and build commands
- β User/group creation operations
- β Git repository initialization steps
What dry-run does NOT do:
- β Make any actual changes to the system
- β Install packages
- β Create files or directories
- β Modify permissions or ownership
This is useful for:
- Understanding what the script will do before execution
- Validating configuration without risk
- Troubleshooting configuration issues
- Documentation and planning
# Standard installation (preserves existing files)
sudo ./deploy-rancid.sh
# Preview changes without executing (dry-run)
sudo ./deploy-rancid.sh --dryrun
# Force overwrite of existing configuration
sudo ./deploy-rancid.sh --force
# Display help information
./deploy-rancid.sh --help
# Display version
./deploy-rancid.sh --version| Option | Description | Default Behavior |
|---|---|---|
--force |
Overwrite existing configuration files | Preserves existing files |
--dryrun / --dry-run |
Preview changes without executing | Executes changes |
--help / -h |
Display help message and exit | N/A |
--version / -v |
Display version information and exit | N/A |
The script is designed to be idempotent, meaning:
- β Safe to run multiple times
- β
Existing files are preserved (unless
--force) - β Existing users/groups are detected and skipped
- β Git repositories are not re-initialized if they exist
- β
Configuration files are backed up before overwrite (with
--force)
# 1. Configure environment
cp .env.example .env
nano .env
# 2. Run deployment
sudo ./deploy-rancid.sh
# 3. Verify installation
sudo -u rancid rancid-run# 1. Update .env file
nano .env
# 2. Preview changes with dry-run
sudo ./deploy-rancid.sh --dryrun
# 3. Apply changes
sudo ./deploy-rancid.sh
# 4. Verify configuration
cat /etc/rancid/rancid.conf# 1. Edit .env to add new group
nano .env
# Add: RANCID_GROUPS=("existing" "new-group")
# 2. Re-run script (idempotent, only adds new group)
sudo ./deploy-rancid.shThe script follows this execution sequence:
1. Parse Arguments
βββΆ Validate command-line options
βββΆ Set FORCE_OVERWRITE flag
2. Prerequisites Check
βββΆ Verify root privileges
βββΆ Check required commands exist
3. Configuration Loading
βββΆ Load .env file (if present)
βββΆ Map variables to internal format
βββΆ Validate configuration
4. Package Installation
βββΆ Update system packages
βββΆ Install runtime dependencies
βββΆ Install RANCID from source (if not already installed)
βββΆ Install build prerequisites
βββΆ Download RANCID source
βββΆ Configure, compile, and install
βββΆ Create symlinks in /usr/bin
5. User/Group Setup
βββΆ Create rancid group (if needed)
βββΆ Create rancid user (if needed)
6. Directory Structure
βββΆ Create base directories
βββΆ Create group directories (configs/, logs/, status/)
βββΆ Copy router.db from template for each group
βββΆ Set proper permissions
7. Configuration Files
βββΆ Write rancid.conf
βββΆ Copy .cloginrc from template
βββΆ Install cron job
8. SSH Key Setup
βββΆ Generate SSH keypair (if needed)
9. Git Initialization
βββΆ Initialize Git repos per group
βββΆ Configure Git user/email
10. Validation
βββΆ Verify commands exist
βββΆ Check file permissions
βββΆ Display next steps
load_local_env(): Sources.envfile and maps variables to internal formatvalidate_and_set_env(): Validates configuration and sets final variables
install_packages(): Installs runtime dependencies and RANCID from sourceinstall_rancid_from_source(): Downloads, compiles, and installs RANCID from sourcecreate_user_group(): Creates rancid user and groupcreate_base_dirs(): Sets up directory structurewrite_rancid_conf(): Writes main RANCID configurationcreate_groups_layout(): Creates directories for each group and copies router.db from templatesetup_cloginrc_placeholder(): Copies credentials file from example-cloginrc templatesetup_ssh_key(): Generates SSH keypair for device accessinit_git_repos(): Initializes Git repositories per groupinstall_cron(): Sets up automated collection schedule
safe_mkdir(): Creates directories with proper permissions (supports dry-run)safe_create_file(): Creates files with backup on overwrite (supports dry-run)ensure_permissions(): Corrects ownership/permissions if incorrect (idempotent, supports dry-run)check_dependencies(): Validates required commands existpost_checks(): Verifies installation success
The script implements intelligent file preservation:
| File Type | Default Behavior | With --force |
|---|---|---|
/etc/rancid/rancid.conf |
Preserve if exists | Backup and overwrite |
/etc/cron.d/rancid |
Preserve if exists | Backup and overwrite |
/var/lib/rancid/.cloginrc |
Preserve if exists | Never overwrite (per requirements) |
router.db files |
Preserve if exists | Never overwrite (per requirements) |
| SSH keys | Preserve if exists | Preserve (never overwrite) |
| Git repositories | Preserve if exists | Preserve (never overwrite) |
Backup naming: filename.bak.YYYYMMDDHHMMSS
The script sets appropriate permissions for security:
| File/Directory | Permissions | Owner | Purpose |
|---|---|---|---|
/etc/rancid/rancid.conf |
644 | root:root | Main configuration |
/etc/cron.d/rancid |
644 | root:root | Cron job configuration |
/var/lib/rancid/.cloginrc |
600 | rancid:rancid | Credentials (must remain 600) |
/var/lib/rancid/.ssh/id_rancid |
600 | rancid:rancid | SSH private key |
/var/lib/rancid/.ssh/id_rancid.pub |
644 | rancid:rancid | SSH public key |
/var/lib/rancid/ |
750 | rancid:rancid | Base directory |
/var/lib/rancid/<group>/ |
750 | rancid:rancid | Group directories |
/var/lib/rancid/<group>/router.db |
640 | rancid:rancid | Device inventory |
/var/lib/rancid/<group>/configs/ |
750 | rancid:rancid | Configuration storage |
/var/lib/rancid/<group>/logs/ |
750 | rancid:rancid | Log files |
/var/lib/rancid/<group>/status/ |
750 | rancid:rancid | Status files |
-
.cloginrcfile:- Contains device credentials
- MUST remain mode 600
- Should use read-only credentials where possible
- Never commit to version control
-
SSH Keys:
- Private key is mode 600 (rancid user only)
- Public key should be distributed to devices
- Keys are never overwritten by the script
-
Environment Files:
.envfile should not be committed (in.gitignore).envfile contains configuration but no credentials
- β Use read-only credentials for device access
- β
Restrict
.cloginrcfile permissions (600) - β Regularly rotate SSH keys
- β Monitor RANCID logs for unauthorized access attempts
- β Keep RANCID packages updated
- β Review cron job permissions regularly
To remove RANCID deployment:
-
Stop cron job:
rm /etc/cron.d/rancid
-
Remove configuration files:
rm -rf /etc/rancid/
-
Remove RANCID data (
β οΈ WARNING: This deletes all collected configs):rm -rf /var/lib/rancid/
-
Remove RANCID user and group:
userdel rancid groupdel rancid
-
Uninstall RANCID binaries (optional):
# Remove symlinks rm -f /usr/bin/rancid /usr/bin/rancid-run /usr/bin/clogin # Remove RANCID installation rm -rf /usr/local/bin/rancid* /usr/local/bin/clogin* /usr/local/share/rancid # Remove runtime dependencies (optional, if not used elsewhere) dnf remove perl-Expect perl-TermReadKey net-snmp-utils
Before removing RANCID, consider backing up:
- Configuration files:
/etc/rancid/ - Collected configurations:
/var/lib/rancid/<group>/configs/ - Device inventory:
/var/lib/rancid/<group>/router.db - Credentials:
/var/lib/rancid/.cloginrc(if you have backups elsewhere)
Solution: Run with sudo:
sudo ./deploy-rancid.shSolution: Ensure you're on RHEL 10 with dnf available:
which dnf
# If missing, you may not be on RHEL 10Solution: Check network connectivity and DNS resolution:
ping 8.8.8.8
curl -I http://www.shrubbery.net/pub/rancid/Solution: Ensure .env file has GIT_NAME set, or the script will use defaults:
# Check .env file
cat .env | grep GIT_NAME
# If missing, add to .env file:
echo 'GIT_NAME="RANCID Automation"' >> .env
echo 'GIT_EMAIL="rancid@example.com"' >> .env
# Re-run script
sudo ./deploy-rancid.shSolution: This is expected behavior. Use --force if you want to overwrite:
sudo ./deploy-rancid.sh --forceSolution: Check common causes:
-
Credentials not configured:
cat /var/lib/rancid/.cloginrc # Ensure credentials are populated -
Devices not in router.db:
cat /var/lib/rancid/<group>/router.db # Ensure devices are listed
-
SSH key not distributed:
cat /var/lib/rancid/.ssh/id_rancid.pub # Distribute to devices -
Check logs:
ls -ltr /var/lib/rancid/*/logs/ tail -f /var/lib/rancid/logs/rancid.log
-
Enable verbose output: The script logs all operations with
[rancid-setup]prefix -
Check file permissions:
ls -la /var/lib/rancid/ ls -la /etc/rancid/
-
Verify Git repositories:
sudo -u rancid git -C /var/lib/rancid/<group> status
-
Test manual collection:
sudo -u rancid rancid-run
-
Review cron logs:
journalctl -u crond | grep rancid
If issues persist:
- Review the script logs (all output is prefixed with
[rancid-setup]) - Check RANCID documentation:
man rancid - Review RANCID logs in
/var/lib/rancid/*/logs/ - Verify configuration files are correct
- Official RANCID Website: http://www.shrubbery.net/rancid/
- RANCID Manual:
man rancid(after installation) - RANCID Configuration Guide:
/usr/share/doc/rancid/(after installation)
- Script:
deploy-rancid.sh- Main deployment script - Configuration Template:
.env.example- Example environment file - Configuration:
.env- Your environment configuration (not in git) - Main Config:
/etc/rancid/rancid.conf- RANCID main configuration - Template Files:
example-router.db- Template for device inventory filesexample-cloginrc- Template for credentials file
- Context Standards:
docs/ai/CONTEXT.md- Development standards - Requirements:
docs/requirements.md- Project requirements - Security Review:
docs/security-ci-review.md- Security guidelines
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
Last Updated: 2025-01-02