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

<img width="2072" height="956" alt="image"
src="https://github.com/user-attachments/assets/ea1acf45-b746-4ffa-8043-be674b87bb60"
/>
This commit is contained in:
Meghan Denny
2025-10-27 12:11:00 -08:00
committed by GitHub
parent 64bfd8b938
commit f3ed784a6b
3 changed files with 31 additions and 7 deletions

View File

@@ -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, "")}`;

View File

@@ -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}`);
}