Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
jacob-carlborg committed May 31, 2021
0 parents commit 53b3895
Show file tree
Hide file tree
Showing 15 changed files with 535 additions and 0 deletions.
79 changes: 79 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
name: Build VM Disk Image

on:
push:
branches: '*'
tags: 'v*'
pull_request:
branches:
- master

jobs:
build:
name: Build
runs-on: ubuntu-latest
container: ubuntu:21.04
strategy:
matrix:
version:
- 6.8

architecture:
- x86-64
- arm64

steps:
- name: Clone Repository
uses: actions/checkout@v2
with:
persist-credentials: false

- name: Install Dependecies
run: apt update && apt install curl unzip "qemu-system-$QEMU_ARCHITECTURE" -y
env:
QEMU_ARCHITECTURE: ${{
matrix.architecture == 'x86-64' && 'x86' ||
matrix.architecture == 'arm64' && 'aarch64' ||
matrix.architecture
}}

- name: Install Packer
run: |
curl -o packer.zip -L https://releases.hashicorp.com/packer/1.7.1/packer_1.7.1_linux_amd64.zip
unzip packer.zip
mv packer /usr/local/bin
- name: Copy UEFI
if: matrix.architecture == 'x86-64'
run: cp /usr/share/ovmf/OVMF.fd resources/ovmf.fd

- name: Download QEMU UEFI
if: matrix.architecture == 'arm64'
run: curl -o resources/qemu_efi.fd -L http://releases.linaro.org/components/kernel/uefi-linaro/latest/release/qemu64/QEMU_EFI.fd

# - name: Setup tmate session
# uses: mxschmitt/action-tmate@v3

- name: Build Image
run: |
PACKER_LOG=1 ./build.sh \
'${{ matrix.version }}' \
'${{ matrix.architecture }}' \
-var 'headless=true' \
-var 'readonly_boot_media=false'
- name: Extract Version
id: version
if: startsWith(github.ref, 'refs/tags/v')
run: echo ::set-output name=VERSION::${GITHUB_REF#refs/tags/v}

- name: Create Release
id: create_release
if: startsWith(github.ref, 'refs/tags/v')
uses: softprops/action-gh-release@v1
with:
name: OpenBSD ${{ steps.version.outputs.VERSION }}
draft: true
files: output/*
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
resources/ovmf.fd
resources/qemu_efi.fd
packer_cache
packer_cache_backup
output
16 changes: 16 additions & 0 deletions build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#!/bin/bash

set -euxo pipefail

OS_VERSION="$1"; shift
ARCHITECTURE="$1"; shift

# rm -rf packer_cache

packer build \
-var-file "var_files/common.pkrvars.hcl" \
-var-file "var_files/$ARCHITECTURE.pkrvars.hcl" \
-var-file "var_files/$OS_VERSION/common.pkrvars.hcl" \
-var-file "var_files/$OS_VERSION/$ARCHITECTURE.pkrvars.hcl" \
"$@" \
openbsd.pkr.hcl
198 changes: 198 additions & 0 deletions openbsd.pkr.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
variable "os_version" {
type = string
description = "The version of the operating system to download and install"
}

variable "architecture" {
default = "x86-64"
type = string
description = "The type of CPU to use when building"
}

variable "machine_type" {
default = "pc"
type = string
description = "The type of machine to use when building"
}

variable "cpu_type" {
default = "qemu64"
type = string
description = "The type of CPU to use when building"
}

variable "memory" {
default = 4096
type = number
description = "The amount of memory to use when building the VM in megabytes"
}

variable "cpus" {
default = 2
type = number
description = "The number of cpus to use when building the VM"
}

variable "disk_size" {
default = "12G"
type = string
description = "The size in bytes of the hard disk of the VM"
}

variable "checksum" {
type = string
description = "The checksum for the virtual hard drive file"
}

variable "root_password" {
default = "vagrant"
type = string
description = "The password for the root user"
}

variable "secondary_user_password" {
default = "vagrant"
type = string
description = "The password for the `secondary_user_username` user"
}

variable "secondary_user_username" {
default = "vagrant"
type = string
description = "The name for the secondary user"
}

variable "headless" {
default = false
description = "When this value is set to `true`, the machine will start without a console"
}

variable "use_default_display" {
default = true
type = bool
description = "If true, do not pass a -display option to qemu, allowing it to choose the default"
}

variable "display" {
default = "cocoa"
description = "What QEMU -display option to use"
}

variable "accelerator" {
default = "tcg"
type = string
description = "The accelerator type to use when running the VM"
}

variable "firmware" {
type = string
description = "The firmware file to be used by QEMU"
}

variable "readonly_boot_media" {
default = true
description = "If true, the boot media will be mounted as readonly"
}

variable "sudo_version" {
type = string
description = "The version of the sudo package to install"
}

variable "rsync_version" {
type = string
description = "The version of the rsync package to install"
}

locals {
image_architecture = var.architecture == "x86-64" ? "amd64" : var.architecture
image = "miniroot${replace(var.os_version, ".", "")}.img"
vm_name = "openbsd-${var.os_version}-${var.architecture}.qcow2"

iso_target_extension = "img"
iso_target_path = "packer_cache"
iso_full_target_path = "${local.iso_target_path}/${sha1(var.checksum)}.${local.iso_target_extension}"

qemu_architecture = var.architecture == "arm64" ? "aarch64" : (
var.architecture == "x86-64" ? "x86_64" : var.architecture
)

readonly_boot_media = var.readonly_boot_media ? "on" : "off"
}

source "qemu" "qemu" {
machine_type = var.machine_type
cpus = var.cpus
memory = var.memory
net_device = "e1000"

disk_compression = true
disk_interface = "virtio"
disk_size = var.disk_size
format = "qcow2"

headless = var.headless
use_default_display = var.use_default_display
display = var.display
accelerator = var.accelerator
qemu_binary = "qemu-system-${local.qemu_architecture}"
firmware = var.firmware

boot_wait = "30s"

boot_command = [
"S<enter><wait>",
"dhclient em0<enter><wait>",
"ftp -o install.conf http://{{ .HTTPIP }}:{{ .HTTPPort }}/resources/install.conf<enter><wait>",
"ftp -o install.sh http://{{ .HTTPIP }}:{{ .HTTPPort }}/resources/install.sh<enter><wait>",
"SECONDARY_USER_USERNAME=${var.secondary_user_username} ",
"SECONDARY_USER_PASSWORD=${var.secondary_user_password} ",
"ROOT_PASSWORD=${var.root_password} ",
"DISKLABEL_TEMPLATE='http://{{ .HTTPIP }}:{{ .HTTPPort }}/resources/template.disklabel' ",
"sh install.sh && reboot<enter>"
]

ssh_username = "root"
ssh_password = var.root_password
ssh_timeout = "10000s"

qemuargs = [
["-cpu", var.cpu_type],
["-boot", "strict=off"],
["-monitor", "none"],
["-device", "virtio-scsi-pci"],
["-device", "scsi-hd,drive=drive0,bootindex=0"],
["-device", "scsi-hd,drive=drive1,bootindex=1"],
["-drive", "if=none,file={{ .OutputDir }}/{{ .Name }},id=drive0,cache=writeback,discard=ignore,format=qcow2"],
["-drive", "if=none,file=${local.iso_full_target_path},id=drive1,media=disk,format=raw,readonly=${local.readonly_boot_media}"],
]

iso_checksum = var.checksum
iso_target_extension = local.iso_target_extension
iso_target_path = local.iso_target_path
iso_urls = [
"http://cdn.openbsd.org/pub/OpenBSD/${var.os_version}/${local.image_architecture}/${local.image}"
]

http_directory = "."
output_directory = "output"
shutdown_command = "shutdown -h -p now"
vm_name = local.vm_name
}

build {
sources = ["qemu.qemu"]

provisioner "shell" {
script = "resources/provision.sh"
environment_vars = [
"SECONDARY_USER=${var.secondary_user_username}",
"SUDO_VERSION=${var.sudo_version}",
"RSYNC_VERSION=${var.rsync_version}"
]
}

/*provisioner "shell-local" {
inline = ["if [ -d packer_cache_backup ]; then cp packer_cache_backup/* ${local.iso_target_path}; fi"]
}*/
}
74 changes: 74 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# OpenBSD Builder

