rootfs en js
This commit is contained in:
parent
08097035e4
commit
2599602d58
6 changed files with 174 additions and 57 deletions
|
@ -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
1
rootfs/.npmrc
Normal file
|
@ -0,0 +1 @@
|
||||||
|
@nulo:registry=https://gitea.nulo.in/api/packages/nulo/npm/
|
126
rootfs/build.js
Normal file
126
rootfs/build.js
Normal 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
20
rootfs/package.json
Normal 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
19
rootfs/pnpm-lock.yaml
Normal 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
8
rootfs/tsconfig.json
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"extends": "@tsconfig/node16/tsconfig.json",
|
||||||
|
"exclude": ["build.js/", "build/"],
|
||||||
|
"compilerOptions": {
|
||||||
|
"allowJs": true,
|
||||||
|
"checkJs": true
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue