rootfs en js

This commit is contained in:
Cat /dev/Nulo 2023-05-31 11:18:11 -03:00
parent 08097035e4
commit 2599602d58
6 changed files with 174 additions and 57 deletions

View file

@ -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"

1
rootfs/.npmrc Normal file
View file

@ -0,0 +1 @@
@nulo:registry=https://gitea.nulo.in/api/packages/nulo/npm/

126
rootfs/build.js Normal file
View file

@ -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<void>}
*/
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<void>}
*/
async function mkdirp(path) {
await mkdir(path, { recursive: true });
}
/**
* @param {string} path
*/
function r(path) {
return join(root, path);
}

20
rootfs/package.json Normal file
View file

@ -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"
}
}

19
rootfs/pnpm-lock.yaml Normal file
View file

@ -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

8
rootfs/tsconfig.json Normal file
View file

@ -0,0 +1,8 @@
{
"extends": "@tsconfig/node16/tsconfig.json",
"exclude": ["build.js/", "build/"],
"compilerOptions": {
"allowJs": true,
"checkJs": true
}
}