Post

I Built An Open-Source Replacement For Apc Smartslot Network Cards Opennmc

I Built An Open-Source Replacement For Apc Smartslot Network Cards Opennmc

I Built An Open-Source Replacement For Apc Smartslot Network Cards Opennmc

If you’ve ever managed a data center or home lab with APC UPS units, you know the pain of proprietary SmartSlot network cards. These cards are expensive, closed-source, and often become obsolete when APC moves on to newer models. I got tired of paying premium prices for outdated hardware, so I built OpenNMC—an open-source alternative that gives you full control over your UPS monitoring and management.

This comprehensive guide covers everything you need to know about OpenNMC, from understanding the technology to installing and configuring your own replacement for APC’s SmartSlot network cards. Whether you’re running a professional data center or a home lab, this project offers a cost-effective, customizable solution for UPS network management.

Understanding OpenNMC

What is OpenNMC?

OpenNMC (Open Network Management Card) is an open-source replacement for APC SmartSlot network cards. It’s built around a custom Linux System-on-Module (SoM) running Buildroot, with Network UPS Tools (NUT) as the underlying monitoring framework and a web interface for management. The project aims to provide the same functionality as APC’s proprietary cards while being open, affordable, and extensible.

History and Development

The project emerged from frustration with APC’s closed ecosystem. Commercial SmartSlot cards typically cost several hundred dollars and receive limited updates. As data centers and home labs increasingly adopt open-source solutions, the need for a transparent, modifiable UPS management system became clear. OpenNMC fills this gap by providing a hardware and software platform that anyone can modify, improve, and adapt to their specific needs.

Key Features and Capabilities

OpenNMC currently offers:

  • SmartSlot Compatibility: Designed to fit directly into APC UPS SmartSlot interfaces
  • NUT Integration: Full Network UPS Tools implementation for comprehensive UPS monitoring
  • Web Interface: Browser-based management and monitoring dashboard
  • SSH Access: Full system access for advanced configuration and troubleshooting
  • Serial Communication: Direct communication with UPS units via the internal serial interface using apcsmart protocol
  • Custom Hardware: Based on a custom Linux SoM for optimal performance and power efficiency

Pros and Cons

Advantages:

  • Open-source and fully customizable
  • Significantly lower cost than commercial alternatives
  • No vendor lock-in
  • Community-driven development and support
  • Ability to add custom features and integrations

Limitations:

  • Requires technical expertise to set up and maintain
  • Hardware assembly required
  • Limited to supported APC UPS models
  • Ongoing development means some features may be experimental

Use Cases and Scenarios

OpenNMC is ideal for:

  • Home Labs: Affordable UPS monitoring for personal infrastructure
  • Small Data Centers: Cost-effective network management for multiple UPS units
  • Educational Environments: Learning platform for UPS management and embedded Linux
  • Research Facilities: Customizable monitoring solutions for specialized equipment
  • Backup Power Systems: Integration with solar, generator, or other backup power setups

The project is actively developed with a growing community. Current priorities include expanding UPS model compatibility, improving the web interface, and adding advanced monitoring features. Future developments may include integration with popular monitoring systems like Prometheus, Grafana dashboards, and API endpoints for automation.

Comparison to Alternatives

FeatureAPC SmartSlotOpenNMCThird-party Cards
Cost$300-800~$100-150$200-400
Open SourceNoYesVaries
CustomizationLimitedFullLimited
Community SupportVendor onlyActive communityVendor-dependent
Hardware ControlNoneCompleteLimited

Prerequisites

Hardware Requirements

To build your own OpenNMC, you’ll need:

  • APC UPS with SmartSlot: Compatible with various SmartUPS models
  • Custom Linux SoM: ARM or x86-based system-on-module
  • Serial Communication Hardware: RS-232 interface for UPS communication
  • Power Supply: 5V or 12V depending on your SoM choice
  • Enclosure: 3D-printed or custom case for the SmartSlot form factor
  • MicroSD/EMMC Storage: For the operating system and configuration files

Software Requirements

  • Buildroot: For creating the custom Linux distribution
  • Network UPS Tools (NUT): Version 2.8 or later
  • Web Server: Lighttpd or Nginx for the management interface
  • SSH Server: Dropbear or OpenSSH for remote access
  • Serial Communication Libraries: For apcsmart protocol support

