dustin
/
jenkinsagent
Archived
1
0
Fork 0

Initial commit

master
Dustin 2022-03-09 00:27:30 -06:00
commit 9d2c710be9
34 changed files with 2754 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/_build

0
Config.in Normal file
View File

32
README.md Normal file
View File

@ -0,0 +1,32 @@
# Network-Booted Jenkins Agent
## Required Build Host Configuration
```sh
sudo dnf install -y \
ncurses-devel \
perl-ExtUtils-MakeMaker \
perl-FindBin \
perl-Thread-Queue \
--
```
```sh
git clone git://git.buildroot.net/buildroot ~/src/buildroot
```
## Build
### Build the Initramfs
```sh
make -C ~/src/buildroot O=${PWD}/_build/initramfs BR2_EXTERNAL=${PWD} jenkinsagent_initramfs_defconfig
make -C _build/initramfs -j $(nproc)
```
### Build the Rootfs
```sh
make -C ~/src/buildroot O=${PWD}/_build/rootfs BR2_EXTERNAL=${PWD} jenkinsagent_defconfig
make -C _build/rootfs -j $(nproc)
```

1
cmdline.txt Normal file
View File

@ -0,0 +1 @@
audit=0 panic=5 console=ttyAMA0 root=nbd:rosalina.pyrocufflink.blue:jenkinsagent rsyslog.dest=rosalina.pyrocufflink.blue sshkeys.root=http://rosalina.pyrocufflink.blue/~dustin/id_ed25519.pub

23
config.txt Normal file
View File

@ -0,0 +1,23 @@
# See http://buildroot.org/manual.html#rootfs-custom
# and http://elinux.org/RPiconfig for a description of config.txt syntax
start_file=start4.elf
fixup_file=fixup4.dat
kernel=Image
# To use an external initramfs file
initramfs rootfs.cpio.lz4
# Disable overscan assuming the display supports displaying the full resolution
# If the text shown on the screen disappears off the edge, comment this out
disable_overscan=1
dtoverlay=vc4-kms-v3d-pi4
dtoverlay=imx219
#dtoverlay=ov5647
dtoverlay=disable-bt
# enable 64bits support
arm_64bit=1

View File

@ -0,0 +1,49 @@
BR2_aarch64=y
BR2_cortex_a72=y
BR2_ARM_FPU_VFPV4=y
BR2_TOOLCHAIN_BUILDROOT_GLIBC=y
BR2_PACKAGE_HOST_LINUX_HEADERS_CUSTOM_5_10=y
BR2_TOOLCHAIN_BUILDROOT_CXX=y
BR2_INIT_SYSTEMD=y
# BR2_TARGET_ENABLE_ROOT_LOGIN is not set
BR2_SYSTEM_DEFAULT_PATH="/bin:/sbin:/usr/bin:/usr/sbin"
BR2_ROOTFS_OVERLAY="$(BR2_EXTERNAL_jenkinsagent_PATH)/rootfs/overlay"
BR2_ROOTFS_POST_FAKEROOT_SCRIPT="$(BR2_EXTERNAL_jenkinsagent_PATH)/rootfs/post-fakeroot.sh"
BR2_ROOTFS_POST_IMAGE_SCRIPT="$(BR2_EXTERNAL_jenkinsagent_PATH)/rootfs/post-image.sh"
BR2_LINUX_KERNEL=y
BR2_LINUX_KERNEL_CUSTOM_TARBALL=y
BR2_LINUX_KERNEL_CUSTOM_TARBALL_LOCATION="$(call github,raspberrypi,linux,0b54dbda3cca2beb51e236a25738784e90853b64)/linux-0b54dbda3cca2beb51e236a25738784e90853b64.tar.gz"
BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y
BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="$(BR2_EXTERNAL_jenkinsagent_PATH)/rootfs/linux.config"
BR2_LINUX_KERNEL_DTS_SUPPORT=y
BR2_LINUX_KERNEL_INTREE_DTS_NAME="broadcom/bcm2711-rpi-4-b"
BR2_LINUX_KERNEL_NEEDS_HOST_OPENSSL=y
# BR2_PACKAGE_BUSYBOX is not set
BR2_PACKAGE_GIT=y
BR2_PACKAGE_XORG7=y
BR2_PACKAGE_RPI_FIRMWARE=y
BR2_PACKAGE_RPI_FIRMWARE_VARIANT_PI4=y
BR2_PACKAGE_RPI_FIRMWARE_CONFIG_FILE="$(BR2_EXTERNAL_jenkinsagent_PATH)/config.txt"
BR2_PACKAGE_OPENJDK=y
BR2_PACKAGE_LIBCURL=y
BR2_PACKAGE_LIBCURL_CURL=y
# BR2_PACKAGE_LIBCURL_EXTRA_PROTOCOLS_FEATURES is not set
BR2_PACKAGE_DHCPCD=y
# BR2_PACKAGE_IFUPDOWN_SCRIPTS is not set
BR2_PACKAGE_IPROUTE2=y
BR2_PACKAGE_OPENSSH=y
BR2_PACKAGE_COREUTILS=y
BR2_PACKAGE_COREUTILS_INDIVIDUAL_BINARIES=y
BR2_PACKAGE_DOCKER_CLI=y
BR2_PACKAGE_DOCKER_ENGINE=y
BR2_PACKAGE_HTOP=y
BR2_PACKAGE_PROCPS_NG=y
BR2_PACKAGE_PSMISC=y
BR2_PACKAGE_RSYSLOG=y
# BR2_PACKAGE_SYSTEMD_HWDB is not set
# BR2_PACKAGE_SYSTEMD_NETWORKD is not set
# BR2_PACKAGE_SYSTEMD_RESOLVED is not set
BR2_PACKAGE_UTIL_LINUX_LOGIN=y
BR2_TARGET_ROOTFS_SQUASHFS=y
BR2_TARGET_ROOTFS_SQUASHFS4_LZ4=y
# BR2_TARGET_ROOTFS_TAR is not set

View File

@ -0,0 +1,21 @@
BR2_aarch64=y
BR2_cortex_a72=y
BR2_ARM_FPU_VFPV4=y
BR2_TOOLCHAIN_BUILDROOT_MUSL=y
BR2_KERNEL_HEADERS_5_10=y
BR2_TOOLCHAIN_BUILDROOT_CXX=y
BR2_INIT_NONE=y
# BR2_TARGET_GENERIC_GETTY is not set
# BR2_TARGET_GENERIC_REMOUNT_ROOTFS_RW is not set
BR2_ROOTFS_OVERLAY="$(BR2_EXTERNAL_jenkinsagent_PATH)/initramfs/overlay"
BR2_PACKAGE_BUSYBOX_CONFIG="$(BR2_EXTERNAL_jenkinsagent_PATH)/initramfs/busybox.config"
BR2_PACKAGE_RPI_FIRMWARE=y
BR2_PACKAGE_RPI_FIRMWARE_VARIANT_PI4=y
BR2_PACKAGE_RPI_FIRMWARE_CONFIG_FILE="board/raspberrypi4-64/config_4_64bit.txt"
# BR2_PACKAGE_IFUPDOWN_SCRIPTS is not set
BR2_PACKAGE_NBD=y
BR2_TARGET_ROOTFS_CPIO=y
BR2_TARGET_ROOTFS_CPIO_LZ4=y
# BR2_TARGET_ROOTFS_TAR is not set
BR2_PACKAGE_HOST_KMOD=y
BR2_PACKAGE_HOST_UTIL_LINUX=y

2
external.desc Normal file
View File

@ -0,0 +1,2 @@
name: jenkinsagent
desc: Jenkins Worker Agent OS

0
external.mk Normal file
View File

1196
initramfs/busybox.config Normal file

File diff suppressed because it is too large Load Diff

40
initramfs/overlay/sbin/init Executable file
View File

@ -0,0 +1,40 @@
#!/bin/sh -e
export PATH=/usr/sbin:/usr/bin:/sbin:/bin
# shellcheck disable=SC2046
set -- $(cat /proc/cmdline)
while [ $# -ge 1 ]; do
case "$1" in
root=nbd:*)
arg=${1#*:}
name=${arg#*:}
host=${arg%:*}
;;
esac
shift
done
mkdir -p /proc /run /sys
mount -t sysfs sysfs /sys
mount -t proc proc /proc
mount -t tmpfs tmpfs /run
for path in /sys/class/net/*; do
[ -e "${path}" ] || continue
ip link set "${path##*/}" up
done
sleep 5
udhcpc -q
@bd-client -N "${name}" -R -p "${host}" /dev/nbd0
mkdir -p /sysroot
mount -o ro -t squashfs /dev/nbd0 /sysroot || nbd-client -c /dev/nbd0
cd /sysroot
mount --move /proc /sysroot/proc
mount --move /sys /sysroot/sys
mount --move /dev /sysroot/dev
mount --move /run /sysroot/run
exec switch_root /sysroot /lib/systemd/systemd

View File

@ -0,0 +1 @@
nbd-client

View File

@ -0,0 +1,33 @@
#!/bin/sh
case "$1" in
deconfig|nak)
;;
renew|bound)
if [ -n "${ip}" ]; then
# shellcheck disable=SC2154 # interface is is an environment variable
ip addr add "${ip}"/"${mask:-32}" dev "${interface}"
fi
if [ -n "${staticroutes}" ]; then
# shellcheck disable=SC2086 # we WANT word splitting here!
set -- ${staticroutes}
ip route add "$1" via "$2" dev "${interface}"
elif [ -n "${router}" ]; then
for gw in ${router}; do
ip route add default via "${gw}" dev "${interface}"
done
fi
: > /etc/resolv.conf
if [ -n "${search}" ]; then
printf 'search %s\n' "${search}" >> /etc/resolv.conf
elif [ -n "${domain}" ]; then
printf 'search %s\n' "${domain}" >> /etc/resolv.conf
fi
if [ -n "${dns}" ]; then
for ns in ${dns}; do
printf 'nameserver %s\n' "${ns}" >> /etc/resolv.conf
done
fi
;;
esac

1163
rootfs/linux.config Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,50 @@
# A sample configuration for dhcpcd.
# See dhcpcd.conf(5) for details.
# Allow users of this group to interact with dhcpcd via the control socket.
#controlgroup wheel
# Inform the DHCP server of our hostname for DDNS.
#hostname
# Use the hardware address of the interface for the Client ID.
clientid
# or
# Use the same DUID + IAID as set in DHCPv6 for DHCPv4 ClientID as per RFC4361.
# Some non-RFC compliant DHCP servers do not reply with this set.
# In this case, comment out duid and enable clientid above.
#duid
# Persist interface configuration when dhcpcd exits.
persistent
# vendorclassid is set to blank to avoid sending the default of
# dhcpcd-<version>:<os>:<machine>:<platform>
vendorclassid
# A list of options to request from the DHCP server.
option domain_name_servers, domain_name, domain_search
option classless_static_routes
# Respect the network MTU. This is applied to DHCP routes.
option interface_mtu
# Request a hostname from the network
option host_name
# Most distributions have NTP support.
#option ntp_servers
# Rapid commit support.
# Safe to enable by default because it requires the equivalent option set
# on the server to actually work.
option rapid_commit
# A ServerID is required by RFC2131.
require dhcp_server_identifier
# Generate SLAAC address using the Hardware Address of the interface
#slaac hwaddr
# OR generate Stable Private IPv6 Addresses based from the DUID
slaac private
denyinterfaces dummy*

View File

5
rootfs/overlay/etc/fstab Normal file
View File

@ -0,0 +1,5 @@
tmpfs /var tmpfs mode=0755,noexec,nosuid,nodev 0 0
tmpfs /root tmpfs size=1M,mode=550 0 0
/dev/mmcblk0 /run/storage ext4 ro,noexec,nosuid,nodev 0 2
overlay /etc/ssh overlay ro,lowerdir=/etc/ssh:/run/storage/ssh,noexec,nodev,nosuid,x-systemd.requires-mounts-for=/run/storage 0 0
/run/storage/docker/key.json /etc/docker/key.json none bind 0 0

View File

@ -0,0 +1,6 @@
global(workDirectory="/var/lib/rsyslog")
module(load="imjournal"
StateFile="imjournal.state")
include(file="/etc/rsyslog.d/*.conf" mode="optional")
include(file="/run/rsyslog.d/*.conf" mode="optional")

View File

