From 0e0ea7e13d9be177064a8358148797239b5af556 Mon Sep 17 00:00:00 2001
From: Salt <rehashedsalt@cock.li>
Date: Sun, 29 Nov 2020 21:39:44 -0600
Subject: [PATCH] Work on a Gentoo bootstrap script

---
 README.md      |  30 ++++++--
 gentoostrap.sh | 184 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 209 insertions(+), 5 deletions(-)
 create mode 100755 gentoostrap.sh

diff --git a/README.md b/README.md
index 201e355..536b5ae 100644
--- a/README.md
+++ b/README.md
@@ -2,20 +2,40 @@
 
 A script to bootstrap a user with git and some auxiliary tools.
 
-## Usage
+## Building User Home
 
 Download and run the latest `bootstrap.sh`:
 
-    cd
-    git clone https://git.9iron.club/salt/bootstrap
-    ./bootstrap/bootstrap.sh $HOME
+```
+cd
+git clone https://git.9iron.club/salt/bootstrap
+./bootstrap/bootstrap.sh $HOME
+```
 
 In the event that you want to simply test `bootstrap.sh`, simply pass a different argument to it:
 
-    ./bootstrap/bootstrap.sh -d /path/to/directory
+```
+./bootstrap/bootstrap.sh -d /path/to/directory
+```
 
 See `bootstrap.sh -h` for more usage information.
 
+## Building a Gentoo Install
+
+First, partition out the system and build a filesystem tree in `/mnt`.
+
+Then, download and run the latest `gentoostrap.sh`:
+
+```
+cd
+git clone https://git.9iron.club/salt/bootstrap
+sudo ./bootstrap/gentoostrap.sh
+```
+
+The script supports a fair few arguments, so it's worth looking into `gentoostrap.sh -h` if you need to customize the system.
+
+Note that this is highly specific to my environment. Most of the configuration management is done in Ansible, but this will create a user with my own personal setup.
+
 ## Older Versions
 
 `build-home.sh` is an older version of the script kept here for legacy compatibility. Do not use it; use `bootstrap.sh`.
diff --git a/gentoostrap.sh b/gentoostrap.sh
new file mode 100755
index 0000000..f3da4b0
--- /dev/null
+++ b/gentoostrap.sh
@@ -0,0 +1,184 @@
+#! /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 -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
+}
+
+# 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' \
+			| uniq \
+			| sort \
+			| head -n 1
+		)"
+	stage3file="$(mktemp "tmp.$USER.$_name.XXXXXX-stage3.tar.xz" -p "/tmp")"
+	trap "cleanup $stage3file" EXIT
+	log "Getting tarball from: $stage3"
+	curl -s "$stage3" -o "$stage3file"
+	log "Decompressing tarball; this will prompt for root privileges"
+	sudo tar xf "$stage3" -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"
+	COMMON_FLAGS="-march=x86-64 -mtune=generic -O2 -pipe"
+	CFLAGS="\${COMMON_FLAGS}"
+	CXXFLAGS="\${COMMON_FLAGS}"
+	GENTOO_MIRRORS="http://distfiles.gentoo.org"
+	MAKEOPTS="$(nproc)"
+	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
+
+	# 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
+	:
+}
+
+# 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 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 "$@"
+