nic

command module
v0.0.0-...-d22ae78 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 27, 2026 License: AGPL-3.0 Imports: 25 Imported by: 0

README

nic

A minimal, standalone network configuration tool for Linux. Single binary, zero dependencies, plain-text config.

Replaces systemd-networkd, netplan, and /etc/network/interfaces with one config file and one command.

Features

  • Declarative config at /etc/nic.conf
  • Rollback-safe iproute2 commands (including abbreviated syntax like ip l s eth0 up)
  • Shortcut syntax for common operations
  • Interface aliasing and MAC pinning
  • Built-in DHCP client with fallback (dhclient, dhcpcd, udhcpc)
  • WiFi support (wpa_supplicant, iwd)
  • DNS management with /etc/resolv.conf guarding
  • IPv4 and IPv6 firewall rules via iptables-restore
  • Config includes with natural sort order
  • Dry-run mode
  • Automatic rollback with confirmation timeout
  • Init system support: systemd, OpenRC, SysV, runit
  • IPv6 with DAD awareness
  • No external Go dependencies

Install

make build
sudo make install            # copies binary + default config
sudo make install-systemd    # also installs systemd service
sudo make install-openrc     # OpenRC
sudo make install-sysv       # SysV init
sudo make install-runit      # runit

The systemd installer does not stop or mask the existing network stack. After validating /etc/nic.conf, either disable conflicting services yourself or run sudo NIC_DISABLE_SYSTEM_SERVICES=1 make install-systemd. When that opt-in mode masks systemd-resolved, it replaces only its runtime /etc/resolv.conf symlink with a regular resolver file; administrator-managed resolver files and other symlink targets are left unchanged.

For staged/package installs, all targets honor DESTDIR; PREFIX, SYSCONFDIR, and init-directory variables can also be overridden.

Usage

nic - network interface configurator

Usage: nic <command> [options]

Commands:
  start                  Apply network configuration
  stop                   Tear down network configuration
  restart [options]      Stop and re-apply configuration
  reload  [options]      Re-apply configuration (shows diff)
  status                 Show current network state
  show                   Show parsed configuration
  dry-run                Show what would be done without applying
  confirm                Confirm changes after reload/restart with timeout
  version                Show version

Options:
  --config=PATH          Config file path (default: /etc/nic.conf)
  --verbose, -v          Show commands being executed
  --confirm-timeout=N    Revert after N seconds if not confirmed (default: 10)
  --no-rollback          Apply restart/reload without a confirmation watcher
  --daemon, -d           Run in daemon mode (keeps DHCP clients running)
  --force                Skip confirmation prompts
  --help, -h             Show this help
  --version, -V          Show version

Configuration

Interface control
# Full iproute2
ip link set eth0 up

# Abbreviated (handled by ip binary)
ip l s eth0 up

# Shortcuts
if eth0 up
if eth0 down
up eth0
down eth0
IP addresses
# Full iproute2
ip address add 192.168.1.100/24 dev eth0

# Abbreviated
ip a a 192.168.1.100/24 dev eth0

# Shortcut (auto-adds /32 or /128 if no prefix)
ip 192.168.1.100/24 eth0
ip fd76:1e4b:375a::/48 eth0
Routes
# Full iproute2
ip route add default via 192.168.1.1 dev eth0

# Abbreviated
ip r a default via 192.168.1.1 dev eth0

# Shortcut
route default via 192.168.1.1 eth0
route 10.0.0.0/8 via 192.168.1.1 eth0
route 172.16.0.0/12 eth0
DNS
nameserver 1.1.1.1
ns 8.8.8.8

Writes /etc/resolv.conf and protects it with chattr +i. Static nameserver entries take precedence over DHCP-provided entries; without static entries, DNS from active DHCP sessions is merged deterministically.

DHCP
dhcp eth0              # auto-detects client
dhcp eth0 dhclient     # force specific client
dhcpv6 eth0            # best-effort DHCPv6
dhcpv6 eth0 required   # abort the whole configuration if DHCPv6 fails

dhcp4 and dhcpv4 are accepted as aliases for dhcp, and dhcp6 for dhcpv6.

Supports dhclient, dhcpcd, and udhcpc.

The native client is tried first. If it cannot obtain a lease, nic falls back to the first installed external client. Specify native, dhclient, dhcpcd, or udhcpc to force one implementation.

dhcpv6 is best-effort: if no lease is obtained but the interface is configured by another address family (a DHCPv4 lease or a static address), nic logs a warning and continues. The configuration fails only when the interface is left with no address at all. Add required to treat any DHCPv6 failure as fatal, which is the equivalent of NetworkManager's ipv6.may-fail=no.

WiFi
wifi MyNetwork MyPassword         # auto-detect interface
wifi MyNetwork MyPassword wlan0   # specify interface

Uses wpa_supplicant or iwd, with WPA3 (SAE) support.

