Salt
272ce9e21b
Hey if you wanna save bandwidth and be nicer to distro maintainers, you probably shouldn't delete your tarball after every attempt
248 lines
6.1 KiB
Bash
Executable File
248 lines
6.1 KiB
Bash
Executable File
#! /bin/bash
|
|
#
|
|
# gentoostrap
|
|
# Build a Gentoo system in /mnt
|
|
# Copyright (C) 2020 Vintage Salt <rehashedsalt@cock.li>
|
|
#
|
|
# Distributed under terms of the MIT license.
|
|
#
|
|
set -e
|
|
|
|
# Read-only set-once variables
|
|
declare -r _name="$(basename -- "$0")"
|
|
# Options
|
|
declare -i _optchroot
|
|
declare _optdest="/mnt"
|
|
declare _optprofile="desktop"
|
|
declare -i _opthelp
|
|
declare -i _optverbose
|
|
# Working variables
|
|
declare -a _args
|
|
declare _return
|
|
|
|
# Helper functions
|
|
log() {
|
|
# Print a line to the terminal if _optverbose is greater than $2
|
|
# $2 defaults to 0
|
|
# loglevel 0: Daily-use messages
|
|
# loglevel 1: Detailed but not quite debugging
|
|
# loglevel 2: Definitely debugging
|
|
[ -z "$1" ] && return 1
|
|
if (( _optverbose >= ${2:-0} )); then
|
|
printf "%s\\n" "$1"
|
|
fi
|
|
}
|
|
warn() {
|
|
# Print a yellow line to the terminal, respecting _optverbose
|
|
[ -z "$1" ] && return 1
|
|
if (( _optverbose >= ${2:-0} )); then
|
|
if [ -t 1 ]; then
|
|
printf "\\e[33m%s\\e[0m\\n" "$1"
|
|
else
|
|
printf "WARN: %s\\n" "$1"
|
|
fi
|
|
fi
|
|
}
|
|
error() {
|
|
# Print a red line to the terminal, exit if $2 is specified
|
|
[ -z "$1" ] && return 1
|
|
if [ -t 2 ]; then
|
|
printf "\\e[31m%s\\e[0m\\n" "$1" 1>&2
|
|
else
|
|
printf "ERROR: %s\\n" "$1" 1>&2
|
|
fi
|
|
[ -z "$2" ] && return
|
|
exit "${2:-1}"
|
|
}
|
|
has() {
|
|
# Parse out all arguments and try to find them in path
|
|
# If an argument cannot be found, set _return and fail
|
|
for prog in "$@"; do
|
|
if ! command -v "$prog" > /dev/null 2>&1; then
|
|
_return="$prog"
|
|
return 1
|
|
fi
|
|
done
|
|
return 0
|
|
}
|
|
|
|
# Helper functions
|
|
cleanup() {
|
|
[ -z "$1" ] && warn "No argument passed to cleanup"
|
|
rm -rf "$1" || warn "Failed to remove $1: $?"
|
|
}
|
|
|
|
# Core program functions
|
|
printhelp() {
|
|
cat << EOF
|
|
Usage: $_name [OPTION]...
|
|
|
|
-h Print this help text
|
|
-c Perform the Gentoo half of installation. Must be invoked from a chroot
|
|
-v Print more status messages. Stacks
|
|
|
|
Copyright (c) 2020 rehashedsalt@cock.li
|
|
Licensed under the MIT license
|
|
EOF
|
|
}
|
|
build-gentoo() {
|
|
# Build Gentoo
|
|
|
|
# First, get a link to a stage3 tarball
|
|
stage3="http://distfiles.gentoo.org/releases/amd64/autobuilds/current-stage3-amd64-systemd/$(
|
|
curl -s http://distfiles.gentoo.org/releases/amd64/autobuilds/current-stage3-amd64-systemd/ \
|
|
| grep -oe 'stage3-amd64-systemd-20.*\.tar\.xz' \
|
|
| sed 's/^stage3.*">//g' \
|
|
| sort \
|
|
| uniq \
|
|
| head -n 1
|
|
)"
|
|
stage3file="/tmp/tmp.$USER.$_name.stage3.tar.xz"
|
|
stage3sig="/tmp/tmp.$USER.$_name.stage3.tar.xz.DIGESTS"
|
|
for file in "$stage3file" "$stage3sig"; do
|
|
touch "$file"
|
|
chmod 0600 "$file"
|
|
done
|
|
# We grab the checksums first to verify the integrity of any tarball leftover from a previous run
|
|
log "Downloading stage3 signature"
|
|
curl -s "$stage3.DIGESTS" -o "$stage3sig"
|
|
if ! [ -f "$stage3file" ]; then
|
|
log "Downloading stage3"
|
|
curl -s "$stage3" -o "$stage3file"
|
|
elif ! grep "$stage3sig" -e "$(sha512sum "$stage3file" | awk '{print $1}')" > /dev/null 2>&1; then
|
|
log "Checksum verification failed; downloading new stage3"
|
|
curl -s "$stage3" -o "$stage3file"
|
|
fi
|
|
# At this point, we should have a new stage3 that matches our signature; die if not
|
|
if ! grep "$stage3sig" -e "$(sha512sum "$stage3file" | awk '{print $1}')" > /dev/null 2>&1; then
|
|
error "stage3 checksum verification failed" 50
|
|
fi
|
|
log "Decompressing tarball; this will prompt for root privileges"
|
|
sudo tar xf "$stage3file" -C "$_optdest"
|
|
|
|
# Now we do some pre-chroot configuration
|
|
pushd "$_optdest" > /dev/null 2>&1
|
|
# These is a very generic make.conf to get the system up and running
|
|
# We use march of x86-64 to ensure compatibility if we're bootstrapping on a host other than the target
|
|
cat <<-EOF > "$_optdest/etc/portage/make.conf"
|
|
# ABI_X86 is used to control multilib support
|
|
ABI_X86="64 32"
|
|
COMMON_FLAGS="-march=x86-64 -mtune=generic -O2 -pipe"
|
|
CFLAGS="\${COMMON_FLAGS}"
|
|
CXXFLAGS="\${COMMON_FLAGS}"
|
|
GENTOO_MIRRORS="http://distfiles.gentoo.org"
|
|
MAKEOPTS="$(nproc)"
|
|
USE="-test"
|
|
EOF
|
|
# Configure default ebuild repositories
|
|
mkdir -p "$_optdest/etc/portage/repos.conf"
|
|
cp "$_optdest/usr/share/portage/config/repos.conf" \
|
|
"$_optdest/etc/portage/repos.conf/gentoo.conf"
|
|
# DNS
|
|
cat <<-EOF > "$_optdest/etc/resolv.conf"
|
|
nameserver 8.8.8.8
|
|
nameserver 8.8.4.4
|
|
EOF
|
|
# Timezone
|
|
cp /etc/timezone "$_optdest/etc/timezone"
|
|
# Locale
|
|
cat <<-EOF > "$_optdest/etc/locale.gen"
|
|
en_US ISO-8859-1
|
|
en_US.UTF-8 UTF-8
|
|
EOF
|
|
|
|
# Now we need to pivot into a chroot and finish configuration natively
|
|
# Buuuut... since we're using systemd, we get to just spawn a systemd-nspawn container
|
|
popd
|
|
cp "$0" "$_optdest/gentoostrap.sh"
|
|
sudo systemd-nspawn --directory="$_optdest" /gentoostrap.sh -c
|
|
}
|
|
build-gentoo-chroot() {
|
|
# Build Gentoo, but from within the chroot environment
|
|
log "Building Gentoo from within chroot"
|
|
|
|
# Sync repositories
|
|
log "Getting ebuild repositories"
|
|
emerge-webrsync
|
|
|
|
# Get the stable plasma/systemd profile and select it
|
|
profile=$(
|
|
eselect profile list \
|
|
| grep -ie 'stable' \
|
|
| grep -ie "$profile" \
|
|
| sort \
|
|
| uniq \
|
|
| head -n 1 \
|
|
| grep -oP '\[\K[^\]]+'
|
|
) || error "Error finding profile: $profile" 51
|
|
[ -z "$profile" ] && error "Could not find profile: $profile" 52
|
|
log "Setting profile $profile"
|
|
eselect profile set "$profile"
|
|
|
|
# BEHOLD!
|
|
emerge -DNuv @world
|
|
# Configure timezone
|
|
emerge --config sys-libs/timezone-data
|
|
# Locales
|
|
locale-gen
|
|
eselect locale set en_US.utf8
|
|
env-update
|
|
. /etc/profile
|
|
|
|
# Build a kernel
|
|
}
|
|
|
|
# Main
|
|
main() {
|
|
# Parse out arguments
|
|
while [ -n "$1" ]; do
|
|
# Parse out flags
|
|
while getopts ":chv" opt; do
|
|
case $opt in
|
|
c)
|
|
_optchroot=1
|
|
;;
|
|
h)
|
|
_opthelp=1
|
|
;;
|
|
v)
|
|
_optverbose+=1
|
|
;;
|
|
:)
|
|
error "Option requires argument: -$OPTARG" 2
|
|
;;
|
|
*)
|
|
error "Invalid option: -$OPTARG" 2
|
|
;;
|
|
esac
|
|
done
|
|
# Store arguments
|
|
shift $((OPTIND - 1))
|
|
if [ -n "$1" ]; then
|
|
_args+=("$1")
|
|
shift
|
|
fi
|
|
unset OPTIND
|
|
done
|
|
# Early hook for help
|
|
[ -n "$_opthelp" ] && printhelp && exit 0
|
|
# Validate critical options
|
|
# TODO: That
|
|
# Validate core program dependencies
|
|
log "Validating dependencies" 2
|
|
if ! has basename curl systemd-nspawn tar; then
|
|
error "Failed to find program: $_return" 1
|
|
fi
|
|
|
|
# Do the do
|
|
if [ -z "$_optchroot" ]; then
|
|
build-gentoo
|
|
else
|
|
build-gentoo-chroot
|
|
fi
|
|
exit 0
|
|
}
|
|
|
|
main "$@"
|
|
|