Initial commit
This commit is contained in:
commit
afed023152
8152 files changed
+2086461
No files matched your search
+134
@@ -0,0 +1,134 @@
|
||||
#!/bin/bash
|
||||
# Published prod installer with reviewed signing keys and compatible, completed releases.
|
||||
set -euo pipefail
|
||||
|
||||
if [[ $# != 0 ]]; then
|
||||
echo "Usage: sudo bash $0" >&2
|
||||
exit 1
|
||||
fi
|
||||
repository_url='https://persistent.oaistatic.com/codex-app-prod/linux'
|
||||
package_name='chatgpt'
|
||||
if [[ $EUID != 0 ]]; then
|
||||
echo "Run this script with sudo: sudo bash $0" >&2
|
||||
exit 1
|
||||
fi
|
||||
for command in pacman pacman-key pacman-conf curl gpg uname; do
|
||||
command -v "$command" >/dev/null || {
|
||||
echo "Missing $command; install pacman, curl, gnupg, and coreutils before continuing." >&2
|
||||
exit 1
|
||||
}
|
||||
done
|
||||
|
||||
temporary=$(mktemp -d)
|
||||
bootstrap_cache=''
|
||||
trap 'if [[ -n $bootstrap_cache ]]; then rm -f -- "$bootstrap_cache.db" "$bootstrap_cache.db.sig"; fi; rm -rf "$temporary"' EXIT
|
||||
architecture=$(uname -m)
|
||||
case "$architecture" in
|
||||
x86_64|aarch64) ;;
|
||||
*) echo 'Unsupported architecture.' >&2; exit 1 ;;
|
||||
esac
|
||||
versions=(26.908.70816 26.908.61612 26.908.40834)
|
||||
# The current reviewed set is authoritative for every fallback candidate.
|
||||
expected_fingerprints='3BFA0E4AE8B8CC16A2D9BA684A3B4A566C4660E4'
|
||||
verification_home="$temporary/verification"
|
||||
mkdir -m 0700 "$verification_home"
|
||||
selected=''
|
||||
for version in "${versions[@]}"; do
|
||||
candidate="$temporary/$version"
|
||||
mkdir "$candidate"
|
||||
package="$package_name-bin-$version-1-$architecture.pkg.tar.zst"
|
||||
unavailable=0
|
||||
for relative_path in \
|
||||
"arch/$version/repository-signing-key.gpg" \
|
||||
"arch/$version/$architecture/$package" \
|
||||
"arch/$version/$architecture/$package.sig" \
|
||||
"arch/$version/$architecture/openai-$package_name.db" \
|
||||
"arch/$version/$architecture/openai-$package_name.db.sig"; do
|
||||
if status=$(curl --proto '=https' --tlsv1.2 --connect-timeout 15 -fL \
|
||||
--write-out '%{http_code}' -o "$candidate/${relative_path##*/}" "$repository_url/$relative_path"); then
|
||||
continue
|
||||
else
|
||||
curl_exit=$?
|
||||
fi
|
||||
case "$curl_exit:$status" in
|
||||
22:404|22:410|22:408|22:429|22:5??|5:*|6:*|7:*|18:*|28:*|52:*|56:*)
|
||||
echo "Release $version is unavailable; trying the next published release." >&2
|
||||
unavailable=1
|
||||
break ;;
|
||||
*) echo "Download failed for $relative_path; not falling back. No changes were made." >&2; exit 1 ;;
|
||||
esac
|
||||
done
|
||||
if [[ $unavailable == 1 ]]; then continue; fi
|
||||
|
||||
if ! fingerprints=$(gpg --homedir "$verification_home" --batch --show-keys --with-colons "$candidate/repository-signing-key.gpg" |
|
||||
awk -F: '$1 == "pub" { primary=1 } $1 == "sub" { primary=0 } $1 == "fpr" && primary { print $10; primary=0 }' |
|
||||
LC_ALL=C sort); then
|
||||
echo 'Invalid OpenAI signing-key bundle; not falling back. No keys imported.' >&2
|
||||
exit 1
|
||||
fi
|
||||
if [[ $fingerprints != "$expected_fingerprints" ]]; then
|
||||
echo 'OpenAI repository signing-key fingerprint mismatch; not falling back. No keys imported.' >&2
|
||||
exit 1
|
||||
fi
|
||||
gpg --homedir "$verification_home" --batch --import "$candidate/repository-signing-key.gpg"
|
||||
if ! gpg --homedir "$verification_home" --batch --no-auto-key-retrieve --no-auto-key-import \
|
||||
--verify "$candidate/openai-$package_name.db.sig" "$candidate/openai-$package_name.db" ||
|
||||
! gpg --homedir "$verification_home" --batch --no-auto-key-retrieve --no-auto-key-import \
|
||||
--verify "$candidate/$package.sig" "$candidate/$package"; then
|
||||
echo 'OpenAI release signature verification failed; not falling back. No keys imported or configuration changed.' >&2
|
||||
exit 1
|
||||
fi
|
||||
selected="$candidate"
|
||||
if [[ $version != "${versions[0]}" ]]; then
|
||||
echo "Using previously published release $version." >&2
|
||||
fi
|
||||
break
|
||||
done
|
||||
if [[ -z $selected ]]; then
|
||||
echo 'No compatible published release is available. Files may still be propagating. No changes were made; download the installer again and retry shortly.' >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
sources_file="/etc/pacman.d/openai-$package_name.conf"
|
||||
cat >"$temporary/repository.conf" <<EOF
|
||||
### THIS FILE IS AUTOMATICALLY CONFIGURED ###
|
||||
# Remove it and its Include line to opt out of automatic package updates.
|
||||
[openai-$package_name]
|
||||
SigLevel = Required DatabaseRequired TrustedOnly
|
||||
Server = $repository_url/arch/\$arch
|
||||
EOF
|
||||
if [[ -e $sources_file ]] && ! cmp -s "$sources_file" "$temporary/repository.conf"; then
|
||||
echo "Not replacing existing pacman configuration: $sources_file" >&2
|
||||
exit 1
|
||||
fi
|
||||
pacman-key --init
|
||||
pacman-key --add "$selected/repository-signing-key.gpg"
|
||||
while IFS= read -r fingerprint; do
|
||||
pacman-key --lsign-key "$fingerprint"
|
||||
done <<<"$expected_fingerprints"
|
||||
install -m 0644 "$temporary/repository.conf" "$sources_file"
|
||||
include_line="Include = $sources_file"
|
||||
if ! grep -qxF "$include_line" /etc/pacman.conf; then
|
||||
printf '\n%s\n' "$include_line" >>/etc/pacman.conf
|
||||
fi
|
||||
# The first transaction must consume the files verified above, not refetch a
|
||||
# newer CDN generation. Keep the installed configuration on the online repo.
|
||||
# Give that snapshot its own cache identity so an older fallback cannot mask
|
||||
# the online catalog's Last-Modified timestamp on the next ordinary upgrade.
|
||||
bootstrap_repo="openai-$package_name-bootstrap-${temporary##*/}"
|
||||
install -m 0644 "$selected/openai-$package_name.db" "$selected/$bootstrap_repo.db"
|
||||
install -m 0644 "$selected/openai-$package_name.db.sig" "$selected/$bootstrap_repo.db.sig"
|
||||
sed -e "s|^Server = .*|Server = file://$selected|" \
|
||||
-e "s|^\\[openai-$package_name\\]$|[$bootstrap_repo]|" "$temporary/repository.conf" \
|
||||
>"$temporary/repository-local.conf"
|
||||
# The copied system configuration can contain private repository credentials.
|
||||
install -m 0600 /dev/null "$temporary/pacman.conf"
|
||||
awk -v original="$include_line" -v replacement="Include = $temporary/repository-local.conf" \
|
||||
'$0 == original { $0 = replacement } { print }' /etc/pacman.conf >"$temporary/pacman.conf"
|
||||
bootstrap_cache="$(pacman-conf --config "$temporary/pacman.conf" DBPath)/sync/$bootstrap_repo"
|
||||
# Allow pacman's unprivileged downloader to read verified artifacts while
|
||||
# keeping all files and the directory writable only by root.
|
||||
chmod 0755 "$temporary" "$selected"
|
||||
chmod 0644 "$selected"/*
|
||||
# Keep pacman's normal confirmation prompts and perform a full system upgrade.
|
||||
pacman --config "$temporary/pacman.conf" -Syu --needed "$package_name-bin"
|
||||
Reference in new issue
Block a user