Network and Security Considerations

  • Network Access: The card needs network connectivity for remote monitoring
  • Firewall Configuration: Restrict access to the management interface
  • SSL/TLS: Implement HTTPS for secure web access
  • Authentication: Set up user accounts and permissions
  • Network Segmentation: Consider placing on a separate management network

User Permissions and Access Levels

  • Administrator: Full system access, configuration changes
  • Monitor: Read-only access to status and logs
  • Backup: Limited access for backup operations only

Pre-installation Checklist

  • Verify UPS model compatibility
  • Ensure SmartSlot is functional
  • Prepare development environment for Buildroot
  • Test serial communication with the UPS
  • Plan network configuration and IP addressing
  • Set up backup procedures for existing configurations

Installation & Setup

Building the Custom Linux Distribution

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# Clone the Buildroot repository
git clone https://github.com/buildroot/buildroot.git
cd buildroot

# Configure for your hardware platform
make menuconfig

# Enable required packages
# Target Packages → Networking Applications → nut
# Target Packages → Networking Applications → lighttpd
# Target Packages → Shells → dropbear
# Target Packages → System Tools → usbutils

# Build the system
make

# Flash to your storage medium
dd if=output/images/rootfs.ext4 of=/dev/sdX bs=4M status=progress

Initial System Configuration

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# First boot configuration
ssh root@opennmc.local

# Set hostname
echo "opennmc" > /etc/hostname
hostname -F /etc/hostname

# Configure network interface
cat > /etc/network/interfaces << EOF
auto eth0
iface eth0 inet static
    address 192.168.1.100
    netmask 255.255.255.0
    gateway 192.168.1.1
    dns-nameservers 8.8.8.8 8.8.4.4
EOF

# Enable SSH at boot
systemctl enable dropbear

NUT Configuration

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# Configure NUT drivers
cat > /etc/nut/ups.conf << EOF
[ups]
    driver = apcsmart
    port = /dev/ttyS0
    desc = "APC UPS via SmartSlot"
    vendorid = 0x051d
EOF

# Configure UPS access
cat > /etc/nut/upsd.users << EOF
[admin]
    password = your_secure_password
    actions = SET
    instcmds = ALL

[monuser]
    password = monitor_password
    upsmon master
EOF

# Configure monitoring
cat > /etc/nut/upsmon.conf << EOF
MONITOR ups@localhost 1 monuser monitor_password master
SHUTDOWNCMD "/sbin/shutdown -h +0"
EOF

Web Interface Setup

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# Configure lighttpd
cat > /etc/lighttpd/lighttpd.conf << EOF
server.modules = (
    "mod_access",
    "mod_alias",
    "mod_compress",
    "mod_redirect"
)

server.document-root = "/var/www"
server.upload-dirs = ( "/var/cache/lighttpd/uploads" )
server.errorlog = "/var/log/lighttpd/error.log"
server.pid-file = "/var/run/lighttpd.pid"
server.username = "www"
server.groupname = "www"
server.port = 80

compress.cache-dir = "/var/cache/lighttpd/compress/"
compress.filetype = ( "application/javascript", "text/css", "text/html", "text/plain" )

url.access-deny = ( "~", ".inc" )
static-file.exclude-extensions = ( ".php", ".pl", ".fcgi" )
index-file.names = ( "index.html" )
EOF

# Create web interface files
mkdir -p /var/www
cat > /var/www/index.html << EOF
<!DOCTYPE html>
<html>
<head>
    <title>OpenNMC - UPS Monitoring</title>
</head>
<body>
    <h1>OpenNMC Status</h1>
    <div id="status">Loading...</div>
    <script>
        fetch('/status.json')
            .then(response => response.json())
            .then(data => {
                document.getElementById('status').innerHTML = `
                    Model: ${data.model}<br>
                    Status: ${data.status}<br>
                    Battery: ${data.battery.charge}%
                `;
            });
    </script>
</body>
</html>
EOF

Verification Steps

1
2
3
4
5
6
7
8
9
10
11
# Test NUT communication
upsc ups@localhost

# Check web interface
curl http://localhost

# Verify SSH access
ssh monuser@localhost

# Test UPS shutdown command
upsdrvctl -u root shutdown

Configuration & Optimization

Advanced NUT Configuration

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# Configure battery calibration
cat > /etc/nut/upsd.conf << EOF
MAXAGE 15
EOF

