@microck/raft 0.0.0-stage → 0.2.1

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.
Files changed (67) hide show
  1. package/.github/assets/raft-logo.png +0 -0
  2. package/LICENSE +21 -0
  3. package/README.md +167 -2
  4. package/deploy/benchmark-boot.py +150 -0
  5. package/deploy/build-image.py +95 -0
  6. package/deploy/deploy.py +176 -0
  7. package/deploy/incus-network.conf +4 -0
  8. package/deploy/install-incus.sh +22 -0
  9. package/deploy/raft-expire.py +62 -0
  10. package/deploy/raft-expire.service +8 -0
  11. package/deploy/raft-expire.timer +8 -0
  12. package/deploy/raft-network.service +12 -0
  13. package/deploy/raft-network.sh +40 -0
  14. package/deploy/verify-controls.py +241 -0
  15. package/deploy/verify-features.py +519 -0
  16. package/deploy/verify-fresh-host.py +301 -0
  17. package/deploy/verify-image-tests.py +139 -0
  18. package/deploy/verify-image.py +95 -0
  19. package/deploy/verify-limits.py +110 -0
  20. package/deploy/verify-live.py +903 -0
  21. package/deploy/verify-release.py +132 -0
  22. package/deploy/verify-tools.py +105 -0
  23. package/docs/benchmarks/amd64-native-ci.json +137 -0
  24. package/docs/benchmarks/arm64-baseline-a.json +108 -0
  25. package/docs/benchmarks/arm64-baseline-b.json +108 -0
  26. package/docs/benchmarks/arm64-candidate-a.json +109 -0
  27. package/docs/benchmarks/arm64-desktop-local.json +22 -0
  28. package/docs/benchmarks/arm64-native-ci.json +137 -0
  29. package/docs/boat-capabilities.md +64 -0
  30. package/docs/boat-parity-design.md +26 -0
  31. package/docs/boot-performance.mdx +102 -0
  32. package/docs/contract.md +93 -0
  33. package/docs/first-box.mdx +86 -0
  34. package/docs/guides/background-jobs.mdx +95 -0
  35. package/docs/guides/backup-recovery.mdx +111 -0
  36. package/docs/guides/desktop-services.mdx +90 -0
  37. package/docs/guides/docker.mdx +84 -0
  38. package/docs/guides/files.mdx +91 -0
  39. package/docs/guides/long-running-services.mdx +109 -0
  40. package/docs/guides/meta.json +18 -0
  41. package/docs/guides/project-setup.mdx +112 -0
  42. package/docs/guides/scripting-ci.mdx +133 -0
  43. package/docs/guides/snapshots-forks.mdx +107 -0
  44. package/docs/guides/troubleshooting.mdx +152 -0
  45. package/docs/guides/upgrades.mdx +113 -0
  46. package/docs/incus.example.json +3 -0
  47. package/docs/index.mdx +40 -0
  48. package/docs/meta.json +21 -0
  49. package/docs/operations.mdx +239 -0
  50. package/docs/publishing.md +48 -0
  51. package/docs/reference/capacity-limits.mdx +92 -0
  52. package/docs/reference/cli.md +288 -0
  53. package/docs/reference/configuration.mdx +77 -0
  54. package/docs/reference/meta.json +10 -0
  55. package/docs/releases/0.2.0.md +22 -0
  56. package/docs/releases/0.2.1.md +14 -0
  57. package/docs/requirements.mdx +47 -0
  58. package/docs/reviews/code-review-2026-10-06.md +168 -0
  59. package/docs/site-development.md +80 -0
  60. package/docs/verification.mdx +237 -0
  61. package/images/incus/build.sh +57 -0
  62. package/images/incus/desktop.sh +21 -0
  63. package/images/incus/raft-desktop.service +7 -0
  64. package/package.json +46 -4
  65. package/raft.py +961 -0
  66. package/raft_files.py +134 -0
  67. package/skills/raft-cli/SKILL.md +117 -0
