This commit is contained in:
Brian Zalewski 2023-11-13 04:53:44 +00:00
parent d413ce15c7
commit 61e90b47b0
11 changed files with 731 additions and 430 deletions

View file

@ -34,77 +34,164 @@
# setup and updates are applied using this script (via a cronjob that does not need to run initialization tasks during
# the cronjobs).
#
# ## TODO
#
# * Automatically add UFW exceptions using [this script](https://github.com/Paul-Reed/cloudflare-ufw)
#
# ## Links
#
# [SSH with short-lived certificates](https://developers.cloudflare.com/cloudflare-one/tutorials/ssh-cert-bastion/)
# @description Logs with style using Gum if it is installed, otherwise it uses `echo`. It also leverages Glow to render markdown.
# When Glow is not installed, it uses `cat`.
# @example
# logger info "An informative log"
logg() {
TYPE="$1"
MSG="$2"
if [ "$TYPE" == 'error' ]; then
if command -v gum > /dev/null; then
gum style --border="thick" "$(gum style --foreground="#ff0000" "✖") $(gum style --bold --background="#ff0000" --foreground="#ffffff" " ERROR ") $(gum style --bold "$MSG")"
else
echo "ERROR: $MSG"
fi
elif [ "$TYPE" == 'info' ]; then
if command -v gum > /dev/null; then
gum style " $(gum style --foreground="#00ffff" "○") $(gum style --faint "$MSG")"
else
echo "INFO: $MSG"
fi
elif [ "$TYPE" == 'md' ]; then
if command -v glow > /dev/null; then
glow "$MSG"
else
cat "$MSG"
fi
elif [ "$TYPE" == 'prompt' ]; then
if command -v gum > /dev/null; then
gum style " $(gum style --foreground="#00008b" "▶") $(gum style --bold "$MSG")"
else
echo "PROMPT: $MSG"
fi
elif [ "$TYPE" == 'star' ]; then
if command -v gum > /dev/null; then
gum style " $(gum style --foreground="#d1d100" "◆") $(gum style --bold "$MSG")"
else
echo "STAR: $MSG"
fi
elif [ "$TYPE" == 'start' ]; then
if command -v gum > /dev/null; then
gum style " $(gum style --foreground="#00ff00" "▶") $(gum style --bold "$MSG")"
else
echo "START: $MSG"
fi
elif [ "$TYPE" == 'success' ]; then
if command -v gum > /dev/null; then
gum style "$(gum style --foreground="#00ff00" "✔") $(gum style --bold "$MSG")"
else
echo "SUCCESS: $MSG"
fi
elif [ "$TYPE" == 'warn' ]; then
if command -v gum > /dev/null; then
gum style " $(gum style --foreground="#d1d100" "◆") $(gum style --bold --background="#ffff00" --foreground="#000000" " WARNING ") $(gum style --bold "$MSG")"
else
echo "WARNING: $MSG"
fi
else
if command -v gum > /dev/null; then
gum style " $(gum style --foreground="#00ff00" "▶") $(gum style --bold "$TYPE")"
else
echo "$MSG"
fi
fi
}
# @description Ensure dependencies like `git` and `curl` are installed (among a few other lightweight system packages)
if ! command -v curl > /dev/null || ! command -v git > /dev/null || ! command -v expect > /dev/null || ! command -v rsync > /dev/null; then
if ! command -v curl > /dev/null || ! command -v git > /dev/null || ! command -v expect > /dev/null || ! command -v rsync > /dev/null || ! command -v unbuffer; then
if command -v apt-get > /dev/null; then
# @description Ensure `build-essential`, `curl`, `expect`, `git`, and `rsync` are installed on Debian / Ubuntu
sudo apt-get update
sudo apt-get install -y build-essential curl expect git rsync
### Debian / Ubuntu
logg info 'Running sudo apt-get update' && sudo apt-get update
logg info 'Running sudo apt-get install -y build-essential curl expect git rsync' && sudo apt-get install -y build-essential curl expect git rsync
elif command -v dnf > /dev/null; then
# @description Ensure `curl`, `expect`, `git`, and `rsync` are installed on Fedora
sudo dnf install -y curl expect git rsync
### Fedora
logg info 'Running sudo dnf install -y curl expect git rsync' && sudo dnf install -y curl expect git rsync
elif command -v yum > /dev/null; then
# @description Ensure `curl`, `expect`, `git`, and `rsync` are installed on CentOS
sudo yum install -y curl expect git rsync
### CentOS
logg info 'Running sudo yum install -y curl expect git rsync' && sudo yum install -y curl expect git rsync
elif command -v pacman > /dev/null; then
# @description Ensure `curl`, `expect`, `git`, and `rsync` are installed on Archlinux
sudo pacman update
sudo pacman -Sy curl expect git rsync
### Archlinux
logg info 'Running sudo pacman update' && sudo pacman update
logg info 'Running sudo pacman -Syu base-devel curl expect git rsync procps-ng file' && sudo pacman -Syu base-devel curl expect git rsync procps-ng file
elif command -v zypper > /dev/null; then
# @description Ensure `curl`, `expect`, `git`, and `rsync` are installed on OpenSUSE
sudo zypper install -y curl expect git rsync
### OpenSUSE
logg info 'Running sudo zypper install -y curl expect git rsync' && sudo zypper install -y curl expect git rsync
elif command -v apk > /dev/null; then
# @description Ensure `curl`, `expect`, `git`, and `rsync` are installed on Alpine
apk add curl expect git rsync
### Alpine
logg info 'Running apk add curl expect git rsync' && apk add curl expect git rsync
elif [ -d /Applications ] && [ -d /Library ]; then
# @description Ensure CLI developer tools are available on macOS (via `xcode-select`)
sudo xcode-select -p >/dev/null 2>&1 || xcode-select --install
### macOS
logg info 'Running sudo xcode-select -p >/dev/null 2>&1 || xcode-select --install' && sudo xcode-select -p >/dev/null 2>&1 || xcode-select --install
elif [[ "$OSTYPE" == 'cygwin' ]] || [[ "$OSTYPE" == 'msys' ]] || [[ "$OSTYPE" == 'win32' ]]; then
# @description Ensure `curl`, `expect`, `git`, and `rsync` are installed on Windows
choco install -y curl expect git rsync
### Windows
logg info 'Running choco install -y curl expect git rsync' && choco install -y curl expect git rsync
elif command -v nix-env > /dev/null; then
### NixOS
logg warn "TODO - Add support for NixOS"
elif [[ "$OSTYPE" == 'freebsd'* ]]; then
### FreeBSD
logg warn "TODO - Add support for FreeBSD"
elif command -v pkg > /dev/null; then
### Termux
logg warn "TODO - Add support for Termux"
elif command -v xbps-install > /dev/null; then
### Void
logg warn "TODO - Add support for Void"
fi
fi
# @description Ensure Homebrew is installed and available in the `PATH`
fi# @description Ensure Homebrew is installed and available in the `PATH`
if ! command -v brew > /dev/null; then
if [ -d /home/linuxbrew/.linuxbrew/bin ]; then
eval $(/home/linuxbrew/.linuxbrew/bin/brew shellenv)
logg info "Sourcing from /home/linuxbrew/.linuxbrew/bin/brew" && eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"
if ! command -v brew > /dev/null; then
echo "The /home/linuxbrew/.linuxbrew directory exists but something is not right. Try removing it and running the script again." && exit 1
logg error "The /home/linuxbrew/.linuxbrew directory exists but something is not right. Try removing it and running the script again." && exit 1
fi
else
# @description Installs Homebrew and addresses a couple potential issues
### Installs Homebrew and addresses a couple potential issues
if command -v sudo > /dev/null && sudo -n true; then
logg info "Installing Homebrew"
echo | /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
else
echo "Homebrew is not installed. The script will attempt to install Homebrew and you might be prompted for your password."
logg info "Homebrew is not installed. The script will attempt to install Homebrew and you might be prompted for your password."
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" || BREW_EXIT_CODE="$?"
if [ -n "$BREW_EXIT_CODE" ]; then
if command -v brew > /dev/null; then
echo "Homebrew was installed but part of the installation failed. Trying a few things to fix the installation.."
logg warn "Homebrew was installed but part of the installation failed. Trying a few things to fix the installation.."
BREW_DIRS="share/man share/doc share/zsh/site-functions etc/bash_completion.d"
for BREW_DIR in $BREW_DIRS; do
if [ -d "$(brew --prefix)/$BREW_DIR" ]; then
sudo chown -R "$(whoami)" "$(brew --prefix)/$BREW_DIR"
logg info "Chowning $(brew --prefix)/$BREW_DIR" && sudo chown -R "$(whoami)" "$(brew --prefix)/$BREW_DIR"
fi
done
brew update --force --quiet
logg info "Running brew update --force --quiet" && brew update --force --quiet && logg success "Successfully ran brew update --force --quiet"
fi
fi
fi
# @description Ensures the `brew` binary is available on Linux machines. macOS installs `brew` into the default `PATH`
# so nothing needs to be done for macOS.
### Ensures the `brew` binary is available on Linux machines. macOS installs `brew` into the default `PATH` so nothing needs to be done for macOS.
if [ -d /home/linuxbrew/.linuxbrew/bin ]; then
eval $(/home/linuxbrew/.linuxbrew/bin/brew shellenv)
logg info "Sourcing shellenv from /home/linuxbrew/.linuxbrew/bin/brew" && eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"
elif [ -f /opt/homebrew/bin/brew ]; then
logg info "Sourcing shellenv from /opt/homebrew/bin/brew" && eval "$(/opt/homebrew/bin/brew shellenv)"
fi
fi
fi
### Ensure GCC is installed via Homebrew
if command -v brew > /dev/null; then
if ! brew list | grep gcc > /dev/null; then
logg info "Installing Homebrew gcc" && brew install gcc
fi
else
logg error "Failed to initialize Homebrew" && exit 2
fi
# @description Ensures `cloudflared` is installed via Homebrew
if ! command -v cloudflared > /dev/null; then
brew install cloudflared

