Many changes

This commit is contained in:
Brian Zalewski 2024-05-27 11:15:03 +00:00
parent fafccd946b
commit e8167f13b7
59 changed files with 614 additions and 2419 deletions

View file

@ -319,5 +319,5 @@ tasks:
A new method is detailed here: https://www.yubico.com/blog/github-now-supports-ssh-security-keys/
It may be worth migrating to that approach.
cmds:
- brew services start yubikey-agent
- brew services restart yubikey-agent
- yubikey-agent -setup

View file

@ -7,58 +7,18 @@
{{ includeTemplate "universal/profile" }}
{{ includeTemplate "universal/logg" }}
{{- $softwareGroup := nospace (cat "_" .host.softwareGroup) }}
{{- $softwareList := list (index .softwareGroups $softwareGroup | toString | replace "[" "" | replace "]" "") | uniq | join " " }}
if command -v install-program > /dev/null; then
if command -v installx > /dev/null; then
if command -v zx > /dev/null; then
logg info 'Installing packages defined in .chezmoidata.yaml under the .softwareGroups key'
logg info 'Installing: {{ $softwareList }}'
# Ask for the administrator password upfront
logg info 'A sudo password may be required for some of the installations'
sudo echo "Sudo access granted."
export DEBIAN_FRONTEND=noninteractive
export HOMEBREW_NO_ENV_HINTS=true
export HOMEBREW_NO_ANALYTICS=1
if ! command -v gcc-11; then
if command -v gcc; then
logg info 'gcc-11 command missing. Symlinking to gcc'
sudo ln -s "$(which gcc)" /usr/local/bin/gcc-11
else
logg warn 'gcc either needs to be added to the PATH or it is missing'
fi
fi
if [ -f "$HOME/.bashrc" ]; then
. "$HOME/.bashrc"
else
logg warn 'No ~/.bashrc file to import before running install-program'
fi
export LC_ALL="en_US.UTF-8"
logg info 'Printing environment variables for GO'
env | grep GO
logg info 'Printing environment variables for Java'
env | grep JAVA
env | grep SDKMAN
if ! command -v unbuffer > /dev/null; then
if command -v brew > /dev/null; then
logg info 'Ensuring expect is installed for the unbuffer command' && brew install --quiet expect
fi
fi
if command -v unbuffer > /dev/null; then
# install-program was refactored into installx
# logg info 'Running unbuffer install-program'
# unbuffer install-program {{ $softwareList }}
logg info 'Running unbuffer installx'
unbuffer installx {{ $softwareList }}
unbuffer installx --all
else
logg info 'Running install-program without unbuffer'
install-program {{ $softwareList }}
logg info 'Running installx'
installx {{ $softwareList }}
installx --all
fi
else
logg error 'zx is not available'
fi
else
logg error 'install-program is not in the PATH. It should be located in ~/.local/bin.'
logg error 'installx is not in the PATH. It should be located in ~/.local/bin.'
fi

View file

