{"id":47298889,"url":"https://github.com/bl4ko/netbox-ssot","last_synced_at":"2026-04-01T18:47:52.158Z","repository":{"id":223892462,"uuid":"729261077","full_name":"bl4ko/netbox-ssot","owner":"bl4ko","description":"Microservice that syncs objects from multiple sources into NetBox as automatic SSOT","archived":false,"fork":false,"pushed_at":"2026-03-24T11:34:02.000Z","size":10308,"stargazers_count":68,"open_issues_count":8,"forks_count":15,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-03-24T12:56:07.390Z","etag":null,"topics":["autosync","cisco-dna-center","dnac","fortigate","go","netbox","netbox-automation","olvm","ovirt","paloalto","paloaltonetworks","proxmox","ssot","sync","vcenter","vmware"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bl4ko.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-12-08T18:42:55.000Z","updated_at":"2026-03-24T11:34:06.000Z","dependencies_parsed_at":"2026-03-16T20:00:29.987Z","dependency_job_id":null,"html_url":"https://github.com/bl4ko/netbox-ssot","commit_stats":null,"previous_names":["bl4ko/netbox-ssot","src-d-o-o/netbox-ssot"],"tags_count":194,"template":false,"template_full_name":null,"purl":"pkg:github/bl4ko/netbox-ssot","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bl4ko%2Fnetbox-ssot","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bl4ko%2Fnetbox-ssot/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bl4ko%2Fnetbox-ssot/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bl4ko%2Fnetbox-ssot/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bl4ko","download_url":"https://codeload.github.com/bl4ko/netbox-ssot/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bl4ko%2Fnetbox-ssot/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31290948,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-01T13:12:26.723Z","status":"ssl_error","status_checked_at":"2026-04-01T13:12:25.102Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["autosync","cisco-dna-center","dnac","fortigate","go","netbox","netbox-automation","olvm","ovirt","paloalto","paloaltonetworks","proxmox","ssot","sync","vcenter","vmware"],"created_at":"2026-03-16T22:00:16.616Z","updated_at":"2026-04-01T18:47:52.151Z","avatar_url":"https://github.com/bl4ko.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Netbox-SSOT\n\n[![Go](https://github.com/bl4ko/netbox-ssot/actions/workflows/ci.yml/badge.svg)](https://github.com/bl4ko/netbox-ssot/actions/workflows/ci.yml)\n[![codecov](https://codecov.io/gh/bl4ko/netbox-ssot/graph/badge.svg)](https://codecov.io/gh/bl4ko/netbox-ssot)\n![GitHub last commit](https://img.shields.io/github/last-commit/bl4ko/netbox-ssot)\n![GitHub Tag](https://img.shields.io/github/v/tag/bl4ko/netbox-ssot)\n![GitHub License](https://img.shields.io/github/license/bl4ko/netbox-ssot)\n\nNetbox-ssot is a small but powerful microservice designed to\nkeep your Netbox instance in sync with external data sources.\n\nIt is designed to be run as a cronjob, and will periodically update Netbox\nwith the latest data from the external sources. It syncs each source in parallel\nto speed up the process of syncing.\n\nCurrently, the supported external data sources types are:\n\n- [`ovirt`](https://www.ovirt.org/)\n- [`vmware`](https://www.vmware.com/products/cloud-infrastructure/vsphere)\n- [`dnac`](https://www.cisco.com/site/us/en/products/networking/catalyst-center/index.html)\n- [`proxmox`](https://www.proxmox.com/en/)\n- [`paloalto`](https://www.paloaltonetworks.com/network-security/next-generation-firewall)\n  - PAN-OS firewall\n- [`fortigate`](https://www.fortinet.com/products/next-generation-firewall)\n- [`fmc`](https://www.cisco.com/site/us/en/products/security/firewalls/firewall-management-center/index.html)\n- [`ios-xe`](https://www.cisco.com/c/en/us/products/ios-nx-os-software/ios-xe/index.html)\n  - All devices with ios-xe supporting netconf\n- [`f5`](https://www.f5.com/products/big-ip)\n  - F5 BIG-IP LTM virtual servers (VIPs) via iControl REST API\n- [`hetznercloud`](https://www.hetzner.com/cloud/)\n  - Syncs locations, datacenters, servers, networks, floating IPs\n\n## Compatibility Matrix\n\n\u003e [!WARNING]\n\u003e Since netbox introduces breaking changes in minor releases, netbox-ssot also introduces breaking changes in minor releases.\n\u003e See the table below for compatibility between netbox-ssot and netbox.\n\n| Version       | Supported Netbox Version |\n| ------------- | ------------------------ |\n| v1.9.x        | \u003e= 4.2.0                 |\n| v1.0.0-v1.8.x | \u003e=4.0.0, \u003c 4.2.0         |\n| v0.x.x        | \u003e=3.7.0, \u003c 4.0.0         |\n\n## CLI Flags\n\n| Flag       | Description                                        | Default       |\n| ---------- | -------------------------------------------------- | ------------- |\n| `--config` | Path to the configuration file                     | `config.yaml` |\n| `--dry-run`| Preview changes without writing to Netbox           | `false`       |\n\n### Dry Run\n\nUse the `--dry-run` flag to preview what changes would be made to Netbox without actually applying them.\nAll read operations (fetching existing Netbox state, connecting to sources) execute normally,\nbut **all write operations** (create, update, delete) are intercepted and logged instead.\n\n```bash\n# Binary\nnetbox-ssot --config config.yaml --dry-run\n\n# Docker\ndocker run -v /path/to/config.yaml:/app/config.yaml ghcr.io/bl4ko/netbox-ssot --dry-run\n\n# Kubernetes (one-off Job)\nkubectl create job --from=cronjob/netbox-ssot netbox-ssot-dry-run -- /app/netbox-ssot --config /app/config.yaml --dry-run\n```\n\nLook for `[DRY-RUN]` entries in the log output to see what would change:\n\n```\nINFO DRY-RUN MODE ENABLED: No changes will be written to Netbox\n...\nINFO [DRY-RUN] Would create objects.Tag at /api/extras/tags/\nINFO [DRY-RUN] Would update objects.Device (ID: 42) with: map[name:server01]\nINFO [DRY-RUN] Would delete objects.IPAddress (ID: 99) at /api/ipam/ip-addresses/\nINFO [DRY-RUN] Would bulk delete 3 objects at /api/dcim/interfaces/\n...\nINFO DRY-RUN COMPLETE: Review the log above for [DRY-RUN] entries to see what would change\n```\n\n\u003e [!NOTE]\n\u003e During a dry run, created objects are assigned fake IDs (starting at 100,000,000) to maintain internal index consistency. These IDs are never written to Netbox.\n\n## Configuration\n\nNetbox-ssot is configured via a single yaml file.\nThe configuration file is divided into three sections:\n\n- [`logger`](#logger): Logger configuration\n- [`netbox`](#netbox): Netbox configuration\n- [`source`](#source): Array of configuration for each data source\n\nExample configuration can be found [here](#example-config).\n\n### Logger\n\n| Parameter      | Description                                            | Type       | Possible values                  | Default | Required |\n| -------------- | ------------------------------------------------------ | ---------- | -------------------------------- | ------- | -------- |\n| `logger.level` | Log level                                              | int/string | [0-3] or [debug,info,warn,error] | 1,info  | No       |\n| `logger.dest`  | Log output filename. Default `\"\"` representing stdout. | str        | Any valid path                   | \"\"      | No       |\n\n### Netbox\n\n| Parameter                       | Description                                                                                                                                                                                                                                                                                                                                       | Type     | Possible values | Default       | Required |\n| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | --------------- | ------------- | -------- |\n| `netbox.apiToken`               | Netbox API token | str      | Any valid token | \"\"            | Yes      |\n| `netbox.hostname`               | Hostname of your netbox instance (e.g `netbox.example.com`).                                                                                                                                                                                                                                                                                      | str      | Valid hostname  | \"\"            | Yes      |\n| `netbox.port`                   | Port of your netbox instance.                                                                                                                                                                                                                                                                                                                     | int      | 0-65536         | 443           | No       |\n| `netbox.httpScheme`             | HTTP scheme of your netbox instance.                                                                                                                                                                                                                                                                                                              | str      | [http, https]   | https         | No       |\n| `netbox.validateCert`           | Validate the TLS certificate of your netbox instance.                                                                                                                                                                                                                                                                                             | bool     | [true, false]   | false         | No       |\n| `netbox.timeout`                | Max timeout for api call of your netbox instance.                                                                                                                                                                                                                                                                                                 | int      | \u003e=0             | 15            | No       |\n| `netbox.removeOrphans`          | If set to **true** all objects, marked with netbox-ssot tag that were not found during this iteration are automatically deleted. If set to **false**, objects that were not found are marked with an **Orphan** tag. We can then use **netbox.removeOrphansAfterDays** to remove the orphans after n days that they were not seen on the sources. | bool     | [true, false]   | true          | No       |\n| `netbox.removeOrphansAfterDays` | Specifies the number of days to wait before automatically deleting objects marked as Orphan. This setting is only applicable if netbox.removeOrphans is set to false. A value of 5 means objects are deleted in five days after being marked as Orphan and not found since.                                                                       | int      | \u003e0              | MaxInt        | No       |\n| `netbox.tag`                    | Tag to be applied to all objects managed by netbox-ssot.                                                                                                                                                                                                                                                                                          | string   | any             | \"netbox-ssot\" | No       |\n| `netbox.tagColor`               | TagColor for the netbox-ssot tag.                                                                                                                                                                                                                                                                                                                 | string   | any             | \"00add8\"      | No       |\n| `netbox.sourcePriority`         | Array of source names in order of priority. If an object (e.g. Vlan) is found in multiple sources, the first source in the list will be used.                                                                                                                                                                                                     | []string | any             | []            | No       |\n| `netbox.caFile`                 | Path to a self signed certificate for netbox.                                                                                                                                                                                                                                                                                                     | string   | Valid path      | \"\"            | No       |\n\n### Source\n\n| Parameter                                | Description                                                                                                              | Source Type                | Type     | Possible values                          | Default    | Required |\n|------------------------------------------|--------------------------------------------------------------------------------------------------------------------------|----------------------------| -------- | ---------------------------------------- |------------| -------- |\n| `source.name`                            | Name of the data source.                                                                                                 | all                        | str      | any                                      | \"\"         | Yes      |\n| `source.type`                            | Type of the data source.                                                                                                 | all                        | str      | [ovirt, vmware, dnac, proxmox, paloalto, fortigate, fmc, ios-xe, f5] | \"\"         | Yes      |\n| `source.httpScheme`                      | Http scheme for the source                                                                                               | all                        | str      | [ http,https]                            | https      | No       |\n| `source.hostname`                        | Hostname of the data source.                                                                                             | all                        | str      | any                                      | \"\"         | Yes      |\n| `source.port`                            | Port of the data source.                                                                                                 | all                        | int      | 0-65536                                  | 443        | No       |\n| `source.username`                        | Username of the data source account.                                                                                     | all                        | str      | any                                      | \"\"         | Yes      |\n| `source.password`                        | Password of the data source account.                                                                                     | all                        | str      | any                                      | \"\"         | Yes      |\n| `source.apiToken`                        | API token of the data source account.                                                                                    | [**fortigate**]            | str      | any                                      | \"\"         | Yes      |\n| `source.validateCert`                    | Enforce TLS certificate validation.                                                                                      | all                        | bool     | [true, false]                            | false      | No       |\n| `source.tagColor`                        | TagColor for the source tag.                                                                                             | all                        | string   | any                                      | Predefined | No       |\n| `source.ignoredSubnets`                  | List of subnets, which will be ignored (e.g. IPs won't be synced).                                                       | all                        | []string | any                                      | []         | No       |\n| `source.permittedSubnets`                | List of subnets, which will be permitted (e.g. only IPs in these subnets will be synced).                                | all                        | []string | any                                      | []         | No       |\n| `source.interfaceFilter`                 | Regex representation of interface names to be ignored (e.g. `(cali\\|vxlan\\|flannel\\|[a-f0-9]{15})`)                      | all                        | string   | any                                      | []         | No       |\n| `source.continueOnError`                 | Continue syncing remaining objects even if one sync function fails.                                                       | all                        | bool     | [true, false]                            | false      | No       |\n| `source.collectArpData`                  | Collect data from the arp table of the device.                                                                           | [**paloalto**, **ios-xe**] | bool     | [true, false]                            | false      | No       |\n| `source.ignoreAssetTags`                 | Don't sync asset tags of devices.                                                                                        | all                        | bool     | [true, false]                            | false      | No       |\n| `source.ignoreSerialNumbers`             | Don't sync serial numbers of devices.                                                                                    | all                        | bool     | [true, false]                            | false      | No       |\n| `source.ignoreVMTemplates`               | Don't sync vm templates.                                                                                                 | [**vmware**, **proxmox**]  | bool     | [true, false]                            | false      | No       |\n| `source.AssignDomainName`                | Suffix node name with `AssignDomainName`.                                                                                | [**proxmox**]              | str      | any                                      | \"\"         | No       |\n| `source.vlanPrefix`                      | Prefix vlan name with `vlanPrefix`.                                                                                      | [**vmware**]               | str      | any                                      | \"\"         | No       |\n| `source.datacenterClusterGroupRelations` | Regex relations in format `regex = clusterGroupName`, that map each datacenter that satisfies regex to clusterGroupname. | [**vmware**, **ovirt**]    | []string | any                                      | []         | No       |\n| `source.hostSiteRelations`               | Regex relations in format `regex = siteName`, that map each host that satisfies regex to site.                           | all                        | []string | any                                      | []         | No       |\n| `source.clusterSiteRelations`            | Regex relations in format `regex = siteName`, that map each cluster that satisfies regex to site.                        | all                        | []string | any                                      | []         | No       |\n| `source.clusterTenantRelations`          | Regex relations in format `regex = tenantName`, that map each cluster that satisfies regex to tenant.                    | all                        | []string | any                                      | []         | No       |\n| `source.hostTenantRelations`             | Regex relations in format `regex = tenantName`, that map each host that satisfies regex to tenant.                       | all                        | []string | any                                      | []         | No       |\n| `source.hostRoleRelations`               | Regex relations in format `regex = roleName`, that map each host that satisfies regex to device role.                    | all                        | []string | any                                      | []         | No       |\n| `source.vmTenantRelations`               | Regex relations in format `regex = tenantName`, that map each vm that satisfies regex to tenant.                         | all                        | []string | any                                      | []         | No       |\n| `source.vmRoleRelations`                 | Regex relations in format `regex = roleName`, that map each vm that satisfies regex to device role.                      | all                        | []string | any                                      | []         | No       |\n| `source.ipVrfRelations`                  | Regex relations in format `regex = vrfName`, that map each ip that satisfies regex to vrf.                               | [**vmware**, **ovirt**, **proxmox**] | []string | any                                      | []         | No       |\n| `source.vlanGroupRelations`              | Regex relations in format `regex = vlanGroup`, that map each vlan that satisfies regex to vlanGroup.                     | all                        | []string | any                                      | []         | No       |\n| `source.vlanGroupSiteRelations`          | Regex relations in format `regex = vlanGroup`, that map each vlanGroup that satisfies regex to site.                     | all                        | []string | any                                      | []         | No       |\n| `source.vlanSiteRelations`               | Regex relations in format `regex = vlan`, that map each vlan that satisfies regex to site.                               | all                        | []string | any                                      | []         | No       |\n| `source.wlanTenantRelations`             | Regex relations in format `regex = tenantName`, that map each wlan that satisfies regex to tenant.                       | [dnac]                     | []string | any                                      | []         | No       |\n| `source.customFieldMappings`             | Mappings of format `customFieldName = option`. Currently, supported options are `contact`, `owner`, `description`.       | [**vmware**]               | []string | any                                      | []         | No       |\n| `source.defaultIPv4MaskBits`             | Default IPv4 subnet mask bits when not provided by the source (e.g. oVirt guest agent).                                  | [**ovirt**]                | int      | 1-32                                     | 32         | No       |\n| `source.defaultIPv6MaskBits`             | Default IPv6 subnet mask bits when not provided by the source (e.g. oVirt guest agent).                                  | [**ovirt**]                | int      | 1-128                                    | 128        | No       |\n| `source.targetInterface`                 | Name of the interface on the target VM/Device to assign VIPs to. The target is resolved by looking up the source hostname IP in NetBox. | [**f5**]                   | string   | any                                      | \"\"         | No       |\n| `source.caFile`                          | Path to a self signed certificate for the source.                                                                        | any                        | string   | Valid path                               | \"\"         | No       |\n\n### Example config\n\n```yaml\nlogger:\n  level: 1\n  dest: \"\"\n\nnetbox:\n  apiToken: \"el1aof2azu6n50ks5zcenp3...\"\n  hostname: \"netbox.example.com\"\n  httpScheme: http\n  port: 443\n  timeout: 30\n  sourcePriority: [\"olvm\", \"prodvmware\", \"prodprox\", \"dnacenter\", \"testvmware\", \"pa-uk\", \"fmc-lab\"] # Not required, but recommended\n\nsource:\n  - name: olvm\n    type: ovirt\n    hostname: ovirt.example.com\n    port: 443\n    username: \"admin\"\n    password: \"topsecret\"\n    interfaceFilter: (cali|vxlan|flannel|docker|[a-f0-9]{15})\n\n  - name: prodvmware\n    type: vmware\n    hostname: vcenter.example.com\n    username: user\n    password: \"top_secret\"\n    clusterSiteRelations:\n      - .* = ExampleSite\n    hostSiteRelations:\n      - .*_NYC = New York\n      - nyc.* = New York\n    customFieldMappings: # Here we define map of our custom field names, to 3 option [email, owner, description]\n      - Mail = email\n      - Creator = owner\n      - Description = description\n\n  - name: prodprox\n    type: proxmox\n    username: svc@pve\n    password: changeme\n    hostname: 192.168.1.254\n    port: 8006\n    validateCert: false\n    clusterSiteRelations:\n     - .* = Site\n\n  - name: forti\n    type: fortigate\n    hostname: forti.example.com\n    apiToken: \"apitokenhere\"\n    validateCert: False\n    hostTenantRelations:\n      - .* = MyTenant\n    hostSiteRelations:\n      - .* = MyTenant\n    vlanTenantRelations:\n      - .* = MyTenant\n\n  - name: pa-uk\n    type: paloalto\n    hostname: 192.168.1.52\n    username: user\n    password: passw0rd\n    hostTenantRelations:\n      - .* = MyTenant\n    hostSiteRelations:\n      - .* = MySite\n    vlanTenantRelations:\n      - .* = MyTenant\n    collectArpData: true\n\n  - name: dnacenter\n    type: dnac\n    hostname: dnac.example.com\n    username: user\n    password: \"pa$$w0rd\"\n    vlanTenantRelations:\n      - .* = MyTenant\n\n  - name: fmc-lab\n    type: fmc\n    hostname: 172.16.1.30\n    username: user\n    password: password\n    validateCert: False\n    hostTenantRelations:\n      - .* = MyTenant\n    hostSiteRelations:\n      - .* = MySite\n    vlanTenantRelations:\n      - .* = MyTenant\n\n  - name: cs1\n    type: ios-xe\n    hostname: 10.10.1.1\n    username: user\n    password: password\n    port: 830\n    validateCert: False\n    hostTenantRelations:\n      - .* = MyTenant\n    hostSiteRelations:\n      - .* = MySite\n    vlanTenantRelations:\n      - .* = MyTenant\n    collectArpData:\n      true\n\n```\n\n## Deployment\n\n### Via docker\n\n```bash\ndocker run -v /path/to/config.yaml:/app/config.yaml ghcr.io/bl4ko/netbox-ssot\n```\n\n### Via k8s\n\nCreate k8s secret from self defined config.yaml:\n\n```yaml\nkubectl create secret generic netbox-ssot-secret --from-file=config.yaml\n```\n\nApply [cronjob](./k8s/cronjob.yaml) with custom settings:\n\n```yaml\nkubectl apply -f cronjob.yaml\n```\n\n#### Using self signed certificate\n\nCreate self signed certificate e.g.:\n\n```yaml\nkubectl create secret generic netbox-ssot-cert --from-file=sub.pem=./sub.pem\n```\n\nUse [cronjob with cert mounted](./k8s/cronjob_with_cert.yaml):\n\n```yaml\nkubectl apply -f cronjob_with_cert.yaml\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbl4ko%2Fnetbox-ssot","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbl4ko%2Fnetbox-ssot","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbl4ko%2Fnetbox-ssot/lists"}