View file

@ -13,35 +13,46 @@
if ! command -v brew > /dev/null; then
if [ -d /home/linuxbrew/.linuxbrew/bin ]; then
eval $(/home/linuxbrew/.linuxbrew/bin/brew shellenv)
logg info "Sourcing from /home/linuxbrew/.linuxbrew/bin/brew" && eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"
if ! command -v brew > /dev/null; then
echo "The /home/linuxbrew/.linuxbrew directory exists but something is not right. Try removing it and running the script again." && exit 1
logg error "The /home/linuxbrew/.linuxbrew directory exists but something is not right. Try removing it and running the script again." && exit 1
fi
else
# @description Installs Homebrew and addresses a couple potential issues
### Installs Homebrew and addresses a couple potential issues
if command -v sudo > /dev/null && sudo -n true; then
logg info "Installing Homebrew"
echo | /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
else
echo "Homebrew is not installed. The script will attempt to install Homebrew and you might be prompted for your password."
logg info "Homebrew is not installed. The script will attempt to install Homebrew and you might be prompted for your password."
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" || BREW_EXIT_CODE="$?"
if [ -n "$BREW_EXIT_CODE" ]; then
if command -v brew > /dev/null; then
echo "Homebrew was installed but part of the installation failed. Trying a few things to fix the installation.."
logg warn "Homebrew was installed but part of the installation failed. Trying a few things to fix the installation.."
BREW_DIRS="share/man share/doc share/zsh/site-functions etc/bash_completion.d"
for BREW_DIR in $BREW_DIRS; do
if [ -d "$(brew --prefix)/$BREW_DIR" ]; then
sudo chown -R "$(whoami)" "$(brew --prefix)/$BREW_DIR"
logg info "Chowning $(brew --prefix)/$BREW_DIR" && sudo chown -R "$(whoami)" "$(brew --prefix)/$BREW_DIR"
fi
done
brew update --force --quiet
logg info "Running brew update --force --quiet" && brew update --force --quiet && logg success "Successfully ran brew update --force --quiet"
fi
fi
fi
# @description Ensures the `brew` binary is available on Linux machines. macOS installs `brew` into the default `PATH`
# so nothing needs to be done for macOS.
### Ensures the `brew` binary is available on Linux machines. macOS installs `brew` into the default `PATH` so nothing needs to be done for macOS.
if [ -d /home/linuxbrew/.linuxbrew/bin ]; then
eval $(/home/linuxbrew/.linuxbrew/bin/brew shellenv)
logg info "Sourcing shellenv from /home/linuxbrew/.linuxbrew/bin/brew" && eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"
elif [ -f /opt/homebrew/bin/brew ]; then
logg info "Sourcing shellenv from /opt/homebrew/bin/brew" && eval "$(/opt/homebrew/bin/brew shellenv)"
fi
fi
fi
### Ensure GCC is installed via Homebrew
if command -v brew > /dev/null; then
if ! brew list | grep gcc > /dev/null; then
logg info "Installing Homebrew gcc" && brew install gcc
fi
else
logg error "Failed to initialize Homebrew" && exit 2
fi

View file

