# Oxidized: a RANCID replacement for network device configuration backup

> Oxidized is a Ruby daemon that logs into network devices, pulls their configuration, and stores each revision through a source and output pipeline. It suits teams replacing RANCID or building config backup into an existing NMS, and it needs a Ruby runtime and a plan for credentials.

**ytti/oxidized** — Oxidized is a network device configuration backup tool. It's a RANCID replacement!

- Repository: https://github.com/ytti/oxidized
- Stars: 3,594 · Forks: 1,058
- Language: Ruby
- License: Apache-2.0
- Published: 2026-09-23 · Updated: 2026-09-23 · Language: en
- Canonical page: https://hysenlabs.com/projects/ytti-oxidized

## What Oxidized solves, and who ends up running it

Network devices hold their configuration locally. When a device is replaced, a line card is swapped, or an engineer makes an undocumented change, that configuration is the only record of how the network was built. Oxidized exists to pull those configurations on a schedule and keep every revision, which is the job RANCID did before it. The README states the goal plainly: "Oxidized is a network device configuration backup tool. It's a RANCID replacement!"

The people who run it are network engineers and the platform teams that support them. The README points at three integration paths: a REST API, syslog-driven change events, and a set of output modules that decide where the configuration text lands. The project also ships models for over 130 operating system types, which is the number the README gives, so a mixed-vendor estate is the expected case rather than an edge case.

One caveat belongs here rather than at the end. The README opens with a maintainer-wanted notice asking whether a company using Oxidized has Ruby developers who could help. That is a statement about the project's own resourcing, and it should shape how much you want to depend on it.

## Sources in, models in the middle, outputs out

Oxidized is a pipeline with three named stages, and the documentation splits them into separate pages: sources, models, and outputs. A source answers the question of which devices exist. The documented options are CSV, SQL, SQLite, MySQL, and HTTP, so the inventory can live in a flat file, a database, or behind an HTTP endpoint your existing system already exposes.

Each device is then matched to a model, a Ruby class that knows how to talk to that operating system and which commands produce a full configuration. The repository keeps these under lib/ and the README links a supported OS type list in docs/Supported-OS-Types.md. The output stage writes the result. Documented outputs include git, git-crypt, HTTP, and plain file, and the README notes that the git output module uses change-event information so that git blame attributes each changed line to a user.

The control plane around this is small and explicit. The README lists a REST API to move a node to the head of the queue (GET/PUT /node/next/[NODE]), to reload the node list (GET /reload), to fetch a configuration (/node/fetch/[NODE] or /node/fetch/group/[NODE]), to list nodes (GET /nodes), and to list versions and diffs for a node (/node/version[NODE]). The web interface and REST API come from the optional oxidized-web gem, not the core gem.

Scheduling is adaptive rather than fixed. The README says Oxidized "automatically adds/removes threads to meet configured retrieval interval", so the thread pool grows and shrinks around the interval you set instead of running a fixed number of workers.

## Installing Oxidized and backing up a first device

The README recommends Debian 12 or newer and Ubuntu 22.04 or newer. On Ubuntu you first enable the universe repository, which is where libssh2-1-dev comes from, then install the build dependencies. The list is long because several gems compile native extensions.

```bash
add-apt-repository universe
apt install ruby ruby-dev libsqlite3-dev libssl-dev pkg-config cmake libssh2-1-dev libicu-dev zlib1g-dev g++ libyaml-dev libzstd-dev
```

With those in place, the core gem installs from RubyGems. The web interface and the script extensions are separate optional gems, and the README is explicit that neither is required to run Oxidized.

```bash
gem install oxidized
gem install oxidized-web    # Web interface and rest API
gem install oxidized-script # Script-based input/output extensions
```

On Rocky Linux the README says to enable EPEL, CRB and Ruby 3.1 through dnf module, then install an equivalent package set before the same gem install. FreeBSD has its own instructions plus a ports package, rubygem-oxidized, with rubygem-oxidized-script and rubygem-oxidized-web alongside it. There is also a Dockerfile in the repository and a docs/Docker.md for container use.

Configuration is YAML. The README states that files are sourced from /etc/oxidized/config and then ~/.config/oxidized/config, and that the hashes are merged. That merge is the useful part: a system-wide file can hold the source definition while a home-directory file holds a personal username and password, which the README suggests for shared setups. It also recommends running Oxidized under its own username.

After the first run, the fastest way to confirm a device was collected is the version endpoint the README documents, /node/version[NODE], which returns the list of stored versions and diffs for that node.

## Where Oxidized is the wrong tool

A model is not a protocol. Oxidized reaches devices over SSH or telnet depending on the model, and each model encodes the commands that produce a configuration on that operating system. If your device is not in the supported list, or if it is a variant whose CLI differs from the model's assumptions, the fetch fails for that node and you are left writing or patching a model in Ruby. That is a real cost, and it lands on whoever owns the tool.

Credentials are the second boundary. Oxidized needs a login that can read configuration on every managed device, and the README's own suggestion of splitting source data from credentials across two config files shows how that secret spreads. There is no documented credential broker in the README; the source definitions are CSV, SQL, SQLite, MySQL, or HTTP, and the credentials travel with them.

The third boundary is scope. Oxidized backs up configurations. It is not a change-management system, not a compliance scanner, and not a configuration deployment tool. The syslog example catches config change events on IOS and JunOS and triggers a fetch, which tells you a change happened and who made it. Acting on that change is somebody else's job.

Finally, there is the maintenance question. The README asks for a maintainer, and the repository's last push was on 2026-09-23. A project can be usable and still be short of hands; the honest framing is that you should be prepared to read Ruby if a model breaks.

