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