dev: automated commit - 2025-06-08 23:28:55
This commit is contained in:
parent
33106ea4a6
commit
0ab9f62ace
13 changed files with 1255 additions and 715 deletions
252
common.sh
Normal file
252
common.sh
Normal file
|
@ -0,0 +1,252 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# Script Standards and Common Functions
|
||||||
|
# Source this file in your scripts for consistent behavior
|
||||||
|
|
||||||
|
# ==============================================================================
|
||||||
|
# STANDARD SCRIPT HEADER
|
||||||
|
# ==============================================================================
|
||||||
|
# All scripts should start with:
|
||||||
|
# #!/usr/bin/env bash
|
||||||
|
# # NAME: Brief description of what the script does
|
||||||
|
# # REQUIRES: sudo interactive (if needed)
|
||||||
|
#
|
||||||
|
# set -euo pipefail
|
||||||
|
#
|
||||||
|
# # Source common functions (adjust path as needed)
|
||||||
|
# source "$(dirname "$0")/common.sh" 2>/dev/null || true
|
||||||
|
|
||||||
|
# ==============================================================================
|
||||||
|
# CONFIGURATION
|
||||||
|
# ==============================================================================
|
||||||
|
readonly SCRIPT_NAME="${0##*/}"
|
||||||
|
readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
|
||||||
|
# Colors for output (only if terminal supports it)
|
||||||
|
if [[ -t 1 ]] && command -v tput >/dev/null 2>&1; then
|
||||||
|
readonly RED=$(tput setaf 1)
|
||||||
|
readonly GREEN=$(tput setaf 2)
|
||||||
|
readonly YELLOW=$(tput setaf 3)
|
||||||
|
readonly BLUE=$(tput setaf 4)
|
||||||
|
readonly PURPLE=$(tput setaf 5)
|
||||||
|
readonly CYAN=$(tput setaf 6)
|
||||||
|
readonly WHITE=$(tput setaf 7)
|
||||||
|
readonly BOLD=$(tput bold)
|
||||||
|
readonly RESET=$(tput sgr0)
|
||||||
|
else
|
||||||
|
readonly RED="" GREEN="" YELLOW="" BLUE="" PURPLE="" CYAN="" WHITE="" BOLD="" RESET=""
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ==============================================================================
|
||||||
|
# LOGGING FUNCTIONS
|
||||||
|
# ==============================================================================
|
||||||
|
log_info() {
|
||||||
|
printf "${GREEN}[INFO]${RESET} %s\n" "$*"
|
||||||
|
}
|
||||||
|
|
||||||
|
log_warn() {
|
||||||
|
printf "${YELLOW}[WARN]${RESET} %s\n" "$*" >&2
|
||||||
|
}
|
||||||
|
|
||||||
|
log_error() {
|
||||||
|
printf "${RED}[ERROR]${RESET} %s\n" "$*" >&2
|
||||||
|
}
|
||||||
|
|
||||||
|
log_success() {
|
||||||
|
printf "${GREEN}[SUCCESS]${RESET} %s\n" "$*"
|
||||||
|
}
|
||||||
|
|
||||||
|
log_debug() {
|
||||||
|
if [[ "${DEBUG:-0}" == "1" ]]; then
|
||||||
|
printf "${CYAN}[DEBUG]${RESET} %s\n" "$*" >&2
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
log_sudo() {
|
||||||
|
printf "${PURPLE}[SUDO]${RESET} %s\n" "$*"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ==============================================================================
|
||||||
|
# UTILITY FUNCTIONS
|
||||||
|
# ==============================================================================
|
||||||
|
command_exists() {
|
||||||
|
command -v "$1" >/dev/null 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
is_root() {
|
||||||
|
[[ $EUID -eq 0 ]]
|
||||||
|
}
|
||||||
|
|
||||||
|
require_root() {
|
||||||
|
if ! is_root; then
|
||||||
|
log_error "This script requires root privileges"
|
||||||
|
log_info "Run with: sudo $0 $*"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check if running in interactive terminal
|
||||||
|
is_interactive() {
|
||||||
|
[[ -t 0 && -t 1 ]]
|
||||||
|
}
|
||||||
|
|
||||||
|
# ==============================================================================
|
||||||
|
# CONFIRMATION FUNCTIONS
|
||||||
|
# ==============================================================================
|
||||||
|
confirm() {
|
||||||
|
local prompt="${1:-Continue?}"
|
||||||
|
local default="${2:-n}"
|
||||||
|
local response
|
||||||
|
|
||||||
|
if ! is_interactive; then
|
||||||
|
log_warn "Non-interactive mode, using default: $default"
|
||||||
|
[[ "$default" == "y" ]]
|
||||||
|
return $?
|
||||||
|
fi
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
if [[ "$default" == "y" ]]; then
|
||||||
|
printf "%s [Y/n]: " "$prompt"
|
||||||
|
else
|
||||||
|
printf "%s [y/N]: " "$prompt"
|
||||||
|
fi
|
||||||
|
|
||||||
|
read -r response
|
||||||
|
response=${response,,} # Convert to lowercase
|
||||||
|
|
||||||
|
case "$response" in
|
||||||
|
"")
|
||||||
|
[[ "$default" == "y" ]]
|
||||||
|
return $?
|
||||||
|
;;
|
||||||
|
y | yes)
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
|
n | no)
|
||||||
|
return 1
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
log_warn "Please answer 'y' or 'n'"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# Show changes and confirm
|
||||||
|
confirm_change() {
|
||||||
|
local file="$1"
|
||||||
|
local description="$2"
|
||||||
|
local temp_file="$3"
|
||||||
|
|
||||||
|
log_info "Proposed changes for $description:"
|
||||||
|
log_info "File: $file"
|
||||||
|
echo
|
||||||
|
|
||||||
|
if command_exists colordiff; then
|
||||||
|
colordiff -u "$file" "$temp_file" 2>/dev/null || diff -u "$file" "$temp_file" 2>/dev/null || true
|
||||||
|
else
|
||||||
|
diff -u "$file" "$temp_file" 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo
|
||||||
|
confirm "Apply these changes?"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ==============================================================================
|
||||||
|
# FILE OPERATIONS
|
||||||
|
# ==============================================================================
|
||||||
|
backup_file() {
|
||||||
|
local file="$1"
|
||||||
|
local backup_suffix="${2:-$(date +%Y%m%d_%H%M%S)}"
|
||||||
|
local backup_file="${file}.backup.${backup_suffix}"
|
||||||
|
|
||||||
|
if [[ -f "$file" ]]; then
|
||||||
|
cp "$file" "$backup_file"
|
||||||
|
log_info "Created backup: $backup_file"
|
||||||
|
echo "$backup_file"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
create_temp_file() {
|
||||||
|
local template="${1:-tmp.XXXXXX}"
|
||||||
|
mktemp "/tmp/${template}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ==============================================================================
|
||||||
|
# PACKAGE MANAGEMENT
|
||||||
|
# ==============================================================================
|
||||||
|
install_packages() {
|
||||||
|
local packages=("$@")
|
||||||
|
|
||||||
|
if [[ ${#packages[@]} -eq 0 ]]; then
|
||||||
|
log_warn "No packages specified"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_info "Installing packages: ${packages[*]}"
|
||||||
|
|
||||||
|
if command_exists paru; then
|
||||||
|
paru -S --needed --noconfirm "${packages[@]}"
|
||||||
|
elif command_exists pacman; then
|
||||||
|
sudo pacman -S --needed --noconfirm "${packages[@]}"
|
||||||
|
else
|
||||||
|
log_error "No supported package manager found"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# ==============================================================================
|
||||||
|
# SERVICE MANAGEMENT
|
||||||
|
# ==============================================================================
|
||||||
|
enable_service() {
|
||||||
|
local service="$1"
|
||||||
|
local user_service="${2:-false}"
|
||||||
|
|
||||||
|
if [[ "$user_service" == "true" ]]; then
|
||||||
|
log_info "Enabling user service: $service"
|
||||||
|
systemctl --user enable --now "$service"
|
||||||
|
else
|
||||||
|
log_info "Enabling system service: $service"
|
||||||
|
sudo systemctl enable --now "$service"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# ==============================================================================
|
||||||
|
# ERROR HANDLING
|
||||||
|
# ==============================================================================
|
||||||
|
cleanup() {
|
||||||
|
local exit_code=$?
|
||||||
|
# Add any cleanup operations here
|
||||||
|
exit $exit_code
|
||||||
|
}
|
||||||
|
|
||||||
|
# Set up trap for cleanup
|
||||||
|
trap cleanup EXIT INT TERM
|
||||||
|
|
||||||
|
# ==============================================================================
|
||||||
|
# SCRIPT INITIALIZATION
|
||||||
|
# ==============================================================================
|
||||||
|
init_script() {
|
||||||
|
log_info "Starting $SCRIPT_NAME"
|
||||||
|
|
||||||
|
# Set DEBUG mode if requested
|
||||||
|
if [[ "${1:-}" == "--debug" ]]; then
|
||||||
|
export DEBUG=1
|
||||||
|
log_debug "Debug mode enabled"
|
||||||
|
shift
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# ==============================================================================
|
||||||
|
# SCRIPT COMPLETION
|
||||||
|
# ==============================================================================
|
||||||
|
finish_script() {
|
||||||
|
local exit_code="${1:-0}"
|
||||||
|
|
||||||
|
if [[ "$exit_code" -eq 0 ]]; then
|
||||||
|
log_success "$SCRIPT_NAME completed successfully"
|
||||||
|
else
|
||||||
|
log_error "$SCRIPT_NAME failed with exit code $exit_code"
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit "$exit_code"
|
||||||
|
}
|
102
main.go
102
main.go
|
@ -32,11 +32,12 @@ type Config struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Script struct {
|
type Script struct {
|
||||||
Path string // Full filesystem path
|
Path string // Full filesystem path
|
||||||
Name string // Just filename (e.g. "install.sh")
|
Name string // Just filename (e.g. "install.sh")
|
||||||
RelPath string // Relative path from runs/ (e.g. "tools/install.sh")
|
RelPath string // Relative path from runs/ (e.g. "tools/install.sh")
|
||||||
Desc string // Description from script comment
|
Desc string // Description from script comment
|
||||||
RequiresSudo bool // Whether script needs elevated privileges
|
RequiresSudo bool // Whether script needs elevated privileges
|
||||||
|
RequiresInteractive bool // Whether script needs interactive input
|
||||||
}
|
}
|
||||||
|
|
||||||
var config Config
|
var config Config
|
||||||
|
@ -213,15 +214,20 @@ func handlePush() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getScriptMetadata(scriptPath string) (string, bool) {
|
type ScriptMetadata struct {
|
||||||
|
RequiresSudo bool
|
||||||
|
RequiresInteractive bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func getScriptMetadata(scriptPath string) (string, ScriptMetadata) {
|
||||||
file, err := os.Open(scriptPath)
|
file, err := os.Open(scriptPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "No description", false
|
return "No description", ScriptMetadata{}
|
||||||
}
|
}
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
|
|
||||||
var desc string
|
var desc string
|
||||||
var requiresSudo bool
|
scriptMetadata := ScriptMetadata{}
|
||||||
|
|
||||||
scanner := bufio.NewScanner(file)
|
scanner := bufio.NewScanner(file)
|
||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
|
@ -231,13 +237,9 @@ func getScriptMetadata(scriptPath string) (string, bool) {
|
||||||
desc = strings.TrimSpace(strings.TrimPrefix(line, "# NAME:"))
|
desc = strings.TrimSpace(strings.TrimPrefix(line, "# NAME:"))
|
||||||
}
|
}
|
||||||
|
|
||||||
if strings.HasPrefix(line, "# REQUIRES: sudo") ||
|
if strings.HasPrefix(line, "# REQUIRES:") {
|
||||||
strings.HasPrefix(line, "# REQUIRES:sudo") ||
|
scriptMetadata.RequiresSudo = strings.Contains(line, "sudo")
|
||||||
strings.HasPrefix(line, "# ELEVATED: true") ||
|
scriptMetadata.RequiresInteractive = strings.Contains(line, "interactive")
|
||||||
strings.HasPrefix(line, "# ELEVATED:true") ||
|
|
||||||
strings.HasPrefix(line, "# SUDO: true") ||
|
|
||||||
strings.HasPrefix(line, "# SUDO:true") {
|
|
||||||
requiresSudo = true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -245,7 +247,7 @@ func getScriptMetadata(scriptPath string) (string, bool) {
|
||||||
desc = "No description"
|
desc = "No description"
|
||||||
}
|
}
|
||||||
|
|
||||||
return desc, requiresSudo
|
return desc, scriptMetadata
|
||||||
}
|
}
|
||||||
|
|
||||||
func findScripts(filters []string) ([]Script, error) {
|
func findScripts(filters []string) ([]Script, error) {
|
||||||
|
@ -271,14 +273,15 @@ func findScripts(filters []string) ([]Script, error) {
|
||||||
scriptName := filepath.Base(path)
|
scriptName := filepath.Base(path)
|
||||||
|
|
||||||
if len(filters) == 0 || matchesFilters(relPath, scriptName, filters) {
|
if len(filters) == 0 || matchesFilters(relPath, scriptName, filters) {
|
||||||
desc, requiresSudo := getScriptMetadata(path)
|
desc, metaData := getScriptMetadata(path)
|
||||||
|
|
||||||
scripts = append(scripts, Script{
|
scripts = append(scripts, Script{
|
||||||
Path: path,
|
Path: path,
|
||||||
Name: scriptName,
|
Name: scriptName,
|
||||||
RelPath: relPath,
|
RelPath: relPath,
|
||||||
Desc: desc,
|
Desc: desc,
|
||||||
RequiresSudo: requiresSudo,
|
RequiresSudo: metaData.RequiresSudo,
|
||||||
|
RequiresInteractive: metaData.RequiresInteractive,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -331,14 +334,15 @@ func executeScript(script Script, args []string, verbose bool) error {
|
||||||
errorLog("sudo command not found - cannot run elevated script")
|
errorLog("sudo command not found - cannot run elevated script")
|
||||||
return fmt.Errorf("sudo not available")
|
return fmt.Errorf("sudo not available")
|
||||||
}
|
}
|
||||||
fullArgs := append([]string{script.Path}, args...)
|
// Use -S to read password from stdin, and preserve environment
|
||||||
|
fullArgs := append([]string{"-S", "-E", script.Path}, args...)
|
||||||
cmd = exec.Command("sudo", fullArgs...)
|
cmd = exec.Command("sudo", fullArgs...)
|
||||||
sudoLog("Running with sudo: %s", strings.Join(append([]string{script.Path}, args...), " "))
|
sudoLog("Running with sudo: %s", strings.Join(append([]string{script.Path}, args...), " "))
|
||||||
} else {
|
} else {
|
||||||
cmd = exec.Command(script.Path, args...)
|
cmd = exec.Command(script.Path, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.Interactive {
|
if config.Interactive || script.RequiresInteractive {
|
||||||
cmd.Stdin = os.Stdin
|
cmd.Stdin = os.Stdin
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -348,7 +352,7 @@ func executeScript(script Script, args []string, verbose bool) error {
|
||||||
}
|
}
|
||||||
defer logFileHandle.Close()
|
defer logFileHandle.Close()
|
||||||
|
|
||||||
showOutput := verbose || config.Interactive
|
showOutput := verbose || config.Interactive || script.RequiresInteractive
|
||||||
if showOutput {
|
if showOutput {
|
||||||
cmd.Stdout = io.MultiWriter(os.Stdout, logFileHandle)
|
cmd.Stdout = io.MultiWriter(os.Stdout, logFileHandle)
|
||||||
cmd.Stderr = io.MultiWriter(os.Stderr, logFileHandle)
|
cmd.Stderr = io.MultiWriter(os.Stderr, logFileHandle)
|
||||||
|
@ -371,6 +375,7 @@ func createNewScript(scriptName string) error {
|
||||||
|
|
||||||
if !strings.HasSuffix(scriptName, ".sh") {
|
if !strings.HasSuffix(scriptName, ".sh") {
|
||||||
scriptName += ".sh"
|
scriptName += ".sh"
|
||||||
|
scriptPath = filepath.Join(config.RunsDir, scriptName)
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := os.Stat(scriptPath); err == nil {
|
if _, err := os.Stat(scriptPath); err == nil {
|
||||||
|
@ -378,15 +383,52 @@ func createNewScript(scriptName string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
template := fmt.Sprintf(`#!/usr/bin/env bash
|
template := fmt.Sprintf(`#!/usr/bin/env bash
|
||||||
# NAME: %s script
|
# NAME: %s
|
||||||
# REQUIRES: sudo
|
# REQUIRES: sudo interactive
|
||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
echo "Running %s script..."
|
# Source common functions
|
||||||
|
source "$(dirname "$0")/../common.sh" || {
|
||||||
|
echo "[ERROR] Could not source common.sh" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
echo "✅ %s completed successfully"
|
check_requirements() {
|
||||||
`, strings.TrimSuffix(scriptName, ".sh"), scriptName, strings.TrimSuffix(scriptName, ".sh"))
|
# Check required commands
|
||||||
|
local required_commands=()
|
||||||
|
# Add your required commands here
|
||||||
|
# required_commands=(git curl wget)
|
||||||
|
|
||||||
|
for cmd in "${required_commands[@]}"; do
|
||||||
|
if ! command_exists "$cmd"; then
|
||||||
|
log_error "Required command not found: $cmd"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
init_script
|
||||||
|
|
||||||
|
check_requirements
|
||||||
|
|
||||||
|
# Your main script logic goes here
|
||||||
|
|
||||||
|
|
||||||
|
# Example operations:
|
||||||
|
# if ! confirm "Proceed with operation?"; then
|
||||||
|
# log_info "Operation cancelled"
|
||||||
|
# finish_script 0
|
||||||
|
# fi
|
||||||
|
|
||||||
|
# Add your implementation here
|
||||||
|
|
||||||
|
finish_script 0
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
||||||
|
`, strings.TrimSuffix(filepath.Base(scriptName), ".sh"))
|
||||||
|
|
||||||
err := os.WriteFile(scriptPath, []byte(template), 0o755)
|
err := os.WriteFile(scriptPath, []byte(template), 0o755)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
84
runs/aur
84
runs/aur
|
@ -1,34 +1,62 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# NAME: aur script
|
# NAME: Install AUR packages
|
||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
echo "Running aur.sh script..."
|
# Source common functions
|
||||||
|
source "$(dirname "$0")/../common.sh" || {
|
||||||
|
echo "[ERROR] Could not source common.sh" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
paru -S --needed --noconfirm adwaita-dark \
|
check_requirements() {
|
||||||
aws-session-manager-plugin \
|
if ! command_exists paru; then
|
||||||
bottles \
|
log_error "paru not found. Install it first"
|
||||||
bruno-bin \
|
exit 1
|
||||||
davmail \
|
fi
|
||||||
dmg2img \
|
}
|
||||||
ebgaramond-otf \
|
|
||||||
insomnia-bin \
|
|
||||||
kubefwd-bin \
|
|
||||||
mpvpaper \
|
|
||||||
ngrok \
|
|
||||||
openvpn3-git \
|
|
||||||
otf-font-awesome-5 \
|
|
||||||
postman-bin \
|
|
||||||
rofi-lbonn-wayland-git \
|
|
||||||
rose-pine-gtk-theme \
|
|
||||||
slack-desktop \
|
|
||||||
soapui \
|
|
||||||
sublime-merge \
|
|
||||||
swayfx-git \
|
|
||||||
teams-for-linux-bin \
|
|
||||||
ttf-font-awesome-5 \
|
|
||||||
ttf-ms-win11-auto \
|
|
||||||
watchman-bin \
|
|
||||||
yubico-authenticator-bin
|
|
||||||
|
|
||||||
echo "✅ aur completed successfully"
|
install_aur_packages() {
|
||||||
|
local packages=(
|
||||||
|
adwaita-dark
|
||||||
|
aws-session-manager-plugin
|
||||||
|
bottles
|
||||||
|
bruno-bin
|
||||||
|
davmail
|
||||||
|
dmg2img
|
||||||
|
ebgaramond-otf
|
||||||
|
insomnia-bin
|
||||||
|
kubefwd-bin
|
||||||
|
mpvpaper
|
||||||
|
ngrok
|
||||||
|
openvpn3-git
|
||||||
|
otf-font-awesome-5
|
||||||
|
postman-bin
|
||||||
|
rofi-lbonn-wayland-git
|
||||||
|
rose-pine-gtk-theme
|
||||||
|
slack-desktop
|
||||||
|
soapui
|
||||||
|
sublime-merge
|
||||||
|
swayfx-git
|
||||||
|
teams-for-linux-bin
|
||||||
|
ttf-font-awesome-5
|
||||||
|
ttf-ms-win11-auto
|
||||||
|
watchman-bin
|
||||||
|
yubico-authenticator-bin
|
||||||
|
betterbird-bin
|
||||||
|
)
|
||||||
|
|
||||||
|
log_info "Installing AUR packages"
|
||||||
|
paru -S --needed --noconfirm "${packages[@]}"
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
init_script
|
||||||
|
|
||||||
|
check_requirements
|
||||||
|
install_aur_packages
|
||||||
|
|
||||||
|
finish_script 0
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
||||||
|
|
378
runs/base
378
runs/base
|
@ -1,199 +1,237 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# NAME: Install base system packages
|
# NAME: Install base system packages with hardware detection
|
||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
AUR_HELPER="paru"
|
# Source common functions
|
||||||
|
source "$(dirname "$0")/../common.sh" || {
|
||||||
if ! command -v $AUR_HELPER &>/dev/null; then
|
echo "[ERROR] Could not source common.sh" >&2
|
||||||
echo "[ERROR] $AUR_HELPER not found. Install it first."
|
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
}
|
||||||
|
|
||||||
echo "Installing organized system packages..."
|
check_requirements() {
|
||||||
|
if ! command_exists paru; then
|
||||||
|
log_error "paru not found. Install it first"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
# ═══════════════════════════════════════════════════════════
|
detect_hardware() {
|
||||||
# 🔧 DETECT HARDWARE
|
local cpu_vendor gpu_info microcode gpu_packages
|
||||||
# ═══════════════════════════════════════════════════════════
|
|
||||||
CPU_VENDOR=$(lscpu | grep "Vendor ID" | awk '{print $3}')
|
|
||||||
GPU_INFO=$(lspci | grep -i vga)
|
|
||||||
|
|
||||||
echo "Detected CPU: $CPU_VENDOR"
|
cpu_vendor=$(lscpu | grep "Vendor ID" | awk '{print $3}')
|
||||||
echo "Detected GPU: $GPU_INFO"
|
gpu_info=$(lspci | grep -i vga)
|
||||||
|
|
||||||
# Determine microcode package
|
log_info "Detected CPU: $cpu_vendor"
|
||||||
if [[ "$CPU_VENDOR" == "GenuineIntel" ]]; then
|
log_info "Detected GPU: $gpu_info"
|
||||||
MICROCODE="intel-ucode"
|
|
||||||
echo "→ Using Intel microcode"
|
|
||||||
elif [[ "$CPU_VENDOR" == "AuthenticAMD" ]]; then
|
|
||||||
MICROCODE="amd-ucode"
|
|
||||||
echo "→ Using AMD microcode"
|
|
||||||
else
|
|
||||||
MICROCODE=""
|
|
||||||
echo "→ Unknown CPU vendor, skipping microcode"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Determine GPU drivers
|
# Determine microcode package
|
||||||
GPU_PACKAGES=""
|
case "$cpu_vendor" in
|
||||||
if echo "$GPU_INFO" | grep -qi "amd\|radeon"; then
|
"GenuineIntel")
|
||||||
GPU_PACKAGES="xf86-video-amdgpu vulkan-radeon lib32-vulkan-radeon opencl-mesa lib32-opencl-mesa"
|
microcode="intel-ucode"
|
||||||
echo "→ Using AMD GPU drivers"
|
log_info "Using Intel microcode"
|
||||||
elif echo "$GPU_INFO" | grep -qi "intel"; then
|
;;
|
||||||
GPU_PACKAGES="xf86-video-intel vulkan-intel lib32-vulkan-intel intel-media-driver"
|
"AuthenticAMD")
|
||||||
echo "→ Using Intel GPU drivers"
|
microcode="amd-ucode"
|
||||||
elif echo "$GPU_INFO" | grep -qi "nvidia"; then
|
log_info "Using AMD microcode"
|
||||||
GPU_PACKAGES="nvidia nvidia-utils lib32-nvidia-utils nvidia-settings"
|
;;
|
||||||
echo "→ Using NVIDIA drivers (you may want to review this)"
|
*)
|
||||||
else
|
microcode=""
|
||||||
echo "→ Unknown GPU, using generic drivers"
|
log_warn "Unknown CPU vendor, skipping microcode"
|
||||||
fi
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
# ═══════════════════════════════════════════════════════════
|
# Determine GPU drivers
|
||||||
# 🔧 SYSTEM BASE
|
gpu_packages=""
|
||||||
# ═══════════════════════════════════════════════════════════
|
if echo "$gpu_info" | grep -qi "amd\|radeon"; then
|
||||||
echo "Installing system base..."
|
gpu_packages="xf86-video-amdgpu vulkan-radeon lib32-vulkan-radeon opencl-mesa lib32-opencl-mesa"
|
||||||
BASE_PACKAGES="base base-devel sudo stow linux-cachyos linux-cachyos-headers linux-firmware efibootmgr efitools mkinitcpio grub systemd-boot-manager"
|
log_info "Using AMD GPU drivers"
|
||||||
|
elif echo "$gpu_info" | grep -qi "intel"; then
|
||||||
|
gpu_packages="xf86-video-intel vulkan-intel lib32-vulkan-intel intel-media-driver"
|
||||||
|
log_info "Using Intel GPU drivers"
|
||||||
|
elif echo "$gpu_info" | grep -qi "nvidia"; then
|
||||||
|
gpu_packages="nvidia nvidia-utils lib32-nvidia-utils nvidia-settings"
|
||||||
|
log_info "Using NVIDIA drivers"
|
||||||
|
else
|
||||||
|
log_warn "Unknown GPU, using generic drivers"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
if [[ -n "$MICROCODE" ]]; then
|
install_base_system() {
|
||||||
BASE_PACKAGES="$BASE_PACKAGES $MICROCODE"
|
log_info "Installing system base packages"
|
||||||
fi
|
|
||||||
|
|
||||||
$AUR_HELPER -S --noconfirm --needed $BASE_PACKAGES
|
local base_packages="base base-devel sudo stow linux-cachyos linux-cachyos-headers linux-firmware efibootmgr efitools mkinitcpio grub systemd-boot-manager"
|
||||||
|
|
||||||
# ═══════════════════════════════════════════════════════════
|
if [[ -n "$microcode" ]]; then
|
||||||
# 🌐 NETWORKING & BLUETOOTH
|
base_packages="$base_packages $microcode"
|
||||||
# ═══════════════════════════════════════════════════════════
|
fi
|
||||||
echo "Installing networking..."
|
|
||||||
$AUR_HELPER -S --noconfirm --needed \
|
|
||||||
networkmanager networkmanager-openvpn network-manager-applet \
|
|
||||||
dhclient dnsmasq iptables-nft iwd wpa_supplicant wireless-regdb \
|
|
||||||
bluez-libs blueman openssh
|
|
||||||
|
|
||||||
# ═══════════════════════════════════════════════════════════
|
paru -S --needed --overwrite="*" $base_packages
|
||||||
# 🔊 AUDIO & VIDEO
|
}
|
||||||
# ═══════════════════════════════════════════════════════════
|
|
||||||
echo "Installing audio/video..."
|
|
||||||
$AUR_HELPER -S --noconfirm --needed \
|
|
||||||
pipewire pipewire-alsa pipewire-pulse wireplumber \
|
|
||||||
pavucontrol alsa-firmware alsa-plugins alsa-utils \
|
|
||||||
gst-libav gst-plugin-pipewire gst-plugins-bad gst-plugins-ugly \
|
|
||||||
mpv ffmpegthumbnailer
|
|
||||||
|
|
||||||
# ═══════════════════════════════════════════════════════════
|
install_networking() {
|
||||||
# 🎨 FONTS & THEMES
|
log_info "Installing networking packages"
|
||||||
# ═══════════════════════════════════════════════════════════
|
|
||||||
echo "Installing fonts and themes..."
|
|
||||||
$AUR_HELPER -S --noconfirm --needed \
|
|
||||||
adobe-source-han-sans-cn-fonts adobe-source-han-sans-jp-fonts \
|
|
||||||
adobe-source-han-sans-kr-fonts adobe-source-serif-fonts \
|
|
||||||
awesome-terminal-fonts inter-font noto-fonts noto-fonts-cjk noto-fonts-emoji \
|
|
||||||
ttf-bitstream-vera ttf-dejavu ttf-fantasque-nerd ttf-fira-code ttf-fira-mono \
|
|
||||||
ttf-fira-sans ttf-font-awesome-5 ttf-liberation ttf-linux-libertine \
|
|
||||||
ttf-meslo-nerd ttf-ms-win11-auto ttf-opensans otf-font-awesome-5 otf-libertinus \
|
|
||||||
papirus-icon-theme rose-pine-gtk-theme
|
|
||||||
|
|
||||||
# ═══════════════════════════════════════════════════════════
|
paru -S --needed \
|
||||||
# 💻 DEVELOPMENT TOOLS
|
networkmanager networkmanager-openvpn network-manager-applet \
|
||||||
# ═══════════════════════════════════════════════════════════
|
dhclient dnsmasq iptables-nft iwd wpa_supplicant wireless-regdb \
|
||||||
echo "Installing development tools..."
|
bluez-libs blueman openssh
|
||||||
$AUR_HELPER -S --noconfirm --needed \
|
}
|
||||||
git git-lfs git-crypt github-cli lazygit \
|
|
||||||
go go-task python python-defusedxml python-packaging \
|
|
||||||
python-protobuf python-pynvim python-pywlroots lua luarocks \
|
|
||||||
ccls cmake ninja neovim-nightly-bin
|
|
||||||
|
|
||||||
# ═══════════════════════════════════════════════════════════
|
install_audio_video() {
|
||||||
# 🛠️ CLI UTILITIES
|
log_info "Installing audio and video packages"
|
||||||
# ═══════════════════════════════════════════════════════════
|
|
||||||
echo "Installing CLI utilities..."
|
|
||||||
$AUR_HELPER -S --noconfirm --needed \
|
|
||||||
bat btop duf dysk dust eza fd fzf glances glow httpie ncdu \
|
|
||||||
plocate ripgrep tealdeer the_silver_searcher tmux wget \
|
|
||||||
xdg-user-dirs zoxide zellij yazi yq zsh
|
|
||||||
|
|
||||||
# ═══════════════════════════════════════════════════════════
|
paru -S --needed \
|
||||||
# 🪟 WINDOW MANAGERS & DESKTOP
|
pipewire pipewire-alsa pipewire-pulse wireplumber \
|
||||||
# ═══════════════════════════════════════════════════════════
|
pavucontrol alsa-firmware alsa-plugins alsa-utils \
|
||||||
echo "Installing window managers..."
|
gst-libav gst-plugin-pipewire gst-plugins-bad gst-plugins-ugly \
|
||||||
$AUR_HELPER -S --noconfirm --needed \
|
mpv ffmpegthumbnailer
|
||||||
swaybg swayfx-git swayidle swaylock-effects waybar \
|
}
|
||||||
wlogout wdisplays wl-clipboard rofi-lbonn-wayland-git
|
|
||||||
|
|
||||||
# ═══════════════════════════════════════════════════════════
|
install_fonts_themes() {
|
||||||
# 🌍 GUI APPLICATIONS
|
log_info "Installing fonts and themes"
|
||||||
# ═══════════════════════════════════════════════════════════
|
|
||||||
echo "Installing GUI applications..."
|
|
||||||
$AUR_HELPER -S --noconfirm --needed \
|
|
||||||
chromium zen-browser-bin \
|
|
||||||
legcord-bin slack-desktop teams-for-linux-bin \
|
|
||||||
obs-studio obsidian sublime-merge dbeaver \
|
|
||||||
libreoffice-fresh kitty nemo nemo-fileroller
|
|
||||||
|
|
||||||
# ═══════════════════════════════════════════════════════════
|
paru -S --needed \
|
||||||
# 📁 SYSTEM UTILITIES
|
adobe-source-han-sans-cn-fonts adobe-source-han-sans-jp-fonts \
|
||||||
# ═══════════════════════════════════════════════════════════
|
adobe-source-han-sans-kr-fonts adobe-source-serif-fonts \
|
||||||
echo "Installing system utilities..."
|
awesome-terminal-fonts inter-font noto-fonts noto-fonts-cjk noto-fonts-emoji \
|
||||||
$AUR_HELPER -S --noconfirm --needed \
|
ttf-bitstream-vera ttf-dejavu ttf-fantasque-nerd ttf-fira-code ttf-fira-mono \
|
||||||
brightnessctl cronie cups cups-pdf gamemode gvfs gvfs-afc gvfs-google \
|
ttf-fira-sans ttf-font-awesome-5 ttf-liberation ttf-linux-libertine \
|
||||||
gvfs-gphoto2 gvfs-mtp gvfs-nfs gvfs-smb haveged hdparm less lvm2 \
|
ttf-meslo-nerd ttf-ms-win11-auto ttf-opensans otf-font-awesome-5 otf-libertinus \
|
||||||
man-db man-pages meld modemmanager mtools mupdf netctl nss-mdns \
|
papirus-icon-theme rose-pine-gtk-theme
|
||||||
ntfs-3g ntp nvme-cli opencl-mesa pacman-contrib pass pika-backup \
|
}
|
||||||
pkgfile power-profiles-daemon pv reflector remmina rsync rtkit \
|
|
||||||
samba seahorse sg3_utils smartmontools snapper solaar steam \
|
|
||||||
steam-native-runtime syncthing system-config-printer timeshift \
|
|
||||||
transmission-qt ufw unrar unzip upower usb_modeswitch usbutils \
|
|
||||||
vi vorta w3m which xdg-desktop-portal xdg-desktop-portal-gnome \
|
|
||||||
xdg-desktop-portal-gtk xdg-desktop-portal-wlr yad zenity
|
|
||||||
|
|
||||||
# ═══════════════════════════════════════════════════════════
|
install_development() {
|
||||||
# 🎮 GAMING & GRAPHICS
|
log_info "Installing development tools"
|
||||||
# ═══════════════════════════════════════════════════════════
|
|
||||||
echo "Installing gaming and graphics..."
|
|
||||||
GAMING_BASE="lib32-alsa-lib lib32-alsa-plugins lib32-gamemode lib32-libpulse lib32-mesa lib32-openal lib32-vkd3d lib32-vulkan-mesa-layers vkd3d vulkan-mesa-layers vulkan-tools vulkan-validation-layers wine protonup-qt"
|
|
||||||
|
|
||||||
if [[ -n "$GPU_PACKAGES" ]]; then
|
paru -S --needed \
|
||||||
$AUR_HELPER -S --noconfirm --needed $GAMING_BASE $GPU_PACKAGES
|
git git-lfs git-crypt github-cli lazygit \
|
||||||
else
|
go go-task python python-defusedxml python-packaging \
|
||||||
$AUR_HELPER -S --noconfirm --needed $GAMING_BASE
|
python-protobuf python-pynvim python-pywlroots lua luarocks \
|
||||||
fi
|
ccls cmake ninja neovim-nightly-bin
|
||||||
|
}
|
||||||
|
|
||||||
# ═══════════════════════════════════════════════════════════
|
install_cli_utilities() {
|
||||||
# 📱 MOBILE & HARDWARE
|
log_info "Installing CLI utilities"
|
||||||
# ═══════════════════════════════════════════════════════════
|
|
||||||
echo "Installing hardware support..."
|
|
||||||
$AUR_HELPER -S --noconfirm --needed \
|
|
||||||
sof-firmware xf86-input-libinput xfsprogs \
|
|
||||||
xorg-server xorg-xdpyinfo xorg-xhost xorg-xinit xorg-xinput \
|
|
||||||
xorg-xkill xorg-xrandr xorg-xwayland
|
|
||||||
|
|
||||||
# ═══════════════════════════════════════════════════════════
|
paru -S --needed \
|
||||||
# ☁️ CLOUD & DEVOPS
|
bat btop duf dysk dust eza fd fzf glances glow httpie ncdu \
|
||||||
# ═══════════════════════════════════════════════════════════
|
plocate ripgrep tealdeer the_silver_searcher tmux wget \
|
||||||
echo "Installing cloud and DevOps tools..."
|
xdg-user-dirs zoxide yazi yq zsh
|
||||||
$AUR_HELPER -S --noconfirm --needed \
|
}
|
||||||
aws-cli aws-session-manager-plugin insomnia-bin \
|
|
||||||
kubectl kubectx kubefwd-bin ngrok postgresql
|
|
||||||
|
|
||||||
# ═══════════════════════════════════════════════════════════
|
install_window_managers() {
|
||||||
# 📚 DOCUMENT & PRODUCTIVITY
|
log_info "Installing window managers and desktop environment"
|
||||||
# ═══════════════════════════════════════════════════════════
|
|
||||||
echo "Installing document tools..."
|
|
||||||
$AUR_HELPER -S --noconfirm --needed \
|
|
||||||
pandoc-cli texinfo wkhtmltopdf-bin zathura zathura-pdf-mupdf \
|
|
||||||
swappy wf-recorder
|
|
||||||
|
|
||||||
# ═══════════════════════════════════════════════════════════
|
paru -S --needed \
|
||||||
# 🔐 SECURITY & ENCRYPTION
|
swaybg swayfx-git swayidle swaylock-effects waybar \
|
||||||
# ═══════════════════════════════════════════════════════════
|
wlogout wdisplays wl-clipboard rofi-lbonn-wayland-git
|
||||||
echo "Installing security tools..."
|
}
|
||||||
$AUR_HELPER -S --noconfirm --needed \
|
|
||||||
yubico-authenticator-bin yubikey-manager-qt
|
|
||||||
|
|
||||||
# ═══════════════════════════════════════════════════════════
|
install_gui_applications() {
|
||||||
# 📦 PACKAGE MANAGERS & MISC
|
log_info "Installing GUI applications"
|
||||||
# ═══════════════════════════════════════════════════════════
|
|
||||||
echo "Installing package managers and misc..."
|
|
||||||
$AUR_HELPER -S --noconfirm --needed \
|
|
||||||
pyenv watchman-bin wimlib
|
|
||||||
|
|
||||||
tldr --update
|
paru -S --needed \
|
||||||
|
chromium zen-browser-bin \
|
||||||
|
legcord-bin slack-desktop teams-for-linux-bin \
|
||||||
|
obs-studio obsidian sublime-merge dbeaver \
|
||||||
|
libreoffice-fresh kitty nemo nemo-fileroller
|
||||||
|
}
|
||||||
|
|
||||||
|
install_system_utilities() {
|
||||||
|
log_info "Installing system utilities"
|
||||||
|
|
||||||
|
paru -S --needed \
|
||||||
|
brightnessctl cronie cups cups-pdf gamemode gvfs gvfs-afc gvfs-google \
|
||||||
|
gvfs-gphoto2 gvfs-mtp gvfs-nfs gvfs-smb haveged hdparm less lvm2 \
|
||||||
|
man-db man-pages meld modemmanager mtools mupdf netctl nss-mdns \
|
||||||
|
ntfs-3g ntp nvme-cli opencl-mesa pacman-contrib pass pika-backup \
|
||||||
|
pkgfile power-profiles-daemon pv reflector remmina rsync rtkit \
|
||||||
|
samba seahorse sg3_utils smartmontools snapper solaar steam \
|
||||||
|
steam-native-runtime syncthing system-config-printer \
|
||||||
|
transmission-qt ufw unrar unzip upower usb_modeswitch usbutils \
|
||||||
|
vi vorta w3m which xdg-desktop-portal xdg-desktop-portal-gnome \
|
||||||
|
xdg-desktop-portal-gtk xdg-desktop-portal-wlr yad zenity
|
||||||
|
}
|
||||||
|
|
||||||
|
install_gaming_graphics() {
|
||||||
|
log_info "Installing gaming and graphics packages"
|
||||||
|
|
||||||
|
local gaming_base="lib32-alsa-lib lib32-alsa-plugins lib32-gamemode lib32-libpulse lib32-mesa lib32-openal lib32-vkd3d lib32-vulkan-mesa-layers vkd3d vulkan-mesa-layers vulkan-tools vulkan-validation-layers wine protonup-qt"
|
||||||
|
|
||||||
|
if [[ -n "$gpu_packages" ]]; then
|
||||||
|
paru -S --needed $gaming_base $gpu_packages
|
||||||
|
else
|
||||||
|
paru -S --needed $gaming_base
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
install_hardware_support() {
|
||||||
|
log_info "Installing hardware support"
|
||||||
|
|
||||||
|
paru -S --needed \
|
||||||
|
sof-firmware xf86-input-libinput xfsprogs \
|
||||||
|
xorg-server xorg-xdpyinfo xorg-xhost xorg-xinit xorg-xinput \
|
||||||
|
xorg-xkill xorg-xrandr xorg-xwayland
|
||||||
|
}
|
||||||
|
|
||||||
|
install_cloud_devops() {
|
||||||
|
log_info "Installing cloud and DevOps tools"
|
||||||
|
|
||||||
|
paru -S --needed \
|
||||||
|
aws-cli aws-session-manager-plugin insomnia-bin \
|
||||||
|
kubectl kubectx kubefwd-bin ngrok postgresql
|
||||||
|
}
|
||||||
|
|
||||||
|
install_document_tools() {
|
||||||
|
log_info "Installing document and productivity tools"
|
||||||
|
|
||||||
|
paru -S --needed \
|
||||||
|
pandoc-cli texinfo wkhtmltopdf-bin zathura zathura-pdf-mupdf \
|
||||||
|
swappy wf-recorder
|
||||||
|
}
|
||||||
|
|
||||||
|
install_security_tools() {
|
||||||
|
log_info "Installing security tools"
|
||||||
|
|
||||||
|
paru -S --needed \
|
||||||
|
yubico-authenticator-bin yubikey-manager-qt
|
||||||
|
}
|
||||||
|
|
||||||
|
install_misc_packages() {
|
||||||
|
log_info "Installing miscellaneous packages"
|
||||||
|
|
||||||
|
paru -S --needed \
|
||||||
|
pyenv watchman-bin wimlib \
|
||||||
|
slurp grim swaync gum nwg-look lxsession colordiff
|
||||||
|
|
||||||
|
log_info "Updating tldr database"
|
||||||
|
tldr --update
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
init_script
|
||||||
|
|
||||||
|
check_requirements
|
||||||
|
detect_hardware
|
||||||
|
|
||||||
|
install_base_system
|
||||||
|
install_networking
|
||||||
|
install_audio_video
|
||||||
|
install_fonts_themes
|
||||||
|
install_development
|
||||||
|
install_cli_utilities
|
||||||
|
install_window_managers
|
||||||
|
install_gui_applications
|
||||||
|
install_system_utilities
|
||||||
|
install_gaming_graphics
|
||||||
|
install_hardware_support
|
||||||
|
install_cloud_devops
|
||||||
|
install_document_tools
|
||||||
|
install_security_tools
|
||||||
|
install_misc_packages
|
||||||
|
|
||||||
|
finish_script 0
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
||||||
|
|
70
runs/boot
70
runs/boot
|
@ -1,37 +1,40 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# NAME: Configure systemd-boot manager settings
|
# NAME: Configure systemd-boot manager settings
|
||||||
|
# REQUIRES: sudo
|
||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
SDBOOT_CONFIG="/etc/sdboot-manage.conf"
|
# Source common functions
|
||||||
|
source "$(dirname "$0")/../common.sh" || {
|
||||||
echo "Configuring systemd-boot manager..."
|
echo "[ERROR] Could not source common.sh" >&2
|
||||||
|
|
||||||
# Check if sdboot-manage is installed
|
|
||||||
if ! command -v sdboot-manage &>/dev/null; then
|
|
||||||
echo "⚠️ sdboot-manage not found. Install systemd-boot-manager first."
|
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
}
|
||||||
|
|
||||||
# Backup existing config if it exists
|
readonly SDBOOT_CONFIG="/etc/sdboot-manage.conf"
|
||||||
if [[ -f "$SDBOOT_CONFIG" ]]; then
|
|
||||||
sudo cp "$SDBOOT_CONFIG" "$SDBOOT_CONFIG.backup.$(date +%Y%m%d_%H%M%S)"
|
|
||||||
echo "→ Backed up existing config"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Create the configuration
|
check_requirements() {
|
||||||
sudo tee "$SDBOOT_CONFIG" >/dev/null <<'EOF'
|
if ! command_exists sdboot-manage; then
|
||||||
|
log_error "sdboot-manage not found. Install systemd-boot-manager first"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
configure_systemd_boot() {
|
||||||
|
log_info "Configuring systemd-boot manager"
|
||||||
|
|
||||||
|
if [[ -f "$SDBOOT_CONFIG" ]]; then
|
||||||
|
backup_file "$SDBOOT_CONFIG"
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_info "Creating systemd-boot configuration"
|
||||||
|
tee "$SDBOOT_CONFIG" >/dev/null <<'EOF'
|
||||||
# Config file for sdboot-manage
|
# Config file for sdboot-manage
|
||||||
# Kernel options to be appended to the "options" line
|
# Kernel options to be appended to the "options" line
|
||||||
LINUX_OPTIONS="zswap.enabled=0 nowatchdog ipv6.disable=1 audit=0 loglevel=3 rd.systemd.show_status=auto rd.udev.log_level=3"
|
LINUX_OPTIONS="zswap.enabled=0 nowatchdog ipv6.disable=1 audit=0 loglevel=3 rd.systemd.show_status=auto rd.udev.log_level=3"
|
||||||
#LINUX_FALLBACK_OPTIONS=""
|
|
||||||
|
|
||||||
# When DISABLE_FALLBACK is set to "yes", it will stop creating fallback entries for each kernel.
|
# When DISABLE_FALLBACK is set to "yes", it will stop creating fallback entries for each kernel.
|
||||||
DISABLE_FALLBACK="no"
|
DISABLE_FALLBACK="no"
|
||||||
|
|
||||||
# Use this pattern to match kernels which should be considered native OS kernels
|
|
||||||
#KERNEL_PATTERN="vmlinuz-"
|
|
||||||
|
|
||||||
# Setting REMOVE_EXISTING to "yes" will remove all your existing systemd-boot entries before building new entries
|
# Setting REMOVE_EXISTING to "yes" will remove all your existing systemd-boot entries before building new entries
|
||||||
REMOVE_EXISTING="yes"
|
REMOVE_EXISTING="yes"
|
||||||
|
|
||||||
|
@ -41,19 +44,18 @@ OVERWRITE_EXISTING="yes"
|
||||||
|
|
||||||
# When REMOVE_OBSOLETE is set to "yes" entries for kernels no longer available on the system will be removed
|
# When REMOVE_OBSOLETE is set to "yes" entries for kernels no longer available on the system will be removed
|
||||||
REMOVE_OBSOLETE="yes"
|
REMOVE_OBSOLETE="yes"
|
||||||
|
|
||||||
# If PRESERVE_FOREIGN is set to "yes", do not delete entries starting with $ENTRY_ROOT
|
|
||||||
#PRESERVE_FOREIGN="no"
|
|
||||||
|
|
||||||
# Setting NO_AUTOUPDATE to "yes" will stop the updates to systemd-boot when systemd is updated - not recommended unless you are seperately updating systemd-boot
|
|
||||||
#NO_AUTOUPDATE="no"
|
|
||||||
|
|
||||||
# Setting NO_AUTOGEN to "yes" will stop the automatic creation of entries when kernels are installed or updated
|
|
||||||
#NO_AUTOGEN="no"
|
|
||||||
|
|
||||||
# Use this to change the default initramfs prefix (e.g. when using booster)
|
|
||||||
#INITRD_PREFIX="initramfs"
|
|
||||||
|
|
||||||
# Additional entities to initrd can be added here, such as microcode if your initramfs does not include it.
|
|
||||||
#INITRD_ENTRIES=()
|
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
log_info "systemd-boot configuration updated"
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
init_script
|
||||||
|
|
||||||
|
check_requirements
|
||||||
|
configure_systemd_boot
|
||||||
|
|
||||||
|
finish_script 0
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
||||||
|
|
47
runs/docker
47
runs/docker
|
@ -1,24 +1,41 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# NAME: Install and configure Docker on Arch Linux
|
# NAME: Install and configure Docker
|
||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
echo "Installing Docker..."
|
# Source common functions
|
||||||
|
source "$(dirname "$0")/../common.sh" || {
|
||||||
|
echo "[ERROR] Could not source common.sh" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
# Install Docker packages
|
install_docker() {
|
||||||
sudo pacman -S --needed --noconfirm docker docker-compose docker-buildx
|
log_info "Installing Docker packages"
|
||||||
|
sudo pacman -S --needed --noconfirm docker docker-compose docker-buildx
|
||||||
|
}
|
||||||
|
|
||||||
# Add current user to docker group
|
configure_docker() {
|
||||||
sudo usermod -aG docker "$USER"
|
log_info "Adding current user to docker group"
|
||||||
|
sudo usermod -aG docker "$USER"
|
||||||
|
|
||||||
# Enable and start Docker service
|
log_info "Enabling Docker services"
|
||||||
sudo systemctl enable docker.service
|
sudo systemctl enable docker.service
|
||||||
sudo systemctl start docker.service
|
sudo systemctl start docker.service
|
||||||
|
sudo systemctl enable containerd.service
|
||||||
|
sudo systemctl start containerd.service
|
||||||
|
}
|
||||||
|
|
||||||
# Enable containerd service (dependency)
|
main() {
|
||||||
sudo systemctl enable containerd.service
|
init_script
|
||||||
sudo systemctl start containerd.service
|
|
||||||
|
|
||||||
echo "✅ Docker installed successfully!"
|
install_docker
|
||||||
echo "⚠️ You need to log out and back in (or reboot) for group changes to take effect"
|
configure_docker
|
||||||
echo "🐳 Test with: docker run hello-world"
|
|
||||||
|
log_info "Docker installed successfully"
|
||||||
|
log_warn "You need to log out and back in (or reboot) for group changes to take effect"
|
||||||
|
log_info "Test with: docker run hello-world"
|
||||||
|
|
||||||
|
finish_script 0
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
||||||
|
|
229
runs/dotfiles
229
runs/dotfiles
|
@ -1,151 +1,118 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# NAME: Setup dotfiles and Neovim configuration
|
# NAME: Setup dotfiles and configuration
|
||||||
|
# REQUIRES: interactive
|
||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
DOTFILES_REPO="https://git.mz.uy/marianozunino/dotfiles.git"
|
# Source common functions
|
||||||
NVIM_REPO="https://github.com/marianozunino/nvim.git"
|
source "$(dirname "$0")/../common.sh" || {
|
||||||
DOTFILES_DIR="$HOME/dotfiles"
|
echo "[ERROR] Could not source common.sh" >&2
|
||||||
NVIM_CONFIG_DIR="$HOME/.config/nvim"
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
echo "🏠 Setting up Forbi's development environment..."
|
readonly DOTFILES_REPO="https://git.mz.uy/marianozunino/dotfiles.git"
|
||||||
|
readonly DOTFILES_DIR="$HOME/dotfiles"
|
||||||
|
|
||||||
# ═══════════════════════════════════════════════════════════
|
check_requirements() {
|
||||||
# 📁 CLONE DOTFILES
|
local required_commands=(git git-crypt stow)
|
||||||
# ═══════════════════════════════════════════════════════════
|
|
||||||
echo "📦 Cloning dotfiles repository..."
|
|
||||||
|
|
||||||
if [[ -d "$DOTFILES_DIR" ]]; then
|
for cmd in "${required_commands[@]}"; do
|
||||||
echo "→ Dotfiles directory already exists, updating..."
|
if ! command_exists "$cmd"; then
|
||||||
cd "$DOTFILES_DIR"
|
log_error "Required command not found: $cmd"
|
||||||
git pull origin main || git pull origin master
|
|
||||||
else
|
|
||||||
echo "→ Cloning dotfiles to $DOTFILES_DIR"
|
|
||||||
git clone "$DOTFILES_REPO" "$DOTFILES_DIR"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# ═══════════════════════════════════════════════════════════
|
|
||||||
# 🔐 HANDLE GIT-CRYPT
|
|
||||||
# ═══════════════════════════════════════════════════════════
|
|
||||||
echo "🔐 Checking for git-crypt..."
|
|
||||||
|
|
||||||
cd "$DOTFILES_DIR"
|
|
||||||
|
|
||||||
# Check if repo uses git-crypt
|
|
||||||
if [[ -f ".git-crypt/.gitattributes" ]] || git-crypt status &>/dev/null; then
|
|
||||||
echo "→ git-crypt repository detected"
|
|
||||||
|
|
||||||
# Check if already unlocked
|
|
||||||
if git-crypt status | grep -q "unlocked"; then
|
|
||||||
echo "→ Repository already unlocked"
|
|
||||||
else
|
|
||||||
echo "→ Repository is encrypted, attempting to unlock..."
|
|
||||||
|
|
||||||
# Check if YubiKey/GPG setup is available
|
|
||||||
if command -v gpg &>/dev/null; then
|
|
||||||
echo "→ GPG found, checking for available keys..."
|
|
||||||
|
|
||||||
# List secret keys to see if YubiKey is connected
|
|
||||||
if gpg --list-secret-keys &>/dev/null; then
|
|
||||||
echo "→ GPG keys detected, attempting git-crypt unlock..."
|
|
||||||
|
|
||||||
# Attempt to unlock with GPG (YubiKey)
|
|
||||||
if git-crypt unlock 2>/dev/null; then
|
|
||||||
echo "✅ Repository unlocked successfully with GPG/YubiKey!"
|
|
||||||
else
|
|
||||||
echo "❌ Failed to unlock with GPG"
|
|
||||||
echo
|
|
||||||
echo "🔑 Manual unlock required:"
|
|
||||||
echo " 1. Make sure your YubiKey is connected"
|
|
||||||
echo " 2. Test GPG: gpg --card-status"
|
|
||||||
echo " 3. Try: cd $DOTFILES_DIR && git-crypt unlock"
|
|
||||||
echo " 4. Or unlock with key file: git-crypt unlock /path/to/key"
|
|
||||||
echo " 5. Then re-run: ./run forbi"
|
|
||||||
echo
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo "❌ No GPG secret keys found"
|
|
||||||
echo
|
|
||||||
echo "🔑 YubiKey/GPG setup needed:"
|
|
||||||
echo " 1. Connect your YubiKey"
|
|
||||||
echo " 2. Import your GPG key: gpg --card-status"
|
|
||||||
echo " 3. Set trust level: gpg --edit-key <your-key-id> trust"
|
|
||||||
echo " 4. Then re-run: ./run forbi"
|
|
||||||
echo
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo "❌ GPG not available"
|
|
||||||
echo
|
|
||||||
echo "🔑 To unlock your dotfiles:"
|
|
||||||
echo " 1. Install GPG and connect YubiKey, or"
|
|
||||||
echo " 2. Use key file: cd $DOTFILES_DIR && git-crypt unlock /path/to/key"
|
|
||||||
echo " 3. Then re-run: ./run forbi"
|
|
||||||
echo
|
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
clone_dotfiles() {
|
||||||
|
log_info "Setting up dotfiles repository"
|
||||||
|
|
||||||
|
if [[ -d "$DOTFILES_DIR" ]]; then
|
||||||
|
log_info "Dotfiles directory already exists, updating"
|
||||||
|
cd "$DOTFILES_DIR"
|
||||||
|
git pull origin main || git pull origin master
|
||||||
|
else
|
||||||
|
log_info "Cloning dotfiles to $DOTFILES_DIR"
|
||||||
|
git clone "$DOTFILES_REPO" "$DOTFILES_DIR"
|
||||||
fi
|
fi
|
||||||
else
|
}
|
||||||
echo "→ No git-crypt encryption detected"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# ═══════════════════════════════════════════════════════════
|
handle_git_crypt() {
|
||||||
# ⚙️ CLONE NEOVIM CONFIG
|
log_info "Checking git-crypt status"
|
||||||
# ═══════════════════════════════════════════════════════════
|
cd "$DOTFILES_DIR"
|
||||||
echo "📝 Setting up Neovim configuration..."
|
|
||||||
|
|
||||||
# Backup existing Neovim config if it exists
|
if git-crypt status | grep -q "unlocked"; then
|
||||||
if [[ -d "$NVIM_CONFIG_DIR" ]]; then
|
log_info "Repository already unlocked"
|
||||||
BACKUP_DIR="$NVIM_CONFIG_DIR.backup.$(date +%Y%m%d_%H%M%S)"
|
return 0
|
||||||
echo "→ Backing up existing Neovim config to $BACKUP_DIR"
|
fi
|
||||||
mv "$NVIM_CONFIG_DIR" "$BACKUP_DIR"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Clone Neovim configuration
|
log_info "Repository is encrypted, attempting to unlock"
|
||||||
echo "→ Cloning Neovim config to $NVIM_CONFIG_DIR"
|
|
||||||
git clone "$NVIM_REPO" "$NVIM_CONFIG_DIR"
|
|
||||||
|
|
||||||
# ═══════════════════════════════════════════════════════════
|
if gpg --card-status &>/dev/null; then
|
||||||
# 🔧 CONFIGURE GIT HOOKS
|
log_info "YubiKey detected, fetching public key"
|
||||||
# ═══════════════════════════════════════════════════════════
|
|
||||||
echo "🎣 Setting up Git hooks for Neovim config..."
|
|
||||||
|
|
||||||
cd "$NVIM_CONFIG_DIR"
|
local key_id
|
||||||
if [[ -d ".githooks" ]]; then
|
key_id=$(gpg --card-status 2>/dev/null | grep "General key info" -A 1 | tail -1 | awk '{print $1}' | sed 's/.*\///')
|
||||||
git config core.hooksPath .githooks
|
|
||||||
echo "→ Git hooks configured"
|
|
||||||
else
|
|
||||||
echo "→ No .githooks directory found, skipping"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# ═══════════════════════════════════════════════════════════
|
if [[ -n "$key_id" ]] && ! gpg --list-keys "$key_id" &>/dev/null; then
|
||||||
# 📂 CREATE NECESSARY DIRECTORIES
|
gpg --card-edit --batch --command-fd 0 <<<"fetch" &>/dev/null ||
|
||||||
# ═══════════════════════════════════════════════════════════
|
gpg --keyserver hkps://keys.openpgp.org --recv-keys "$key_id" &>/dev/null || true
|
||||||
echo "📂 Creating necessary directories..."
|
fi
|
||||||
|
else
|
||||||
|
log_error "YubiKey not detected"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
# Create .config directory if it doesn't exist
|
if git-crypt unlock 2>/dev/null; then
|
||||||
mkdir -p "$HOME/.config"
|
log_info "Repository unlocked successfully"
|
||||||
|
else
|
||||||
|
log_error "Failed to unlock repository"
|
||||||
|
log_info "Manual unlock required: cd $DOTFILES_DIR && git-crypt unlock"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
# Create common development directories
|
create_directories() {
|
||||||
mkdir -p "$HOME/Dev"
|
log_info "Creating necessary directories"
|
||||||
mkdir -p "$HOME/.local/bin"
|
mkdir -p "$HOME/.config" "$HOME/Dev" "$HOME/.local/bin"
|
||||||
|
}
|
||||||
|
|
||||||
echo
|
stow_packages() {
|
||||||
echo "# Install everything"
|
cd "$DOTFILES_DIR"
|
||||||
echo "stow */"
|
|
||||||
echo
|
|
||||||
echo "# Or install individual modules"
|
|
||||||
echo "stow zsh"
|
|
||||||
echo "stow nvim"
|
|
||||||
echo "stow sway"
|
|
||||||
echo
|
|
||||||
echo "Run these commands in: $DOTFILES_DIR"
|
|
||||||
|
|
||||||
# ═══════════════════════════════════════════════════════════
|
log_info "Available stow packages:"
|
||||||
# 📋 SUMMARY & NEXT STEPS
|
for dir in */; do
|
||||||
# ═══════════════════════════════════════════════════════════
|
if [[ -d "$dir" ]]; then
|
||||||
echo
|
log_info " ${dir%/}"
|
||||||
echo "📁 Locations:"
|
fi
|
||||||
echo " • Dotfiles: $DOTFILES_DIR"
|
done
|
||||||
echo " • Neovim config: $NVIM_CONFIG_DIR"
|
|
||||||
|
if confirm "Stow all packages?" "y"; then
|
||||||
|
log_info "Stowing all packages"
|
||||||
|
if stow */; then
|
||||||
|
log_info "All packages stowed successfully"
|
||||||
|
else
|
||||||
|
log_error "Some packages failed to stow. Check for conflicts"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
log_info "Skipping automatic stow. Run manually:"
|
||||||
|
log_info " cd $DOTFILES_DIR"
|
||||||
|
log_info " stow <package_name>"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
init_script
|
||||||
|
|
||||||
|
check_requirements
|
||||||
|
clone_dotfiles
|
||||||
|
handle_git_crypt
|
||||||
|
create_directories
|
||||||
|
stow_packages
|
||||||
|
|
||||||
|
log_info "Dotfiles location: $DOTFILES_DIR"
|
||||||
|
|
||||||
|
finish_script 0
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
||||||
|
|
211
runs/limine
211
runs/limine
|
@ -1,211 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
# NAME: Script to transition from systemd-boot to Limine bootloader
|
|
||||||
# REQUIRES: sudo
|
|
||||||
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
echo "do you confirm this transition?"
|
|
||||||
|
|
||||||
read -r -p "Are you sure? [y/N] " response
|
|
||||||
|
|
||||||
if [[ "$response" != "y" ]]; then
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
RED='\033[0;31m'
|
|
||||||
GREEN='\033[0;32m'
|
|
||||||
YELLOW='\033[1;33m'
|
|
||||||
BLUE='\033[0;34m'
|
|
||||||
NC='\033[0m'
|
|
||||||
|
|
||||||
print_status() { echo -e "${BLUE}[INFO]${NC} $1"; }
|
|
||||||
print_success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; }
|
|
||||||
print_warning() { echo -e "${YELLOW}[WARNING]${NC} $1"; }
|
|
||||||
print_error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
|
||||||
|
|
||||||
if [[ $EUID -ne 0 ]]; then
|
|
||||||
print_error "This script must be run as root (use sudo)"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ! command -v pacman &>/dev/null; then
|
|
||||||
print_error "This script is designed for Arch Linux / CachyOS systems"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
print_status "Starting transition from systemd-boot to Limine..."
|
|
||||||
|
|
||||||
ESP_PATH=""
|
|
||||||
if command -v bootctl &>/dev/null; then
|
|
||||||
ESP_PATH=$(bootctl --print-esp-path 2>/dev/null || echo "")
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ -z "$ESP_PATH" ]]; then
|
|
||||||
if [[ -d "/boot/EFI" ]]; then
|
|
||||||
ESP_PATH="/boot"
|
|
||||||
elif [[ -d "/efi/EFI" ]]; then
|
|
||||||
ESP_PATH="/efi"
|
|
||||||
else
|
|
||||||
print_error "Could not detect ESP path"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
print_success "ESP detected at: $ESP_PATH"
|
|
||||||
|
|
||||||
BACKUP_DIR="/root/bootloader-backup-$(date +%Y%m%d-%H%M%S)"
|
|
||||||
mkdir -p "$BACKUP_DIR"
|
|
||||||
|
|
||||||
[[ -d "$ESP_PATH/loader" ]] && cp -r "$ESP_PATH/loader" "$BACKUP_DIR/" 2>/dev/null || true
|
|
||||||
[[ -d "$ESP_PATH/EFI/systemd" ]] && cp -r "$ESP_PATH/EFI/systemd" "$BACKUP_DIR/" 2>/dev/null || true
|
|
||||||
efibootmgr -v >"$BACKUP_DIR/efibootmgr-backup.txt" 2>/dev/null || true
|
|
||||||
|
|
||||||
print_success "Backup created at: $BACKUP_DIR"
|
|
||||||
|
|
||||||
CURRENT_CMDLINE=""
|
|
||||||
if [[ -f "/etc/kernel/cmdline" ]]; then
|
|
||||||
CURRENT_CMDLINE=$(cat /etc/kernel/cmdline)
|
|
||||||
print_status "Found existing /etc/kernel/cmdline: $CURRENT_CMDLINE"
|
|
||||||
else
|
|
||||||
CURRENT_CMDLINE=$(cat /proc/cmdline | sed 's/BOOT_IMAGE=[^ ]* //')
|
|
||||||
print_status "Using current /proc/cmdline: $CURRENT_CMDLINE"
|
|
||||||
fi
|
|
||||||
|
|
||||||
print_status "Installing Limine and related packages..."
|
|
||||||
pacman -S --needed --noconfirm limine limine-snapper-sync limine-mkinitcpio-hook
|
|
||||||
print_success "Limine packages installed"
|
|
||||||
|
|
||||||
print_status "Installing Limine bootloader to ESP..."
|
|
||||||
mkdir -p "$ESP_PATH/EFI/Limine"
|
|
||||||
|
|
||||||
if [[ -f "/usr/share/limine/limine_x64.efi" ]]; then
|
|
||||||
cp /usr/share/limine/limine_x64.efi "$ESP_PATH/EFI/Limine/"
|
|
||||||
elif [[ -f "/usr/share/limine/BOOTX64.EFI" ]]; then
|
|
||||||
cp /usr/share/limine/BOOTX64.EFI "$ESP_PATH/EFI/Limine/limine_x64.efi"
|
|
||||||
else
|
|
||||||
print_error "Could not find Limine EFI files"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
print_success "Limine files installed to ESP"
|
|
||||||
|
|
||||||
print_status "Creating UEFI boot entry for Limine..."
|
|
||||||
ESP_DEVICE=$(df "$ESP_PATH" | tail -1 | awk '{print $1}')
|
|
||||||
ESP_DISK=$(echo "$ESP_DEVICE" | sed 's/[0-9]*$//')
|
|
||||||
ESP_PART_NUM=$(echo "$ESP_DEVICE" | sed 's/.*[^0-9]//')
|
|
||||||
|
|
||||||
efibootmgr -c -d "$ESP_DISK" -p "$ESP_PART_NUM" -L "Limine" -l "\\EFI\\Limine\\limine_x64.efi" || {
|
|
||||||
print_warning "Could not create UEFI boot entry automatically"
|
|
||||||
}
|
|
||||||
|
|
||||||
print_success "Limine UEFI boot entry created"
|
|
||||||
|
|
||||||
print_status "Configuring kernel command line..."
|
|
||||||
echo "$CURRENT_CMDLINE" >/etc/kernel/cmdline
|
|
||||||
print_success "Kernel command line configured: $CURRENT_CMDLINE"
|
|
||||||
|
|
||||||
print_status "Configuring Limine..."
|
|
||||||
[[ ! -f "/etc/default/limine" ]] && cat >/etc/default/limine <<EOF
|
|
||||||
SPACE_NUMBER=2
|
|
||||||
ENABLE_VERIFICATION=yes
|
|
||||||
BACKUP_THRESHOLD=8
|
|
||||||
BOOT_ORDER="*, *fallback, Snapshots"
|
|
||||||
ENABLE_SORT=no
|
|
||||||
ENABLE_LIMINE_FALLBACK=no
|
|
||||||
FIND_BOOTLOADERS=yes
|
|
||||||
ROOT_SNAPSHOTS_PATH="/@snapshots"
|
|
||||||
EOF
|
|
||||||
|
|
||||||
print_status "Creating custom Limine configuration..."
|
|
||||||
cat >"$ESP_PATH/limine.conf" <<'EOF'
|
|
||||||
### Read more at config document: https://github.com/limine-bootloader/limine/blob/trunk/CONFIG.md
|
|
||||||
timeout: 1
|
|
||||||
### Note: For "default_entry" to select a sub-entry within an OS menu, modify "/OS name" to "/+OS name" to keep its submenus visible.
|
|
||||||
default_entry: 2
|
|
||||||
#interface_branding_color: 3
|
|
||||||
interface_branding:
|
|
||||||
hash_mismatch_panic: no
|
|
||||||
term_palette: 1e1e2e;f38ba8;a6e3a1;f9e2af;89b4fa;f5c2e7;94e2d5;cdd6f4
|
|
||||||
term_palette_bright: 585b70;f38ba8;a6e3a1;f9e2af;89b4fa;f5c2e7;94e2d5;cdd6f4
|
|
||||||
term_background: 1e1e2e
|
|
||||||
term_foreground: cdd6f4
|
|
||||||
term_background_bright: 585b70
|
|
||||||
term_foreground_bright: cdd6f4
|
|
||||||
|
|
||||||
EOF
|
|
||||||
|
|
||||||
print_status "Generating Limine boot entries..."
|
|
||||||
limine-update
|
|
||||||
print_success "Limine configuration created"
|
|
||||||
|
|
||||||
print_status "Setting Limine as default boot option..."
|
|
||||||
LIMINE_ENTRY=$(efibootmgr | grep "Limine" | head -1 | cut -c5-8)
|
|
||||||
|
|
||||||
if [[ -n "$LIMINE_ENTRY" ]]; then
|
|
||||||
CURRENT_ORDER=$(efibootmgr | grep "BootOrder" | cut -d' ' -f2)
|
|
||||||
NEW_ORDER=$(echo "$CURRENT_ORDER" | sed "s/$LIMINE_ENTRY,//g" | sed "s/,$LIMINE_ENTRY//g" | sed "s/^$LIMINE_ENTRY$//g")
|
|
||||||
|
|
||||||
if [[ -n "$NEW_ORDER" ]]; then
|
|
||||||
efibootmgr -o "$LIMINE_ENTRY,$NEW_ORDER"
|
|
||||||
else
|
|
||||||
efibootmgr -o "$LIMINE_ENTRY"
|
|
||||||
fi
|
|
||||||
|
|
||||||
print_success "Limine set as default boot option"
|
|
||||||
else
|
|
||||||
print_warning "Could not find Limine boot entry to set as default"
|
|
||||||
fi
|
|
||||||
|
|
||||||
print_status "Removing systemd-boot components..."
|
|
||||||
|
|
||||||
# Remove systemd-boot UEFI entries
|
|
||||||
SYSTEMD_ENTRIES=$(efibootmgr | grep -i "Linux Boot Manager\|systemd" | cut -c5-8 || true)
|
|
||||||
if [[ -n "$SYSTEMD_ENTRIES" ]]; then
|
|
||||||
for entry in $SYSTEMD_ENTRIES; do
|
|
||||||
print_status "Removing UEFI boot entry: Boot$entry"
|
|
||||||
efibootmgr -b "$entry" -B || print_warning "Failed to remove boot entry $entry"
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Remove systemd-boot files from ESP
|
|
||||||
if [[ -d "$ESP_PATH/EFI/systemd" ]]; then
|
|
||||||
print_status "Removing systemd-boot EFI files..."
|
|
||||||
rm -rf "$ESP_PATH/EFI/systemd"
|
|
||||||
print_success "systemd-boot EFI files removed"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ -d "$ESP_PATH/loader" ]]; then
|
|
||||||
print_status "Removing systemd-boot configuration..."
|
|
||||||
rm -rf "$ESP_PATH/loader"
|
|
||||||
print_success "systemd-boot configuration removed"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ -f "$ESP_PATH/limine.conf" ]]; then
|
|
||||||
print_success "Limine configuration file exists"
|
|
||||||
else
|
|
||||||
print_error "Limine configuration file missing!"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ -f "$ESP_PATH/EFI/Limine/limine_x64.efi" ]]; then
|
|
||||||
print_success "Limine EFI bootloader exists"
|
|
||||||
else
|
|
||||||
print_error "Limine EFI bootloader missing!"
|
|
||||||
fi
|
|
||||||
|
|
||||||
sudo pacman -S snap-pac
|
|
||||||
sudo systemctl enable --now limine-snapper-sync.service
|
|
||||||
|
|
||||||
echo
|
|
||||||
print_success "TRANSITION COMPLETED SUCCESSFULLY!"
|
|
||||||
echo
|
|
||||||
print_status "Summary:"
|
|
||||||
echo " • Limine bootloader installed to: $ESP_PATH/EFI/Limine/"
|
|
||||||
echo " • Configuration file: $ESP_PATH/limine.conf"
|
|
||||||
echo " • Kernel command line: /etc/kernel/cmdline"
|
|
||||||
echo " • Backup created at: $BACKUP_DIR"
|
|
||||||
echo " • Boot order updated"
|
|
||||||
echo " • systemd-boot completely removed"
|
|
||||||
echo
|
|
||||||
print_warning "IMPORTANT: Reboot to test the new Limine setup!"
|
|
||||||
print_warning "systemd-boot has been completely removed - ensure Limine works before removing backup!"
|
|
||||||
print_success "Script completed. Please reboot when ready."
|
|
279
runs/limine_hibernate
Executable file
279
runs/limine_hibernate
Executable file
|
@ -0,0 +1,279 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# NAME: Configure hibernation for CachyOS with Limine bootloader
|
||||||
|
# REQUIRES: sudo interactive
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Source common functions
|
||||||
|
source "$(dirname "$0")/../common.sh" || {
|
||||||
|
echo "[ERROR] Could not source common.sh" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly LIMINE_CONFIG="/etc/default/limine"
|
||||||
|
readonly MKINITCPIO_CONFIG="/etc/mkinitcpio.conf"
|
||||||
|
|
||||||
|
check_requirements() {
|
||||||
|
local swap_uuid
|
||||||
|
swap_uuid=$(blkid -t TYPE=swap -o value -s UUID | head -n1)
|
||||||
|
|
||||||
|
if [[ -z "$swap_uuid" ]]; then
|
||||||
|
log_error "No swap partition found"
|
||||||
|
log_info "Please create a swap partition or swapfile before running this script"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_info "Found swap partition UUID: $swap_uuid"
|
||||||
|
readonly SWAP_UUID="$swap_uuid"
|
||||||
|
}
|
||||||
|
|
||||||
|
escape_for_sed() {
|
||||||
|
printf '%s\n' "$1" | sed 's/[[\.*^$()+?{|]/\\&/g'
|
||||||
|
}
|
||||||
|
|
||||||
|
show_diff_and_confirm() {
|
||||||
|
local file="$1"
|
||||||
|
local description="$2"
|
||||||
|
local temp_file="$3"
|
||||||
|
|
||||||
|
log_info "Proposed changes for $description"
|
||||||
|
log_info "File: $file"
|
||||||
|
echo
|
||||||
|
|
||||||
|
if command_exists colordiff; then
|
||||||
|
colordiff -u "$file" "$temp_file" || true
|
||||||
|
else
|
||||||
|
diff -u "$file" "$temp_file" || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo
|
||||||
|
confirm "Apply these changes?"
|
||||||
|
}
|
||||||
|
|
||||||
|
update_limine_config() {
|
||||||
|
log_info "Updating Limine configuration"
|
||||||
|
|
||||||
|
backup_file "$LIMINE_CONFIG"
|
||||||
|
|
||||||
|
local current_cmdline new_cmdline changes_made=false
|
||||||
|
current_cmdline=$(grep 'KERNEL_CMDLINE\[default\]' "$LIMINE_CONFIG" | cut -d'"' -f2)
|
||||||
|
log_info "Current kernel cmdline: $current_cmdline"
|
||||||
|
|
||||||
|
new_cmdline="$current_cmdline"
|
||||||
|
|
||||||
|
if [[ ! "$new_cmdline" =~ resume= ]]; then
|
||||||
|
new_cmdline="$new_cmdline resume=UUID=$SWAP_UUID"
|
||||||
|
log_info "Adding resume parameter"
|
||||||
|
changes_made=true
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! "$new_cmdline" =~ ipv6.disable= ]]; then
|
||||||
|
new_cmdline="$new_cmdline ipv6.disable=1"
|
||||||
|
log_info "Adding ipv6.disable parameter"
|
||||||
|
changes_made=true
|
||||||
|
fi
|
||||||
|
|
||||||
|
new_cmdline=$(echo "$new_cmdline" | sed 's/ */ /g' | sed 's/^ *//' | sed 's/ *$//')
|
||||||
|
|
||||||
|
if [[ "$changes_made" == "true" ]]; then
|
||||||
|
log_info "New kernel cmdline: $new_cmdline"
|
||||||
|
|
||||||
|
local new_cmdline_escaped temp_file
|
||||||
|
new_cmdline_escaped=$(escape_for_sed "$new_cmdline")
|
||||||
|
temp_file=$(mktemp)
|
||||||
|
|
||||||
|
sed "s|KERNEL_CMDLINE\[default\]=\".*\"|KERNEL_CMDLINE[default]=\"$new_cmdline_escaped\"|" "$LIMINE_CONFIG" >"$temp_file"
|
||||||
|
|
||||||
|
if show_diff_and_confirm "$LIMINE_CONFIG" "LIMINE CONFIGURATION" "$temp_file"; then
|
||||||
|
cp "$temp_file" "$LIMINE_CONFIG"
|
||||||
|
log_info "Limine configuration updated successfully"
|
||||||
|
rm "$temp_file"
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
log_info "Skipping Limine configuration update"
|
||||||
|
log_info "You can manually add: resume=UUID=$SWAP_UUID to your kernel cmdline"
|
||||||
|
rm "$temp_file"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
log_info "Limine configuration already contains required parameters"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
update_mkinitcpio_config() {
|
||||||
|
log_info "Updating mkinitcpio configuration"
|
||||||
|
|
||||||
|
backup_file "$MKINITCPIO_CONFIG"
|
||||||
|
|
||||||
|
if grep -q '^HOOKS=.*resume' "$MKINITCPIO_CONFIG"; then
|
||||||
|
log_info "Resume hook already present in mkinitcpio.conf"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_info "Adding resume hook to mkinitcpio.conf"
|
||||||
|
|
||||||
|
local current_hooks new_hooks temp_file
|
||||||
|
current_hooks=$(grep '^HOOKS=' "$MKINITCPIO_CONFIG")
|
||||||
|
log_info "Current HOOKS: $current_hooks"
|
||||||
|
|
||||||
|
new_hooks=$(echo "$current_hooks" | sed 's/filesystems/filesystems resume/' | sed 's/resume resume/resume/')
|
||||||
|
|
||||||
|
if [[ ! "$new_hooks" =~ resume ]]; then
|
||||||
|
new_hooks=$(echo "$current_hooks" | sed 's/)/ resume)/')
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_info "New HOOKS: $new_hooks"
|
||||||
|
|
||||||
|
local new_hooks_escaped
|
||||||
|
new_hooks_escaped=$(escape_for_sed "$new_hooks")
|
||||||
|
temp_file=$(mktemp)
|
||||||
|
|
||||||
|
sed "s|^HOOKS=.*|$new_hooks_escaped|" "$MKINITCPIO_CONFIG" >"$temp_file"
|
||||||
|
|
||||||
|
if show_diff_and_confirm "$MKINITCPIO_CONFIG" "MKINITCPIO CONFIGURATION" "$temp_file"; then
|
||||||
|
cp "$temp_file" "$MKINITCPIO_CONFIG"
|
||||||
|
log_info "mkinitcpio.conf updated successfully"
|
||||||
|
rm "$temp_file"
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
log_info "Skipping mkinitcpio.conf update"
|
||||||
|
log_info "You can manually add 'resume' to your HOOKS array"
|
||||||
|
rm "$temp_file"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
apply_system_changes() {
|
||||||
|
local limine_updated="$1"
|
||||||
|
local mkinitcpio_updated="$2"
|
||||||
|
local operations_needed=()
|
||||||
|
|
||||||
|
log_info "System updates required"
|
||||||
|
|
||||||
|
if [[ "$mkinitcpio_updated" == "true" ]]; then
|
||||||
|
operations_needed+=("Regenerate initramfs (mkinitcpio -P)")
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$limine_updated" == "true" ]]; then
|
||||||
|
operations_needed+=("Update Limine bootloader (limine-update)")
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ${#operations_needed[@]} -eq 0 ]]; then
|
||||||
|
log_info "No system updates needed - configuration is already up to date"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_info "The following operations need to be performed:"
|
||||||
|
for i in "${!operations_needed[@]}"; do
|
||||||
|
log_info " $((i + 1)). ${operations_needed[$i]}"
|
||||||
|
done
|
||||||
|
|
||||||
|
if ! confirm "Apply all pending system changes?" "y"; then
|
||||||
|
log_warn "Skipping system updates"
|
||||||
|
log_warn "Configuration files have been updated but system changes were not applied"
|
||||||
|
log_info "You will need to manually run:"
|
||||||
|
|
||||||
|
if [[ "$mkinitcpio_updated" == "true" ]]; then
|
||||||
|
log_info " mkinitcpio -P"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$limine_updated" == "true" ]]; then
|
||||||
|
log_info " limine-update"
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_warn "Hibernation will not work until these commands are executed"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_info "Applying system changes"
|
||||||
|
|
||||||
|
if [[ "$mkinitcpio_updated" == "true" ]]; then
|
||||||
|
log_info "Regenerating initramfs"
|
||||||
|
if ! mkinitcpio -P; then
|
||||||
|
log_error "Failed to regenerate initramfs"
|
||||||
|
log_info "Please check the configuration and run 'mkinitcpio -P' manually"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
log_info "Initramfs regenerated successfully"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$limine_updated" == "true" ]]; then
|
||||||
|
log_info "Updating Limine configuration"
|
||||||
|
if ! limine-update; then
|
||||||
|
log_error "Failed to update Limine bootloader"
|
||||||
|
log_info "Please run 'limine-update' manually"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
log_info "Limine bootloader updated successfully"
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
show_completion_summary() {
|
||||||
|
local limine_updated="$1"
|
||||||
|
local mkinitcpio_updated="$2"
|
||||||
|
|
||||||
|
log_info "Hibernation configuration completed successfully"
|
||||||
|
echo
|
||||||
|
log_info "Configuration details:"
|
||||||
|
log_info " - Swap UUID: $SWAP_UUID"
|
||||||
|
|
||||||
|
if [[ "$limine_updated" == "true" ]]; then
|
||||||
|
log_info " - Resume parameter added to kernel cmdline"
|
||||||
|
log_info " - IPv6 disabled (optional optimization)"
|
||||||
|
else
|
||||||
|
log_info " - Kernel cmdline already configured"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$mkinitcpio_updated" == "true" ]]; then
|
||||||
|
log_info " - Resume hook added to initramfs"
|
||||||
|
else
|
||||||
|
log_info " - Resume hook already present in initramfs"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo
|
||||||
|
log_info "Backups created:"
|
||||||
|
log_info " - $LIMINE_CONFIG.backup.*"
|
||||||
|
log_info " - $MKINITCPIO_CONFIG.backup.*"
|
||||||
|
echo
|
||||||
|
log_info "Next steps:"
|
||||||
|
log_info " 1. Reboot your system"
|
||||||
|
log_info " 2. Test hibernation with: systemctl hibernate"
|
||||||
|
log_info " 3. Wake up and verify everything works correctly"
|
||||||
|
echo
|
||||||
|
log_info "If you encounter issues, restore backups with:"
|
||||||
|
log_info " cp $LIMINE_CONFIG.backup.* $LIMINE_CONFIG"
|
||||||
|
log_info " cp $MKINITCPIO_CONFIG.backup.* $MKINITCPIO_CONFIG"
|
||||||
|
log_info " mkinitcpio -P && limine-update"
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
init_script
|
||||||
|
|
||||||
|
check_requirements
|
||||||
|
|
||||||
|
local limine_updated mkinitcpio_updated
|
||||||
|
|
||||||
|
if update_limine_config; then
|
||||||
|
limine_updated="true"
|
||||||
|
else
|
||||||
|
limine_updated="false"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if update_mkinitcpio_config; then
|
||||||
|
mkinitcpio_updated="true"
|
||||||
|
else
|
||||||
|
mkinitcpio_updated="false"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if apply_system_changes "$limine_updated" "$mkinitcpio_updated"; then
|
||||||
|
show_completion_summary "$limine_updated" "$mkinitcpio_updated"
|
||||||
|
finish_script 0
|
||||||
|
else
|
||||||
|
finish_script 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
55
runs/nvim
Executable file
55
runs/nvim
Executable file
|
@ -0,0 +1,55 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# NAME: Setup Neovim configuration
|
||||||
|
# REQUIRES: interactive
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Source common functions
|
||||||
|
source "$(dirname "$0")/../common.sh" || {
|
||||||
|
echo "[ERROR] Could not source common.sh" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly NVIM_REPO="https://github.com/marianozunino/nvim.git"
|
||||||
|
readonly NVIM_CONFIG_DIR="$HOME/.config/nvim"
|
||||||
|
|
||||||
|
check_requirements() {
|
||||||
|
if ! command_exists git; then
|
||||||
|
log_error "git is required but not installed"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
setup_neovim_config() {
|
||||||
|
log_info "Setting up Neovim configuration"
|
||||||
|
|
||||||
|
if [[ -d "$NVIM_CONFIG_DIR" ]]; then
|
||||||
|
local backup_dir="$NVIM_CONFIG_DIR.backup.$(date +%Y%m%d_%H%M%S)"
|
||||||
|
log_info "Backing up existing Neovim config to $backup_dir"
|
||||||
|
mv "$NVIM_CONFIG_DIR" "$backup_dir"
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_info "Cloning Neovim config to $NVIM_CONFIG_DIR"
|
||||||
|
git clone "$NVIM_REPO" "$NVIM_CONFIG_DIR"
|
||||||
|
|
||||||
|
cd "$NVIM_CONFIG_DIR"
|
||||||
|
|
||||||
|
if [[ -d ".githooks" ]]; then
|
||||||
|
git config core.hooksPath .githooks
|
||||||
|
chmod +x .githooks/* 2>/dev/null || true
|
||||||
|
log_info "Git hooks configured"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
init_script
|
||||||
|
|
||||||
|
check_requirements
|
||||||
|
setup_neovim_config
|
||||||
|
|
||||||
|
log_info "Neovim configuration: $NVIM_CONFIG_DIR"
|
||||||
|
|
||||||
|
finish_script 0
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
69
runs/paru
69
runs/paru
|
@ -1,26 +1,59 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# NAME: Installs paru
|
# NAME: Install paru AUR helper
|
||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
if command -v paru &>/dev/null; then
|
# Source common functions
|
||||||
echo "paru ya está instalado."
|
source "$(dirname "$0")/../common.sh" || {
|
||||||
exit 0
|
echo "[ERROR] Could not source common.sh" >&2
|
||||||
fi
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
echo "Instalando dependencias necesarias..."
|
check_requirements() {
|
||||||
sudo pacman -S --needed --noconfirm base-devel git
|
local required_commands=(git makepkg)
|
||||||
|
|
||||||
tmpdir=$(mktemp -d)
|
for cmd in "${required_commands[@]}"; do
|
||||||
echo "Temp dir: $tmpdir"
|
if ! command_exists "$cmd"; then
|
||||||
cd "$tmpdir"
|
log_error "Required command not found: $cmd"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
echo "Cloning paru..."
|
install_paru() {
|
||||||
git clone https://aur.archlinux.org/paru.git
|
if command_exists paru; then
|
||||||
cd paru
|
log_info "paru is already installed"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
echo "Compiling paru..."
|
log_info "Installing build dependencies"
|
||||||
makepkg -si --noconfirm
|
sudo pacman -S --needed --noconfirm base-devel git
|
||||||
|
|
||||||
echo "Cleaning up..."
|
local tmpdir
|
||||||
cd ..
|
tmpdir=$(mktemp -d)
|
||||||
rm -rf "$tmpdir"
|
log_info "Using temporary directory: $tmpdir"
|
||||||
|
|
||||||
|
cd "$tmpdir"
|
||||||
|
|
||||||
|
log_info "Cloning paru repository"
|
||||||
|
git clone https://aur.archlinux.org/paru.git
|
||||||
|
cd paru
|
||||||
|
|
||||||
|
log_info "Building and installing paru"
|
||||||
|
makepkg -si --noconfirm
|
||||||
|
|
||||||
|
log_info "Cleaning up temporary files"
|
||||||
|
cd /
|
||||||
|
rm -rf "$tmpdir"
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
init_script
|
||||||
|
|
||||||
|
check_requirements
|
||||||
|
install_paru
|
||||||
|
|
||||||
|
finish_script 0
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
||||||
|
|
152
runs/services
152
runs/services
|
@ -3,103 +3,99 @@
|
||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
echo "Enabling and configuring system services..."
|
# Source common functions
|
||||||
|
source "$(dirname "$0")/../common.sh" || {
|
||||||
|
echo "[ERROR] Could not source common.sh" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
# ═══════════════════════════════════════════════════════════
|
enable_networking_services() {
|
||||||
# 🌐 NETWORKING SERVICES
|
log_info "Enabling networking services"
|
||||||
# ═══════════════════════════════════════════════════════════
|
|
||||||
echo "Enabling networking services..."
|
|
||||||
|
|
||||||
# NetworkManager (main network management)
|
sudo systemctl enable --now NetworkManager.service
|
||||||
sudo systemctl enable --now NetworkManager.service
|
sudo systemctl enable --now bluetooth.service
|
||||||
|
sudo systemctl enable --now sshd.service
|
||||||
|
}
|
||||||
|
|
||||||
# Bluetooth
|
enable_audio_services() {
|
||||||
sudo systemctl enable --now bluetooth.service
|
log_info "Enabling audio services"
|
||||||
|
|
||||||
# SSH daemon
|
systemctl --user enable --now pipewire.service
|
||||||
sudo systemctl enable --now sshd.service
|
systemctl --user enable --now pipewire-pulse.service
|
||||||
|
systemctl --user enable --now wireplumber.service
|
||||||
|
}
|
||||||
|
|
||||||
# ═══════════════════════════════════════════════════════════
|
enable_printing_services() {
|
||||||
# 🔊 AUDIO SERVICES
|
log_info "Enabling printing services"
|
||||||
# ═══════════════════════════════════════════════════════════
|
|
||||||
echo "Enabling audio services..."
|
|
||||||
|
|
||||||
# PipeWire audio (replaces PulseAudio)
|
sudo systemctl enable --now cups.service
|
||||||
systemctl --user enable --now pipewire.service
|
}
|
||||||
systemctl --user enable --now pipewire-pulse.service
|
|
||||||
systemctl --user enable --now wireplumber.service
|
|
||||||
|
|
||||||
# ═══════════════════════════════════════════════════════════
|
configure_time_locale() {
|
||||||
# 🖨️ PRINTING SERVICES
|
log_info "Configuring time and locale services"
|
||||||
# ═══════════════════════════════════════════════════════════
|
|
||||||
echo "Enabling printing services..."
|
|
||||||
|
|
||||||
# CUPS printing system
|
if ! grep -q "en_US.UTF-8 UTF-8" /etc/locale.gen; then
|
||||||
sudo systemctl enable --now cups.service
|
echo "en_US.UTF-8 UTF-8" | sudo tee -a /etc/locale.gen
|
||||||
|
sudo locale-gen
|
||||||
|
fi
|
||||||
|
|
||||||
# ═══════════════════════════════════════════════════════════
|
echo "LANG=en_US.UTF-8" | sudo tee /etc/locale.conf
|
||||||
# ⏰ TIME & SCHEDULING SERVICES
|
log_info "System locale set to en_US.UTF-8"
|
||||||
# ═══════════════════════════════════════════════════════════
|
|
||||||
echo "Configuring time and scheduling services..."
|
|
||||||
|
|
||||||
echo "en_US.UTF-8 UTF-8" | sudo tee -a /etc/locale.gen
|
sudo timedatectl set-timezone America/Montevideo
|
||||||
sudo locale-gen
|
sudo timedatectl set-ntp true
|
||||||
|
sudo systemctl enable --now systemd-timesyncd.service
|
||||||
|
sudo systemctl enable --now cronie.service
|
||||||
|
}
|
||||||
|
|
||||||
# Set system locale
|
enable_security_services() {
|
||||||
echo "LANG=en_US.UTF-8" | sudo tee /etc/locale.conf
|
log_info "Enabling security services"
|
||||||
echo "→ System locale set to en_US.UTF-8"
|
|
||||||
|
|
||||||
sudo timedatectl set-timezone America/Montevideo
|
sudo systemctl enable --now ufw.service
|
||||||
|
sudo ufw --force enable
|
||||||
|
sudo ufw default deny incoming
|
||||||
|
sudo ufw default allow outgoing
|
||||||
|
}
|
||||||
|
|
||||||
# Enable NTP time synchronization
|
enable_backup_services() {
|
||||||
sudo timedatectl set-ntp true
|
log_info "Enabling backup services"
|
||||||
sudo systemctl enable --now systemd-timesyncd.service
|
|
||||||
|
|
||||||
# Cron daemon for scheduled tasks
|
if findmnt / -t btrfs &>/dev/null; then
|
||||||
sudo systemctl enable --now cronie.service
|
sudo systemctl enable --now snapper-timeline.timer
|
||||||
|
sudo systemctl enable --now snapper-cleanup.timer
|
||||||
|
log_info "Snapper enabled (BTRFS detected)"
|
||||||
|
else
|
||||||
|
log_info "Skipping Snapper (no BTRFS detected)"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
# ═══════════════════════════════════════════════════════════
|
enable_power_management() {
|
||||||
# 🔒 SECURITY & FIREWALL SERVICES
|
log_info "Enabling power management"
|
||||||
# ═══════════════════════════════════════════════════════════
|
|
||||||
echo "Enabling security services..."
|
|
||||||
|
|
||||||
# UFW firewall
|
sudo systemctl enable --now power-profiles-daemon.service
|
||||||
sudo systemctl enable --now ufw.service
|
}
|
||||||
|
|
||||||
# Enable basic firewall rules
|
enable_system_optimization() {
|
||||||
sudo ufw --force enable
|
log_info "Enabling system optimization"
|
||||||
sudo ufw default deny incoming
|
|
||||||
sudo ufw default allow outgoing
|
|
||||||
|
|
||||||
# ═══════════════════════════════════════════════════════════
|
sudo systemctl enable --now haveged.service
|
||||||
# 💾 BACKUP & SYNC SERVICES
|
sudo systemctl enable --now plocate-updatedb.timer
|
||||||
# ═══════════════════════════════════════════════════════════
|
sudo systemctl enable --now syncthing@forbi.service
|
||||||
echo "Enabling backup services..."
|
}
|
||||||
|
|
||||||
# Snapper for BTRFS snapshots (if using BTRFS)
|
main() {
|
||||||
if findmnt / -t btrfs &>/dev/null; then
|
init_script
|
||||||
sudo systemctl enable --now snapper-timeline.timer
|
|
||||||
sudo systemctl enable --now snapper-cleanup.timer
|
|
||||||
echo "→ Snapper enabled (BTRFS detected)"
|
|
||||||
else
|
|
||||||
echo "→ Skipping Snapper (no BTRFS detected)"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# ═══════════════════════════════════════════════════════════
|
enable_networking_services
|
||||||
# ⚡ POWER MANAGEMENT
|
enable_audio_services
|
||||||
# ═══════════════════════════════════════════════════════════
|
enable_printing_services
|
||||||
echo "Enabling power management..."
|
configure_time_locale
|
||||||
|
enable_security_services
|
||||||
|
enable_backup_services
|
||||||
|
enable_power_management
|
||||||
|
enable_system_optimization
|
||||||
|
|
||||||
# Power profiles daemon
|
finish_script 0
|
||||||
sudo systemctl enable --now power-profiles-daemon.service
|
}
|
||||||
|
|
||||||
# ═══════════════════════════════════════════════════════════
|
main "$@"
|
||||||
# 🔧 SYSTEM OPTIMIZATION
|
|
||||||
# ═══════════════════════════════════════════════════════════
|
|
||||||
echo "Enabling system optimization..."
|
|
||||||
|
|
||||||
# Haveged entropy daemon
|
|
||||||
sudo systemctl enable --now haveged.service
|
|
||||||
|
|
||||||
# Locate database updates
|
|
||||||
sudo systemctl enable --now plocate-updatedb.timer
|
|
||||||
|
|
42
runs/sudo
Executable file
42
runs/sudo
Executable file
|
@ -0,0 +1,42 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# NAME: Configure passwordless sudo for wheel group
|
||||||
|
# REQUIRES: sudo
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Source common functions
|
||||||
|
source "$(dirname "$0")/../common.sh" || {
|
||||||
|
echo "[ERROR] Could not source common.sh" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
check_requirements() {
|
||||||
|
if ! is_root; then
|
||||||
|
log_error "This script requires root privileges"
|
||||||
|
log_info "Run with: sudo $0"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
configure_sudo() {
|
||||||
|
local sudoers_file="/etc/sudoers.d/wheel"
|
||||||
|
local config_line="%wheel ALL=(ALL:ALL) NOPASSWD: ALL"
|
||||||
|
|
||||||
|
log_sudo "Configuring wheel group for passwordless sudo"
|
||||||
|
|
||||||
|
echo "$config_line" >"$sudoers_file"
|
||||||
|
chmod 440 "$sudoers_file"
|
||||||
|
|
||||||
|
log_info "Wheel group configured for passwordless sudo"
|
||||||
|
log_info "Users in wheel group can now use sudo without password"
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
init_script
|
||||||
|
|
||||||
|
check_requirements
|
||||||
|
configure_sudo
|
||||||
|
|
||||||
|
finish_script 0
|
||||||
|
}
|
||||||
|
main "$@"
|
Loading…
Add table
Add a link
Reference in a new issue