## Oxidized against RANCID and against a general-purpose backup

RANCID is the comparison the project itself invites, and the difference is structural. RANCID is a collection of Perl scripts driven by a cron job and a device list; Oxidized is a long-running Ruby service with a thread pool that adjusts to a retrieval interval, a REST API, and pluggable sources and outputs. If you already know RANCID's directory layout and its control scripts, moving to Oxidized means moving to a service you query rather than scripts you schedule.

The other realistic alternative is generic configuration backup built into a monitoring platform. The distinction there is the model layer. A general-purpose tool that copies files over SSH assumes it can read a path; Oxidized assumes it must log in, enter the right mode, and run the commands that emit a configuration, which is why it carries models per operating system. That is more work to maintain and more accurate on devices whose configuration is not a file on disk.

If your estate is small and homogeneous, a cron job plus git may genuinely be enough, and Oxidized's pipeline is more machinery than the problem needs. The case for Oxidized starts when device types multiply and when you want the fetch, the diff, and the change attribution to come from one place.

## Licence, upgrades, and the cost of keeping it running

Oxidized is licensed Apache-2.0, and the LICENSE file sits at the top level of the repository. The optional gems are separate packages, so check each one's licence before you bundle them into a distribution rather than installing them from RubyGems. That is a packaging question for your legal and release process, not something to settle from a README.

Upgrades are gem upgrades. The recent release line runs 0.35.0 in December 2025, 0.36.0 in March 2026, and 0.37.0 in May 2026, with the last push to the repository on 2026-09-23. The practical cost is not the gem install command; it is that a new release can change a model, and a changed model can alter what a device returns. Pin the gem version, and keep the output directory under version control so you can see when collected configurations change shape after an upgrade.

The recurring cost is the model layer. Every new device family you add either matches an existing model or becomes a small Ruby class you own. Budget for that as ongoing work rather than a one-time setup, and keep the config files in a place your team can review, since the README's merge behaviour means a per-user file can silently override a system-wide setting.

## Running Oxidized in a container or from a package

The repository ships a Dockerfile, and the README points to docs/Docker.md for Docker and Podman use. The Dockerfile builds on debian:trixie-slim, creates a non-privileged oxidized user with UID and GID 30000, and installs runit as the service supervisor with dumb-init for PID 1 signal handling and gosu to drop privileges. It also symlinks /bin/sh to /bin/bash, citing PR #3637, because Ruby runs /bin/sh and the exec hooks expect bash.

That detail matters if you write hooks. An exec hook that assumes bash syntax will work in the container because of the symlink and may behave differently on a host where /bin/sh is dash. The container also pre-creates /home/oxidized/.config/oxidized/.msmtprc and links it into the home directory for msmtp mail configuration, so email hooks have a predictable path.

If you would rather not run a container, the FreeBSD ports route installs rubygem-oxidized, rubygem-oxidized-script, and rubygem-oxidized-web as packages. Both paths end at the same YAML configuration and the same source, model, output pipeline.

## Conclusion

Adopt Oxidized if you already run Ruby tooling or an NMS such as LibreNMS and want per-device config history with a git output and change hooks. Do not adopt it if you need a maintained-without-question project: the README carries a maintainer-wanted notice, and the repository's last push was on 2026-09-23. Before rolling it out, verify that a model exists for your exact device OS in docs/Supported-OS-Types.md, confirm which source your inventory will come from, and decide where the git output directory lives.

## FAQ

### How do I install Oxidized on Ubuntu?

Enable the universe repository, install the build dependencies listed in the README (ruby, ruby-dev, libsqlite3-dev, libssl-dev, pkg-config, cmake, libssh2-1-dev, libicu-dev, zlib1g-dev, g++, libyaml-dev, libzstd-dev), then run gem install oxidized. oxidized-web and oxidized-script are optional gems for the web interface, REST API and script extensions.

### How do I set up Oxidized for network configuration backup?

Configuration is YAML and is sourced from /etc/oxidized/config and then ~/.config/oxidized/config, with the hashes merged. You define a source for the device inventory (CSV, SQL, SQLite, MySQL or HTTP), rely on a model for each device OS, and pick an output such as git, git-crypt, HTTP or file. The README recommends running Oxidized under its own username.

### How do I use Oxidized?

Oxidized runs as a service that fetches device configurations on a configured retrieval interval, adding and removing threads to meet it. You interact with it through the REST API from the optional oxidized-web gem, for example GET /nodes to list nodes, GET /reload to reload the node list, and /node/version[NODE] to see stored versions and diffs.

### How do I install Oxidized for network configuration backup?

On Debian or Ubuntu, install the dependency packages from the README and then run gem install oxidized; the same gem install works on Rocky Linux and FreeBSD once their own dependency steps are done. FreeBSD also offers rubygem-oxidized and its companion packages through ports, and there is a Dockerfile with instructions in docs/Docker.md.

### Does Oxidized work with LibreNMS?

The README does not document a LibreNMS integration, so it cannot be confirmed from the project's own material. What the README does document is a generic HTTP source, which is the mechanism a monitoring system would use to feed a device inventory into Oxidized.

## Sources

- [Issues](https://github.com/ytti/oxidized/issues)
- [License: Apache-2.0](https://github.com/ytti/oxidized/blob/master/LICENSE)
- [README](https://github.com/ytti/oxidized/blob/master/README.md)
- [Releases](https://github.com/ytti/oxidized/releases)
- [ytti/oxidized on GitHub](https://github.com/ytti/oxidized)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/ytti-oxidized