Because the configuration contains the WiFi passphrase, every file containing a wifi directive must be owned appropriately and have mode 0600. Passwords are never placed in command-line arguments and are stored only in protected runtime backend configuration.

Firewall
iptables /etc/nic.rules.v4
ip6tables /etc/nic.rules.v6

Each directive points to a complete rules file in iptables-save/ iptables-restore format. iptables loads IPv4 rules with iptables-restore; ip6tables loads IPv6 rules with ip6tables-restore. Relative paths are resolved from the configuration file that contains the directive.

A rules file is the complete desired state for its address family, not a partial table update. If a table exists in the live rules but is omitted from the file, nic flushes it, removes its user-defined chains, and leaves its built-in chains with ACCEPT policies. This also clears rules and user chains from tables introduced by a failed configuration when rollback restores a baseline that did not contain them.

The default installation includes conservative example files at /etc/nic.rules.v4 and /etc/nic.rules.v6, but both directives are commented out in /etc/nic.conf. Review the rules—especially the allowed SSH port—before enabling either family.

Rules are loaded at the point the directive appears, so place it before the interfaces it is meant to protect are brought up. Note that the two address families filter DHCP differently: the DHCPv4 client uses a packet socket and is not seen by the INPUT chain, while the DHCPv6 client uses a UDP socket, so a default-drop IPv6 policy must accept UDP port 546 as the shipped example does.

To remain compatible with iptables releases that predate iptables-restore --wait, nic invokes the restore command without that option and retries xtables-lock contention for up to 10 seconds.

Firewall state participates in NIC's baseline and confirmation-timeout rollback. Only a family named by the current or desired configuration is captured and restored; configuring IPv4 rules does not alter IPv6 rules, or vice versa. During a reload, a family replaced by the desired configuration is kept on its current policy until its new rules directive runs; nic does not briefly restore the pre-nic firewall first.

Aliases and MAC pinning
# Static alias
alias my_eth enp14s0

# Pin by MAC address (resolved at runtime)
pin my_eth aa:bb:cc:dd:ee:ff

# Use alias in subsequent commands
if my_eth up
ip 192.168.1.100/24 my_eth
Includes
include nic.d/*.conf

Paths are relative to the config file directory. Files are loaded in natural sort order (2.conf before 10.conf).

Comments
# Full line comment
ip 10.0.0.1/24 eth0 # inline comment

Example: LACP bond with VLAN

# /etc/nic.conf

# Create bond
ip link add bond0 type bond mode 802.3ad xmit_hash_policy layer2+3 lacp_rate fast
ip link set eth0 down
ip link set eth1 down
ip link set eth0 master bond0
ip link set eth1 master bond0
if bond0 up

# VLAN on top of bond
ip link add link bond0 name bond0.100 type vlan id 100
ip 192.168.100.10/24 bond0.100
if bond0.100 up

# Default route and DNS
route default via 192.168.100.1 bond0.100
ns 1.1.1.1

Restart safety

nic restart and nic reload save the current network state before applying changes. If you don't run nic confirm within the timeout (default 10 seconds), the previous state is automatically restored. This prevents locking yourself out over SSH.

reload compares the last applied configuration with the desired one, restores the pre-nic baseline, and then applies the desired state. Removed addresses, routes, links, DNS entries, DHCP sessions, and WiFi connections therefore do not linger. Use --no-rollback only in automation that intentionally accepts the new configuration immediately.

To keep that rollback guarantee, passthrough accepts link creation and the restorable link settings (up/down, mtu, MAC address, and master), plus address, route, and rule add/replace commands. Destructive operations such as ip link delete, interface renames, namespace moves, and unsupported iproute2 objects are rejected instead of being applied without a safe inverse.

sudo nic restart --confirm-timeout=30
# test connectivity...
sudo nic confirm

Build

Requires Go 1.22+.

make build    # produces ./nic for the host architecture
make test     # run tests
make lint     # run golangci-lint

Cross-compilation needs no toolchain beyond Go; the binary is pure Go and is built with CGO_ENABLED=0.

make cross            # all targets below, into ./dist
make cross-x86_64     # dist/nic-<version>-x86_64    (GOARCH=amd64)
make cross-arm64      # dist/nic-<version>-arm64
make cross-armv7      # dist/nic-<version>-armv7     (GOARM=7)
make cross-armv6      # dist/nic-<version>-armv6     (GOARM=6)
make cross-riscv64    # dist/nic-<version>-riscv64

Override CROSS_TARGETS to build a subset, and DISTDIR to change the output directory.

License

nic - network interfaces configurator
Copyright (C) 2026  c0m4r <https://github.com/c0m4r>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with this program.  If not, see <https://www.gnu.org/licenses/>.

Linux® is the registered trademark of Linus Torvalds in the U.S. and other countries.

Documentation

The Go Gopher

There is no documentation for this package.

Directories

Path Synopsis
internal
dns

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL