From 2599602d5847abb9e5d89d27b028ca6040aa6cfb Mon Sep 17 00:00:00 2001 From: Nulo Date: Wed, 31 May 2023 11:18:11 -0300 Subject: [PATCH] rootfs en js --- build-rootfs.sh | 57 ------------------- rootfs/.npmrc | 1 + rootfs/build.js | 126 ++++++++++++++++++++++++++++++++++++++++++ rootfs/package.json | 20 +++++++ rootfs/pnpm-lock.yaml | 19 +++++++ rootfs/tsconfig.json | 8 +++ 6 files changed, 174 insertions(+), 57 deletions(-) delete mode 100755 build-rootfs.sh create mode 100644 rootfs/.npmrc create mode 100644 rootfs/build.js create mode 100644 rootfs/package.json create mode 100644 rootfs/pnpm-lock.yaml create mode 100644 rootfs/tsconfig.json diff --git a/build-rootfs.sh b/build-rootfs.sh deleted file mode 100755 index a1ae6ba..0000000 --- a/build-rootfs.sh +++ /dev/null @@ -1,57 +0,0 @@ -#!/bin/sh -xe -# https://github.com/firecracker-microvm/firecracker/blob/main/docs/rootfs-and-kernel-setup.md - -dir="$(mktemp --tmpdir -d tmp.fireactions-rootfs.XXXXXXXXXX)" -podman run -it --rm -v "$dir:/rootfs:Z" docker.io/alpine:3.18 sh -c " -mkdir -p /rootfs/etc/apk -cp -r /etc/apk/keys /rootfs/etc/apk/ -echo https://dl-cdn.alpinelinux.org/alpine/v3.18/main >> /rootfs/etc/apk/repositories -echo https://dl-cdn.alpinelinux.org/alpine/v3.18/community >> /rootfs/etc/apk/repositories -apk add --initdb --root /rootfs alpine-base dropbear util-linux dropbear-dbclient dhcpcd -" - -# gotta go fast -echo 'rc_parallel="YES"' >> "$dir"/etc/rc.conf - -mkdir -p "$dir"/usr/local/sbin -go build -tags=netgo -o "$dir"/usr/local/sbin/fireactions-agent ./agent -# https://github.com/OpenRC/openrc/blob/master/service-script-guide.md -echo "#!/sbin/openrc-run -pidfile=\"/run/\${RC_SVCNAME}.pid\" -command_background=true -command=/usr/local/sbin/fireactions-agent" > "$dir"/etc/init.d/fireactions-agent -chmod +x "$dir"/etc/init.d/fireactions-agent -ln -s /etc/init.d/fireactions-agent "$dir"/etc/runlevels/default/ - -ln -s /etc/init.d/devfs "$dir"/etc/runlevels/boot/ -ln -s /etc/init.d/procfs "$dir"/etc/runlevels/boot/ -ln -s /etc/init.d/sysfs "$dir"/etc/runlevels/boot/ -ln -s /etc/init.d/networking "$dir"/etc/runlevels/default/ -# ln -s /etc/init.d/dhcpcd "$dir"/etc/runlevels/default/ -ln -s /etc/init.d/dropbear "$dir"/etc/runlevels/default/ - -echo ttyS0 > "$dir"/etc/securetty -ln -s agetty "$dir"/etc/init.d/agetty.ttyS0 -ln -s /etc/init.d/agetty.ttyS0 "$dir"/etc/runlevels/default/ -# ln -s /etc/init.d/local "$dir"/etc/runlevels/default/ - -mkdir -p "$dir"/etc/dropbear -for t in rsa dss ed25519 ecdsa; do - dropbearkey -t $t -f "$dir/etc/dropbear/dropbear_${t}_host_key" -done - -sudo mkdir -p "$dir"/root/.ssh -echo ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEhrcTPMrhrOdwpgFkRFjTt8rdxt3gg16LJvBCZENRWa user@personal | sudo tee "$dir"/root/.ssh/authorized_keys -echo "auto lo -iface lo inet loopback" > "$dir"/etc/network/interfaces - -rm rootfs.ext4 -fallocate --length 1G rootfs.ext4 -mkfs.ext4 rootfs.ext4 - -mkdir -p /tmp/rootfs -sudo mount rootfs.ext4 /tmp/rootfs -sudo cp -r "$dir"/* /tmp/rootfs/ -sudo umount /tmp/rootfs - -# sudo rm -rf "$dir" diff --git a/rootfs/.npmrc b/rootfs/.npmrc new file mode 100644 index 0000000..97c56e9 --- /dev/null +++ b/rootfs/.npmrc @@ -0,0 +1 @@ +@nulo:registry=https://gitea.nulo.in/api/packages/nulo/npm/ diff --git a/rootfs/build.js b/rootfs/build.js new file mode 100644 index 0000000..bbccf44 --- /dev/null +++ b/rootfs/build.js @@ -0,0 +1,126 @@ +import { init } from "@nulo/apkit"; +import { execFile as _execFile } from "node:child_process"; +import { + chmod, + mkdir, + mkdtemp, + readFile, + readdir, + rm, + symlink, + writeFile, +} from "node:fs/promises"; +import { tmpdir } from "node:os"; +import { join } from "node:path"; +import { promisify } from "node:util"; +const execFile = promisify(_execFile); + +const root = await mkdtemp(join(tmpdir(), "tmp.fireactions-rootfs.")); +const alpine = await init(root); +await alpine.install(["dropbear", "util-linux", "dropbear-dbclient", "dhcpcd"]); + +// gotta go fast +await append(r("/etc/rc.conf"), 'rc_parallel="YES"'); + +await mkdirp(r("/usr/local/sbin")); +await execFile("go", [ + "build", + "-tags=netgo", + "-o", + r("/usr/local/sbin/fireactions-agent"), + "./agent", +]); +// https://github.com/OpenRC/openrc/blob/master/service-script-guide.md +await writeFile( + r("/etc/init.d/fireactions-agent"), + `#!/sbin/openrc-run +pidfile="/run/\${RC_SVCNAME}.pid" +command_background=true +command=/usr/local/sbin/fireactions-agent` +); +await chmod(r("/etc/init.d/fireactions-agent"), 0o700); +await alpine.rcUpdate("default", "fireactions-agent"); + +await alpine.rcUpdate("boot", "devfs"); +await alpine.rcUpdate("boot", "procfs"); +await alpine.rcUpdate("boot", "sysfs"); +// alpine.rcUpdate('default', 'dhcpcd') +await alpine.rcUpdate("default", "dropbear"); + +await writeFile(r("/etc/securetty"), "ttyS0"); +await symlink("agetty", r("/etc/init.d/agetty.ttyS0")); +await alpine.rcUpdate("default", "agetty.ttyS0"); + +await mkdirp(r("/etc/dropbear")); +for (const t of ["rsa", "dss", "ed25519", "ecdsa"]) { + await execFile("dropbearkey", [ + "-t", + t, + "-f", + r(`/etc/dropbear/dropbear_${t}_host_key`), + ]); +} + +await execFile("sudo", ["mkdir", "-p", r("/root/.ssh")]); +await writeFile( + "authorized_keys", + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEhrcTPMrhrOdwpgFkRFjTt8rdxt3gg16LJvBCZENRWa user@personal" +); +await execFile("sudo", [ + "mv", + "authorized_keys", + r("/root/.ssh/authorized_keys"), +]); + +await alpine.rcUpdate("default", "networking"); +await writeFile( + r("/etc/network/interfaces"), + `auto lo +iface lo inet loopback` +); + +const ext4 = "rootfs.ext4"; +await rm(ext4); +await execFile("fallocate", ["--length", "1G", ext4]); +await execFile("mkfs.ext4", [ext4]); + +const mountpoint = await mkdtemp(join(tmpdir(), "tmp.fireactions-mountpoint.")); +try { + await mkdirp(mountpoint); + await execFile("sudo", ["mount", ext4, mountpoint]); + try { + for (const dir of await readdir(root)) { + await execFile("sudo", ["cp", "-r", r(dir), mountpoint]); + } + } finally { + await execFile("sudo", ["umount", mountpoint]); + } +} finally { + await rm(mountpoint, { recursive: true }); +} + +// # sudo rm -rf "$dir" + +// helpers +/** + * @param {import("node:fs").PathLike} path + * @param {string} content + * @returns {Promise} + */ +async function append(path, content) { + const file = await readFile(path, "utf-8"); + await writeFile(path, file + "\n" + content); +} +/** + * @param {import("node:fs").PathLike} path + * @returns {Promise} + */ +async function mkdirp(path) { + await mkdir(path, { recursive: true }); +} +/** + * @param {string} path + */ +function r(path) { + return join(root, path); +} diff --git a/rootfs/package.json b/rootfs/package.json new file mode 100644 index 0000000..a29052e --- /dev/null +++ b/rootfs/package.json @@ -0,0 +1,20 @@ +{ + "name": "fireactions-rootfs", + "type": "module", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "@nulo/apkit": "https://gitea.nulo.in/Nulo/apkit" + }, + "devDependencies": { + "@tsconfig/node16": "^1.0.4", + "@types/node": "^20.2.5" + } +} diff --git a/rootfs/pnpm-lock.yaml b/rootfs/pnpm-lock.yaml new file mode 100644 index 0000000..7e4ca0b --- /dev/null +++ b/rootfs/pnpm-lock.yaml @@ -0,0 +1,19 @@ +lockfileVersion: '6.0' + +devDependencies: + '@tsconfig/node16': + specifier: ^1.0.4 + version: 1.0.4 + '@types/node': + specifier: ^20.2.5 + version: 20.2.5 + +packages: + + /@tsconfig/node16@1.0.4: + resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} + dev: true + + /@types/node@20.2.5: + resolution: {integrity: sha512-JJulVEQXmiY9Px5axXHeYGLSjhkZEnD+MDPDGbCbIAbMslkKwmygtZFy1X6s/075Yo94sf8GuSlFfPzysQrWZQ==} + dev: true diff --git a/rootfs/tsconfig.json b/rootfs/tsconfig.json new file mode 100644 index 0000000..7105231 --- /dev/null +++ b/rootfs/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "@tsconfig/node16/tsconfig.json", + "exclude": ["build.js/", "build/"], + "compilerOptions": { + "allowJs": true, + "checkJs": true + } +}