typescript-virtual-container 1.5.3 → 1.5.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +44 -532
- package/dist/.tsbuildinfo +1 -0
- package/dist/SSHMimic/executor.js +23 -5
- package/dist/VirtualPackageManager/index.js +10 -0
- package/dist/VirtualShell/shell.js +158 -11
- package/dist/commands/basename.d.ts +13 -0
- package/dist/commands/basename.js +45 -0
- package/dist/commands/bc.d.ts +2 -0
- package/dist/commands/bc.js +28 -0
- package/dist/commands/file.d.ts +8 -0
- package/dist/commands/file.js +57 -0
- package/dist/commands/fun.d.ts +32 -0
- package/dist/commands/fun.js +172 -0
- package/dist/commands/ip.d.ts +7 -0
- package/dist/commands/ip.js +52 -0
- package/dist/commands/jobs.d.ts +4 -0
- package/dist/commands/jobs.js +27 -0
- package/dist/commands/last.d.ts +13 -0
- package/dist/commands/last.js +68 -0
- package/dist/commands/manuals-bundle.js +598 -6
- package/dist/commands/registry.js +30 -2
- package/dist/commands/runtime.js +24 -3
- package/dist/commands/set.js +20 -0
- package/dist/commands/sh.js +74 -1
- package/dist/commands/tput.d.ts +13 -0
- package/dist/commands/tput.js +76 -0
- package/dist/commands/w.d.ts +7 -0
- package/dist/commands/w.js +38 -0
- package/dist/utils/expand.d.ts +12 -0
- package/dist/utils/expand.js +87 -1
- package/package.json +9 -3
- package/.github/ISSUE_TEMPLATE/bug_report.yml +0 -50
- package/.github/ISSUE_TEMPLATE/feature_request.yml +0 -31
- package/.github/dependabot.yml +0 -27
- package/.github/pull_request_template.md +0 -21
- package/.github/workflows/create-pull-request.yml +0 -85
- package/.github/workflows/publish.yml +0 -25
- package/.github/workflows/test-battery.yml +0 -102
- package/.vscode/settings.json +0 -20
- package/CODE_OF_CONDUCT.md +0 -39
- package/CONTRIBUTING.md +0 -59
- package/HONEYPOT.md +0 -358
- package/SECURITY.md +0 -33
- package/benchmark-results.txt +0 -40
- package/benchmark-virtualshell.ts +0 -88
- package/biome.json +0 -37
- package/build.js +0 -22
- package/builds/fortune-nyx-v1.5.3-directbash-k6.1.0.mjs +0 -1764
- package/builds/fortune-nyx-v1.5.3-ssh-nosftp.js +0 -1764
- package/builds/fortune-nyx-v1.5.3-ssh.cjs +0 -1765
- package/builds/fortune-nyx-v1.5.3-web.min.js +0 -17036
- package/bun.lock +0 -244
- package/docs/.nojekyll +0 -1
- package/docs/app.js +0 -1751
- package/docs/assets/hierarchy.js +0 -1
- package/docs/assets/highlight.css +0 -162
- package/docs/assets/icons.js +0 -18
- package/docs/assets/icons.svg +0 -1
- package/docs/assets/main.js +0 -60
- package/docs/assets/navigation.js +0 -1
- package/docs/assets/search.js +0 -1
- package/docs/assets/style.css +0 -1633
- package/docs/classes/HoneyPot.html +0 -31
- package/docs/classes/IdleManager.html +0 -162
- package/docs/classes/SshClient.html +0 -66
- package/docs/classes/VirtualFileSystem.html +0 -279
- package/docs/classes/VirtualPackageManager.html +0 -63
- package/docs/classes/VirtualSftpServer.html +0 -169
- package/docs/classes/VirtualShell.html +0 -285
- package/docs/classes/VirtualSshServer.html +0 -182
- package/docs/classes/VirtualUserManager.html +0 -276
- package/docs/demo.html +0 -82
- package/docs/functions/assertDiff.html +0 -6
- package/docs/functions/diffSnapshots.html +0 -7
- package/docs/functions/formatDiff.html +0 -6
- package/docs/functions/getArg.html +0 -13
- package/docs/functions/getFlag.html +0 -15
- package/docs/functions/ifFlag.html +0 -11
- package/docs/hierarchy.html +0 -1
- package/docs/index.html +0 -1869
- package/docs/interfaces/AuditLogEntry.html +0 -6
- package/docs/interfaces/CommandContext.html +0 -22
- package/docs/interfaces/CommandResult.html +0 -26
- package/docs/interfaces/ExecStream.html +0 -11
- package/docs/interfaces/HoneyPotStats.html +0 -16
- package/docs/interfaces/IdleManagerOptions.html +0 -7
- package/docs/interfaces/InstalledPackage.html +0 -20
- package/docs/interfaces/NanoEditorSession.html +0 -8
- package/docs/interfaces/PackageDefinition.html +0 -30
- package/docs/interfaces/PackageFile.html +0 -8
- package/docs/interfaces/PasswordChallenge.html +0 -16
- package/docs/interfaces/RemoveOptions.html +0 -4
- package/docs/interfaces/ShellEnv.html +0 -6
- package/docs/interfaces/ShellModule.html +0 -14
- package/docs/interfaces/ShellProperties.html +0 -14
- package/docs/interfaces/ShellStream.html +0 -11
- package/docs/interfaces/SudoChallenge.html +0 -24
- package/docs/interfaces/VfsBaseNode.html +0 -12
- package/docs/interfaces/VfsDiff.html +0 -10
- package/docs/interfaces/VfsDiffEntry.html +0 -6
- package/docs/interfaces/VfsDiffModified.html +0 -10
- package/docs/interfaces/VfsDirectoryNode.html +0 -15
- package/docs/interfaces/VfsFileNode.html +0 -17
- package/docs/interfaces/VfsOptions.html +0 -26
- package/docs/interfaces/VfsSnapshot.html +0 -3
- package/docs/interfaces/VfsSnapshotBaseNode.html +0 -8
- package/docs/interfaces/VfsSnapshotDirectoryNode.html +0 -10
- package/docs/interfaces/VfsSnapshotFileNode.html +0 -12
- package/docs/interfaces/VirtualActiveSession.html +0 -12
- package/docs/interfaces/VirtualSftpServerOptions.html +0 -7
- package/docs/interfaces/VirtualShellVfsLike.html +0 -15
- package/docs/interfaces/VirtualShellVfsOptions.html +0 -3
- package/docs/interfaces/WriteFileOptions.html +0 -6
- package/docs/media/LICENSE +0 -21
- package/docs/modules.html +0 -1
- package/docs/types/ArgParseOptions.html +0 -4
- package/docs/types/CommandMode.html +0 -2
- package/docs/types/CommandOutcome.html +0 -2
- package/docs/types/IdleState.html +0 -1
- package/docs/types/VfsNodeStats.html +0 -2
- package/docs/types/VfsNodeType.html +0 -2
- package/docs/types/VfsPersistenceMode.html +0 -5
- package/docs/types/VfsSnapshotNode.html +0 -2
- package/examples/README.md +0 -288
- package/examples/app.js +0 -1751
- package/examples/app.ts +0 -299
- package/examples/build.js +0 -27
- package/examples/demo.html +0 -33
- package/examples/honeypot-audit.ts +0 -180
- package/examples/honeypot-export.ts +0 -253
- package/examples/honeypot-quickstart.ts +0 -110
- package/examples/index.html +0 -82
- package/examples/server.js +0 -55
- package/polyfills/buffer.js +0 -117
- package/polyfills/node_child_process/index.js +0 -2
- package/polyfills/node_crypto/index.js +0 -167
- package/polyfills/node_events/index.js +0 -9
- package/polyfills/node_fs/index.js +0 -202
- package/polyfills/node_fs/promises.js +0 -4
- package/polyfills/node_os/index.js +0 -9
- package/polyfills/node_path/index.js +0 -28
- package/polyfills/node_vm/index.js +0 -7
- package/polyfills/node_zlib/index.js +0 -3
- package/polyfills/process.js +0 -14
- package/polyfills/ssh2/index.js +0 -75
- package/scripts/build-all.mjs +0 -226
- package/scripts/build-names.mjs +0 -43
- package/scripts/generate-manuals-bundle.mjs +0 -49
- package/scripts/postinstall.js +0 -42
- package/scripts/publish-package.sh +0 -70
- package/src/Honeypot/index.ts +0 -457
- package/src/SSHClient/index.ts +0 -270
- package/src/SSHMimic/exec.ts +0 -49
- package/src/SSHMimic/executor.ts +0 -251
- package/src/SSHMimic/hostKey.ts +0 -21
- package/src/SSHMimic/index.ts +0 -337
- package/src/SSHMimic/loginBanner.ts +0 -36
- package/src/SSHMimic/loginFormat.ts +0 -10
- package/src/SSHMimic/prompt.ts +0 -14
- package/src/SSHMimic/sftp.ts +0 -883
- package/src/VirtualFileSystem/binaryPack.ts +0 -258
- package/src/VirtualFileSystem/index.ts +0 -1193
- package/src/VirtualFileSystem/internalTypes.ts +0 -43
- package/src/VirtualFileSystem/journal.ts +0 -171
- package/src/VirtualFileSystem/path.ts +0 -74
- package/src/VirtualPackageManager/index.ts +0 -996
- package/src/VirtualShell/idleManager.ts +0 -137
- package/src/VirtualShell/index.ts +0 -475
- package/src/VirtualShell/shell.ts +0 -700
- package/src/VirtualShell/shellParser.ts +0 -285
- package/src/VirtualUserManager/index.ts +0 -758
- package/src/bun.d.ts +0 -1
- package/src/commands/adduser.ts +0 -103
- package/src/commands/alias.ts +0 -69
- package/src/commands/apt.ts +0 -233
- package/src/commands/awk.ts +0 -168
- package/src/commands/base64.ts +0 -29
- package/src/commands/cat.ts +0 -52
- package/src/commands/cd.ts +0 -25
- package/src/commands/chmod.ts +0 -85
- package/src/commands/clear.ts +0 -15
- package/src/commands/command-helpers.ts +0 -286
- package/src/commands/cp.ts +0 -83
- package/src/commands/curl.ts +0 -147
- package/src/commands/cut.ts +0 -36
- package/src/commands/date.ts +0 -30
- package/src/commands/declare.ts +0 -49
- package/src/commands/deluser.ts +0 -98
- package/src/commands/df.ts +0 -23
- package/src/commands/diff.ts +0 -43
- package/src/commands/dpkg.ts +0 -180
- package/src/commands/du.ts +0 -56
- package/src/commands/echo.ts +0 -58
- package/src/commands/env.ts +0 -23
- package/src/commands/exit.ts +0 -18
- package/src/commands/export.ts +0 -34
- package/src/commands/find.ts +0 -68
- package/src/commands/free.ts +0 -47
- package/src/commands/grep.ts +0 -116
- package/src/commands/groups.ts +0 -19
- package/src/commands/gzip.ts +0 -88
- package/src/commands/head.ts +0 -52
- package/src/commands/help.ts +0 -152
- package/src/commands/helpers.ts +0 -234
- package/src/commands/history.ts +0 -34
- package/src/commands/hostname.ts +0 -14
- package/src/commands/htop.ts +0 -20
- package/src/commands/id.ts +0 -19
- package/src/commands/index.ts +0 -9
- package/src/commands/kill.ts +0 -19
- package/src/commands/ln.ts +0 -71
- package/src/commands/ls.ts +0 -243
- package/src/commands/lsb-release.ts +0 -63
- package/src/commands/man.ts +0 -31
- package/src/commands/manuals/adduser.txt +0 -11
- package/src/commands/manuals/apt-cache.txt +0 -12
- package/src/commands/manuals/apt.txt +0 -20
- package/src/commands/manuals/awk.txt +0 -13
- package/src/commands/manuals/cat.txt +0 -14
- package/src/commands/manuals/cd.txt +0 -16
- package/src/commands/manuals/chmod.txt +0 -16
- package/src/commands/manuals/clear.txt +0 -10
- package/src/commands/manuals/cp.txt +0 -10
- package/src/commands/manuals/curl.txt +0 -20
- package/src/commands/manuals/date.txt +0 -14
- package/src/commands/manuals/declare.txt +0 -12
- package/src/commands/manuals/deluser.txt +0 -10
- package/src/commands/manuals/df.txt +0 -10
- package/src/commands/manuals/dpkg-query.txt +0 -11
- package/src/commands/manuals/dpkg.txt +0 -14
- package/src/commands/manuals/du.txt +0 -11
- package/src/commands/manuals/echo.txt +0 -11
- package/src/commands/manuals/false.txt +0 -10
- package/src/commands/manuals/find.txt +0 -11
- package/src/commands/manuals/free.txt +0 -12
- package/src/commands/manuals/grep.txt +0 -13
- package/src/commands/manuals/groups.txt +0 -10
- package/src/commands/manuals/gzip.txt +0 -11
- package/src/commands/manuals/head.txt +0 -10
- package/src/commands/manuals/help.txt +0 -11
- package/src/commands/manuals/history.txt +0 -11
- package/src/commands/manuals/hostname.txt +0 -10
- package/src/commands/manuals/id.txt +0 -10
- package/src/commands/manuals/kill.txt +0 -13
- package/src/commands/manuals/ls.txt +0 -20
- package/src/commands/manuals/lsb_release.txt +0 -14
- package/src/commands/manuals/mkdir.txt +0 -10
- package/src/commands/manuals/mv.txt +0 -10
- package/src/commands/manuals/nano.txt +0 -11
- package/src/commands/manuals/neofetch.txt +0 -10
- package/src/commands/manuals/node.txt +0 -13
- package/src/commands/manuals/npm.txt +0 -13
- package/src/commands/manuals/npx.txt +0 -13
- package/src/commands/manuals/passwd.txt +0 -11
- package/src/commands/manuals/ping.txt +0 -10
- package/src/commands/manuals/printf.txt +0 -11
- package/src/commands/manuals/ps.txt +0 -10
- package/src/commands/manuals/pwd.txt +0 -10
- package/src/commands/manuals/python3.txt +0 -13
- package/src/commands/manuals/readlink.txt +0 -10
- package/src/commands/manuals/return.txt +0 -10
- package/src/commands/manuals/rm.txt +0 -10
- package/src/commands/manuals/sed.txt +0 -11
- package/src/commands/manuals/set.txt +0 -11
- package/src/commands/manuals/shift.txt +0 -10
- package/src/commands/manuals/sleep.txt +0 -10
- package/src/commands/manuals/sort.txt +0 -12
- package/src/commands/manuals/source.txt +0 -11
- package/src/commands/manuals/ssh.txt +0 -11
- package/src/commands/manuals/stat.txt +0 -10
- package/src/commands/manuals/su.txt +0 -13
- package/src/commands/manuals/sudo.txt +0 -11
- package/src/commands/manuals/tail.txt +0 -10
- package/src/commands/manuals/tar.txt +0 -19
- package/src/commands/manuals/tee.txt +0 -10
- package/src/commands/manuals/test.txt +0 -11
- package/src/commands/manuals/touch.txt +0 -11
- package/src/commands/manuals/tr.txt +0 -10
- package/src/commands/manuals/trap.txt +0 -10
- package/src/commands/manuals/true.txt +0 -10
- package/src/commands/manuals/type.txt +0 -10
- package/src/commands/manuals/uname.txt +0 -12
- package/src/commands/manuals/uniq.txt +0 -12
- package/src/commands/manuals/unset.txt +0 -10
- package/src/commands/manuals/uptime.txt +0 -11
- package/src/commands/manuals/wc.txt +0 -12
- package/src/commands/manuals/wget.txt +0 -12
- package/src/commands/manuals/which.txt +0 -10
- package/src/commands/manuals/whoami.txt +0 -10
- package/src/commands/manuals/xargs.txt +0 -10
- package/src/commands/manuals-bundle.ts +0 -898
- package/src/commands/mkdir.ts +0 -31
- package/src/commands/mv.ts +0 -50
- package/src/commands/nano.ts +0 -38
- package/src/commands/neofetch.ts +0 -53
- package/src/commands/node.ts +0 -341
- package/src/commands/npm.ts +0 -132
- package/src/commands/passwd.ts +0 -50
- package/src/commands/ping.ts +0 -32
- package/src/commands/printf.ts +0 -129
- package/src/commands/ps.ts +0 -58
- package/src/commands/pwd.ts +0 -9
- package/src/commands/python.ts +0 -2229
- package/src/commands/read.ts +0 -46
- package/src/commands/registry.ts +0 -249
- package/src/commands/rm.ts +0 -42
- package/src/commands/runtime.ts +0 -421
- package/src/commands/sed.ts +0 -68
- package/src/commands/seq.ts +0 -43
- package/src/commands/set.ts +0 -29
- package/src/commands/sh.ts +0 -467
- package/src/commands/shift.ts +0 -63
- package/src/commands/sleep.ts +0 -20
- package/src/commands/sort.ts +0 -46
- package/src/commands/source.ts +0 -52
- package/src/commands/stat.ts +0 -61
- package/src/commands/su.ts +0 -72
- package/src/commands/sudo.ts +0 -76
- package/src/commands/tail.ts +0 -53
- package/src/commands/tar.ts +0 -102
- package/src/commands/tee.ts +0 -36
- package/src/commands/test.ts +0 -137
- package/src/commands/touch.ts +0 -28
- package/src/commands/tr.ts +0 -70
- package/src/commands/tree.ts +0 -20
- package/src/commands/true.ts +0 -27
- package/src/commands/type.ts +0 -48
- package/src/commands/uname.ts +0 -29
- package/src/commands/uniq.ts +0 -39
- package/src/commands/unset.ts +0 -17
- package/src/commands/uptime.ts +0 -54
- package/src/commands/wc.ts +0 -55
- package/src/commands/wget.ts +0 -148
- package/src/commands/which.ts +0 -37
- package/src/commands/who.ts +0 -25
- package/src/commands/whoami.ts +0 -14
- package/src/commands/xargs.ts +0 -31
- package/src/index.ts +0 -67
- package/src/modules/linuxRootfs.ts +0 -1961
- package/src/modules/neofetch.ts +0 -358
- package/src/modules/shellInteractive.ts +0 -57
- package/src/modules/shellRuntime.ts +0 -76
- package/src/self-standalone.ts +0 -542
- package/src/standalone-wo-sftp.ts +0 -38
- package/src/standalone.ts +0 -72
- package/src/types/commands.ts +0 -146
- package/src/types/pipeline.ts +0 -52
- package/src/types/streams.ts +0 -32
- package/src/types/tar-stream.d.ts +0 -38
- package/src/types/vfs.ts +0 -98
- package/src/utils/expand.ts +0 -491
- package/src/utils/perfLogger.ts +0 -72
- package/src/utils/tokenize.ts +0 -98
- package/src/utils/vfsDiff.ts +0 -275
- package/tests/command-helpers.test.ts +0 -116
- package/tests/commands-admin-net.test.ts +0 -441
- package/tests/commands-advanced.test.ts +0 -456
- package/tests/commands-core.test.ts +0 -562
- package/tests/commands-missing.test.ts +0 -570
- package/tests/commands-specific-units.test.ts +0 -327
- package/tests/commands-text-sys.test.ts +0 -445
- package/tests/expand.test.ts +0 -170
- package/tests/helpers.test.ts +0 -97
- package/tests/new-features.test.ts +0 -1036
- package/tests/parser-executor.test.ts +0 -37
- package/tests/sftp.test.ts +0 -323
- package/tests/ssh-exec.test.ts +0 -45
- package/tests/test-helper.ts +0 -79
- package/tests/users.test.ts +0 -86
- package/tsconfig.json +0 -49
- package/typedoc.json +0 -47
|
@@ -1,1961 +0,0 @@
|
|
|
1
|
-
/** biome-ignore-all lint/style/useNamingConvention: ENV VAR KEYS + system names */
|
|
2
|
-
/**
|
|
3
|
-
* linuxRootfs.ts
|
|
4
|
-
*
|
|
5
|
-
* Bootstraps a realistic Linux directory hierarchy in the VFS.
|
|
6
|
-
* Called once during VirtualShell initialization. Idempotent — skips
|
|
7
|
-
* paths that already exist so FS-mode snapshots survive restarts.
|
|
8
|
-
*
|
|
9
|
-
* Emulation fidelity: modelled after a Fortune GNU/Linux 1.0 (Nyx)
|
|
10
|
-
* container with Firecracker MicroVM kernel 6.x, virtio block devices
|
|
11
|
-
* (vda/vdb/vdc/vdd), cgroups v1 hierarchy, Node.js 22, Python 3.12,
|
|
12
|
-
* GCC 13, OpenJDK 21, and a Fortune-style package database.
|
|
13
|
-
*
|
|
14
|
-
* Public API:
|
|
15
|
-
* - bootstrapLinuxRootfs() one-shot boot (VirtualShell calls this)
|
|
16
|
-
* - refreshProc() refresh /proc/* (call on session changes)
|
|
17
|
-
* - syncEtcPasswd() sync /etc/passwd|group|shadow from UserManager
|
|
18
|
-
* - createLinuxRootfsEngine() engine with .boot() + .tick() for live loops
|
|
19
|
-
*/
|
|
20
|
-
|
|
21
|
-
import * as os from "node:os";
|
|
22
|
-
import VirtualFileSystem from "../VirtualFileSystem";
|
|
23
|
-
import { decodeVfs } from "../VirtualFileSystem/binaryPack";
|
|
24
|
-
import type { ShellProperties } from "../VirtualShell";
|
|
25
|
-
import type { VirtualActiveSession, VirtualUserManager } from "../VirtualUserManager";
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
// ─── helpers ────────────────────────────────────────────────────────────────
|
|
29
|
-
|
|
30
|
-
function ensureDir(vfs: VirtualFileSystem, path: string, mode = 0o755): void {
|
|
31
|
-
if (!vfs.exists(path)) vfs.mkdir(path, mode);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
function ensureFile(
|
|
35
|
-
vfs: VirtualFileSystem,
|
|
36
|
-
path: string,
|
|
37
|
-
content: string,
|
|
38
|
-
mode = 0o644,
|
|
39
|
-
): void {
|
|
40
|
-
vfs.writeStub(path, content, mode);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
function write(vfs: VirtualFileSystem, path: string, content: string): void {
|
|
44
|
-
vfs.writeFile(path, content);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/** FNV-1a 32-bit — deterministic seed from any string */
|
|
48
|
-
function fnv1a(str: string): number {
|
|
49
|
-
let h = 2166136261;
|
|
50
|
-
for (let i = 0; i < str.length; i++) {
|
|
51
|
-
h ^= str.charCodeAt(i);
|
|
52
|
-
h = Math.imul(h, 16777619);
|
|
53
|
-
}
|
|
54
|
-
return h >>> 0;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// ─── /etc ────────────────────────────────────────────────────────────────────
|
|
58
|
-
|
|
59
|
-
function bootstrapEtc(
|
|
60
|
-
vfs: VirtualFileSystem,
|
|
61
|
-
hostname: string,
|
|
62
|
-
props: ShellProperties,
|
|
63
|
-
): void {
|
|
64
|
-
ensureDir(vfs, "/etc");
|
|
65
|
-
|
|
66
|
-
// os-release — Fortune Nyx identity
|
|
67
|
-
ensureFile(
|
|
68
|
-
vfs,
|
|
69
|
-
"/etc/os-release",
|
|
70
|
-
`${[
|
|
71
|
-
`NAME="Fortune GNU/Linux"`,
|
|
72
|
-
`PRETTY_NAME="${props.os}"`,
|
|
73
|
-
`ID=fortune`,
|
|
74
|
-
`ID_LIKE=debian`,
|
|
75
|
-
`HOME_URL="https://github.com/itsrealfortune/typescript-virtual-container"`,
|
|
76
|
-
`VERSION_CODENAME=nyx`,
|
|
77
|
-
`VERSION_ID="24.04"`,
|
|
78
|
-
`FORTUNE_CODENAME=nyx`,
|
|
79
|
-
].join("\n")}\n`,
|
|
80
|
-
);
|
|
81
|
-
|
|
82
|
-
ensureFile(vfs, "/etc/debian_version", "nyx/stable\n");
|
|
83
|
-
ensureFile(vfs, "/etc/hostname", `${hostname}\n`);
|
|
84
|
-
ensureFile(
|
|
85
|
-
vfs,
|
|
86
|
-
"/etc/shells",
|
|
87
|
-
"/bin/sh\n/bin/bash\n/usr/bin/bash\n/bin/dash\n/usr/bin/dash\n",
|
|
88
|
-
);
|
|
89
|
-
ensureFile(
|
|
90
|
-
vfs,
|
|
91
|
-
"/etc/profile",
|
|
92
|
-
`${[
|
|
93
|
-
"export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
|
94
|
-
"export PS1='\\u@\\h:\\w\\$ '",
|
|
95
|
-
].join("\n")}\n`,
|
|
96
|
-
);
|
|
97
|
-
|
|
98
|
-
ensureFile(vfs, "/etc/issue", "Fortune GNU/Linux 24.04 LTS \\n \\l\n");
|
|
99
|
-
ensureFile(vfs, "/etc/issue.net", "Fortune GNU/Linux 24.04 LTS\n");
|
|
100
|
-
ensureFile(
|
|
101
|
-
vfs,
|
|
102
|
-
"/etc/motd",
|
|
103
|
-
["", `Welcome to ${props.os}`, `Kernel: ${props.kernel}`, ""].join("\n"),
|
|
104
|
-
);
|
|
105
|
-
ensureFile(vfs, "/etc/lsb-release",
|
|
106
|
-
`${[
|
|
107
|
-
"DISTRIB_ID=Fortune",
|
|
108
|
-
"DISTRIB_RELEASE=24.04",
|
|
109
|
-
"DISTRIB_CODENAME=nyx",
|
|
110
|
-
`DISTRIB_DESCRIPTION="${props.os}"`,
|
|
111
|
-
].join("\n")}\n`,
|
|
112
|
-
);
|
|
113
|
-
|
|
114
|
-
// APT — Fortune Nyx sources
|
|
115
|
-
ensureDir(vfs, "/etc/apt");
|
|
116
|
-
ensureDir(vfs, "/etc/apt/sources.list.d");
|
|
117
|
-
ensureDir(vfs, "/etc/apt/trusted.gpg.d");
|
|
118
|
-
ensureDir(vfs, "/etc/apt/keyrings");
|
|
119
|
-
ensureFile(
|
|
120
|
-
vfs,
|
|
121
|
-
"/etc/apt/sources.list",
|
|
122
|
-
`${[
|
|
123
|
-
"# Fortune GNU/Linux package sources (Fortune 1.0 Nyx)",
|
|
124
|
-
"deb [virtual] fortune://packages.fortune.local nyx main contrib non-free",
|
|
125
|
-
"deb [virtual] fortune://packages.fortune.local nyx-updates main contrib non-free",
|
|
126
|
-
"deb [virtual] fortune://security.fortune.local nyx-security main",
|
|
127
|
-
].join("\n")}\n`,
|
|
128
|
-
);
|
|
129
|
-
ensureFile(vfs, "/etc/apt/apt.conf.d/70debconf", `// debconf config\n`);
|
|
130
|
-
|
|
131
|
-
// network
|
|
132
|
-
ensureDir(vfs, "/etc/network");
|
|
133
|
-
ensureFile(
|
|
134
|
-
vfs,
|
|
135
|
-
"/etc/network/interfaces",
|
|
136
|
-
`${[
|
|
137
|
-
"auto lo",
|
|
138
|
-
"iface lo inet loopback",
|
|
139
|
-
"",
|
|
140
|
-
"auto eth0",
|
|
141
|
-
"iface eth0 inet dhcp",
|
|
142
|
-
].join("\n")}\n`,
|
|
143
|
-
);
|
|
144
|
-
ensureDir(vfs, "/etc/netplan");
|
|
145
|
-
ensureFile(
|
|
146
|
-
vfs,
|
|
147
|
-
"/etc/netplan/01-eth0.yaml",
|
|
148
|
-
`${[
|
|
149
|
-
"network:",
|
|
150
|
-
" version: 2",
|
|
151
|
-
" ethernets:",
|
|
152
|
-
" eth0:",
|
|
153
|
-
" dhcp4: true",
|
|
154
|
-
].join("\n")}\n`,
|
|
155
|
-
);
|
|
156
|
-
|
|
157
|
-
ensureFile(vfs, "/etc/resolv.conf", "nameserver 1.1.1.1\nnameserver 8.8.8.8\n");
|
|
158
|
-
|
|
159
|
-
ensureFile(
|
|
160
|
-
vfs,
|
|
161
|
-
"/etc/hosts",
|
|
162
|
-
`${[
|
|
163
|
-
"127.0.0.1 localhost",
|
|
164
|
-
`127.0.1.1 ${hostname}`,
|
|
165
|
-
"::1 localhost ip6-localhost ip6-loopback",
|
|
166
|
-
"fe00::0 ip6-localnet",
|
|
167
|
-
"ff00::0 ip6-mcastprefix",
|
|
168
|
-
"ff02::1 ip6-allnodes",
|
|
169
|
-
"ff02::2 ip6-allrouters",
|
|
170
|
-
].join("\n")}\n`,
|
|
171
|
-
);
|
|
172
|
-
|
|
173
|
-
ensureFile(vfs, "/etc/nsswitch.conf",
|
|
174
|
-
`${[
|
|
175
|
-
"passwd: files systemd",
|
|
176
|
-
"group: files systemd",
|
|
177
|
-
"shadow: files",
|
|
178
|
-
"hosts: files dns",
|
|
179
|
-
"networks: files",
|
|
180
|
-
"protocols: db files",
|
|
181
|
-
"services: db files",
|
|
182
|
-
"ethers: db files",
|
|
183
|
-
"rpc: db files",
|
|
184
|
-
].join("\n")}\n`,
|
|
185
|
-
);
|
|
186
|
-
|
|
187
|
-
ensureDir(vfs, "/etc/cron.d");
|
|
188
|
-
ensureDir(vfs, "/etc/cron.daily");
|
|
189
|
-
ensureDir(vfs, "/etc/cron.hourly");
|
|
190
|
-
ensureDir(vfs, "/etc/cron.weekly");
|
|
191
|
-
ensureDir(vfs, "/etc/cron.monthly");
|
|
192
|
-
ensureDir(vfs, "/etc/init.d");
|
|
193
|
-
ensureDir(vfs, "/etc/systemd");
|
|
194
|
-
ensureDir(vfs, "/etc/systemd/system");
|
|
195
|
-
ensureDir(vfs, "/etc/systemd/system/multi-user.target.wants");
|
|
196
|
-
ensureDir(vfs, "/etc/systemd/network");
|
|
197
|
-
ensureFile(vfs, "/etc/systemd/system.conf",
|
|
198
|
-
"[Manager]\nDefaultTimeoutStartSec=90s\nDefaultTimeoutStopSec=90s\n",
|
|
199
|
-
);
|
|
200
|
-
|
|
201
|
-
// fstab — virtio block devices matching Firecracker layout
|
|
202
|
-
ensureFile(
|
|
203
|
-
vfs,
|
|
204
|
-
"/etc/fstab",
|
|
205
|
-
`${[
|
|
206
|
-
"# <file system> <mount point> <type> <options> <dump> <pass>",
|
|
207
|
-
"/dev/vda / ext4 rw,relatime,resuid=65534,resgid=65534 0 1",
|
|
208
|
-
"/dev/vdb /opt/rclone squashfs ro,relatime,errors=continue 0 0",
|
|
209
|
-
"tmpfs /tmp tmpfs defaults,noatime 0 0",
|
|
210
|
-
"tmpfs /run tmpfs defaults,noatime 0 0",
|
|
211
|
-
"tmpfs /dev/shm tmpfs rw,relatime 0 0",
|
|
212
|
-
].join("\n")}\n`,
|
|
213
|
-
);
|
|
214
|
-
|
|
215
|
-
// login.defs
|
|
216
|
-
ensureFile(
|
|
217
|
-
vfs,
|
|
218
|
-
"/etc/login.defs",
|
|
219
|
-
`${[
|
|
220
|
-
"MAIL_DIR /var/mail",
|
|
221
|
-
"PASS_MAX_DAYS 99999",
|
|
222
|
-
"PASS_MIN_DAYS 0",
|
|
223
|
-
"PASS_WARN_AGE 7",
|
|
224
|
-
"UID_MIN 1000",
|
|
225
|
-
"UID_MAX 60000",
|
|
226
|
-
"GID_MIN 1000",
|
|
227
|
-
"GID_MAX 60000",
|
|
228
|
-
"CREATE_HOME yes",
|
|
229
|
-
"UMASK 022",
|
|
230
|
-
"USERGROUPS_ENAB yes",
|
|
231
|
-
"ENCRYPT_METHOD SHA512",
|
|
232
|
-
].join("\n")}\n`,
|
|
233
|
-
);
|
|
234
|
-
|
|
235
|
-
// security + pam
|
|
236
|
-
ensureDir(vfs, "/etc/security");
|
|
237
|
-
ensureFile(vfs, "/etc/security/limits.conf",
|
|
238
|
-
"# /etc/security/limits.conf\n* soft nofile 1024\n* hard nofile 65536\n",
|
|
239
|
-
);
|
|
240
|
-
ensureFile(vfs, "/etc/security/access.conf", "# /etc/security/access.conf\n");
|
|
241
|
-
|
|
242
|
-
ensureDir(vfs, "/etc/pam.d");
|
|
243
|
-
ensureFile(vfs, "/etc/pam.d/common-auth",
|
|
244
|
-
"auth [success=1 default=ignore] pam_unix.so nullok\nauth requisite pam_deny.so\nauth required pam_permit.so\n",
|
|
245
|
-
);
|
|
246
|
-
ensureFile(vfs, "/etc/pam.d/common-account",
|
|
247
|
-
"account [success=1 new_authtok_reqd=done default=ignore] pam_unix.so\naccount requisite pam_deny.so\naccount required pam_permit.so\n",
|
|
248
|
-
);
|
|
249
|
-
ensureFile(vfs, "/etc/pam.d/common-password",
|
|
250
|
-
"password [success=1 default=ignore] pam_unix.so obscure sha512\npassword requisite pam_deny.so\npassword required pam_permit.so\n",
|
|
251
|
-
);
|
|
252
|
-
ensureFile(vfs, "/etc/pam.d/common-session",
|
|
253
|
-
"session [default=1] pam_permit.so\nsession requisite pam_deny.so\nsession required pam_permit.so\nsession optional pam_umask.so\nsession required pam_unix.so\n",
|
|
254
|
-
);
|
|
255
|
-
ensureFile(vfs, "/etc/pam.d/sshd",
|
|
256
|
-
"@include common-auth\n@include common-account\n@include common-session\n",
|
|
257
|
-
);
|
|
258
|
-
ensureFile(vfs, "/etc/pam.d/login",
|
|
259
|
-
"@include common-auth\n@include common-account\n@include common-session\n",
|
|
260
|
-
);
|
|
261
|
-
ensureFile(vfs, "/etc/pam.d/sudo",
|
|
262
|
-
"@include common-auth\n@include common-account\n@include common-session\n",
|
|
263
|
-
);
|
|
264
|
-
|
|
265
|
-
// sudo
|
|
266
|
-
ensureDir(vfs, "/etc/sudoers.d");
|
|
267
|
-
ensureFile(vfs, "/etc/sudoers",
|
|
268
|
-
"Defaults\tenv_reset\nDefaults\tmail_badpass\nDefaults\tsecure_path=\"/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"\nroot ALL=(ALL:ALL) ALL\n%sudo ALL=(ALL:ALL) ALL\n",
|
|
269
|
-
0o440,
|
|
270
|
-
);
|
|
271
|
-
ensureFile(vfs, "/etc/sudoers.d/README",
|
|
272
|
-
"# Files in this directory are parsed by sudo, if the file is not a backup.\n",
|
|
273
|
-
0o440,
|
|
274
|
-
);
|
|
275
|
-
|
|
276
|
-
// ld
|
|
277
|
-
ensureFile(vfs, "/etc/ld.so.conf", "include /etc/ld.so.conf.d/*.conf\n");
|
|
278
|
-
ensureDir(vfs, "/etc/ld.so.conf.d");
|
|
279
|
-
ensureFile(vfs, "/etc/ld.so.conf.d/x86_64-linux-gnu.conf",
|
|
280
|
-
"/lib/x86_64-linux-gnu\n/usr/lib/x86_64-linux-gnu\n",
|
|
281
|
-
);
|
|
282
|
-
ensureFile(vfs, "/etc/ld.so.conf.d/fakeroot.conf",
|
|
283
|
-
"/usr/lib/x86_64-linux-gnu/libfakeroot\n",
|
|
284
|
-
);
|
|
285
|
-
|
|
286
|
-
// locale + timezone
|
|
287
|
-
ensureFile(vfs, "/etc/locale.conf", "LANG=en_US.UTF-8\n");
|
|
288
|
-
ensureFile(vfs, "/etc/locale.gen", "en_US.UTF-8 UTF-8\n");
|
|
289
|
-
ensureFile(vfs, "/etc/default/locale", "LANG=en_US.UTF-8\n");
|
|
290
|
-
ensureFile(vfs, "/etc/timezone", "UTC\n");
|
|
291
|
-
ensureFile(vfs, "/etc/localtime", "UTC\n");
|
|
292
|
-
|
|
293
|
-
// environment
|
|
294
|
-
ensureFile(vfs, "/etc/environment",
|
|
295
|
-
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\n",
|
|
296
|
-
);
|
|
297
|
-
|
|
298
|
-
// adduser.conf
|
|
299
|
-
ensureFile(vfs, "/etc/adduser.conf",
|
|
300
|
-
`${[
|
|
301
|
-
"DSHELL=/bin/bash",
|
|
302
|
-
"DHOME=/home",
|
|
303
|
-
"GROUPHOMES=no",
|
|
304
|
-
"LETTERHOMES=no",
|
|
305
|
-
"SKEL=/etc/skel",
|
|
306
|
-
"FIRST_SYSTEM_UID=100",
|
|
307
|
-
"LAST_SYSTEM_UID=999",
|
|
308
|
-
"FIRST_SYSTEM_GID=100",
|
|
309
|
-
"LAST_SYSTEM_GID=999",
|
|
310
|
-
"FIRST_UID=1000",
|
|
311
|
-
"LAST_UID=59999",
|
|
312
|
-
"FIRST_GID=1000",
|
|
313
|
-
"LAST_GID=59999",
|
|
314
|
-
"USERGROUPS=yes",
|
|
315
|
-
"NAME_REGEX=\"^[a-z][-a-z0-9_]*$\"",
|
|
316
|
-
"SYS_NAME_REGEX=\"^[a-z_][-a-z0-9_]*$\"",
|
|
317
|
-
].join("\n")}\n`,
|
|
318
|
-
);
|
|
319
|
-
|
|
320
|
-
// /etc/skel
|
|
321
|
-
ensureDir(vfs, "/etc/skel");
|
|
322
|
-
ensureFile(vfs, "/etc/skel/.bashrc",
|
|
323
|
-
`${[
|
|
324
|
-
"# ~/.bashrc: executed by bash(1) for non-login shells.",
|
|
325
|
-
"case $- in",
|
|
326
|
-
" *i*) ;;",
|
|
327
|
-
" *) return;;",
|
|
328
|
-
"esac",
|
|
329
|
-
"HISTCONTROL=ignoreboth",
|
|
330
|
-
"HISTSIZE=1000",
|
|
331
|
-
"HISTFILESIZE=2000",
|
|
332
|
-
"shopt -s histappend",
|
|
333
|
-
"shopt -s checkwinsize",
|
|
334
|
-
"alias ll='ls -alF'",
|
|
335
|
-
"alias la='ls -A'",
|
|
336
|
-
"alias l='ls -CF'",
|
|
337
|
-
].join("\n")}\n`,
|
|
338
|
-
);
|
|
339
|
-
ensureFile(vfs, "/etc/skel/.bash_logout", "# ~/.bash_logout\n");
|
|
340
|
-
ensureFile(vfs, "/etc/skel/.profile",
|
|
341
|
-
"# ~/.profile\n[ -n \"$BASH_VERSION\" ] && [ -f \"$HOME/.bashrc\" ] && . \"$HOME/.bashrc\"\n",
|
|
342
|
-
);
|
|
343
|
-
|
|
344
|
-
// alternatives
|
|
345
|
-
ensureDir(vfs, "/etc/alternatives");
|
|
346
|
-
const alternatives: [string, string][] = [
|
|
347
|
-
["python3", "/usr/bin/python3.12"],
|
|
348
|
-
["python", "/usr/bin/python3.12"],
|
|
349
|
-
["editor", "/usr/bin/nano"],
|
|
350
|
-
["vi", "/usr/bin/nano"],
|
|
351
|
-
["cc", "/usr/bin/gcc"],
|
|
352
|
-
["gcc", "/usr/bin/gcc-13"],
|
|
353
|
-
["g++", "/usr/bin/g++-13"],
|
|
354
|
-
["java", "/usr/lib/jvm/java-21-openjdk-amd64/bin/java"],
|
|
355
|
-
["node", "/usr/bin/node"],
|
|
356
|
-
["npm", "/usr/bin/npm"],
|
|
357
|
-
["awk", "/usr/bin/mawk"],
|
|
358
|
-
["pager", "/usr/bin/less"],
|
|
359
|
-
];
|
|
360
|
-
for (const [name, target] of alternatives) {
|
|
361
|
-
ensureFile(vfs, `/etc/alternatives/${name}`, target);
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
// java
|
|
365
|
-
ensureDir(vfs, "/etc/java-21-openjdk");
|
|
366
|
-
ensureDir(vfs, "/etc/java-21-openjdk/security");
|
|
367
|
-
ensureFile(vfs, "/etc/java-21-openjdk/security/java.security", "# java.security\n");
|
|
368
|
-
ensureFile(vfs, "/etc/java-21-openjdk/logging.properties", "# logging.properties\n");
|
|
369
|
-
|
|
370
|
-
// misc
|
|
371
|
-
ensureFile(vfs, "/etc/bash.bashrc",
|
|
372
|
-
"# System-wide .bashrc\n[ -z \"$PS1\" ] && return\n",
|
|
373
|
-
);
|
|
374
|
-
ensureFile(vfs, "/etc/inputrc",
|
|
375
|
-
"# /etc/inputrc\n$include /etc/inputrc.d\nset bell-style none\n",
|
|
376
|
-
);
|
|
377
|
-
ensureFile(vfs, "/etc/magic", "# magic\n");
|
|
378
|
-
ensureFile(vfs, "/etc/magic.mime", "# magic.mime\n");
|
|
379
|
-
ensureFile(vfs, "/etc/papersize", "a4\n");
|
|
380
|
-
ensureFile(vfs, "/etc/ucf.conf", "# ucf.conf\n");
|
|
381
|
-
ensureFile(vfs, "/etc/gai.conf",
|
|
382
|
-
"# getaddrinfo() configuration\nlabel ::1/128 0\nprecedence ::1/128 50\n",
|
|
383
|
-
);
|
|
384
|
-
ensureFile(vfs, "/etc/services",
|
|
385
|
-
"# Network services\nftp 21/tcp\nssh 22/tcp\nsmtp 25/tcp\nhttp 80/tcp\nhttps 443/tcp\n",
|
|
386
|
-
);
|
|
387
|
-
ensureFile(vfs, "/etc/protocols",
|
|
388
|
-
"# protocols\nip 0 IP\nicmp 1 ICMP\ntcp 6 TCP\nudp 17 UDP\n",
|
|
389
|
-
);
|
|
390
|
-
|
|
391
|
-
ensureDir(vfs, "/etc/profile.d");
|
|
392
|
-
ensureFile(vfs, "/etc/profile.d/01-locale-fix.sh",
|
|
393
|
-
"[ -z \"$LANG\" ] && export LANG=en_US.UTF-8\n",
|
|
394
|
-
);
|
|
395
|
-
ensureFile(vfs, "/etc/profile.d/apps-bin-path.sh",
|
|
396
|
-
"export PATH=\"$PATH:/snap/bin\"\n",
|
|
397
|
-
);
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
// ─── /etc/passwd + /etc/group + /etc/shadow ─────────────────────────────────
|
|
401
|
-
|
|
402
|
-
/**
|
|
403
|
-
* Sync `/etc/passwd`, `/etc/group`, and `/etc/shadow` from the
|
|
404
|
-
* VirtualUserManager's current user list into the VFS.
|
|
405
|
-
*/
|
|
406
|
-
export function syncEtcPasswd(
|
|
407
|
-
vfs: VirtualFileSystem,
|
|
408
|
-
users: VirtualUserManager,
|
|
409
|
-
): void {
|
|
410
|
-
const userList = users.listUsers();
|
|
411
|
-
|
|
412
|
-
const passwdLines = [
|
|
413
|
-
"root:x:0:0:root:/root:/bin/bash",
|
|
414
|
-
"daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin",
|
|
415
|
-
"bin:x:2:2:bin:/bin:/usr/sbin/nologin",
|
|
416
|
-
"sys:x:3:3:sys:/dev:/usr/sbin/nologin",
|
|
417
|
-
"sync:x:4:65534:sync:/bin:/bin/sync",
|
|
418
|
-
"games:x:5:60:games:/usr/games:/usr/sbin/nologin",
|
|
419
|
-
"man:x:6:12:man:/var/cache/man:/usr/sbin/nologin",
|
|
420
|
-
"lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin",
|
|
421
|
-
"mail:x:8:8:mail:/var/mail:/usr/sbin/nologin",
|
|
422
|
-
"news:x:9:9:news:/var/spool/news:/usr/sbin/nologin",
|
|
423
|
-
"uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin",
|
|
424
|
-
"proxy:x:13:13:proxy:/bin:/usr/sbin/nologin",
|
|
425
|
-
"www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin",
|
|
426
|
-
"backup:x:34:34:backup:/var/backups:/usr/sbin/nologin",
|
|
427
|
-
"list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin",
|
|
428
|
-
"irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin",
|
|
429
|
-
"_apt:x:42:65534::/nonexistent:/usr/sbin/nologin",
|
|
430
|
-
"nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin",
|
|
431
|
-
"messagebus:x:100:106::/nonexistent:/usr/sbin/nologin",
|
|
432
|
-
"systemd-network:x:998:998:systemd Network Management:/:/usr/sbin/nologin",
|
|
433
|
-
"systemd-resolve:x:999:999:systemd Resolver:/:/usr/sbin/nologin",
|
|
434
|
-
"polkitd:x:997:997:polkit:/nonexistent:/usr/sbin/nologin",
|
|
435
|
-
];
|
|
436
|
-
|
|
437
|
-
let uid = 1000;
|
|
438
|
-
for (const u of userList) {
|
|
439
|
-
if (u === "root") continue;
|
|
440
|
-
passwdLines.push(`${u}:x:${uid}:${uid}::/home/${u}:/bin/bash`);
|
|
441
|
-
uid++;
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
vfs.writeFile("/etc/passwd", `${passwdLines.join("\n")}\n`);
|
|
445
|
-
|
|
446
|
-
const sudoers = userList.filter((u) => users.isSudoer(u)).join(",");
|
|
447
|
-
const nonRootUsers = userList.filter((u) => u !== "root").join(",");
|
|
448
|
-
|
|
449
|
-
const groupLines = [
|
|
450
|
-
"root:x:0:",
|
|
451
|
-
"daemon:x:1:",
|
|
452
|
-
"bin:x:2:",
|
|
453
|
-
"sys:x:3:",
|
|
454
|
-
"adm:x:4:syslog",
|
|
455
|
-
"tty:x:5:",
|
|
456
|
-
"disk:x:6:",
|
|
457
|
-
"lp:x:7:",
|
|
458
|
-
"mail:x:8:",
|
|
459
|
-
"news:x:9:",
|
|
460
|
-
"uucp:x:10:",
|
|
461
|
-
"man:x:12:",
|
|
462
|
-
"proxy:x:13:",
|
|
463
|
-
"kmem:x:15:",
|
|
464
|
-
"dialout:x:20:",
|
|
465
|
-
"fax:x:21:",
|
|
466
|
-
"voice:x:22:",
|
|
467
|
-
"cdrom:x:24:",
|
|
468
|
-
"floppy:x:25:",
|
|
469
|
-
"tape:x:26:",
|
|
470
|
-
`sudo:x:27:${sudoers}`,
|
|
471
|
-
"audio:x:29:",
|
|
472
|
-
"dip:x:30:",
|
|
473
|
-
"www-data:x:33:",
|
|
474
|
-
"backup:x:34:",
|
|
475
|
-
"operator:x:37:",
|
|
476
|
-
"list:x:38:",
|
|
477
|
-
"irc:x:39:",
|
|
478
|
-
"src:x:40:",
|
|
479
|
-
"_apt:x:42:",
|
|
480
|
-
"shadow:x:42:",
|
|
481
|
-
"utmp:x:43:",
|
|
482
|
-
"video:x:44:",
|
|
483
|
-
"sasl:x:45:",
|
|
484
|
-
"plugdev:x:46:",
|
|
485
|
-
"staff:x:50:",
|
|
486
|
-
"games:x:60:",
|
|
487
|
-
`users:x:100:${nonRootUsers}`,
|
|
488
|
-
"nogroup:x:65534:",
|
|
489
|
-
"messagebus:x:106:",
|
|
490
|
-
"systemd-network:x:998:",
|
|
491
|
-
"systemd-resolve:x:999:",
|
|
492
|
-
"polkitd:x:997:",
|
|
493
|
-
];
|
|
494
|
-
vfs.writeFile("/etc/group", `${groupLines.join("\n")}\n`);
|
|
495
|
-
|
|
496
|
-
const shadowLines = [
|
|
497
|
-
"root:*:19000:0:99999:7:::",
|
|
498
|
-
"daemon:*:19000:0:99999:7:::",
|
|
499
|
-
"nobody:*:19000:0:99999:7:::",
|
|
500
|
-
"messagebus:*:19000:0:99999:7:::",
|
|
501
|
-
"_apt:*:19000:0:99999:7:::",
|
|
502
|
-
"systemd-network:!:19000:::::::",
|
|
503
|
-
"systemd-resolve:!:19000:::::::",
|
|
504
|
-
"polkitd:!:19000:::::::",
|
|
505
|
-
];
|
|
506
|
-
for (const u of userList) {
|
|
507
|
-
if (u === "root") continue;
|
|
508
|
-
shadowLines.push(`${u}:!:19000:0:99999:7:::`);
|
|
509
|
-
}
|
|
510
|
-
vfs.writeFile("/etc/shadow", `${shadowLines.join("\n")}\n`, { mode: 0o640 });
|
|
511
|
-
}
|
|
512
|
-
|
|
513
|
-
// ─── /proc helpers ───────────────────────────────────────────────────────────
|
|
514
|
-
|
|
515
|
-
function ttyToPid(tty: string): number {
|
|
516
|
-
const match = tty.match(/(\d+)$/);
|
|
517
|
-
return 1000 + (match?.[1] ? parseInt(match[1], 10) : 0);
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
function writeProcPid(
|
|
521
|
-
vfs: VirtualFileSystem,
|
|
522
|
-
pid: number,
|
|
523
|
-
username: string,
|
|
524
|
-
_tty: string,
|
|
525
|
-
cmdline: string,
|
|
526
|
-
startedAt: string,
|
|
527
|
-
env: Record<string, string>,
|
|
528
|
-
): void {
|
|
529
|
-
const dir = `/proc/${pid}`;
|
|
530
|
-
ensureDir(vfs, dir);
|
|
531
|
-
ensureDir(vfs, `${dir}/fd`);
|
|
532
|
-
ensureDir(vfs, `${dir}/fdinfo`);
|
|
533
|
-
ensureDir(vfs, `${dir}/net`);
|
|
534
|
-
|
|
535
|
-
const uptimeSec = Math.floor((Date.now() - new Date(startedAt).getTime()) / 1000);
|
|
536
|
-
const comm = cmdline.split(/\s+/)[0] ?? "bash";
|
|
537
|
-
|
|
538
|
-
write(vfs, `${dir}/cmdline`, `${cmdline.replace(/\s+/g, "\0")}\0`);
|
|
539
|
-
write(vfs, `${dir}/comm`, comm);
|
|
540
|
-
write(
|
|
541
|
-
vfs,
|
|
542
|
-
`${dir}/status`,
|
|
543
|
-
`${[
|
|
544
|
-
`Name: ${comm}`,
|
|
545
|
-
`Umask: 0022`,
|
|
546
|
-
`State: S (sleeping)`,
|
|
547
|
-
`Tgid: ${pid}`,
|
|
548
|
-
`Pid: ${pid}`,
|
|
549
|
-
`PPid: 1`,
|
|
550
|
-
`TracerPid: 0`,
|
|
551
|
-
`Uid: 0\t0\t0\t0`,
|
|
552
|
-
`Gid: 0\t0\t0\t0`,
|
|
553
|
-
`FDSize: 64`,
|
|
554
|
-
`Groups:`,
|
|
555
|
-
`VmPeak: 20480 kB`,
|
|
556
|
-
`VmSize: 16384 kB`,
|
|
557
|
-
`VmLck: 0 kB`,
|
|
558
|
-
`VmPin: 0 kB`,
|
|
559
|
-
`VmHWM: 4096 kB`,
|
|
560
|
-
`VmRSS: 4096 kB`,
|
|
561
|
-
`RssAnon: 512 kB`,
|
|
562
|
-
`RssFile: 3584 kB`,
|
|
563
|
-
`RssShmem: 0 kB`,
|
|
564
|
-
`VmData: 2048 kB`,
|
|
565
|
-
`VmStk: 132 kB`,
|
|
566
|
-
`VmExe: 924 kB`,
|
|
567
|
-
`VmLib: 2744 kB`,
|
|
568
|
-
`VmPTE: 52 kB`,
|
|
569
|
-
`VmSwap: 0 kB`,
|
|
570
|
-
`Threads: 1`,
|
|
571
|
-
`SigQ: 0/31968`,
|
|
572
|
-
`SigPnd: 0000000000000000`,
|
|
573
|
-
`SigBlk: 0000000000010000`,
|
|
574
|
-
`SigIgn: 0000000000380004`,
|
|
575
|
-
`SigCgt: 000000004b817efb`,
|
|
576
|
-
`CapInh: 0000000000000000`,
|
|
577
|
-
`CapPrm: 000001ffffffffff`,
|
|
578
|
-
`CapEff: 000001ffffffffff`,
|
|
579
|
-
`CapBnd: 000001ffffffffff`,
|
|
580
|
-
`CapAmb: 0000000000000000`,
|
|
581
|
-
`NoNewPrivs: 0`,
|
|
582
|
-
`Seccomp: 0`,
|
|
583
|
-
`voluntary_ctxt_switches: 100`,
|
|
584
|
-
`nonvoluntary_ctxt_switches: 10`,
|
|
585
|
-
].join("\n")}\n`,
|
|
586
|
-
);
|
|
587
|
-
write(
|
|
588
|
-
vfs,
|
|
589
|
-
`${dir}/stat`,
|
|
590
|
-
`${pid} (${comm}) S 1 ${pid} ${pid} 0 -1 4194304 0 0 0 0 ${uptimeSec} 0 0 0 20 0 1 0 0 16777216 4096 18446744073709551615 93824992235520 93824992290000 140737488347024 0 0 0 65536 3686404 1266761467 1 0 0 17 0 0 0 0 0 0\n`,
|
|
591
|
-
);
|
|
592
|
-
write(
|
|
593
|
-
vfs,
|
|
594
|
-
`${dir}/statm`,
|
|
595
|
-
`4096 1024 768 231 0 512 0\n`,
|
|
596
|
-
);
|
|
597
|
-
write(
|
|
598
|
-
vfs,
|
|
599
|
-
`${dir}/environ`,
|
|
600
|
-
`${Object.entries(env).map(([k, v]) => `${k}=${v}`).join("\0")}\0`,
|
|
601
|
-
);
|
|
602
|
-
write(vfs, `${dir}/cwd`, `/home/${username}\0`);
|
|
603
|
-
write(vfs, `${dir}/exe`, "/bin/bash\0");
|
|
604
|
-
write(vfs, `${dir}/maps`,
|
|
605
|
-
"00400000-004e7000 r-xp 00000000 fd:00 131073 /bin/bash\n" +
|
|
606
|
-
"006e7000-006e8000 r--p 000e7000 fd:00 131073 /bin/bash\n" +
|
|
607
|
-
"006e8000-006f1000 rw-p 000e8000 fd:00 131073 /bin/bash\n" +
|
|
608
|
-
"7fff00000000-7fff00001000 rw-p 00000000 00:00 0 [stack]\n" +
|
|
609
|
-
"7fff00000000-7fff00001000 r-xp 00000000 00:00 0 [vdso]\n",
|
|
610
|
-
);
|
|
611
|
-
write(vfs, `${dir}/limits`,
|
|
612
|
-
`${[
|
|
613
|
-
"Limit Soft Limit Hard Limit Units",
|
|
614
|
-
"Max cpu time unlimited unlimited seconds",
|
|
615
|
-
"Max file size unlimited unlimited bytes",
|
|
616
|
-
"Max data size unlimited unlimited bytes",
|
|
617
|
-
"Max stack size 8388608 unlimited bytes",
|
|
618
|
-
"Max core file size 0 unlimited bytes",
|
|
619
|
-
"Max resident set unlimited unlimited bytes",
|
|
620
|
-
"Max processes 31968 31968 processes",
|
|
621
|
-
"Max open files 1048576 1048576 files",
|
|
622
|
-
"Max locked memory 8388608 8388608 bytes",
|
|
623
|
-
"Max address space unlimited unlimited bytes",
|
|
624
|
-
"Max file locks unlimited unlimited locks",
|
|
625
|
-
"Max pending signals 31968 31968 signals",
|
|
626
|
-
"Max msgqueue size 819200 819200 bytes",
|
|
627
|
-
"Max nice priority 0 0",
|
|
628
|
-
"Max realtime priority 0 0",
|
|
629
|
-
"Max realtime timeout unlimited unlimited us",
|
|
630
|
-
].join("\n")}\n`,
|
|
631
|
-
);
|
|
632
|
-
write(vfs, `${dir}/io`,
|
|
633
|
-
"rchar: 1048576\nwchar: 65536\nsyscr: 512\nsyscw: 64\nread_bytes: 0\nwrite_bytes: 0\ncancelled_write_bytes: 0\n",
|
|
634
|
-
);
|
|
635
|
-
write(vfs, `${dir}/oom_score`, "0\n");
|
|
636
|
-
write(vfs, `${dir}/oom_score_adj`, "0\n");
|
|
637
|
-
write(vfs, `${dir}/loginuid`, "0\n");
|
|
638
|
-
write(vfs, `${dir}/wchan`, "poll_schedule_timeout\n");
|
|
639
|
-
write(vfs, `${dir}/schedstat`, "1000000 0 1\n");
|
|
640
|
-
|
|
641
|
-
for (const fd of ["0", "1", "2"]) {
|
|
642
|
-
ensureFile(vfs, `${dir}/fd/${fd}`, "");
|
|
643
|
-
ensureFile(vfs, `${dir}/fdinfo/${fd}`,
|
|
644
|
-
`pos:\t0\nflags:\t0${fd === "0" ? "2" : fd === "1" ? "1" : "1"}02\nmnt_id:\t13\n`,
|
|
645
|
-
);
|
|
646
|
-
}
|
|
647
|
-
}
|
|
648
|
-
|
|
649
|
-
// ─── /proc boot log ──────────────────────────────────────────────────────────
|
|
650
|
-
|
|
651
|
-
function bootProcLog(vfs: VirtualFileSystem, props: ShellProperties): void {
|
|
652
|
-
ensureDir(vfs, "/proc/boot");
|
|
653
|
-
ensureFile(
|
|
654
|
-
vfs,
|
|
655
|
-
"/proc/boot/log",
|
|
656
|
-
`${[
|
|
657
|
-
`[ 0.000000] Linux version ${props.kernel} (fortune@build) #1 SMP PREEMPT_DYNAMIC`,
|
|
658
|
-
"[ 0.000000] Command line: console=ttyS0 reboot=k panic=1 nomodule random.trust_cpu=1 ipv6.disable=1",
|
|
659
|
-
"[ 0.000060] BIOS-provided physical RAM map:",
|
|
660
|
-
"[ 0.000070] ACPI: RSDP 0x00000000000F05B0 000014 (v00 BOCHS )",
|
|
661
|
-
"[ 0.000120] PCI: Using configuration type 1 for base access",
|
|
662
|
-
"[ 0.000240] clocksource: tsc-early: mask: 0xffffffffffffffff",
|
|
663
|
-
"[ 0.000320] ACPI: IRQ0 used by override",
|
|
664
|
-
"[ 0.000420] Initializing cgroup subsys cpuset",
|
|
665
|
-
"[ 0.000440] Initializing cgroup subsys cpu",
|
|
666
|
-
"[ 0.000450] Initializing cgroup subsys cpuacct",
|
|
667
|
-
"[ 0.000460] Linux agpgart interface v0.103",
|
|
668
|
-
"[ 0.000480] PCI: pci_cache_line_size set to 64 bytes",
|
|
669
|
-
"[ 0.000510] virtio-pci 0000:00:01.0: runtime IRQs not yet assigned",
|
|
670
|
-
"[ 0.000680] NET: Registered PF_INET6 protocol family",
|
|
671
|
-
"[ 0.000720] Freeing unused kernel image (initmem) memory",
|
|
672
|
-
"[ 0.000760] Write protecting the kernel read-only data",
|
|
673
|
-
"[ 0.000800] Run /sbin/init as init process",
|
|
674
|
-
"[ 0.001200] systemd[1]: Detected virtualization kvm",
|
|
675
|
-
"[ 0.001300] systemd[1]: Detected architecture x86-64",
|
|
676
|
-
"[ 0.002000] systemd[1]: Starting Fortune GNU/Linux...",
|
|
677
|
-
"[ 0.003000] systemd[1]: Started Journal Service",
|
|
678
|
-
"[ 0.010000] EXT4-fs (vda): mounted filesystem",
|
|
679
|
-
"[ 0.020000] systemd[1]: Reached target Basic System",
|
|
680
|
-
"[ 0.030000] systemd[1]: Started Login Service",
|
|
681
|
-
].join("\n")}\n`,
|
|
682
|
-
);
|
|
683
|
-
ensureFile(vfs, "/proc/boot/version", `Linux ${props.kernel} (virtual)\n`);
|
|
684
|
-
}
|
|
685
|
-
|
|
686
|
-
// ─── /proc refresh ───────────────────────────────────────────────────────────
|
|
687
|
-
|
|
688
|
-
/**
|
|
689
|
-
* Populate and refresh `/proc` virtual entries based on host stats and
|
|
690
|
-
* provided active sessions. Rewrites uptime, meminfo, cpuinfo, loadavg,
|
|
691
|
-
* per-pid entries, and /proc/self.
|
|
692
|
-
*
|
|
693
|
-
* Safe to call repeatedly — acts as a live kernel state snapshot.
|
|
694
|
-
*/
|
|
695
|
-
export function refreshProc(
|
|
696
|
-
vfs: VirtualFileSystem,
|
|
697
|
-
props: ShellProperties,
|
|
698
|
-
hostname: string,
|
|
699
|
-
shellStartTime: number,
|
|
700
|
-
sessions: VirtualActiveSession[] = [],
|
|
701
|
-
): void {
|
|
702
|
-
ensureDir(vfs, "/proc");
|
|
703
|
-
|
|
704
|
-
const uptimeSec = Math.floor((Date.now() - shellStartTime) / 1000);
|
|
705
|
-
const idleSec = Math.floor(uptimeSec * 0.9);
|
|
706
|
-
write(vfs, "/proc/uptime", `${uptimeSec}.00 ${idleSec}.00\n`);
|
|
707
|
-
|
|
708
|
-
// meminfo — real host values, Linux-compatible format
|
|
709
|
-
const totalMemKb = Math.floor(os.totalmem() / 1024);
|
|
710
|
-
const freeMemKb = Math.floor(os.freemem() / 1024);
|
|
711
|
-
const availMemKb = Math.floor(freeMemKb * 0.95);
|
|
712
|
-
const buffersKb = Math.floor(totalMemKb * 0.03);
|
|
713
|
-
const cachedKb = Math.floor(totalMemKb * 0.08);
|
|
714
|
-
const shmemKb = Math.floor(totalMemKb * 0.005);
|
|
715
|
-
const slabKb = Math.floor(totalMemKb * 0.02);
|
|
716
|
-
const pageTablesKb = Math.floor(totalMemKb * 0.001);
|
|
717
|
-
write(
|
|
718
|
-
vfs,
|
|
719
|
-
"/proc/meminfo",
|
|
720
|
-
`${[
|
|
721
|
-
`MemTotal: ${String(totalMemKb).padStart(10)} kB`,
|
|
722
|
-
`MemFree: ${String(freeMemKb).padStart(10)} kB`,
|
|
723
|
-
`MemAvailable: ${String(availMemKb).padStart(10)} kB`,
|
|
724
|
-
`Buffers: ${String(buffersKb).padStart(10)} kB`,
|
|
725
|
-
`Cached: ${String(cachedKb).padStart(10)} kB`,
|
|
726
|
-
`SwapCached: ${String(0).padStart(10)} kB`,
|
|
727
|
-
`Active: ${String(Math.floor((buffersKb + cachedKb) * 1.2)).padStart(10)} kB`,
|
|
728
|
-
`Inactive: ${String(Math.floor(cachedKb * 0.6)).padStart(10)} kB`,
|
|
729
|
-
`Active(anon): ${String(Math.floor(totalMemKb * 0.001)).padStart(10)} kB`,
|
|
730
|
-
`Inactive(anon): ${String(Math.floor(totalMemKb * 0.006)).padStart(10)} kB`,
|
|
731
|
-
`Active(file): ${String(Math.floor(cachedKb * 1.2)).padStart(10)} kB`,
|
|
732
|
-
`Inactive(file): ${String(Math.floor(cachedKb * 0.6)).padStart(10)} kB`,
|
|
733
|
-
`Unevictable: ${String(0).padStart(10)} kB`,
|
|
734
|
-
`Mlocked: ${String(0).padStart(10)} kB`,
|
|
735
|
-
`SwapTotal: ${String(0).padStart(10)} kB`,
|
|
736
|
-
`SwapFree: ${String(0).padStart(10)} kB`,
|
|
737
|
-
`Zswap: ${String(0).padStart(10)} kB`,
|
|
738
|
-
`Zswapped: ${String(0).padStart(10)} kB`,
|
|
739
|
-
`Dirty: ${String(Math.floor(Math.random() * 64)).padStart(10)} kB`,
|
|
740
|
-
`Writeback: ${String(0).padStart(10)} kB`,
|
|
741
|
-
`AnonPages: ${String(Math.floor(totalMemKb * 0.001)).padStart(10)} kB`,
|
|
742
|
-
`Mapped: ${String(Math.floor(cachedKb * 0.4)).padStart(10)} kB`,
|
|
743
|
-
`Shmem: ${String(shmemKb).padStart(10)} kB`,
|
|
744
|
-
`KReclaimable: ${String(Math.floor(slabKb * 0.6)).padStart(10)} kB`,
|
|
745
|
-
`Slab: ${String(slabKb).padStart(10)} kB`,
|
|
746
|
-
`SReclaimable: ${String(Math.floor(slabKb * 0.6)).padStart(10)} kB`,
|
|
747
|
-
`SUnreclaim: ${String(Math.floor(slabKb * 0.4)).padStart(10)} kB`,
|
|
748
|
-
`KernelStack: ${String(Math.floor(totalMemKb * 0.0005)).padStart(10)} kB`,
|
|
749
|
-
`PageTables: ${String(pageTablesKb).padStart(10)} kB`,
|
|
750
|
-
`NFS_Unstable: ${String(0).padStart(10)} kB`,
|
|
751
|
-
`Bounce: ${String(0).padStart(10)} kB`,
|
|
752
|
-
`WritebackTmp: ${String(0).padStart(10)} kB`,
|
|
753
|
-
`CommitLimit: ${String(Math.floor(totalMemKb * 0.5)).padStart(10)} kB`,
|
|
754
|
-
`Committed_AS: ${String(Math.floor(totalMemKb * 0.05)).padStart(10)} kB`,
|
|
755
|
-
`VmallocTotal: ${String(35184372087808 / 1024).padStart(10)} kB`,
|
|
756
|
-
`VmallocUsed: ${String(Math.floor(totalMemKb * 0.01)).padStart(10)} kB`,
|
|
757
|
-
`VmallocChunk: ${String(0).padStart(10)} kB`,
|
|
758
|
-
`Percpu: ${String(Math.floor(totalMemKb * 0.0001)).padStart(10)} kB`,
|
|
759
|
-
`HardwareCorrupted: ${String(0).padStart(6)} kB`,
|
|
760
|
-
`AnonHugePages: ${String(0).padStart(10)} kB`,
|
|
761
|
-
`ShmemHugePages: ${String(0).padStart(10)} kB`,
|
|
762
|
-
`ShmemPmdMapped: ${String(0).padStart(10)} kB`,
|
|
763
|
-
`FileHugePages: ${String(0).padStart(10)} kB`,
|
|
764
|
-
`FilePmdMapped: ${String(0).padStart(10)} kB`,
|
|
765
|
-
`HugePages_Total: ${String(0).padStart(8)}`,
|
|
766
|
-
`HugePages_Free: ${String(0).padStart(8)}`,
|
|
767
|
-
`HugePages_Rsvd: ${String(0).padStart(8)}`,
|
|
768
|
-
`HugePages_Surp: ${String(0).padStart(8)}`,
|
|
769
|
-
`Hugepagesize: ${String(2048).padStart(10)} kB`,
|
|
770
|
-
`Hugetlb: ${String(0).padStart(10)} kB`,
|
|
771
|
-
`DirectMap4k: ${String(Math.floor(totalMemKb * 0.02)).padStart(10)} kB`,
|
|
772
|
-
`DirectMap2M: ${String(Math.floor(totalMemKb * 0.98)).padStart(10)} kB`,
|
|
773
|
-
].join("\n")}\n`,
|
|
774
|
-
);
|
|
775
|
-
|
|
776
|
-
// cpuinfo — real host CPU passthrough + x86 feature flags matching Firecracker Xeon
|
|
777
|
-
const cpus = os.cpus();
|
|
778
|
-
const cpuLines: string[] = [];
|
|
779
|
-
for (let i = 0; i < cpus.length; i++) {
|
|
780
|
-
const c = cpus[i];
|
|
781
|
-
if (!c) continue;
|
|
782
|
-
cpuLines.push(
|
|
783
|
-
`processor\t: ${i}`,
|
|
784
|
-
`vendor_id\t: GenuineIntel`,
|
|
785
|
-
`cpu family\t: 6`,
|
|
786
|
-
`model\t\t: 85`,
|
|
787
|
-
`model name\t: ${c.model}`,
|
|
788
|
-
`stepping\t: 7`,
|
|
789
|
-
`microcode\t: 0x1`,
|
|
790
|
-
`cpu MHz\t\t: ${c.speed.toFixed(3)}`,
|
|
791
|
-
`cache size\t: 33792 KB`,
|
|
792
|
-
`physical id\t: 0`,
|
|
793
|
-
`siblings\t: ${cpus.length}`,
|
|
794
|
-
`core id\t\t: ${i}`,
|
|
795
|
-
`cpu cores\t: ${cpus.length}`,
|
|
796
|
-
`apicid\t\t: ${i}`,
|
|
797
|
-
`initial apicid\t: ${i}`,
|
|
798
|
-
`fpu\t\t: yes`,
|
|
799
|
-
`fpu_exception\t: yes`,
|
|
800
|
-
`cpuid level\t: 13`,
|
|
801
|
-
`wp\t\t: yes`,
|
|
802
|
-
`flags\t\t: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology nonstop_tsc cpuid tsc_known_freq pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch cpuid_fault ssbd ibrs ibpb stibp ibrs_enhanced fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm avx512f avx512dq rdseed adx smap clflushopt clwb avx512cd avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves arat umip avx512_vnni md_clear arch_capabilities`,
|
|
803
|
-
`bugs\t\t: spectre_v1 spectre_v2 spec_store_bypass swapgs taa mmio_stale_data retbleed eibrs_pbrsb bhi ibpb_no_ret spectre_v2_user its`,
|
|
804
|
-
`bogomips\t: ${(c.speed * 2 / 1000).toFixed(2)}`,
|
|
805
|
-
`clflush size\t: 64`,
|
|
806
|
-
`cache_alignment\t: 64`,
|
|
807
|
-
`address sizes\t: 46 bits physical, 48 bits virtual`,
|
|
808
|
-
`power management:`,
|
|
809
|
-
"",
|
|
810
|
-
);
|
|
811
|
-
}
|
|
812
|
-
write(vfs, "/proc/cpuinfo", `${cpuLines.join("\n")}\n`);
|
|
813
|
-
|
|
814
|
-
write(
|
|
815
|
-
vfs,
|
|
816
|
-
"/proc/version",
|
|
817
|
-
`Linux version ${props.kernel} (fortune@nyx-build) (gcc (Fortune 13.3.0-nyx1) 13.3.0, GNU ld (GNU Binutils for Fortune) 2.42) #2 SMP PREEMPT_DYNAMIC\n`,
|
|
818
|
-
);
|
|
819
|
-
write(vfs, "/proc/hostname", `${hostname}\n`);
|
|
820
|
-
|
|
821
|
-
// loadavg
|
|
822
|
-
const load = (Math.random() * 0.3).toFixed(2);
|
|
823
|
-
const numProcs = 1 + sessions.length;
|
|
824
|
-
write(vfs, "/proc/loadavg", `${load} ${load} ${load} ${numProcs}/${numProcs} 1\n`);
|
|
825
|
-
|
|
826
|
-
// /proc/cmdline — Firecracker boot args
|
|
827
|
-
write(vfs, "/proc/cmdline",
|
|
828
|
-
`console=ttyS0 reboot=k panic=1 nomodule random.trust_cpu=1 ipv6.disable=1 swiotlb=noforce rdinit=/process_api init_on_free=1 -- --firecracker-init --addr 0.0.0.0:2024 --max-ws-buffer-size 32768 --block-local-connections\n`,
|
|
829
|
-
);
|
|
830
|
-
|
|
831
|
-
// /proc/filesystems — matching real container
|
|
832
|
-
write(vfs, "/proc/filesystems",
|
|
833
|
-
`${[
|
|
834
|
-
"nodev\tsysfs",
|
|
835
|
-
"nodev\ttmpfs",
|
|
836
|
-
"nodev\tbdev",
|
|
837
|
-
"nodev\tproc",
|
|
838
|
-
"nodev\tcgroup",
|
|
839
|
-
"nodev\tcgroup2",
|
|
840
|
-
"nodev\tcpuset",
|
|
841
|
-
"nodev\tdevtmpfs",
|
|
842
|
-
"nodev\tbinfmt_misc",
|
|
843
|
-
"nodev\tdebugfs",
|
|
844
|
-
"nodev\tsecurityfs",
|
|
845
|
-
"nodev\tsockfs",
|
|
846
|
-
"nodev\tbpf",
|
|
847
|
-
"nodev\tpipefs",
|
|
848
|
-
"nodev\tramfs",
|
|
849
|
-
"nodev\thugetlbfs",
|
|
850
|
-
"nodev\trpc_pipefs",
|
|
851
|
-
"nodev\tdevpts",
|
|
852
|
-
"\text3",
|
|
853
|
-
"\text2",
|
|
854
|
-
"\text4",
|
|
855
|
-
"\tsquashfs",
|
|
856
|
-
"nodev\tnfs",
|
|
857
|
-
"nodev\tnfs4",
|
|
858
|
-
"nodev\tautofs",
|
|
859
|
-
"\tfuseblk",
|
|
860
|
-
"nodev\tfuse",
|
|
861
|
-
"nodev\tfusectl",
|
|
862
|
-
"nodev\toverlay",
|
|
863
|
-
"\txfs",
|
|
864
|
-
"nodev\tmqueue",
|
|
865
|
-
"nodev\tselinuxfs",
|
|
866
|
-
"nodev\tpstore",
|
|
867
|
-
].join("\n")}\n`,
|
|
868
|
-
);
|
|
869
|
-
|
|
870
|
-
// /proc/mounts — virtio block device layout
|
|
871
|
-
const mountsContent = `${[
|
|
872
|
-
"proc /proc proc rw,relatime 0 0",
|
|
873
|
-
"sysfs /sys sysfs rw,relatime 0 0",
|
|
874
|
-
"devtmpfs /dev devtmpfs rw,relatime,size=2045672k,nr_inodes=511418,mode=755 0 0",
|
|
875
|
-
"tmpfs /dev/shm tmpfs rw,relatime 0 0",
|
|
876
|
-
"devpts /dev/pts devpts rw,relatime,mode=600,ptmxmode=000 0 0",
|
|
877
|
-
"tmpfs /sys/fs/cgroup tmpfs rw,relatime 0 0",
|
|
878
|
-
"cgroup /sys/fs/cgroup/cpu cgroup rw,relatime,cpu 0 0",
|
|
879
|
-
"cgroup /sys/fs/cgroup/cpuacct cgroup rw,relatime,cpuacct 0 0",
|
|
880
|
-
"cgroup /sys/fs/cgroup/memory cgroup rw,relatime,memory 0 0",
|
|
881
|
-
"cgroup /sys/fs/cgroup/devices cgroup rw,relatime,devices 0 0",
|
|
882
|
-
"cgroup /sys/fs/cgroup/freezer cgroup rw,relatime,freezer 0 0",
|
|
883
|
-
"cgroup /sys/fs/cgroup/blkio cgroup rw,relatime,blkio 0 0",
|
|
884
|
-
"cgroup /sys/fs/cgroup/pids cgroup rw,relatime,pids 0 0",
|
|
885
|
-
"cgroup2 /sys/fs/cgroup/unified cgroup2 rw,relatime 0 0",
|
|
886
|
-
"/dev/vda / ext4 rw,relatime,resuid=65534,resgid=65534 0 0",
|
|
887
|
-
"/dev/vdb /opt/rclone squashfs ro,relatime,errors=continue 0 0",
|
|
888
|
-
"tmpfs /run tmpfs rw,nosuid,nodev,noexec,relatime,size=204800k,mode=755 0 0",
|
|
889
|
-
"tmpfs /tmp tmpfs rw,nosuid,nodev,noatime 0 0",
|
|
890
|
-
].join("\n")}\n`;
|
|
891
|
-
write(vfs, "/proc/mounts", mountsContent);
|
|
892
|
-
ensureDir(vfs, "/proc/self");
|
|
893
|
-
write(vfs, "/proc/self/mounts", mountsContent);
|
|
894
|
-
|
|
895
|
-
// /proc/net
|
|
896
|
-
ensureDir(vfs, "/proc/net");
|
|
897
|
-
write(vfs, "/proc/net/dev",
|
|
898
|
-
`${[
|
|
899
|
-
"Inter-| Receive | Transmit",
|
|
900
|
-
" face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed",
|
|
901
|
-
" lo: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0",
|
|
902
|
-
" eth0: 128628 1230 0 19 0 0 0 0 52027469 2045 0 0 0 0 0 0",
|
|
903
|
-
].join("\n")}\n`,
|
|
904
|
-
);
|
|
905
|
-
write(vfs, "/proc/net/if_inet6", "");
|
|
906
|
-
write(vfs, "/proc/net/tcp",
|
|
907
|
-
" sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode\n",
|
|
908
|
-
);
|
|
909
|
-
write(vfs, "/proc/net/tcp6",
|
|
910
|
-
" sl local_address remote_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode\n",
|
|
911
|
-
);
|
|
912
|
-
write(vfs, "/proc/net/udp",
|
|
913
|
-
" sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode\n",
|
|
914
|
-
);
|
|
915
|
-
write(vfs, "/proc/net/route",
|
|
916
|
-
"Iface\tDestination\tGateway\tFlags\tRefCnt\tUse\tMetric\tMask\t\tMTU\tWindow\tIRTT\n" +
|
|
917
|
-
"eth0\t00000000\t0101A8C0\t0003\t0\t0\t100\t00000000\t0\t0\t0\n" +
|
|
918
|
-
"eth0\t0000A8C0\t00000000\t0001\t0\t0\t100\t00FFFFFF\t0\t0\t0\n",
|
|
919
|
-
);
|
|
920
|
-
write(vfs, "/proc/net/arp",
|
|
921
|
-
"IP address HW type Flags HW address Mask Device\n",
|
|
922
|
-
);
|
|
923
|
-
write(vfs, "/proc/net/fib_trie", "Local:\n +-- 0.0.0.0/0 3 0 5\n");
|
|
924
|
-
write(vfs, "/proc/net/unix",
|
|
925
|
-
"Num RefCount Protocol Flags Type St Inode Path\n" +
|
|
926
|
-
"0000000000000000: 00000002 00000000 00010000 0001 01 10000 /run/dbus/system_bus_socket\n",
|
|
927
|
-
);
|
|
928
|
-
write(vfs, "/proc/net/sockstat",
|
|
929
|
-
"sockets: used 8\nTCP: inuse 0 orphan 0 tw 0 alloc 0 mem 0\nUDP: inuse 0 mem 0\nUDPLITE: inuse 0\nRAW: inuse 0\nFRAG: inuse 0 memory 0\n",
|
|
930
|
-
);
|
|
931
|
-
|
|
932
|
-
// /proc/partitions — virtio block devices
|
|
933
|
-
write(
|
|
934
|
-
vfs,
|
|
935
|
-
"/proc/partitions",
|
|
936
|
-
`${[
|
|
937
|
-
"major minor #blocks name",
|
|
938
|
-
"",
|
|
939
|
-
" 254 0 268435456 vda",
|
|
940
|
-
" 254 16 9664 vdb",
|
|
941
|
-
" 254 32 656 vdc",
|
|
942
|
-
" 254 48 5464 vdd",
|
|
943
|
-
].join("\n")}\n`,
|
|
944
|
-
);
|
|
945
|
-
|
|
946
|
-
// /proc/swaps — no swap (matches real env: SwapTotal 0)
|
|
947
|
-
write(vfs, "/proc/swaps",
|
|
948
|
-
"Filename\t\t\t\tType\t\tSize\t\tUsed\t\tPriority\n",
|
|
949
|
-
);
|
|
950
|
-
|
|
951
|
-
// /proc/diskstats — virtio block device I/O counters
|
|
952
|
-
write(vfs, "/proc/diskstats",
|
|
953
|
-
`${[
|
|
954
|
-
" 254 0 vda 1000 0 8000 500 200 0 1600 100 0 600 600 0 0 0 0",
|
|
955
|
-
" 254 16 vdb 100 0 800 50 0 0 0 0 0 50 50 0 0 0 0",
|
|
956
|
-
" 254 32 vdc 50 0 400 25 0 0 0 0 0 25 25 0 0 0 0",
|
|
957
|
-
" 254 48 vdd 80 0 640 40 0 0 0 0 0 40 40 0 0 0 0",
|
|
958
|
-
].join("\n")}\n`,
|
|
959
|
-
);
|
|
960
|
-
|
|
961
|
-
// /proc/interrupts
|
|
962
|
-
write(vfs, "/proc/interrupts",
|
|
963
|
-
` CPU0\n 0: ${Math.floor(uptimeSec * 250)} IO-APIC 2-edge timer\n 1: 9 IO-APIC 1-edge i8042\n NMI: 0 Non-maskable interrupts\n ERR: 0\n MIS: 0\n PIN: 0 Posted-interrupt notification event\n NPI: 0 Nested posted-interrupt event\n PIW: 0 Posted-interrupt wakeup event\n`,
|
|
964
|
-
);
|
|
965
|
-
|
|
966
|
-
// /proc/sys — sysctl virtual tree (real values)
|
|
967
|
-
ensureDir(vfs, "/proc/sys");
|
|
968
|
-
ensureDir(vfs, "/proc/sys/kernel");
|
|
969
|
-
ensureDir(vfs, "/proc/sys/net");
|
|
970
|
-
ensureDir(vfs, "/proc/sys/net/ipv4");
|
|
971
|
-
ensureDir(vfs, "/proc/sys/net/ipv6");
|
|
972
|
-
ensureDir(vfs, "/proc/sys/net/core");
|
|
973
|
-
ensureDir(vfs, "/proc/sys/vm");
|
|
974
|
-
ensureDir(vfs, "/proc/sys/fs");
|
|
975
|
-
ensureDir(vfs, "/proc/sys/fs/inotify");
|
|
976
|
-
|
|
977
|
-
write(vfs, "/proc/sys/kernel/hostname", `${hostname}\n`);
|
|
978
|
-
write(vfs, "/proc/sys/kernel/ostype", "Linux\n");
|
|
979
|
-
write(vfs, "/proc/sys/kernel/osrelease", `${props.kernel}\n`);
|
|
980
|
-
write(vfs, "/proc/sys/kernel/pid_max", "32768\n");
|
|
981
|
-
write(vfs, "/proc/sys/kernel/threads-max", "31968\n");
|
|
982
|
-
write(vfs, "/proc/sys/kernel/randomize_va_space", "2\n");
|
|
983
|
-
write(vfs, "/proc/sys/kernel/dmesg_restrict", "0\n");
|
|
984
|
-
write(vfs, "/proc/sys/kernel/kptr_restrict", "0\n");
|
|
985
|
-
write(vfs, "/proc/sys/kernel/perf_event_paranoid", "2\n");
|
|
986
|
-
write(vfs, "/proc/sys/kernel/printk", "4\t4\t1\t7\n");
|
|
987
|
-
write(vfs, "/proc/sys/kernel/sysrq", "176\n");
|
|
988
|
-
write(vfs, "/proc/sys/kernel/panic", "1\n");
|
|
989
|
-
write(vfs, "/proc/sys/kernel/panic_on_oops", "1\n");
|
|
990
|
-
write(vfs, "/proc/sys/kernel/core_pattern", "core\n");
|
|
991
|
-
write(vfs, "/proc/sys/kernel/core_uses_pid", "0\n");
|
|
992
|
-
write(vfs, "/proc/sys/kernel/ngroups_max", "65536\n");
|
|
993
|
-
write(vfs, "/proc/sys/kernel/cap_last_cap", "40\n");
|
|
994
|
-
write(vfs, "/proc/sys/kernel/unprivileged_userns_clone", "1\n");
|
|
995
|
-
write(vfs, "/proc/sys/net/ipv4/ip_forward", "0\n");
|
|
996
|
-
write(vfs, "/proc/sys/net/ipv4/tcp_syncookies", "1\n");
|
|
997
|
-
write(vfs, "/proc/sys/net/ipv4/tcp_fin_timeout", "60\n");
|
|
998
|
-
write(vfs, "/proc/sys/net/ipv4/tcp_keepalive_time", "7200\n");
|
|
999
|
-
write(vfs, "/proc/sys/net/ipv4/conf/all/rp_filter", "2\n");
|
|
1000
|
-
write(vfs, "/proc/sys/net/ipv6/conf/all/disable_ipv6", "1\n");
|
|
1001
|
-
write(vfs, "/proc/sys/net/core/somaxconn", "4096\n");
|
|
1002
|
-
write(vfs, "/proc/sys/net/core/rmem_max", "212992\n");
|
|
1003
|
-
write(vfs, "/proc/sys/net/core/wmem_max", "212992\n");
|
|
1004
|
-
write(vfs, "/proc/sys/vm/swappiness", "60\n");
|
|
1005
|
-
write(vfs, "/proc/sys/vm/overcommit_memory", "0\n");
|
|
1006
|
-
write(vfs, "/proc/sys/vm/overcommit_ratio", "50\n");
|
|
1007
|
-
write(vfs, "/proc/sys/vm/dirty_ratio", "20\n");
|
|
1008
|
-
write(vfs, "/proc/sys/vm/dirty_background_ratio", "10\n");
|
|
1009
|
-
write(vfs, "/proc/sys/vm/min_free_kbytes", "65536\n");
|
|
1010
|
-
write(vfs, "/proc/sys/vm/vfs_cache_pressure", "100\n");
|
|
1011
|
-
write(vfs, "/proc/sys/fs/file-max", "1048576\n");
|
|
1012
|
-
write(vfs, "/proc/sys/fs/inotify/max_user_watches", "524288\n");
|
|
1013
|
-
write(vfs, "/proc/sys/fs/inotify/max_user_instances","512\n");
|
|
1014
|
-
write(vfs, "/proc/sys/fs/inotify/max_queued_events", "16384\n");
|
|
1015
|
-
|
|
1016
|
-
// /proc/cgroups — v1 hierarchy
|
|
1017
|
-
write(vfs, "/proc/cgroups",
|
|
1018
|
-
`${[
|
|
1019
|
-
"#subsys_name\thierarchy\tnum_cgroups\tenabled",
|
|
1020
|
-
"cpuset\t5\t1\t1",
|
|
1021
|
-
"cpu\t1\t1\t1",
|
|
1022
|
-
"cpuacct\t2\t1\t1",
|
|
1023
|
-
"blkio\t6\t1\t1",
|
|
1024
|
-
"memory\t3\t1\t1",
|
|
1025
|
-
"devices\t4\t1\t1",
|
|
1026
|
-
"freezer\t7\t1\t1",
|
|
1027
|
-
"pids\t8\t1\t1",
|
|
1028
|
-
].join("\n")}\n`,
|
|
1029
|
-
);
|
|
1030
|
-
|
|
1031
|
-
// init process (PID 1)
|
|
1032
|
-
writeProcPid(vfs, 1, "root", "pts/0", "/sbin/init", new Date(shellStartTime).toISOString(), {});
|
|
1033
|
-
|
|
1034
|
-
// per-session processes
|
|
1035
|
-
for (const session of sessions) {
|
|
1036
|
-
const pid = ttyToPid(session.tty);
|
|
1037
|
-
writeProcPid(vfs, pid, session.username, session.tty, "bash", session.startedAt, {
|
|
1038
|
-
USER: session.username,
|
|
1039
|
-
HOME: `/home/${session.username}`,
|
|
1040
|
-
TERM: "xterm-256color",
|
|
1041
|
-
SHELL: "/bin/bash",
|
|
1042
|
-
LANG: "en_US.UTF-8",
|
|
1043
|
-
PATH: "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
|
1044
|
-
LOGNAME: session.username,
|
|
1045
|
-
});
|
|
1046
|
-
}
|
|
1047
|
-
|
|
1048
|
-
// /proc/self — mirror of most recent session
|
|
1049
|
-
const selfPid = sessions.length > 0 ? ttyToPid(sessions[sessions.length - 1]!.tty) : 1;
|
|
1050
|
-
try { vfs.remove("/proc/self"); } catch { /* ignore */ }
|
|
1051
|
-
|
|
1052
|
-
const selfSrc = `/proc/${selfPid}`;
|
|
1053
|
-
ensureDir(vfs, "/proc/self");
|
|
1054
|
-
ensureDir(vfs, "/proc/self/fd");
|
|
1055
|
-
ensureDir(vfs, "/proc/self/fdinfo");
|
|
1056
|
-
ensureDir(vfs, "/proc/self/net");
|
|
1057
|
-
|
|
1058
|
-
if (vfs.exists(selfSrc)) {
|
|
1059
|
-
for (const entry of vfs.list(selfSrc)) {
|
|
1060
|
-
const srcPath = `${selfSrc}/${entry}`;
|
|
1061
|
-
const dstPath = `/proc/self/${entry}`;
|
|
1062
|
-
try {
|
|
1063
|
-
const st = vfs.stat(srcPath);
|
|
1064
|
-
if (st.type === "file") write(vfs, dstPath, vfs.readFile(srcPath));
|
|
1065
|
-
} catch { /* skip */ }
|
|
1066
|
-
}
|
|
1067
|
-
} else {
|
|
1068
|
-
write(vfs, "/proc/self/cmdline", "bash\0");
|
|
1069
|
-
write(vfs, "/proc/self/comm", "bash");
|
|
1070
|
-
write(vfs, "/proc/self/status", "Name:\tbash\nState:\tS (sleeping)\nPid:\t1\nPPid:\t0\n");
|
|
1071
|
-
write(vfs, "/proc/self/environ", "");
|
|
1072
|
-
write(vfs, "/proc/self/cwd", "/root\0");
|
|
1073
|
-
write(vfs, "/proc/self/exe", "/bin/bash\0");
|
|
1074
|
-
}
|
|
1075
|
-
}
|
|
1076
|
-
|
|
1077
|
-
// ─── /sys ─────────────────────────────────────────────────────────────────────
|
|
1078
|
-
|
|
1079
|
-
function bootstrapSys(vfs: VirtualFileSystem, hostname: string, props: ShellProperties): void {
|
|
1080
|
-
ensureDir(vfs, "/sys");
|
|
1081
|
-
|
|
1082
|
-
// No real DMI in Firecracker — /sys/devices/virtual/dmi/id does not exist.
|
|
1083
|
-
// Expose /sys/class/net, /sys/fs/cgroup, /sys/kernel only.
|
|
1084
|
-
|
|
1085
|
-
ensureDir(vfs, "/sys/devices");
|
|
1086
|
-
ensureDir(vfs, "/sys/devices/virtual");
|
|
1087
|
-
ensureDir(vfs, "/sys/devices/system");
|
|
1088
|
-
ensureDir(vfs, "/sys/devices/system/cpu");
|
|
1089
|
-
ensureDir(vfs, "/sys/devices/system/cpu/cpu0");
|
|
1090
|
-
ensureFile(vfs, "/sys/devices/system/cpu/cpu0/online", "1\n");
|
|
1091
|
-
ensureFile(vfs, "/sys/devices/system/cpu/online", "0\n");
|
|
1092
|
-
ensureFile(vfs, "/sys/devices/system/cpu/possible", "0\n");
|
|
1093
|
-
ensureFile(vfs, "/sys/devices/system/cpu/present", "0\n");
|
|
1094
|
-
ensureDir(vfs, "/sys/devices/system/node");
|
|
1095
|
-
ensureDir(vfs, "/sys/devices/system/node/node0");
|
|
1096
|
-
ensureFile(vfs, "/sys/devices/system/node/node0/cpumap", "1\n");
|
|
1097
|
-
|
|
1098
|
-
ensureDir(vfs, "/sys/class");
|
|
1099
|
-
ensureDir(vfs, "/sys/class/net");
|
|
1100
|
-
ensureDir(vfs, "/sys/class/net/eth0");
|
|
1101
|
-
ensureFile(vfs, "/sys/class/net/eth0/operstate", "up\n");
|
|
1102
|
-
ensureFile(vfs, "/sys/class/net/eth0/carrier", "1\n");
|
|
1103
|
-
ensureFile(vfs, "/sys/class/net/eth0/mtu", "1500\n");
|
|
1104
|
-
ensureFile(vfs, "/sys/class/net/eth0/speed", "10000\n");
|
|
1105
|
-
ensureFile(vfs, "/sys/class/net/eth0/duplex", "full\n");
|
|
1106
|
-
ensureFile(vfs, "/sys/class/net/eth0/address", "aa:bb:cc:dd:ee:ff\n");
|
|
1107
|
-
ensureFile(vfs, "/sys/class/net/eth0/tx_queue_len","1000\n");
|
|
1108
|
-
|
|
1109
|
-
const seed = fnv1a(hostname);
|
|
1110
|
-
const macSeed = seed.toString(16).padStart(8, "0");
|
|
1111
|
-
ensureFile(vfs, "/sys/class/net/eth0/address",
|
|
1112
|
-
`52:54:00:${macSeed.slice(0,2)}:${macSeed.slice(2,4)}:${macSeed.slice(4,6)}\n`,
|
|
1113
|
-
);
|
|
1114
|
-
|
|
1115
|
-
ensureDir(vfs, "/sys/class/net/lo");
|
|
1116
|
-
ensureFile(vfs, "/sys/class/net/lo/operstate", "unknown\n");
|
|
1117
|
-
ensureFile(vfs, "/sys/class/net/lo/carrier", "1\n");
|
|
1118
|
-
ensureFile(vfs, "/sys/class/net/lo/mtu", "65536\n");
|
|
1119
|
-
ensureFile(vfs, "/sys/class/net/lo/address", "00:00:00:00:00:00\n");
|
|
1120
|
-
|
|
1121
|
-
ensureDir(vfs, "/sys/class/block");
|
|
1122
|
-
ensureDir(vfs, "/sys/class/block/vda");
|
|
1123
|
-
ensureFile(vfs, "/sys/class/block/vda/size", "536870912\n");
|
|
1124
|
-
ensureFile(vfs, "/sys/class/block/vda/ro", "0\n");
|
|
1125
|
-
ensureFile(vfs, "/sys/class/block/vda/removable","0\n");
|
|
1126
|
-
|
|
1127
|
-
// cgroup fs
|
|
1128
|
-
ensureDir(vfs, "/sys/fs");
|
|
1129
|
-
ensureDir(vfs, "/sys/fs/cgroup");
|
|
1130
|
-
for (const subsys of ["cpu", "cpuacct", "memory", "devices", "blkio", "pids", "freezer", "unified"]) {
|
|
1131
|
-
ensureDir(vfs, `/sys/fs/cgroup/${subsys}`);
|
|
1132
|
-
if (subsys !== "unified") {
|
|
1133
|
-
ensureFile(vfs, `/sys/fs/cgroup/${subsys}/tasks`, "1\n");
|
|
1134
|
-
ensureFile(vfs, `/sys/fs/cgroup/${subsys}/notify_on_release`, "0\n");
|
|
1135
|
-
ensureFile(vfs, `/sys/fs/cgroup/${subsys}/release_agent`, "");
|
|
1136
|
-
}
|
|
1137
|
-
}
|
|
1138
|
-
ensureFile(vfs, "/sys/fs/cgroup/memory/memory.limit_in_bytes", `${os.totalmem()}\n`);
|
|
1139
|
-
ensureFile(vfs, "/sys/fs/cgroup/memory/memory.usage_in_bytes", `${os.totalmem() - os.freemem()}\n`);
|
|
1140
|
-
ensureFile(vfs, "/sys/fs/cgroup/memory/memory.memsw.limit_in_bytes",`${os.totalmem()}\n`);
|
|
1141
|
-
ensureFile(vfs, "/sys/fs/cgroup/cpu/cpu.cfs_period_us", "100000\n");
|
|
1142
|
-
ensureFile(vfs, "/sys/fs/cgroup/cpu/cpu.cfs_quota_us", "-1\n");
|
|
1143
|
-
ensureFile(vfs, "/sys/fs/cgroup/cpu/cpu.shares", "1024\n");
|
|
1144
|
-
|
|
1145
|
-
ensureDir(vfs, "/sys/kernel");
|
|
1146
|
-
ensureFile(vfs, "/sys/kernel/hostname", `${hostname}\n`);
|
|
1147
|
-
ensureFile(vfs, "/sys/kernel/osrelease", `${props.kernel}\n`);
|
|
1148
|
-
ensureFile(vfs, "/sys/kernel/ostype", "Linux\n");
|
|
1149
|
-
|
|
1150
|
-
// security
|
|
1151
|
-
ensureDir(vfs, "/sys/kernel/security");
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
// Still; we will create virtual dmi
|
|
1155
|
-
ensureDir(vfs, "/sys/devices/virtual");
|
|
1156
|
-
ensureDir(vfs, "/sys/devices/virtual/dmi");
|
|
1157
|
-
ensureDir(vfs, "/sys/devices/virtual/dmi/id");
|
|
1158
|
-
const product = `VirtualNode-${(seed % 10000).toString().padStart(4, "0")}`;
|
|
1159
|
-
|
|
1160
|
-
// Full DMI table — deterministic, seeded from hostname
|
|
1161
|
-
const dmi: Record<string, string> = {
|
|
1162
|
-
bios_vendor: "Virtual BIOS",
|
|
1163
|
-
bios_version: "1.0",
|
|
1164
|
-
bios_date: "01/01/2025",
|
|
1165
|
-
sys_vendor: "Fortune Systems",
|
|
1166
|
-
product_name: product,
|
|
1167
|
-
product_family: "VirtualContainer",
|
|
1168
|
-
product_version: "v1",
|
|
1169
|
-
product_uuid: `${seed.toString(16).padStart(8, "0")}-0000-0000-0000-000000000000`,
|
|
1170
|
-
product_serial: `SN-${seed}`,
|
|
1171
|
-
chassis_type: "3",
|
|
1172
|
-
chassis_vendor: "Virtual",
|
|
1173
|
-
chassis_version: "v1",
|
|
1174
|
-
board_name: "fortune-board",
|
|
1175
|
-
modalias: `dmi:bvnVirtual:bvr1.0:svnFortune:pn${product}`,
|
|
1176
|
-
};
|
|
1177
|
-
|
|
1178
|
-
for (const [k, v] of Object.entries(dmi)) {
|
|
1179
|
-
ensureFile(vfs, `/sys/devices/virtual/dmi/id/${k}`, `${v}\n`);
|
|
1180
|
-
}
|
|
1181
|
-
|
|
1182
|
-
ensureDir(vfs, "/sys/class");
|
|
1183
|
-
ensureDir(vfs, "/sys/class/net");
|
|
1184
|
-
ensureDir(vfs, "/sys/kernel");
|
|
1185
|
-
|
|
1186
|
-
ensureFile(vfs, "/sys/kernel/hostname", `${hostname}\n`);
|
|
1187
|
-
ensureFile(vfs, "/sys/kernel/osrelease", `${props.kernel}\n`);
|
|
1188
|
-
ensureFile(vfs, "/sys/kernel/ostype", "Linux\n");
|
|
1189
|
-
|
|
1190
|
-
}
|
|
1191
|
-
|
|
1192
|
-
// ─── /dev ─────────────────────────────────────────────────────────────────────
|
|
1193
|
-
|
|
1194
|
-
function bootstrapDev(vfs: VirtualFileSystem): void {
|
|
1195
|
-
ensureDir(vfs, "/dev");
|
|
1196
|
-
|
|
1197
|
-
// character devices — matching real Firecracker container
|
|
1198
|
-
ensureFile(vfs, "/dev/null", "", 0o666);
|
|
1199
|
-
ensureFile(vfs, "/dev/zero", "", 0o666);
|
|
1200
|
-
ensureFile(vfs, "/dev/full", "", 0o666);
|
|
1201
|
-
ensureFile(vfs, "/dev/random", "", 0o444);
|
|
1202
|
-
ensureFile(vfs, "/dev/urandom", "", 0o444);
|
|
1203
|
-
ensureFile(vfs, "/dev/mem", "", 0o640);
|
|
1204
|
-
ensureFile(vfs, "/dev/port", "", 0o640);
|
|
1205
|
-
ensureFile(vfs, "/dev/kmsg", "", 0o660);
|
|
1206
|
-
ensureFile(vfs, "/dev/hwrng", "", 0o660);
|
|
1207
|
-
ensureFile(vfs, "/dev/fuse", "", 0o660);
|
|
1208
|
-
ensureFile(vfs, "/dev/autofs", "", 0o660);
|
|
1209
|
-
ensureFile(vfs, "/dev/userfaultfd", "", 0o660);
|
|
1210
|
-
ensureFile(vfs, "/dev/cpu_dma_latency", "", 0o660);
|
|
1211
|
-
ensureFile(vfs, "/dev/ptp0", "", 0o660);
|
|
1212
|
-
|
|
1213
|
-
// snapshot (KVM-specific)
|
|
1214
|
-
ensureFile(vfs, "/dev/snapshot", "", 0o660);
|
|
1215
|
-
|
|
1216
|
-
// terminal devices
|
|
1217
|
-
ensureFile(vfs, "/dev/console", "", 0o600);
|
|
1218
|
-
ensureFile(vfs, "/dev/tty", "", 0o666);
|
|
1219
|
-
ensureFile(vfs, "/dev/ttyS0", "", 0o660);
|
|
1220
|
-
ensureFile(vfs, "/dev/ptmx", "", 0o666);
|
|
1221
|
-
|
|
1222
|
-
// tty0–63 (like real env)
|
|
1223
|
-
for (let i = 0; i <= 63; i++) {
|
|
1224
|
-
ensureFile(vfs, `/dev/tty${i}`, "", 0o620);
|
|
1225
|
-
}
|
|
1226
|
-
|
|
1227
|
-
// vcs devices
|
|
1228
|
-
ensureFile(vfs, "/dev/vcs", "", 0o620);
|
|
1229
|
-
ensureFile(vfs, "/dev/vcs1", "", 0o620);
|
|
1230
|
-
ensureFile(vfs, "/dev/vcsa", "", 0o620);
|
|
1231
|
-
ensureFile(vfs, "/dev/vcsa1", "", 0o620);
|
|
1232
|
-
ensureFile(vfs, "/dev/vcsu", "", 0o620);
|
|
1233
|
-
ensureFile(vfs, "/dev/vcsu1", "", 0o620);
|
|
1234
|
-
|
|
1235
|
-
// loop devices (0–7)
|
|
1236
|
-
for (let i = 0; i < 8; i++) {
|
|
1237
|
-
ensureFile(vfs, `/dev/loop${i}`, "", 0o660);
|
|
1238
|
-
}
|
|
1239
|
-
ensureDir(vfs, "/dev/loop-control");
|
|
1240
|
-
|
|
1241
|
-
// virtio block devices (vda–vdd matching mounts)
|
|
1242
|
-
ensureFile(vfs, "/dev/vda", "", 0o660);
|
|
1243
|
-
ensureFile(vfs, "/dev/vdb", "", 0o660);
|
|
1244
|
-
ensureFile(vfs, "/dev/vdc", "", 0o660);
|
|
1245
|
-
ensureFile(vfs, "/dev/vdd", "", 0o660);
|
|
1246
|
-
|
|
1247
|
-
// network tun
|
|
1248
|
-
ensureDir(vfs, "/dev/net");
|
|
1249
|
-
ensureFile(vfs, "/dev/net/tun", "", 0o660);
|
|
1250
|
-
|
|
1251
|
-
// misc
|
|
1252
|
-
ensureDir(vfs, "/dev/pts");
|
|
1253
|
-
ensureDir(vfs, "/dev/shm");
|
|
1254
|
-
ensureDir(vfs, "/dev/cpu");
|
|
1255
|
-
ensureFile(vfs, "/dev/stdin", "", 0o666);
|
|
1256
|
-
ensureFile(vfs, "/dev/stdout", "", 0o666);
|
|
1257
|
-
ensureFile(vfs, "/dev/stderr", "", 0o666);
|
|
1258
|
-
ensureDir(vfs, "/dev/fd");
|
|
1259
|
-
ensureFile(vfs, "/dev/vga_arbiter", "", 0o660);
|
|
1260
|
-
ensureFile(vfs, "/dev/vsock", "", 0o660);
|
|
1261
|
-
}
|
|
1262
|
-
|
|
1263
|
-
// ─── /usr ─────────────────────────────────────────────────────────────────────
|
|
1264
|
-
|
|
1265
|
-
function bootstrapUsr(vfs: VirtualFileSystem): void {
|
|
1266
|
-
ensureDir(vfs, "/usr");
|
|
1267
|
-
ensureDir(vfs, "/usr/bin");
|
|
1268
|
-
ensureDir(vfs, "/usr/sbin");
|
|
1269
|
-
ensureDir(vfs, "/usr/local");
|
|
1270
|
-
ensureDir(vfs, "/usr/local/bin");
|
|
1271
|
-
ensureDir(vfs, "/usr/local/lib");
|
|
1272
|
-
ensureDir(vfs, "/usr/local/share");
|
|
1273
|
-
ensureDir(vfs, "/usr/local/include");
|
|
1274
|
-
ensureDir(vfs, "/usr/local/sbin");
|
|
1275
|
-
ensureDir(vfs, "/usr/share");
|
|
1276
|
-
ensureDir(vfs, "/usr/share/doc");
|
|
1277
|
-
ensureDir(vfs, "/usr/share/man");
|
|
1278
|
-
ensureDir(vfs, "/usr/share/man/man1");
|
|
1279
|
-
ensureDir(vfs, "/usr/share/man/man5");
|
|
1280
|
-
ensureDir(vfs, "/usr/share/man/man8");
|
|
1281
|
-
ensureDir(vfs, "/usr/share/common-licenses");
|
|
1282
|
-
ensureDir(vfs, "/usr/share/ca-certificates");
|
|
1283
|
-
ensureDir(vfs, "/usr/share/zoneinfo");
|
|
1284
|
-
ensureDir(vfs, "/usr/lib");
|
|
1285
|
-
ensureDir(vfs, "/usr/lib/x86_64-linux-gnu");
|
|
1286
|
-
ensureDir(vfs, "/usr/lib/python3");
|
|
1287
|
-
ensureDir(vfs, "/usr/lib/python3/dist-packages");
|
|
1288
|
-
ensureDir(vfs, "/usr/lib/python3.12");
|
|
1289
|
-
ensureDir(vfs, "/usr/lib/jvm");
|
|
1290
|
-
ensureDir(vfs, "/usr/lib/jvm/java-21-openjdk-amd64");
|
|
1291
|
-
ensureDir(vfs, "/usr/lib/jvm/java-21-openjdk-amd64/bin");
|
|
1292
|
-
ensureDir(vfs, "/usr/lib/node_modules");
|
|
1293
|
-
ensureDir(vfs, "/usr/lib/node_modules/npm");
|
|
1294
|
-
ensureDir(vfs, "/usr/include");
|
|
1295
|
-
ensureDir(vfs, "/usr/src");
|
|
1296
|
-
|
|
1297
|
-
// builtins — all bins present in the real container
|
|
1298
|
-
const builtins = [
|
|
1299
|
-
"sh", "bash", "ls", "cat", "echo", "grep", "find", "sort",
|
|
1300
|
-
"head", "tail", "cut", "tr", "sed", "awk", "wc", "tee",
|
|
1301
|
-
"tar", "gzip", "gunzip", "touch", "mkdir", "rm", "mv", "cp",
|
|
1302
|
-
"chmod", "ln", "pwd", "env", "date", "sleep", "id", "whoami",
|
|
1303
|
-
"hostname", "uname", "ps", "kill", "df", "du", "curl", "wget",
|
|
1304
|
-
"nano", "diff", "uniq", "xargs", "base64",
|
|
1305
|
-
];
|
|
1306
|
-
|
|
1307
|
-
// From a real container
|
|
1308
|
-
// const builtins = [
|
|
1309
|
-
// // core
|
|
1310
|
-
// "sh", "bash", "dash",
|
|
1311
|
-
// "ls", "cat", "echo", "grep", "find", "sort",
|
|
1312
|
-
// "head", "tail", "cut", "tr", "sed", "awk", "mawk", "gawk",
|
|
1313
|
-
// "wc", "tee", "tar", "gzip", "gunzip", "bzip2", "xz",
|
|
1314
|
-
// "touch", "mkdir", "rm", "mv", "cp", "ln", "pwd",
|
|
1315
|
-
// "chmod", "chown", "chgrp", "env", "date", "sleep",
|
|
1316
|
-
// "id", "whoami", "hostname", "uname", "ps", "kill",
|
|
1317
|
-
// "df", "du", "dd", "stat", "file",
|
|
1318
|
-
// // net
|
|
1319
|
-
// "curl", "wget", "nc", "netcat", "ss", "ip",
|
|
1320
|
-
// // editors
|
|
1321
|
-
// "nano", "vi",
|
|
1322
|
-
// // text
|
|
1323
|
-
// "diff", "uniq", "xargs", "base64", "md5sum", "sha256sum",
|
|
1324
|
-
// "strings", "hexdump", "od", "column", "fmt", "paste",
|
|
1325
|
-
// "join", "comm", "split", "csplit", "fold", "expand",
|
|
1326
|
-
// // archive
|
|
1327
|
-
// "zip", "unzip",
|
|
1328
|
-
// // process
|
|
1329
|
-
// "top", "htop", "free", "uptime", "dmesg", "lsof",
|
|
1330
|
-
// "strace", "ltrace", "pgrep", "pkill", "nohup", "nice",
|
|
1331
|
-
// // fs
|
|
1332
|
-
// "mount", "umount", "lsblk", "fdisk", "blkid", "e2fsck",
|
|
1333
|
-
// // misc
|
|
1334
|
-
// "bc", "expr", "seq", "yes", "true", "false", "test",
|
|
1335
|
-
// "readlink", "realpath", "dirname", "basename", "mktemp",
|
|
1336
|
-
// "install", "make",
|
|
1337
|
-
// // dev tools
|
|
1338
|
-
// "gcc", "gcc-13", "g++", "g++-13", "cpp", "as", "ld",
|
|
1339
|
-
// "ar", "nm", "objdump", "objcopy", "strip", "size",
|
|
1340
|
-
// "cc", "c++", "pkg-config",
|
|
1341
|
-
// // package
|
|
1342
|
-
// "apt", "apt-get", "apt-cache", "dpkg", "dpkg-query",
|
|
1343
|
-
// "lsb_release", "add-apt-repository",
|
|
1344
|
-
// // scripting
|
|
1345
|
-
// "perl", "python3", "python3.12", "pipx",
|
|
1346
|
-
// // node/npm
|
|
1347
|
-
// "node", "npm", "npx",
|
|
1348
|
-
// // java
|
|
1349
|
-
// "java", "javac", "jar", "javadoc",
|
|
1350
|
-
// // security
|
|
1351
|
-
// "openssl", "gpg", "gpg2", "gpgv", "ssh", "ssh-keygen",
|
|
1352
|
-
// "sudo", "su", "passwd", "adduser", "useradd",
|
|
1353
|
-
// // misc system
|
|
1354
|
-
// "systemctl", "journalctl", "loginctl",
|
|
1355
|
-
// "timedatectl", "localectl",
|
|
1356
|
-
// "lshw", "lscpu", "lsusb", "lspci",
|
|
1357
|
-
// // text proc
|
|
1358
|
-
// "jq", "xmllint", "pandoc",
|
|
1359
|
-
// // multimedia
|
|
1360
|
-
// "ffmpeg",
|
|
1361
|
-
// ];
|
|
1362
|
-
|
|
1363
|
-
for (const bin of builtins) {
|
|
1364
|
-
ensureFile(vfs, `/usr/bin/${bin}`, `#!/bin/sh\nexec builtin ${bin} "$@"\n`, 0o755);
|
|
1365
|
-
}
|
|
1366
|
-
|
|
1367
|
-
// sbin equivalents
|
|
1368
|
-
const sbins = [
|
|
1369
|
-
"nologin", "useradd", "userdel", "groupadd", "groupdel",
|
|
1370
|
-
"adduser", "deluser", "shutdown", "reboot", "halt",
|
|
1371
|
-
"init", "service", "update-alternatives", "update-rc.d",
|
|
1372
|
-
"depmod", "modprobe", "insmod", "rmmod", "lsmod",
|
|
1373
|
-
"ifconfig", "route", "iptables", "ip6tables",
|
|
1374
|
-
"arp", "iwconfig", "ethtool",
|
|
1375
|
-
"fdisk", "parted", "mkfs.ext4", "fsck",
|
|
1376
|
-
"ldconfig", "ldconfig.real",
|
|
1377
|
-
];
|
|
1378
|
-
for (const bin of sbins) {
|
|
1379
|
-
ensureFile(vfs, `/usr/sbin/${bin}`, `#!/bin/sh\nexec builtin ${bin} "$@"\n`, 0o755);
|
|
1380
|
-
}
|
|
1381
|
-
|
|
1382
|
-
// versioned python symlink stubs
|
|
1383
|
-
ensureFile(vfs, "/usr/bin/python3.12", `#!/bin/sh\nexec python3 "$@"\n`, 0o755);
|
|
1384
|
-
ensureFile(vfs, "/usr/bin/python3", `#!/bin/sh\nexec python3.12 "$@"\n`, 0o755);
|
|
1385
|
-
|
|
1386
|
-
// node version stubs
|
|
1387
|
-
ensureFile(vfs, "/usr/bin/node", `#!/bin/sh\nexec node "$@"\n`, 0o755);
|
|
1388
|
-
ensureFile(vfs, "/usr/bin/npm", `#!/bin/sh\nexec npm "$@"\n`, 0o755);
|
|
1389
|
-
ensureFile(vfs, "/usr/bin/npx", `#!/bin/sh\nexec npx "$@"\n`, 0o755);
|
|
1390
|
-
|
|
1391
|
-
// java stubs
|
|
1392
|
-
ensureFile(vfs, "/usr/lib/jvm/java-21-openjdk-amd64/bin/java",
|
|
1393
|
-
`#!/bin/sh\nexec java "$@"\n`, 0o755);
|
|
1394
|
-
ensureFile(vfs, "/usr/lib/jvm/java-21-openjdk-amd64/bin/javac",
|
|
1395
|
-
`#!/bin/sh\nexec javac "$@"\n`, 0o755);
|
|
1396
|
-
|
|
1397
|
-
// /usr/share/common-licenses stubs
|
|
1398
|
-
ensureFile(vfs, "/usr/share/common-licenses/GPL-2", "GNU General Public License v2\n");
|
|
1399
|
-
ensureFile(vfs, "/usr/share/common-licenses/GPL-3", "GNU General Public License v3\n");
|
|
1400
|
-
ensureFile(vfs, "/usr/share/common-licenses/LGPL-2.1","GNU Lesser General Public License v2.1\n");
|
|
1401
|
-
ensureFile(vfs, "/usr/share/common-licenses/Apache-2.0","Apache License 2.0\n");
|
|
1402
|
-
ensureFile(vfs, "/usr/share/common-licenses/MIT", "MIT License\n");
|
|
1403
|
-
}
|
|
1404
|
-
|
|
1405
|
-
// ─── /var ─────────────────────────────────────────────────────────────────────
|
|
1406
|
-
|
|
1407
|
-
/** Realistic dpkg status database from real container package list */
|
|
1408
|
-
const DPKG_STATUS = `\
|
|
1409
|
-
Package: bash
|
|
1410
|
-
Status: install ok installed
|
|
1411
|
-
Priority: required
|
|
1412
|
-
Section: shells
|
|
1413
|
-
Installed-Size: 7012
|
|
1414
|
-
Maintainer: Fortune Maintainers <maintainers@fortune.local>
|
|
1415
|
-
Architecture: amd64
|
|
1416
|
-
Version: 5.2.21-2nyx1
|
|
1417
|
-
Depends: base-files (>= 2.1.12), fortune-utils (>= 1.0)
|
|
1418
|
-
Description: GNU Bourne Again SHell
|
|
1419
|
-
bash is an sh-compatible command language interpreter that executes commands
|
|
1420
|
-
read from the standard input or from a file.
|
|
1421
|
-
|
|
1422
|
-
Package: coreutils
|
|
1423
|
-
Status: install ok installed
|
|
1424
|
-
Priority: required
|
|
1425
|
-
Section: utils
|
|
1426
|
-
Installed-Size: 18272
|
|
1427
|
-
Maintainer: Fortune Maintainers <maintainers@fortune.local>
|
|
1428
|
-
Architecture: amd64
|
|
1429
|
-
Version: 9.4-3nyx1
|
|
1430
|
-
Depends: libacl1 (>= 2.2.23), libattr1 (>= 1:2.4.44), libc6 (>= 2.17)
|
|
1431
|
-
Description: GNU core utilities
|
|
1432
|
-
This package contains the basic file, shell and text manipulation utilities.
|
|
1433
|
-
|
|
1434
|
-
Package: nodejs
|
|
1435
|
-
Status: install ok installed
|
|
1436
|
-
Priority: optional
|
|
1437
|
-
Section: web
|
|
1438
|
-
Installed-Size: 107120
|
|
1439
|
-
Maintainer: NodeSource <nodejs@nodesource.com>
|
|
1440
|
-
Architecture: amd64
|
|
1441
|
-
Version: 22.22.2-1nyx1
|
|
1442
|
-
Depends: libc6 (>= 2.17), libgcc-s1 (>= 3.0), libstdc++6 (>= 9.0)
|
|
1443
|
-
Description: Node.js event-based server-side javascript engine
|
|
1444
|
-
Node.js is similar in design to and influenced by systems like Ruby's Twisted.
|
|
1445
|
-
|
|
1446
|
-
Package: python3
|
|
1447
|
-
Status: install ok installed
|
|
1448
|
-
Priority: important
|
|
1449
|
-
Section: python
|
|
1450
|
-
Installed-Size: 68
|
|
1451
|
-
Maintainer: Fortune Maintainers <maintainers@fortune.local>
|
|
1452
|
-
Architecture: amd64
|
|
1453
|
-
Version: 3.12.3-0nyx1
|
|
1454
|
-
Depends: python3.12 (>= 3.12.3-0nyx1)
|
|
1455
|
-
Description: interactive high-level object-oriented language (default python3)
|
|
1456
|
-
Python, the high-level, interactive object oriented language, includes an
|
|
1457
|
-
extensive class library with lots of goodies for network programming.
|
|
1458
|
-
|
|
1459
|
-
Package: python3.12
|
|
1460
|
-
Status: install ok installed
|
|
1461
|
-
Priority: optional
|
|
1462
|
-
Section: python
|
|
1463
|
-
Installed-Size: 36
|
|
1464
|
-
Maintainer: Fortune Maintainers <maintainers@fortune.local>
|
|
1465
|
-
Architecture: amd64
|
|
1466
|
-
Version: 3.12.3-1nyx1
|
|
1467
|
-
Depends: python3.12-minimal (= 3.12.3-1nyx1), libpython3.12-stdlib
|
|
1468
|
-
Description: Interactive high-level object-oriented language (version 3.12)
|
|
1469
|
-
Python is a high-level, interactive, object-oriented language. Its 3.12 version
|
|
1470
|
-
includes an extensive class library.
|
|
1471
|
-
|
|
1472
|
-
Package: gcc-13
|
|
1473
|
-
Status: install ok installed
|
|
1474
|
-
Priority: optional
|
|
1475
|
-
Section: devel
|
|
1476
|
-
Installed-Size: 70460
|
|
1477
|
-
Maintainer: Fortune GCC Maintainers <gcc@fortune.local>
|
|
1478
|
-
Architecture: amd64
|
|
1479
|
-
Version: 13.3.0-6nyx1
|
|
1480
|
-
Depends: cpp-13 (= 13.3.0-6nyx1), gcc-13-base (= 13.3.0-6nyx1)
|
|
1481
|
-
Description: GNU C compiler
|
|
1482
|
-
This is the GNU C compiler, a fairly portable optimizing compiler for C.
|
|
1483
|
-
|
|
1484
|
-
Package: openjdk-21-jre-headless
|
|
1485
|
-
Status: install ok installed
|
|
1486
|
-
Priority: optional
|
|
1487
|
-
Section: java
|
|
1488
|
-
Installed-Size: 174488
|
|
1489
|
-
Maintainer: Fortune Maintainers <maintainers@fortune.local>
|
|
1490
|
-
Architecture: amd64
|
|
1491
|
-
Version: 21.0.10+7-1~nyx
|
|
1492
|
-
Depends: libc6 (>= 2.17), libgcc-s1 (>= 3.4)
|
|
1493
|
-
Description: OpenJDK Java runtime, using Hotspot JIT (headless)
|
|
1494
|
-
Minimal Java runtime - needed for executing non-graphical Java programs.
|
|
1495
|
-
|
|
1496
|
-
Package: curl
|
|
1497
|
-
Status: install ok installed
|
|
1498
|
-
Priority: standard
|
|
1499
|
-
Section: web
|
|
1500
|
-
Installed-Size: 544
|
|
1501
|
-
Maintainer: Fortune Maintainers <maintainers@fortune.local>
|
|
1502
|
-
Architecture: amd64
|
|
1503
|
-
Version: 8.5.0-2nyx1
|
|
1504
|
-
Depends: libcurl4 (= 8.5.0-2nyx1), zlib1g (>= 1:1.1.4)
|
|
1505
|
-
Description: command line tool for transferring data with URL syntax
|
|
1506
|
-
curl is a command line tool for transferring data with URL syntax, supporting
|
|
1507
|
-
DICT, FILE, FTP, FTPS, GOPHER, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, POP3,
|
|
1508
|
-
POP3S, RTMP, RTSP, SCP, SFTP, SMTP, SMTPS, TELNET and TFTP.
|
|
1509
|
-
|
|
1510
|
-
Package: git
|
|
1511
|
-
Status: install ok installed
|
|
1512
|
-
Priority: optional
|
|
1513
|
-
Section: vcs
|
|
1514
|
-
Installed-Size: 36552
|
|
1515
|
-
Maintainer: Fortune VCS Team <vcs@fortune.local>
|
|
1516
|
-
Architecture: amd64
|
|
1517
|
-
Version: 1:2.43.0-1nyx1
|
|
1518
|
-
Depends: liberror-perl, git-man, libc6 (>= 2.34), libcurl3-gnutls
|
|
1519
|
-
Description: fast, scalable, distributed revision control system
|
|
1520
|
-
Git is popular version control system designed to handle very large projects
|
|
1521
|
-
with speed and efficiency; it is used mainly for various open source projects.
|
|
1522
|
-
|
|
1523
|
-
Package: openssl
|
|
1524
|
-
Status: install ok installed
|
|
1525
|
-
Priority: optional
|
|
1526
|
-
Section: utils
|
|
1527
|
-
Installed-Size: 1320
|
|
1528
|
-
Maintainer: Fortune Security Team <security@fortune.local>
|
|
1529
|
-
Architecture: amd64
|
|
1530
|
-
Version: 3.0.13-0nyx1
|
|
1531
|
-
Depends: libssl3 (>= 3.0.13)
|
|
1532
|
-
Description: Secure Sockets Layer toolkit - cryptographic utility
|
|
1533
|
-
This package is part of the OpenSSL project's implementation of the SSL and TLS
|
|
1534
|
-
cryptographic protocols and related technologies.
|
|
1535
|
-
|
|
1536
|
-
Package: wget
|
|
1537
|
-
Status: install ok installed
|
|
1538
|
-
Priority: standard
|
|
1539
|
-
Section: web
|
|
1540
|
-
Installed-Size: 1100
|
|
1541
|
-
Maintainer: Fortune Maintainers <maintainers@fortune.local>
|
|
1542
|
-
Architecture: amd64
|
|
1543
|
-
Version: 1.21.4-1nyx1
|
|
1544
|
-
Depends: libc6 (>= 2.17), libgnutls30 (>= 3.7.9), libidn2-0 (>= 2.0.0)
|
|
1545
|
-
Description: retrieves files from the web
|
|
1546
|
-
GNU Wget is a program for retrieving files from the web, supporting the HTTP,
|
|
1547
|
-
HTTPS and FTP protocols.
|
|
1548
|
-
|
|
1549
|
-
Package: make
|
|
1550
|
-
Status: install ok installed
|
|
1551
|
-
Priority: optional
|
|
1552
|
-
Section: devel
|
|
1553
|
-
Installed-Size: 556
|
|
1554
|
-
Maintainer: Fortune Maintainers <maintainers@fortune.local>
|
|
1555
|
-
Architecture: amd64
|
|
1556
|
-
Version: 4.3-4.1nyx1
|
|
1557
|
-
Depends: libc6 (>= 2.17)
|
|
1558
|
-
Description: utility for directing compilation
|
|
1559
|
-
GNU Make is a utility which controls the generation of executables and other
|
|
1560
|
-
target files of a program from the program's source files.
|
|
1561
|
-
|
|
1562
|
-
Package: ffmpeg
|
|
1563
|
-
Status: install ok installed
|
|
1564
|
-
Priority: optional
|
|
1565
|
-
Section: video
|
|
1566
|
-
Installed-Size: 2184
|
|
1567
|
-
Maintainer: Fortune Multimedia Team <multimedia@fortune.local>
|
|
1568
|
-
Architecture: amd64
|
|
1569
|
-
Version: 7:6.1.1-3nyx1
|
|
1570
|
-
Depends: libavcodec60, libavdevice60, libavfilter9, libavformat60, libavutil58
|
|
1571
|
-
Description: Tools for transcoding, streaming and playing of multimedia files
|
|
1572
|
-
FFmpeg is a complete, cross-platform solution to record, convert and stream
|
|
1573
|
-
audio and video.
|
|
1574
|
-
|
|
1575
|
-
Package: pandoc
|
|
1576
|
-
Status: install ok installed
|
|
1577
|
-
Priority: optional
|
|
1578
|
-
Section: text
|
|
1579
|
-
Installed-Size: 96248
|
|
1580
|
-
Maintainer: Fortune Haskell Group <haskell@fortune.local>
|
|
1581
|
-
Architecture: amd64
|
|
1582
|
-
Version: 3.1.3+ds-2
|
|
1583
|
-
Depends: libgmp10, libgcc-s1, libffi8
|
|
1584
|
-
Description: general markup converter
|
|
1585
|
-
Pandoc is a Haskell library for converting from one markup format to another.
|
|
1586
|
-
|
|
1587
|
-
Package: tesseract-ocr
|
|
1588
|
-
Status: install ok installed
|
|
1589
|
-
Priority: optional
|
|
1590
|
-
Section: graphics
|
|
1591
|
-
Installed-Size: 1736
|
|
1592
|
-
Maintainer: Fortune OCR Team <ocr@fortune.local>
|
|
1593
|
-
Architecture: amd64
|
|
1594
|
-
Version: 5.3.4-1build5
|
|
1595
|
-
Depends: libc6 (>= 2.14), libleptonica-dev
|
|
1596
|
-
Description: Tesseract Open Source OCR Engine
|
|
1597
|
-
Tesseract is an Open Source OCR Engine, originally developed by HP and now
|
|
1598
|
-
sponsored by Google.
|
|
1599
|
-
|
|
1600
|
-
Package: dpkg
|
|
1601
|
-
Status: install ok installed
|
|
1602
|
-
Priority: required
|
|
1603
|
-
Section: admin
|
|
1604
|
-
Installed-Size: 6800
|
|
1605
|
-
Maintainer: Fortune Package Team <dpkg@fortune.local>
|
|
1606
|
-
Architecture: amd64
|
|
1607
|
-
Version: 1.22.6nyx1
|
|
1608
|
-
Depends: libc6 (>= 2.17), libzstd1 (>= 1.5.5)
|
|
1609
|
-
Description: Fortune package management system
|
|
1610
|
-
This package provides the low-level infrastructure for handling the
|
|
1611
|
-
installation and removal of Fortune software packages.
|
|
1612
|
-
|
|
1613
|
-
Package: apt
|
|
1614
|
-
Status: install ok installed
|
|
1615
|
-
Priority: important
|
|
1616
|
-
Section: admin
|
|
1617
|
-
Installed-Size: 4236
|
|
1618
|
-
Maintainer: Fortune Package Team <apt@fortune.local>
|
|
1619
|
-
Architecture: amd64
|
|
1620
|
-
Version: 2.8.3nyx1
|
|
1621
|
-
Depends: libapt-pkg6.0 (>= 2.8.3), adduser, gpgv
|
|
1622
|
-
Description: commandline package manager
|
|
1623
|
-
This package provides commandline tools for searching and managing as well as
|
|
1624
|
-
querying information about packages as a low-level access to all features of
|
|
1625
|
-
the libapt-pkg library.
|
|
1626
|
-
|
|
1627
|
-
Package: systemd
|
|
1628
|
-
Status: install ok installed
|
|
1629
|
-
Priority: optional
|
|
1630
|
-
Section: admin
|
|
1631
|
-
Installed-Size: 36476
|
|
1632
|
-
Maintainer: Fortune System Team <systemd@fortune.local>
|
|
1633
|
-
Architecture: amd64
|
|
1634
|
-
Version: 255.4-1nyx1
|
|
1635
|
-
Depends: libacl1 (>= 2.2.23), libblkid1 (>= 2.24), libc6 (>= 2.39)
|
|
1636
|
-
Description: system and service manager
|
|
1637
|
-
systemd is a system and service manager for Linux. It provides aggressive
|
|
1638
|
-
parallelization capabilities, uses socket and D-Bus activation for starting
|
|
1639
|
-
services, offers on-demand starting of daemons, keeps track of processes using
|
|
1640
|
-
Linux cgroups, maintains mount and automount points, and implements an
|
|
1641
|
-
elaborate transactional dependency-based service control logic.
|
|
1642
|
-
|
|
1643
|
-
Package: nano
|
|
1644
|
-
Status: install ok installed
|
|
1645
|
-
Priority: important
|
|
1646
|
-
Section: editors
|
|
1647
|
-
Installed-Size: 888
|
|
1648
|
-
Maintainer: Fortune Maintainers <maintainers@fortune.local>
|
|
1649
|
-
Architecture: amd64
|
|
1650
|
-
Version: 7.2-2
|
|
1651
|
-
Depends: libc6 (>= 2.17), libncursesw6 (>= 6)
|
|
1652
|
-
Description: small, friendly text editor inspired by Pico
|
|
1653
|
-
GNU nano is an easy-to-use text editor originally designed as a replacement
|
|
1654
|
-
for Pico, the ncurses-based editor from the non-free mailer package Pine.
|
|
1655
|
-
|
|
1656
|
-
Package: less
|
|
1657
|
-
Status: install ok installed
|
|
1658
|
-
Priority: important
|
|
1659
|
-
Section: text
|
|
1660
|
-
Installed-Size: 344
|
|
1661
|
-
Maintainer: Fortune Maintainers <maintainers@fortune.local>
|
|
1662
|
-
Architecture: amd64
|
|
1663
|
-
Version: 1:640-2build2
|
|
1664
|
-
Depends: libc6 (>= 2.17), libtinfo6 (>= 6)
|
|
1665
|
-
Description: pager program similar to more
|
|
1666
|
-
This package provides the \`less\` command, which is similar to more but allows
|
|
1667
|
-
you to move backwards through the file.
|
|
1668
|
-
|
|
1669
|
-
`;
|
|
1670
|
-
|
|
1671
|
-
function bootstrapVar(vfs: VirtualFileSystem): void {
|
|
1672
|
-
ensureDir(vfs, "/var");
|
|
1673
|
-
ensureDir(vfs, "/var/log");
|
|
1674
|
-
ensureDir(vfs, "/var/log/apt");
|
|
1675
|
-
ensureDir(vfs, "/var/log/journal");
|
|
1676
|
-
ensureDir(vfs, "/var/log/private");
|
|
1677
|
-
ensureDir(vfs, "/var/tmp");
|
|
1678
|
-
ensureDir(vfs, "/var/cache");
|
|
1679
|
-
ensureDir(vfs, "/var/cache/apt");
|
|
1680
|
-
ensureDir(vfs, "/var/cache/apt/archives");
|
|
1681
|
-
ensureDir(vfs, "/var/cache/apt/archives/partial");
|
|
1682
|
-
ensureDir(vfs, "/var/cache/debconf");
|
|
1683
|
-
ensureDir(vfs, "/var/cache/ldconfig");
|
|
1684
|
-
ensureDir(vfs, "/var/cache/fontconfig");
|
|
1685
|
-
ensureDir(vfs, "/var/cache/PackageKit");
|
|
1686
|
-
ensureDir(vfs, "/var/lib");
|
|
1687
|
-
ensureDir(vfs, "/var/lib/apt");
|
|
1688
|
-
ensureDir(vfs, "/var/lib/apt/lists");
|
|
1689
|
-
ensureDir(vfs, "/var/lib/apt/lists/partial");
|
|
1690
|
-
ensureDir(vfs, "/var/lib/dpkg");
|
|
1691
|
-
ensureDir(vfs, "/var/lib/dpkg/info");
|
|
1692
|
-
ensureDir(vfs, "/var/lib/dpkg/updates");
|
|
1693
|
-
ensureDir(vfs, "/var/lib/dpkg/alternatives");
|
|
1694
|
-
ensureDir(vfs, "/var/lib/misc");
|
|
1695
|
-
ensureDir(vfs, "/var/lib/systemd");
|
|
1696
|
-
ensureDir(vfs, "/var/lib/systemd/coredump");
|
|
1697
|
-
ensureDir(vfs, "/var/lib/pam");
|
|
1698
|
-
ensureDir(vfs, "/var/lib/git");
|
|
1699
|
-
ensureDir(vfs, "/var/lib/PackageKit");
|
|
1700
|
-
ensureDir(vfs, "/var/lib/python");
|
|
1701
|
-
ensureDir(vfs, "/var/spool");
|
|
1702
|
-
ensureDir(vfs, "/var/spool/cron");
|
|
1703
|
-
ensureDir(vfs, "/var/spool/mail");
|
|
1704
|
-
ensureDir(vfs, "/var/mail");
|
|
1705
|
-
ensureDir(vfs, "/var/backups");
|
|
1706
|
-
ensureDir(vfs, "/var/www");
|
|
1707
|
-
|
|
1708
|
-
// dpkg status — realistic package database
|
|
1709
|
-
ensureFile(vfs, "/var/lib/dpkg/status", DPKG_STATUS);
|
|
1710
|
-
ensureFile(vfs, "/var/lib/dpkg/available", "");
|
|
1711
|
-
ensureFile(vfs, "/var/lib/dpkg/lock", "");
|
|
1712
|
-
ensureFile(vfs, "/var/lib/dpkg/lock-frontend", "");
|
|
1713
|
-
|
|
1714
|
-
// apt state
|
|
1715
|
-
ensureFile(vfs, "/var/lib/apt/lists/lock", "");
|
|
1716
|
-
ensureFile(vfs, "/var/cache/apt/pkgcache.bin", "");
|
|
1717
|
-
ensureFile(vfs, "/var/cache/apt/srcpkgcache.bin", "");
|
|
1718
|
-
|
|
1719
|
-
// syslog stubs
|
|
1720
|
-
ensureFile(vfs, "/var/log/syslog",
|
|
1721
|
-
`${new Date().toUTCString()} ${""} kernel: Virtual container started\n`,
|
|
1722
|
-
);
|
|
1723
|
-
ensureFile(vfs, "/var/log/auth.log", "");
|
|
1724
|
-
ensureFile(vfs, "/var/log/kern.log", "");
|
|
1725
|
-
ensureFile(vfs, "/var/log/dpkg.log", "");
|
|
1726
|
-
ensureFile(vfs, "/var/log/apt/history.log", "");
|
|
1727
|
-
ensureFile(vfs, "/var/log/apt/term.log", "");
|
|
1728
|
-
ensureFile(vfs, "/var/log/faillog", "");
|
|
1729
|
-
ensureFile(vfs, "/var/log/lastlog", "");
|
|
1730
|
-
ensureFile(vfs, "/var/log/wtmp", "");
|
|
1731
|
-
ensureFile(vfs, "/var/log/btmp", "");
|
|
1732
|
-
ensureFile(vfs, "/var/log/alternatives.log", "");
|
|
1733
|
-
|
|
1734
|
-
// /run
|
|
1735
|
-
ensureDir(vfs, "/run");
|
|
1736
|
-
ensureDir(vfs, "/run/lock");
|
|
1737
|
-
ensureDir(vfs, "/run/lock/subsys");
|
|
1738
|
-
ensureDir(vfs, "/run/systemd");
|
|
1739
|
-
ensureDir(vfs, "/run/systemd/ask-password");
|
|
1740
|
-
ensureDir(vfs, "/run/systemd/sessions");
|
|
1741
|
-
ensureDir(vfs, "/run/systemd/users");
|
|
1742
|
-
ensureDir(vfs, "/run/user");
|
|
1743
|
-
ensureDir(vfs, "/run/dbus");
|
|
1744
|
-
ensureDir(vfs, "/run/adduser");
|
|
1745
|
-
ensureFile(vfs, "/run/utmp", "");
|
|
1746
|
-
ensureFile(vfs, "/run/dbus/system_bus_socket", "");
|
|
1747
|
-
}
|
|
1748
|
-
|
|
1749
|
-
// ─── /bin + /sbin symlinks ────────────────────────────────────────────────────
|
|
1750
|
-
|
|
1751
|
-
function bootstrapBin(vfs: VirtualFileSystem): void {
|
|
1752
|
-
// Modern Fortune Nyx: /bin and /sbin are symlinks to /usr/bin and /usr/sbin
|
|
1753
|
-
if (!vfs.exists("/bin")) vfs.symlink("/usr/bin", "/bin");
|
|
1754
|
-
if (!vfs.exists("/sbin")) vfs.symlink("/usr/sbin", "/sbin");
|
|
1755
|
-
|
|
1756
|
-
// /var/run → /run (systemd compat)
|
|
1757
|
-
if (!vfs.exists("/var/run")) vfs.symlink("/run", "/var/run");
|
|
1758
|
-
|
|
1759
|
-
ensureDir(vfs, "/lib");
|
|
1760
|
-
ensureDir(vfs, "/lib64");
|
|
1761
|
-
ensureDir(vfs, "/lib/x86_64-linux-gnu");
|
|
1762
|
-
ensureDir(vfs, "/lib/modules");
|
|
1763
|
-
|
|
1764
|
-
// lib64 symlink (standard on x86_64)
|
|
1765
|
-
if (!vfs.exists("/lib64/ld-linux-x86-64.so.2")) {
|
|
1766
|
-
ensureFile(vfs, "/lib64/ld-linux-x86-64.so.2", "", 0o755);
|
|
1767
|
-
}
|
|
1768
|
-
}
|
|
1769
|
-
|
|
1770
|
-
// ─── /tmp ─────────────────────────────────────────────────────────────────────
|
|
1771
|
-
|
|
1772
|
-
function bootstrapTmp(vfs: VirtualFileSystem): void {
|
|
1773
|
-
ensureDir(vfs, "/tmp", 0o1777);
|
|
1774
|
-
// node compile cache dir (present in real env)
|
|
1775
|
-
ensureDir(vfs, "/tmp/node-compile-cache", 0o1777);
|
|
1776
|
-
}
|
|
1777
|
-
|
|
1778
|
-
// ─── /root home ───────────────────────────────────────────────────────────────
|
|
1779
|
-
|
|
1780
|
-
function bootstrapRoot(vfs: VirtualFileSystem): void {
|
|
1781
|
-
ensureDir(vfs, "/root", 0o700);
|
|
1782
|
-
ensureDir(vfs, "/root/.ssh", 0o700);
|
|
1783
|
-
ensureDir(vfs, "/root/.config", 0o755);
|
|
1784
|
-
ensureDir(vfs, "/root/.config/pip", 0o755);
|
|
1785
|
-
ensureDir(vfs, "/root/.local", 0o755);
|
|
1786
|
-
ensureDir(vfs, "/root/.local/share", 0o755);
|
|
1787
|
-
ensureFile(
|
|
1788
|
-
vfs,
|
|
1789
|
-
"/root/.bashrc",
|
|
1790
|
-
`${[
|
|
1791
|
-
"# root .bashrc",
|
|
1792
|
-
"export PS1='\\[\\033[0;31m\\]\\u@\\h\\[\\033[0m\\]:\\[\\033[0;34m\\]\\w\\[\\033[0m\\]# '",
|
|
1793
|
-
"export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
|
1794
|
-
"export LANG=en_US.UTF-8",
|
|
1795
|
-
"alias ll='ls -la'",
|
|
1796
|
-
"alias la='ls -A'",
|
|
1797
|
-
"alias l='ls -CF'",
|
|
1798
|
-
].join("\n")}\n`,
|
|
1799
|
-
);
|
|
1800
|
-
ensureFile(vfs, "/root/.profile",
|
|
1801
|
-
"[ -f ~/.bashrc ] && . ~/.bashrc\n",
|
|
1802
|
-
);
|
|
1803
|
-
ensureFile(vfs, "/root/.bash_logout",
|
|
1804
|
-
"# ~/.bash_logout\n",
|
|
1805
|
-
);
|
|
1806
|
-
ensureFile(vfs, "/root/.config/pip/pip.conf",
|
|
1807
|
-
"[global]\nbreak-system-packages = true\n",
|
|
1808
|
-
);
|
|
1809
|
-
}
|
|
1810
|
-
|
|
1811
|
-
// ─── /opt /srv /mnt /media ────────────────────────────────────────────────────
|
|
1812
|
-
|
|
1813
|
-
function bootstrapMisc(vfs: VirtualFileSystem, props: ShellProperties): void {
|
|
1814
|
-
ensureDir(vfs, "/opt");
|
|
1815
|
-
ensureDir(vfs, "/opt/rclone");
|
|
1816
|
-
ensureDir(vfs, "/srv");
|
|
1817
|
-
ensureDir(vfs, "/mnt");
|
|
1818
|
-
ensureDir(vfs, "/media");
|
|
1819
|
-
|
|
1820
|
-
// /boot — no kernel images in Firecracker containers (kernel is external),
|
|
1821
|
-
// but maintain the directory structure for tool compatibility
|
|
1822
|
-
ensureDir(vfs, "/boot");
|
|
1823
|
-
ensureDir(vfs, "/boot/grub");
|
|
1824
|
-
ensureFile(vfs, "/boot/grub/grub.cfg",
|
|
1825
|
-
`${[
|
|
1826
|
-
"# GRUB configuration (virtual)",
|
|
1827
|
-
"set default=0",
|
|
1828
|
-
"set timeout=0",
|
|
1829
|
-
"",
|
|
1830
|
-
`menuentry "Fortune GNU/Linux" {`,
|
|
1831
|
-
` linux /vmlinuz-${props.kernel} root=/dev/vda rw console=ttyS0`,
|
|
1832
|
-
` initrd /initrd.img-${props.kernel}`,
|
|
1833
|
-
`}`,
|
|
1834
|
-
].join("\n")}\n`,
|
|
1835
|
-
);
|
|
1836
|
-
|
|
1837
|
-
const kver = props.kernel;
|
|
1838
|
-
ensureFile(vfs, `/boot/vmlinuz-${kver}`, "", 0o644);
|
|
1839
|
-
ensureFile(vfs, `/boot/initrd.img-${kver}`, "", 0o644);
|
|
1840
|
-
ensureFile(vfs, `/boot/System.map-${kver}`, `${kver} virtual\n`, 0o644);
|
|
1841
|
-
ensureFile(vfs, `/boot/config-${kver}`, `# Linux kernel config ${kver}\nCONFIG_VIRTIO=y\nCONFIG_VIRTIO_BLK=y\nCONFIG_VIRTIO_NET=y\nCONFIG_KVM_GUEST=y\n`, 0o644);
|
|
1842
|
-
|
|
1843
|
-
if (!vfs.exists("/vmlinuz")) vfs.symlink(`/boot/vmlinuz-${kver}`, "/vmlinuz");
|
|
1844
|
-
if (!vfs.exists("/vmlinuz.old")) vfs.symlink(`/boot/vmlinuz-${kver}`, "/vmlinuz.old");
|
|
1845
|
-
if (!vfs.exists("/initrd.img")) vfs.symlink(`/boot/initrd.img-${kver}`,"/initrd.img");
|
|
1846
|
-
if (!vfs.exists("/initrd.img.old")) vfs.symlink(`/boot/initrd.img-${kver}`,"/initrd.img.old");
|
|
1847
|
-
|
|
1848
|
-
// No /snap — not present in Firecracker container
|
|
1849
|
-
// /proc/cmdline confirms: no snapd boot args
|
|
1850
|
-
|
|
1851
|
-
// /lost+found — ext4 recovery
|
|
1852
|
-
ensureDir(vfs, "/lost+found", 0o700);
|
|
1853
|
-
|
|
1854
|
-
// /home — users managed by bootstrapRoot + syncEtcPasswd
|
|
1855
|
-
ensureDir(vfs, "/home");
|
|
1856
|
-
}
|
|
1857
|
-
|
|
1858
|
-
// ── Static rootfs snapshot cache ─────────────────────────────────────────────
|
|
1859
|
-
|
|
1860
|
-
const _staticRootfsCache = new Map<string, Buffer>();
|
|
1861
|
-
|
|
1862
|
-
function _staticCacheKey(hostname: string, props: ShellProperties): string {
|
|
1863
|
-
return `${hostname}|${props.kernel}|${props.os}|${props.arch}`;
|
|
1864
|
-
}
|
|
1865
|
-
|
|
1866
|
-
/**
|
|
1867
|
-
* Build or retrieve the static rootfs VFSB snapshot for the given
|
|
1868
|
-
* hostname + ShellProperties combination.
|
|
1869
|
-
*
|
|
1870
|
-
* Subsequent calls with the same key return the cached Buffer in ~0ms.
|
|
1871
|
-
*/
|
|
1872
|
-
export function getStaticRootfsSnapshot(
|
|
1873
|
-
hostname: string,
|
|
1874
|
-
props: ShellProperties,
|
|
1875
|
-
): Buffer {
|
|
1876
|
-
const key = _staticCacheKey(hostname, props);
|
|
1877
|
-
const cached = _staticRootfsCache.get(key);
|
|
1878
|
-
if (cached) return cached;
|
|
1879
|
-
|
|
1880
|
-
const tmp = new VirtualFileSystem({ mode: "memory" });
|
|
1881
|
-
bootstrapEtc(tmp, hostname, props);
|
|
1882
|
-
bootstrapSys(tmp, hostname, props);
|
|
1883
|
-
bootstrapDev(tmp);
|
|
1884
|
-
bootstrapUsr(tmp);
|
|
1885
|
-
bootstrapVar(tmp);
|
|
1886
|
-
bootstrapBin(tmp);
|
|
1887
|
-
bootstrapTmp(tmp);
|
|
1888
|
-
bootstrapMisc(tmp, props);
|
|
1889
|
-
bootProcLog(tmp, props);
|
|
1890
|
-
|
|
1891
|
-
const snapshot = tmp.encodeBinary();
|
|
1892
|
-
_staticRootfsCache.set(key, snapshot);
|
|
1893
|
-
return snapshot;
|
|
1894
|
-
}
|
|
1895
|
-
|
|
1896
|
-
// ─── main entry point ─────────────────────────────────────────────────────────
|
|
1897
|
-
|
|
1898
|
-
/**
|
|
1899
|
-
* Bootstraps the full Linux rootfs hierarchy in the VFS.
|
|
1900
|
-
* Safe to call multiple times — idempotent.
|
|
1901
|
-
*
|
|
1902
|
-
* @param vfs Target virtual filesystem.
|
|
1903
|
-
* @param users User manager (for /etc/passwd sync).
|
|
1904
|
-
* @param hostname Virtual hostname.
|
|
1905
|
-
* @param props Shell properties (kernel, os, arch).
|
|
1906
|
-
* @param shellStartTime Unix ms of shell creation (for uptime).
|
|
1907
|
-
* @param sessions Active sessions (for /proc/<pid> population).
|
|
1908
|
-
*/
|
|
1909
|
-
export function bootstrapLinuxRootfs(
|
|
1910
|
-
vfs: VirtualFileSystem,
|
|
1911
|
-
users: VirtualUserManager,
|
|
1912
|
-
hostname: string,
|
|
1913
|
-
props: ShellProperties,
|
|
1914
|
-
shellStartTime: number,
|
|
1915
|
-
sessions: VirtualActiveSession[] = [],
|
|
1916
|
-
): void {
|
|
1917
|
-
const snapshot = getStaticRootfsSnapshot(hostname, props);
|
|
1918
|
-
const hasRestoredData = vfs.getMode() === "fs" && vfs.exists("/home");
|
|
1919
|
-
|
|
1920
|
-
if (hasRestoredData) {
|
|
1921
|
-
// Snapshot was already restored — merge static rootfs without
|
|
1922
|
-
// clobbering user files and directories.
|
|
1923
|
-
vfs.mergeRootTree(decodeVfs(snapshot));
|
|
1924
|
-
} else {
|
|
1925
|
-
// Fresh start — replace the empty tree with the full static rootfs.
|
|
1926
|
-
vfs.importRootTree(decodeVfs(snapshot));
|
|
1927
|
-
}
|
|
1928
|
-
|
|
1929
|
-
bootstrapRoot(vfs);
|
|
1930
|
-
refreshProc(vfs, props, hostname, shellStartTime, sessions);
|
|
1931
|
-
syncEtcPasswd(vfs, users);
|
|
1932
|
-
}
|
|
1933
|
-
|
|
1934
|
-
// ─── optional live engine ─────────────────────────────────────────────────────
|
|
1935
|
-
|
|
1936
|
-
/**
|
|
1937
|
-
* Engine for runtimes that want periodic /proc refresh (e.g. web shell
|
|
1938
|
-
* with live `top`/`ps` output). Call `.boot()` once, then `.tick()` on
|
|
1939
|
-
* each session change or on a timer.
|
|
1940
|
-
*
|
|
1941
|
-
* ```ts
|
|
1942
|
-
* const engine = createLinuxRootfsEngine(vfs, props, hostname, Date.now());
|
|
1943
|
-
* engine.boot(users, sessions);
|
|
1944
|
-
* setInterval(() => engine.tick(shell.listActiveSessions()), 5000);
|
|
1945
|
-
* ```
|
|
1946
|
-
*/
|
|
1947
|
-
export function createLinuxRootfsEngine(
|
|
1948
|
-
vfs: VirtualFileSystem,
|
|
1949
|
-
props: ShellProperties,
|
|
1950
|
-
hostname: string,
|
|
1951
|
-
startTime: number,
|
|
1952
|
-
) {
|
|
1953
|
-
return {
|
|
1954
|
-
boot(users: VirtualUserManager, sessions: VirtualActiveSession[] = []) {
|
|
1955
|
-
bootstrapLinuxRootfs(vfs, users, hostname, props, startTime, sessions);
|
|
1956
|
-
},
|
|
1957
|
-
tick(sessions: VirtualActiveSession[] = []) {
|
|
1958
|
-
refreshProc(vfs, props, hostname, startTime, sessions);
|
|
1959
|
-
},
|
|
1960
|
-
};
|
|
1961
|
-
}
|