# Set up email notifications
cat > /etc/nut/notifycmd << EOF
#!/bin/bash
SUBJECT="UPS Alert: $4"
MESSAGE="UPS $2 on $1 has status: $4"
echo "$MESSAGE" | mail -s "$SUBJECT" admin@example.com
EOF
chmod +x /etc/nut/notifycmd

# Configure powerdown delay
upsrw -s onbattery.delay=30 ups@localhost

Security Hardening

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Configure firewall
iptables -F
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT

# Allow established connections
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

# Allow SSH (limited)
iptables -A INPUT -p tcp --dport 22 -s 192.168.1.0/24 -j ACCEPT

# Allow web interface (limited)
iptables -A INPUT -p tcp --dport 80 -s 192.168.1.0/24 -j ACCEPT

# Save rules
iptables-save > /etc/iptables/rules.v4

Performance Optimization

1
2
3
4
5
6
7
8
9
10
11
12
# Optimize serial communication
stty -F /dev/ttyS0 2400 sane raw cs8 hupcl cread clocal -crtscts

# Configure NUT polling intervals
cat > /etc/nut/upsmon.conf << EOF
MONITOR ups@localhost 1 monuser monitor_password master
POLLFREQ 5
POLLFREQALERT 5
EOF

# Optimize memory usage
echo "vm.swappiness=10" >> /etc/sysctl.conf

Integration with Monitoring Systems

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Configure Prometheus metrics
cat > /usr/local/bin/ups_exporter << EOF
#!/bin/bash
upsc ups@localhost | grep -E '^(battery.charge|ups.status|input.voltage|output.voltage|ups.load)' | \
while read line; do
    key=$(echo $line | cut -d' ' -f1 | sed 's/\./_/g')
    value=$(echo $line | cut -d' ' -f2)
    echo "ups_$key $value"
done
EOF
chmod +x /usr/local/bin/ups_exporter

# Add to crontab for regular collection
echo "* * * * * /usr/local/bin/ups_exporter > /var/lib/prometheus/metrics.txt" | crontab -

Customization Options

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# Create custom scripts directory
mkdir -p /opt/opennmc/scripts

# Example custom alert script
cat > /opt/opennmc/scripts/low_battery_alert << EOF
#!/bin/bash
THRESHOLD=20
CURRENT=$(upsc ups@localhost battery.charge)

if [ "$CURRENT" -lt "$THRESHOLD" ]; then
    MESSAGE="Battery at ${CURRENT}%, consider shutting down"
    logger -t opennmc "$MESSAGE"
    # Add your custom notification logic here
fi
EOF
chmod +x /opt/opennmc/scripts/low_battery_alert

# Add to crontab
echo "*/5 * * * * /opt/opennmc/scripts/low_battery_alert" | crontab -

Usage & Operations

Common Operations and Commands

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Check UPS status
upsc ups@localhost

# View detailed information
upsc ups@localhost ups.status
upsc ups@localhost battery.charge
upsc ups@localhost input.voltage
upsc ups@localhost output.voltage

# Test shutdown sequence
upsdrvctl -u root shutdown

# Manual battery test
upsdrvctl -u root battery.test.start

# View logs
tail -f /var/log/nut/ups.log

