Repository navigation
Expand file tree
/
Copy pathinstall.sh
More file actions
executable file
·156 lines (141 loc) · 7.48 KB
/
Copy pathinstall.sh
File metadata and controls
executable file
·156 lines (141 loc) · 7.48 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#!/bin/sh
# kern installer - downloads the latest prebuilt static binary for this platform.
#
# curl -fsSL https://getkern.dev/install.sh | sh
#
# Honors:
# KERN_INSTALL_DIR where to install (default: ~/.local/bin, or /usr/local/bin as root)
# KERN_VERSION a specific tag, e.g. v0.3.0 (default: latest)
# No dependencies beyond a POSIX shell, curl (or wget), tar, and sha256sum (optional, for
# integrity verification). Linux only - kern is a Linux sandbox.
set -eu
REPO="getkern/kern"
RED='\033[0;31m'; GRN='\033[0;32m'; DIM='\033[2m'; ZZ='\033[0m'
err() { printf "${RED}error${ZZ}: %s\n" "$1" >&2; exit 1; }
info() { printf "${GRN}==>${ZZ} %s\n" "$1"; }
# --- platform detection ---
os="$(uname -s)"
# Darwin gets its own message rather than the generic one: it is the single point where a Mac user
# meets kern, and "Linux-only" alone reads as a dead end. There is no native port and there will not
# be one (macOS has no namespaces or cgroups), but kern runs unchanged in any Linux VM, so the error
# hands over the four commands that get there instead of just closing the door.
case "$os" in
Linux) ;;
Darwin)
# Look before prescribing. Telling a Mac that already runs OrbStack or Docker Desktop to install
# colima is asking for a second VM to do what the first one is doing right now, and it is the
# most common shape: someone who wants a container runtime usually has one running already. So
# name the Linux the machine ALREADY has, and keep the install line for a Mac that has none.
have=""
for vm in colima limactl orb docker; do
command -v "$vm" >/dev/null 2>&1 && have="$have $vm"
done
if [ -n "$have" ]; then
# Presence, not function, and deliberately: `docker info` on a Mac whose Docker Desktop is not
# running can take seconds, and this is an ERROR path that has already failed the user once.
# So the message never claims the VM is up, it says what to do in either case.
route="This Mac has a Linux VM installed (${have# }). Start it if it is not running, and use
it rather than installing a second one:
colima ssh # colima. For Lima: limactl shell <instance>
docker run --rm -it --privileged --tmpfs /run ubuntu # OrbStack / Docker Desktop
then run this installer again inside it. --privileged is privilege INSIDE that VM, which is
already a boundary against macOS, and it is needed because a box mounts its own /proc."
else
route="No Linux VM was found on this Mac. One way to get one:
brew install colima
colima start
colima ssh
curl -fsSL https://raw.githubusercontent.com/getkern/kern/main/install.sh | sh"
fi
err "kern is Linux-only (detected Darwin), and a native macOS port is a non-goal: macOS has no
namespaces and no cgroups, so there is nothing for kern to build a box out of.
$route
No GPU and no GPIO are reachable from a Linux guest on a Mac. See docs/INSTALL.md."
;;
*) err "kern is Linux-only (detected $os)." ;;
esac
case "$(uname -m)" in
x86_64 | amd64) arch="x86_64-unknown-linux-musl" ;;
aarch64 | arm64) arch="aarch64-unknown-linux-musl" ;;
*) err "unsupported architecture: $(uname -m) (x86_64 and aarch64 are published)." ;;
esac
# --- downloader ---
# The IPv4 retry is not paranoia: inside a WSL2 distro whose curl is built against c-ares (Alpine's
# is), an AAAA lookup against the WSL NAT resolver can go unanswered while the A record resolves
# perfectly. curl then reports "Could not resolve host" for a name that `getent hosts` resolves a
# second later, which reads as a broken installer rather than a broken lookup. Measured on Windows 10
# 22H2: the same URL fails plain and returns 200 with --ipv4. One retry, and it says why.
if command -v curl >/dev/null 2>&1; then
dl() {
curl -fsSL "$1" -o "$2" && return 0
echo " download failed, retrying over IPv4 only (some WSL/musl resolvers stall on AAAA)" >&2
curl -fsSL --ipv4 "$1" -o "$2"
}
elif command -v wget >/dev/null 2>&1; then
dl() {
wget -qO "$2" "$1" && return 0
echo " download failed, retrying over IPv4 only (some WSL/musl resolvers stall on AAAA)" >&2
wget -qO "$2" -4 "$1"
}
else
err "need curl or wget to download."
fi
ver="${KERN_VERSION:-latest}"
asset="kern-${arch}.tar.gz"
if [ "$ver" = "latest" ]; then
base="https://github.com/${REPO}/releases/latest/download"
else
base="https://github.com/${REPO}/releases/download/${ver}"
fi
# --- install dir ---
if [ -n "${KERN_INSTALL_DIR:-}" ]; then
bindir="$KERN_INSTALL_DIR"
elif [ "$(id -u)" = "0" ]; then
bindir="/usr/local/bin"
else
bindir="$HOME/.local/bin"
fi
tmp="$(mktemp -d)"
trap 'rm -rf "$tmp"' EXIT INT TERM
info "downloading ${asset} (${ver})"
dl "${base}/${asset}" "${tmp}/${asset}" || err "download failed - is ${ver} published for ${arch}?"
# --- integrity (best-effort: verify if the checksum asset and sha256sum are both available) ---
if command -v sha256sum >/dev/null 2>&1 && dl "${base}/${asset}.sha256" "${tmp}/${asset}.sha256" 2>/dev/null; then
want="$(awk '{print $1}' "${tmp}/${asset}.sha256")"
got="$(sha256sum "${tmp}/${asset}" | awk '{print $1}')"
[ "$want" = "$got" ] || err "checksum mismatch (expected $want, got $got)."
info "checksum verified"
else
printf "${DIM} (skipping checksum verification)${ZZ}\n"
fi
info "installing to ${bindir}"
mkdir -p "$bindir"
tar -C "$tmp" -xzf "${tmp}/${asset}"
install -m755 "${tmp}/kern" "${bindir}/kern"
info "installed $("${bindir}/kern" --version)"
case ":${PATH}:" in
*":${bindir}:"*)
# On PATH is not the same as FIRST on PATH. An older kern in /usr/local/bin keeps winning, so
# `kern --version` reports the old one and the install looks like it did nothing. Say which file
# actually answers, and only when it is not the one just written.
winner=$(command -v kern 2>/dev/null || true)
if [ -n "$winner" ] && [ "$winner" != "${bindir}/kern" ]; then
printf "${DIM} note: \`kern\` still resolves to ${winner} ($("$winner" --version 2>/dev/null || echo 'unknown version')) - it comes earlier on your PATH${ZZ}\n"
printf "${DIM} to use the one just installed: export PATH=\"${bindir}:\$PATH\" (or remove ${winner})${ZZ}\n"
fi
;;
*) printf "${DIM} ${bindir} is not on your PATH - add: export PATH=\"${bindir}:\$PATH\"${ZZ}\n" ;;
esac
# THE ONE HOST POLICY THAT MAKES THE NEXT COMMAND FAIL, said HERE rather than left for the reader to
# discover from a syscall name. Ubuntu 23.10+ ships `kernel.apparmor_restrict_unprivileged_userns=1`,
# which grants the user namespace and refuses its rootless id map, so no box starts at all. MEASURED
# on a stock Ubuntu 24.04.4 cloud image: install succeeds, and the first command in the README fails.
# The installer cannot fix it (the remedies need root, and this script may be piped into a plain sh),
# but a reader who is told before trying loses a minute instead of an evening.
if [ "$(cat /proc/sys/kernel/apparmor_restrict_unprivileged_userns 2>/dev/null || echo 0)" = "1" ]; then
printf "\n${DIM} note: this host restricts unprivileged user namespaces (Ubuntu 23.10+ default),${ZZ}\n"
printf "${DIM} which lets the namespace be created and refuses its uid map - no box can start yet.${ZZ}\n"
printf "${DIM} install the profile kern carries, which keeps the restriction on for everything else:${ZZ}\n"
printf " ${bindir}/kern doctor --apparmor-profile | sudo tee /etc/apparmor.d/kern >/dev/null && sudo apparmor_parser -r /etc/apparmor.d/kern\n"
printf "${DIM} then \`${bindir}/kern doctor\` should say ready. Full explanation: \`kern doctor\`.${ZZ}\n\n"
fi