@ -0,0 +1,9 @@
[Unit]
Description=Copy /var contents to writable storage
DefaultDependencies=no
After=var.mount
Before=local-fs.target
[Service]
Type=oneshot
ExecStart=/usr/libexec/copy-var.sh

View File

@ -0,0 +1,2 @@
[Unit]
Before=network-online.target

View File

@ -0,0 +1,2 @@
[Service]
PIDFile=/run/dhcpcd/pid

View File

@ -0,0 +1,9 @@
[Unit]
Description=Fetch SSH authorized_keys for %I
Wants=network-online.target
After=network-online.target
[Service]
Type=oneshot
ExecStart=/usr/libexec/fetch-sshkeys.sh
User=%I

View File

@ -0,0 +1,7 @@
[Unit]
Description=Generate rsyslog.conf
Before=rsyslog.service
[Service]
Type=oneshot
ExecStart=/usr/libexec/gen-rsyslog-conf.sh

View File

@ -0,0 +1,19 @@
[Unit]
Description=htop process viewer
Conflicts=gtty@tty1.service
[Service]
ExecStart=/usr/bin/htop --readonly
TTYPath=/dev/tty1
StandardInput=tty
StandardOutput=tty
StandardError=journal
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
#PrivateDevices=true
PrivateNetwork=true
ProtectKernelTunables=true
ProtectKernelModules=true
CapabilityBoundingSet=
NoNewPrivileges=true

View File

@ -0,0 +1 @@
../copy-var.service

View File

@ -0,0 +1 @@
../fetch-sshkeys@.service

View File

@ -0,0 +1 @@
../htop.service

View File

@ -0,0 +1 @@
../gen-rsyslog-conf.service

View File

@ -0,0 +1 @@
d /run/rsyslog.d 0755 root root -

View File

@ -0,0 +1,23 @@
#!/bin/sh
set -e
cleanup() {
if [ -n "${tmpdir}" ] && [ -d "${tmpdir}" ] && [ / != "${tmpdir}" ]; then
if mountpoint -q "${tmpdir}"; then
umount "${tmpdir}"
fi
rm -rf "${tmpdir}"
fi
unset tmpdir
}
tmpdir=$(TMPDIR=/run mktemp -d)
trap cleanup INT QUIT TERM EXIT
mount -o bind / "${tmpdir}"
cp -a "${tmpdir}"/var/. /var/
if [ -x "$(command -v selinuxenabled)" ] && selinuxenabled; then
restorecon -RF /var
fi

View File

@ -0,0 +1,29 @@
#!/bin/sh -e
umask 0077
mkdir -p ~/.ssh
: > ~/.ssh/authorized_keys
fetch_keys() {
curl -fsSL "${1}" >> ~/.ssh/authorized_keys
}
# shellcheck disable=SC2046
set -- $(cat /proc/cmdline)
while [ $# -ge 1 ]; do
case "$1" in
sshkeys.*=*)
arg=${1#*.}
user=${arg%=*}
url=${arg#*=}
if [ "${user}" = "${USER}" ]; then
fetch_keys "${url}"
fi
;;
esac
shift
done
if [ -x "$(command -v selinuxenabled)" ] && selinuxenabled; then
restorecon -RF ~/.ssh
fi

View File

@ -0,0 +1,12 @@
#!/bin/sh -e
# shellcheck disable=SC2046
set -- $(cat /proc/cmdline)
while [ $# -ge 1 ]; do
case "$1" in
rsyslog.dest=*)
printf '*.* @%s\n' "${1#*=}" >> /run/rsyslog.d/remote.conf
;;
esac
shift
done

9
rootfs/post-fakeroot.sh Executable file
View File

@ -0,0 +1,9 @@
#!/bin/sh
"${HOST_DIR}"/bin/systemctl --root="${TARGET_DIR}" disable \
cups-lpd.socket \
cups.service \
cups.socket \
systemd-networkd.service \
systemd-resolved.service \
--

5
rootfs/post-image.sh Executable file
View File

@ -0,0 +1,5 @@
#!/bin/sh
# shellcheck disable=SC2154
cp -v "${BR2_EXTERNAL_jenkinsagent_PATH}"/cmdline.txt \
"${BINARIES_DIR}"/rpi-firmware/cmdline.txt