{"id":15501966,"url":"https://github.com/dspeichert/netbootd","last_synced_at":"2025-06-11T09:34:29.327Z","repository":{"id":42501976,"uuid":"338653376","full_name":"DSpeichert/netbootd","owner":"DSpeichert","description":"Lightweight network boot/install server (DHCP, TFTP, HTTP)","archived":false,"fork":false,"pushed_at":"2023-05-01T00:06:21.000Z","size":736,"stargazers_count":238,"open_issues_count":1,"forks_count":21,"subscribers_count":7,"default_branch":"main","last_synced_at":"2025-04-09T19:17:36.641Z","etag":null,"topics":["boot","dhcp","netinstall","pxe","pxeboot","tftp"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/DSpeichert.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}},"created_at":"2021-02-13T19:33:19.000Z","updated_at":"2025-03-29T12:59:34.000Z","dependencies_parsed_at":"2024-01-15T15:46:05.733Z","dependency_job_id":"f4687ea8-d7a7-4a8d-938b-65ed26434dec","html_url":"https://github.com/DSpeichert/netbootd","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DSpeichert%2Fnetbootd","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DSpeichert%2Fnetbootd/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DSpeichert%2Fnetbootd/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DSpeichert%2Fnetbootd/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/DSpeichert","download_url":"https://codeload.github.com/DSpeichert/netbootd/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248094988,"owners_count":21046770,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["boot","dhcp","netinstall","pxe","pxeboot","tftp"],"created_at":"2024-10-02T09:06:42.719Z","updated_at":"2025-04-09T19:17:42.175Z","avatar_url":"https://github.com/DSpeichert.png","language":"Go","readme":"# netbootd\n\nnetbootd is a lightweight network boot server, designed for maximum flexibility\nand with \"batteries included\" approach in mind, serving as a DHCP, TFTP and HTTP server.\nIt includes a basic templating functionality, designed to allow generating e.g. preseed\nfiles for unattended OS installation.\n\nIt can be compared to [Foreman](https://github.com/theforeman/foreman) or [Cobbler](https://github.com/cobbler/cobbler),\nas the goal is to PXE-boot a machine into an operating system or installation environment.\n\nUnlike Foreman and Cobbler, netbootd is actually a DHCP, TFTP and HTTP server.\nIt does not require any other software to be used.\n\nnetbootd aims to provide maximum flexibility and unlike Foreman or Cobbler makes\nno attempt to simplify the process of network booting. The results will be only\nas good as the configuration (the manifest in this case).\n\nnetbootd's configuration consists of a set of manifests, with each manifest representing a machine\nto be provisioned. Netbootd also provides a simple HTTP API for managing manifests, so that netbootd\ncan become part of a larger automation workflow.\n\n**Note: This software is highly experimental, at proof-of-concept stage. It works\nbut a lot of critical features are missing.**\n\n## DHCP\n\nnetbootd includes a DHCP server that will respond ONLY to MAC addresses found in\none of the manifests. It does not implement the concept of leases as IPs are implied\nto be statically allocated via manifest configuration.\n\nMultiple options are supported, such as router, hostname, domain, DNS, NTP,\nand naturally NBP.\n\n## TFTP and HTTP\n\nnetbootd exposes all \"mounts\" via both TFTP and HTTP simultatenously.\nNaturally, it's not a good idea to transfer really large files over TFTP but PXE generally\nrequires use of TFTP in most cases.\n\nTFTP and HTTP content can either be static text (embedded in the manifest), generated content (using\nGo's `text/template` templating engine) or proxied to upstream HTTP(S). This last feature is mainly intended to proxy\nTFTP to HTTP(S) but very well may be used to reverse-proxy HTTP in otherwise isolated environments and can use a proxy\nitself\n(`HTTP_PROXY` and `NO_PROXY` is honored automatically by Go).\n\nnetbootd can serve local files using the `path.localDir` configuration option.\nnetbootd also contains a bundled version of [iPXE](https://ipxe.org/), which allows\ndownloading (typically) kernel and initrd over HTTP instead of TFTP.\n\n## Manifests\n\nA manifest represents a machine to be provisioned/served. The behavior of built-in DHCP, TFTP and HTTP server is\nspecific to a manifest, meaning that it varies based on source MAC/IP. Each host may see different content\nat `/something` path.\n\nNote that this is not a security feature, and you should not host any sensitive content. MAC and IPs can be easily\nspoofed. In fact, netbootd includes a convenience feature to spoof source IP for troubleshooting purposes.\nAppend `?spoof=\u003cip-address\u003e` to HTTP request to see the response for a particular host. There is no TFTP counterpart of\nthis feature.\n\nExample manifests are included in the `examples/` directory.\n\n### Anatomy of a manifest\n\n```yaml\n---\n# ID can be anything unique, URL-safe, used to identify it for HTTP API\nid: ubuntu-1804\n\n### DHCP options - used for DHCP responses from netbootd\n# IP address with subnet (CIDR) to give out\nipv4: 192.168.17.101/24\n# Hostname (without domain part) (Option 12)\nhostname: ubuntu-machine-1804\n# Domain part (used for hostname) (Option 15)\ndomain: test.local\n# Lease duration is used as Option 51\n# Note that netbootd is a static-assignment server, which does not prevent IP conflicts.\nleaseDuration: 1h\n# The MAC addresses which map to this manifest\n# List multiple for machine with multiple NICs, if not sure which one boots first\nmac:\n  - 00:15:5d:bd:be:15\n  - aa:bb:cc:dd:ee:fc\n# Domain name servers (DNS) in the order of preference (Option 6)\ndns:\n  - 1.2.3.4\n  - 3.4.5.6\n# Routers in the order of preference (Option 3), more than one is rare\nrouter:\n  - 192.168.17.1\n# NTP servers in the order of preference (Option 42), IP address required\nntp:\n  - 192.168.17.1\n# Whether a bundled iPXE bootloader should be served first (before bootFilename).\n# When iPXE is loaded, it does DHCP again and netbootd detects its client string\n# to break the boot loop and serve bootFilename instead.\nipxe: true\n# The name of NBP file name, server over TFTP from \"next server\",\n# which netbootd automatically points to be itself.\n# This should map to a \"mount\" below.\nbootFilename: install.ipxe\n\n# Mounts define virtual per-host (per-manifest) paths that are acessible\n# over both TFTP and HTTP but only from the IP address of in this manifest.\n# Each mount can be either a proxy mount (HTTP/HTTPS proxy) or a content mount (static).\nmounts:\n  - path: /netboot\n    # When true, all paths starting with this prefix use this mount.\n    pathIsPrefix: true\n    # When proxy is defined, these requests are proxied to a HTTP/HTTPS address.\n    proxy: http://archive.ubuntu.com/ubuntu/dists/bionic-updates/main/installer-amd64/current/images/hwe-netboot/ubuntu-installer/amd64/\n    # When true, the proxy path defined above gets a suffix to the Path prefix appended to it.\n    appendSuffix: true\n\n  - path: /subdir\n    # When true, all paths starting with this prefix use this mount.\n    pathIsPrefix: true\n    # Provides a path on the host to find the files.\n    # So that localDir: /tftpboot path: /subdir and client request: /subdir/file.x so that the host\n    # path becomes /tfptboot/file.x\n    localDir: /tftpboot\n    # When true, the localDir path defined above gets a suffix to the Path prefix appended to it.\n    appendSuffix: true\n\n  - path: /install.ipxe\n    # The templating context provides access to: .LocalIP, .RemoteIP, .HttpBaseUrl and .Manifest.\n    # Sprig functions are available: masterminds.github.io/sprig\n    content: |\n      #!ipxe\n      # See https://ipxe.org/scripting for iPXE commands/scripting documentation\n\n      set base {{ .HttpBaseUrl }}/netboot\n\n      {{ $hostnameParts := splitList \".\" .Manifest.Hostname }}\n      kernel ${base}/linux gfxpayload=800x600x16,800x600 initrd=initrd.gz auto=true url={{ .HttpBaseUrl.String }}/preseed.txt netcfg/get_ipaddress={{ .Manifest.IPv4.IP }} netcfg/get_netmask={{ .Manifest.IPv4.Netmask }} netcfg/get_gateway={{ first .Manifest.Router }} netcfg/get_nameservers=\"{{ .Manifest.DNS | join \" \" }}\" netcfg/disable_autoconfig=true hostname={{ first $hostnameParts }} domain={{ rest $hostnameParts | join \".\" }} DEBCONF_DEBUG=developer\n      initrd ${base}/initrd.gz\n      boot\n```\n\n## HTTP API\n\nIn this preview/development version, this HTTP API does not support authentication.\n\n\u003cdetails\u003e\n\u003csummary\u003eGET /api/manifests\u003c/summary\u003e\nReturns a dictionary of all manifests keyed by their ID.\n\nSupports `Accept` header (if provided) that allows selecting a json output (`Accept: application/json`).\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eGET /api/manifests/{id}\u003c/summary\u003e\nReturns a single manifest with ID provided in the URL path.\n\nSupports `Accept` header (if provided) that allows selecting a json output (`Accept: application/json`).\n\nReturns:\n\n* 200 for successful response\n* 404 if manifest with provided ID does not exist\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003ePUT /api/manifests/{id}\u003c/summary\u003e\nAccepts a manifest in either JSON (`Content-type: application/json`) or YAML (default) format.\n\nReturns:\n\n* 201 Created on success\n* 400 for malformed request (invalid manifest)\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eDELETE /api/manifests/{id}\u003c/summary\u003e\nEnsures that manifest with provided ID does not exist.\n\nAlways returns 204, even if manifest already did not exist.\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eGET|POST /api/self/suspend-boot\u003c/summary\u003e\nAllows a provisioned host to ask not to be booted again.\nThis does not block DHCP, TFTP or HTTP requests, it only removes NBP information from DHCP responses.\n\nThis operation looks for a manifest matching the IP address of the requester. It is possible to spoof it\nwith `?spoof=1.2.3.4` query parameter.\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eGET|POST /api/self/unsuspend-boot\u003c/summary\u003e\nRe-enables booting for a provisioned host.\n\nThis operation looks for a manifest matching the IP address of the requester. It is possible to spoof it\nwith `?spoof=1.2.3.4` query parameter.\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eGET /api/self/manifest\u003c/summary\u003e\nReturns a manifest matching requester's IP Address.\n\nSupports `Accept` header (if provided) that allows selecting a json output (`Accept: application/json`).\n\nThis operation looks for a manifest matching the IP address of the requester. It is possible to spoof it\nwith `?spoof=1.2.3.4` query parameter.\n\u003c/details\u003e\n\n## Usage\n\n```\nUsage:\n  netbootd server [flags]\n\nFlags:\n  -a, --address string        IP address to listen on (DHCP, TFTP, HTTP)\n  -r, --api-port int          HTTP API port to listen on (default 8081)\n      --api-tls-cert string   Path to TLS certificate API\n      --api-tls-key string    Path to TLS certificate for API\n  -h, --help                  help for server\n  -p, --http-port int         HTTP port to listen on (default 8080)\n  -i, --interface string      interface to listen on, e.g. eth0 (DHCP)\n  -m, --manifests string      load manifests from directory\n\nGlobal Flags:\n  -d, --debug                    enable debug logging\n      --disable-journal-logger   disable zerolog journald logger\n      --trace                    enable trace logging\n```\n\nRun e.g. `./netbootd --trace server -m ./examples/`\n \n## Roadmap / TODOs\n\n* [x] API TLS \u0026 Authentication\n* [ ] Manifest persistence (currently API-configured manifests live in memory only)\n* [ ] Pluggable store backends (e.g. Redis, Etcd, files) for Manifests\n* [ ] Notifications (e.g. long-polling wait to return when a given host actually booted)\n* [ ] Per-manifest logs available over API\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdspeichert%2Fnetbootd","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdspeichert%2Fnetbootd","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdspeichert%2Fnetbootd/lists"}