A command-line tool and library for hierarchical IPv4 CIDR allocation across multi-cloud infrastructure with NetBox IPAM integration.
Subnetter is production-ready for IPv4 CIDR allocation. The project includes:
Subnetter is organized as a monorepo with the following packages:
Managing IP address space in modern cloud environments presents several challenges:
Subnetter solves these problems through automated, hierarchical CIDR allocation that ensures consistency, prevents overlaps, documents all allocations, and scales with your organization.
SubnetterError hierarchy with codes and help text# Install CLI globally
npm install -g @subnetter/cli
# Or use with npx
npx @subnetter/cli generate -c config.json
# Install for programmatic use
npm install @subnetter/core
# Install NetBox integration
npm install @subnetter/netbox
subnetter generate -c config.json -o allocations.csv
Options:
-c, --config <path>: Configuration file (JSON/YAML) required-o, --output <path>: Output CSV file (default: allocations.csv)-p, --provider <name>: Filter by cloud provider-b, --base-cidr <cidr>: Override base CIDR-v, --verbose: Enable debug logging-l, --log-level <level>: Log level (silent, error, warn, info, debug, trace)subnetter validate -c config.json
subnetter analyze -c config.json
Shows configuration statistics including account count, region count, and estimated subnet count.
subnetter validate-allocations -f allocations.csv
Checks an existing CSV file for CIDR overlaps.
subnetter netbox-export -c config.json --netbox-url https://netbox.example.com --dry-run
Options:
--netbox-url <url>: NetBox API URL required--netbox-token <token>: API token (or use NETBOX_TOKEN env var)--dry-run: Preview changes without applying--prune: Delete orphaned prefixes--status <status>: Prefix status (container, active, reserved, deprecated){
"baseCidr": "10.0.0.0/8",
"prefixLengths": {
"account": 16,
"region": 20,
"az": 22
},
"accounts": [
{
"name": "production",
"clouds": {
"aws": {
"regions": ["us-east-1", "us-west-2"]
},
"azure": {
"regions": ["eastus", "westus"]
}
}
}
],
"subnetTypes": {
"public": 26,
"private": 24,
"database": 27
}
}
baseCidr: Base CIDR block for allocationaccounts: Array of account configurations with cloud/region mappingssubnetTypes: Subnet types with their prefix lengthsprefixLengths: Override default prefix lengths for account/region/az levelscloudProviders: Explicit list (usually inferred from accounts)import {
loadConfig,
CidrAllocator,
writeAllocationsToCsv,
validateNoOverlappingCidrs
} from '@subnetter/core';
async function main() {
// Load and validate configuration
const config = await loadConfig('./config.json');
// Generate allocations
const allocator = new CidrAllocator(config);
const allocations = allocator.generateAllocations();
// Validate no overlaps
const validation = validateNoOverlappingCidrs(allocations);
if (!validation.valid) {
console.error(`Found ${validation.overlaps.length} overlaps`);
process.exit(1);
}
// Write to CSV
await writeAllocationsToCsv(allocations, './allocations.csv');
console.log(`Generated ${allocations.length} allocations`);
}
main();
import { CidrAllocator, loadConfig } from '@subnetter/core';
import { NetBoxClient, NetBoxExporter } from '@subnetter/netbox';
const config = await loadConfig('./config.json');
const allocator = new CidrAllocator(config);
const allocations = allocator.generateAllocations();
const client = new NetBoxClient({
url: 'https://netbox.example.com',
token: process.env.NETBOX_TOKEN!,
});
const exporter = new NetBoxExporter(client);
const result = await exporter.export(allocations, {
dryRun: false,
baseCidr: config.baseCidr,
});
console.log(`Created: ${result.summary.created}`);
console.log(`Updated: ${result.summary.updated}`);
import {
loadConfig,
SubnetterError,
ConfigurationError,
AllocationError,
ErrorCode
} from '@subnetter/core';
try {
const config = await loadConfig('./config.json');
} catch (error) {
if (error instanceof ConfigurationError) {
console.error(`Config error [${error.code}]: ${error.message}`);
console.log('Help:', error.getHelpText());
} else if (error instanceof AllocationError) {
if (error.code === ErrorCode.INSUFFICIENT_SPACE) {
console.error('Not enough IP space. Try a larger base CIDR.');
}
}
}
| Column | Description |
|---|---|
| Account Name | Account identifier |
| VPC Name | VPC name (account-region) |
| Cloud Provider | aws, azure, or gcp |
| Region Name | Cloud region |
| Availability Zone | AZ within region |
| Region CIDR | CIDR for the region |
| VPC CIDR | CIDR for the VPC |
| AZ CIDR | CIDR for the AZ |
| Subnet CIDR | CIDR for the subnet |
| Subnet Role | Subnet type/role |
| Usable IPs | Available IP addresses |
# Clone and install
git clone https://github.com/gangster/subnetter.git
cd subnetter
yarn install
# Build all packages
yarn build
# Run tests
yarn test
yarn test:e2e
# Lint
yarn lint
Contributions are welcome! See the Developer Guide for setup instructions and coding standards.
MIT