This project builds the OpenBSD VM image for the
[cross-platform-actions/action](https://github.com/cross-platform-actions/action)
GitHub action. The image contains a standard OpenBSD installation without any
X components, man pages or games. It will install the following file sets:

* bsd
* bsd.mp
* bsd.rd
* baseXX.tgz
* compXX.tgz

In addition to the above file sets, the following packages are installed as well:

* sudo
* bash
* curl
* rsync

Except for the root user, there's one additional user, `runner`, which is the
user that will be running the commands in the GitHub action. This user is
allowed use `sudo` without a password.

## Architectures and Versions

The following architectures and versions are supported:

| Version | x86-64 | arm64 |
|---------|--------|-------|
| 6.8 |||

## Building Locally

### Prerequisite

* [Packer](https://www.packer.io) 1.7.1 or later
* [QEMU](https://qemu.org)

### Building

1. Clone the repository:
```
git clone https://github.com/cross-platform-actions/openbsd-builder
cd openbsd-builder
```

2. Run `build.sh` to build the image:
```
./build.sh <version> <architecture>
```
Where `<version>` and `<architecture>` are the any of the versions or
architectures available in the above table.

The above command will build the VM image and the resulting disk image will be
at the path: `output/openbsd-6.8-amd64.qcow2`.

## Additional Information

At startup, the image will look for a second hard drive. If present and it
contains a file named `keys` at the root, it will install this file as the
`authorized_keys` file for the `runner` user. The disk is expected to be
formatted as FAT32. This is used as an alternative to a shared folder between
the host and the guest, since this is not supported by the xhyve hypervisor.
FAT32 is chosen because it's the only filesystem that is supported by both the
host (macOS) and the guest (OpenBSD) out of the box.

The VM needs to be configured with the `e1000` network device. The disk needs to
be configured with the GPT partitioning scheme. And the VM needs to be configured
to use UEFI. All this is required for the VM image to be able to run using the
xhyve hypervisor.

The qcow2 format is chosen because unused space doesn't take up any space on
disk, it's compressible and easily converts the raw format, used by xhyve.
14 changes: 14 additions & 0 deletions resources/install.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
System hostname = openbsd
IPv4 address for = dhcp
Password for root account = {{ ROOT_PASSWORD }}
Do you expect to run the X Window System = no
Setup a user = {{ SECONDARY_USER_USERNAME }}
Password for user = {{ SECONDARY_USER_PASSWORD }}
Allow root ssh login = yes
What timezone are you in = Etc/UTC
Which disk is the root disk = sd0
Use (W)hole disk MBR, whole disk (G)PT or (E)dit = g
URL to autopartitioning template for disklabel = {{ DISKLABEL_TEMPLATE }}
Http Server = cdn.openbsd.org
Set name(s) = -game* -x* -man*
Directory does not contain SHA256.sig. Continue without verification = yes
Loading

0 comments on commit 53b3895

Please sign in to comment.