Repository: kelseyhightower/coreos-ipxe-server
Branch: master
Commit: 8b671421047f
Files: 19
Total size: 24.0 KB
Directory structure:
gitextract_12q8nhyr/
├── .gitignore
├── LICENSE
├── README.md
├── api.go
├── api_test.go
├── config/
│ └── config.go
├── docker/
│ ├── .gitignore
│ ├── Dockerfile
│ └── setup_docker.sh
├── docs/
│ ├── api.md
│ ├── cloudconfigs.md
│ ├── configuration.md
│ ├── docker.md
│ ├── getting_started.md
│ ├── profiles.md
│ └── sshkeys.md
├── kernel/
│ ├── options.go
│ └── options_test.go
└── main.go
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
data
coreos-ipxe-server
================================================
FILE: LICENSE
================================================
Copyright (c) 2014 Kelsey Hightower
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
# CoreOS iPXE Server
[](https://drone.io/github.com/kelseyhightower/coreos-ipxe-server/latest)
The CoreOS iPXE Server attempts to automate as much of the [Booting CoreOS via iPXE](https://coreos.com/docs/running-coreos/bare-metal/booting-with-ipxe/) process as possible, mainly generating iPXE boot scripts and serving CoreOS PXE boot images.
## Table of Contents
- [Installation](#installation)
- [Getting Started](docs/getting_started.md)
- [API](docs/api.md)
- [Profiles](docs/profiles.md)
- [Docker setup example](docs/docker.md)
## Installation
### Binary Release
```
curl -L https://github.com/kelseyhightower/coreos-ipxe-server/releases/download/v0.3.0/coreos-ipxe-server-0.3.0-darwin-amd64 -o coreos-ipxe-server
chmod +x coreos-ipxe-server
```
### Source
#### Clone
```
mkdir -p ${GOPATH}/src/github.com/kelseyhightower
cd ${GOPATH}/src/github.com/kelseyhightower
git clone git@github.com:kelseyhightower/coreos-ipxe-server.git
```
#### Build
```
cd ${GOPATH}/src/github.com/kelseyhightower/coreos-ipxe-server
go build .
```
================================================
FILE: api.go
================================================
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"path/filepath"
"text/template"
"github.com/kelseyhightower/coreos-ipxe-server/config"
"github.com/kelseyhightower/coreos-ipxe-server/kernel"
)
const ipxeBootScript = `#!ipxe
set coreos-version {{.Version}}
set base-url http://{{.BaseUrl}}/images/amd64-usr/${coreos-version}
kernel ${base-url}/coreos_production_pxe.vmlinuz{{.Options}}
initrd ${base-url}/coreos_production_pxe_image.cpio.gz
boot
`
func ipxeBootScriptServer(w http.ResponseWriter, r *http.Request) {
log.Printf("creating boot script for %s", r.RemoteAddr)
baseUrl := config.BaseUrl
if baseUrl == "" {
baseUrl = r.Host
}
v := r.URL.Query()
options := kernel.New()
// Process the profile parameter.
profile := v.Get("profile")
if profile != "" {
profilePath := filepath.Join(config.DataDir, fmt.Sprintf("profiles/%s.json", profile))
err := kernalOptionsFromFile(profilePath, options)
if err != nil {
log.Printf("Error reading kernal options from %s: %s", profilePath, err)
http.Error(w, err.Error(), 500)
return
}
}
if options.CloudConfig != "" {
options.SetCloudConfigUrl(fmt.Sprintf("http://%s/configs/%s.yml", baseUrl, options.CloudConfig))
}
if options.SSHKey != "" {
sshKeyPath := filepath.Join(config.DataDir, fmt.Sprintf("sshkeys/%s.pub", options.SSHKey))
sshKey, err := sshKeyFromFile(sshKeyPath)
if err != nil {
log.Printf("Error reading ssh publickey from %s: %s", sshKeyPath, err)
http.Error(w, err.Error(), 500)
return
}
options.SSHKey = sshKey
}
// Process the iPXE boot script template.
t, err := template.New("ipxebootscript").Parse(ipxeBootScript)
if err != nil {
log.Print("Error generating iPXE boot script: " + err.Error())
http.Error(w, "Error generating the iPXE boot script", 500)
return
}
data := map[string]string{
"BaseUrl": baseUrl,
"Options": options.String(),
"Version": options.Version,
}
err = t.Execute(w, data)
if err != nil {
log.Print("Error generating iPXE boot script: " + err.Error())
http.Error(w, "Error generating the iPXE boot script", 500)
return
}
return
}
func sshKeyServer(w http.ResponseWriter, r *http.Request) {
v := r.URL.Query()
keyName := v.Get("name")
if keyName != "" {
log.Printf("retrieving ssh key %s.pub for %s", keyName, r.RemoteAddr)
sshKeyPath := filepath.Join(config.DataDir, fmt.Sprintf("sshkeys/%s.pub", keyName))
sshKey, err := sshKeyFromFile(sshKeyPath)
if err != nil {
log.Printf("Error reading ssh publickey from %s: %s", sshKeyPath, err)
http.Error(w, err.Error(), 500)
return
}
data := []byte(fmt.Sprintf("[{\"key\": \"%s\"}]", sshKey))
w.Write(data)
}
return
}
func sshKeyFromFile(filename string) (string, error) {
b, err := ioutil.ReadFile(filename)
if err != nil {
return "", err
}
return string(bytes.TrimSpace(b)), nil
}
func kernalOptionsFromFile(filename string, options *kernel.Options) error {
data, err := ioutil.ReadFile(filename)
if err != nil {
return err
}
err = json.Unmarshal(data, options)
if err != nil {
return err
}
return nil
}
================================================
FILE: api_test.go
================================================
// Copyright 2014 Kelsey Hightower. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"net/http/httptest"
"os"
"path/filepath"
"testing"
"github.com/kelseyhightower/coreos-ipxe-server/config"
"github.com/kelseyhightower/coreos-ipxe-server/kernel"
)
func createTestData(profiles map[string]*kernel.Options, sshKeys map[string]string) (string, error) {
d, err := ioutil.TempDir("", "coreos-ipxe-server")
if err != nil {
return "", err
}
sshKeyDir := filepath.Join(d, "sshkeys")
err = os.Mkdir(sshKeyDir, 0755)
if err != nil {
return "", err
}
for k, v := range sshKeys {
sshKeyPath := filepath.Join(sshKeyDir, fmt.Sprintf("%s.pub", k))
err := ioutil.WriteFile(sshKeyPath, []byte(v), 0644)
if err != nil {
return "", err
}
}
profileDir := filepath.Join(d, "profiles")
err = os.Mkdir(profileDir, 0755)
if err != nil {
return "", err
}
for k, v := range profiles {
profilePath := filepath.Join(profileDir, fmt.Sprintf("%s.json", k))
data, err := json.Marshal(v)
if err != nil {
return "", err
}
err = ioutil.WriteFile(profilePath, data, 0644)
if err != nil {
return "", err
}
}
return d, nil
}
var profileAOut = `#!ipxe
set coreos-version 310.1.0
set base-url http://example.com/images/amd64-usr/${coreos-version}
kernel ${base-url}/coreos_production_pxe.vmlinuz
initrd ${base-url}/coreos_production_pxe_image.cpio.gz
boot
`
var profileBOut = `#!ipxe
set coreos-version 310.1.0
set base-url http://example.com/images/amd64-usr/${coreos-version}
kernel ${base-url}/coreos_production_pxe.vmlinuz rootfstype=btrfs console=tty0 console=ttyS0 cloud-config-url=http://example.com/configs/b.yml coreos.autologin=ttyS0 sshkey="ssh-rsa AAAAB3Ncoreos" root=/dev/sda1
initrd ${base-url}/coreos_production_pxe_image.cpio.gz
boot
`
var iPxeBootScriptTests = []struct {
name string
body string
code int
baseUrl string
url string
}{
{"a", profileAOut, 200, "", "http://example.com?profile=a"},
{"b", profileBOut, 200, "example.com", "http://example.com?profile=b"},
{"c", "", 500, "example.com", "http://example.com?profile=c"},
{"d", "", 500, "example.com", "http://example.com?profile=d"},
}
func TestIPxeBootScriptServer(t *testing.T) {
sshkeys := map[string]string{
"coreos": "ssh-rsa AAAAB3Ncoreos",
}
profiles := map[string]*kernel.Options{
"a": &kernel.Options{
CloudConfig: "",
Console: []string{},
CoreOSAutologin: "",
Root: "",
RootFstype: "",
SSHKey: "",
Version: "310.1.0",
},
"b": &kernel.Options{
CloudConfig: "b",
Console: []string{"tty0", "ttyS0"},
CoreOSAutologin: "ttyS0",
Root: "/dev/sda1",
RootFstype: "btrfs",
SSHKey: "coreos",
Version: "310.1.0",
},
"c": &kernel.Options{
CloudConfig: "c",
Console: []string{"tty0", "ttyS0"},
CoreOSAutologin: "ttyS0",
Root: "/dev/sda1",
RootFstype: "btrfs",
SSHKey: "imabadkey",
Version: "310.1.0",
},
}
testDataDir, err := createTestData(profiles, sshkeys)
if err != nil {
t.Error(err)
}
defer os.RemoveAll(testDataDir)
config.DataDir = testDataDir
for _, v := range iPxeBootScriptTests {
config.BaseUrl = v.baseUrl
req, err := http.NewRequest("GET", v.url, nil)
if err != nil {
t.Error(err)
}
w := httptest.NewRecorder()
ipxeBootScriptServer(w, req)
if w.Code == 200 && (v.name == "a" || v.name == "b") {
if w.Body.String() != v.body {
t.Errorf("expected %s\ngot %s\n", v.body, w.Body.String())
}
} else if (v.name == "c" || v.name == "d") && w.Code != 500 {
t.Errorf("expected %d\ngot %d\n", v.code, w.Code)
}
}
}
var SSHKeyServerTests = []struct {
name string
body string
code int
baseUrl string
url string
}{
{"a", `[{"key": "ssh-rsa AAAAB3Ncoreos"}]`, 200, "", "http://example.com/keys?name=coreos"},
{"b", `[{"key": "ssh-rsa AAAAB3Nfoo"}]`, 200, "example.com", "http://example.com/keys?name=foo"},
{"c", "", 500, "example.com", "http://example.com/keys?name=badkey"},
}
func TestSSHKeyServer(t *testing.T) {
sshkeys := map[string]string{
"coreos": "ssh-rsa AAAAB3Ncoreos",
"foo": "ssh-rsa AAAAB3Nfoo",
}
testDataDir, err := createTestData(nil, sshkeys)
if err != nil {
t.Error(err)
}
defer os.RemoveAll(testDataDir)
config.DataDir = testDataDir
for _, v := range SSHKeyServerTests {
config.BaseUrl = v.baseUrl
req, err := http.NewRequest("GET", v.url, nil)
if err != nil {
t.Error(err)
}
w := httptest.NewRecorder()
sshKeyServer(w, req)
if w.Code == 200 && (v.name == "a" || v.name == "b") {
if w.Body.String() != v.body {
t.Errorf("expected %s\ngot %s\n", v.body, w.Body.String())
}
} else if (v.name == "c") && w.Code != 500 {
t.Errorf("expected %d\ngot %d\n", v.code, w.Code)
}
}
}
================================================
FILE: config/config.go
================================================
package config
import (
"os"
)
var (
BaseUrl string
DataDir string
ListenAddr string
)
var defaultDataDir = "/opt/coreos-ipxe-server"
var defaultListenAddr = "0.0.0.0:4777"
func init() {
BaseUrl = os.Getenv("COREOS_IPXE_SERVER_BASE_URL")
// Set the data directory where the coreos directory containing
// the ssh public key, kernal and boot images.
DataDir = os.Getenv("COREOS_IPXE_SERVER_DATA_DIR")
if DataDir == "" {
DataDir = defaultDataDir
}
ListenAddr = os.Getenv("COREOS_IPXE_SERVER_LISTEN_ADDR")
if ListenAddr == "" {
ListenAddr = defaultListenAddr
}
}
================================================
FILE: docker/.gitignore
================================================
configs/
images/
profiles/
sshkeys/
================================================
FILE: docker/Dockerfile
================================================
FROM google/golang
RUN mkdir -p /gopath/src/github.com/kelseyhightower
WORKDIR /gopath/src/github.com/kelseyhightower
RUN git clone https://github.com/kelseyhightower/coreos-ipxe-server.git
WORKDIR /gopath/src/github.com/kelseyhightower/coreos-ipxe-server
RUN go install
RUN mkdir -p /opt/coreos-ipxe-server
ADD configs /opt/coreos-ipxe-server/configs
ADD images /opt/coreos-ipxe-server/images
ADD profiles /opt/coreos-ipxe-server/profiles
ADD sshkeys /opt/coreos-ipxe-server/sshkeys
ENV COREOS_IPXE_SERVER_DATA_DIR /opt/coreos-ipxe-server
# URL has to be substituted with correct value. Can be overwritten during docker run
ENV COREOS_IPXE_SERVER_BASE_URL coreos.ipxe.example.com:4777
ENV COREOS_IPXE_SERVER_LISTEN_ADDR 0.0.0.0:4777
CMD /gopath/bin/coreos-ipxe-server
================================================
FILE: docker/setup_docker.sh
================================================
#!/bin/bash
# SETUP ENV
COREOS_IPXE_SERVER_BASE_URL="<ip/dns record>:4777"
COREOS_IPXE_SERVER_LISTEN_ADDR="0.0.0.0:4777"
VERSIONS=("367.1.0" "379.3.0")
# PREPARE DIRECTORY STRUCTURE
mkdir -p {configs,images,profiles,sshkeys}
# DOWNLOAD IMAGES
for VERSION in "${VERSIONS[@]}"
do
echo "Downloading files for version ${VERSION}"
mkdir -p images/amd64-usr/$VERSION
wget -nc http://storage.core-os.net/coreos/amd64-usr/$VERSION/coreos_production_pxe_image.cpio.gz -O images/amd64-usr/${VERSION}/coreos_production_pxe_image.cpio.gz
wget -nc http://storage.core-os.net/coreos/amd64-usr/$VERSION/coreos_production_pxe.vmlinuz -O images/amd64-usr/${VERSION}/coreos_production_pxe.vmlinuz
done
# CUSTOMIZE COREOS SERVER CONFIGURATION
echo "<ssh-key>" > sshkeys/coreos.pub
cat > configs/development.yml <<EOF
#cloud-config
ssh_authorized_keys:
- <ssh-key>
coreos:
etcd:
# generate a new token for each unique cluster from https://discovery.etcd.io/new
# WARNING: replace each time you 'vagrant destroy'
discovery: https://discovery.etcd.io/a1efed8239a47c98c12ce07e2b67f0ed
addr: $public_ipv4:4001
peer-addr: $public_ipv4:7001
units:
- name: etcd.service
command: start
- name: fleet.service
command: start
runtime: no
content: |
[Unit]
Description=fleet
[Service]
Environment=FLEET_PUBLIC_IP=$public_ipv4
ExecStart=/usr/bin/fleet
- name: docker-tcp.socket
command: start
enable: true
content: |
[Unit]
Description=Docker Socket for the API
[Socket]
ListenStream=2375
Service=docker.service
BindIPv6Only=both
[Install]
WantedBy=sockets.target
EOF
for VERSION in "${VERSIONS[@]}"
do
cat > profiles/development_${VERSION}.json <<EOF
{
"cloud_config": "development",
"rootfstype": "btrfs",
"sshkey": "coreos",
"version": "${VERSION}"
}
EOF
done
# BUILD DOCKER
docker build -t jveverka/ipxe .
# RUN DOCKER
docker run -d -p 4777:4777 -e "COREOS_IPXE_SERVER_BASE_URL=${COREOS_IPXE_SERVER_BASE_URL}" -e "COREOS_IPXE_SERVER_LISTEN_ADDR=${COREOS_IPXE_SERVER_LISTEN_ADDR}" jveverka/ipxe
================================================
FILE: docs/api.md
================================================
# API
## iPXE Boot Script
Dynamically generate a CoreOS iPXE boot script.
```
GET http://coreos.ipxe.example.com
```
**Parameters**
Name | Type | Description
-----|------|------------
profile | string | The CoreOS iPXE profile to use.
#### Generate Boot Script with a specific profile
```
GET http://coreos.ipxe.example.com?profile=development
```
**Response**
```
HTTP/1.1 200 OK
```
```
set coreos-version 310.1.0
set base-url http://coreos.ipxe.example.com/images/amd64-usr/${coreos-version}
kernel ${base-url}/coreos_production_pxe.vmlinuz console=tty0 rootfstype=btrfs cloud-config-url=http://coreos.ipxe.example.com/configs/development.yml
initrd ${base-url}/coreos_production_pxe_image.cpio.gz
boot
```
## Retrieve an SSH Public Key
Produce an SSH public key suitable for use by `coreos-cloudconfig` to insert into
a user's `authorized_keys`.
```
GET http://coreos.ipxe.example.com/keys
```
**Parameters**
Name | Type | Description
-----|------|------------
name | string | The name of the key (not including .pub)
#### Generate a key for a specified name
```
GET http://coreos.ipxe.example.com/keys?name=foo
```
**Response**
```
HTTP/1.1 200 OK
```
```
[{"key":"ssh-rsa AAAAB3N... foo@bar"}]
```
================================================
FILE: docs/cloudconfigs.md
================================================
### Cloud Configs
Cloud configs can be used to automate the configuration of your CoreOS install. The `cloud-config-url` is configured via the cloud-config-url boot parameter, which is part of the CoreOS iPXE boot script. Cloud configs are identified by id and are stored under the `$COREOS_IPXE_SERVER_DATA_DIR/configs` directory.
Example:
```
$COREOS_IPXE_SERVER_DATA_DIR/configs/development.yml
```
================================================
FILE: docs/configuration.md
================================================
## Configuration
### Environment Variables
#### Optional:
```
COREOS_IPXE_SERVER_DATA_DIR
COREOS_IPXE_SERVER_BASE_URL
COREOS_IPXE_SERVER_LISTEN_ADDR
```
#### Example:
```
export COREOS_IPXE_SERVER_DATA_DIR="/opt/coreos-ipxe-server"
export COREOS_IPXE_SERVER_BASE_URL="coreos.ipxe.example.com:4777"
export COREOS_IPXE_SERVER_LISTEN_ADDR="0.0.0.0:4777"
```
================================================
FILE: docs/docker.md
================================================
# Example of running coreos-ipxe-server on docker
### The script will
- Prepare directory structure
- download images for versions specified in VERSIONS
- create default config files
- build ipxe docker image
- run ipxe docker container
### Following has to be done before running the script
- update following env vars so that they suit your needs
- ```
COREOS_IPXE_SERVER_BASE_URL ip/dns on which your docker will listen
COREOS_IPXE_SERVER_LISTEN_ADDR="0.0.0.0:4777"
VERSIONS=("367.1.0" "379.3.0")
```
- include your ssh-key
- run script
- cd docker && ./setup_docker.sh
If everything runs sucessfully you should be able to see you container running among others using ``docker ps``
You can try to access iPXE config on ``<COREOS_IPXE_SERVER_BASE_URL>:4777/?profile=development_<VERSION>``
In my case it will be ``http://10.102.11.42:4777/?profile=development_367.1.0``
================================================
FILE: docs/getting_started.md
================================================
# Getting Started
- [Installation](#installation)
- [Configuration](#configuration)
- [Create the Data Directory](#create-the-data-directory)
- [Download the CoreOS PXE Images](#download-the-coreos-pxe-images)
- [Add a Cloud Config File](#add-a-cloud-config-file)
- [Add a SSH Public Key](#add-an-ssh-public-key)
- [Add an iPXE Profile](#add-an-ipxe-profile)
- [Example Data Directory Layout](#example-data-directory-layout)
### Installation
```
curl -L https://github.com/kelseyhightower/coreos-ipxe-server/releases/download/v0.3.0/coreos-ipxe-server-0.3.0-darwin-amd64 -o coreos-ipxe-server
chmod +x coreos-ipxe-server
```
### Configuration
All configuration is handled via environment variables with sane defaults. See [Configuration](configuration.md) for more details.
### Create the Data Directory
The data directory is where the CoreOS images, SSH public keys, cloud configs and iPXE profiles are stored. The data directory defaults to `/opt/coreos-ipxe-server`; set it to a different directory via the `COREOS_IPXE_SERVER_DATA_DIR` environment variable:
```
mkdir -p $COREOS_IPXE_SERVER_DATA_DIR/{configs,images,profiles,sshkeys}
```
### Download the CoreOS PXE Images
The CoreOS PXE images are stored under the `$COREOS_IPXE_SERVER_DATA_DIR/images` directory.
```
mkdir -p $COREOS_IPXE_SERVER_DATA_DIR/images/amd64-usr/310.1.0
cd $COREOS_IPXE_SERVER_DATA_DIR/images/amd64-usr/310.1.0
wget http://storage.core-os.net/coreos/amd64-usr/310.1.0/coreos_production_pxe_image.cpio.gz
wget http://storage.core-os.net/coreos/amd64-usr/310.1.0/coreos_production_pxe.vmlinuz
```
### Add an SSH Public Key
SSH public keys are used to login to your CoreOS instance. SSH public keys are stored under the `$COREOS_IPXE_SERVER_DATA_DIR/sshkeys` directory.
Edit `$COREOS_IPXE_SERVER_DATA_DIR/sshkeys/coreos.pub`
```
ssh-rsa AAAAB3Nza...
```
### Add a Cloud Config File
Cloud config files are used to automated the setup of your CoreOS instance. See [Customize with Cloud Config](https://coreos.com/docs/cluster-management/setup/cloudinit-cloud-config/) for more details. Cloud config files are stored under the `$COREOS_IPXE_SERVER_DATA_DIR/configs` directory.
Edit `$COREOS_IPXE_SERVER_DATA_DIR/configs/development.yml`
```
#cloud-config
ssh_authorized_keys:
- ssh-rsa AAAAB3Nza...
coreos:
etcd:
addr: $private_ipv4:4001
peer-addr: $private_ipv4:7001
units:
- name: etcd.service
command: start
- name: fleet.service
command: start
- name: docker.socket
command: start
oem:
id: coreos
name: CoreOS Custom
version-id: 310.1.0
home-url: https://coreos.com
```
### Add an iPXE Profile
iPXE profiles are used to define CoreOS boot parameters. iPXE profiles are stored under the `$COREOS_IPXE_SERVER_DATA_DIR/profiles` directory.
Edit `$COREOS_IPXE_SERVER_DATA_DIR/profiles/development.json`
```
{
"cloud_config": "development",
"rootfstype": "btrfs",
"sshkey": "coreos",
"version": "310.1.0"
}
```
### Example Data Directory Layout
```
/opt/coreos-ipxe-server/
├── configs
│ └── development.yml
├── images
│ └── amd64-usr
│ └── 310.1.0
│ ├── coreos_production_pxe.vmlinuz
│ └── coreos_production_pxe_image.cpio.gz
├── profiles
│ └── development.json
└── sshkeys
└── coreos.pub
```
================================================
FILE: docs/profiles.md
================================================
# Profiles
iPXE profiles are used to define CoreOS kernel options used during the PXE boot process. Profiles are identified by id and are stored under the `$COREOS_IPXE_SERVER_DATA_DIR/profiles` directory.
## File Format
The iPXE profile file uses the JSON file format.
A iPXE profile file should contain an associative array which has zero or more of the following keys:
* cloud_config
* console
* coreos_autologin
* rootfstype
* sshkey
* version
See [Configuring pxelinux](https://coreos.com/docs/running-coreos/bare-metal/booting-with-pxe/#configuring-pxelinux) for more details.
### Example Profile
```
$COREOS_IPXE_SERVER_DATA_DIR/profiles/development.json
```
```
{
"cloud_config": "development",
"console": ["tty0", "tty1"],
"coreos_autologin": "tty1",
"rootfstype": "btrfs",
"sshkey": "coreos",
"version": "310.1.0"
}
```
================================================
FILE: docs/sshkeys.md
================================================
# SSH Public Keys
SSH keys are configured via the sshkey boot parameter, which is part of the CoreOS iPXE boot script. SSH keys are identified by id and are stored under the `$COREOS_IPXE_SERVER_DATA_DIR/sshkeys` directory.
Example:
```
$COREOS_IPXE_SERVER_DATA_DIR/sshkeys/coreos.pub
```
================================================
FILE: kernel/options.go
================================================
package kernel
import (
"bytes"
"fmt"
)
type Options struct {
CloudConfig string `json:"cloud_config"`
Console []string `json:"console"`
CoreOSAutologin string `json:"coreos_autologin"`
Root string `json:"root"`
RootFstype string `json:"rootfstype"`
SSHKey string `json:"sshkey"`
Version string `json:"version"`
cloudConfigUrl string
}
func New() *Options {
return &Options{}
}
func (o *Options) SetCloudConfigUrl(url string) {
o.cloudConfigUrl = url
}
func (o *Options) String() string {
var options bytes.Buffer
if o.RootFstype != "" {
options.WriteString(fmt.Sprintf(" rootfstype=%s", o.RootFstype))
}
for _, c := range o.Console {
options.WriteString(fmt.Sprintf(" console=%s", c))
}
if o.cloudConfigUrl != "" {
options.WriteString(fmt.Sprintf(" cloud-config-url=%s", o.cloudConfigUrl))
}
if o.CoreOSAutologin != "" {
options.WriteString(fmt.Sprintf(" coreos.autologin=%s", o.CoreOSAutologin))
}
if o.SSHKey != "" {
options.WriteString(fmt.Sprintf(" sshkey=\"%s\"", o.SSHKey))
}
if o.Root != "" {
options.WriteString(fmt.Sprintf(" root=%s", o.Root))
}
return options.String()
}
================================================
FILE: kernel/options_test.go
================================================
package kernel
import (
"testing"
)
func TestDefaultOptions(t *testing.T) {
want := ""
o := New()
options := o.String()
if options != want {
t.Errorf("wanted %s, got %s", want, options)
}
}
var optionstests = []struct {
cloudConfigUrl string
console []string
coreOSAutologin string
root string
rootFstype string
sshKey string
options string
}{
{
"http://host/config.yml",
[]string{"tty0", "ttyS0"},
"ttyS0",
"",
"tmpfs",
"ssh-rsa AAAAB3Nza...",
" rootfstype=tmpfs console=tty0 console=ttyS0 cloud-config-url=http://host/config.yml coreos.autologin=ttyS0 sshkey=\"ssh-rsa AAAAB3Nza...\"",
},
{
"",
nil,
"",
"",
"",
"ssh-rsa AAAAB3Nza...",
" sshkey=\"ssh-rsa AAAAB3Nza...\"",
},
}
func TestOptions(t *testing.T) {
for _, tt := range optionstests {
o := New()
o.SetCloudConfigUrl(tt.cloudConfigUrl)
if tt.console != nil {
o.Console = tt.console
}
o.RootFstype = tt.rootFstype
o.SSHKey = tt.sshKey
o.CoreOSAutologin = tt.coreOSAutologin
o.Root = tt.root
got := o.String()
if got != tt.options {
t.Errorf("wanted %s, got %s", tt.options, got)
}
}
}
================================================
FILE: main.go
================================================
// Copyright 2014 Kelsey Hightower. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"fmt"
"log"
"net/http"
"path/filepath"
"github.com/kelseyhightower/coreos-ipxe-server/config"
)
func main() {
for _, s := range []string{"/images/", "/configs/", "/profiles/"} {
// Register static file servers.
http.Handle(s, http.StripPrefix(s,
http.FileServer(http.Dir(filepath.Join(config.DataDir, s)))))
}
// Register the sshkey script server.
http.HandleFunc("/keys", sshKeyServer)
// Register the iPXE boot script server.
http.HandleFunc("/", ipxeBootScriptServer)
// Start the iPXE Boot Server.
fmt.Println("Starting CoreOS iPXE Server...")
fmt.Printf("Listening on %s\n", config.ListenAddr)
if config.BaseUrl != "" {
fmt.Printf("Advertised URL %s\n", config.BaseUrl)
}
fmt.Printf("Data directory: %s\n", config.DataDir)
log.Fatal(http.ListenAndServe(config.ListenAddr, nil))
}
gitextract_12q8nhyr/ ├── .gitignore ├── LICENSE ├── README.md ├── api.go ├── api_test.go ├── config/ │ └── config.go ├── docker/ │ ├── .gitignore │ ├── Dockerfile │ └── setup_docker.sh ├── docs/ │ ├── api.md │ ├── cloudconfigs.md │ ├── configuration.md │ ├── docker.md │ ├── getting_started.md │ ├── profiles.md │ └── sshkeys.md ├── kernel/ │ ├── options.go │ └── options_test.go └── main.go
SYMBOL INDEX (16 symbols across 6 files)
FILE: api.go
constant ipxeBootScript (line 17) | ipxeBootScript = `#!ipxe
function ipxeBootScriptServer (line 25) | func ipxeBootScriptServer(w http.ResponseWriter, r *http.Request) {
function sshKeyServer (line 83) | func sshKeyServer(w http.ResponseWriter, r *http.Request) {
function sshKeyFromFile (line 101) | func sshKeyFromFile(filename string) (string, error) {
function kernalOptionsFromFile (line 109) | func kernalOptionsFromFile(filename string, options *kernel.Options) err...
FILE: api_test.go
function createTestData (line 21) | func createTestData(profiles map[string]*kernel.Options, sshKeys map[str...
function TestIPxeBootScriptServer (line 87) | func TestIPxeBootScriptServer(t *testing.T) {
function TestSSHKeyServer (line 160) | func TestSSHKeyServer(t *testing.T) {
FILE: config/config.go
function init (line 16) | func init() {
FILE: kernel/options.go
type Options (line 8) | type Options struct
method SetCloudConfigUrl (line 23) | func (o *Options) SetCloudConfigUrl(url string) {
method String (line 27) | func (o *Options) String() string {
function New (line 19) | func New() *Options {
FILE: kernel/options_test.go
function TestDefaultOptions (line 7) | func TestDefaultOptions(t *testing.T) {
function TestOptions (line 45) | func TestOptions(t *testing.T) {
FILE: main.go
function main (line 16) | func main() {
Condensed preview — 19 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (28K chars).
[
{
"path": ".gitignore",
"chars": 24,
"preview": "data\ncoreos-ipxe-server\n"
},
{
"path": "LICENSE",
"chars": 1060,
"preview": "Copyright (c) 2014 Kelsey Hightower\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthi"
},
{
"path": "README.md",
"chars": 1135,
"preview": "# CoreOS iPXE Server\n\n[](https"
},
{
"path": "api.go",
"chars": 3113,
"preview": "package main\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io/ioutil\"\n\t\"log\"\n\t\"net/http\"\n\t\"path/filepath\"\n\t\"text/template"
},
{
"path": "api_test.go",
"chars": 5005,
"preview": "// Copyright 2014 Kelsey Hightower. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// licens"
},
{
"path": "config/config.go",
"chars": 587,
"preview": "package config\n\nimport (\n\t\"os\"\n)\n\nvar (\n\tBaseUrl string\n\tDataDir string\n\tListenAddr string\n)\n\nvar defaultDataDir ="
},
{
"path": "docker/.gitignore",
"chars": 36,
"preview": "configs/\nimages/\nprofiles/\nsshkeys/\n"
},
{
"path": "docker/Dockerfile",
"chars": 775,
"preview": "FROM google/golang\n\nRUN mkdir -p /gopath/src/github.com/kelseyhightower\n\nWORKDIR /gopath/src/github.com/kelseyhightower\n"
},
{
"path": "docker/setup_docker.sh",
"chars": 2195,
"preview": "#!/bin/bash\n\n# SETUP ENV\nCOREOS_IPXE_SERVER_BASE_URL=\"<ip/dns record>:4777\"\nCOREOS_IPXE_SERVER_LISTEN_ADDR=\"0.0.0.0:4777"
},
{
"path": "docs/api.md",
"chars": 1226,
"preview": "# API\n\n## iPXE Boot Script\n\nDynamically generate a CoreOS iPXE boot script.\n\n```\nGET http://coreos.ipxe.example.com\n```\n"
},
{
"path": "docs/cloudconfigs.md",
"chars": 405,
"preview": "### Cloud Configs\n\nCloud configs can be used to automate the configuration of your CoreOS install. The `cloud-config-url"
},
{
"path": "docs/configuration.md",
"chars": 360,
"preview": "## Configuration\n\n### Environment Variables\n\n#### Optional:\n\n```\nCOREOS_IPXE_SERVER_DATA_DIR\nCOREOS_IPXE_SERVER_BASE_URL"
},
{
"path": "docs/docker.md",
"chars": 878,
"preview": "# Example of running coreos-ipxe-server on docker\n\n### The script will\n- Prepare directory structure\n- download images f"
},
{
"path": "docs/getting_started.md",
"chars": 3302,
"preview": "# Getting Started\n\n- [Installation](#installation)\n- [Configuration](#configuration)\n- [Create the Data Directory](#crea"
},
{
"path": "docs/profiles.md",
"chars": 851,
"preview": "# Profiles\n\niPXE profiles are used to define CoreOS kernel options used during the PXE boot process. Profiles are identi"
},
{
"path": "docs/sshkeys.md",
"chars": 292,
"preview": "# SSH Public Keys\n\nSSH keys are configured via the sshkey boot parameter, which is part of the CoreOS iPXE boot script. "
},
{
"path": "kernel/options.go",
"chars": 1183,
"preview": "package kernel\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n)\n\ntype Options struct {\n\tCloudConfig string `json:\"cloud_config\"`\n\tConso"
},
{
"path": "kernel/options_test.go",
"chars": 1167,
"preview": "package kernel\n\nimport (\n\t\"testing\"\n)\n\nfunc TestDefaultOptions(t *testing.T) {\n\twant := \"\"\n\to := New()\n\toptions := o.Str"
},
{
"path": "main.go",
"chars": 999,
"preview": "// Copyright 2014 Kelsey Hightower. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// licens"
}
]
About this extraction
This page contains the full source code of the kelseyhightower/coreos-ipxe-server GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 19 files (24.0 KB), approximately 7.5k tokens, and a symbol index with 16 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.