From f3ed784a6b356b6552964f042ad532f81e95feda Mon Sep 17 00:00:00 2001 From: Meghan Denny Date: Mon, 27 Oct 2025 12:11:00 -0800 Subject: [PATCH] scripts: teach machine.mjs how to spawn a freebsd image on aws (#24109) exploratory look into https://github.com/oven-sh/bun/issues/1524 this still leaves that far off from being closed but an important first step this is important because this script is used to spawn our base images for CI and will provide boxes for local testing not sure how far i'll get but a rough "road to freebsd" map for anyone reading: - [x] this - [ ] ensure `bootstrap.sh` can run successfully - [ ] ensure WebKit can build from source - [ ] ensure other dependencies can build from source - [ ] add freebsd to our WebKit fork releases - [ ] add freebsd to our Zig fork releases - [ ] ensure bun can build from source - [ ] run `[build images]` and add freebsd to CI - [ ] fix runtime test failures image --- package.json | 1 + scripts/machine.mjs | 25 +++++++++++++++++++++++-- scripts/utils.mjs | 12 +++++++----- 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index c0fcee4b5f..b5d18cf725 100644 --- a/package.json +++ b/package.json @@ -89,6 +89,7 @@ "machine:linux:alpine": "./scripts/machine.mjs ssh --cloud=aws --arch=x64 --instance-type c7i.2xlarge --os=linux --distro=alpine --release=3.22", "machine:linux:amazonlinux": "./scripts/machine.mjs ssh --cloud=aws --arch=x64 --instance-type c7i.2xlarge --os=linux --distro=amazonlinux --release=2023", "machine:windows:2019": "./scripts/machine.mjs ssh --cloud=aws --arch=x64 --instance-type c7i.2xlarge --os=windows --release=2019", + "machine:freebsd": "./scripts/machine.mjs ssh --cloud=aws --arch=x64 --instance-type c7i.large --os=freebsd --release=14.3", "sync-webkit-source": "bun ./scripts/sync-webkit-source.ts" } } diff --git a/scripts/machine.mjs b/scripts/machine.mjs index 5ea5cdae66..5c7998aa80 100755 --- a/scripts/machine.mjs +++ b/scripts/machine.mjs @@ -389,6 +389,9 @@ const aws = { owner = "amazon"; name = `Windows_Server-${release || "*"}-English-Full-Base-*`; } + } else if (os === "freebsd") { + owner = "782442783595"; // upstream member of FreeBSD team, likely Colin Percival + name = `FreeBSD ${release}-STABLE-${{ "aarch64": "arm64", "x64": "amd64" }[arch] ?? "amd64"}-* UEFI-PREFERRED cloud-init UFS`; } if (!name) { @@ -400,6 +403,7 @@ const aws = { "owner-alias": owner, "name": name, }); + // console.table(baseImages.map(v => v.Name)); if (!baseImages.length) { throw new Error(`No base image found: ${inspect(options)}`); @@ -425,6 +429,8 @@ const aws = { } const { ImageId, Name, RootDeviceName, BlockDeviceMappings } = image; + // console.table({ os, arch, instanceType, Name, ImageId }); + const blockDeviceMappings = BlockDeviceMappings.map(device => { const { DeviceName } = device; if (DeviceName === RootDeviceName) { @@ -620,6 +626,7 @@ const aws = { * @property {SshKey[]} [sshKeys] * @property {string} [username] * @property {string} [password] + * @property {Os} [os] */ /** @@ -648,6 +655,7 @@ function getCloudInit(cloudInit) { const authorizedKeys = cloudInit["sshKeys"]?.map(({ publicKey }) => publicKey) || []; let sftpPath = "/usr/lib/openssh/sftp-server"; + let shell = "/bin/bash"; switch (cloudInit["distro"]) { case "alpine": sftpPath = "/usr/lib/ssh/sftp-server"; @@ -658,6 +666,18 @@ function getCloudInit(cloudInit) { sftpPath = "/usr/libexec/openssh/sftp-server"; break; } + switch (cloudInit["os"]) { + case "linux": + case "windows": + // handled above + break; + case "freebsd": + sftpPath = "/usr/libexec/openssh/sftp-server"; + shell = "/bin/csh"; + break; + default: + throw new Error(`Unsupported os: ${cloudInit["os"]}`); + } let users; if (username === "root") { @@ -671,7 +691,7 @@ function getCloudInit(cloudInit) { users: - name: ${username} sudo: ALL=(ALL) NOPASSWD:ALL - shell: /bin/bash + shell: ${shell} ssh_authorized_keys: ${authorizedKeys.map(key => ` - ${key}`).join("\n")} @@ -1050,7 +1070,7 @@ function getCloud(name) { } /** - * @typedef {"linux" | "darwin" | "windows"} Os + * @typedef {"linux" | "darwin" | "windows" | "freebsd"} Os * @typedef {"aarch64" | "x64"} Arch * @typedef {"macos" | "windowsserver" | "debian" | "ubuntu" | "alpine" | "amazonlinux"} Distro */ @@ -1204,6 +1224,7 @@ async function main() { }; let { detached, bootstrap, ci, os, arch, distro, release, features } = options; + if (os === "freebsd") bootstrap = false; let name = `${os}-${arch}-${(release || "").replace(/\./g, "")}`; diff --git a/scripts/utils.mjs b/scripts/utils.mjs index 604227f9cd..c9ad28be53 100755 --- a/scripts/utils.mjs +++ b/scripts/utils.mjs @@ -1538,7 +1538,7 @@ export function parseNumber(value) { /** * @param {string} string - * @returns {"darwin" | "linux" | "windows"} + * @returns {"darwin" | "linux" | "windows" | "freebsd"} */ export function parseOs(string) { if (/darwin|apple|mac/i.test(string)) { @@ -1550,6 +1550,9 @@ export function parseOs(string) { if (/win/i.test(string)) { return "windows"; } + if (/freebsd/i.test(string)) { + return "freebsd"; + } throw new Error(`Unsupported operating system: ${string}`); } @@ -1900,22 +1903,21 @@ export function getUsernameForDistro(distro) { if (/windows/i.test(distro)) { return "administrator"; } - if (/alpine|centos/i.test(distro)) { return "root"; } - if (/debian/i.test(distro)) { return "admin"; } - if (/ubuntu/i.test(distro)) { return "ubuntu"; } - if (/amazon|amzn|al\d+|rhel/i.test(distro)) { return "ec2-user"; } + if (/freebsd/i.test(distro)) { + return "root"; + } throw new Error(`Unsupported distro: ${distro}`); }