@@ -0,0 +1,57 @@
1
+ #!/bin/bash
2
+ # Run inside a fresh native ARM64 or AMD64 Debian 13 Incus image, without host secrets.
3
+ set -eu
4
+ case "$(dpkg --print-architecture)" in
5
+ arm64) node_arch=arm64 ;;
6
+ amd64) node_arch=x64 ;;
7
+ *) echo 'Raft images support ARM64 and AMD64' >&2; exit 1 ;;
8
+ esac
9
+ export DEBIAN_FRONTEND=noninteractive
10
+ apt-get update -qq
11
+ apt-get install -y --no-install-recommends apparmor ca-certificates curl git openssh-server rsync jq ripgrep file less sudo locales python3 python3-pip python3-venv pipx build-essential clang cmake ninja-build golang rustc cargo default-jdk maven gradle kotlin scala ruby ruby-bundler php-cli composer erlang-base elixir r-base docker.io docker-cli docker-buildx chromium chromium-sandbox ffmpeg unzip xz-utils tar x11vnc xvfb x11-utils novnc websockify openbox dbus-x11
12
+ # Ubuntu hosts restrict unprofiled user namespaces. Load a guest-local rule
13
+ # for Chromium's exact executable so its sandbox can create its namespaces.
14
+ # Incus's outer confinement and the host-wide restriction remain in force.
15
+ cat > /etc/apparmor.d/raft-chromium <<'PROFILE'
16
+ abi <abi/4.0>,
17
+ include <tunables/global>
18
+ profile raft-chromium /usr/lib/chromium/chromium flags=(unconfined) {
19
+ userns,
20
+ }
21
+ PROFILE
22
+ systemctl enable apparmor
23
+ systemctl restart apparmor
24
+ mkdir -p /workspace /opt/raft
25
+ node_archive="node-v24.21.0-linux-${node_arch}.tar.xz"
26
+ curl -fsSL -A 'OpenAI File Downloader, XaiImageApiFetch/1.0' "https://nodejs.org/dist/v24.21.0/${node_archive}" -o /tmp/raft-node.tar.xz
27
+ curl -fsSL -A 'OpenAI File Downloader, XaiImageApiFetch/1.0' https://nodejs.org/dist/v24.21.0/SHASUMS256.txt -o /tmp/raft-node.sha256
28
+ cd /tmp
29
+ awk -v archive="$node_archive" '$2 == archive {print $1 " raft-node.tar.xz"}' raft-node.sha256 | sha256sum -c -
30
+ tar -xJf /tmp/raft-node.tar.xz -C /usr/local --strip-components=1
31
+ PIPX_HOME=/opt/raft/pipx PIPX_BIN_DIR=/usr/local/bin pipx install uv==0.12.23
32
+ npm install -g pnpm@12.9.1 bun@1.4.2 deno@2.9.6
33
+ curl -fsSL -A 'OpenAI File Downloader, XaiImageApiFetch/1.0' https://dot.net/v1/dotnet-install.sh -o /tmp/raft-dotnet-install.sh
34
+ bash /tmp/raft-dotnet-install.sh --version 10.0.401 --install-dir /usr/local/share/dotnet
35
+ ln -s /usr/local/share/dotnet/dotnet /usr/local/bin/dotnet
36
+ useradd -m -s /bin/bash developer
37
+ printf 'developer ALL=(ALL) NOPASSWD:ALL\n' > /etc/sudoers.d/raft-developer
38
+ chmod 440 /etc/sudoers.d/raft-developer
39
+ mkdir -p /etc/ssh/sshd_config.d /etc/systemd/system/ssh.service.d
40
+ printf 'PasswordAuthentication no\nKbdInteractiveAuthentication no\nPermitRootLogin prohibit-password\nHostKey /etc/ssh/ssh_host_ed25519_key\n' > /etc/ssh/sshd_config.d/00-raft.conf
41
+ # Generate keys before sshd validates them; published templates contain no host keys.
42
+ # Only the advertised Ed25519 key is needed; generating unused RSA keys slows first boot.
43
+ cat > /etc/systemd/system/ssh.service.d/raft-keys.conf <<'UNIT'
44
+ [Service]
45
+ ExecStartPre=
46
+ ExecStartPre=/bin/sh -ec 'test -f /etc/ssh/ssh_host_ed25519_key || ssh-keygen -q -t ed25519 -N "" -f /etc/ssh/ssh_host_ed25519_key'
47
+ ExecStartPre=/usr/sbin/sshd -t
48
+ UNIT
49
+ systemctl enable docker ssh
50
+ systemctl start docker
51
+ docker info --format '{{.ServerVersion}}'
52
+ dpkg-query -W > /opt/raft/packages.tsv
53
+ npm list -g --depth=0 --json > /opt/raft/npm-packages.json
54
+ apt-get clean
55
+ rm -rf /var/lib/apt/lists/* /tmp/raft-node* /tmp/raft-dotnet-install.sh /root/.npm/_cacache /root/.npm/_logs
56
+ rm -f /etc/ssh/ssh_host_*
57
+ truncate -s 0 /etc/machine-id
@@ -0,0 +1,21 @@
1
+ #!/bin/sh
2
+ set -eu
3
+ export DISPLAY=:99
4
+ Xvfb :99 -screen 0 1280x720x24 -nolisten tcp &
5
+ xvfb_pid=$!
6
+ trap 'kill "$xvfb_pid" 2>/dev/null || true' EXIT
7
+ # Start clients as soon as X accepts requests, rather than sleeping on every launch.
8
+ attempt=0
9
+ until xdpyinfo >/dev/null 2>&1; do
10
+ attempt=$((attempt + 1))
11
+ if [ "$attempt" -ge 100 ]; then
12
+ echo 'Xvfb did not become ready within five seconds' >&2
13
+ exit 1
14
+ fi
15
+ sleep 0.05
16
+ done
17
+ runuser -u developer -- env DISPLAY=:99 openbox &
18
+ # This dedicated Xvfb display has no login manager to wait for.
19
+ X11VNC_AVOID_WINDOWS=never x11vnc -display :99 -localhost -nopw -forever -shared -rfbport 5900 &
20
+ websockify --web=/usr/share/novnc 0.0.0.0:6080 127.0.0.1:5900 &
21
+ wait
@@ -0,0 +1,7 @@
1
+ [Unit]
2
+ Description=Private Raft desktop on demand
3
+ After=network.target
4
+ [Service]
5
+ ExecStart=/usr/local/bin/raft-desktop
6
+ Restart=on-failure
7
+ KillMode=control-group
package/package.json CHANGED
@@ -1,6 +1,48 @@
1
1
  {
2
2
  "name": "@microck/raft",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.2.1",
4
+ "description": "Self-hosted Linux workspaces powered by Incus, an open-source alternative to boat.dev",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/Microck/raft.git"
9
+ },
10
+ "homepage": "https://raft.micr.dev",
11
+ "bugs": {
12
+ "url": "https://github.com/Microck/raft/issues"
13
+ },
14
+ "bin": {
15
+ "raft": "raft.py"
16
+ },
17
+ "os": [
18
+ "linux"
19
+ ],
20
+ "files": [
21
+ "raft.py",
22
+ "raft_files.py",
23
+ "deploy/*.py",
24
+ "deploy/*.sh",
25
+ "deploy/*.conf",
26
+ "deploy/*.service",
27
+ "deploy/*.timer",
28
+ "docs/**/*.md",
29
+ "docs/**/*.mdx",
30
+ "docs/**/*.json",
31
+ "images/incus/*.sh",
32
+ "images/incus/*.service",
33
+ "skills/raft-cli/SKILL.md",
34
+ ".github/assets/raft-logo.png"
35
+ ],
36
+ "keywords": [
37
+ "raft",
38
+ "sandbox",
39
+ "incus",
40
+ "self-hosted",
41
+ "linux",
42
+ "cli"
43
+ ],
44
+ "publishConfig": {
45
+ "access": "public",
46
+ "provenance": true
47
+ }
48
+ }