@ -1,41 +1,41 @@
if ! command -v curl > /dev/null || ! command -v git > /dev/null || ! command -v expect > /dev/null || ! command -v rsync > /dev/null || ! command -v unbuffer; then
if command -v apt-get > /dev/null; then
### Debian / Ubuntu
sudo apt-get update
sudo apt-get install -y build-essential curl expect git rsync
logg info 'Running sudo apt-get update' && sudo apt-get update
logg info 'Running sudo apt-get install -y build-essential curl expect git rsync' && sudo apt-get install -y build-essential curl expect git rsync
elif command -v dnf > /dev/null; then
### Fedora
sudo dnf install -y curl expect git rsync
logg info 'Running sudo dnf install -y curl expect git rsync' && sudo dnf install -y curl expect git rsync
elif command -v yum > /dev/null; then
### CentOS
sudo yum install -y curl expect git rsync
logg info 'Running sudo yum install -y curl expect git rsync' && sudo yum install -y curl expect git rsync
elif command -v pacman > /dev/null; then
### Archlinux
sudo pacman update
sudo pacman -Syu base-devel curl expect git rsync procps-ng file
logg info 'Running sudo pacman update' && sudo pacman update
logg info 'Running sudo pacman -Syu base-devel curl expect git rsync procps-ng file' && sudo pacman -Syu base-devel curl expect git rsync procps-ng file
elif command -v zypper > /dev/null; then
### OpenSUSE
sudo zypper install -y curl expect git rsync
logg info 'Running sudo zypper install -y curl expect git rsync' && sudo zypper install -y curl expect git rsync
elif command -v apk > /dev/null; then
### Alpine
apk add curl expect git rsync
logg info 'Running apk add curl expect git rsync' && apk add curl expect git rsync
elif [ -d /Applications ] && [ -d /Library ]; then
### macOS
sudo xcode-select -p >/dev/null 2>&1 || xcode-select --install
logg info 'Running sudo xcode-select -p >/dev/null 2>&1 || xcode-select --install' && sudo xcode-select -p >/dev/null 2>&1 || xcode-select --install
elif [[ "$OSTYPE" == 'cygwin' ]] || [[ "$OSTYPE" == 'msys' ]] || [[ "$OSTYPE" == 'win32' ]]; then
### Windows
choco install -y curl expect git rsync
logg info 'Running choco install -y curl expect git rsync' && choco install -y curl expect git rsync
elif command -v nix-env > /dev/null; then
### NixOS
echo "TODO - Add support for NixOS"
logg warn "TODO - Add support for NixOS"
elif [[ "$OSTYPE" == 'freebsd'* ]]; then
### FreeBSD
echo "TODO - Add support for FreeBSD"
logg warn "TODO - Add support for FreeBSD"
elif command -v pkg > /dev/null; then
### Termux
echo "TODO - Add support for Termux"
logg warn "TODO - Add support for Termux"
elif command -v xbps-install > /dev/null; then
### Void
echo "TODO - Add support for Void"
logg warn "TODO - Add support for Void"
fi
fi

View file

@ -26,8 +26,7 @@ if ! command -v brew > /dev/null; then
fi
fi
### Ensures the `brew` binary is available on Linux machines. macOS installs `brew` into the default `PATH`
# so nothing needs to be done for macOS.
### Ensures the `brew` binary is available on Linux machines. macOS installs `brew` into the default `PATH` so nothing needs to be done for macOS.
if [ -d /home/linuxbrew/.linuxbrew/bin ]; then
logg info "Sourcing shellenv from /home/linuxbrew/.linuxbrew/bin/brew" && eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"
elif [ -f /opt/homebrew/bin/brew ]; then
@ -36,6 +35,7 @@ if ! command -v brew > /dev/null; then
fi
fi
### Ensure GCC is installed via Homebrew
if command -v brew > /dev/null; then
if ! brew list | grep gcc > /dev/null; then
logg info "Installing Homebrew gcc" && brew install gcc

View file