@ -15,7 +15,7 @@ bashItPlugins() {
### Ensure Powerline is installed
if ! command -v powerline > /dev/null; then
logg info 'Installing powerline via install-program'
install-program powerline > /dev/null
installx powerline
fi
### Include Bash It
@ -380,7 +380,7 @@ enableAutoUpdateDarwin() {
logg info 'Loading /Library/LaunchDaemons/com.apple.automatedupdates.plist'
if sudo launchctl list | grep 'com.apple.automatedupdates' > /dev/null; then
logg info 'Unloading previous com.apple.automatedupdates configuration'
sudo launchctl unload /Library/LaunchDaemons/clamdscan.plist
sudo launchctl unload /Library/LaunchDaemons/com.apple.automatedupdates.plist
fi
sudo launchctl load -w /Library/LaunchDaemons/com.apple.automatedupdates.plist
else
@ -395,6 +395,8 @@ enableAutoUpdateDarwin() {
fi
}
# Temporary next line for debugging
export DEBUG=true
if [ -n "$DEBUG" ] || [ -n "$DEBUG_MODE" ]; then
logg info 'The DEBUG or DEBUG_MODE environment variable is set so the post-install tasks will be run synchronously'
bashItPlugins

View file

@ -1,3 +1,3 @@
{{- if and (or (and (stat (joinPath .host.home ".config" "age" "chezmoi.txt")) (stat (joinPath .chezmoi.sourceDir ".chezmoitemplates" "secrets" "CLOUDFLARE_R2_ID"))) (env "CLOUDFLARE_R2_ID")) (or (and (stat (joinPath .host.home ".config" "age" "chezmoi.txt")) (stat (joinPath .chezmoi.sourceDir ".chezmoitemplates" "secrets" "CLOUDFLARE_R2_SECRET"))) (env "CLOUDFLARE_R2_SECRET")) (ne .user.cloudflare.r2 "") -}}
{{ .host.home }}/.local/mnt/s3
/{{- if eq .host.distro.id "darwin" -}}Volumes{{- else -}}mnt{{- end -}}/User
{{- end -}}

View file

@ -0,0 +1,2 @@
-- Defeat copy / paste blockers (Source: https://www.hammerspoon.org/go/)
hs.hotkey.bind({"cmd", "alt"}, "V", function() hs.eventtap.keyStrokes(hs.pasteboard.getContents()) end)

View file

@ -6,7 +6,7 @@
# the default Install Doctor configurations.
### Language / Fonts
export LANG="en_US"
export LANG="en_US.UTF-8"
export LC_ALL="en_US.UTF-8"
### Licensing

View file

@ -29,6 +29,9 @@ osascript -e "tell application \"Terminal\" to set the font name of window 1 to
osascript -e "tell application \"Terminal\" to set the font size of window 1 to 12"
# TODO - Add anti-aliasing
# Hammerspoon
defaults write org.hammerspoon.Hammerspoon MJConfigFile "~/.config/hammerspoon/init.lua"
# Keep-alive: update existing `sudo` time stamp until `.macos` has finished
while true; do sudo -n true; sleep 60; kill -0 "$$" || exit; done 2>/dev/null &

View file

@ -1,8 +1,8 @@
# Generated by Powerlevel10k configuration wizard on 2023-08-04 at 00:33 EDT.
# Based on romkatv/powerlevel10k/config/p10k-classic.zsh.
# Wizard options: nerdfont-complete + powerline, large icons, classic, unicode, darkest,
# 24h time, vertical separators, sharp heads, flat tails, 1 line, compact, many icons,
# concise, transient_prompt, instant_prompt=quiet.
# Generated by Powerlevel10k configuration wizard on 2024-05-27 at 07:04 EDT.
# Based on romkatv/powerlevel10k/config/p10k-classic.zsh, checksum 2750.
# Wizard options: nerdfont-v3 + powerline, large icons, classic, unicode, darkest,
# 24h time, vertical separators, flat heads, flat tails, 1 line, compact, many icons,
# concise, instant_prompt=quiet.
# Type `p10k configure` to generate another config.
#
# Config for Powerlevel10k with classic powerline prompt style. Type `p10k configure` to generate
@ -84,6 +84,7 @@
context # user@hostname
# nordvpn # nordvpn connection status, linux only (https://nordvpn.com/)
# ranger # ranger shell (https://github.com/ranger/ranger)
# yazi # yazi shell (https://github.com/sxyazi/yazi)
nnn # nnn shell (https://github.com/jarun/nnn)
# lf # lf shell (https://github.com/gokcehan/lf)
# xplr # xplr shell (https://github.com/sayanarijit/xplr)
@ -100,6 +101,7 @@
# todo # todo items (https://github.com/todotxt/todo.txt-cli)
timewarrior # timewarrior tracking status (https://timewarrior.net/)
taskwarrior # taskwarrior task count (https://taskwarrior.org/)
per_directory_history # Oh My Zsh per-directory-history local/global indicator
# cpu_arch # CPU architecture
time # current time
# ip # ip address and bandwidth usage for a specified network interface
@ -111,7 +113,7 @@
)
# Defines character set used by powerlevel10k. It's best to let `p10k configure` set it for you.
typeset -g POWERLEVEL9K_MODE=nerdfont-complete
typeset -g POWERLEVEL9K_MODE=nerdfont-v3
# When set to `moderate`, some icons will have an extra space after them. This is meant to avoid
# icon overlap when using non-monospace fonts. When set to `none`, spaces are not added.
typeset -g POWERLEVEL9K_ICON_PADDING=moderate
@ -174,9 +176,9 @@
# For example: POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS=(os_icon context_joined)
# The right end of left prompt.
typeset -g POWERLEVEL9K_LEFT_PROMPT_LAST_SEGMENT_END_SYMBOL='\uE0B0'
typeset -g POWERLEVEL9K_LEFT_PROMPT_LAST_SEGMENT_END_SYMBOL=''
# The left end of right prompt.
typeset -g POWERLEVEL9K_RIGHT_PROMPT_FIRST_SEGMENT_START_SYMBOL='\uE0B2'
typeset -g POWERLEVEL9K_RIGHT_PROMPT_FIRST_SEGMENT_START_SYMBOL=''
# The left end of left prompt.
typeset -g POWERLEVEL9K_LEFT_PROMPT_FIRST_SEGMENT_START_SYMBOL=''
# The right end of right prompt.
@ -242,7 +244,7 @@
.java-version
.perl-version
.php-version
.tool-version
.tool-versions
.shorten_folder_marker
.svn
.terraform
@ -428,11 +430,17 @@
res+=" ${modified}wip"
fi
# ⇣42 if behind the remote.
(( VCS_STATUS_COMMITS_BEHIND )) && res+=" ${clean}${VCS_STATUS_COMMITS_BEHIND}"
# ⇡42 if ahead of the remote; no leading space if also behind the remote: ⇣42⇡42.
(( VCS_STATUS_COMMITS_AHEAD && !VCS_STATUS_COMMITS_BEHIND )) && res+=" "
(( VCS_STATUS_COMMITS_AHEAD )) && res+="${clean}${VCS_STATUS_COMMITS_AHEAD}"
if (( VCS_STATUS_COMMITS_AHEAD || VCS_STATUS_COMMITS_BEHIND )); then
# ⇣42 if behind the remote.
(( VCS_STATUS_COMMITS_BEHIND )) && res+=" ${clean}${VCS_STATUS_COMMITS_BEHIND}"
# ⇡42 if ahead of the remote; no leading space if also behind the remote: ⇣42⇡42.
(( VCS_STATUS_COMMITS_AHEAD && !VCS_STATUS_COMMITS_BEHIND )) && res+=" "
(( VCS_STATUS_COMMITS_AHEAD )) && res+="${clean}${VCS_STATUS_COMMITS_AHEAD}"
elif [[ -n $VCS_STATUS_REMOTE_BRANCH ]]; then
# Tip: Uncomment the next line to display '=' if up to date with the remote.
# res+=" ${clean}="
fi
# ⇠42 if behind the push remote.
(( VCS_STATUS_PUSH_COMMITS_BEHIND )) && res+=" ${clean}${VCS_STATUS_PUSH_COMMITS_BEHIND}"
(( VCS_STATUS_PUSH_COMMITS_AHEAD && !VCS_STATUS_PUSH_COMMITS_BEHIND )) && res+=" "
@ -571,7 +579,7 @@
###############[ asdf: asdf version manager (https://github.com/asdf-vm/asdf) ]###############
# Default asdf color. Only used to display tools for which there is no color override (see below).
# Tip: Override this parameter for ${TOOL} with POWERLEVEL9K_ASDF_${TOOL}_FOREGROUND.
# typeset -g POWERLEVEL9K_ASDF_FOREGROUND=66
typeset -g POWERLEVEL9K_ASDF_FOREGROUND=66
# There are four parameters that can be used to hide asdf tools. Each parameter describes
# conditions under which a tool gets hidden. Parameters can hide tools but not unhide them. If at
@ -722,6 +730,12 @@
typeset -g POWERLEVEL9K_RANGER_FOREGROUND=178
# Custom icon.
# typeset -g POWERLEVEL9K_RANGER_VISUAL_IDENTIFIER_EXPANSION='⭐'
####################[ yazi: yazi shell (https://github.com/sxyazi/yazi) ]#####################
# Yazi shell color.
typeset -g POWERLEVEL9K_YAZI_FOREGROUND=178
# Custom icon.
# typeset -g POWERLEVEL9K_YAZI_VISUAL_IDENTIFIER_EXPANSION='⭐'
######################[ nnn: nnn shell (https://github.com/jarun/nnn) ]#######################
# Nnn shell color.
@ -798,9 +812,8 @@
# Text and color for insert vi mode.
typeset -g POWERLEVEL9K_VI_INSERT_MODE_STRING=
typeset -g POWERLEVEL9K_VI_MODE_INSERT_FOREGROUND=66
# Custom icon.
# typeset -g POWERLEVEL9K_RANGER_VISUAL_IDENTIFIER_EXPANSION='⭐'
# typeset -g POWERLEVEL9K_VI_MODE_VISUAL_IDENTIFIER_EXPANSION='⭐'
######################################[ ram: free RAM ]#######################################
# RAM color.
@ -882,6 +895,19 @@
# Custom icon.
# typeset -g POWERLEVEL9K_TASKWARRIOR_VISUAL_IDENTIFIER_EXPANSION='⭐'
######[ per_directory_history: Oh My Zsh per-directory-history local/global indicator ]#######
# Color when using local/global history.
typeset -g POWERLEVEL9K_PER_DIRECTORY_HISTORY_LOCAL_FOREGROUND=135
typeset -g POWERLEVEL9K_PER_DIRECTORY_HISTORY_GLOBAL_FOREGROUND=130
# Tip: Uncomment the next two lines to hide "local"/"global" text and leave just the icon.
# typeset -g POWERLEVEL9K_PER_DIRECTORY_HISTORY_LOCAL_CONTENT_EXPANSION=''
# typeset -g POWERLEVEL9K_PER_DIRECTORY_HISTORY_GLOBAL_CONTENT_EXPANSION=''
# Custom icon.
# typeset -g POWERLEVEL9K_PER_DIRECTORY_HISTORY_LOCAL_VISUAL_IDENTIFIER_EXPANSION='⭐'
# typeset -g POWERLEVEL9K_PER_DIRECTORY_HISTORY_GLOBAL_VISUAL_IDENTIFIER_EXPANSION='⭐'
################################[ cpu_arch: CPU architecture ]################################
# CPU architecture color.
typeset -g POWERLEVEL9K_CPU_ARCH_FOREGROUND=172
@ -1351,7 +1377,7 @@
#[ aws: aws profile (https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-profiles.html) ]#
# Show aws only when the command you are typing invokes one of these tools.
# Tip: Remove the next line to always show aws.
typeset -g POWERLEVEL9K_AWS_SHOW_ON_COMMAND='aws|awless|terraform|pulumi|terragrunt'
typeset -g POWERLEVEL9K_AWS_SHOW_ON_COMMAND='aws|awless|cdk|terraform|pulumi|terragrunt'
# POWERLEVEL9K_AWS_CLASSES is an array with even number of elements. The first element
# in each pair defines a pattern against which the current AWS profile gets matched.
@ -1399,10 +1425,39 @@
# Show azure only when the command you are typing invokes one of these tools.
# Tip: Remove the next line to always show azure.
typeset -g POWERLEVEL9K_AZURE_SHOW_ON_COMMAND='az|terraform|pulumi|terragrunt'
# POWERLEVEL9K_AZURE_CLASSES is an array with even number of elements. The first element
# in each pair defines a pattern against which the current azure account name gets matched.
# More specifically, it's P9K_CONTENT prior to the application of context expansion (see below)
# that gets matched. If you unset all POWERLEVEL9K_AZURE_*CONTENT_EXPANSION parameters,
# you'll see this value in your prompt. The second element of each pair in
# POWERLEVEL9K_AZURE_CLASSES defines the account class. Patterns are tried in order. The
# first match wins.
#
# For example, given these settings:
#
# typeset -g POWERLEVEL9K_AZURE_CLASSES=(
# '*prod*' PROD
# '*test*' TEST
# '*' OTHER)
#
# If your current azure account is "company_test", its class is TEST because "company_test"
# doesn't match the pattern '*prod*' but does match '*test*'.
#
# You can define different colors, icons and content expansions for different classes:
#
# typeset -g POWERLEVEL9K_AZURE_TEST_FOREGROUND=28
# typeset -g POWERLEVEL9K_AZURE_TEST_VISUAL_IDENTIFIER_EXPANSION='⭐'
# typeset -g POWERLEVEL9K_AZURE_TEST_CONTENT_EXPANSION='> ${P9K_CONTENT} <'
typeset -g POWERLEVEL9K_AZURE_CLASSES=(
# '*prod*' PROD # These values are examples that are unlikely
# '*test*' TEST # to match your needs. Customize them as needed.
'*' OTHER)
# Azure account name color.
typeset -g POWERLEVEL9K_AZURE_FOREGROUND=32
typeset -g POWERLEVEL9K_AZURE_OTHER_FOREGROUND=32
# Custom icon.
# typeset -g POWERLEVEL9K_AZURE_VISUAL_IDENTIFIER_EXPANSION='⭐'
# typeset -g POWERLEVEL9K_AZURE_OTHER_VISUAL_IDENTIFIER_EXPANSION='⭐'
##########[ gcloud: google cloud account and project (https://cloud.google.com/) ]###########
# Show gcloud only when the command you are typing invokes one of these tools.
@ -1568,7 +1623,7 @@
# Show battery in yellow when it's discharging.
typeset -g POWERLEVEL9K_BATTERY_DISCONNECTED_FOREGROUND=178
# Battery pictograms going from low to high level of charge.
typeset -g POWERLEVEL9K_BATTERY_STAGES='\uf58d\uf579\uf57a\uf57b\uf57c\uf57d\uf57e\uf57f\uf580\uf581\uf578'
typeset -g POWERLEVEL9K_BATTERY_STAGES='\UF008E\UF007A\UF007B\UF007C\UF007D\UF007E\UF007F\UF0080\UF0081\UF0082\UF0079'
# Don't show the remaining time to charge/discharge.
typeset -g POWERLEVEL9K_BATTERY_VERBOSE=false
@ -1623,7 +1678,7 @@
# User-defined prompt segments may optionally provide an instant_prompt_* function. Its job
# is to generate the prompt segment for display in instant prompt. See
# https://github.com/romkatv/powerlevel10k/blob/master/README.md#instant-prompt.
# https://github.com/romkatv/powerlevel10k#instant-prompt.
#
# Powerlevel10k will call instant_prompt_* at the same time as the regular prompt_* function
# and will record all `p10k segment` calls it makes. When displaying instant prompt, Powerlevel10k
@ -1651,7 +1706,7 @@
# - always: Trim down prompt when accepting a command line.
# - same-dir: Trim down prompt when accepting a command line unless this is the first command
# typed after changing current working directory.
typeset -g POWERLEVEL9K_TRANSIENT_PROMPT=always
typeset -g POWERLEVEL9K_TRANSIENT_PROMPT=off
# Instant prompt mode.
#
@ -1659,7 +1714,7 @@
# it incompatible with your zsh configuration files.
# - quiet: Enable instant prompt and don't print warnings when detecting console output
# during zsh initialization. Choose this if you've read and understood
# https://github.com/romkatv/powerlevel10k/blob/master/README.md#instant-prompt.
# https://github.com/romkatv/powerlevel10k#instant-prompt.
# - verbose: Enable instant prompt and print a warning when detecting console output during
# zsh initialization. Choose this if you've never tried instant prompt, haven't
# seen the warning, or if you are unsure what this all means.
@ -1680,4 +1735,4 @@
typeset -g POWERLEVEL9K_CONFIG_FILE=${${(%):-%x}:a}
(( ${#p10k_config_opts} )) && setopt ${p10k_config_opts[@]}
'builtin' 'unset' 'p10k_config_opts'
'builtin' 'unset' 'p10k_config_opts'

View file

@ -71,7 +71,7 @@ if [ "$BASH_SUPPORT" = 'true' ]; then
else
if [ -d /Applications ] && [ -d /Library ] && [ -d /System ]; then
# macOS
OS_ICON=""
OS_ICON=""
else
OS_ICON=""
fi

View file

@ -7,6 +7,8 @@
# there is already a user / group with the name present on the system before running
# any code.
set -euo pipefail
### Check if the script is being run as root
if [[ $EUID -ne 0 ]]; then
logg error "This script must be run as root"

View file

@ -1,3 +1,3 @@
#!/usr/bin/env bash
tinypng -k {{ .user.tinypngKey }} "$*"
tinypng -k {{ .user.tinypngKey }} $*

View file

@ -0,0 +1,70 @@
#!/usr/bin/env zx
// @file Get Secret
// @brief This helper utility allows you to return decrypted secrets or check the file system / environment variables to ensure the secrets are available
const customArgv = minimist(process.argv.slice(3), {
boolean: [
'exists'
],
alias: {
e: 'exists',
}
})
const secretDir = `${os.homedir()}/.local/share/chezmoi/home/.chezmoitemplates/secrets`
if (customArgv.exists && !customArgv._.length) {
console.error('Must pass one or more secrets to check for when using --exists', customArgv)
process.exit(1)
} else if (!customArgv.exists && (!customArgv._.length || customArgv._.length > 1)) {
console.log('Must pass exactly one argument.', customArgv)
process.exit(1)
} else {
if (customArgv.exists) {
ensureAllChezmoiSecrets(customArgv._)
} else {
const secretName = customArgv._[0]
if (process.env[secretName]) {
console.log(process.env[secretName])
process.exit(0)
}
// Check for presence of secret in appropriate Chezmoi directory
const secretPath = `${secretDir}/${secretName}`
const fileExists = fs.existsSync(`${secretPath}`)
if (fileExists) {
getChezmoiSecret(secretPath)
} else {
console.error(`The file ${os.homedir()}/.local/share/chezmoi/home/.chezmoitemplates/secrets/${secretName} does not exist!`)
process.exit(1)
}
}
}
async function getChezmoiSecret(secretPath) {
try {
const decryptedSecret = await $`cat "${secretPath}" | chezmoi decrypt`
console.log(decryptedSecret.stdout)
process.exit(0)
} catch (e) {
console.error(`Error decrypting ${secretPath}`, e)
process.exit(1)
}
}
async function ensureAllChezmoiSecrets(secretNames) {
try {
const promises = []
for (let secretName of secretNames) {
if (!process.env[secretName]) {
promises.push(fs.promises.stat(`${secretDir}/${secretName}`))
}
}
await Promise.all(promises)
process.exit(0)
} catch (e) {
console.error(`One or more of the secret names are not available as environment variables or in ${secretDir}`)
console.log(`Secrets that were checked:`, customArgv._)
process.exit(1)
}
}

File diff suppressed because it is too large Load diff

View file

@ -6,6 +6,15 @@ $.verbose = false
let installOrder, osArch, osId, osType, pkgs, sysType
const cacheDir = os.homedir() + '/.cache/installx'
const customArgv = minimist(process.argv.slice(3), {
boolean: [
'all'
],
alias: {
a: 'all',
}
})
function log(message) {
console.log(`${chalk.cyanBright('instx->')} ${message}`)
}
@ -483,7 +492,7 @@ async function main() {
const installKeys = Object.keys(pkgs)
.filter(i => expandDeps(argv._).includes(i))
log(`Constructing installation data`)
const installData = pkgMap(installKeys)
const installData = pkgMap(customArgv.all ? Object.keys(pkgs) : installKeys)
log(`Filtering install instructions`)
const installInstructions = installData
.map(x => {
@ -602,9 +611,9 @@ async function main() {
const name = typeof y === 'string' ? y : y.name
const sudo = typeof y === 'string' ? null : y.sudo
if (osType === 'linux' && x.installType !== 'brew' && x.installType !== 'cask' && systemctlInstalled) {
return sudo !== false ? $`sudo systemctl enable --now ${name}` : $`systemctl enable --now ${name}`
return sudo === true ? $`sudo systemctl enable --now ${name}` : $`systemctl enable --now ${name}`
} else if (brewInstalled) {
return sudo === true ? $`sudo brew services start ${name}` : $`brew services start ${name}`
return sudo === true ? $`sudo brew services restart ${name}` : $`brew services restart ${name}`
}
})
})

View file

@ -1,5 +1,7 @@
#!/usr/bin/env bash
set -euo pipefail
updateApk() {
if command -v apk > /dev/null; then
logg info 'Running sudo apk update' && sudo apk update || logg error 'Failed to run sudo apk update'

View file

@ -1,14 +0,0 @@
#!/usr/bin/env bash
# @file Aqua Initialization
# @brief Updates and installs any Aqua dependencies that are defined in Aqua's configuration file.
# @description
# This script updates Aqua and then installs any Aqua dependencies that are defined.
if command -v aqua > /dev/null; then
logg info 'Updating Aqua'
aqua update-aqua
logg info 'Installing Aqua dependencies (if any are defined)'
aqua install -a
else
logg info 'Skipping aqua install script because aqua was not installed'
fi

View file

@ -2,12 +2,14 @@
# @file Atuin Initialization
# @brief Registers with atuin, logs in, imports command history, and synchronizes
set -euo pipefail
if command -v atuin > /dev/null; then
source "${XDG_CONFIG_HOME:-$HOME/.config}/shell/private.sh"
get-secret --exists ATUIN_USERNAME ATUIN_EMAIL ATUIN_PASSWORD ATUIN_KEY
logg info 'Registering Atuin account'
atuin register -u "$ATUIN_USERNAME" -e "$ATUIN_EMAIL" -p "$ATUIN_PASSWORD"
atuin register -u "$(get-secret ATUIN_USERNAME)" -e "$(get-secret ATUIN_EMAIL)" -p "$(get-secret ATUIN_PASSWORD)"
logg info 'Logging into Atuin account'
atuin login -u "$ATUIN_USERNAME" -p "$ATUIN_PASSWORD" -k "$ATUIN_KEY"
atuin login -u "$(get-secret ATUIN_USERNAME)" -p "$(get-secret ATUIN_PASSWORD)" -k "$(get-secret ATUIN_KEY)"
logg info 'Running atuin import auto'
atuin import auto
logg info 'Running atuin sync'

View file

@ -2,6 +2,8 @@
# @file Blocky Configuration
# @brief Copies over configuration (and service file, in the case of Linux) to the appropriate system location
set -euo pipefail
if command -v blocky > /dev/null; then
if [ -d /Applications ] && [ -d /System ]; then
### macOS

View file

@ -2,12 +2,15 @@
# @file ClamAV Configuration
# @brief Applies ClamAV configuration, updates its database, and configures background services
set -euo pipefail
if command -v freshclam > /dev/null; then
### Add freshclam.conf
if [ -f "$HOME/.local/etc/clamav/freshclam.conf" ]; then
sudo mkdir -p /usr/local/etc/clamav
sudo cp -f "$HOME/.local/etc/clamav/freshclam.conf" /usr/local/etc/clamav/freshclam.conf
if [ -d "${HOMEBREW_PREFIX:-/opt/homebrew}/etc/clamav" ] && [ ! -f "${HOMEBREW_PREFIX:-/opt/homebrew}/etc/clamav/freshclam.conf" ]; then
if [ -d "${HOMEBREW_PREFIX:-/opt/homebrew}/etc/clamav" ] && [ ! -L "${HOMEBREW_PREFIX:-/opt/homebrew}/etc/clamav/freshclam.conf" ]; then
sudo rm -f "${HOMEBREW_PREFIX:-/opt/homebrew}/etc/clamav/freshclam.conf"
ln -s /usr/local/etc/clamav/freshclam.conf "${HOMEBREW_PREFIX:-/opt/homebrew}/etc/clamav/freshclam.conf"
fi
fi
@ -16,7 +19,8 @@ if command -v freshclam > /dev/null; then
if [ -f "$HOME/.local/etc/clamav/clamd.conf" ]; then
sudo mkdir -p /usr/local/etc/clamav
sudo cp -f "$HOME/.local/etc/clamav/clamd.conf" /usr/local/etc/clamav/clamd.conf
if [ -d "${HOMEBREW_PREFIX:-/opt/homebrew}/etc/clamav" ] && [ ! -f "${HOMEBREW_PREFIX:-/opt/homebrew}/etc/clamav/clamd.conf" ]; then
if [ -d "${HOMEBREW_PREFIX:-/opt/homebrew}/etc/clamav" ] && [ ! -L "${HOMEBREW_PREFIX:-/opt/homebrew}/etc/clamav/clamd.conf" ]; then
sudo rm -f "${HOMEBREW_PREFIX:-/opt/homebrew}/etc/clamav/clamd.conf"
ln -s /usr/local/etc/clamav/clamd.conf "${HOMEBREW_PREFIX:-/opt/homebrew}/etc/clamav/clamd.conf"
fi
fi

View file

@ -4,6 +4,8 @@
# @description
# 1. Skips the deletion of a tunnel when it is currently in use
set -euo pipefail
if command -v cloudflared > /dev/null; then
# Show warning message about ~/.cloudflared already existing
if [ -d "$HOME/.cloudflared" ]; then

View file

@ -8,26 +8,18 @@
# be passed in as a secret (either via the encrypted secret method or passed in as an environment
# variable).
set -euo pipefail
if command -v docker > /dev/null; then
### Acquire DOCKERHUB_TOKEN
DOCKERHUB_TOKEN_FILE="${XDG_DATA_HOME:-$HOME/.local/share}/chezmoi/home/.chezmoitemplates/secrets/DOCKERHUB_TOKEN"
if [ -f "$DOCKERHUB_TOKEN_FILE" ]; then
logg info "Found DOCKERHUB_TOKEN in ${XDG_DATA_HOME:-$HOME/.local/share}/chezmoi/home/.chezmoitemplates/secrets"
if [ -f "${XDG_CONFIG_HOME:-$HOME/.config}/age/chezmoi.txt" ]; then
logg info 'Decrypting DOCKERHUB_TOKEN token with Age encryption key'
DOCKERHUB_TOKEN="$(cat "$DOCKERHUB_TOKEN_FILE" | chezmoi decrypt)"
else
logg warn 'Age encryption key is missing from ~/.config/age/chezmoi.txt'
fi
else
logg warn "DOCKERHUB_TOKEN is missing from ${XDG_DATA_HOME:-$HOME/.local/share}/chezmoi/home/.chezmoitemplates/secrets"
fi
get-secret --exists DOCKERHUB_TOKEN || exit 1
### Acquire DOCKERHUB_USER
if [ -f "${XDG_CONFIG_HOME:-$HOME/.config}/chezmoi/chezmoi.yaml" ]; then
DOCKERHUB_USER="$(yq '.data.user.docker.username' ~/.config/chezmoi/chezmoi.yaml)"
else
logg info "${XDG_CONFIG_HOME:-$HOME/.config}/chezmoi/chezmoi.yaml is missing which is required for populating the DOCKERHUB_USER"
logg error "${XDG_CONFIG_HOME:-$HOME/.config}/chezmoi/chezmoi.yaml is missing which is required for populating the DOCKERHUB_USER"
exit 1
fi
### Launch Docker.app
@ -36,6 +28,7 @@ if command -v docker > /dev/null; then
fi
### Pre-authenticate with DockerHub
DOCKERHUB_TOKEN="$(get-secret DOCKERHUB_TOKEN)"
if [ -n "$DOCKERHUB_TOKEN" ] && [ -n "$DOCKERHUB_USER" ]; then
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

View file

@ -2,9 +2,14 @@
# @file EasyEngine
# @brief Configures EasyEngine to use the CloudFlare API for configuring Let's Encrypt
set -euo pipefail
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
### Ensure secrets
get-secret --exists CLOUDFLARE_EMAIL CLOUDFLARE_API_KEY
### Configure EasyEngine
logg info 'Configuring EasyEngine with CloudFlare automatic SSL insuance'
ee config set le-mail "$(get-secret CLOUDFLARE_EMAIL)"
ee config set cloudflare-api-key "$(get-secret CLOUDFLARE_API_KEY)"
fi

View file

@ -2,14 +2,18 @@
# @file Endlessh Configuration
# @brief Applies the Endlessh configuration and starts the service on Linux systems
set -euo pipefail
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

View file

@ -10,19 +10,25 @@
# ## Secrets
#
# For more information about storing secrets like SSH keys and API keys, refer to our [Secrets documentation](https://install.doctor/docs/customization/secrets).
#
# ## TODO
#
# * Create seperate environments based on encrypted secret type (e.g. Allow `envchain cloudflare env` instead of `envchain default env` for everything)
set -euo pipefail
### 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
logg info "Adding $file to System keyring via envchain"
cat "$file" | chezmoi decrypt | envchain -s default "$(basename $file)" > /dev/null || logg info 'Importing "$(basename $file)" failed'
done
while read ENCRYPTED_FILE; do
logg info "Adding $ENCRYPTED_FILE to System keyring via envchain"
cat "$ENCRYPTED_FILE" | chezmoi decrypt | envchain -s default "$(basename $ENCRYPTED_FILE)" > /dev/null || logg info "Importing "$(basename $ENCRYPTED_FILE)" failed"
done< <(find "${XDG_DATA_HOME:-$HOME/.local/share}/chezmoi/home/.chezmoitemplates/secrets" -type f -maxdepth 1 -mindepth 1)
logg success "Added Chezmoi-managed secrets into System keyring via envchain"
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
fi

View file

@ -11,6 +11,8 @@
#
# * [`fail2ban` configuration folder](https://github.com/megabyte-labs/install.doctor/tree/master/home/private_dot_ssh/fail2ban)
set -euo pipefail
if command -v fail2ban-client > /dev/null; then
if [[ ! "$(test -d /proc && grep Microsoft /proc/version > /dev/null)" ]]; then
if [ -f "$HOME/.ssh/fail2ban/jail.local" ]; then

View file

@ -2,9 +2,14 @@
# @file Fig Login
# @brief Logs into Fig using the FIG_TOKEN
set -euo pipefail
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'
### Ensure FIG_TOKEN
get-secret --exists FIG_TOKEN
### Login to Fig
fig login --token "$(get-secret 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

@ -43,6 +43,8 @@
# * [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
set -euo pipefail
function installFirefoxProfileConnector() {
logg info 'Installing the Firefox Profile Connector'
if command -v apt-get > /dev/null; then
@ -272,7 +274,7 @@ function firefoxSetup() {
### 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
while read FIREFOX_PLUGIN; 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"
@ -310,7 +312,7 @@ function firefoxSetup() {
else
logg warn 'A null Firefox add-on ID was detected for '"$FIREFOX_PLUGIN"''
fi
done
done< <(yq '.firefoxAddOns[]' ~/.local/share/chezmoi/home/.chezmoidata.yaml)
fi
done
fi

View file

@ -17,6 +17,8 @@
#
# * [Secrets / Environment variables documentation](https://install.doctor/docs/customization/secrets)
set -euo pipefail
### 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
@ -40,10 +42,11 @@ if [ -f "${XDG_DATA_HOME:-$HOME/.local/share}/github-runnerconfig.sh" ]; 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')"
RUNNER_ORG="$(yq '.data.user.github.runnerOrg' "${XDG_CONFIG_HOME:-$HOME/.config}/chezmoi/chezmoi.yaml")"
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/${RUNNER_ORG}/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=$?
logg info "Joining GitHub runner to https://github.com/${RUNNER_ORG}"
"${XDG_DATA_HOME:-$HOME/.local/share}/github-runner/config.sh" --unattended --url https://github.com/${RUNNER_ORG} --token "$RUNNER_TOKEN" --labels "$LABELS" || EXIT_CODE=$?
if [ -n "$EXIT_CODE" ]; then
logg error 'GitHub runner configuration failed' && exit 1
fi

View file

@ -20,6 +20,8 @@
# * [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
set -euo pipefail
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

View file

@ -24,6 +24,8 @@
# * [`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)
set -euo pipefail
function chromeSetUp() {
### Ensure Chrome policies directory is present
logg info 'Processing policy directories for Chromium based browsers'
@ -63,7 +65,7 @@ function chromeSetUp() {
fi
### Add extension JSON
logg info "Adding Chrome extensions to $EXTENSION_DIR"
for EXTENSION in {{ list (.chromeExtensions | toString | replace "[" "" | replace "]" "") | uniq | join " " }}; do
while read EXTENSION; 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"
@ -74,7 +76,7 @@ function chromeSetUp() {
else
cp -f "${XDG_CONFIG_HOME:-$HOME/.config}/chrome/extension.json" "$EXTENSION_DIR/${EXTENSION_ID}.json"
fi
done
done< <(yq '.chromeExtensions[]' "${XDG_DATA_HOME:-$HOME/.local/share}/chezmoi/home/.chezmoidata.yaml")
else
logg info "$EXTENSION_DIR does not exist"
fi

View file

@ -14,6 +14,8 @@
# 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.
set -euo pipefail
MOUNT_FOLDER="/mnt"
UPDATE_FSTAB="--update-fstab"
if [ -d /Applications ] && [ -d /System ]; then

View file

@ -4,6 +4,8 @@
# @description
# This script ensures Keybase utilizes a configuration that, by default, adds a security fix.
set -euo pipefail
if command -v keybase > /dev/null; then
KEYBASE_CONFIG="${XDG_CONFIG_HOME:-$HOME/.config}/keybase/config.json"
if [ -f "$KEYBASE_CONFIG" ]; then

View file

@ -2,6 +2,8 @@
# @file Mise Install / Tweaks
# @brief Performs initial install of mise targets and applies tweaks such as symlinking mise's Java version with the system Java target on macOS
set -euo pipefail
if command -v mise > /dev/null; then
logg info 'Running mise install' && mise install

View file

@ -9,6 +9,8 @@
# 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.
set -euo pipefail
ensureNetdataOwnership() {
### Ensure /usr/local/var/lib/netdata/cloud.d is owned by user
if [ -d /usr/local/var/lib/netdata ]; then
@ -22,6 +24,9 @@ ensureNetdataOwnership() {
fi
}
### Ensure secrets are available
get-secret --exists NETDATA_ROOM NETDATA_TOKEN
### 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
@ -32,7 +37,7 @@ if command -v netdata-claim.sh > /dev/null; then
### 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"'
sudo -H -u netdata bash -c "yes | netdata-claim.sh -token="$(get-secret NETDATA_TOKEN)" -rooms="$(get-secret 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.

View file

@ -11,6 +11,8 @@
# * [NGINX Amplify login](https://amplify.nginx.com/login)
# * [NGINX Amplify documentation](https://docs.nginx.com/nginx-amplify/#)
set -euo pipefail
if command -v nginx > /dev/null; then
if [ -d /Applications ] && [ -d /System ]; then
### macOS
@ -19,21 +21,17 @@ if command -v nginx > /dev/null; then
else
### Linux
NGINX_CONFIG_DIR=/etc/nginx
NGINX_AMPLIFY_API_KEY_FILE="${XDG_DATA_HOME:-$HOME/.local/share}/chezmoi/home/.chezmoitemplates/secrets/NGINX_AMPLIFY_API_KEY"
if [ -f "$NGINX_AMPLIFY_API_KEY_FILE" ]; then
logg info "Found NGINX_AMPLIFY_API_KEY in ${XDG_DATA_HOME:-$HOME/.local/share}/chezmoi/home/.chezmoitemplates/secrets"
if [ -f "${XDG_CONFIG_HOME:-$HOME/.config}/age/chezmoi.txt" ]; then
logg info 'Decrypting NGINX_AMPLIFY_API_KEY token with Age encryption key'
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="$(cat "$NGINX_AMPLIFY_API_KEY_FILE" | chezmoi decrypt)" sh "$TMP"
else
logg warn 'Age encryption key is missing from ~/.config/age/chezmoi.txt'
fi
if get-secret --exists NGINX_AMPLIFY_API_KEY; then
### Download NGINX Amplify script
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"
### NGINX Amplify registration
logg info 'Running the NGINX Amplify setup script'
API_KEY="$(get-secret NGINX_AMPLIFY_API_KEY)" sh "$TMP"
else
logg warn "NGINX_AMPLIFY_API_KEY is missing from ${XDG_DATA_HOME:-$HOME/.local/share}/chezmoi/home/.chezmoitemplates/secrets"
logg warn "Skipping NGINX Amplify setup because the NGINX_AMPLIFY_API_KEY was unavailable"
fi
fi
logg info "Ensuring $NGINX_CONFIG_DIR is present" && sudo mkdir -p "$NGINX_CONFIG_DIR"
@ -42,9 +40,8 @@ if command -v nginx > /dev/null; then
if [ -d /Applications ] && [ -d /System ]; then
### macOS
if [ -d "${HOMEBREW_PREFIX:-/opt/homebrew}/etc/nginx" ] && [ ! -L "${HOMEBREW_PREFIX:-/opt/homebrew}/etc/nginx" ]; then
logg info "Removing directory at ${HOMEBREW_PREFIX:-/opt/homebrew}/etc/nginx"
sudo rm -rf "{HOMEBREW_PREFIX:-/opt/homebrew}/etc/nginx"
logg info "Symlinking /usr/local/etc/nginx to ${HOMEBREW_PREFIX:-/opt/homebrew}/etc/nginx"
logg info "Removing ${HOMEBREW_PREFIX:-/opt/homebrew}/etc/nginx directory and its contents in favor of symlink to /usr/local/etc/nginx"
rm -rf "${HOMEBREW_PREFIX:-/opt/homebrew}/etc/nginx"
ln -s /usr/local/etc/nginx "${HOMEBREW_PREFIX:-/opt/homebrew}/etc/nginx"
else
logg info "Skipping symlinking of /usr/local/etc/nginx to ${HOMEBREW_PREFIX:-/opt/homebrew}/etc/nginx because directory symlink already appears to be there"

View file

@ -2,6 +2,8 @@
# @file NTFY Dependencies
# @brief Ensures branding assets and sound files are in system locations. Also, ensures system dependencies are installed
set -euo pipefail
if command -v ntfy > /dev/null; then
### Branding assets
logg info 'Ensuring branding assets are in expected place for ntfy'

View file

@ -4,6 +4,8 @@
# @description
# This script installs Plymouth and then configures it to use our custom Betelgeuse theme.
set -euo pipefail
### Create /etc/plymouth/plymouthd.conf
if [ -f /etc/plymouth/plymouthd.conf ]; then
### Back up original plymouthd.conf
@ -14,20 +16,20 @@ if [ -f /etc/plymouth/plymouthd.conf ]; then
### 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 "Theme=Betelgeuse" | 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
if [ -f "/usr/local/share/plymouth/themes/Betelgeuse/Betelgeuse.plymouth" ]; then
sudo update-alternatives --install /usr/share/plymouth/themes/default.plymouth default.plymouth "/usr/local/share/plymouth/themes/Betelgeuse/Betelgeuse.plymouth" 100
logg success 'Installed default.plymouth'
# Required sometimes
sudo update-alternatives --set default.plymouth "/usr/local/share/plymouth/themes/{{ .theme }}/{{ .theme }}.plymouth"
sudo update-alternatives --set default.plymouth "/usr/local/share/plymouth/themes/Betelgeuse/Betelgeuse.plymouth"
logg success 'Set default.plymouth'
else
logg warn "/usr/local/share/plymouth/themes/{{ .theme }}/{{ .theme }}.plymouth does not exist!"
logg warn "/usr/local/share/plymouth/themes/Betelgeuse/Betelgeuse.plymouth does not exist!"
fi
else
logg warn 'update-alternatives is not available'
@ -47,14 +49,14 @@ fi
# 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 }}'
if [ ! -d '/usr/share/plymouth/themes/Betelgeuse' ]; then
logg info 'Symlinking /usr/local/share/plymouth/themes/Betelgeuse to /usr/share/plymouth/themes/Betelgeuse'
sudo ln -s '/usr/local/share/plymouth/themes/Betelgeuse' '/usr/share/plymouth/themes/Betelgeuse'
fi
### Set default Plymouth theme
if command -v plymouth-set-default-theme > /dev/null; then
sudo plymouth-set-default-theme -R '{{ .theme }}' || EXIT_CODE=$?
sudo plymouth-set-default-theme -R 'Betelgeuse' || 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
@ -66,12 +68,12 @@ 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
if [ -f "/usr/local/share/plymouth/themes/Betelgeuse/Betelgeuse.plymouth" ]; then
# Required sometimes
sudo update-alternatives --set default.plymouth "/usr/local/share/plymouth/themes/{{ .theme }}/{{ .theme }}.plymouth"
sudo update-alternatives --set default.plymouth "/usr/local/share/plymouth/themes/Betelgeuse/Betelgeuse.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!"
logg warn "/usr/local/share/plymouth/themes/Betelgeuse/Betelgeuse.plymouth does not exist!"
fi
else
logg warn 'update-alternatives is not available'

View file

@ -10,19 +10,7 @@
# cat ~/.bashrc | mail -s "My subject" name@email.com
# ```
### Acquire SENDGRID_API_KEY
SENDGRID_API_KEY_FILE="${XDG_DATA_HOME:-$HOME/.local/share}/chezmoi/home/.chezmoitemplates/secrets/SENDGRID_API_KEY"
if [ -f "$SENDGRID_API_KEY_FILE" ]; then
logg info "Found SENDGRID_API_KEY in ${XDG_DATA_HOME:-$HOME/.local/share}/chezmoi/home/.chezmoitemplates/secrets"
if [ -f "${XDG_CONFIG_HOME:-$HOME/.config}/age/chezmoi.txt" ]; then
logg info 'Decrypting SENDGRID_API_KEY token with Age encryption key'
SENDGRID_API_KEY="$(cat "$SENDGRID_API_KEY_FILE" | chezmoi decrypt)"
else
logg warn 'Age encryption key is missing from ~/.config/age/chezmoi.txt'
fi
else
logg warn "SENDGRID_API_KEY is missing from ${XDG_DATA_HOME:-$HOME/.local/share}/chezmoi/home/.chezmoitemplates/secrets"
fi
set -euo pipefail
### Acquire PUBLIC_SERVICES_DOMAIN and PRIMARY_EMAIL
if command -v yq > /dev/null; then
@ -36,9 +24,8 @@ else
logg warn 'yq is not installed on the system and is required for populating the PUBLIC_SERVICES_DOMAIN and PRIMARY_EMAIL'
fi
### Setup Postfix if SENDGRID_API_KEY is retrieved
if [ -n "$SENDGRID_API_KEY" ] && [ "$SENDGRID_API_KEY" != "" ]; then
if get-secret --exists SENDGRID_API_KEY; then
if command -v postfix > /dev/null; then
### Ensure dependencies are installed
if command -v apt-get > /dev/null; then

View file

@ -13,6 +13,8 @@
#
# * [Privoxy configuration](https://github.com/megabyte-labs/install.doctor/tree/master/home/dot_config/privoxy/config)
set -euo pipefail
### Configure variables
if [ -d /Applications ] && [ -d /System ]; then
### macOS

View file

@ -8,7 +8,7 @@
#
# This script sets up Rclone to provide several folders that are synchronized with S3-compliant buckets (using CloudFlare R2 by default).
# The script ensures required directories are created and that proper permissions are applied. This script will only run if `rclone` is
# available in the `PATH`. It also requires the user to provide `CLOUDFLARE_R2_ID` and `CLOUDFLARE_R2_SECRET` as either environment variables
# available in the `PATH`. It also requires the user to provide `CLOUDFLARE_R2_SECRET` and `CLOUDFLARE_R2_SECRET` as either environment variables
# or through the encrypted repository-fork-housed method detailed in the [Secrets documentation](https://install.doctor/docs/customization/secrets).
#
# ## Mounts
@ -44,81 +44,193 @@
# * [Rclone mount script](https://github.com/megabyte-labs/install.doctor/tree/master/home/dot_local/bin/executable_rclone-mount)
# * [Rclone default configurations](https://github.com/megabyte-labs/install.doctor/tree/master/home/dot_config/rclone)
# * [Rclone documentation](https://rclone.org/docs/)
if command -v rclone > /dev/null; then
{{- if and (or (and (stat (joinPath .host.home ".config" "age" "chezmoi.txt")) (stat (joinPath .chezmoi.sourceDir ".chezmoitemplates" "secrets" "CLOUDFLARE_R2_ID"))) (env "CLOUDFLARE_R2_ID")) (or (and (stat (joinPath .host.home ".config" "age" "chezmoi.txt")) (stat (joinPath .chezmoi.sourceDir ".chezmoitemplates" "secrets" "CLOUDFLARE_R2_SECRET"))) (env "CLOUDFLARE_R2_SECRET")) (ne .user.cloudflare.r2 "") }}
logg info 'Removing ~/.config/rclone/rclone.conf Install Doctor managed block'
CONFIG_FILE="${XDG_CONFIG_HOME:-$HOME/.config}/rclone/rclone.conf"
if cat "$CONFIG_FILE" | grep '# INSTALL DOCTOR MANAGED S3 START' > /dev/null; then
# TODO: Remove old block
START_LINE="$(echo `grep -n -m 1 "# INSTALL DOCTOR MANAGED S3 START" "$CONFIG_FILE" | cut -f1 -d ":"`)"
END_LINE="$(echo `grep -n -m 1 "# INSTALL DOCTOR MANAGED S3 END" "$CONFIG_FILE" | cut -f1 -d ":"`)"
if command -v gsed > /dev/null; then
gsed -i "$START_LINE,${END_LINE}d" "$CONFIG_FILE" > /dev/null
set -euo pipefail
### Acquire CLOUDFLARE_R2_ID
if [ -z "$CLOUDFLARE_R2_ID" ]; then
CLOUDFLARE_R2_ID_FILE="${XDG_DATA_HOME:-$HOME/.local/share}/chezmoi/home/.chezmoitemplates/secrets/CLOUDFLARE_R2_ID"
if [ -f "$CLOUDFLARE_R2_ID_FILE" ]; then
logg info "Found CLOUDFLARE_R2_ID in ${XDG_DATA_HOME:-$HOME/.local/share}/chezmoi/home/.chezmoitemplates/secrets"
if [ -f "${XDG_CONFIG_HOME:-$HOME/.config}/age/chezmoi.txt" ]; then
logg info 'Decrypting CLOUDFLARE_R2_ID token with Age encryption key'
CLOUDFLARE_R2_ID="$(cat "$CLOUDFLARE_R2_ID_FILE" | chezmoi decrypt)"
else
sed -i "$START_LINE,${END_LINE}d" "$CONFIG_FILE" > /dev/null
logg warn 'Age encryption key is missing from ~/.config/age/chezmoi.txt'
exit 1
fi
else
logg warn "CLOUDFLARE_R2_ID is missing from ${XDG_DATA_HOME:-$HOME/.local/share}/chezmoi/home/.chezmoitemplates/secrets"
exit 1
fi
logg info 'Adding ~/.config/rclone/rclone.conf INSTALL DOCTOR managed block'
sudo tee -a "$CONFIG_FILE" > /dev/null <<EOT
else
logg info 'CLOUDFLARE_R2_ID provided as environment variable'
fi
### Acquire CLOUDFLARE_R2_SECRET
if [ -z "$CLOUDFLARE_R2_SECRET" ]; then
CLOUDFLARE_R2_SECRET_FILE="${XDG_DATA_HOME:-$HOME/.local/share}/chezmoi/home/.chezmoitemplates/secrets/CLOUDFLARE_R2_SECRET"
if [ -f "$CLOUDFLARE_R2_SECRET_FILE" ]; then
logg info "Found CLOUDFLARE_R2_SECRET in ${XDG_DATA_HOME:-$HOME/.local/share}/chezmoi/home/.chezmoitemplates/secrets"
if [ -f "${XDG_CONFIG_HOME:-$HOME/.config}/age/chezmoi.txt" ]; then
logg info 'Decrypting CLOUDFLARE_R2_SECRET token with Age encryption key'
CLOUDFLARE_R2_SECRET="$(cat "$CLOUDFLARE_R2_SECRET_FILE" | chezmoi decrypt)"
else
logg warn 'Age encryption key is missing from ~/.config/age/chezmoi.txt'
exit 1
fi
else
logg warn "CLOUDFLARE_R2_SECRET is missing from ${XDG_DATA_HOME:-$HOME/.local/share}/chezmoi/home/.chezmoitemplates/secrets"
exit 1
fi
else
logg info 'CLOUDFLARE_R2_SECRET provided as environment variable'
fi
### Acquire CLOUDFLARE_R2_ID_USER
if [ -z "$CLOUDFLARE_R2_ID_USER" ]; then
CLOUDFLARE_R2_ID_USER_FILE="${XDG_DATA_HOME:-$HOME/.local/share}/chezmoi/home/.chezmoitemplates/secrets/CLOUDFLARE_R2_ID_USER"
if [ -f "$CLOUDFLARE_R2_ID_USER_FILE" ]; then
logg info "Found CLOUDFLARE_R2_ID_USER in ${XDG_DATA_HOME:-$HOME/.local/share}/chezmoi/home/.chezmoitemplates/secrets"
if [ -f "${XDG_CONFIG_HOME:-$HOME/.config}/age/chezmoi.txt" ]; then
logg info 'Decrypting CLOUDFLARE_R2_ID_USER token with Age encryption key'
CLOUDFLARE_R2_ID_USER="$(cat "$CLOUDFLARE_R2_ID_USER_FILE" | chezmoi decrypt)"
else
logg warn 'Age encryption key is missing from ~/.config/age/chezmoi.txt'
exit 1
fi
else
logg warn "CLOUDFLARE_R2_ID_USER is missing from ${XDG_DATA_HOME:-$HOME/.local/share}/chezmoi/home/.chezmoitemplates/secrets"
exit 1
fi
else
logg info 'CLOUDFLARE_R2_ID_USER provided as environment variable'
fi
### Acquire CLOUDFLARE_R2_SECRET_USER
if [ -z "$CLOUDFLARE_R2_SECRET_USER" ]; then
CLOUDFLARE_R2_SECRET_USER_FILE="${XDG_DATA_HOME:-$HOME/.local/share}/chezmoi/home/.chezmoitemplates/secrets/CLOUDFLARE_R2_SECRET_USER"
if [ -f "$CLOUDFLARE_R2_SECRET_USER_FILE" ]; then
logg info "Found CLOUDFLARE_R2_SECRET_USER in ${XDG_DATA_HOME:-$HOME/.local/share}/chezmoi/home/.chezmoitemplates/secrets"
if [ -f "${XDG_CONFIG_HOME:-$HOME/.config}/age/chezmoi.txt" ]; then
logg info 'Decrypting CLOUDFLARE_R2_SECRET_USER token with Age encryption key'
CLOUDFLARE_R2_SECRET_USER="$(cat "$CLOUDFLARE_R2_SECRET_USER_FILE" | chezmoi decrypt)"
else
logg warn 'Age encryption key is missing from ~/.config/age/chezmoi.txt'
exit 1
fi
else
logg warn "CLOUDFLARE_R2_SECRET_USER is missing from ${XDG_DATA_HOME:-$HOME/.local/share}/chezmoi/home/.chezmoitemplates/secrets"
exit 1
fi
else
logg info 'CLOUDFLARE_R2_SECRET_USER provided as environment variable'
fi
### Begin configuration
if command -v rclone > /dev/null; then
R2_ENDPOINT="$(yq '.data.user.cloudflare.r2' "${XDG_CONFIG_HOME:-$HOME/.config}/chezmoi/chezmoi.yaml")"
if [ "$R2_ENDPOINT" != 'null' ]; then
logg info 'Removing ~/.config/rclone/rclone.conf Install Doctor managed block'
CONFIG_FILE="${XDG_CONFIG_HOME:-$HOME/.config}/rclone/rclone.conf"
if cat "$CONFIG_FILE" | grep '# INSTALL DOCTOR MANAGED S3 START' > /dev/null; then
# TODO: Remove old block
START_LINE="$(echo `grep -n -m 1 "# INSTALL DOCTOR MANAGED S3 START" "$CONFIG_FILE" | cut -f1 -d ":"`)"
END_LINE="$(echo `grep -n -m 1 "# INSTALL DOCTOR MANAGED S3 END" "$CONFIG_FILE" | cut -f1 -d ":"`)"
if command -v gsed > /dev/null; then
gsed -i "$START_LINE,${END_LINE}d" "$CONFIG_FILE" > /dev/null
else
sed -i "$START_LINE,${END_LINE}d" "$CONFIG_FILE" > /dev/null
fi
fi
logg info 'Adding ~/.config/rclone/rclone.conf INSTALL DOCTOR managed block'
tee -a "$CONFIG_FILE" > /dev/null <<EOT
# INSTALL DOCTOR MANAGED S3 START
[User-{{ .user.username}}]
access_key_id = {{ if (stat (joinPath .chezmoi.sourceDir ".chezmoitemplates" "secrets" "CLOUDFLARE_R2_ID_USER")) }}{{- includeTemplate "secrets/CLOUDFLARE_R2_ID_USER" | decrypt | trim -}}{{ else }}{{- env "CLOUDFLARE_R2_ID_USER" -}}{{ end }}
[User-$USER]
access_key_id = ${CLOUDFLARE_R2_ID_USER}
acl = private
endpoint = {{ .user.cloudflare.r2 }}.r2.cloudflarestorage.com
endpoint = ${R2_ENDPOINT}.r2.cloudflarestorage.com
provider = Cloudflare
region = auto
secret_access_key = {{ if (stat (joinPath .chezmoi.sourceDir ".chezmoitemplates" "secrets" "CLOUDFLARE_R2_SECRET_USER")) }}{{- includeTemplate "secrets/CLOUDFLARE_R2_SECRET_USER" | decrypt | trim -}}{{ else }}{{- env "CLOUDFLARE_R2_SECRET_USER" -}}{{ end }}
secret_access_key = ${CLOUDFLARE_R2_SECRET_USER}
type = s3
# INSTALL DOCTOR MANAGED S3 END
EOT
{{- end }}
# sudo chown -f root "$CONFIG_FILE"
sudo chmod -f 600 "$CONFIG_FILE"
logg info 'Ensuring /var/cache/rclone exists'
sudo mkdir -p /var/cache/rclone
sudo chmod 750 /var/cache/rclone
fi
### 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 rclone rclone
sudo add-usergroup "$USER" rclone
fi
### User config file permissions
sudo chmod -f 600 "$CONFIG_FILE"
sudo chown -f "$USER:rclone" "$CONFIG_FILE"
### Setup /var/cache/rclone
logg info 'Ensuring /var/cache/rclone exists'
sudo mkdir -p /var/cache/rclone
sudo chmod 750 /var/cache/rclone
sudo chown -Rf rclone:rclone /var/cache/rclone
### Setup /var/log/rclone
logg info 'Ensuring /var/log/rclone exists'
sudo mkdir -p /var/log/rclone
sudo chmod 750 /var/log/rclone
sudo chown -Rf rclone:rclone /var/log/rclone
### Add rclone-mount to /usr/local/bin
logg info 'Adding ~/.local/bin/rclone-mount to /usr/local/bin'
sudo cp -f "$HOME/.local/bin/rclone-mount" /usr/local/bin/rclone-mount
sudo chmod +x /usr/local/bin/rclone-mount
### Setup /etc/rcloneignore
logg info 'Adding ~/.config/rclone/rcloneignore to /etc/rcloneignore'
sudo cp -f "${XDG_CONFIG_HOME:-$HOME/.config}/rclone/rcloneignore" /etc/rcloneignore
sudo chown -Rf rclone:rclone /etc/rcloneignore
sudo chmod 640 /etc/rcloneignore
### Setup /etc/rclone.conf
logg info 'Adding ~/.config/rclone/system-rclone.conf to /etc/rclone.conf'
sudo cp -f "${XDG_CONFIG_HOME:-$HOME/.config}/rclone/system-rclone.conf" /etc/rclone.conf
sudo chown -Rf rclone:rclone /etc/rclone.conf
sudo chmod 600 /etc/rclone.conf
if [ -d /Applications ] && [ -d /System ]; then
### Enable Rclone mounts
logg info 'Ensuring Rclone mount-on-reboot definitions are in place'
if [ -f "$HOME/Library/LaunchDaemons/rclone.private.plist" ] && [ ! -f "/Library/LaunchDaemons/rclone.private.plist" ]; then
logg info 'Adding /Volumes/Private as S3 bucket mount, enabled at boot'
sudo mkdir -p /Library/LaunchDaemons
sudo cp -f "$HOME/Library/LaunchDaemons/rclone.private.plist" '/Library/LaunchDaemons/rclone.private.plist'
sudo launchctl load '/Library/LaunchDaemons/rclone.private.plist' && logg success 'launchctl load successful'
sudo mkdir -p /Library/LaunchDaemons
### rclone.private.plist
sudo cp -f "$HOME/Library/LaunchDaemons/rclone.private.plist" '/Library/LaunchDaemons/rclone.private.plist'
logg info 'Ensuring rclone.private.plist service is started'
if sudo launchctl list | grep 'rclone.private.plist' > /dev/null; then
logg info 'Unloading previous rclone.private.plist configuration'
sudo launchctl unload /Library/LaunchDaemons/rclone.private.plist
fi
if [ -f "$HOME/Library/LaunchDaemons/rclone.public.plist" ] && [ ! -f "/Library/LaunchDaemons/rclone.public.plist" ]; then
logg info 'Adding /Volumes/Public as S3 bucket mount, enabled at boot'
sudo mkdir -p /Library/LaunchDaemons
sudo cp -f "$HOME/Library/LaunchDaemons/rclone.public.plist" '/Library/LaunchDaemons/rclone.public.plist'
sudo launchctl load '/Library/LaunchDaemons/rclone.public.plist' && logg success 'launchctl load successful'
logg info 'Starting up rclone.private.plist configuration'
sudo launchctl load -w /Library/LaunchDaemons/rclone.private.plist
### rclone.public.plist
sudo cp -f "$HOME/Library/LaunchDaemons/rclone.public.plist" '/Library/LaunchDaemons/rclone.public.plist'
logg info 'Ensuring rclone.public.plist service is started'
if sudo launchctl list | grep 'rclone.public.plist' > /dev/null; then
logg info 'Unloading previous rclone.public.plist configuration'
sudo launchctl unload /Library/LaunchDaemons/rclone.public.plist
fi
if [ -f "$HOME/Library/LaunchDaemons/rclone.user.plist" ] && [ ! -f "/Library/LaunchDaemons/rclone.user.plist" ]; then
logg info "Adding /Volumes/User-$USER as S3 bucket mount, enabled at boot"
sudo mkdir -p /Library/LaunchDaemons
sudo cp -f "$HOME/Library/LaunchDaemons/rclone.user.plist" '/Library/LaunchDaemons/rclone.user.plist'
sudo launchctl load '/Library/LaunchDaemons/rclone.user.plist' && logg success 'launchctl load successful'
logg info 'Starting up rclone.public.plist configuration'
sudo launchctl load -w /Library/LaunchDaemons/rclone.public.plist
### rclone.user.plist
sudo cp -f "$HOME/Library/LaunchDaemons/rclone.user.plist" '/Library/LaunchDaemons/rclone.user.plist'
logg info 'Ensuring rclone.user.plist service is started'
if sudo launchctl list | grep 'rclone.user.plist' > /dev/null; then
logg info 'Unloading previous rclone.user.plist configuration'
sudo launchctl unload /Library/LaunchDaemons/rclone.user.plist
fi
logg info 'Starting up rclone.user.plist configuration'
sudo launchctl load -w "$HOME/Library/LaunchDaemons/rclone.user.plist"
elif [ -d /etc/systemd/system ]; then
find "${XDG_CONFIG_HOME:-$HOME/.config}/rclone/system" -mindepth 1 -maxdepth 1 -type f | while read RCLONE_SERVICE; do
### Add systemd service file
@ -126,17 +238,20 @@ EOT
FILENAME="$(basename "$RCLONE_SERVICE")"
SERVICE_ID="$(echo "$FILENAME" | sed 's/.service//')"
sudo cp -f "$RCLONE_SERVICE" "/etc/systemd/system/$(basename "$RCLONE_SERVICE")"
### Ensure mount folder is created
logg info "Ensuring /mnt/$SERVICE_ID is created with proper permissions"
sudo mkdir -p "/mnt/$SERVICE_ID"
sudo chmod 750 "/mnt/$SERVICE_ID"
### Enable / restart the service
logg info "Enabling / restarting the $SERVICE_ID S3 service"
sudo systemctl enable "$SERVICE_ID"
sudo systemctl restart "$SERVICE_ID"
done
### Add user Rclone mount
logg info 'Adding user S3 rclone mount (available at ~/.local/mnt/s3)'
logg info 'Adding user S3 rclone mount (available at ~/Cloud/User and /Volumes/User)'
sudo cp -f "${XDG_CONFIG_HOME:-$HOME/.config}/rclone/s3-user.service" "/etc/systemd/system/s3-${USER}.service"
logg info 'Enabling / restarting the S3 user mount'
sudo systemctl enable "s3-${USER}"

View file

@ -2,6 +2,8 @@
# @file rkhunter configuration
# @brief This script applies the rkhunter integration and updates it as well
set -euo pipefail
if command -v rkhunter > /dev/null; then
if [ -d /Applications ] && [ -d /System ]; then
### macOS

View file

@ -47,6 +47,9 @@
#
# * [Default Samba configuration](https://github.com/megabyte-labs/install.doctor/tree/master/home/dot_local/samba/config.tmpl)
# * [Secrets / Environment variables documentation](https://install.doctor/docs/customization/secrets)
set -euo pipefail
### Configure Samba server
if command -v smbd > /dev/null; then
# Add user / group with script in ~/.local/bin/add-usergroup, if it is available
@ -63,26 +66,67 @@ if command -v smbd > /dev/null; then
fi
PRIVATE_SHARE="/$MNT_FOLDER/Private"
PUBLIC_SHARE="/$MNT_FOLDER/Public"
### Private share
logg info "Ensuring $PRIVATE_SHARE is created"
sudo mkdir -p "$PRIVATE_SHARE"
sudo chmod 750 "$PRIVATE_SHARE"
sudo chown -Rf root:rclone "$PRIVATE_SHARE"
### Public share
logg info "Ensuring $PUBLIC_SHARE is created"
sudo mkdir -p "$PUBLIC_SHARE"
sudo chmod 755 "$PUBLIC_SHARE"
sudo chown -Rf root:rclone "$PUBLIC_SHARE"
logg info "Ensuring $HOME/Public is created"
mkdir -p "$HOME/Public"
chmod 755 "$HOME/Public"
chown -Rf "$USER":rclone "$HOME/Public"
### User share
logg info "Ensuring $HOME/Shared is created"
mkdir -p "$HOME/Shared"
chmod 755 "$HOME/Shared"
chown -Rf "$USER":rclone "$HOME/Shared"
### Copy the Samba server configuration file
if [ -d /Applications ] && [ -d /System ]; then
sudo sharing -a "$PRIVATE_SHARE" -S "Private (System)" -n "Private (System)" -g 000 -s 001 -E 1 -R 1 && logg success "Configured $PRIVATE_SHARE as a private Samba share" || logg info 'sharing command failed - it is likely that the share was already set up'
sudo sharing -a "$PUBLIC_SHARE" -S "Public (System)" -n "Public (System)" -g 001 -s 001 -E 1 -R 0 && logg success "Configured $PUBLIC_SHARE as a public Samba share" || logg info 'sharing command failed - it is likely that the share was already set up'
sudo sharing -a "$HOME/Public" -S "Public (User)" -n "Public (User)" -g 001 -s 001 -E 1 -R 0 && logg success "Configured $HOME/Public as a public Samba share" || logg info 'sharing command failed - it is likely that the share was already set up'
### System Private Samba Share
if SMB_OUTPUT=$(sudo sharing -a "$PRIVATE_SHARE" -S "Private (System)" -n "Private (System)" -g 000 -s 001 -E 1 -R 1); then
logg success "Configured $PRIVATE_SHARE as a private Samba share"
else
if echo $SMB_OUTPUT | grep 'smb name already exists' > /dev/null; then
logg info "$PRIVATE_SHARE Samba share already exists"
else
logg error 'An error occurred while running sudo sharing -a "$PRIVATE_SHARE" -S "Private (System)" -n "Private (System)" -g 000 -s 001 -E 1 -R 1'
echo "$SMB_OUTPUT"
fi
fi
### System Public Samba Share
if SMB_OUTPUT=$(sudo sharing -a "$PUBLIC_SHARE" -S "Public (System)" -n "Public (System)" -g 001 -s 001 -E 1 -R 0); then
logg success "Configured $PUBLIC_SHARE as a system public Samba share"
else
if echo $SMB_OUTPUT | grep 'smb name already exists' > /dev/null; then
logg info "$PUBLIC_SHARE Samba share already exists"
else
logg error 'An error occurred while running sudo sharing -a "$PUBLIC_SHARE" -S "Public (System)" -n "Public (System)" -g 001 -s 001 -E 1 -R 0'
echo "$SMB_OUTPUT"
fi
fi
### User Shared Samba Share
if SMB_OUTPUT=$(sudo sharing -a "$HOME/Shared" -S "Shared (User)" -n "Shared (User)" -g 001 -s 001 -E 1 -R 0); then
logg success "Configured $HOME/Shared as a user-scoped Samba share"
else
if echo $SMB_OUTPUT | grep 'smb name already exists' > /dev/null; then
logg info "$HOME/Shared Samba share already exists"
else
logg error 'An error occurred while running sudo sharing -a "$HOME/Shared" -S "Shared (User)" -n "Shared (User)" -g 001 -s 001 -E 1 -R 0'
echo "$SMB_OUTPUT"
fi
fi
else
### Copy Samba configuration
logg info "Copying Samba server configuration to /etc/samba/smb.conf"
sudo cp -f "${XDG_CONFIG_HOME:-$HOME/.config}/samba/config" "/etc/samba/smb.conf"
### Reload configuration file changes
logg info 'Reloading the smbd config'
smbcontrol smbd reload-config

View file

@ -2,16 +2,23 @@
# @file sftpgo configuration
# @brief This script copies over the required configuration files for sftpgo and then initializes sftpgo
set -euo pipefail
if command -v sftpgo > /dev/null; then
### Copy configuration file
sudo mkdir -p /usr/local/etc/sftpgo
logg info 'Copying over sftpgo configuration to /usr/local/etc/sftpgo/sftpgo.json'
sudo cp -f "$HOME/.local/etc/sftpgo/sftpgo.json" /usr/local/etc/sftpgo/sftpgo.json
### Copy branding assets / banner
logg info 'Copying over sftpgo branding assets'
sudo cp -f "$HOME/.local/etc/sftpgo/banner" /usr/local/etc/sftpgo/banner
sudo mkdir -p /usr/local/etc/branding
sudo cp -f "$HOME/.local/etc/branding/favicon.ico" /usr/local/etc/branding/favicon.ico
sudo cp -f "$HOME/.local/etc/branding/logo-color-256x256.png" /usr/local/etc/branding/logo-color-256x256.png
sudo cp -f "$HOME/.local/etc/branding/logo-color-900x900.png" /usr/local/etc/branding/logo-color-900x900.png
### Initialize
logg info 'Running sudo sftpgo initprovider'
sudo sftpgo initprovider
else

View file

@ -41,6 +41,8 @@
# * [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
set -euo pipefail
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'

View file

@ -10,6 +10,8 @@
# CloudFlare WARP, you will have to set up a [split tunnel](https://www.youtube.com/watch?v=eDFs8hm3xWc) for
# [Tailscale IP addresses](https://tailscale.com/kb/1105/other-vpns).
set -euo pipefail
### Disconnect from CloudFlare WARP (if connected)
if command -v warp-cli > /dev/null; then
warp-cli disconnect && logg info 'CloudFlare WARP temporarily disconnected while Tailscale connects'
@ -35,32 +37,38 @@ if [ -d /Applications ] && [ -d /System ]; then
fi
### Acquire TAILSCALE_AUTH_KEY
TAILSCALE_KEY_FILE="${XDG_DATA_HOME:-$HOME/.local/share}/chezmoi/home/.chezmoitemplates/secrets/TAILSCALE_AUTH_KEY"
if [ -f "$TAILSCALE_KEY_FILE" ]; then
logg info "Found TAILSCALE_AUTH_KEY in ${XDG_DATA_HOME:-$HOME/.local/share}/chezmoi/home/.chezmoitemplates/secrets"
if [ -f "${XDG_CONFIG_HOME:-$HOME/.config}/age/chezmoi.txt" ]; then
logg info 'Decrypting TAILSCALE_AUTH_KEY token with Age encryption key'
TAILSCALE_AUTH_KEY="$(cat "$TAILSCALE_KEY_FILE" | chezmoi decrypt)"
if [ -z "$TAILSCALE_AUTH_KEY" ]; then
TAILSCALE_AUTH_KEY_FILE="${XDG_DATA_HOME:-$HOME/.local/share}/chezmoi/home/.chezmoitemplates/secrets/TAILSCALE_AUTH_KEY"
if [ -f "$TAILSCALE_AUTH_KEY_FILE" ]; then
logg info "Found TAILSCALE_AUTH_KEY in ${XDG_DATA_HOME:-$HOME/.local/share}/chezmoi/home/.chezmoitemplates/secrets"
if [ -f "${XDG_CONFIG_HOME:-$HOME/.config}/age/chezmoi.txt" ]; then
logg info 'Decrypting TAILSCALE_AUTH_KEY token with Age encryption key'
TAILSCALE_AUTH_KEY="$(cat "$TAILSCALE_AUTH_KEY_FILE" | chezmoi decrypt)"
else
logg warn 'Age encryption key is missing from ~/.config/age/chezmoi.txt'
exit 1
fi
else
logg warn 'Age encryption key is missing from ~/.config/age/chezmoi.txt'
logg warn "TAILSCALE_AUTH_KEY is missing from ${XDG_DATA_HOME:-$HOME/.local/share}/chezmoi/home/.chezmoitemplates/secrets"
exit 1
fi
else
logg warn "TAILSCALE_AUTH_KEY is missing from ${XDG_DATA_HOME:-$HOME/.local/share}/chezmoi/home/.chezmoitemplates/secrets"
logg info 'TAILSCALE_AUTH_KEY provided as environment variable'
fi
### Connect to Tailscale network
if [ -n "$TAILSCALE_AUTH_KEY" ] && [ "$TAILSCALE_AUTH_KEY" != "" ]; then
if get-secret --exists TAILSCALE_AUTH_KEY; then
if [ -f /Applications/Tailscale.app/Contents/MacOS/Tailscale ]; then
logg info 'Connecting to Tailscale with user-defined authentication key (TAILSCALE_AUTH_KEY)'
timeout 30 /Applications/Tailscale.app/Contents/MacOS/Tailscale up --authkey="$TAILSCALE_AUTH_KEY" --accept-routes || EXIT_CODE=$?
timeout 30 /Applications/Tailscale.app/Contents/MacOS/Tailscale up --authkey="$(get-secret TAILSCALE_AUTH_KEY)" --accept-routes || EXIT_CODE=$?
if [ -n "$EXIT_CODE" ]; then
logg warn '/Applications/Tailscale.app/Contents/MacOS/Tailscale timed out'
fi
logg info 'Disabling update check'
/Applications/Tailscale.app/Contents/MacOS/Tailscale set --update-check=false
elif command -v tailscale > /dev/null && [ "$TAILSCALE_AUTH_KEY" != "" ]; then
elif command -v tailscale > /dev/null; then
logg info 'Connecting to Tailscale with user-defined authentication key (TAILSCALE_AUTH_KEY)'
timeout 30 tailscale up --authkey="$TAILSCALE_AUTH_KEY" --accept-routes || EXIT_CODE=$?
timeout 30 tailscale up --authkey="$(get-secret TAILSCALE_AUTH_KEY)" --accept-routes || EXIT_CODE=$?
if [ -n "$EXIT_CODE" ]; then
logg warn 'tailscale up timed out'
else

View file

@ -1,10 +0,0 @@
#!/usr/bin/env bash
# @file tfenv
# @brief Configures tfenv to use the latest version of Terraform
if command -v tfenv > /dev/null; then
logg info 'Configuring tfenv to use latest version of Terraform'
tfenv use latest
else
logg warn 'tfenv is not available in the PATH'
fi

View file

@ -4,6 +4,8 @@
# @description
# This script applies a Timeshift configuration that defines how Timeshift should maintain system backups.
set -euo pipefail
if command -v timeshift > /dev/null; then
logg info 'Ensuring /etc/timeshift is a directory'
sudo mkdir -p /etc/timeshift

View file

@ -14,6 +14,8 @@
#
# * [Tor configuration](https://github.com/megabyte-labs/install.doctor/tree/master/home/dot_config/tor/torrc)
set -euo pipefail
### Determine the Tor configuration location by checking whether the system is macOS or Linux
if [ -d /Applications ] && [ -d /System ]; then
### macOS
@ -40,7 +42,7 @@ if command -v torify > /dev/null; then
ln -s /usr/local/etc/tor/torrc "${HOMEBREW_PREFIX:-/opt/homebrew}/etc/tor/torrc"
else
if [ -L "${HOMEBREW_PREFIX:-/opt/homebrew}/etc/tor/torrc" ]; then
logg info ""${HOMEBREW_PREFIX:-/opt/homebrew}/etc/tor/torrc" symlinked"
logg info ""${HOMEBREW_PREFIX:-/opt/homebrew}/etc/tor/torrc" already symlinked to $TORRC_CONFIG"
else
logg warn ""${HOMEBREW_PREFIX:-/opt/homebrew}/etc/tor/torrc" not symlinked!"
fi

View file

@ -2,6 +2,8 @@
# @file VIM Plugins AOT Installation
# @brief This script triggers VIM to pre-install plugins so that VIM loads into the desired state the first time it is invoked
set -euo pipefail
logg info "Installing VIM plugins" && vim +'PlugInstall --sync' +qall
# @description This script installs the extensions defined in `${XDG_CONFIG_HOME:-$HOME/.config}/coc/extensions/package.json`

View file

@ -4,6 +4,8 @@
# @description
# This script ensures the VirtualBox extension pack that corresponds with VirtualBox's version is properly installed.
set -euo pipefail
### Run logic if VirtualBox is installed
if command -v VirtualBox > /dev/null; then
### Install VirtualBox extension pack if it is not installed already

View file

@ -42,6 +42,8 @@
# * [`home/.chezmoidata.yaml`](https://github.com/megabyte-labs/install.doctor/blob/master/home/.chezmoidata.yaml)
# * [Default license key gist](https://gist.github.com/PurpleVibe32/30a802c3c8ec902e1487024cdea26251)
set -euo pipefail
### Run logic if VMware is installed
if command -v vmware > /dev/null; then
### Build kernel modules if they are not present
@ -137,9 +139,15 @@ if command -v vagrant > /dev/null && command -v vmware-id > /dev/null; then
logg success 'Generated Vagrant VMWare Utility certificates via vagrant-vmware-utility certificate generate'
fi
logg info 'Ensuring the Vagrant VMWare Utility service is enabled'
sudo vagrant-vmware-utility service install || EXIT_CODE=$?
if [ -n "$EXIT_CODE" ]; then
logg info 'The Vagrant VMWare Utility command vagrant-vmware-utility service install failed. If it was already set up, there should be a notice above.'
if VVU_OUTPUT=$(sudo vagrant-vmware-utility service install 2>&1); then
logg info 'sudo vagrant-vmware-utility service install successfully ran'
else
if echo $VVU_OUTPUT | grep 'service is already installed' > /dev/null; then
logg info 'Vagrant VMWare Utility is already installed'
else
logg error 'An error occurred while running sudo vagrant-vmware-utility service install'
echo "$VVU_OUTPUT"
fi
fi
fi
else

View file

@ -2,9 +2,17 @@
# @file Volta initialization
# @brief This script initializes Volta and ensures the latest version of node and yarn are installed
set -euo pipefail
export VOLTA_HOME="${XDG_DATA_HOME:-$HOME/.local/share}/volta"
export PATH="$VOLTA_HOME/bin:$PATH"
### Disconnect from CloudFlare WARP (if connected)
if command -v warp-cli > /dev/null; then
warp-cli disconnect && logg info 'CloudFlare WARP temporarily disconnected while Volta installs Node / Yarn'
fi
### Configure Volta if it is installed
if command -v volta > /dev/null; then
logg info 'Running volta setup'
volta setup

View file

@ -72,6 +72,8 @@
# * [Visual Studio Code settings folder](https://github.com/megabyte-labs/install.doctor/blob/master/home/dot_config/Code/User)
# * [Visual Studio Code `extensions.json`](https://github.com/megabyte-labs/install.doctor/blob/master/home/dot_config/Code/User/extensions.json)
set -euo pipefail
### Hides useless error during extension installations
# Error looks like:
# (node:53151) [DEP0005] DeprecationWarning: Buffer() is deprecated due to security and usability issues. Please use the Buffer.alloc(), Buffer.allocUnsafe(), or Buffer.from() methods instead.

View file

@ -50,6 +50,8 @@
# * [Linux managed configuration](https://github.com/megabyte-labs/install.doctor/tree/master/home/dot_config/warp/private_mdm.xml.tmpl)
# * [macOS managed configuration](https://github.com/megabyte-labs/install.doctor/tree/master/home/Library/Managed%20Preferences/private_com.cloudflare.warp.plist.tmpl)
set -euo pipefail
SSL_CERT_PATH="/etc/ssl/cert.pem"
### Install CloudFlare WARP (on non-WSL *nix systems)
if [[ ! "$(test -d /proc && grep Microsoft /proc/version > /dev/null)" ]]; then
@ -60,7 +62,7 @@ if [[ ! "$(test -d /proc && grep Microsoft /proc/version > /dev/null)" ]]; then
else
logg info 'Cloudflare WARP already installed'
fi
elif [ '{{ .host.distro.id }}' = 'debian' ]; then
elif [ -n "$(uname -a | grep Debian)" ]; then
### Add CloudFlare WARP desktop app apt-get source
if [ ! -f /etc/apt/sources.list.d/cloudflare-client.list ]; then
logg info 'Adding CloudFlare WARP keyring'
@ -71,7 +73,7 @@ if [[ ! "$(test -d /proc && grep Microsoft /proc/version > /dev/null)" ]]; then
### Update apt-get and install the CloudFlare WARP CLI
sudo apt-get update && sudo apt-get install -y cloudflare-warp
elif [ '{{ .host.distro.id }}' = 'ubuntu' ]; then
elif [ -n "$(uname -a | grep Ubuntu)" ]; then
### Add CloudFlare WARP desktop app apt-get source
if [ ! -f /etc/apt/sources.list.d/cloudflare-client.list ]; then
logg info 'Adding CloudFlare WARP keyring'

View file

@ -2,6 +2,11 @@
# @file Wazuh Client Install
# @brief Installs the Wazuh client and connects to the manager if configured to do so through secrets / environment variables
set -euo pipefail
### Ensure secrets
get-secret --exists WAZUH_MANAGER WAZUH_REGISTRATION_PASSWORD
if [ -d /Applications ] && [ -d /System ]; then
### macOS
logg info 'Downloading the macOS Wazuh agent pkg'
@ -13,7 +18,7 @@ if [ -d /Applications ] && [ -d /System ]; then
wget -q "$PKG_URL" -O /tmp/wazuh-agent.pkg &> /dev/null
logg info 'Setting Wazuh launch parameters in /tmp/wazuh_envs'
# https://documentation.wazuh.com/current/user-manual/agent/deployment-variables/deployment-variables-macos.html
echo "WAZUH_MANAGER="$WAZUH_MANAGER" && WAZUH_REGISTRATION_SERVER="$WAZUH_MANAGER" && WAZUH_REGISTRATION_PASSWORD="WazuhRegister" && WAZUH_AGENT_NAME="$WAZUH_AGENT_NAME"" > /tmp/wazuh_envs
echo "WAZUH_MANAGER="$(get-secret WAZUH_MANAGER)" && WAZUH_REGISTRATION_PASSWORD="$(get-secret WAZUH_REGISTRATION_PASSWORD)"" > /tmp/wazuh_envs
logg info 'Installing the Wazuh agent pkg'
sudo installer -pkg /tmp/wazuh-agent.pkg -target /
sudo chmod 755 /Library/Ossec

View file

@ -20,8 +20,7 @@
# * [VPN profile folder](https://github.com/megabyte-labs/install.doctor/blob/master/home/dot_config/vpn)
# * [VPN profile documentation](https://install.doctor/docs/customization/secrets#vpn-profiles)
# TODO - Populate Tunnelblick on macOS using the .ovpn profiles located in $HOME/.config/vpn (execpt in the `openvpn` entry of software.yml)
# along with the secrets for the protonVPN OpenVPN (check vpn-linux.tmpl)
set -euo pipefail
### Backs up previous network settings to `/Library/Preferences/com.apple.networkextension.plist.old` before applying new VPN profiles
logg info 'Backing up /Library/Preferences/com.apple.networkextension.plist to /Library/Preferences/com.apple.networkextension.plist.old'

File diff suppressed because it is too large Load diff