Monitoring and Maintenance

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# Set up log rotation
cat > /etc/logrotate.d/nut << EOF
/var/log/nut/*.log {
    daily
    missingok
    rotate 30
    compress
    delaycompress
    notifempty
    create 644 nut nut
}
EOF

# Monitor system health
cat > /usr/local/bin/health_check << EOF
#!/bin/bash
echo "=== OpenNMC Health Check ==="
echo "Date: $(date)"
echo "Uptime: $(uptime)"
echo "Load: $(cat /proc/loadavg)"
echo "Memory: $(free -h | grep Mem)"
echo "Disk: $(df -h / | tail -1)"
echo "NUT Status: $(upsc ups@localhost ups.status 2>/dev/null || echo 'NUT not responding')"
EOF
chmod +x /usr/local/bin/health_check

# Schedule regular checks
echo "0 * * * * /usr/local/bin/health_check >> /var/log/opennmc_health.log" | crontab -

Backup and Recovery Procedures

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# Backup configuration files
cat > /usr/local/bin/backup_config << EOF
#!/bin/bash
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="/backup/opennmc/${DATE}"
mkdir -p "$BACKUP_DIR"

cp -r /etc/nut "$BACKUP_DIR/"
cp -r /etc/lighttpd "$BACKUP_DIR/"
cp /etc/network/interfaces "$BACKUP_DIR/"
cp /etc/ssh/sshd_config "$BACKUP_DIR/"

echo "Backup completed: $BACKUP_DIR"
EOF
chmod +x /usr/local/bin/backup_config

# Schedule daily backups
echo "0 2 * * * /usr/local/bin/backup_config" | crontab -

# Create recovery script
cat > /usr/local/bin/recover_config << EOF
#!/bin/bash
BACKUP_DIR="$1"
if [ -z "$BACKUP_DIR" ]; then
    echo "Usage: $0 <backup_directory>"
    exit 1
fi

cp -r "$BACKUP_DIR/nut/" /etc/
cp -r "$BACKUP_DIR/lighttpd/" /etc/
cp "$BACKUP_DIR/interfaces" /etc/network/
cp "$BACKUP_DIR/sshd_config" /etc/ssh/

systemctl restart nut
systemctl restart lighttpd
EOF
chmod +x /usr/local/bin/recover_config

Scaling Considerations

For multiple UPS units:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# Configure multiple UPS devices
cat > /etc/nut/ups.conf << EOF
[ups1]
    driver = apcsmart
    port = /dev/ttyS0
    desc = "UPS 1 in Rack A"

[ups2]
    driver = apcsmart
    port = /dev/ttyS1
    desc = "UPS 2 in Rack B"
EOF

# Configure monitoring for multiple devices
cat > /etc/nut/upsmon.conf << EOF
MONITOR ups1@localhost 1 monuser monitor_password master
MONITOR ups2@localhost 1 monuser monitor_password master
EOF

Troubleshooting

Common Issues and Solutions

Issue: NUT cannot communicate with UPS

1
2
3
4
5
6
7
8
9
10
# Check serial port permissions
ls -l /dev/ttyS0
chmod 666 /dev/ttyS0

# Test direct communication
echo -e "ID\r" > /dev/ttyS0
cat /dev/ttyS0

# Verify driver selection
upsdrvctl -u root start

Issue: Web interface not accessible

1
2
3
4
5
6
7
8
9
10
11
# Check lighttpd status
systemctl status lighttpd

# Verify port binding
netstat -tlnp | grep 80

# Check firewall rules
iptables -L -n

# Test from localhost
curl http://localhost

Issue: SSH connection refused

1
2
3
4
5
6
7
8
# Check SSH service
systemctl status dropbear

# Verify SSH port
netstat -tlnp | grep 22

# Check SSH configuration
cat /etc/ssh/sshd_config

Debug Commands and Log Analysis

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# Enable debug logging for NUT
cat > /etc/nut/nut.conf << EOF
MODE=standalone
VERBOSE=3
EOF

# Monitor NUT communication
upsc -D ups@localhost

# Check system logs
journalctl -u nut-server
journalctl -u lighttpd
journalctl -u dropbear

# Monitor serial communication
cat /proc/tty/driver/serial

Performance Tuning

1
2
3
4
5
6
7
8
9
10
11
12
13
# Optimize NUT polling frequency
cat > /etc/nut/upsmon.conf << EOF
MONITOR ups@localhost 1 monuser monitor_password master
POLLFREQ 3
POLLFREQALERT 1
AT ONBATT *EXECUTE /opt/opennmc/scripts/on_battery.sh
AT ONLINE *EXECUTE /opt/opennmc/scripts/online.sh
EOF

# Monitor system resources
top -b -n 1 | head -20
vmstat 1 5
iostat -x 1 3

Security Considerations

1
2
3
4
5
6
7
8
9
10
11
12
13
# Regular security audit
cat > /usr/local/bin/security_audit << EOF
#!/bin/bash
echo "=== Security Audit ==="
echo "Last login: $(last -2 | head -1)"
echo "Listening ports: $(netstat -tlnp | wc -l)"
echo "Firewall rules: $(iptables -L | grep -c ACCEPT)"
echo "Password file: $(ls -lh /etc/shadow)"
EOF
chmod +x /usr/local/bin/security_audit

# Schedule weekly audits
echo "0 4 * * 0 /usr/local/bin/security_audit >> /var/log/security_audit.log" | crontab -

Where to Get Help and Resources

  • Project Repository: https://github.com/yourusername/opennmc
  • NUT Documentation: https://networkupstools.org/docs/user-manual.html
  • Buildroot Documentation: https://buildroot.org/docs.html

This post is licensed under CC BY 4.0 by the author.