diff --git a/README.md b/README.md index c74cf62..ffa7aa4 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ # ansible + Getting real with system management via ansible-pull. Per-system configuration is handled via local files to the provisioned machine, @@ -10,59 +11,124 @@ accessed via the show-config and edit-config aliases. This setup is specific to the maintainer's devices and needs. You're welcome to use it as an example for your needs, but do not expect it to work as-is. -## Currently Supported Linux Systems +## Currently Supported Systems + +This information is as of 2025-11-21. + +### Primary + +These are the operating systems used as my daily driver. + +#### Debian Trixie + +This has been used as my primary server and workstation OS since at least 2024. +The `apt` version of `ansible` in both Bookworm and Trixie are sufficient, +no longer need to use `ansible` out of `pip`. + +### Secondary + +These are tested via my Docker project's `ProvisionsTests` container but not currently used as daily drivers. + +#### Arch + +TBD + +#### Fedora + +TBD + +#### OpenSUSE + +TBD + +#### Ubuntu + +TBD + +## Previusly Supported Systems + ### Debian Family + #### Debian + 100%, but only if using a recent enough version of Ansible. `pip` usually has a better version than `apt`. + #### Ubuntu + 100%, both server and desktop. + #### Pop!_OS + 100%, have not used for a while though. + #### Mint + 100%, but not really used, just tested once for fun. + #### Parrot Security OS (MATE) + 100% for a while, but OS did not serve maintainer's needs and 404 errors were terrible while updating. Ubuntu Rolling Rhino filled the gap. ### Arch Family + +#### Arch + +100% at some point, including installation and configuration of a Desktop Environment. + #### Manjaro + 100% at some point. ### Fedora Family + #### Fedora 35 -Workstation: 100% + +Workstation: 100%, Server: 100% ## Suse Family + ### openSUSE Tumbleweed v2022-02-17 -Generic: 100% + +Generic: 100%, Workstation: 100% ### openSUSE Leap 15.4 + Generic: 100% Workstation: Currently failing at `[Workstation | Linux | Flatpak Distro | Package Manager | Install From Repo]` with message `Problem: nothing provides libedataserver-1.2.so.24 needed by the to be installed evolution-data-server-32bit-3.34.4-3.3.1.x86_64`. ### NixOS + 99%, still need to get Telegraf going and refactor local.yml but everything else is working well. It is automatically implementing git.hyperling.com/me/env-nixos. -## Currently Supported Unix Systems ### FreeBSD 12, 13 + 100%, although GUI is not working completely on 13 yet (dash-to-dock doesn't compile). Software choices are slightly more limited since not `flatpak`-enabled and not feeling a `ports` setup. ## Waiting To Be Tested + ### Kali Linux + ### Arch Linux ARM + Specifically for the Pinephone. + ### Arch Linux x86 + Would be great to have Arch get built up by this. Used for many years but left after update problems due to a long computer hiatus. + ### Fedora Mobile + Specifically for the Pinephone. ## Future Goals + Eventually some of the scripts and install files will be put into the files folder. This will allow initializing systems outside of the maintainer's home network. @@ -74,6 +140,8 @@ benefit has yet to be seen for some tasks. Shared facts will definitely continue to exist under the facts tree. ## Other Notes + ### Get Setup Values + Use this command to see the variables for a system: `ansible localhost -m setup --connection=local`. diff --git a/facts/general/package.yml b/facts/general/package.yml index d65af26..f774ffa 100644 --- a/facts/general/package.yml +++ b/facts/general/package.yml @@ -2,7 +2,7 @@ # Define program names for package builtin. # This file is for ALL systems and should not include UI components. -- name: General | Facts | Packages | Shared Defaults +- name: General | Facts | Package | Shared Defaults set_fact: sshfs: sshfs tar: tar @@ -12,7 +12,7 @@ dig: dig neofetch: neofetch -- name: General | Facts | Packages | Parrot OS Fixes +- name: General | Facts | Package | Parrot OS Fixes set_fact: ansible_pkg_mgr: "apt" ansible_python_interpreter: "/usr/bin/python3" @@ -56,10 +56,15 @@ encfs: fusefs-encfs when: ansible_system == "FreeBSD" +- name: General | Facts | Package | dnf (Fixes) # TBD: Fix + test package names: mlocate, dig, neofetch + set_fact: + ansible_pkg_mgr: dnf + when: ansible_pkg_mgr in ("dnf5") + - name: General | Facts | Package | dnf set_fact: sshfs: fuse-sshfs - locate: mlocate + locate: plocate opensshd: openssh microcode_amd: microcode_ctl microcode_intel: microcode_ctl diff --git a/files/dwm/config.h b/files/dwm/config.h index c83cd5d..6d0ebf5 100644 --- a/files/dwm/config.h +++ b/files/dwm/config.h @@ -104,7 +104,11 @@ static Key keys[] = { { MODKEY|ShiftMask, XK_q, quit, {0} }, // Mine { MODKEY, XK_q, killclient, {0} }, -// Volume (https://varunbpatil.github.io/2013/09/28/dwm.html) + // extra search shortcut + { MODKEY, XK_s, spawn, {.v = dmenucmd } }, + // fullscreen shortcut for m onocle + { MODKEY, XK_f, setlayout, {.v = &layouts[2]} }, +// Volume (https://varunbpatil.github.io/2013/09/28/dwm.html) { 0, 0x1008ff12,spawn, {.v = mutecmd } }, { 0, 0x1008ff11,spawn, {.v = lowervolcmd } }, { 0, 0x1008ff13,spawn, {.v = raisevolcmd } }, diff --git a/files/dwm/dwm-status.function b/files/dwm/dwm-status.function new file mode 100755 index 0000000..7eeee70 --- /dev/null +++ b/files/dwm/dwm-status.function @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +# 2025-11-10 Hyperling +# Icons: https://fontawesome.com/v4/cheatsheet/ + +source "`which status.function`" + +function dwm-status { + status-display --dwm +} diff --git a/files/dwm/dwm.sh b/files/dwm/dwm.sh index 31e9669..352bf77 100644 --- a/files/dwm/dwm.sh +++ b/files/dwm/dwm.sh @@ -5,17 +5,17 @@ ## Load System Libs ## if [ -d /etc/X11/xinit/xinitrc.d ]; then - for f in /etc/X11/xinit/xinitrc.d/*; do - [ -x "$f" ] && . "$f" - done - unset f + for f in /etc/X11/xinit/xinitrc.d/*; do + [ -x "$f" ] && . "$f" + done + unset f fi if [ -d /usr/local/etc/X11/xinit/xinitrc.d ]; then - for f in /usr/local/etc/X11/xinit/xinitrc.d/*; do - [ -x "$f" ] && . "$f" - done - unset f + for f in /usr/local/etc/X11/xinit/xinitrc.d/*; do + [ -x "$f" ] && . "$f" + done + unset f fi @@ -34,10 +34,9 @@ xsetroot -solid "$purple" # slstatus, from Suckless # #exec slstatus & -# Custom # -while true; do - xsetroot -name "`whoami`@`hostname` `date +"%Y-%m-%d %H:%M:%S"`" -done & +# Custom Setup # +source "`which dwm-status.function`" +dwm-status & ## Start ## diff --git a/files/functions/battery.function b/files/functions/battery.function new file mode 100755 index 0000000..c74e298 --- /dev/null +++ b/files/functions/battery.function @@ -0,0 +1,22 @@ +#!/usr/bin/env bash +# 2025-11-10 Hyperling + +function battery-display { + detailed="N" + if [[ -n $1 ]]; then + detailed="Y" + fi + + if [[ "$detailed" == "Y" ]]; then + upower -i /org/freedesktop/UPower/devices/battery_BAT0 | grep percentage | grep -o "[0-9.%]*" + else + int="`upower -i /org/freedesktop/UPower/devices/battery_BAT0 | grep percentage | grep -o "[0-9]*" | head -n 1`" + echo "${int}%" + fi +} +alias show-battery="battery-display" +alias battery="battery-display" +alias battery-use="battery-display" +alias battery-usage="battery-display" +alias battery-level="battery-display" +alias battery-levels="battery-display" diff --git a/files/functions/cpu.function b/files/functions/cpu.function new file mode 100644 index 0000000..c333f30 --- /dev/null +++ b/files/functions/cpu.function @@ -0,0 +1,3 @@ +#/usr/local/bin env + +# TBD/TODO diff --git a/files/functions/memory.function b/files/functions/memory.function new file mode 100644 index 0000000..c333f30 --- /dev/null +++ b/files/functions/memory.function @@ -0,0 +1,3 @@ +#/usr/local/bin env + +# TBD/TODO diff --git a/files/functions/status.function b/files/functions/status.function new file mode 100755 index 0000000..27d90a6 --- /dev/null +++ b/files/functions/status.function @@ -0,0 +1,85 @@ +#!/usr/bin/env bash +# 2025-11-10 Hyperling +# Icons: https://fontawesome.com/v4/cheatsheet/ + +source "`which volume.function`" +source "`which battery.function`" +source "`which storage.function`" + +function datetime { + date +"%Y-%m-%d %H:%M:%S" +} +function status-display { + # Defaults + cmd="echo" + sleep=0.2 + if [[ "`storage-root`" == "`storage-home`" ]]; then + function status-display-storage { + echo "`storage-root`" + } + else + function status-display-storage { + echo "Root (`storage-root`), Home (`storage-home`)" + } + fi + + # Test Config + if [[ $1 == "-t" || $1 == "--test" || $1 == "test" ]]; then + sleep=5 + fi + + # DWM Config + if [[ $1 == "-d" || $1 == "--dwm" || $1 == "dwm" ]]; then + cmd="xsetroot -name" + if [[ "`storage-root`" == "`storage-home`" ]]; then + function status-display-storage { + echo "`storage-root-dwm`)" + } + else + function status-display-storage { + echo "(Root `storage-root-dwm`, Home `storage-home-dwm`)" + } + fi + fi + battery=""; storage=""; volume=""; datetime=""; + userhost="`whoami`@`hostname`" + while true; do + # Exit if parent process is gone. + #TBD/TODO + + # Reset Variables + if [[ $datetime == *"00" ]]; then + unset battery + unset storage + fi + if [[ $datetime != "`datetime`" ]]; then + unset volume + unset datetime + fi + + # Set Variables + if [[ -z $battery ]]; then + battery="`battery-display`" + fi + if [[ -z $storage ]]; then + storage="`status-display-storage`" + fi + if [[ -z $volume ]]; then + volume="`volume-display`" + fi + if [[ -z $datetime ]]; then + datetime="`datetime`" + fi + + # Display Variables + readout="$readout  $battery" + readout="$readout |  $storage" + readout="$readout |  $volume" + readout="$readout |  $userhost" + readout="$readout |  $datetime" + $cmd "$readout" + readout="" + sleep $sleep + done +} +alias status="status-display --test" diff --git a/files/functions/storage.function b/files/functions/storage.function new file mode 100755 index 0000000..62c8d72 --- /dev/null +++ b/files/functions/storage.function @@ -0,0 +1,38 @@ +#!/usr/bin/env bash +# 2025-11-10 Hyperling + +function storage-display { + location="$1" + style="$2" + + if [[ -z "$location" ]]; then + echo "ERROR: Location must be passed. $location" + fi + + if [[ "$style" == "%" || "$style" == "pct" || "$style" == "percent" ]]; then + df -h "$location" | tail -n 1 | awk '{print $5" Used"}' + elif [[ "$style" == "/" || "$style" == "use" || "$style" == "usage" ]]; then + df -h "$location" | tail -n 1 | awk '{print $4"/"$2" Free"}' + elif [[ "$style" == "G" || "$style" == "S" || "$style" == "F" ]]; then + df -h "$location" | tail -n 1 | awk '{print $4" Free"}' + else + df -h "$location" | tail -n 1 | awk '{print $5" Used - "$4"/"$2" Free"}' + fi +} +alias storage='echo -n "Root: " && storage-display "/" "F" && echo -n "Home: " && storage-display "/home" "F"' + +export dwm_storage_style="F" + +function storage-root { + storage-display / "$1" +} +function storage-root-dwm { + storage-root "$dwm_storage_style" +} + +function storage-home { + storage-display /home "$1" +} +function storage-home-dwm { + storage-home "$dwm_storage_style" +} diff --git a/files/functions/swap.function b/files/functions/swap.function new file mode 100644 index 0000000..c333f30 --- /dev/null +++ b/files/functions/swap.function @@ -0,0 +1,3 @@ +#/usr/local/bin env + +# TBD/TODO diff --git a/files/functions/volume.function b/files/functions/volume.function new file mode 100755 index 0000000..6807ff0 --- /dev/null +++ b/files/functions/volume.function @@ -0,0 +1,173 @@ +#!/usr/bin/env bash +# 2025-11-10 Hyperling +# Volume management for systems without working volume buttons. +# Written for ease of use in terminal and simple window management systems. + +function volume-usage { + cat <<- EOF + Usage: volume [%int] [(+/-)%int] [-d] [-r] [-t] [-h] + + Set to a static value: + volume 100, volume 65 + + Increment or decrement. Passing only + or - and no number defaults to 5. + volume -5, volume 5-, volume - 5, volume 5 - + volume +20, volume 20+, volume + 20, volume 20 + + + Display the current volume: + volume, + volume-display, volume display, volume --display, volume -d, + volume +d + + Set volume to a random number between 0 and 100. + volume-random, volume random, volume --random, volume -r + + Be silly and oscillate volume in a loop: + volume-trip, volume trip, volume --trip, volume -t + + Display this help text: + volume-usage, + volume-help volume help, volume --help, volume -h + EOF + return $1 +} +alias volume-help="volume-usage" +alias vol-h="volume-help" + +function volume { + + ## Check Params ## + + if [[ "$1" == "--help" || "$1" == "help" || "$1" == "-h" ]]; then + volume-usage 1 + return 1 + fi + if [[ (-z "$1" && -z "$2") + || "$1" == "--display" || "$1" == "display" || "$1" == "-d" || "$1" == "+d" + ]]; then + volume-display + return 0 + fi + + ## Parse Params ## + + dir="" + amt="" + + # Remove percent signs. + if [[ "$1" == *"%"* || "$2" == *"%"* ]]; then + set -- "${1//%/}" "${2//%/}" + fi + + # Check if format is written text. + if [[ "$1" == "full" || "$1" == "max" ]]; then + amt=100 + fi + if [[ "$1" == "mute" || "$1" == "none" ]]; then + amt=0 + fi + + # Check if the format is "volume +/- %int" + if [[ -z "$amt" && -z "$dir" ]]; then + if [[ "$1" == "+" || "$1" == "-" ]]; then + dir="$1" + amt="$2" + if [[ -z "$2" ]]; then + amt="5" + else + amt="$2" + fi + fi + fi + + # Check if the format is "volume +/- %int". + if [[ -z "$amt" && -z "$dir" ]]; then + if [[ "$2" == "+" || "$2" == "-" ]]; then + amt="$1" + dir="$2" + fi + fi + + # Check if amount and direction are adjacent, and if so, pull the values. + if [[ -z "$amt" && -z "$dir" ]]; then + if [[ "$1" == *"+"* ]]; then + dir="+" + elif [[ "$1" == *"-"* ]]; then + dir="-" + fi + if [[ -n "$dir" && -z "$amt" ]]; then + amt="$1" + amt=${amt//-/} + amt=${amt//+/} + fi + fi + + # Check if format is direct volume. + if [[ -z "$dir" && -z "$amt" && -n "$1" && -z "$2" ]]; then + amt="$1" + fi + + ## Error Checking ## + regex='^[0-9]+$' + if ! [[ $amt =~ $regex ]]; then + echo "> ERROR: Amount '$amt' does not seem like a integer." + volume-usage 2 + return 2 + fi + + ## Main ## + + if [[ -n "$dir" && -n "$amt" ]]; then + echo "> Changing volume by '$dir$amt%'." + amixer -q sset Master ${amt}%${dir} + echo "> Volume is now '`volume-display`'." + return 0 + fi + + if [[ -z "$dir" && -n "$1" ]]; then + echo "> Setting volume to '$amt'." + amixer -q sset Master ${amt}% + echo "> Volume has been set to '`volume-display`'." + return 0 + fi + + echo "> ERROR: Should not have made it here. Please report this to the developer." + echo "$0 $1 $2" + return 7 +} +alias vol="volume " +alias vol-="volume - " +alias vol+="volume + " + +function volume-display { + if [[ "$1" == "-v" || "$1" == "--verbose" || "$1" == "verbose" ]]; then + amixer sget Master + else + amixer sget Master | egrep -o '[0-9]{1,3}%' | head -n 1 + fi +} +alias "vol-d"="volume-display" + +## TBD/TODO ## + +# Go up and down until cancelled. +#function volume-trip { +# curr eq amixer current readout +# if curr lt 50 then dir eq + else dir eq - +# while true; do +# if vol is 0 then dir eq + +# if vol is 100 then dir eq - +# curr eq \$curr $dir 1 +# amixer set volume to curr +# sleep 0.1 +# done +#} +#alias vol-t="volume-trip" +#alias volume-wub="volume-trip" +#alias vol-w="volume-wub" + +#function volume-random { +# v eq $RANDOM % 101 +# amixer set volume eq v +#} +#alias vol-r="volume-random" diff --git a/files/functions/vpn.function b/files/functions/vpn.function new file mode 100644 index 0000000..c333f30 --- /dev/null +++ b/files/functions/vpn.function @@ -0,0 +1,3 @@ +#/usr/local/bin env + +# TBD/TODO diff --git a/files/functions/wifi.function b/files/functions/wifi.function new file mode 100644 index 0000000..c333f30 --- /dev/null +++ b/files/functions/wifi.function @@ -0,0 +1,3 @@ +#/usr/local/bin env + +# TBD/TODO diff --git a/files/scripts/backup_system.sh b/files/scripts/backup_system.sh index 7992337..4b0f85e 100755 --- a/files/scripts/backup_system.sh +++ b/files/scripts/backup_system.sh @@ -39,7 +39,7 @@ echo "*** Creating backup at '$BACKUP' ***" sudo zip -rv "$BACKUP" \ /etc /var/{log,mail,spool} /srv /boot \ /usr/local/etc $EXTRA \ - -x "/srv/backup/*" + -x "/srv/backup/*" -x "/srv/sftp/*" status="$?" if [[ "$status" != 0 ]]; then @@ -48,7 +48,7 @@ fi if [[ -e "$BACKUP" ]]; then ls -alh "$BACKUP" - echo "*** '$BACKUP' created successfully! ***"s + echo "*** '$BACKUP' created successfully! ***" else echo "*** '$BACKUP' not found! ***" exit 1 diff --git a/files/scripts/compress_image.sh b/files/scripts/compress_image.sh index 7b48afb..e86f313 100755 --- a/files/scripts/compress_image.sh +++ b/files/scripts/compress_image.sh @@ -28,7 +28,7 @@ function usage() { # Parameters: # 1) The exit status to use. status=$1 - echo "Usage: $PROG [-s SIZE] [-l LOCATION] [-A | [-r] [-f] [-d] [-c]] [-h] [-x]" >&2 + echo "Usage: $PROG [-s SIZE] [-l LOCATION] [-A | [-r] [-f] [-d] [-c]] [-h] [-x] [-t]" >&2 cat <<- EOF Compress JPG or PNG image(s). Can handle folders and work recursively. @@ -45,13 +45,14 @@ function usage() { -A : Resursively Force, Delete, and Clean. -h : Display this usage text. -x : Enable BASH debugging. + -t : Format timestamp. EOF exit $status } ## Parameters ## -while getopts ":s:l:rfFdcAhx" opt; do +while getopts ":s:l:rfFdcAhxt" opt; do case $opt in s) in_size="$OPTARG" && size="$in_size" ;; l) location="$OPTARG" ;; @@ -64,6 +65,7 @@ while getopts ":s:l:rfFdcAhx" opt; do A) recurse="Y" && search="find" && force="Y" && delete="Y" && expand="Y" ;; h) usage 0 ;; x) set -x ;; + t) format_time="Y" ;; *) echo "ERROR: Option $OPTARG not recognized." >&2 && usage 1 ;; esac done @@ -130,7 +132,9 @@ $search "$location" | sort | while read image; do # Date Data new_image_exp="${TEMP:0:4}-${TEMP:4:2}-${TEMP:6:2}" # Time Data - new_image_exp="${new_image_exp}_${TEMP:8:2}-${TEMP:10:2}-${TEMP:12:2}" + if [[ "$format_time" == "Y" ]]; then + new_image_exp="${new_image_exp}_${TEMP:8:2}-${TEMP:10:2}-${TEMP:12:2}" + fi # Remainder Data if [[ "${TEMP:14:1}" == "." ]]; then SEP="" diff --git a/setup.sh b/setup.sh index e10f8c1..4daef13 100755 --- a/setup.sh +++ b/setup.sh @@ -9,13 +9,18 @@ LOCAL=$DIR/local.yml URL="https://git.hyperling.com/me/env-ansible" BRANCH="main" +config_dir="/usr/local/etc/hyperling-scm" +general_config="$config_dir/general.ini" +workstation_config="$config_dir/workstation.ini" +server_config="$config_dir/server.ini" + ## Functions ## # Accepts 1 parameter, it is used as the exit status. function usage { cat <<- EOF - $PROG [-l] [-b branch_name] [-h] + $PROG [-l] [-b branch_name] [-g] [-w] [-s] [-f] [-h] Program to initialize synchronization with Hyperling's Ansible configuration. $URL @@ -23,8 +28,12 @@ function usage { -l : Run the local playbook associated with this $PROG. This is helpful for development or just saving bandwidth. It also provides prettier colors than the plaintext from ansible-pull. ;) - -b branch_name: Download and run a specific branch. Default is $BRANCH. - -h : Display this help text + -b branch_name : Download and run a specific branch. Default is $BRANCH. + -g : Enable the General config with test contents. + -w : Enable the Workstation config with test contents. + -s : Enable the Server config with test contents. + -f : Display this system's facts. + -h : Display this help text. EOF exit $1 @@ -32,10 +41,14 @@ function usage { ## Parameter Parsing ## -while getopts ":lb:h" arg; do +while getopts ":lb:gwsfh" arg; do case $arg in l) local="Y" && echo "Running $LOCAL as the playbook." ;; b) branch="$OPTARG" && echo "Using branch $branch instead of $BRANCH." ;; + g) create_general="Y" && echo "Requested '$general_config'." ;; + w) create_workstation="Y" && echo "Requested '$workstation_config'." ;; + s) create_server="Y" && echo "Requested '$server_config'." ;; + f) show_facts="Y" ;; h) usage ;; *) echo "ERROR: Parameter $OPTARG was not recognized." && usage 1 ;; esac @@ -47,15 +60,32 @@ if [[ ! -z $1 && $1 != "-"* ]]; then usage 1 fi -if [[ $branch == "" ]]; then +if [[ -z "$local" && "$branch" == "" ]]; then echo "Using default branch $BRANCH." branch="$BRANCH" fi +if [[ -n "$create_general" && -f "$general_config" ]]; then + echo "WARNING: General configuration already exists, will not overwrite." + ls -lh "$general" +fi +if [[ -n "$create_workstation" && -f "$workstation_config" ]]; then + echo "WARNING: Workstation configuration already exists, will not overwrite." + ls -lh "$workstation_config" +fi +if [[ -n "$create_server" && -f "$server_config" ]]; then + echo "WARNING: Server configuration already exists, will not overwrite." + ls -lh "$server_config" +fi + ## Main ## os="$(cat /etc/os-release)" -os="$os $(uname -a)" +if [[ ! -f /.dockerenv ]]; then + # If we are not in a Docker container, also check what the kernel says. + os="$os $(uname -a)" + # Docker containers use the host kernel which gives an incorrect reading. +fi echo "Making sure all necessary packages are installed..." if [[ `which ansible > /dev/null; echo $?` != 0 ]]; then @@ -97,10 +127,71 @@ if [[ `which ansible > /dev/null; echo $?` != 0 ]]; then fi echo "Installed!" +if [[ "$show_facts" == "Y" ]]; then + echo "Showing Ansible Facts" + ansible localhost -m setup --connection=local +fi + #echo "Adding Ansible Collections..." #ansible-galaxy collection install community.general #echo "Added!" +# Create basic layouts if configs do not exist and are requested. + +if [[ -n "$create_general" + || -n "$create_workstation" + || -n "$create_server" ]] +then + sudo mkdir -pv "$config_dir" + MARK1="BEGIN" + MARK2="END" +fi +if [[ -n "$create_general" && ! -f "$general_config" ]]; then + function print_general_contents { + cat <<- EOF + ; $MARK1 MANAGED BY ANSIBLE | Generic Config + ; $MARK2 MANAGED BY ANSIBLE | Generic Config + ; TEST DATA + enable=true + user=test + user_desc=Test + branch=$branch + ; TEST DATA + EOF + } + print_general_contents | sudo tee "$general_config" + ls -lh "$general_config" +fi +if [[ -n "$create_workstation" && ! -f "$workstation_config" ]]; then + function print_workstation_contents { + cat <<- EOF + ; $MARK1 MANAGED BY ANSIBLE | Workstation Config + ; $MARK2 MANAGED BY ANSIBLE | Workstation Config + ; TEST DATA + enable=true + coding=true + editing=false + gaming=false + ; TEST DATA + EOF + } + print_workstation_contents | sudo tee "$workstation_config" + ls -lh "$workstation_config" +fi +if [[ -n "$create_server" && ! -f "$server_config" ]]; then + function print_server_contents { + cat <<- EOF + ; $MARK1 MANAGED BY ANSIBLE | Server Config + ; $MARK2 MANAGED BY ANSIBLE | Server Config + ; TEST DATA + enable=true + ; TEST DATA + EOF + } + print_server_contents | sudo tee "$server_config" + ls -lh "$server_config" +fi + echo "Provisioning Ansible..." if [[ $local == "Y" ]]; then sudo ansible-playbook $LOCAL diff --git a/tasks/general/acct_mgmt/provision_config.yml b/tasks/general/acct_mgmt/provision_config.yml index 18fc457..8fbd5c7 100644 --- a/tasks/general/acct_mgmt/provision_config.yml +++ b/tasks/general/acct_mgmt/provision_config.yml @@ -26,7 +26,7 @@ blockinfile: path: "{{ gen_file }}" block: | - ; Please note that all potions require lowercase keys and values. + ; Please note that all portions require lowercase keys and values. ; ;;;;;;;;;;;;;;;;;;;; Basic Options ;;;;;;;;;;;;;;;;;;;; ; diff --git a/tasks/general/acct_mgmt/users.yml b/tasks/general/acct_mgmt/users.yml index 069f502..46d9a5b 100644 --- a/tasks/general/acct_mgmt/users.yml +++ b/tasks/general/acct_mgmt/users.yml @@ -453,8 +453,8 @@ return 0 fi - docker compose down && docker compose build && + docker compose down && docker compose up -d if [[ -n "$1" ]]; then @@ -475,9 +475,9 @@ return 0 fi - docker compose down && docker compose pull && docker compose build && + docker compose down && docker compose up -d if [[ -n "$1" ]]; then @@ -519,12 +519,12 @@ docker ps return; fi - echo "*** Going Down ***" && - docker compose down && echo "*** Upgrading Images ***" && docker compose pull && echo "*** Building Containers ***" && docker compose build && + echo "*** Going Down ***" && + docker compose down && echo "*** Starting Daemons ***" && docker compose up -d && echo "*** Following Log ***" && @@ -554,6 +554,10 @@ return 0 } + alias_docker_other: | + alias docker-stop="docker compose down" + alias docker-start="docker compose up -d && docker compose start" + alias docker-prep="docker compose pull && docker compose build" alias_code_check: | alias code-check=' echo "Checking ~/Code directory for git changes." @@ -564,6 +568,16 @@ echo -e "\n*** `basename $project` ***" cd $project if [[ -d .git ]]; then + git ls-remote --exit-code --heads origin dev + dev_exists="$?" + if [[ "$dev_exists" == 0 ]]; then + git switch dev + elif [[ "$dev_exists" == 2 ]]; then + git switch main + else + echo "ERROR: Unknown status for dev_exists, '$dev_exists'." + continue + fi git pull git push else @@ -783,16 +797,70 @@ date "+%Y%m%d" } function_backup: | + export BACKUP_DIR="/srv/backup" function backup { /usr/local/bin/backup_system.sh } alias backup-system="backup" alias system-backup="backup" - alias check-backups="ll /srv/backup" + alias check-backups="ll $BACKUP_DIR" function clean-backup { - sh -c "rm -rfv /srv/backup/*" + sh -c "rm -rfv $BACKUP_DIR/*" } alias clean-backups="clean-backup" + function_pull_prod_backups: | + export DOCKER="Docker" + export SYSTEM="System" + function pull_prod_backup { + if [[ -z "$1" || ("$1" != "$DOCKER" && "$1" != "$SYSTEM") ]]; then + echo "ERROR: Parameter 1 not correct, expecting '$DOCKER' or '$SYSTEM'." + return 1 + fi + backup_type="$1" + echo "Looking for '*${backup_type}*.zip'" + ls -lh *${backup_type}*.zip 2>/dev/null + status="$?" + if [[ "$status" == "0" ]]; then + echo "File already downloaded, skipping." + return 0 + else + echo "File still needed, downloading to local tmp/." + fi + mkdir -pv tmp + scp -P {{ prod_port }} \ + {{ prod_user }}@{{ prod_host }}:"$BACKUP_DIR/*${backup_type}*.zip" \ + tmp/ + if [[ "$?" == "0" ]]; then + echo "Succeeded!" + mv -v tmp/*.zip ./ + rmdir -v tmp + else + echo "Failed!" + mv tmp ~/TRASH/"tmp_`now`" + fi + } + function pull_prod_backups { + dir="ProductionBackups-Pulled`today`" + mkdir -pv "$dir" + cd "$dir" + pull_prod_backup "$DOCKER" + pull_prod_backup "$SYSTEM" + du -h *.zip | sort -h + status="$?" + cd .. + if [[ "$status" != 0 ]]; then + echo "Failed to find zip files, removing folder." + rmdir -v "$dir" + return 1 + fi + echo "Done!" + } + alias pull-prod-backups="pull_prod_backups" + alias pull-backups="pull_prod_backups" + alias prod-backups="pull_prod_backups" + alias prod-backup="pull_prod_backups" + alias pull-prod="pull_prod_backups" + alias prod-pull="pull_prod_backups" function_log: | function log { echo -e "$1" @@ -881,6 +949,120 @@ alias_sudo: | # Allows for alias expansions when using sudo, such as doing "sudo ll". alias sudo="sudo " + function_load_branch: | + # Change a branch to point at another. + function load-branch { + rcvr="$1" # branch which we want to modify + base="$2" # branch with the changes we want + + if [[ "$rcvr" == "main" ]]; then + echo "*** ERROR: Are you nuts, fool!? Not main! Do it manually! ***" + return 1 + fi + + if [[ -z "$base" ]]; then + if [[ "$rcvr" == "prod" ]]; then + base="stage" + elif [[ "$rcvr" == "stage" ]]; then + base="dev" + else + echo "* Unsure which branch to use for '$rcvr'. Please specify." + return 1 + fi + echo "* Base was not specified, using '$base' for '$rcvr'." + else + echo "* Requested pointing '$rcvr' branch to '$base'." + fi + + echo -e "\n* Ensuring we are on base branch '$base'." && + git switch "$base" && + echo -e "\n* Changing pointer for '$rcvr' to '$base'." && + git branch -f "$rcvr" "$base" && + #echo -e "\n* Switching to branch '$rcvr'." && + #git switch "$rcvr" && + echo -e "\n* Forcing push on branch '$rcvr'." && + git push --force --set-upstream origin "$rcvr" && + echo -e "\n* Done! Displaying list of remote branches." && + git ls-remote --heads | sort + + if [[ "$base" != "dev" ]]; then + echo -e "\n* Checking if a dev branch exists." + git ls-remote --exit-code --heads origin dev + dev_exists="$?" + if [[ "$dev_exists" == 0 ]]; then + echo -e "\n* Switching back to dev." + git switch dev + elif [[ "$dev_exists" == 2 ]]; then + echo -e "\n* Switching back to main." + git switch main + else + echo "*** ERROR: Unknown status for dev_exists, '$dev_exists'. ***" + fi + fi + + echo -e "\n* Verifying which branch we're on." + git branch + } + alias load-prod="load-branch prod" + alias load-stage="load-branch stage" + alias rollback-prod="load-branch prod main" + alias rollback-stage="load-branch stage prod" + alias rollback-dev="load-branch dev stage" + alias reset-prod="load-branch prod main" + alias reset-stage="load-branch stage main" + alias reset-dev="load-branch dev main" + function check-code-branches { + for dir in ~/Code/*/; do + cd $dir + pwd + git ls-remote --heads + echo " " + cd .. + done + } + alias check-branches="check-code-branches" + alias check-branch="git ls-remote --heads" + alias branch-check="check-branch" + alias_reload_bash: | + alias reload-bash="source ~/.bashrc" + alias bash-reload="reload-bash" + alias shell-reload="reload-bash" + alias reload-shell="reload-bash" + alias reload="reload-bash" + alias_hugo_server: | + alias hugo-server-dev="hugo server -D --gc" # --ignoreCache --noHTTPCache --disableFastRender" + alias hugo-server-stage="hugo server --gc" # --noHTTPCache --disableFastRender" + alias hugo-server-prod="hugo server --gc --minify" + alias hugo-server="hugo-server-dev" + global_functions: | + for global_function in "{{ global_bin }}/"*".function"; do + if [[ -f "$global_function" ]]; then + . "$global_function" + fi + done + alias_flatpak_clean: | + alias flatpak-clean="flatpak uninstall --unused" + alias_commit: | + function commit_usage { + echo 'Usage: commit "This is a commit message"' + } + function commit { + if [[ -z "$1" ]]; then + echo "ERROR: Message must be provided." + commit_usage + return 1 + fi + if [[ "$1" == "-h"* || "$1" == "--h"* ]]; then + commit_usage + fi + message="$1" + git add . && + git commit -m "$message" && + git push + + status="$?" + return "$status" + } - name: General | Account Management | Users | Files | Common Variable set_fact: @@ -952,10 +1134,18 @@ {{ alias_ansible_facts }} {{ function_now }} {{ function_backup }} + {{ function_pull_prod_backups }} {{ function_log }} {{ function_debian_upgrade }} {{ function_ebook_convert }} {{ alias_sudo }} + {{ function_load_branch }} + {{ alias_reload_bash }} + {{ alias_hugo_server }} + {{ global_functions }} + {{ alias_docker_other }} + {{ alias_flatpak_clean }} + {{ alias_commit }} - name: General | Account Management | Users | Files | .bashrc blockinfile: @@ -1025,3 +1215,17 @@ - .bashrc - .zshrc - .vimrc + + +- name: General | Account Management | Users | Files | Helper Functions (Reset) + shell: "rm -v {{ global_bin }}/*.function" + +- name: General | Account Management | Users | Files | Helper Functions + copy: + src: "{{ item }}" + dest: "{{ global_bin }}" + owner: root + group: "{{ root_group }}" + mode: 0755 + with_fileglob: + - "functions/*.function" diff --git a/tasks/general/cron/ansible.yml b/tasks/general/cron/ansible.yml index f68cb45..df6eafa 100644 --- a/tasks/general/cron/ansible.yml +++ b/tasks/general/cron/ansible.yml @@ -12,7 +12,7 @@ user: ansible name: "Ansible Sync" minute: "*/30" - job: "sleep $(( $RANDOM / 20 )); sudo {{ ansible_pull_exec.stdout }} -v -o -U {{ git_repo_http }} --checkout {{ branch }}" + job: "bash -c 'sleep $(( $RANDOM / 20 )); sudo {{ ansible_pull_exec.stdout }} -v -o -U {{ git_repo_http }} --checkout {{ branch }}'" state: present disabled: "{{ 'yes' if no_telem else 'no' }}" @@ -21,6 +21,6 @@ user: ansible name: "Ansible Weekly Forced Sync" special_time: daily - job: "sleep $(( $RANDOM / 1 )); sudo {{ ansible_pull_exec.stdout }} -v -U {{ git_repo_http }} --checkout {{ branch }}" + job: "bash -c 'sleep $(( $RANDOM / 1 )); sudo {{ ansible_pull_exec.stdout }} -v -U {{ git_repo_http }} --checkout {{ branch }}'" state: present disabled: "{{ 'yes' if no_telem else 'no' }}" diff --git a/tasks/general/software/packages.yml b/tasks/general/software/packages.yml index 5f0d05f..c1975d5 100644 --- a/tasks/general/software/packages.yml +++ b/tasks/general/software/packages.yml @@ -82,6 +82,15 @@ when: ansible_distribution == "Ubuntu" ignore_errors: yes +- name: General | Software | Packages | Add Generic Kernel + Headers (Debian) + package: + name: + - linux-image-amd64 + - linux-headers-amd64 + state: present + when: ansible_distribution == "Debian" + ignore_errors: yes + - name: General | Software | Services | Install killall (Looking at you, Debian) package: name: psmisc diff --git a/tasks/workstation/linux/software/flatpaks.yml b/tasks/workstation/linux/software/flatpaks.yml index 9e986e0..b9f7a57 100644 --- a/tasks/workstation/linux/software/flatpaks.yml +++ b/tasks/workstation/linux/software/flatpaks.yml @@ -36,13 +36,14 @@ flatpaks_generic: - { app: "org.mozilla.firefox", name: "firefox-flatpak", extra: "" } - { app: "io.gitlab.librewolf-community", name: "librewolf", extra: "" } - - { app: "chat.simplex.simplex", name: "simplex", extra: "" } - { app: "org.signal.Signal", name: "signal", extra: "" } - { app: "im.riot.Riot", name: "element", extra: "" } - { app: "org.telegram.desktop", name: "telegram", extra: "" } - { app: "org.gimp.GIMP", name: "gimp", extra: "" } - { app: "org.libreoffice.LibreOffice", name: "office", extra: "" } - { app: "com.transmissionbt.Transmission", name: "transmission", extra: "" } + - { app: "app.grayjay.Grayjay", name: "grayjay", extra: "" } + - { app: "com.github.xournalpp.xournalpp", name: "xournal", extra: "" } flatpaks_coding: - { app: "com.vscodium.codium", name: "codium-flatpak", extra: "" } - { app: "com.google.AndroidStudio", name: "android-studio", extra: "" } @@ -71,11 +72,12 @@ # 2022-11-20 No longer using any of these and they're taking up a lot of space. # - { app: "com.jetbrains.PyCharm-Community", name: "pycharm", extra: "" } # End 2022-11-20 # - - { app: "io.lbry.lbry-app", name: "lbry", extra: "dbus-launch" } # No longer supported, noticed 2023-09-01. - - { app: "chat.delta.desktop", name: "deltachat", extra: "" } # No longer used, removed 2023-12-18. - - { app: "org.gnome.Geary", name: "geary", extra: "" } # No longer used, removed 2024-12-15 + - { app: "io.lbry.lbry-app", name: "lbry", extra: "dbus-launch" } # 2023-09-01, Noticed it is no longer supported. + - { app: "chat.delta.desktop", name: "deltachat", extra: "" } # 2023-12-18, No longer used. + - { app: "org.gnome.Geary", name: "geary", extra: "" } # 2024-12-15, No longer used. - { app: "org.rncbc.qsynth", name: "qsynth", extra: "" } # 2024-12-15, Not worth the setup, use LMMS or VMPK. - - { app: "org.godotengine.Godot", name: "godot", extra: "" } # 20250831 Stopped playing with this months / years ago. + - { app: "org.godotengine.Godot", name: "godot", extra: "" } # 2025-08-31, Stopped playing with this months / years ago. Seemed cool but Flutter is working well for this purpose. + - { app: "chat.simplex.simplex", name: "simplex", extra: "" } # 2025-11-22, Takes a ton of space and does not work without interacting with phone. # Generic # diff --git a/tasks/workstation/shared/settings/gnome.yml b/tasks/workstation/shared/settings/gnome.yml index 9d28198..f67ec0b 100644 --- a/tasks/workstation/shared/settings/gnome.yml +++ b/tasks/workstation/shared/settings/gnome.yml @@ -12,16 +12,18 @@ , 'org.gnome.Nautilus.desktop' , 'io.gitlab.librewolf-community.desktop', 'librewolf.desktop' , 'org.mozilla.firefox.desktop', 'firefox.desktop' - , 'org.signal.Signal.desktop', 'signal-desktop.desktop' - , 'org.telegram.desktop.desktop' - , 'com.discordapp.Discord.desktop' , 'com.vscodium.codium.desktop' , 'codium.desktop' , 'org.shotcut.Shotcut.desktop' , 'io.lmms.LMMS.desktop' + , 'app.grayjay.Grayjay.desktop' , 'io.lbry.lbry-app.desktop', 'lbry.desktop' , 'com.valvesoftware.Steam.desktop' , 'net.lutris.Lutris.desktop' + , 'mullvad-vpn.desktop' + , 'org.signal.Signal.desktop', 'signal-desktop.desktop' + , 'org.telegram.desktop.desktop' + , 'com.discordapp.Discord.desktop' ]" dconf_terminal: gnome-terminal dconf_theme: Adwaita-dark @@ -272,6 +274,13 @@ dconf write /org/gnome/desktop/media-handling/autorun-never true && inc_dconf && + ## Gnome Terminal ## + + # TBD: Do not start new tabs in previous tab's directory. + # The profile ID is likely unique and will need to be retrieved first. + #/org/gnome/terminal/legacy/profiles:/:b1dcc9dd-5262-4d8d-a863-c897e6d979b9/preserve-working-directory + #'never' + ## Success ## sleep 0 || diff --git a/tasks/workstation/shared/software/dwm.yml b/tasks/workstation/shared/software/dwm.yml index c9e2c96..1e5d77d 100644 --- a/tasks/workstation/shared/software/dwm.yml +++ b/tasks/workstation/shared/software/dwm.yml @@ -3,7 +3,7 @@ # https://dwm.suckless.org/ # https://sites.google.com/site/lazyboxx/-articles/dwm-a-newbie-s-guide#TOC-Status-Bar -#TODO: Move this to tasks/shared/ pasth rather than tasks/linux/. +#TODO: Move this to tasks/shared/ path rather than tasks/linux/. #TODO: Generate files based on blockinfile. #TODO: Fix config.mk for FreeBSD automatically (use /usr/local/ for libs not /usr/X11RC/) #TODO: scm.sh to use bash variable so that FreeBSD correctly hits /usr/local/bin/bash. @@ -23,14 +23,14 @@ ## Download ## - name: Workstation | Linux | Software | DWM | Git Clone - git: + git: repo: https://git.suckless.org/dwm dest: "{{ dwm_install_dir }}" clone: yes force: yes - name: Workstation | Linux | Software | DWM | Git Clone (st) - git: + git: repo: https://git.suckless.org/st dest: "{{ st_install_dir }}" clone: yes @@ -78,3 +78,16 @@ owner: root group: "{{ root_group }}" mode: 0644 + + +## Status Bar ## + +- name: Workstation | Linux | Software | DWM | Status Bar Function + copy: + src: "{{ item }}" + dest: "{{ global_bin }}" + owner: root + group: "{{ root_group }}" + mode: 0755 + with_fileglob: + - "dwm/*.function"