#!/usr/bin/env bash set -eox pipefail {{- includeTemplate "universal/logg" }} ### Qubes dom0 if command -v qubesctl > /dev/null; then # The VM name that will manage the Ansible provisioning (for Qubes dom0) ANSIBLE_PROVISION_VM="provision" # Ensure sys-whonix is configured (for Qubes dom0) CONFIG_WIZARD_COUNT=0 ENABLE_OBFSC='false' function configureWizard() { if xwininfo -root -tree | grep "Anon Connection Wizard"; then WINDOW_ID="$(xwininfo -root -tree | grep "Anon Connection Wizard" | sed 's/^ *\([^ ]*\) .*/\1/')" xdotool windowactivate "$WINDOW_ID" && sleep 1 && xdotool key 'Enter' && sleep 1 && xdotool key 'Tab Tab Enter' && sleep 24 && xdotool windowactivate "$WINDOW_ID" && sleep 1 && xdotool key 'Enter' && sleep 300 qvm-shutdown --wait sys-whonix sleep 3 qvm-start sys-whonix if xwininfo -root -tree | grep "systemcheck | Whonix" > /dev/null; then WINDOW_ID_SYSCHECK="$(xwininfo -root -tree | grep "systemcheck | Whonix" | sed 's/^ *\([^ ]*\) .*/\1/')" if xdotool windowactivate "$WINDOW_ID_SYS_CHECK"; then sleep 1 xdotool key 'Enter' fi fi else sleep 3 CONFIG_WIZARD_COUNT=$((CONFIG_WIZARD_COUNT + 1)) if [[ "$CONFIG_WIZARD_COUNT" == '4' ]]; then echo "The sys-whonix anon-connection-wizard utility did not open." else echo "Checking for anon-connection-wizard again.." configureWizard fi fi } ### Ensure dom0 is updated 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 ### Ensure sys-whonix is running if ! qvm-check --running sys-whonix; then qvm-start sys-whonix --skip-if-running configureWizard > /dev/null fi ### Ensure TemplateVMs are updated 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? sudo timeout 600 qubesctl --show-output --skip-dom0 --templates state.sls update.qubes-vm &> /dev/null || EXIT_CODE=$? while read RESTART_VM; do qvm-shutdown --wait "$RESTART_VM" 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 ### Ensure provisioning VM can run commands on any VM echo "/bin/bash" | sudo tee /etc/qubes-rpc/qubes.VMShell sudo chmod 755 /etc/qubes-rpc/qubes.VMShell echo "$ANSIBLE_PROVISION_VM"' 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 ### Create provisioning VM and initialize the provisioning process from there qvm-create --label red --template debian-11 "$ANSIBLE_PROVISION_VM" &> /dev/null || EXIT_CODE=$? qvm-volume extend "$ANSIBLE_PROVISION_VM:private" "40G" if [ -f ~/.vaultpass ]; then qvm-run "$ANSIBLE_PROVISION_VM" 'rm -f ~/QubesIncoming/dom0/.vaultpass' qvm-copy-to-vm "$ANSIBLE_PROVISION_VM" ~/.vaultpass qvm-run "$ANSIBLE_PROVISION_VM" 'cp ~/QubesIncoming/dom0/.vaultpass ~/.vaultpass' fi qvm-run --pass-io "$ANSIBLE_PROVISION_VM" 'curl -sSL https://install.doctor/start > ~/start.sh && bash ~/start.sh' exit 0 fi ### System package manager update / Homebrew dependencies if ! command -v curl > /dev/null || ! command -v git > /dev/null; then logg 'Ensuring `curl` and `git` are installed via the system package manager' if command -v apt-get > /dev/null; then # Debian / Ubuntu sudo apt-get update sudo apt-get install -y curl git elif command -v dnf > /dev/null; then # Fedora sudo dnf install -y curl git elif command -v yum > /dev/null; then # CentOS sudo yum install -y curl git elif command -v pacman > /dev/null; then # Archlinux sudo pacman update sudo pacman -Sy curl git elif command -v zypper > /dev/null; then # OpenSUSE sudo zypper install -y curl git nodejs elif command -v apk > /dev/null; then # Alpine apk add curl git elif [ -d /Applications ] && [ -d /Library ]; then # macOS sudo xcode-select -p >/dev/null 2>&1 || xcode-select --install elif command -v nix-env > /dev/null; then # NixOS echo "TODO - Add support for NixOS" elif [[ "$OSTYPE" == 'freebsd'* ]]; then # FreeBSD echo "TODO - Add support for FreeBSD" elif command -v pkg > /dev/null; then # Termux echo "TODO - Add support for Termux" elif command -v xbps-install > /dev/null; then # Void echo "TODO - Add support for Void" elif [[ "$OSTYPE" == 'cygwin' ]] || [[ "$OSTYPE" == 'msys' ]] || [[ "$OSTYPE" == 'win32' ]]; then # Windows choco install -y curl git node fi fi ### Install Homebrew ensurePackageManagerHomebrew() { if ! command -v brew > /dev/null; then logg info 'Installing Homebrew' if command -v sudo > /dev/null && sudo -n true; then echo | bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" else logg info 'Looks like the user does not have passwordless sudo privileges. A sudo password may be required.' 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. Attempting to fix..' 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 fi } ensurePackageManagerHomebrew ### Install installer dependencies via Homebrew installBrewPackage() { if ! command -v "$1" > /dev/null; then logg 'Installing `'"$1"'`' brew install "$1" fi } if command -v brew > /dev/null; then installBrewPackage chezmoi installBrewPackage glow installBrewPackage gum installBrewPackage node installBrewPackage zx fi ### Ensure source files are present logg 'Ensuring /usr/local/src/hiawatha is owned by the user' if [ -d /usr/local/src/hiawatha ] && [ ! -w /usr/local/src/hiawatha ]; then sudo chown -Rf "$USER":"$(id -g -n)" /usr/local/src/hiawatha fi if [ -d /usr/local/src/hiawatha/.git ]; then logg info 'Pulling the latest changes from https://gitlab.com/megabyte-labs/dotfiles.git to /usr/local/src/hiawatha' cd /usr/local/src/hiawatha git config pull.rebase false git reset --hard HEAD git clean -fxd git pull origin master else logg info 'Cloning https://gitlab.com/megabyte-labs/dotfiles.git to /usr/local/src/hiawatha' rm -rf /usr/local/src/hiawatha sudo git clone https://gitlab.com/megabyte-labs/dotfiles.git /usr/local/src/hiawatha chown -Rf "$USER":"$(id -g -n)" /usr/local/src/hiawatha fi ### Copy folders logg info 'Copying folders from /usr/local/src/hiawatha to the HOME directory' find /usr/local/src/hiawatha -maxdepth 1 -mindepth 1 -type d | while read FOLDER; do BASENAME="$(basename "$FOLDER")" # Prevent initial-scaffolding of OS-specific files since Chezmoi will handle them if [ "$BASENAME" != 'AppData' ] && [ "$BASENAME" != 'Library' ] && [ "$BASENAME" != '.git' ]; then if [ ! -d "$HOME/$BASENAME" ]; then mkdir -p "$HOME/$BASENAME" fi cp -rf "$FOLDER/"* "$HOME/$BASENAME" fi done ### Copy files logg info 'Copying files from /usr/local/src/hiawatha to the HOME directory' find /usr/local/src/hiawatha -maxdepth 1 -mindepth 1 -type f | while read FILE; do BASENAME="$(basename "$FILE")" # Prevent repository-specific files from being copied over to user's HOME if [[ "$BASENAME" != *'.md' ]] && [[ "$BASENAME" != *'.sh' ]] && [ "$BASENAME" != '.chezmoiroot' ] && [ "$BASENAME" != 'logo.png' ] && [ "$BASENAME" != '.gitlab-ci.yml' ]; then cp "$FILE" "$HOME/$BASENAME" chmod 600 "$HOME/$BASENAME" fi done ### Ensure ~/.local/bin files are executable logg info 'Ensuring scripts in ~/.local/bin are executable' find "$HOME/.local/bin" -maxdepth 1 -mindepth 1 -type f | while read BINFILE; do chmod +x "$BINFILE" done ### Chezmoi if [ ! -f "$HOME/.config/chezmoi/chezmoi.yaml" ]; then logg info 'Running `chezmoi init` since the ~/.config/chezmoi/chezmoi.yaml is not present' chezmoi init fi logg info 'Running `chezmoi apply`' cat <> /tmp/chezmoi-intro # User / Environment Variables This script will automatically set up a handful of different configurations should you decide to add your information. Below you can find a description of what each piece of information is used for as well as the name of the environment variable you can specify to bypass the prompt. ## Work Environment Set to true if you are setting up a work environment where things like Tor should not be installed. * Environment variable: `WORK_ENVIRONMENT` ## Restricted Environment Set to true if you are setting up an environment that should not use sudo / administrator privileges. This is a WIP. * Environment variable: `RESTRICTED_ENVIRONMENT` ## Software Group The category you select for software group will determine which list of software should be installed. The lists are configurable by modifying `~/.local/share/chezmoi/software.yml`. * Environment variable: `SOFTWARE_GROUP` ## Name Enter your full name as you would like it to appear in configuration files such as the Git configuration. * Environment variable: `FULL_NAME` ## E-mail Enter your primary e-mail address. * Environment variable: `PRIMARY_EMAIL` ## Public GPG Key ID If you have a public GPG key available on the Ubuntu or MIT keyservers, then you can enter it so that it is automatically imported. * Environment variable: `KEYID` ## Timezone Enter your timezone in the format of `America/New_York`. It should be available in the TZ database. * Environment variable: `TIMEZONE` ## Domain The domain address you would like to use for any part of the deployment that involves launching a publicly web service. * Environment variable: `PUBLIC_SERVICES_DOMAIN` ## CloudFlare API Token The API token is used to automatically configure various web services that rely on public DNS records. * Environment variable: `CLOUDFLARE_API_TOKEN` ## GitHub Read-Only Token Pass in a GitHub read-only token linked to your account to automatically save a backup of your GitHub repositories. * Environment variable: `GITHUB_READ_TOKEN` ## GitLab Read-Only Token Pass in a GitLab read-only token linked to your account to automatically save a backup of your GitLab repositories. * Environment variable: `GITLAB_READ_TOKEN` ## G-mail Address Add a G-mail address which you would like to use as the handler for outgoing SMTP mail. * Environment variable: `GMAIL_ADDRESS` ## G-mail App Password Add the app password to your G-mail address so that outgoing mail can be handled by G-mail. * Environment variable: `GMAIL_APP_PASSWORD` ## Ngrok Authentication Token Add your Ngrok authentication token so that the configuration file can be automatically generated. * Environment Variable: `NGROK_AUTH_TOKEN` ## Slack API Token Add your Slack API token so that `slackterm` can be automatically set up. * Environment Variable: `SLACK_API_TOKEN` ## Tabby Configuration ID Add your Tabby configuration ID to automatically sync Tabby settings. * Environment Variable: `TABBY_CONFIG_ID` ## Tabby Sync Token Add your Tabby sync token to automatically sync Tabby settings. This works in conjunction with the Tabby Configuration ID mentioned above. * Environment Variable: `TABBY_SYNC_TOKEN` ## EOF glow /tmp/chezmoi-intro 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 ~/.local/share/chezmoi/home/.chezmoidata.yaml file.' SOFTWARE_GROUP="$(gum choose "Basic" "Standard" "Development" "Experimental")" chezmoi apply