@ -1,6 +1,7 @@
# @description Logs with style using Gum if it is installed, otherwise it uses `echo`. It also leverages Glow to render markdown.
# When Glow is not installed, it uses `cat`.
# @example logger info "An informative log"
# @example
# logger info "An informative log"
logg() {
TYPE="$1"
MSG="$2"

116
scripts/pfsense.sh Normal file
View file

@ -0,0 +1,116 @@
#!/bin/sh
# @file pfSense Setup
# @brief Configures pfSense
# @description
# This script sets up pfSense with features like:
#
# 1. [Netdata Cloud](https://learn.netdata.cloud/docs/installing/pfsense)
# @description Logs with style using Gum if it is installed, otherwise it uses `echo`. It also leverages Glow to render markdown.
# When Glow is not installed, it uses `cat`.
# @example
# logger info "An informative log"
logg() {
TYPE="$1"
MSG="$2"
if [ "$TYPE" == 'error' ]; then
if command -v gum > /dev/null; then
gum style --border="thick" "$(gum style --foreground="#ff0000" "✖") $(gum style --bold --background="#ff0000" --foreground="#ffffff" " ERROR ") $(gum style --bold "$MSG")"
else
echo "ERROR: $MSG"
fi
elif [ "$TYPE" == 'info' ]; then
if command -v gum > /dev/null; then
gum style " $(gum style --foreground="#00ffff" "○") $(gum style --faint "$MSG")"
else
echo "INFO: $MSG"
fi
elif [ "$TYPE" == 'md' ]; then
if command -v glow > /dev/null; then
glow "$MSG"
else
cat "$MSG"
fi
elif [ "$TYPE" == 'prompt' ]; then
if command -v gum > /dev/null; then
gum style " $(gum style --foreground="#00008b" "▶") $(gum style --bold "$MSG")"
else
echo "PROMPT: $MSG"
fi
elif [ "$TYPE" == 'star' ]; then
if command -v gum > /dev/null; then
gum style " $(gum style --foreground="#d1d100" "◆") $(gum style --bold "$MSG")"
else
echo "STAR: $MSG"
fi
elif [ "$TYPE" == 'start' ]; then
if command -v gum > /dev/null; then
gum style " $(gum style --foreground="#00ff00" "▶") $(gum style --bold "$MSG")"
else
echo "START: $MSG"
fi
elif [ "$TYPE" == 'success' ]; then
if command -v gum > /dev/null; then
gum style "$(gum style --foreground="#00ff00" "✔") $(gum style --bold "$MSG")"
else
echo "SUCCESS: $MSG"
fi
elif [ "$TYPE" == 'warn' ]; then
if command -v gum > /dev/null; then
gum style " $(gum style --foreground="#d1d100" "◆") $(gum style --bold --background="#ffff00" --foreground="#000000" " WARNING ") $(gum style --bold "$MSG")"
else
echo "WARNING: $MSG"
fi
else
if command -v gum > /dev/null; then
gum style " $(gum style --foreground="#00ff00" "▶") $(gum style --bold "$TYPE")"
else
echo "$MSG"
fi
fi
}
### Enable FreeBSD package repo
logg info 'Enabling FreeBSD package repo'
FILE_PATH="/usr/local/etc/pkg/repos/pfSense.conf"
TMP_FILE=$(mktemp)
REPLACEMENT="FreeBSD: { enabled: yes }"
echo "$REPLACEMENT" > "$TMP_FILE"
tail -n +2 "$FILE_PATH" >> "$TMP_FILE"
mv -f "$TMP_FILE" "$FILE_PATH"
rm -f "$TMP_FILE"
### Install Netdata / dependencies
logg info 'Installing Netdata system package dependencies'
pkg update
pkg install -y curl pkgconf bash e2fsprogs-libuuid libuv nano
pkg install -y json-c-0.15_1
pkg install -y py39-certifi-2023.5.7
pkg install -y py39-asn1crypto
pkg install -y py39-pycparser
pkg install -y py39-cffi
pkg install -y py39-six
pkg install -y py39-cryptography
pkg install -y py39-idna
pkg install -y py39-openssl
pkg install -y py39-pysocks
pkg install -y py39-urllib3
pkg install -y py39-yaml
pkg install -y netdata
### Modify Netdata configuration
logg info 'Configuring Netdata to work with Netdata Cloud'
# TODO: Add below to netdata.conf
# bind to = 127.0.0.1 to bind to = 0.0.0.0
NETDATA_CLOUD_API_TOKEN="YOUR_API_TOKEN_HERE"
cat <<EOF > /usr/local/etc/netdata/netdata.conf
[backend]
enabled = yes
data source = netdata
destination = https://app.netdata.cloud
api key = ${NETDATA_CLOUD_API_TOKEN}
EOF
### Start Netdata
logg info 'Starting Netdata service'
service netdata onestart

View file

@ -1,5 +1,5 @@
#!/usr/bin/env bash
# @file Quick Start
# @file Quick Start Provision Script
# @brief Main entry point for Install Doctor that ensures Homebrew and a few dependencies are installed before cloning the repository and running Chezmoi.
# @description
# This script ensures Homebrew is installed and then installs a few dependencies that Install Doctor relies on.
@ -38,10 +38,10 @@
# provisioning script on a wide variety of operating systems.
#
# | Variable | Description |
# |------------------------|-----------------------------------------------------------------------------------|
# |---------------------------|-----------------------------------------------------------------------------------|
# | `START_REPO` (or `REPO`) | Variable to specify the Git fork to use when provisioning |
# | `ANSIBLE_PROVISION_VM` | **For Qubes**, determines the name of the VM used to provision the system |
# | `DEBUG_MODE` | Set to true to enable verbose logging |
# | `DEBUG_MODE` (or `DEBUG`) | Set to true to enable verbose logging |
#
# For a full list of variables you can use to customize Install Doctor, check out our [Customization](https://install.doctor/docs/customization)
# and [Secrets](https://install.doctor/docs/customization/secrets) documentation.
@ -51,52 +51,10 @@
# [Install Doctor homepage](https://install.doctor)
# [Install Doctor documentation portal](https://install.doctor/docs) (includes tips, tricks, and guides on how to customize the system to your liking)
# @description Ensure Ubuntu / Debian run in `noninteractive` mode
export DEBIAN_FRONTEND=noninteractive
# @description Load default settings if it is in a CI setting
if [ -n "$CI" ]; then
export HOST="$HOST"
export NO_RESTART=true
export HEADLESS_INSTALL=true
export SOFTWARE_GROUP="Full"
export FULL_NAME="Brian Zalewski"
export PRIMARY_EMAIL="help@megabyte.space"
export PUBLIC_SERVICES_DOMAIN="lab.megabyte.space"
export RESTRICTED_ENVIRONMENT=false
export WORK_ENVIRONMENT=false
fi
# @description Detect `START_REPO` format and determine appropriate git address, otherwise use the master Install Doctor branch
setStartRepo() {
if [ -z "$START_REPO" ]; then
START_REPO="https://github.com/megabyte-labs/install.doctor.git"
else
if [[ "$START_REPO" == *"/"* ]]; then
# Either full git address or GitHubUser/RepoName
if [[ "$START_REPO" == *":"* ]] || [[ "$START_REPO" == *"//"* ]]; then
START_REPO="$START_REPO"
else
START_REPO="https://github.com/${START_REPO}.git"
fi
else
START_REPO="https://github.com/$START_REPO/install.doctor.git"
fi
fi
}
# @description Disconnect from WARP, if connected
warpDisconnect() {
if command -v warp-cli > /dev/null; then
if warp-cli status | grep 'Connected' > /dev/null; then
warp-cli disconnect && echo "Disconnected WARP to prevent conflicts"
fi
fi
}
# @description Logs with style using Gum if it is installed, otherwise it uses `echo`. It also leverages Glow to render markdown.
# When Glow is not installed, it uses `cat`.
# @example logger info "An informative log"
# @example
# logger info "An informative log"
logg() {
TYPE="$1"
MSG="$2"
@ -108,7 +66,7 @@ logg() {
fi
elif [ "$TYPE" == 'info' ]; then
if command -v gum > /dev/null; then
gum style " $(gum style --foreground="#00ffff" "○") $(gum style --faint --foreground="#ffffff" "$MSG")"
gum style " $(gum style --foreground="#00ffff" "○") $(gum style --faint "$MSG")"
else
echo "INFO: $MSG"
fi
@ -156,16 +114,157 @@ logg() {
fi
fi
}
# @section Environment variables and system dependencies
# @description Ensure Ubuntu / Debian run in `noninteractive` mode. Detect `START_REPO` format and determine appropriate git address,
# otherwise use the master Install Doctor branch
setEnvironmentVariables() {
export DEBIAN_FRONTEND=noninteractive
if [ -z "$START_REPO" ] && [ -z "$REPO" ]; then
export START_REPO="https://github.com/megabyte-labs/install.doctor.git"
else
if [ -n "$REPO" ] && [ -z "$START_REPO" ]; then
export START_REPO="$REPO"
fi
if [[ "$START_REPO" == *"/"* ]]; then
# Either full git address or GitHubUser/RepoName
if [[ "$START_REPO" == *":"* ]] || [[ "$START_REPO" == *"//"* ]]; then
export START_REPO="$START_REPO"
else
export START_REPO="https://github.com/${START_REPO}.git"
fi
else
export START_REPO="https://github.com/$START_REPO/install.doctor.git"
fi
fi
}
# @description Notify user that they can press CTRL+C to prevent /etc/sudoers from being modified (which is currently required for headless installs on some systems)
# @description Ensure dependencies like `git` and `curl` are installed (among a few other lightweight system packages)
ensureBasicDeps() {
if ! command -v curl > /dev/null || ! command -v git > /dev/null || ! command -v expect > /dev/null || ! command -v rsync > /dev/null || ! command -v unbuffer; then
if command -v apt-get > /dev/null; then
### Debian / Ubuntu
logg info 'Running sudo apt-get update' && sudo apt-get update
logg info 'Running sudo apt-get install -y build-essential curl expect git rsync' && sudo apt-get install -y build-essential curl expect git rsync
elif command -v dnf > /dev/null; then
### Fedora
logg info 'Running sudo dnf install -y curl expect git rsync' && sudo dnf install -y curl expect git rsync
elif command -v yum > /dev/null; then
### CentOS
logg info 'Running sudo yum install -y curl expect git rsync' && sudo yum install -y curl expect git rsync
elif command -v pacman > /dev/null; then
### Archlinux
logg info 'Running sudo pacman update' && sudo pacman update
logg info 'Running sudo pacman -Syu base-devel curl expect git rsync procps-ng file' && sudo pacman -Syu base-devel curl expect git rsync procps-ng file
elif command -v zypper > /dev/null; then
### OpenSUSE
logg info 'Running sudo zypper install -y curl expect git rsync' && sudo zypper install -y curl expect git rsync
elif command -v apk > /dev/null; then
### Alpine
logg info 'Running apk add curl expect git rsync' && apk add curl expect git rsync
elif [ -d /Applications ] && [ -d /Library ]; then
### macOS
logg info 'Running sudo xcode-select -p >/dev/null 2>&1 || xcode-select --install' && sudo xcode-select -p >/dev/null 2>&1 || xcode-select --install
elif [[ "$OSTYPE" == 'cygwin' ]] || [[ "$OSTYPE" == 'msys' ]] || [[ "$OSTYPE" == 'win32' ]]; then
### Windows
logg info 'Running choco install -y curl expect git rsync' && choco install -y curl expect git rsync
elif command -v nix-env > /dev/null; then
### NixOS
logg warn "TODO - Add support for NixOS"
elif [[ "$OSTYPE" == 'freebsd'* ]]; then
### FreeBSD
logg warn "TODO - Add support for FreeBSD"
elif command -v pkg > /dev/null; then
### Termux
logg warn "TODO - Add support for Termux"
elif command -v xbps-install > /dev/null; then
### Void
logg warn "TODO - Add support for Void"
fi
fi}
# @description Ensure Homebrew is installed and available in the `PATH`
ensureHomebrew() {
if ! command -v brew > /dev/null; then
if [ -d /home/linuxbrew/.linuxbrew/bin ]; then
logg info "Sourcing from /home/linuxbrew/.linuxbrew/bin/brew" && eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"
if ! command -v brew > /dev/null; then
logg error "The /home/linuxbrew/.linuxbrew directory exists but something is not right. Try removing it and running the script again." && exit 1
fi
else
### Installs Homebrew and addresses a couple potential issues
if command -v sudo > /dev/null && sudo -n true; then
logg info "Installing Homebrew"
echo | /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
else
logg info "Homebrew is not installed. The script will attempt to install Homebrew and you might be prompted for your password."
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" || BREW_EXIT_CODE="$?"
if [ -n "$BREW_EXIT_CODE" ]; then
if command -v brew > /dev/null; then
logg warn "Homebrew was installed but part of the installation failed. Trying a few things to fix the installation.."
BREW_DIRS="share/man share/doc share/zsh/site-functions etc/bash_completion.d"
for BREW_DIR in $BREW_DIRS; do
if [ -d "$(brew --prefix)/$BREW_DIR" ]; then
logg info "Chowning $(brew --prefix)/$BREW_DIR" && sudo chown -R "$(whoami)" "$(brew --prefix)/$BREW_DIR"
fi
done
logg info "Running brew update --force --quiet" && brew update --force --quiet && logg success "Successfully ran brew update --force --quiet"
fi
fi
fi
### Ensures the `brew` binary is available on Linux machines. macOS installs `brew` into the default `PATH` so nothing needs to be done for macOS.
if [ -d /home/linuxbrew/.linuxbrew/bin ]; then
logg info "Sourcing shellenv from /home/linuxbrew/.linuxbrew/bin/brew" && eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"
elif [ -f /opt/homebrew/bin/brew ]; then
logg info "Sourcing shellenv from /opt/homebrew/bin/brew" && eval "$(/opt/homebrew/bin/brew shellenv)"
fi
fi
fi
### Ensure GCC is installed via Homebrew
if command -v brew > /dev/null; then
if ! brew list | grep gcc > /dev/null; then
logg info "Installing Homebrew gcc" && brew install gcc
fi
else
logg error "Failed to initialize Homebrew" && exit 2
fi
}
# @description Load default settings if it is in a CI setting
setCIEnvironmentVariables() {
if [ -n "$CI" ]; then
logg info "Automatically setting environment variables since the CI environment variable is defined"
logg info "Setting HOST to $HOST" && export HOST="$HOST"
logg info "Setting NO_RESTART to true" && export NO_RESTART=true
logg info "Setting HEADLESS_INSTALL to true " && export HEADLESS_INSTALL=true
logg info "Setting SOFTWARE_GROUP to Full-Desktop" && export SOFTWARE_GROUP="Full-Desktop"
logg info "Setting FULL_NAME to Brian Zalewski" && export FULL_NAME="Brian Zalewski"
logg info "Setting PRIMARY_EMAIL to help@megabyte.space" && export PRIMARY_EMAIL="help@megabyte.space"
logg info "Setting PUBLIC_SERVICES_DOMAIN to lab.megabyte.space" && export PUBLIC_SERVICES_DOMAIN="lab.megabyte.space"
logg info "Setting RESTRICTED_ENVIRONMENT to false" && export RESTRICTED_ENVIRONMENT=false
logg info "Setting WORK_ENVIRONMENT to false" && export WORK_ENVIRONMENT=false
fi
}
# @description Disconnect from WARP, if connected
ensureWarpDisconnected() {
if command -v warp-cli > /dev/null; then
if warp-cli status | grep 'Connected' > /dev/null; then
logg info "Disconnecting from WARP" && warp-cli disconnect && logg success "Disconnected WARP to prevent conflicts"
fi
fi
}
# @description Notify user that they can press CTRL+C to prevent `/etc/sudoers` from being modified (which is currently required for headless installs on some systems).
# Additionally, this function will add the current user to `/etc/sudoers` so that headless automation is possible.
setupPasswordlessSudo() {
sudo -n true || SUDO_EXIT_CODE=$?
logg info 'Your user will temporarily be granted passwordless sudo for the duration of the script'
if [ -n "$SUDO_EXIT_CODE" ]; then
logg info 'Press CTRL+C to bypass this prompt to either enter your password when needed or perform a non-privileged installation'
logg info 'Note: Non-privileged installations are not yet supported'
fi
# @description Add current user to /etc/sudoers so that headless automation is possible
if ! sudo cat /etc/sudoers | grep '# TEMPORARY FOR INSTALL DOCTOR' > /dev/null; then
if [ -n "$SUDO_PASSWORD" ]; then
printf '%s\n' "$SUDO_PASSWORD" | sudo -p "" -S echo "$(whoami) ALL=(ALL:ALL) NOPASSWD: ALL # TEMPORARY FOR INSTALL DOCTOR" | sudo tee -a /etc/sudoers
@ -173,12 +272,11 @@ if ! sudo cat /etc/sudoers | grep '# TEMPORARY FOR INSTALL DOCTOR' > /dev/null;
echo "$(whoami) ALL=(ALL:ALL) NOPASSWD: ALL # TEMPORARY FOR INSTALL DOCTOR" | sudo tee -a /etc/sudoers
fi
fi
}
# @section Qubes dom0 Bootstrap
# @description Perform Qubes dom0 specific logic like updating system packages, setting up the Tor VM, updating TemplateVMs, and
# beginning the provisioning process using Ansible and an AppVM used to handle the provisioning process
if command -v qubesctl > /dev/null; then
# @section Qubes dom0
# @description Ensure sys-whonix is configured (for Qubes dom0)
ensureSysWhonix() {
CONFIG_WIZARD_COUNT=0
function configureWizard() {
if xwininfo -root -tree | grep "Anon Connection Wizard"; then
@ -205,21 +303,27 @@ if command -v qubesctl > /dev/null; then
fi
fi
}
}
# @description Ensure dom0 is updated
ensureDom0Updated() {
if [ ! -f /root/dom0-updated ]; then
sudo qubesctl --show-output state.sls update.qubes-dom0
sudo qubes-dom0-update --clean -y
touch /root/dom0-updated
fi
}
# @description Ensure sys-whonix is running
ensureSysWhonixRunning() {
if ! qvm-check --running sys-whonix; then
qvm-start sys-whonix --skip-if-running
configureWizard > /dev/null
fi
}
# @description Ensure TemplateVMs are updated
ensureTemplateVMsUpdated() {
if [ ! -f /root/templatevms-updated ]; then
# timeout of 10 minutes is added here because the whonix-gw VM does not like to get updated
# with this method. Anyone know how to fix this?
@ -229,17 +333,20 @@ if command -v qubesctl > /dev/null; then
done< <(qvm-ls --all --no-spinner --fields=name,state | grep Running | grep -v sys-net | grep -v sys-firewall | grep -v sys-whonix | grep -v dom0 | awk '{print $1}')
sudo touch /root/templatevms-updated
fi
}
# @description Ensure provisioning VM can run commands on any VM
ensureProvisioningVMPermissions() {
echo "/bin/bash" | sudo tee /etc/qubes-rpc/qubes.VMShell
sudo chmod 755 /etc/qubes-rpc/qubes.VMShell
echo "${ANSIBLE_PROVISION_VM:=provision}"' dom0 allow' | sudo tee /etc/qubes-rpc/policy/qubes.VMShell
echo "$ANSIBLE_PROVISION_VM"' $anyvm allow' | sudo tee -a /etc/qubes-rpc/policy/qubes.VMShell
sudo chown "$(whoami):$(whoami)" /etc/qubes-rpc/policy/qubes.VMShell
sudo chmod 644 /etc/qubes-rpc/policy/qubes.VMShell
}
# @description Create provisioning VM and initialize the provisioning process from there
createAndInitProvisionVM() {
qvm-create --label red --template debian-11 "$ANSIBLE_PROVISION_VM" &> /dev/null || true
qvm-volume extend "$ANSIBLE_PROVISION_VM:private" "40G"
if [ -f ~/.vaultpass ]; then
@ -247,154 +354,115 @@ if command -v qubesctl > /dev/null; then
qvm-copy-to-vm "$ANSIBLE_PROVISION_VM" ~/.vaultpass
qvm-run "$ANSIBLE_PROVISION_VM" 'cp ~/QubesIncoming/dom0/.vaultpass ~/.vaultpass'
fi
}
# @description Restart the provisioning process with the same script but from the provisioning VM
runStartScriptInProvisionVM() {
qvm-run --pass-io "$ANSIBLE_PROVISION_VM" 'curl -sSL https://install.doctor/start > ~/start.sh && bash ~/start.sh'
}
# @description Perform Qubes dom0 specific logic like updating system packages, setting up the Tor VM, updating TemplateVMs, and
# beginning the provisioning process using Ansible and an AppVM used to handle the provisioning process
handleQubesDom0() {
if command -v qubesctl > /dev/null; then
ensureSysWhonix
ensureDom0Updated
ensureSysWhonixRunning
ensureTemplateVMsUpdated
ensureProvisioningVMPermissions
createAndInitProvisionVM
runStartScriptInProvisionVM
exit 0
fi
}
# @description Ensure basic system packages are available on the device
if ! command -v curl > /dev/null || ! command -v git > /dev/null || ! command -v expect > /dev/null || ! command -v rsync > /dev/null; then
if command -v apt-get > /dev/null; then
# @description Ensure `build-essential`, `curl`, `expect`, `git`, `rsync`, `procps`, and `file` are installed on Debian / Ubuntu
sudo apt-get update
sudo apt-get install -y build-essential curl expect git rsync procps file
elif command -v dnf > /dev/null; then
# @description Ensure `curl`, `expect`, `git`, `rsync`, `procps-ng`, and `file` are installed on Fedora (as well as the Development Tools package)
sudo dnf groupinstall -y 'Development Tools'
sudo dnf install -y curl expect git rsync procps-ng file
elif command -v yum > /dev/null; then
# @description Ensure `curl`, `expect`, `git`, `rsync`, `procps-ng`, and `file` are installed on CentOS (as well as the Development Tools package)
sudo yum groupinstall -y 'Development Tools'
sudo yum install -y curl expect git rsync procps-ng file
elif command -v pacman > /dev/null; then
# @description Ensure `base-devel`, `curl`, `expect`, `git`, `rsync`, `procps-ng`, and `file` are installed on Archlinux
sudo pacman update
sudo pacman -Syu base-devel curl expect git rsync procps-ng file
elif command -v zypper > /dev/null; then
# @description Ensure `curl`, `expect`, `git`, `rsync`, `procps`, and `file` are installed on OpenSUSE (as well as the devel_basis pattern)
sudo zypper install -yt pattern devel_basis
sudo zypper install -y curl expect git rsync procps file
elif command -v apk > /dev/null; then
# @description Ensure `curl`, `expect`, `git`, `rsync`, `procps`, and `file` are installed on Alpine
apk add build-base curl expect git rsync procps file
elif [ -d /Applications ] && [ -d /Library ]; then
# @description Ensure CLI developer tools are available on macOS (via `xcode-select`)
sudo xcode-select -p >/dev/null 2>&1 || xcode-select --install
elif [[ "$OSTYPE" == 'cygwin' ]] || [[ "$OSTYPE" == 'msys' ]] || [[ "$OSTYPE" == 'win32' ]]; then
# @description Ensure `curl`, `expect`, `git`, and `rsync` are installed on Windows
choco install -y curl expect git rsync
# @section Homebrew dependencies
# @description Helper function used by [[ensureHomebrewDeps]] to ensure a Homebrew package is installed after
# first checking if it is already available on the system.
installBrewPackage() {
if ! command -v "$1" > /dev/null; then
logg 'Installing '"$1"''
brew install "$1"
fi
}
# @description Installs various dependencies using Homebrew.
#
# 1. Ensures Chezmoi, Node.js, and ZX are installed.
# 2. Installs Glow and Gum if the `HEADLESS_INSTALL` environment variable is not set.
# 3. If the system is macOS, then also install `gsed`.
ensureHomebrewDeps() {
### TUI experience
if [ -z "$HEADLESS_INSTALL" ]; then
installBrewPackage "gum"
installBrewPackage "glow"
fi
# @description Ensure Homebrew is installed and available
if ! command -v brew > /dev/null; then
if [ -d /home/linuxbrew/.linuxbrew/bin ]; then
eval $(/home/linuxbrew/.linuxbrew/bin/brew shellenv)
if ! command -v brew > /dev/null; then
echo "The /home/linuxbrew/.linuxbrew directory exists but something is not right. Try removing it and running the script again." && exit 1
fi
else
# @description Installs Homebrew and addresses a couple potential issues
if command -v sudo > /dev/null && sudo -n true; then
echo | /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
else
echo "Homebrew is not installed. The script will attempt to install Homebrew and you might be prompted for your password."
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" || BREW_EXIT_CODE="$?"
if [ -n "$BREW_EXIT_CODE" ]; then
if command -v brew > /dev/null; then
echo "Homebrew was installed but part of the installation failed. Trying a few things to fix the installation.."
BREW_DIRS="share/man share/doc share/zsh/site-functions etc/bash_completion.d"
for BREW_DIR in $BREW_DIRS; do
if [ -d "$(brew --prefix)/$BREW_DIR" ]; then
sudo chown -R "$(whoami)" "$(brew --prefix)/$BREW_DIR"
fi
done
brew update --force --quiet
fi
fi
fi
### Base dependencies
installBrewPackage "chezmoi"
installBrewPackage "node"
installBrewPackage "zx"
# @description Ensures the `brew` binary is available on Linux machines. macOS installs `brew` into the default `PATH`
# so nothing needs to be done for macOS.
if [ -d /home/linuxbrew/.linuxbrew/bin ]; then
eval $(/home/linuxbrew/.linuxbrew/bin/brew shellenv)
elif [ -f /opt/homebrew/bin/brew ]; then
eval "$(/opt/homebrew/bin/brew shellenv)"
fi
fi
### macOS
if [ -d /Applications ] && [ -d /System ]; then
installBrewPackage "gsed"
fi
}
# @description Ensure Chezmoi is installed
if ! command -v chezmoi > /dev/null; then
brew install chezmoi
fi
# @description Ensure Node.js is installed
if ! command -v node > /dev/null; then
brew install node
fi
# @description Ensure ZX is installed
if ! command -v zx > /dev/null; then
brew install zx
fi
# @description Install Glow / Gum if the `HEADLESS_INSTALL` variable is not set to true
if [ "$HEADLESS_INSTALL" != 'true' ]; then
# @description Ensure Gum is installed
if ! command -v gum > /dev/null; then
brew install gum
fi
# @description Ensure Glow is installed
if ! command -v glow > /dev/null; then
brew install glow
fi
fi
# @description Ensure the ${XDG_DATA_HOME:-$HOME/.local/share}/chezmoi directory is cloned and up-to-date
logg info 'Setting git http.postBuffer value high for large source repository'
git config --global http.postBuffer 524288000
# @section Chezmoi
# @description Ensure the `${XDG_DATA_HOME:-$HOME/.local/share}/chezmoi` directory is cloned and up-to-date using the previously
# set `START_REPO` as the source repository.
cloneChezmoiSourceRepo() {
logg info 'Setting git http.postBuffer value high for large source repository' && git config --global http.postBuffer 524288000
if [ -d "${XDG_DATA_HOME:-$HOME/.local/share}/chezmoi/.git" ]; then
cd "${XDG_DATA_HOME:-$HOME/.local/share}/chezmoi"
logg info "Pulling the latest changes from ${START_REPO:-https://github.com/megabyte-labs/install.doctor.git}"
git pull origin master
logg info "Changing directory to ${XDG_DATA_HOME:-$HOME/.local/share}/chezmoi" && cd "${XDG_DATA_HOME:-$HOME/.local/share}/chezmoi"
logg info "Pulling the latest changes in ${XDG_DATA_HOME:-$HOME/.local/share}/chezmoi" && git pull origin master
else
logg info "Cloning ${START_REPO} to ${XDG_DATA_HOME:-$HOME/.local/share}/chezmoi"
git clone ${START_REPO} "${XDG_DATA_HOME:-$HOME/.local/share}/chezmoi"
logg info "Ensuring ${XDG_DATA_HOME:-$HOME/.local/share} is a folder" && mkdir -p "${XDG_DATA_HOME:-$HOME/.local/share}"
logg info "Cloning ${START_REPO} to ${XDG_DATA_HOME:-$HOME/.local/share}/chezmoi" && git clone "${START_REPO}" "${XDG_DATA_HOME:-$HOME/.local/share}/chezmoi"
fi
}
# @description If the `${XDG_CONFIG_HOME:-$HOME/.config}/chezmoi/chezmoi.yaml` file is missing, then guide the user through the initial setup
if [ ! -f "${XDG_CONFIG_HOME:-$HOME/.config}/chezmoi/chezmoi.yaml" ]; then
# @description Show introduction message if Glow is installed
# @description Guide the user through the initial setup by showing TUI introduction and accepting input through various prompts.
#
# 1. Show `chezmoi-intro.md` with `glow`
# 2. Prompt for the software group if the `SOFTWARE_GROUP` variable is not defined
# 3. Run `chezmoi init` when the Chezmoi configuration is missing (i.e. `${XDG_CONFIG_HOME:-$HOME/.config}/chezmoi/chezmoi.yaml`)
initChezmoiAndPrompt() {
### Show `chezmoi-intro.md` with `glow`
if command -v glow > /dev/null; then
glow "${XDG_DATA_HOME:-$HOME/.local/share}/chezmoi/docs/terminal/chezmoi-intro.md"
fi
# @description Prompt for the software group if the `SOFTWARE_GROUP` variable is not defined
### Prompt for the software group if the `SOFTWARE_GROUP` variable is not defined
if command -v gum > /dev/null; then
if [ -z "$SOFTWARE_GROUP" ]; then
logg prompt 'Select the software group you would like to install. If your environment is a macOS, Windows, or environment with the DISPLAY environment variable then desktop software will be installed too. The software groups are in the '"${XDG_CONFIG_HOME:-$HOME/.config}/chezmoi/chezmoi.yaml"' file.'
SOFTWARE_GROUP="$(gum choose "Basic" "Standard" "Full")"
SOFTWARE_GROUP="$(gum choose "Basic" "Server" "Standard" "Full")"
export SOFTWARE_GROUP
fi
else
logg error 'Woops! Gum needs to be installed for the guided installation. Try running brew install gum' && exit 1
fi
# @description Run `chezmoi init` when the Chezmoi configuration is missing
if [ ! -f "${XDG_CONFIG_HOME:-$HOME/.config}/chezmoi/chezmoi.yaml" ]; then
### Run `chezmoi init` when the Chezmoi configuration is missing
logg info 'Running chezmoi init since the '"${XDG_CONFIG_HOME:-$HOME/.config}/chezmoi/chezmoi.yaml"' is not present'
chezmoi init
fi
}
# @description Run `chezmoi apply` and enable verbose mode if the `DEBUG_MODE` environment variable is set to true
if [ "$DEBUG_MODE" = 'true' ]; then
DEBUG_MODIFIER="-vvvvv"
# @description Run `chezmoi apply` and enable verbose mode if the `DEBUG_MODE` or `DEBUG` environment variable is set to true
configureDebugMode() {
if [ -n "$DEBUG_MODE" ] || [ -n "$DEBUG" ]; then
logg info "Either DEBUG_MODE or DEBUG environment variables were set so Chezmoi will be run in debug mode"
export DEBUG_MODIFIER="-vvvvv"
fi
}
# @description Save the log of the provision process to `$HOME/.local/var/log/install.doctor/install.doctor.$(date +%s).log` and add the Chezmoi
# `--force` flag if the `HEADLESS_INSTALL` variable is set to true.
# `--force` flag if the `HEADLESS_INSTALL` variable is set to `true`.
runChezmoi() {
mkdir -p "$HOME/.local/var/log/install.doctor"
LOG_FILE="$HOME/.local/var/log/install.doctor/install.doctor.$(date +%s).log"
if [ "$HEADLESS_INSTALL" = 'true' ]; then
@ -428,27 +496,43 @@ else
fi
fi
fi
}
# @description Ensure gsed is available on macOS (for modifying `/etc/sudoers` to remove passwordless sudo)
if [ -d /Applications ] && [ -d /System ]; then
if ! command -v gsed > /dev/null; then
if command -v brew > /dev/null; then
brew install gsed
else
logg warn 'Homebrew is not available and passwordless sudo might still be enabled in /etc/sudoers. Modify the file manually if you wish to disable passwordless sudo.'
fi
fi
fi
# @section Post-provision logic
# @description Ensure temporary passwordless sudo privileges are removed from `/etc/sudoers`
removePasswordlessSudo() {
if command -v gsed > /dev/null; then
sudo gsed -i '/# TEMPORARY FOR INSTALL DOCTOR/d' /etc/sudoers || logg warn 'Failed to remove passwordless sudo from the /etc/sudoers file'
else
sudo sed -i '/# TEMPORARY FOR INSTALL DOCTOR/d' /etc/sudoers || logg warn 'Failed to remove passwordless sudo from the /etc/sudoers file'
fi
}
# @description Render the `docs/terminal/post-install.md` file to the terminal at the end of the provisioning process
postProvision() {
logg success 'Provisioning complete!'
if command -v glow > /dev/null && [ -f "${XDG_DATA_HOME:-$HOME/.local/share}/chezmoi/docs/terminal/post-install.md" ]; then
glow "${XDG_DATA_HOME:-$HOME/.local/share}/chezmoi/docs/terminal/post-install.md"
fi
}
# @section Execution order
# @description The `provisionLogic` function is used to define the order of the script. All of the functions it relies on are defined
# above.
provisionLogic() {
logg info "Setting environment variables" && setEnvironmentVariables
logg info "Handling CI variables" && setCIEnvironmentVariables
logg info "Ensuring WARP is disconnected" && ensureWarpDisconnected
logg info "Ensuring system Homebrew dependencies are installed" && ensureBasicDeps
logg info "Ensuring Homebrew is available" && ensureHomebrew
logg info "Applying passwordless sudo" && setupPasswordlessSudo
logg info "Handling Qubes dom0 logic (if applicable)" && handleQubesDom0
logg info "Cloning / updating source repository" && cloneChezmoiSourceRepo
logg info "Handling pre-provision logic" && initChezmoiAndPrompt
logg info "Handling debug mode if DEBUG or DEBUG_MODE are defined" && configureDebugMode
logg info "Running the Chezmoi provisioning" && runChezmoi
logg info "Ensuring temporary passwordless sudo is removed" && removePasswordlessSudo
logg info "Handling post-provision logic" && postProvision
}
provisionLogic

View file

@ -42,11 +42,13 @@
#
# [SSH with short-lived certificates](https://developers.cloudflare.com/cloudflare-one/tutorials/ssh-cert-bastion/)
{{ include "partials" "logg" -}}
# @description Ensure dependencies like `git` and `curl` are installed (among a few other lightweight system packages)
{{ include "partials" "basic-deps" }}
{{ include "partials" "basic-deps" -}}
# @description Ensure Homebrew is installed and available in the `PATH`
{{ include "partials" "homebrew" }}
{{ include "partials" "homebrew" -}}
# @description Ensures `cloudflared` is installed via Homebrew
if ! command -v cloudflared > /dev/null; then

View file

@ -11,4 +11,4 @@
#
# **Note**: `https://install.doctor/brew` points to this file.
{{ include "partials" "homebrew" }}
{{ include "partials" "homebrew" -}}

View file

@ -6,6 +6,6 @@
#
# 1. [Netdata Cloud](https://learn.netdata.cloud/docs/installing/pfsense)
{{ include "partials" "logg" }}
{{ include "partials" "logg" -}}
{{ include "partials" "pfsense" }}
{{ include "partials" "pfsense" -}}

View file

@ -51,7 +51,7 @@
# [Install Doctor homepage](https://install.doctor)
# [Install Doctor documentation portal](https://install.doctor/docs) (includes tips, tricks, and guides on how to customize the system to your liking)
{{ include "partials" "logg" }}
{{ include "partials" "logg" -}}
# @section Environment variables and system dependencies
# @description Ensure Ubuntu / Debian run in `noninteractive` mode. Detect `START_REPO` format and determine appropriate git address,
@ -79,12 +79,12 @@ setEnvironmentVariables() {
# @description Ensure dependencies like `git` and `curl` are installed (among a few other lightweight system packages)
ensureBasicDeps() {
{{ include "partials" "basic-deps" }}
{{ include "partials" "basic-deps" -}}
}
# @description Ensure Homebrew is installed and available in the `PATH`
ensureHomebrew() {
{{ include "partials" "homebrew" }}
{{ include "partials" "homebrew" -}}
}
# @description Load default settings if it is in a CI setting
@ -294,7 +294,7 @@ initChezmoiAndPrompt() {
if command -v gum > /dev/null; then
if [ -z "$SOFTWARE_GROUP" ]; then
logg prompt 'Select the software group you would like to install. If your environment is a macOS, Windows, or environment with the DISPLAY environment variable then desktop software will be installed too. The software groups are in the '"${XDG_CONFIG_HOME:-$HOME/.config}/chezmoi/chezmoi.yaml"' file.'
SOFTWARE_GROUP="$(gum choose "General-Purpose-Server" "Basic" "Standard" "Full")"
SOFTWARE_GROUP="$(gum choose "Basic" "Server" "Standard" "Full")"
export SOFTWARE_GROUP
fi
else
@ -317,7 +317,7 @@ configureDebugMode() {
}
# @description Save the log of the provision process to `$HOME/.local/var/log/install.doctor/install.doctor.$(date +%s).log` and add the Chezmoi
# `--force` flag if the `HEADLESS_INSTALL` variable is set to `true``.
# `--force` flag if the `HEADLESS_INSTALL` variable is set to `true`.
runChezmoi() {
mkdir -p "$HOME/.local/var/log/install.doctor"
LOG_FILE="$HOME/.local/var/log/install.doctor/install.doctor.$(date +%s).log"