Skip to content

Commit

Permalink
Manifest documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
DSpeichert committed Mar 9, 2021
1 parent 93c7d00 commit 8b141d3
Show file tree
Hide file tree
Showing 7 changed files with 91 additions and 13 deletions.
76 changes: 72 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,17 +47,85 @@ downloading (typically) kernel and initrd over HTTP instead of TFTP.

## Manifests

A manifest represents a machine to be provisioned/served. The behavior of built-in
DHCP, TFTP and HTTP server is specific to a manifest, meaning that it varies based
on source MAC/IP. Each host may see different content at `/something` path.
A manifest represents a machine to be provisioned/served. The behavior of built-in DHCP, TFTP and HTTP server is
specific to a manifest, meaning that it varies based on source MAC/IP. Each host may see different content
at `/something` path.

Note that this is not a security feature and you should not host any sensitive content. MAC and IPs can be easily
Note that this is not a security feature, and you should not host any sensitive content. MAC and IPs can be easily
spoofed. In fact, netbootd includes a convenience feature to spoof source IP for troubleshooting purposes.
Append `?spoof=<ip-address>` to HTTP request to see the response for a particular host. There is no TFTP counterpart of
this feature.

Example manifests are included in the `examples/` directory.

### Anatomy of a manifest

```yaml
---
# ID can be anything unique, URL-safe, used to identify it for HTTP API
id: ubuntu-1804

### DHCP options - used for DHCP responses from netbootd
# IP address with subnet (CIDR) to give out
ipv4: 192.168.17.101/24
# Hostname (without domain part) (Option 12)
hostname: ubuntu-machine-1804
# Domain part (used for hostname) (Option 15)
domain: test.local
# Lease duration is used as Option 51
# Note that netbootd is a static-assignment server, which does not prevent IP conflicts.
leaseDuration: 1h
# The MAC addresses which map to this manifest
# List multiple for machine with multiple NICs, if not sure which one boots first
mac:
- 00:15:5d:bd:be:15
- aa:bb:cc:dd:ee:fc
# Domain name servers (DNS) in the order of preference (Option 6)
dns:
- 1.2.3.4
- 3.4.5.6
# Routers in the order of preference (Option 3), more than one is rare
router:
- 192.168.17.1
# NTP servers in the order of preference (Option 42), IP address required
ntp:
- 192.168.17.1
# Whether a bundled iPXE bootloader should be served first (before bootFilename).
# When iPXE is loaded, it does DHCP again and netbootd detects its client string
# to break the boot loop and serve bootFilename instead.
ipxe: true
# The name of NBP file name, server over TFTP from "next server",
# which netbootd automatically points to be itself.
# This should map to a "mount" below.
bootFilename: install.ipxe

# Mounts define virtual per-host (per-manifest) paths that are acessible
# over both TFTP and HTTP but only from the IP address of in this manifest.
# Each mount can be either a proxy mount (HTTP/HTTPS proxy) or a content mount (static).
mounts:
- path: /netboot
# When true, all paths starting with this prefix use this mount.
pathIsPrefix: true
# When proxy is defined, these requests are proxied to a HTTP/HTTPS address.
proxy: http://archive.ubuntu.com/ubuntu/dists/bionic-updates/main/installer-amd64/current/images/hwe-netboot/ubuntu-installer/amd64/
# When true, the proxy path defined above gets a suffix to the Path prefix appended to it.
proxyAppendSuffix: true

- path: /install.ipxe
# The templating context provides access to: .LocalIP, .RemoteIP, .HttpBaseUrl and .Manifest.
# Sprig functions are available: masterminds.github.io/sprig
content: |
#!ipxe
# See https://ipxe.org/scripting for iPXE commands/scripting documentation
set base {{ .HttpBaseUrl }}/netboot
{{ $hostnameParts := splitList "." .Manifest.Hostname }}
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
initrd ${base}/initrd.gz
boot
```
## HTTP API
In this preview/development version, this HTTP API does not support authentication.
Expand Down
5 changes: 5 additions & 0 deletions dhcpd/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,11 @@ func (server *Server) HandleMsg4(buf []byte, oob *ipv4.ControlMessage, peer net.
resp.Options.Update(dhcpv4.OptRouter(manifest.Router...))
}

// NTP
if req.IsOptionRequested(dhcpv4.OptionNTPServers) {
resp.Options.Update(dhcpv4.OptNTPServers(manifest.NTP...))
}

// NBP
if req.IsOptionRequested(dhcpv4.OptionTFTPServerName) && !manifest.Suspended {
resp.Options.Update(dhcpv4.OptTFTPServerName(localIp.String()))
Expand Down
2 changes: 1 addition & 1 deletion examples/ubuntu-1804.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ router:

# in the "order of preference"
ntp:
- pool.ntp.org
- 192.168.17.1

ipxe: true
bootFilename: install.ipxe
Expand Down
2 changes: 1 addition & 1 deletion examples/ubuntu-2004-ram.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ router:

# in the "order of preference"
ntp:
- pool.ntp.org
- 192.168.17.1

ipxe: true
bootFilename: install.ipxe
Expand Down
2 changes: 1 addition & 1 deletion examples/ubuntu-2004.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ router:

# in the "order of preference"
ntp:
- pool.ntp.org
- 192.168.17.1

ipxe: true
bootFilename: install.ipxe
Expand Down
1 change: 0 additions & 1 deletion manifest/ipnet.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"net"
)

// An IPNet represents an IP network.
type IPWithNet struct {
IP net.IP
Net net.IPNet
Expand Down
16 changes: 11 additions & 5 deletions manifest/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"time"
)

// Manifest represents user-supplied per-host manifest information.
// go-yaml accepts completely lowercase version of keys but is not case-insensitive
// https://github.com/go-yaml/yaml/issues/123
// some fields are forcefully mapped to camelCase instead of CamelCase and camelcase
Expand All @@ -21,13 +22,14 @@ type Manifest struct {
MAC []HardwareAddr
DNS []net.IP
Router []net.IP
NTP []string
NTP []net.IP
Ipxe bool
BootFilename string `yaml:"bootFilename"`
Mounts []Mount
Suspended bool
}

// Mount represents a path exposed via TFTP and HTTP.
type Mount struct {
// Path at which to select this mount.
Path string
Expand Down Expand Up @@ -88,12 +90,16 @@ func (m Mount) ProxyDirector() (func(req *http.Request), error) {
return director, nil
}

// Content template is evaluated with ContentContext
// ContentContext is the template context available for static Content embedded in Manifests.
type ContentContext struct {
LocalIP net.IP
RemoteIP net.IP
// Address of netbootd server
LocalIP net.IP
// Address of client
RemoteIP net.IP
// Base URL to the HTTP service (IP and port) - not API
HttpBaseUrl *url.URL
Manifest *Manifest
// Copy of Manifest
Manifest *Manifest
}

// Return best matching Mount, respecting exact and prefix-based mount paths.
Expand Down

0 comments on commit 8b141d3

Please sign in to comment.