Moving scripts to post scripts

This commit is contained in:
Brian Zalewski 2024-05-04 02:40:44 +00:00
parent 602c1f630a
commit 236a008f7a
22 changed files with 1393 additions and 1370 deletions

View file

@ -7,7 +7,7 @@ let installOrder, osArch, osId, osType, pkgs, sysType
const cacheDir = os.homedir() + '/.cache/installx'
function log(message) {
process.env.DEBUG && console.log(`${chalk.cyanBright('instx->')} ${message}`)
console.log(`${chalk.cyanBright('instx->')} ${message}`)
}
async function getOsInfo() {

View file

@ -0,0 +1,23 @@
#!/usr/bin/env bash
# @file DockerHub Login
# @brief Logs into DockerHub for Docker Desktop
# @description
# This script logs into DockerHub so that Docker Desktop is pre-authenticated. This
# functionality requires that the `DOCKERHUB_USER` be passed in as an environment variable (or
# directly editted in the `~/.config/chezmoi/chezmoi.yaml` file) and that the `DOCKERHUB_TOKEN`
# be passed in as a secret (either via the encrypted secret method or passed in as an environment
# variable).
if command -v docker > /dev/null; then
DOCKERHUB_TOKEN="{{ if (stat (joinPath .chezmoi.sourceDir ".chezmoitemplates" "secrets" "DOCKERHUB_TOKEN")) }}{{- includeTemplate "secrets/DOCKERHUB_TOKEN" | decrypt | trim -}}{{ else }}{{- env "DOCKERHUB_TOKEN" -}}{{ end }}"
DOCKERHUB_USER="{{ .user.docker.username }}"
if [ -d "/Applications/Docker.app" ] || [ -d "$HOME/Applications/Docker.app" ]; then
logg info 'Ensuring Docker.app is open' && open --background -a Docker --args --accept-license --unattended
fi
logg info 'Headlessly authenticating with DockerHub registry' && echo "$DOCKERHUB_TOKEN" | docker login -u "$DOCKERHUB_USER" --password-stdin > /dev/null && logg success 'Successfully authenticated with DockerHub registry'
fi
### Symlink on macOS
if [ -f "$HOME/Library/Containers/com.docker.docker/Data/docker.raw.sock" ]; then
logg info 'Symlinking /var/run/docker.sock to macOS Library location' && sudo ln -s "$HOME/Library/Containers/com.docker.docker/Data/docker.raw.sock" /var/run/docker.sock
fi

View file

@ -0,0 +1,10 @@
#!/usr/bin/env bash
# @file EasyEngine
# @brief Configures EasyEngine to use the CloudFlare API for configuring Let's Encrypt
if command -v ee > /dev/null; then
if [ -n "$CLOUDFLARE_EMAIL" ] && [ -n "$CLOUDFLARE_API_KEY" ]; then
ee config set le-mail "$CLOUDFLARE_EMAIL"
ee config set cloudflare-api-key "$CLOUDFLARE_API_KEY"
fi
fi

View file

@ -0,0 +1,45 @@
#!/usr/bin/env bash
# @file Endlessh Configuration
# @brief Applies the Endlessh configuration and starts the service on Linux systems
function configureEndlessh() {
### Update the service configuration file
logg info 'Updating endlessh service configuration file'
sudo sed -i 's/^.*#AmbientCapabilities=CAP_NET_BIND_SERVICE/AmbientCapabilities=CAP_NET_BIND_SERVICE/' /usr/lib/systemd/system/endlessh.service
sudo sed -i 's/^.*PrivateUsers=true/#PrivateUsers=true/' /usr/lib/systemd/system/endlessh.service
logg info 'Reloading systemd' && sudo systemctl daemon-reload
### Update capabilities of `endlessh`
logg info 'Updating capabilities of endlessh' && sudo setcap 'cap_net_bind_service=+ep' /usr/bin/endlessh
### Restart / enable Endlessh
logg info 'Enabling the endlessh service' && sudo systemctl enable endlessh
logg info 'Restarting the endlessh service' && sudo systemctl restart endlessh
}
### Update /etc/endlessh/config if environment is not WSL
if [[ ! "$(test -d proc && grep Microsoft /proc/version > /dev/null)" ]]; then
if command -v endlessh > /dev/null; then
if [ -d /etc/endlessh ]; then
logg info 'Copying ~/.ssh/endlessh/config to /etc/endlessh/config' && sudo cp -f "$HOME/.ssh/endlessh/config" /etc/endlessh/config
configureEndlessh || CONFIGURE_EXIT_CODE=$?
if [ -n "$CONFIGURE_EXIT_CODE" ]; then
logg error 'Configuring endlessh service failed' && exit 1
else
logg success 'Successfully configured endlessh service'
fi
elif [ -f /etc/endlessh.conf ]; then
logg info 'Copying ~/.ssh/endlessh/config to /etc/endlessh.conf' && sudo cp -f "$HOME/.ssh/endlessh/config" /etc/endlessh.conf
configureEndlessh || CONFIGURE_EXIT_CODE=$?
if [ -n "$CONFIGURE_EXIT_CODE" ]; then
logg error 'Configuring endlessh service failed' && exit 1
else
logg success 'Successfully configured endlessh service'
fi
else
logg warn 'Neither the /etc/endlessh folder nor the /etc/endlessh.conf file exist'
fi
else
logg info 'Skipping Endlessh configuration because the endlessh executable is not available in the PATH'
fi
else
logg info 'Skipping Endlessh configuration since environment is WSL'
fi

View file

@ -0,0 +1,26 @@
#!/usr/bin/env bash
# @file Store Secrets in Keyring
# @brief Stores secret environment variables into the System keyring
# @description
# This script imports secret environment variables into the System keyring if `envchain` is installed.
# Secrets stored in the folder 'home/.chezmoitemplates/secrets' following the Install Doctor method are
# imported into the System keyring by this script. There is only one namespace called `default` where the
# secrets are stored. Executing `envchain default env` displays all the environment variables and their values.
#
# ## Secrets
#
# For more information about storing secrets like SSH keys and API keys, refer to our [Secrets documentation](https://install.doctor/docs/customization/secrets).
### Import environment variables into `envchain`
if command -v envchain > /dev/null; then
if [ -f "$HOME/.config/age/chezmoi.txt" ]; then
logg info 'Importing environment variables into the System keyring'
for file in {{ joinPath .chezmoi.sourceDir ".chezmoitemplates" "secrets" "*" }}; do
cat "$file" | chezmoi decrypt | envchain -s default "$(basename $file)" > /dev/null || logg info 'Importing "$(basename $file)" failed'
done
else
logg warn 'Unable to import any variables into envchain because ~/.config/age/chezmoi.txt was not created by the secrets encryption process yet'
fi
else
logg info 'envchain is not installed or it is not available in the PATH'
fi

View file

@ -0,0 +1,52 @@
#!/usr/bin/env bash
# @file Fail2ban Configuration
# @brief Applies the system `fail2ban` jail configuration and then restarts the service
# @description
# Fail2ban is an SSH security program that temporarily bans IP addresses that could possibly be
# attempting to gain unauthorized system access. This script applies the "jail" configuration
# located at `home/private_dot_ssh/fail2ban/` to the system location. It then enables and restarts
# the `fail2ban` configuration.
#
# ## Links
#
# * [`fail2ban` configuration folder](https://github.com/megabyte-labs/install.doctor/tree/master/home/private_dot_ssh/fail2ban)
### Notify of script start
logg info 'Configuring fail2ban'
### Restart fail2ban
function restartFailToBan() {
if [ -d /Applications ] && [ -d /System ]; then
### macOS
logg info 'Enabling the fail2ban Homebrew service'
brew services restart fail2ban
else
# Linux
logg info 'Enabling the fail2ban service'
sudo systemctl enable fail2ban
logg info 'Restarting the fail2ban service'
sudo systemctl restart fail2ban
fi
}
### Update the jail.local file if environment is not WSL
logg info 'Checking if script is being run in WSL environment'
if [[ ! "$(test -d /proc && grep Microsoft /proc/version > /dev/null)" ]]; then
if [ -d /etc/fail2ban ]; then
logg info 'Copying ~/.ssh/fail2ban/jail.local to /etc/fail2ban/jail.local'
sudo cp -f "$HOME/.ssh/fail2ban/jail.local" /etc/fail2ban/jail.local
restartFailToBan
elif [ -d /usr/local/etc/fail2ban ]; then
logg info 'Copying ~/.ssh/fail2ban/jail.local to /usr/local/etc/fail2ban/jail.local'
sudo cp -f "$HOME/.ssh/fail2ban/jail.local" /usr/local/etc/fail2ban/jail.local
restartFailToBan
elif [ -d "${HOMEBREW_PREFIX:-/opt/homebrew}/etc/fail2ban" ]; then
logg info "Copying ~/.ssh/fail2ban/jail.local to ${HOMEBREW_PREFIX:-/opt/homebrew}/etc/fail2ban/jail.local"
sudo cp -f "$HOME/.ssh/fail2ban/jail.local" "${HOMEBREW_PREFIX:-/opt/homebrew}/etc/fail2ban/jail.local"
restartFailToBan
else
logg warn 'The /etc/fail2ban (Linux), the /usr/local/etc/fail2ban, and the ${HOMEBREW_PREFIX:-/opt/homebrew}/etc/fail2ban (macOS) folder do not exist'
fi
else
logg info 'Skipping sshd_config application since environment is WSL'
fi

View file

@ -0,0 +1,10 @@
#!/usr/bin/env bash
# @file Fig Login
# @brief Logs into Fig using the FIG_TOKEN
if command -v fig > /dev/null; then
source ~/.config/shell/private.sh
fig login --token "$FIG_TOKEN" || logg info 'Fig login failed - User might already be logged in'
else
logg warn 'fig is not available in the PATH'
fi

View file

@ -0,0 +1,320 @@
#!/usr/bin/env bash
# @file Firefox Settings / Add-Ons / Profiles
# @brief This script configures system-wide settings, sets up Firefox Profile Switcher, creates various profiles from different sources, and installs a configurable list of Firefox Add-Ons.
# @description
# The Firefox setup script performs a handful of tasks that automate the setup of Firefox as well as
# useful utilities that will benefit Firefox power-users. The script also performs the same logic on
# [LibreWolf](https://librewolf.net/) installations.
#
# ## Features
#
# * Installs and sets up [Firefox Profile Switcher](https://github.com/null-dev/firefox-profile-switcher)
# * Sets up system-wide enterprise settings (with configurations found in `~/.local/share/firefox`)
# * Sets up a handful of default profiles to use with the Firefox Profile Switcher
# * Automatically installs the plugins defined in the firefoxAddOns key of [`home/.chezmoidata.yaml`](https://github.com/megabyte-labs/install.doctor/blob/master/home/.chezmoidata.yaml) to the Standard and Private profiles
# * Configures the default profile to clone its settings from the profile stored in firefoxPublicProfile of `home/.chezmoidata.yaml`
# * Optionally, if the Chezmoi encryption key is present, then the default profile will be set to the contents of an encrypted `.tar.gz` that must be stored in the cloud somewhere (with the firefoxPrivateProfile key in `home/.chezmoidata.yaml` defining the URL of the encrypted `.tar.gz`)
#
# ## Profiles
#
# The script sets up numerous profiles for user flexibility. They can be switched by using the Firefox Profile Switcher
# that this script sets up. The map of the profiles is generated by using the template file stored in `~/.local/share/firefox/profiles.ini`.
# The following details the features of each profile:
#
# | Name | Description |
# |------------------|---------------------------------------------------------------------------------------------|
# | Factory | Default browser settings (system-wide configurations still apply) |
# | default-release | Same as Factory (unmodified and generated by headlessly opening Firefox / LibreWolf) |
# | Git (Public) | Pre-configured profile with address stored in `firefoxPublicProfile` |
# | Standard | Cloned from the profile above with `firefoxAddOns` also installed |
# | Miscellaneous | Cloned from the Factory profile (with the user.js found in `~/.config/firefox` applied) |
# | Development | Same as Miscellaneous |
# | Automation | Same as Miscellaneous |
# | Private | Populated from an encrypted profile stored in the cloud (also installs `firefoxAddOns`) |
#
# ## Notes
#
# * The Firefox Profile Switcher is only compatible with Firefox and not LibreWolf
# * This script is only designed to properly provision profiles on a fresh installation (so it does not mess around with pre-existing / already configured profiles)
# * Additional profiles for LibreWolf are not added because the Firefox Profile Switcher is not compatible with LibreWolf
#
# ## Links
#
# * [System-wide configurations](https://github.com/megabyte-labs/install.doctor/tree/master/home/dot_local/share/firefox) as well as the location of the `profile.ini` and some other configurations
# * [User-specific configurations](https://github.com/megabyte-labs/install.doctor/blob/master/home/dot_config/firefox/user.js) added to all profiles except Factory
function installFirefoxProfileConnector() {
logg info 'Installing the Firefox Profile Connector'
if command -v apt-get > /dev/null; then
sudo apt-get install -y https://github.com/null-dev/firefox-profile-switcher-connector/releases/latest/download/linux-x64.deb
elif command -v dnf > /dev/null; then
sudo dnf install -y https://github.com/null-dev/firefox-profile-switcher-connector/releases/latest/download/linux-x64.rpm
elif command -v yay > /dev/null; then
yay -Ss firefox-profile-switcher-connector
else
logg warn 'apt-get, dnf, and yay were all unavailable so the Firefox Profile Connector helper executable could not be installed'
fi
}
function firefoxSetup() {
### Installs the Firefox Profile Connector on Linux systems (Snap / Flatpak installs are not included in this function, but instead inline below)
### Add Firefox enterprise profile
# TODO - figure out how to do this for other installations like Flatpak and macOS and Librewolf
for FIREFOX_DIR in '/usr/lib/firefox' '/usr/lib/firefox-esr' '/etc/firefox' '/etc/firefox-esr' '/Applications/Firefox.app/Contents/Resources'; do
if [ -d "$FIREFOX_DIR" ] && [ -d "${XDG_DATA_HOME:-$HOME/.local/share}/firefox" ] && command -v rsync > /dev/null; then
logg info "Syncing enterprise profiles from ${XDG_DATA_HOME:-$HOME/.local/share}/firefox to $FIREFOX_DIR"
sudo rsync -artvu "${XDG_DATA_HOME:-$HOME/.local/share}/firefox/" "$FIREFOX_DIR" > /dev/null
fi
done
### Loop through various Firefox profile locations
for SETTINGS_DIR in "$HOME/snap/firefox/common/.mozilla/firefox" "$HOME/.var/app/org.mozilla.firefox/.mozilla/firefox" "$HOME/Library/Application Support/Firefox/Profiles" "$HOME/.mozilla/firefox"; do
### Determine executable to use
logg info "Processing Firefox profile location $SETTINGS_DIR"
unset FIREFOX_EXE
if [ "$SETTINGS_DIR" == "$HOME/.var/app/org.mozilla.firefox/.mozilla/firefox" ]; then
if ! command -v org.mozilla.firefox > /dev/null || [ ! -d "$HOME/.var/app/org.mozilla.firefox" ]; then
continue
else
FIREFOX_EXE="$(which org.mozilla.firefox)"
### Firefox Profile Switcher
BASE_DIR="$HOME/.var/app/org.mozilla.firefox"
BIN_INSTALL_DIR="$BASE_DIR/data/firefoxprofileswitcher-install"
MANIFEST_INSTALL_DIR="$BASE_DIR/.mozilla/native-messaging-hosts"
DOWNLOAD_URL="https://github.com/null-dev/firefox-profile-switcher-connector/releases/latest/download/linux-x64.deb"
### Ensure Firefox Profile Switcher is not already installed
if [ ! -f "$BIN_INSTALL_DIR/usr/bin/ff-pswitch-connector" ] || [ ! -f "$MANIFEST_INSTALL_DIR/ax.nd.profile_switcher_ff.json" ]; then
### Download profile switcher
mkdir -p "$BIN_INSTALL_DIR"
TMP_FILE="$(mktemp)"
logg info 'Downloading Firefox Profile Switch connector'
curl -sSL "$DOWNLOAD_URL" -o "$TMP_FILE"
ar p "$TMP_FILE" data.tar.xz | tar xfJ - --strip-components=2 -C "$BIN_INSTALL_DIR" usr/bin/ff-pswitch-connector
rm -f "$TMP_FILE"
### Create manifest
logg info 'Copying profile switcher configuration to manifest directory'
mkdir -p "$MANIFEST_INSTALL_DIR"
cat "${XDG_DATA_HOME:-$HOME/.local/share}/firefox/profile-switcher.json" | sed 's=PATH_PLACEHOLDER='"$BIN_INSTALL_DIR"'=' > "$MANIFEST_INSTALL_DIR/ax.nd.profile_switcher_ff.json"
fi
fi
elif [ "$SETTINGS_DIR" == "$HOME/.var/app/io.gitlab.librewolf-community/.librewolf" ]; then
if ! command -v io.gitlab.librewolf-community > /dev/null || [ ! -d "$HOME/.var/app/io.gitlab.librewolf-community" ]; then
continue
else
continue
# FIREFOX_EXE="$(which io.gitlab.librewolf-community)"
fi
elif [ "$SETTINGS_DIR" == "$HOME/Library/Application Support/Firefox/Profiles" ]; then
FIREFOX_EXE="/Applications/Firefox.app/Contents/MacOS/firefox"
if [ ! -f "$FIREFOX_EXE" ] || [ ! -d /Applications ]; then
continue
else
### Download Firefox Profile Switcher
if [ ! -d /usr/local/Cellar/firefox-profile-switcher-connector ]; then
logg info 'Ensuring Firefox Profile Switcher is installed'
brew install --quiet null-dev/firefox-profile-switcher/firefox-profile-switcher-connector
fi
### Ensure Firefox Profile Switcher configuration is symlinked
if [ ! -d "/Library/Application Support/Mozilla/NativeMessagingHosts/ax.nd.profile_switcher_ff.json" ]; then
logg info 'Ensuring Firefox Profile Switcher is configured'
sudo mkdir -p "/Library/Applcation Support/Mozilla/NativeMessagingHosts"
sudo ln -sf "$(brew ls -l firefox-profile-switcher-connector | grep -i ax.nd.profile_switcher_ff.json | head -n1)" "/Library/Application Support/Mozilla/NativeMessagingHosts/ax.nd.profile_switcher_ff.json"
fi
fi
elif [ "$SETTINGS_DIR" == "$HOME/Library/Application Support/LibreWolf/Profiles" ]; then
continue
# FIREFOX_EXE="/Applications/LibreWolf.app/Contents/MacOS/librewolf"
# if [ ! -f "$FIREFOX_EXE" ] || [ ! -d /Applications ]; then
# logg info "$FIREFOX_EXE is not a file"
# continue
# fi
elif [ "$SETTINGS_DIR" == "$HOME/snap/firefox/common/.mozilla/firefox" ]; then
FIREFOX_EXE="/snap/bin/firefox"
if [ ! -f "$FIREFOX_EXE" ] || [ ! -d "$HOME/snap/firefox" ]; then
continue
else
### Firefox Profile Switcher
BASE_DIR="$HOME/snap/firefox/common"
BIN_INSTALL_DIR="$BASE_DIR/firefoxprofileswitcher-install"
MANIFEST_INSTALL_DIR="$BASE_DIR/.mozilla/native-messaging-hosts"
DOWNLOAD_URL="https://github.com/null-dev/firefox-profile-switcher-connector/releases/latest/download/linux-x64.deb"
### Ensure Firefox Profile Switcher is not already installed
if [ ! -f "$BIN_INSTALL_DIR/usr/bin/ff-pswitch-connector" ] || [ ! -f "$MANIFEST_INSTALL_DIR/ax.nd.profile_switcher_ff.json" ]; then
### Download profile switcher
mkdir -p "$BIN_INSTALL_DIR"
TMP_FILE="$(mktemp)"
logg info 'Downloading Firefox Profile Switch connector'
curl -sSL "$DOWNLOAD_URL" -o "$TMP_FILE"
ar p "$TMP_FILE" data.tar.xz | tar xfJ - --strip-components=2 -C "$BIN_INSTALL_DIR" usr/bin/ff-pswitch-connector
rm -f "$TMP_FILE"
### Create manifest
logg info 'Copying profile switcher configuration to manifest directory'
mkdir -p "$MANIFEST_INSTALL_DIR"
cat "${XDG_DATA_HOME:-$HOME/.local/share}/firefox/profile-switcher.json" | sed 's/PATH_PLACEHOLDER/'"$BIN_INSTALL_DIR"'/' > "$MANIFEST_INSTALL_DIR/ax.nd.profile_switcher_ff.json"
fi
fi
elif [ "$SETTINGS_DIR" == "$HOME/.mozilla/firefox" ]; then
if command -v firefox-esr > /dev/null; then
FIREFOX_EXE="$(which firefox-esr)"
installFirefoxProfileConnector
elif command -v firefox > /dev/null && [ "$(which firefox)" != *'snap'* ] && [ "$(which firefox)" != *'flatpak'* ] && [ ! -d /Applications ] && [ ! -d /System ]; then
# Conditional check ensures Snap / Flatpak / macOS Firefox versions do not try to install to the wrong folder
FIREFOX_EXE="$(which firefox)"
installFirefoxProfileConnector
else
if [ -d /Applications ] && [ -d /System ]; then
# Continue on macOS without logging because profiles are not stored here on macOS
continue
else
logg warn 'Unable to register Firefox executable'
logg info "Settings directory: $SETTINGS_DIR"
continue
fi
fi
fi
### Initiatize Firefox default profiles
logg info "Processing executable located at $FIREFOX_EXE"
if command -v "$FIREFOX_EXE" > /dev/null; then
### Create default profile by launching Firefox headlessly
logg info "Firefox executable set to $FIREFOX_EXE"
if [ ! -d "$SETTINGS_DIR" ]; then
logg info 'Running Firefox (or its derivative) headlessly to generate default profiles'
timeout 14 "$FIREFOX_EXE" --headless
logg info 'Finished running Firefox headlessly'
elif [ -d /Applications ] && [ -d /System ] && [ ! -f "$SETTINGS_DIR/../installs.ini" ]; then
logg info 'Running Firefox (or its derivative) headlessly to generate default profiles because install.ini is not at the macOS default location.'
timeout 14 "$FIREFOX_EXE" --headless
logg info 'Finished running Firefox headlessly (while fixing the missing macOS installs.ini issue)'
fi
### Ensure settings directory exists (since the application was brought up temporarily headlessly)
if [ ! -d "$SETTINGS_DIR" ]; then
logg warn "The settings directory located at $SETTINGS_DIR failed to be populated by running the browser headlessly"
continue
fi
### Add the populated profiles.ini
logg info "Copying "${XDG_DATA_HOME:-$HOME/.local/share}/firefox/profiles.ini" to profile directory"
logg info "The settings directory is $SETTINGS_DIR"
if [ -d /Applications ] && [ -d /System ]; then
# macOS
logg info "Copying ~/.local/share/firefox/profiles.ini to $SETTINGS_DIR/../profiles.ini"
cp -f "${XDG_DATA_HOME:-$HOME/.local/share}/firefox/profiles.ini" "$SETTINGS_DIR/../profiles.ini"
SETTINGS_INI="$SETTINGS_DIR/../installs.ini"
else
# Linux
logg info "Copying ~/.local/share/firefox/profiles.ini to $SETTINGS_DIR/profiles.ini"
cp -f "${XDG_DATA_HOME:-$HOME/.local/share}/firefox/profiles.ini" "$SETTINGS_DIR/profiles.ini"
SETTINGS_INI="$SETTINGS_DIR/installs.ini"
fi
### Default profile (created by launching Firefox headlessly)
DEFAULT_RELEASE_PROFILE="$(find "$SETTINGS_DIR" -mindepth 1 -maxdepth 1 -name "*.default" -not -name "profile.default")"
if [ -n "$DEFAULT_RELEASE_PROFILE" ]; then
logg info "Syncing $DEFAULT_RELEASE_PROFILE to $SETTINGS_DIR/profile.default"
rsync -a "$DEFAULT_RELEASE_PROFILE/" "$SETTINGS_DIR/profile.default"
else
logg warn 'Unable to sync default Mozilla Firefox profile'
fi
### Ensure original installs.ini is removed
if [ -f "$SETTINGS_INI" ]; then
# DEFAULT_PROFILE_PROFILE="$SETTINGS_DIR/$(cat "$SETTINGS_INI" | grep 'Default=' | sed 's/.*Profiles\///')"
logg info 'Removing previous installs.ini file'
rm -f "$SETTINGS_INI"
else
logg info 'installs.ini was not present in the Mozilla Firefox settings folder'
fi
### Miscellaneous default profiles
for NEW_PROFILE in "automation" "development" "miscellaneous"; do
if [ ! -d "$SETTINGS_DIR/profile.${NEW_PROFILE}" ] && [ -d "$SETTINGS_DIR/profile.default" ]; then
logg info "Cloning $NEW_PROFILE from profile.default"
rsync -a "$SETTINGS_DIR/profile.default/" "$SETTINGS_DIR/profile.${NEW_PROFILE}"
rsync -a "${XDG_DATA_HOME:-$HOME/.local/share}/firefox/" "$SETTINGS_DIR/profile.${NEW_PROFILE}"
cp -f "${XDG_CONFIG_HOME:-$HOME/.config}/firefox/user.js" "$SETTINGS_DIR/profile.${NEW_PROFILE}"
fi
done
### Public git profile
if [ -d "$SETTINGS_DIR/profile.git" ]; then
logg info 'Resetting the Firefox git profile'
cd "$SETTINGS_DIR/profile.git"
git reset --hard HEAD
git clean -fxd
logg info 'Pulling latest updates to the Firefox git profile'
git pull origin master
else
logg info 'Cloning the public Firefox git profile'
cd "$SETTINGS_DIR" && git clone "$FIREFOX_PUBLIC_PROFILE" profile.git
fi
### Copy user.js to profile.git profile
cp -f "${XDG_CONFIG_HOME:-$HOME/.config}/firefox/user.js" "$SETTINGS_DIR/profile.git"
### Git profile w/ plugins installed (installation happens below)
if [ ! -d "$SETTINGS_DIR/profile.plugins" ]; then
logg info "Syncing $SETTINGS_DIR/profile.git to $SETTINGS_DIR/profile.plugins"
rsync -a "$SETTINGS_DIR/profile.git/" "$SETTINGS_DIR/profile.plugins"
rsync -a "${XDG_DATA_HOME:-$HOME/.local/share}/firefox/" "$SETTINGS_DIR/profile.plugins"
cp -f "${XDG_CONFIG_HOME:-$HOME/.config}/firefox/user.js" "$SETTINGS_DIR/profile.plugins"
fi
### Private hosted profile
# Deprecated in favor of using the Restic profile tasks saved in `~/.config/task/Taskfile.yml`
# if [ ! -d "$SETTINGS_DIR/profile.private" ]; then
# logg info 'Downloading the encrypted Firefox private profile'
# cd "$SETTINGS_DIR"
# curl -sSL '{ { .firefoxPrivateProfile } }' -o profile.private.tar.gz.age
# logg info 'Decrypting the Firefox private profile'
# chezmoi decrypt profile.private.tar.gz.age > profile.private.tar.gz || EXIT_DECRYPT_CODE=$?
# if [ -z "$EXIT_DECRYPT_CODE" ]; then
# rm -f profile.private.tar.gz.age
# logg info 'Decompressing the Firefox private profile'
# tar -xzf profile.private.tar.gz
# logg success 'The Firefox private profile was successfully installed'
# cp -f "${XDG_CONFIG_HOME:-$HOME/.config}/firefox/user.js" "$SETTINGS_DIR/profile.private"
# logg info 'Copied ~/.config/firefox/user.js to profile.private profile'
# else
# logg error 'Failed to decrypt the private Firefox profile'
# fi
# fi
### Install Firefox addons (using list declared in .chezmoidata.yaml)
for SETTINGS_PROFILE in "profile.plugins" "profile.private"; do
if [ -d "$SETTINGS_DIR/$SETTINGS_PROFILE" ]; then
for FIREFOX_PLUGIN in {{ list (.firefoxAddOns | toString | replace "[" "" | replace "]" "") | uniq | join " " }}; do
logg info "Processing the $FIREFOX_PLUGIN Firefox add-on"
PLUGIN_HTML="$(mktemp)"
curl --silent "https://addons.mozilla.org/en-US/firefox/addon/$FIREFOX_PLUGIN/" > "$PLUGIN_HTML"
PLUGIN_TMP="$(mktemp)"
if ! command -v htmlq > /dev/null && command -v brew > /dev/null; then
logg info 'Installing htmlq using Homebrew since it is a dependency for populating Firefox add-ons' && brew install htmlq
fi
cat "$PLUGIN_HTML" | htmlq '#redux-store-state' | sed 's/^<scri.*application\/json">//' | sed 's/<\/script>$//' > "$PLUGIN_TMP"
PLUGIN_ID="$(jq '.addons.bySlug["'"$FIREFOX_PLUGIN"'"]' "$PLUGIN_TMP")"
if [ "$PLUGIN_ID" != 'null' ]; then
PLUGIN_FILE_ID="$(jq -r '.addons.byID["'"$PLUGIN_ID"'"].guid' "$PLUGIN_TMP")"
if [ "$PLUGIN_FILE_ID" != 'null' ]; then
PLUGIN_URL="$(cat "$PLUGIN_HTML" | htmlq '.InstallButtonWrapper-download-link' --attribute href)"
PLUGIN_FILENAME="${PLUGIN_FILE_ID}.xpi"
PLUGIN_FOLDER="$(echo "$PLUGIN_FILENAME" | sed 's/.xpi$//')"
if [ ! -d "$SETTINGS_DIR/$SETTINGS_PROFILE/extensions/$PLUGIN_FOLDER" ]; then
logg info 'Downloading add-on XPI file for '"$PLUGIN_FILENAME"' ('"$FIREFOX_PLUGIN"')'
if [ ! -d "$SETTINGS_DIR/$SETTINGS_PROFILE/extensions" ]; then
mkdir -p "$SETTINGS_DIR/$SETTINGS_PROFILE/extensions"
fi
curl -sSL "$PLUGIN_URL" -o "$SETTINGS_DIR/$SETTINGS_PROFILE/extensions/$PLUGIN_FILENAME"
# Unzipping like this causes Firefox to complain about unsigned plugins
# TODO - figure out how to headlessly enable the extensions in such a way that is compatible with Flatpak / Snap
# using the /usr/lib/firefox/distribution/policies.json works but this is not compatible with Flatpak / Snap out of the box
# it seems since they do not have access to the file system by default. Also, using the policies.json approach forces
# all Firefox profiles to use the same extensions. Ideally, we should find a way to enable the extensions scoped
# to the user profile.
# logg info 'Unzipping '"$PLUGIN_FILENAME"' ('"$FIREFOX_PLUGIN"')'
# unzip "$SETTINGS_DIR/$SETTINGS_PROFILE/extensions/$PLUGIN_FILENAME" -d "$SETTINGS_DIR/$SETTINGS_PROFILE/extensions/$PLUGIN_FOLDER"
logg success 'Installed '"$FIREFOX_PLUGIN"''
fi
else
logg warn 'A null Firefox add-on filename was detected for '"$FIREFOX_PLUGIN"''
fi
else
logg warn 'A null Firefox add-on ID was detected for '"$FIREFOX_PLUGIN"''
fi
done
fi
done
fi
done
}
firefoxSetup

View file

@ -0,0 +1,64 @@
#!/usr/bin/env bash
# @file GitHub Runner Registration
# @brief Registers a GitHub action runner with GitHub
# @description
# This script registers the host as a self-hosted GitHub runner with scope set
# in the `.user.github.runnerOrg` input in the `.chezmoi.yaml.tmpl` file. If your organization is `megabyte-labs`, then
# the value of `.user.github.runnerOrg` should be `megabyte-labs`. A self-hosted runner is an application
# that that allows you to run tasks from GitHub CI.
#
# This script adds 3 labels to the runner: self-hosted, _hostname_, and _operating-system family_.
#
# The script automatically acquires the GitHub Action runner token (as long as you specify your `.user.github.runnerOrg` value in `.chezmoi.yaml.tmpl`).
# In order to authenticate with GitHub, you should have the `GITHUB_TOKEN` environment variable in place with the appropriate permissions
# specified when you generate the token.
#
# ## Links
#
# * [Secrets / Environment variables documentation](https://install.doctor/docs/customization/secrets)
### Check if GitHub runner is installed
if [ -f "${XDG_DATA_HOME:-$HOME/.local/share}/github-runnerconfig.sh" ]; then
if [ -f "${XDG_DATA_HOME:-$HOME/.local/share}/github-runner/.runner" ]; then
logg info "GitHub Actions runner is already configured (${XDG_DATA_HOME:-$HOME/.local/share}/github-runner/.runner file is present)"
else
logg info 'Creating runner configuration'
### Configure labels
HOST_DISTRO_FAMILY="$(yq '.data.host.distro.family' "${XDG_CONFIG_HOME:-$HOME/.config}/chezmoi/chezmoi.yaml")"
HOST_DISTRO_ID="$(yq '.data.host.distro.id' "${XDG_CONFIG_HOME:-$HOME/.config}/chezmoi/chezmoi.yaml")"
LABELS="self-hosted,$(yq '.data.host.hostname' "${XDG_CONFIG_HOME:-$HOME/.config}/chezmoi/chezmoi.yaml"),$HOST_DISTRO_FAMILY"
if [ "$HOST_DISTRO_FAMILY" != "$HOST_DISTRO_ID" ]; then
LABELS="${LABELS},$HOST_DISTRO_ID"
fi
if command -v VirtualBox > /dev/null; then
LABELS="${LABELS},virtualbox"
fi
if command -v docker > /dev/null; then
LABELS="${LABELS},docker"
fi
if [ -n "$GITHUB_TOKEN" ]; then
if command -v jq > /dev/null; then
### Acquire token
logg info 'Acquiring runner token'
RUNNER_TOKEN="$(curl -sSL -X POST -H "Accept: application/vnd.github+json" -H "Authorization: Bearer $GITHUB_TOKEN" -H "X-GitHub-Api-Version: 2022-11-28" https://api.github.com/orgs/{{ .user.github.runnerOrg }}/actions/runners/registration-token | jq -r '.token')"
### Generate the configuration
logg info 'Joining GitHub runner to https://github.com/{{ .user.github.runnerOrg }}'
"${XDG_DATA_HOME:-$HOME/.local/share}/github-runner/config.sh" --unattended --url https://github.com/{{ .user.github.runnerOrg }} --token "$RUNNER_TOKEN" --labels "$LABELS" || EXIT_CODE=$?
if [ -n "$EXIT_CODE" ]; then
logg error 'GitHub runner configuration failed' && exit 1
fi
### Install / start the service
logg info 'Configuring runner service'
"${XDG_DATA_HOME:-$HOME/.local/share}/github-runner/svc.sh" install && logg success 'Successfully installed the GitHub Actions runner service'
logg info 'Starting runner service'
"${XDG_DATA_HOME:-$HOME/.local/share}/github-runner/svc.sh" start && logg success 'Started the GitHub Actions runner service'
else
logg warn 'jq is required by the GitHub runner configuration script'
fi
else
logg warn 'The GITHUB_TOKEN environment variable is not present'
fi
fi
else
logg info "The GitHub Actions runner installation is not present at ${XDG_DATA_HOME:-$HOME/.local/share}/github-runner"
fi

View file

@ -0,0 +1,114 @@
#!/usr/bin/env bash
# @file GitLab Runner Configuration
# @brief Registers GitLab Runner(s) with the given GitLab instance
# @description
# This script registers the runner(s) with the given GitLab instance. SaaS GitLab can also be provided as the GitLab instance to register
# the runners with. The script configures the runners to use either Docker or VirtualBox Executor. Refer to
# [this page](https://docs.gitlab.com/runner/executors/docker.html) and [this page](https://docs.gitlab.com/runner/executors/virtualbox.html)
# for details about the available configuration settings.
#
# Runners are always tagged with these 2 values: `hostname` and `docker`/`virtualbox` depending on the type of executor. If a list of tags is provided,
# the runner is tagged with these values in addition to the above mentioned values. If the list of tags is empty, no additonal tags are added and the
# runner is configured to pickup `untagged` jobs.
#
# Configuring other type of executors is not supported by this script.
#
# ## Secrets
#
# The following chart details the secret(s) that are needed to configure the runner:
#
# | Secret | Description |
# |------------------------|------------------------------------------------------------|
# | `GITLAB_RUNNER_TOKEN` | The token generated when the runner was created in GitLab |
#
# For more information about storing secrets like SSH keys and API keys, refer to our Secrets documentation provided below
#
# ## Configuration Variables
#
# The following chart details the input variable(s) that are used to determine the configuration of the runner:
#
# | Variable | Description |
# |---------------------|----------------------------------------------------------------------------------------------------------|
# | `glurl` | The URL of the Gitlab instance to associate the Runner with |
# | `runnerImage` | Docker image to use to configure the runner. Needed only when configuring `Docker` executor |
# | `runnerDescription` | Description of this runner |
# | `runnerTags` | Comma separated list of tags for this runner. See details in the description for more info |
# | `baseVM` | Name of the VirtualBox VM to use for creating runner. Needed only when configuring `VirtualBox` executor |
#
# ## Links
#
# * [Secrets / Environment variables documentation](https://install.doctor/docs/customization/secrets)
### Check if Docker is installed and operational so Docker executor(s) can be registered
if command -v docker > /dev/null && docker run --rm hello-world > /dev/null; then
HAS_DOCKER=1
else
HAS_DOCKER=0
logg warn 'Docker is not installed or it is not operational'
fi
### Check if VirtualBox is installed and operational so VirtualBox executor(s) can be registered
if command -v VirtualBox > /dev/null; then
HAS_VIRTUALBOX=1
else
HAS_VIRTUALBOX=0
logg warn 'VirtualBox is not installed'
fi
### Configure runners if Docker or VirtualBox is installed
if [ $HAS_DOCKER -eq 0 ] && [ $HAS_VIRTUALBOX -eq 0 ]; then
logg warn 'Docker and VirtualBox are not installed. Not registering runner(s).'
else
### Run logic if gitlab-runner is installed
if command -v gitlab-runner > /dev/null; then
### Populate appropriate token
case "$OSTYPE" in
solaris*) echo "TODO" ;;
darwin*) GITLAB_RUNNER_TOKEN="{{ if (stat (joinPath .chezmoi.sourceDir ".chezmoitemplates" "secrets" "GITLAB_RUNNER_TOKEN_DARWIN")) }}{{ includeTemplate "secrets/GITLAB_RUNNER_TOKEN_DARWIN" | decrypt | trim }}{{ else }}{{ env "GITLAB_RUNNER_TOKEN_DARWIN" }}{{ end }}" ;;
linux*) GITLAB_RUNNER_TOKEN="{{ if (stat (joinPath .chezmoi.sourceDir ".chezmoitemplates" "secrets" "GITLAB_RUNNER_TOKEN_LINUX")) }}{{ includeTemplate "secrets/GITLAB_RUNNER_TOKEN_LINUX" | decrypt | trim }}{{ else }}{{ env "GITLAB_RUNNER_TOKEN_LINUX" }}{{ end }}" ;;
bsd*) echo "TODO" ;;
msys*) GITLAB_RUNNER_TOKEN="{{ if (stat (joinPath .chezmoi.sourceDir ".chezmoitemplates" "secrets" "GITLAB_RUNNER_TOKEN_WINDOWS")) }}{{ includeTemplate "secrets/GITLAB_RUNNER_TOKEN_WINDOWS" | decrypt | trim }}{{ else }}{{ env "GITLAB_RUNNER_TOKEN_WINDOWS" }}{{ end }}" ;;
cygwin*) GITLAB_RUNNER_TOKEN="{{ if (stat (joinPath .chezmoi.sourceDir ".chezmoitemplates" "secrets" "GITLAB_RUNNER_TOKEN_WINDOWS")) }}{{ includeTemplate "secrets/GITLAB_RUNNER_TOKEN_WINDOWS" | decrypt | trim }}{{ else }}{{ env "GITLAB_RUNNER_TOKEN_WINDOWS" }}{{ end }}" ;;
*) echo "unknown: $OSTYPE" ;;
esac
### Check if Runner Token value is present before attempting to register runner(s)
if [ $GITLAB_RUNNER_TOKEN != "" ]; then
### Registering runners
{{ $cmd := `gitlab-runner register \
--non-interactive \
--token $GITLAB_RUNNER_TOKEN \` }}
### Register Docker based runners if Docker is installed and operational
if [ $HAS_DOCKER -eq 1 ]; then
logg info 'Registering GitLab Runner(s) that use Docker executor'
{{- range .host.gitlabRunners }}
{{- if index . "runnerImage" }}
{{- $cmd }}
--url {{ .glurl }} \
--executor "docker" \
--description "{{ .runnerDescription }} - on {{ $.chezmoi.hostname }}" \
--docker-image {{ .runnerImage }} \
{{ if and .runnerTags (gt (len .runnerTags) 0) }}--tag-list "{{ .runnerTags }},{{ $.chezmoi.hostname }},docker"
{{- else }}--tag-list "{{ $.chezmoi.hostname }},docker" --run-untagged{{ end }} || echo 'Runner registration failed"
{{ end -}}
{{ end }}
fi
### Register VirtualBox based runners if VirtualBox is installed
if [ $HAS_VIRTUALBOX -eq 1 ]; then
logg info 'Registering GitLab Runner(s) that use VirtualBox executor'
{{- range .host.gitlabRunners }}
{{- if index . "baseVM" }}
{{- $cmd }}
--url {{ .glurl }} \
--executor "virtualbox" \
--description "{{ .runnerDescription }} - on {{ $.chezmoi.hostname }}" \
--virtualbox-base-name "{{ .baseVM }}" \
{{ if and .runnerTags (gt (len .runnerTags) 0) }}--tag-list "{{ .runnerTags }},{{ $.chezmoi.hostname }},virtualbox"
{{- else }}--tag-list "{{ $.chezmoi.hostname }},virtualbox" --run-untagged{{ end }} || echo 'Runner registration failed"
{{ end -}}
{{ end }}
fi
else
logg warn 'GITLAB_RUNNER_TOKEN is not set. Not registering runner(s)'
fi
else
logg warn 'gitlab-runner is not installed or is not available in PATH'
fi
fi

View file

@ -0,0 +1,47 @@
#!/usr/bin/env bash
# @file git-o-matic Configuration
# @brief Starts service on Linux systems to monitor Git repositories
# @description
# git-o-matic is a tool to monitor git repositories and automatically pull/push changes. Multiple repositories can be
# monitored by running multiple instances of `gitomatic`. This script supports SSH Key based authentication only.
#
# If the `gitomatic` program is installed, this script creates and starts a Systemd service to monitor the repositories.
# The repositories are cloned if they are not available at the path.
#
# ## Notes
# * The author name and email address for commits are the same as `.user.name` and `.user.email` (configured in the `home/.chezmoi.yaml.tmpl` file)
# * `gitomatic` automatically pushes and pulls changes. The script does not change this behavior
# * `gitomatic` checks for changes every minute. This setting is not changed by this script
# * The User's default SSH Key is used for authentication
#
# ## Links
#
# * [gitomatic GitHub repository](https://github.com/muesli/gitomatic/)
# * [Systemd Unit file](https://github.com/megabyte-labs/install.doctor/blob/master/home/dot_config/gitomatic/gitomatic.service.tmpl)
# * [Helper script](https://github.com/megabyte-labs/install.doctor/blob/master/home/dot_local/bin/executable_gitomatic_service.tmpl
if command -v gitomatic > /dev/null; then
### Copy bin to /usr/local/bin
logg info "Copying $HOME/.local/bin/gitomatic-service to /usr/local/bin/gitomatic-service" && sudo cp -f "$HOME/.local/bin/gitomatic-service" /usr/local/bin/gitomatic-servic
### Copy gitomatic to global directory
if [ ! -f /usr/local/bin/gitomatic ]; then
logg info 'Copying gitomatic executable to /usr/local/bin/gitomatic' && sudo cp -f "$(which gitomatic)" /usr/local/bin/gitomatic
f
if [ -d /Applications ] && [ -d /System ]; then
### macOS
logg info 'Copying gitomatic plist file to /Library/LaunchDaemons' && sudo cp -f "${XDG_CONFIG_HOME:-$HOME/.config}/gitomatic/com.github.muesli.gitomatic.plist" /Library/LaunchDaemons/com.github.muesli.gitomatic.plist
if ! sudo launchctl list | grep 'gitomatic' > /dev/null; then
logg info 'Running sudo launchctl load /Library/LaunchDaemons/com.github.muesli.gitomatic.plist' && sudo launchctl load /Library/LaunchDaemons/com.github.muesli.gitomatic.plist
logg info 'Running sudo launchctl start /Library/LaunchDaemons/com.github.muesli.gitomatic.plist' && sudo launchctl start /Library/LaunchDaemons/com.github.muesli.gitomatic.plist
else
logg info "gitomatic services appear to already be loaded"
fi
else
### Linux
logg info 'Copying gitomatic systemd unit file to /etc/systemd/system/' && sudo cp -f "${XDG_CONFIG_HOME:-$HOME/.config}/gitomatic/gitomatic.service" /etc/systemd/system/gitomatic.service
logg info 'Reloading systemd daemon' && sudo systemctl daemon-reload
logg info 'Enabling and starting gitomatic service' && sudo systemctl enable --now gitomatic
fi
else
logg info 'gitomatic is not installed or it is not available in PATH'
fi

View file

@ -0,0 +1,84 @@
#!/usr/bin/env bash
# @file Chrome Settings / Extensions
# @brief This script configures Chrome, Brave, and Chromium system-wide managed / recommended policies settings. It also pre-loads a configurable list of Chrome extensions to Chrome, Brave, Chromium, and Edge (if they are installed).
# @description
# This Chrome setup script applies system-wide settings and pre-loads Chrome extensions into the browser profiles. The
# extensions still must be enabled but they appear in the Chrome extensions menu and can be enabled with the toggle. The
# system settings are applied to Chrome, Chromium, and Brave. Extensions are installed to the same browsers plus Microsoft Edge.
#
# ## Features
#
# * Adds `~/.config/chrome/managed.json` to the `managed/policies.json` system locations
# * Adds `~/.config/chrome/recommended.json` to the `recommended/policies.json` system locations
# * Pre-loads extension metadata for all the extensions defined under `chromeExtensions` in the [`home/.chezmoidata.yaml`](https://github.com/megabyte-labs/install.doctor/blob/master/home/.chezmoidata.yaml) file
#
# ## TODO
#
# * Automatically enable the extensions that are pre-loaded
# * Create several profiles with different characteristics (similar to the Firefox setup script)
# * Ensure the directories that the script cycles through to install managed settings and extensions are complete for all installation types (i.e. there might need to be some additions for Flatpak installations since their folder structure is different)
# * Document how [`chromium-flags.conf`](https://github.com/megabyte-labs/install.doctor/blob/master/home/dot_config/chromium-flags.conf) can be or is integrated
#
# ## Links
#
# * [`managed.json`](https://github.com/megabyte-labs/install.doctor/blob/master/home/dot_config/chrome/managed.json)
# * [`recommended.json`](https://github.com/megabyte-labs/install.doctor/blob/master/home/dot_config/chrome/recommended.json)
function chromeSetUp() {
### Ensure Chrome policies directory is present
logg info 'Processing policy directories for Chromium based browsers'
for POLICY_DIR in "/opt/google/chrome/policies"; do
if [ -d "$(dirname "$POLICY_DIR")" ]; then
### Managed policies
if [ ! -f "$POLICY_DIR/managed/policies.json" ]; then
logg info "Ensuring directory $POLICY_DIR/managed exists"
sudo mkdir -p "$POLICY_DIR/managed"
logg info "Copying ${XDG_CONFIG_HOME:-$HOME/.config}/chrome/managed.json to $POLICY_DIR/managed/policies.json"
sudo cp -f "${XDG_CONFIG_HOME:-$HOME/.config}/chrome/managed.json" "$POLICY_DIR/managed/policies.json"
fi
### Recommended policies
if [ ! -f "$POLICY_DIR/recommended/policies.json" ]; then
logg info "Ensuring directory $POLICY_DIR/recommended exists" && sudo mkdir -p "$POLICY_DIR/recommended"
logg info "Copying ${XDG_CONFIG_HOME:-$HOME/.config}/chrome/recommended.json to $POLICY_DIR/recommended/policies.json"
sudo cp -f "${XDG_CONFIG_HOME:-$HOME/.config}/chrome/recommended.json" "$POLICY_DIR/recommended/policies.json"
fi
else
logg info "Skipping extension injection into $POLICY_DIR - create these folders prior to running to create managed configs"
fi
done
### Add Chrome extension JSON
logg info 'Populating Chrome extension JSON'
for EXTENSION_DIR in "/opt/google/chrome/extensions" "$HOME/Library/Application Support/Google/Chrome/External Extensions"; do
### Ensure program-type is installed
if [ -d "$(dirname "$EXTENSION_DIR")" ]; then
### Ensure extension directory exists
if [[ "$EXTENSION_DIR" == '/opt/'* ]] || [[ "$EXTENSION_DIR" == '/etc/'* ]]; then
if [ ! -d "$EXTENSION_DIR" ]; then
logg info "Creating directory $EXTENSION_DIR" && sudo mkdir -p "$EXTENSION_DIR"
fi
else
if [ ! -d "$EXTENSION_DIR" ]; then
logg info "Creating directory $EXTENSION_DIR" && mkdir -p "$EXTENSION_DIR"
fi
fi
### Add extension JSON
logg info "Adding Chrome extensions to $EXTENSION_DIR"
for EXTENSION in {{ list (.chromeExtensions | toString | replace "[" "" | replace "]" "") | uniq | join " " }}; do
logg info "Adding Chrome extension manifest ($EXTENSION)"
if ! echo "$EXTENSION" | grep 'https://chrome.google.com/webstore/detail/' > /dev/null; then
EXTENSION="https://chrome.google.com/webstore/detail/$EXTENSION"
fi
EXTENSION_ID="$(echo "$EXTENSION" | sed 's/^.*\/\([^\/]*\)$/\1/')"
if [[ "$EXTENSION_DIR" == '/opt/'* ]] || [[ "$EXTENSION_DIR" == '/etc/'* ]]; then
sudo cp -f "${XDG_CONFIG_HOME:-$HOME/.config}/chrome/extension.json" "$EXTENSION_DIR/${EXTENSION_ID}.json"
else
cp -f "${XDG_CONFIG_HOME:-$HOME/.config}/chrome/extension.json" "$EXTENSION_DIR/${EXTENSION_ID}.json"
fi
done
else
logg info "$EXTENSION_DIR does not exist"
fi
done
}
chromeSetUp

View file

@ -0,0 +1,43 @@
#!/usr/bin/env bash
# @file JuiceFS
# @brief Mounts various S3-backed storage volumes (assuming correct secrets are in place)
# @description
# This script handles the mounting of various S3-backed storage volumes via [JuiceFS](https://juicefs.com/en/).
# The script will attempt to mount four different S3 volumes:
#
# 1. `public-{ { .juicefsVolumeNamePostfix } }`
# 2. `private-{ { .juicefsVolumeNamePostfix } }`
# 3. `docker-{ { .juicefsVolumeNamePostfix } }`
# 4. `user-{ { .juicefsVolumeNamePostfix } }`
#
# Where `{ { .juicefsVolumeNamePostfix } }` is replaced with the name stored in `home/.chezmoidata.yaml`.
# When creating the four volumes in the [JuiceFS console](https://juicefs.com/console/), it is important that you name the volumes using
# these four volume names.
MOUNT_FOLDER="/mnt"
UPDATE_FSTAB="--update-fstab"
if [ -d /Applications ] && [ -d /System ]; then
### macOS
MOUNT_FOLDER="/Volumes"
UPDATE_FSTAB=""
elif [ -f /snap/juicefs/current/juicefs ]; then
logg info 'Symlinking /snap/juicefs/current/juicefs to /snap/bin/juicefs' && sudo ln -s -f /snap/juicefs/current/juicefs /snap/bin/juicefs
fi
logg info "Acquiring juicefsVolumeNamePostfix from ${XDG_DATA_HOME:-$HOME/.local/share}/chezmoi/home/.chezmoidata.yaml"
JUICEFS_VOLUME_PREFIX="$(yq '.juicefsVolumeNamePostfix' "${XDG_DATA_HOME:-$HOME/.local/share}/chezmoi/home/.chezmoidata.yaml")"
for MOUNT_NAME in "docker" "private" "public" "user"; do
if [ "$MOUNT_NAME" == "user" ]; then
sudo juicefs mount --enable-xattr -o user_id="$(id -u "$USER")",group_id="$(id -g "$USER")" --conf-dir "${XDG_CONFIG_HOME:-$HOME/.config}/juicefs" -b $UPDATE_FSTAB "${JUICEFS_VOLUME_PREFIX}-${MOUNT_NAME}" "$HOME/.local/jfs"
else
sudo juicefs mount --enable-xattr --conf-dir /root/.juicefs $UPDATE_FSTAB -b "${JUICEFS_VOLUME_PREFIX}-${MOUNT_NAME}" "${MOUNT_FOLDER}/jfs-${MOUNT_NAME}"
fi
done
### Linux systemd
if command -v systemctl > /dev/null; then
logg info 'Ensuring /etc/systemd/system/docker.service.d exists as a directory' && sudo mkdir -p /etc/systemd/system/docker.service.d
logg info 'Creating /etc/systemd/system/docker.service.d/override.conf which ensures JuiceFS is loaded before Docker starts'
echo '[Unit]' | sudo tee /etc/systemd/system/docker.service.d/override.conf
echo 'After=network-online.target firewalld.service containerd.service jfs.mount' | sudo tee -a /etc/systemd/system/docker.service.d/override.conf
fi

View file

@ -0,0 +1,17 @@
#!/usr/bin/env bash
# @file Keybase Configuration
# @brief Updates Keybase's system configuration with the Keybase configuration stored in the `home/dot_config/keybase/config.json` location.
# @description
# This script ensures Keybase utilizes a configuration that, by default, adds a security fix.
if command -v keybase > /dev/null; then
KEYBASE_CONFIG="${XDG_CONFIG_HOME:-$HOME/.config}/keybase/config.json"
if [ -f "$KEYBASE_CONFIG" ]; then
logg info 'Ensuring /etc/keybase is a directory' && sudo mkdir -p /etc/keybase
logg info "Copying $KEYBASE_CONFIG to /etc/keybase/config.json" && sudo cp -f "$KEYBASE_CONFIG" /etc/keybase/config.json
else
logg warn "No Keybase config located at $KEYBASE_CONFIG"
fi
else
logg info 'The keybase executable is not available'
fi

View file

@ -0,0 +1,64 @@
#!/usr/bin/env bash
# @file Microsoft Edge Extensions
# @brief See ~/.local/bin/installx/post-google-chrome.sh for more details
function chromeSetUp() {
### Ensure Chrome policies directory is present
# logg info 'Processing policy directories for Chromium based browsers'
### TODO - Find POLICY_DIR location for Microsoft Edge
# for POLICY_DIR in "/opt/google/chrome/policies" "/etc/chromium/policies" "/etc/brave/policies"; do
# if [ -d "$(dirname "$POLICY_DIR")" ]; then
# ### Managed policies
# if [ ! -f "$POLICY_DIR/managed/policies.json" ]; then
# logg info "Ensuring directory $POLICY_DIR/managed exists"
# sudo mkdir -p "$POLICY_DIR/managed"
# logg info "Copying ${XDG_CONFIG_HOME:-$HOME/.config}/chrome/managed.json to $POLICY_DIR/managed/policies.json"
# sudo cp -f "${XDG_CONFIG_HOME:-$HOME/.config}/chrome/managed.json" "$POLICY_DIR/managed/policies.json"
# fi
# ### Recommended policies
# if [ ! -f "$POLICY_DIR/recommended/policies.json" ]; then
# logg info "Ensuring directory $POLICY_DIR/recommended exists" && sudo mkdir -p "$POLICY_DIR/recommended"
# logg info "Copying ${XDG_CONFIG_HOME:-$HOME/.config}/chrome/recommended.json to $POLICY_DIR/recommended/policies.json"
# sudo cp -f "${XDG_CONFIG_HOME:-$HOME/.config}/chrome/recommended.json" "$POLICY_DIR/recommended/policies.json"
# fi
# else
# logg info "Skipping extension injection into $POLICY_DIR - create these folders prior to running to create managed configs"
# fi
# done
### Add Chrome extension JSON
logg info 'Populating Chrome extension JSON'
for EXTENSION_DIR in "$HOME/Library/Application Support/Microsoft/Edge/External Extensions"; do
### Ensure program-type is installed
if [ -d "$(dirname "$EXTENSION_DIR")" ]; then
### Ensure extension directory exists
if [[ "$EXTENSION_DIR" == '/opt/'* ]] || [[ "$EXTENSION_DIR" == '/etc/'* ]]; then
if [ ! -d "$EXTENSION_DIR" ]; then
logg info "Creating directory $EXTENSION_DIR" && sudo mkdir -p "$EXTENSION_DIR"
fi
else
if [ ! -d "$EXTENSION_DIR" ]; then
logg info "Creating directory $EXTENSION_DIR" && mkdir -p "$EXTENSION_DIR"
fi
fi
### Add extension JSON
logg info "Adding Chrome extensions to $EXTENSION_DIR"
for EXTENSION in {{ list (.chromeExtensions | toString | replace "[" "" | replace "]" "") | uniq | join " " }}; do
logg info "Adding Chrome extension manifest ($EXTENSION)"
if ! echo "$EXTENSION" | grep 'https://chrome.google.com/webstore/detail/' > /dev/null; then
EXTENSION="https://chrome.google.com/webstore/detail/$EXTENSION"
fi
EXTENSION_ID="$(echo "$EXTENSION" | sed 's/^.*\/\([^\/]*\)$/\1/')"
if [[ "$EXTENSION_DIR" == '/opt/'* ]] || [[ "$EXTENSION_DIR" == '/etc/'* ]]; then
sudo cp -f "${XDG_CONFIG_HOME:-$HOME/.config}/chrome/extension.json" "$EXTENSION_DIR/${EXTENSION_ID}.json"
else
cp -f "${XDG_CONFIG_HOME:-$HOME/.config}/chrome/extension.json" "$EXTENSION_DIR/${EXTENSION_ID}.json"
fi
done
else
logg info "$EXTENSION_DIR does not exist"
fi
done
}
chromeSetUp

View file

@ -0,0 +1,157 @@
#!/usr/bin/env bash
# @file Netdata
# @brief Connects Netdata with Netdata's free cloud dashboard and applies some system optimizations, if necessary
# @description
# This script connects Netdata with Netdata Cloud if Netdata is installed, the `NETDATA_TOKEN` is provided, and the
# `NETDATA_ROOM` is defined. This allows you to graphically browse through system metrics on all your connected devices
# from a single free web application.
#
# This script installs additional alerts and enables notifications if Netdata is installed. Email notifications are configured
# using the provided primary email address. If the OS is Debian based, Netdata shows the number of CVEs in currently installed packages.
ensureNetdataOwnership() {
### Ensure /usr/local/var/lib/netdata/cloud.d is owned by user
if [ -d /usr/local/var/lib/netdata ]; then
logg info 'Ensuring permissions are correct on /usr/local/var/lib/netdata' && sudo chown -Rf netdata:netdata /usr/local/var/lib/netdata 2> /dev/null || sudo chown -Rf netdata:$(id -g -n) /usr/local/var/lib/netdata
elif [ -d /var/lib/netdata ]; then
logg info 'Ensuring permissions are correct on /var/lib/netdata' && sudo chown -Rf netdata:netdata /var/lib/netdata 2> /dev/null || sudo chown -Rf netdata:$(id -g -n) /var/lib/netdata
elif [ -d "${HOMEBREW_PREFIX:-/opt/homebrew}/var/lib/netdata" ]; then
logg info "Ensuring permissions are correct on ${HOMEBREW_PREFIX:-/opt/homebrew}/var/lib/netdata" && sudo chown -Rf netdata:netdata "${HOMEBREW_PREFIX:-/opt/homebrew}/var/lib/netdata" 2> /dev/null || sudo chown -Rf netdata:$(id -g -n) "${HOMEBREW_PREFIX:-/opt/homebrew}/var/lib/netdata"
else
logg warn 'No /var/lib/netdata folder found'
fi
}
### Claim the instance with Netdata Cloud
if command -v netdata-claim.sh > /dev/null; then
### Add user / group with script in ~/.local/bin/add-usergroup, if it is available
if command -v add-usergroup > /dev/null; then
sudo add-usergroup "$USER" netdata
fi
### Ensure ownership
ensureNetdataOwnership
### netdata-claim.sh must be run as netdata user
sudo -H -u netdata bash -c 'export NETDATA_ROOM="{{- if (stat (joinPath .chezmoi.sourceDir ".chezmoitemplates" "secrets" "NETDATA_ROOM")) -}}{{- includeTemplate "secrets/NETDATA_ROOM" | decrypt | trim -}}{{- else -}}{{- env "NETDATA_ROOM" -}}{{- end -}}" && export NETDATA_TOKEN="{{- if (stat (joinPath .chezmoi.sourceDir ".chezmoitemplates" "secrets" "NETDATA_TOKEN")) -}}{{- includeTemplate "secrets/NETDATA_TOKEN" | decrypt | trim -}}{{- else -}}{{- env "NETDATA_TOKEN" -}}{{- end -}}" && yes | netdata-claim.sh -token="$NETDATA_TOKEN" -rooms="$NETDATA_ROOM" -url="https://app.netdata.cloud"'
### Kernel optimizations
# These are mentioned while installing via the kickstart.sh script method. We are using Homebrew for the installation though.
# Assuming these optimizations do not cause any harm.
if [ -d /Applications ] && [ -d /System ]; then
### macOS
logg info 'System is macOS so Netdata kernel optimizations are not required'
else
### Linux
if [ -d /sys/kernel/mm/ksm ]; then
logg info 'Adding Netdata kernel optimization for /sys/kernel/mm/ksm/run'
echo 1 | sudo tee /sys/kernel/mm/ksm/run
logg info 'Adding Netdata kernel optimization for /sys/kernel/mm/ksm/sleep_millisecs'
echo 1000 | sudo tee /sys/kernel/mm/ksm/sleep_millisecs
else
logg info 'The /sys/kernel/mm/ksm directory does not exist so Netdata kernel optimizations are not being applied'
fi
fi
### Install additional alerts and enable notifications
if command -v netdata > /dev/null; then
### Copy the additional alert definitions
if [ -d /usr/local/etc/netdata ]; then
NETDATA_ETC='/usr/local/etc/netdata/'
elif [ -d /etc/netdata ]; then
NETDATA_ETC='/etc/netdata'
elif [ -d "${HOMEBREW_PREFIX:-/opt/homebrew}/etc/netdata" ]; then
NETDATA_ETC="${HOMEBREW_PREFIX:-/opt/homebrew}/etc/netdata"
else
logg error 'No etc location found for netdata' && exit 1
fi
logg info "Copying ${XDG_CONFIG_HOME:-$HOME/.config}/netdata/health.d/ to $NETDATA_ETC" && sudo cp -rf "${XDG_CONFIG_HOME:-$HOME/.config}/netdata/health.d/" "$NETDATA_ETC"
if command -v gsed > /dev/null; then
SED_UTIL="gsed"
else
SED_UTIL="sed"
fi
### Blocky
logg info "Adding Blocky metrics collection to $NETDATA_ETC/go.d/prometheus.conf"
sudo "$SED_UTIL" -i "/jobs:/a\ - name: blocky_local \n url: 'http://127.0.0.1:4000/metrics'" "$NETDATA_ETC/go.d/prometheus.conf"
### SFTPGo
logg info "Adding SFTPGo metrics collection to $NETDATA_ETC/go.d/prometheus.conf"
sudo "$SED_UTIL" -i "/jobs:/a\ - name: sftpgo_local \n url: 'http://127.0.0.1:57500/metrics'" "$NETDATA_ETC/go.d/prometheus.conf"
# Backup current health alarm configuration and apply new one
if [ -d /usr/local/lib/netdata ]; then
NETDATA_LIB='/usr/local/lib/netdata'
elif [ -d /usr/lib/netdata ]; then
NETDATA_LIB='/usr/lib/netdata'
elif [ -d "${HOMEBREW_PREFIX:-/opt/homebrew}/lib/netdata" ]; then
NETDATA_LIB="${HOMEBREW_PREFIX:-/opt/homebrew}/lib/netdata"
else
logg error 'No lib location found for netdata' && exit 1
fi
logg info "Copying ${XDG_CONFIG_HOME:-$HOME/.config}/netdata/health_alarm_notify.conf to $NETDATA_LIB/conf.d/health_alarm_notify.conf" && sudo cp -f "${XDG_CONFIG_HOME:-$HOME/.config}/netdata/health_alarm_notify.conf" "$NETDATA_LIB/conf.d/health_alarm_notify.conf"
else
logg warn 'netdata is not available in the PATH or is not installed'
fi
### Ensure the apt command is available before running `debsecan` logic
if command -v apt-get > /dev/null; then
### Configure Netdata to gather information about CVEs in the installed packages
if command -v debsecan > /dev/null; then
DEBSECAN_GIT="${XDG_DATA_HOME:-$HOME/.local/share}/netdata-debsecan"
### Installing the script to generate report on CVEs in installed packages
logg info 'Installing script to generate report on CVEs in installed packages' && sudo cp -f "$DEBSECAN_GIT/usr_local_bin_debsecan-by-type" "/usr/local/bin/debsecan-by-type"
### Generate initial debsecan reports in /var/log/debsecan/
logg info 'Generating initial debsecan reports in /var/log/debsecan/' && debsecan-by-type
### Configure dpkg to refresh the file after each run
logg info 'Configuring dpkg to refresh the file after each run' && sudo cp -f "$DEBSECAN_GIT/etc_apt_apt.conf.d_99debsecan" /etc/apt/apt.conf.d/99-debsecan
### Add a cron job to refresh the file every hour
logg info 'Adding a cron job to refresh the file every hour' && sudo cp -f "$DEBSECAN_GIT/etc_cron.d_debsecan" /etc/cron.d/debsecan
### Install the module/configuration file
logg info 'Installing the module and configuration file'
sudo "$DEBSECAN_GIT/debsecan.chart.py" /usr/libexec/netdata/python.d/debsecan.chart.py
sudo "$DEBSECAN_GIT/debsecan.conf" /etc/netdata/python.d/debsecan.conf
else
logg warn 'apt-get is available but debsecan is not available in the PATH or is not installed'
fi
fi
### Ensure / report whether speedtest-cli is installed
if ! command -v speedtest-cli > /dev/null; then
if command -v pipx > /dev/null; then
pipx install speedtest-cli
else
logg warn 'speedtest-cli not installed and pipx is not available'
fi
fi
### Configure Netdata to gather information about Internet connection speed
if command -v speedtest-cli > /dev/null; then
### Installing the script to generate report on Internet connection speed
logg info 'Installing script to generate report on Internet connection speed'
LIBEXEC_PATH="$(netdata -W buildinfo | grep 'Configure' | sed "s/.*--libexecdir=\([^ \']*\).*/\1/")"
if [ -d /usr/libexec/netdata/charts.d ]; then
sudo cp -f "${XDG_DATA_HOME:-$HOME/.local/share}/netdata-speedtest/speedtest.chart.sh" "/usr/libexec/netdata/charts.d/speedtest.chart.sh"
elif [ -d "$LIBEXEC_PATH/netdata/charts.d" ]; then
logg info "$LIBEXEC_PATH/netdata/charts.d present on system"
cp -f "${XDG_DATA_HOME:-$HOME/.local/share}/netdata-speedtest/speedtest.chart.sh" "$LIBEXEC_PATH/netdata/charts.d/speedtest.chart.sh"
else
logg warn "Failed to find appropriate directory to add Netdata speedtest chart script"
fi
else
logg warn 'speedtest-cli is not available in the PATH or is not installed'
fi
### Ensure ownership again
ensureNetdataOwnership
### Restart Netdata service
if command -v systemctl > /dev/null; then
logg info 'Enabling netdata service' && sudo systemctl enable netdata
logg info 'Restarting netdata service' && sudo systemctl restart netdata
elif [ -d /Applications ] && [ -d /System ]; then
logg info 'Starting / enabling netdata service' && brew services restart netdata
else
logg warn 'systemctl is not available'
fi
else
logg info 'netdata-claim.sh is not available in the PATH'
fi

View file

@ -0,0 +1,20 @@
#!/usr/bin/env bash
# @file NGINX Amplify Join
# @brief Set up NGINX Amplify and joins the cloud monitoring service dashboard
# @description
# This script installs NGINX Amplify and connects with the user's NGINX Amplify instance, assuming the `NGINX_AMPLIFY_API_KEY`
# is defined. NGINX Amplify is a free web application that serves as a way of browsing through metrics of all your connected
# NGINX instances.
#
# ## Links
#
# * [NGINX Amplify login](https://amplify.nginx.com/login)
# * [NGINX Amplify documentation](https://docs.nginx.com/nginx-amplify/#)
if command -v nginx > /dev/null; then
logg info 'Downloading the NGINX Amplify installer script'
TMP="$(mktemp)"
curl -sSL https://github.com/nginxinc/nginx-amplify-agent/raw/master/packages/install.sh > "$TMP"
logg info 'Running the NGINX Amplify setup script'
API_KEY="{{ if (stat (joinPath .chezmoi.sourceDir ".chezmoitemplates" "secrets" "NGINX_AMPLIFY_API_KEY")) }}{{- includeTemplate "secrets/NGINX_AMPLIFY_API_KEY" | decrypt | trim -}}{{ else }}{{- env "NGINX_AMPLIFY_API_KEY" -}}{{ end }}" sh "$TMP"
fi

View file

@ -0,0 +1,94 @@
#!/usr/bin/env bash
# @file Plymouth Theme / Configuration
# @brief Configures Plymouth to use a custom theme
# @description
# This script installs Plymouth and then configures it to use our custom Betelgeuse theme.
### Create /etc/plymouth/plymouthd.conf
if [ -f /etc/plymouth/plymouthd.conf ]; then
### Back up original plymouthd.conf
if [ ! -f /etc/plymouth/plymouthd.conf.bak ]; then
logg info 'Backing up /etc/plymouth/plymouthd.conf to /etc/plymouth/plymouthd.conf.bak'
sudo cp -f /etc/plymouth/plymouthd.conf /etc/plymouth/plymouthd.conf.bak
fi
### Create new plymouthd.conf
logg info 'Populating the /etc/plymouth/plymouthd.conf file'
echo "[Daemon]" | sudo tee /etc/plymouth/plymouthd.conf > /dev/null
echo "Theme={{ .theme }}" | sudo tee -a /etc/plymouth/plymouthd.conf > /dev/null
echo "ShowDelay=1" | sudo tee -a /etc/plymouth/plymouthd.conf > /dev/null
fi
### Apply update-alternatives
if command -v update-alternatives > /dev/null; then
if [ -f "/usr/local/share/plymouth/themes/{{ .theme }}/{{ .theme }}.plymouth" ]; then
sudo update-alternatives --install /usr/share/plymouth/themes/default.plymouth default.plymouth "/usr/local/share/plymouth/themes/{{ .theme }}/{{ .theme }}.plymouth" 100
logg success 'Installed default.plymouth'
# Required sometimes
sudo update-alternatives --set default.plymouth "/usr/local/share/plymouth/themes/{{ .theme }}/{{ .theme }}.plymouth"
logg success 'Set default.plymouth'
else
logg warn "/usr/local/share/plymouth/themes/{{ .theme }}/{{ .theme }}.plymouth does not exist!"
fi
else
logg warn 'update-alternatives is not available'
fi
### Update /etc/plymouth/plymouthd.conf
# Replaced by code above
# if [ -f /etc/plymouth/plymouthd.conf ]; then
# logg info 'Setting ShowDelay=1 in /etc/plymouth/plymouthd.conf'
# if cat /etc/plymouth/plymouthd.conf | grep ShowDelay; then
# sudo sed -i 's/^ShowDelay=.*/ShowDelay=1/' /etc/plymouth/plymouthd.conf
# else
# echo 'ShowDelay=1' | sudo tee -a /etc/plymouth/plymouthd.conf > /dev/null
# fi
# else
# logg warn '/etc/plymouth/plymouthd.conf does not exist!'
# fi
### Symlink /usr/local/share/plymouth/themes to /usr/share/plymouth/themes
if [ ! -d '/usr/share/plymouth/themes/{{ .theme }}' ]; then
logg info 'Symlinking /usr/local/share/plymouth/themes/{{ .theme }} to /usr/share/plymouth/themes/{{ .theme }}'
sudo ln -s '/usr/local/share/plymouth/themes/{{ .theme }}' '/usr/share/plymouth/themes/{{ .theme }}'
fi
### Set default Plymouth theme
if command -v plymouth-set-default-theme > /dev/null; then
sudo plymouth-set-default-theme -R '{{ .theme }}' || EXIT_CODE=$?
if [ -n "$EXIT_CODE" ]; then
logg warn 'There may have been an issue while setting the Plymouth default theme with plymouth-set-default-theme'
else
logg success 'Set Plymouth default theme with plymouth-set-default-theme'
fi
else
logg warn 'Could not apply default Plymouth theme because plymouth-set-default-theme is missing'
fi
### Apply update-alternatives (again - required sometimes)
if command -v update-alternatives > /dev/null; then
if [ -f "/usr/local/share/plymouth/themes/{{ .theme }}/{{ .theme }}.plymouth" ]; then
# Required sometimes
sudo update-alternatives --set default.plymouth "/usr/local/share/plymouth/themes/{{ .theme }}/{{ .theme }}.plymouth"
logg success 'Set default.plymouth (second time is required sometimes)'
else
logg warn "/usr/local/share/plymouth/themes/{{ .theme }}/{{ .theme }}.plymouth does not exist!"
fi
else
logg warn 'update-alternatives is not available'
fi
### Update kernel / initrd images
# Set `export DEBUG_MODE=true` to bypass GRUB2 / Plymouth application
if [ "$DEBUG_MODE" != 'true' ]; then
if command -v update-initramfs > /dev/null; then
logg info 'Running sudo update-initramfs -u'
sudo update-initramfs -u
logg success 'Updated kernel / initrd images for Plymouth'
elif command -v dracut > /dev/null; then
logg info 'Running sudo dracut --regenerate-all -f'
sudo dracut --regenerate-all -f
logg success 'Updated kernel / initrd images for Plymouth'
else
logg warn 'Unable to update kernel / initrd images because neither update-initramfs or dracut are available'
fi
fi

View file

@ -0,0 +1,140 @@
#!/usr/bin/env bash
# @file SendGrid Postfix Configuration
# @brief Configures Postfix to use SendGrid as a relay host so you can use the `mail` program to send e-mail from the command-line
# @description
# This script follows the instructions from [SendGrid's documentation on integrating Postfix](https://docs.sendgrid.com/for-developers/sending-email/postfix).
# After this script runs, you should be able to send outgoing e-mails using SendGrid as an SMTP handler. In other words, you will
# be able to use the `mail` CLI command to send e-mails. The following is an example mailing the contents of `~/.bashrc` to `name@email.com`:
#
# ```shell
# cat ~/.bashrc | mail -s "My subject" name@email.com
# ```
if [ -n "$SENDGRID_API_KEY" ] && [ "$SENDGRID_API_KEY" != "" ]; then
if command -v postfix > /dev/null; then
### Ensure dependencies are installed
if command -v apt-get > /dev/null; then
logg info 'Installing libsasl2-modules'
sudo apt-get update
sudo apt-get install -y libsasl2-modules || EXIT_CODE=$?
elif command -v dnf > /dev/null; then
sudo dnf install -y cyrus-sasl-plain || EXIT_CODE=$?
elif command -v yum > /dev/null; then
sudo yum install -y cyrus-sasl-plain || EXIT_CODE=$?
fi
if [ -n "$EXIT_CODE" ]; then
logg warn 'There was an error ensuring the Postfix-SendGrid dependencies were installed'
fi
if [ -d /etc/postfix ]; then
### Add the SendGrid Postfix settings to the Postfix configuration
if [ -f "${XDG_CONFIG_HOME:-$HOME/.config}/postfix/main.cf" ]; then
CONFIG_FILE=/etc/postfix/main.cf
if cat "$CONFIG_FILE" | grep '### INSTALL DOCTOR MANAGED' > /dev/null; then
logg info 'Removing Install Doctor-managed block of code in /etc/postfix/main.cf block'
START_LINE="$(echo `grep -n -m 1 "### INSTALL DOCTOR MANAGED ### START" "$CONFIG_FILE" | cut -f1 -d ":"`)"
END_LINE="$(echo `grep -n -m 1 "### INSTALL DOCTOR MANAGED ### END" "$CONFIG_FILE" | cut -f1 -d ":"`)"
if [ -n "$START_LINE" ] && [ -n "$END_LINE" ]; then
if command -v gsed > /dev/null; then
sudo gsed -i "${START_LINE},${END_LINE}d" "$CONFIG_FILE"
else
sudo sed -i "${START_LINE},${END_LINE}d" "$CONFIG_FILE"
fi
else
logg info 'No start-line or end-line detected - configuration appears to already be clean'
fi
fi
### Add Postfix main configuration
logg "Adding the following configuration from ${XDG_CONFIG_HOME:-$HOME/.config}/postfix/main.cf to /etc/postfix/main.cf"
cat "${XDG_CONFIG_HOME:-$HOME/.config}/postfix/main.cf" | sudo tee -a "$CONFIG_FILE" > /dev/null
echo "" | sudo tee -a "$CONFIG_FILE" > /dev/null
fi
### Ensure proper permissions on `sasl_passwd` and update Postfix hashmaps
if [ -f "${XDG_CONFIG_HOME:-$HOME/.config}/postfix/sasl_passwd" ]; then
logg info "Copying file from ${XDG_CONFIG_HOME:-$HOME/.config}/postfix/sasl_passwd to /etc/postfix/sasl_passwd"
sudo cp -f "${XDG_CONFIG_HOME:-$HOME/.config}/postfix/sasl_passwd" /etc/postfix/sasl_passwd
logg info 'Assigning proper permissions to /etc/postfix/sasl_passwd'
sudo chmod 600 /etc/postfix/sasl_passwd
logg info 'Updating Postfix hashmaps for /etc/postfix/sasl_passwd'
sudo postmap /etc/postfix/sasl_passwd
else
logg warn '~/.config/postfix/sasl_passwd file is missing'
fi
### Forward root e-mails
if [ -d /root ]; then
logg info "Forwarding root e-mails to $PRIMARY_EMAIL"
echo "$PRIMARY_EMAIL" | sudo tee /root/.forward > /dev/null || logg error 'Failed to set root user .forward file'
elif [ -d /var/root ]; then
logg info "Forwarding root e-mails to $PRIMARY_EMAIL"
echo "$PRIMARY_EMAIL" | sudo tee /var/root/.forward > /dev/null || logg error 'Failed to set root user .forward file'
else
logg warn 'Unable to identify root user home directory'
fi
### Ensure /etc/postfix/header_checks exists
if [ ! -d /etc/postfix/header_checks ]; then
logg info 'Creating /etc/postfix/header_checks since it does not exist'
sudo touch /etc/postfix/header_checks
fi
### Re-write header From for SendGrid
if ! cat /etc/postfix/header_checks | grep "no-reply@${PUBLIC_SERVICES_DOMAIN}" > /dev/null; then
logg info 'Added From REPLACE to /etc/postfix/header_checks'
echo "/^From:.*@${PUBLIC_SERVICES_DOMAIN}/ REPLACE From: no-reply@${PUBLIC_SERVICES_DOMAIN}" | sudo tee -a /etc/postfix/header_checks > /dev/null
fi
### Update aliases
if [ -f /etc/aliases ]; then
logg info "Forward root e-mails to $PRIMARY_EMAIL"
ALIASES_TMP="$(mktemp)"
logg info "Setting $PRIMARY_EMAIL as root e-mail in temporary file"
sudo sed "s/#root.*/root:\ $PRIMARY_EMAIL/" /etc/aliases > "$ALIASES_TMP"
logg info 'Moving temporary file to /etc/aliases'
sudo mv -f "$ALIASES_TMP" /etc/aliases
if ! cat /etc/aliases | grep "$USER_USERNAME: root" > /dev/null; then
logg info 'Forward user e-mail to root@localhost'
echo "$USER_USERNAME: root" | sudo tee -a /etc/aliases > /dev/null
fi
### Ensure old /etc/aliases.db is removed
if [ -f /etc/aliases.db ]; then
logg info 'Ensuring /etc/aliases.db is removed' && sudo rm -f /etc/aliases.db
else
logg info '/etc/aliases.db was not found'
fi
### Re-generate the /etc/aliases.db file
if [ -f /etc/aliases ]; then
logg info 'Ensuring proper permissions on the /etc/aliases file' && sudo chown $(stat -c "%U:%G" /etc/sudoers) /etc/aliases
logg info 'Generating Postfix aliases' && sudo postalias /etc/aliases > /dev/null
else
logg warn '/etc/aliases is missing which is required for Postfix'
fi
# The `sudo newaliases` mode is probably used to regenerate the /etc/aliases.db
# but since we are removing it to ensure proper permissions, this method is commented out.
# logg info 'Running newaliases to regenerate the alias database' && sudo newaliases
else
logg warn '/etc/aliases does not appear to exist'
fi
if [ -d /Applications ] && [ -d /System ]; then
### macOS
# Source: https://budiirawan.com/install-mail-server-mac-osx/
if [ -f "${XDG_CONFIG_HOME:-$HOME/.config}/postfix/com.apple.postfix.master.plist" ] && ! sudo launchctl list | grep 'postfix.master' > /dev/null; then
logg info 'Copying com.apple.postfix.master.plist'
sudo cp -f "${XDG_CONFIG_HOME:-$HOME/.config}/postfix/com.apple.postfix.master.plist" /System/Library/LaunchDaemons/com.apple.postfix.master.plist
sudo launchctl load /System/Library/LaunchDaemons/com.apple.postfix.master.plist && logg success 'launchctl load of com.apple.postfix.master successful'
fi
if ! sudo postfix status > /dev/null; then
logg info 'Starting postfix'
sudo postfix start > /dev/null
else
logg info 'Reloading postfix'
sudo postfix reload > /dev/null
fi
else
### Enable / restart postfix on Linux
logg info 'Enabling / restarting postfix'
sudo systemctl enable postfix
sudo systemctl restart postfix
fi
else
logg warn '/etc/postfix is not a directory! Skipping SendGrid Postfix setup.'
fi
else
logg info 'Skipping Postfix configuration because Postfix is not installed'
fi
fi

View file

@ -0,0 +1,55 @@
#!/usr/bin/env bash
# @file Tabby Plugins
# @brief This script installs the default Tabby plugins which are defined in `${XDG_CONFIG_HOME:-$HOME/.config}/tabby/plugins/package.json`
# @description
# This script pre-installs a handful of useful Tabby plugins which are defined in `${XDG_CONFIG_HOME:-$HOME/.config}/tabby/plugins/package.json`.
# These default plugins can be customized by editting the `package.json` file stored in your Install Doctor fork in the Tabby `plugins/package.json`
# file.
#
# ## Default Plugins Configuration
#
# The script will install all the plugins defined in the `package.json` file by navigating to the `~/.config/tabby/plugins` folder
# and then run `npm install`. The default configuration will include the following plugins:
#
# ```json
# {
# ...
# // Notable dependencies listed below
# "dependencies": {
# "tabby-docker": "^0.2.0",
# "tabby-save-output": "^3.1.0",
# "tabby-search-in-browser": "^0.0.1",
# "tabby-workspace-manager": "^0.0.4"
# },
# ...
# }
# ```
#
# ## Default Plugin Descriptions
#
# The following chart provides a short description of the default plugins that are pre-installed alongside Tabby:
#
# | NPM Package | Description |
# |---------------------------|---------------------------------------------------------------------|
# | `tabby-docker` | Allows you to shell directly into Docker containers |
# | `tabby-save-output` | This plugin lets you stream console output into a file. |
# | `tabby-search-in-browser` | Allows you to open a internet browser and search for selected text. |
# | `tabby-workspace-manager` | Allows you to create multiple workspace profiles. |
#
# ## Links
#
# * [Tabby plugins `package.json`](https://github.com/megabyte-labs/install.doctor/tree/master/home/dot_config/tabby/plugins/package.json)
# * [Secrets / Environment variables documentation](https://install.doctor/docs/customization/secrets) which details how to store your Tabby configuration in as an encrypted file
if [ -f "${XDG_CONFIG_HOME:-$HOME/.config}/tabby/plugins/package.json" ]; then
if [ -d "${XDG_CONFIG_HOME:-$HOME/.config}/tabby/plugins/node_modules" ]; then
logg info 'Skipping Tabby plugin installation because it looks like the plugins were already installed since node_modules is present in ~/.config/tabby/plugins'
else
logg info 'Installing Tabby plugins defined in '"${XDG_CONFIG_HOME:-$HOME/.config}/tabby/plugins/package.json"''
cd "${XDG_CONFIG_HOME:-$HOME/.config}/tabby/plugins"
npm install --quiet --no-progress
logg success 'Finished installing Tabby plugins'
fi
else
logg info 'Skipping Tabby plugin installation because is not present'
fi

View file

@ -0,0 +1,7 @@
#!/usr/bin/env bash
# @file tfenv
# @brief Configures tfenv to use the latest version of Terraform
if command -v tfenv > /dev/null; then
tfenv use latest
fi

File diff suppressed because it is too large Load diff