diff --git a/.bashrc b/.bashrc index 7f395bd..e1bcacb 100644 --- a/.bashrc +++ b/.bashrc @@ -109,35 +109,6 @@ if [ -f "$HOME/.nix-profile/etc/profile.d/hm-session-vars.sh" ]; then . "$HOME/.nix-profile/etc/profile.d/hm-session-vars.sh" fi -# zoxide if available -if command -v zoxide &> /dev/null; then - eval "$(zoxide init bash)" -fi - -# Check if we are running from zellij, if not then launch it -launch_zellij_conditionally() { - if [ -z "$ZELLIJ" ]; then - # Don't launch zellij in tmux, vscode, screen or zeditor. - if [ ! -t 1 ] || [ -n "$TMUX" ] || [ -n "$VSCODE_STABLE" ] || [ -n "$STY" ] || [ -n "$ZED_TERM" ]; then - return - fi - - # Launch zellij - zellij - - # Exit if zellij exits properly with a zero exit code - if [ $? -eq 0 ]; then - exit $? - fi - - echo "Zellij exited with a non-zero exit code, falling back to regular shell." - return - fi -} - -# Disabled for now, I don't like the way it behaves but I don't want to remove it either -# launch_zellij_conditionally - # Source ble.sh if it exists if [[ -f "${HOME}/.nix-profile/share/blesh/ble.sh" ]]; then source "${HOME}/.nix-profile/share/blesh/ble.sh" diff --git a/bin/actions/hello.py b/bin/actions/hello.py index c2a65fd..187e1af 100755 --- a/bin/actions/hello.py +++ b/bin/actions/hello.py @@ -12,9 +12,14 @@ from helpers.functions import printfe, logo, _rainbow_color, COLORS def get_last_ssh_login(): """Get information about the last SSH login""" try: - # Using lastlog2 to get the last login information - result = subprocess.run(['lastlog2', '-u', os.environ.get("USER", "")], + result = subprocess.run(['lastlog', '-u', os.environ.get("USER", "")], capture_output=True, text=True) + + # If lastlog didn't work try lastlog2 + if result.returncode != 0: + result = subprocess.run(['lastlog2', os.environ.get("USER", "")], + capture_output=True, text=True) + if result.returncode == 0: lines = result.stdout.strip().split('\n') if len(lines) >= 2: # Header line + data line diff --git a/bin/actions/update.py b/bin/actions/update.py index 85d2264..3e8fd84 100755 --- a/bin/actions/update.py +++ b/bin/actions/update.py @@ -28,15 +28,54 @@ def ensure_ansible_collections(): ] printfe("cyan", "Checking for required Ansible collections...") + + # Get list of installed collections using ansible-galaxy status, output = run_command(["ansible-galaxy", "collection", "list"], shell=False) - if not status: - printfe("red", "Failed to list Ansible collections") - return False - - # Check each required collection and install if missing + printfe("yellow", f"Failed to list Ansible collections: {output}") + printfe("yellow", "Will try to install all required collections.") + installed_collections = [] + else: + # Parse output to get installed collections + installed_collections = [] + + # Split output into lines and process + lines = output.splitlines() + collection_section = False + + for line in lines: + line = line.strip() + + # Skip empty lines + if not line: + continue + + # Check if we've reached the collection listing section + if line.startswith("Collection"): + collection_section = True + continue + + # Skip the separator line after the header + if collection_section and line.startswith("--"): + continue + + # Process collection entries + if collection_section and " " in line: + # Format is typically: "community.general 10.4.0" + parts = line.split() + if len(parts) >= 1: + collection_name = parts[0] + installed_collections.append(collection_name) + + # Check which required collections are missing + missing_collections = [] for collection in required_collections: - if collection not in output: + if collection not in installed_collections: + missing_collections.append(collection) + + # Install missing collections + if missing_collections: + for collection in missing_collections: printfe("yellow", f"Installing {collection} collection...") status, install_output = run_command(["ansible-galaxy", "collection", "install", collection], shell=False) if not status: @@ -44,6 +83,8 @@ def ensure_ansible_collections(): printfe("yellow", f"Continuing anyway, but playbook might fail if it requires {collection}") else: printfe("green", f"Successfully installed {collection} collection") + else: + printfe("green", "All required collections are already installed.") return True @@ -123,16 +164,7 @@ def main(): dotfiles_path = os.environ.get("DOTFILES_PATH", os.path.expanduser("~/.dotfiles")) hostname = os.uname().nodename username = os.environ.get("USER", os.environ.get("USERNAME", "user")) - - # Check if ansible is installed - status, _ = run_command(["which", "ansible-playbook"], shell=False) - if not status: - printfe("yellow", "Ansible is not installed, installing it with pipx...") - status, output = run_command(["pipx", "install", "--include-deps", "ansible", "ansible-lint"], shell=False) - if not status: - printfe("red", f"Failed to install Ansible: {output}") - return 1 - + # Ensure required collections are installed if not ensure_ansible_collections(): printfe("red", "Failed to ensure required Ansible collections are installed") @@ -140,6 +172,7 @@ def main(): printfe("cyan", "Running Ansible playbook...") ansible_cmd = [ + "/usr/bin/env", "ansible-playbook", "-i", f"{dotfiles_path}/config/ansible/inventory.ini", f"{dotfiles_path}/config/ansible/main.yml", diff --git a/bin/dotf b/bin/dotf index 9668d81..c4f6d9a 100755 --- a/bin/dotf +++ b/bin/dotf @@ -12,7 +12,9 @@ DOTFILES_PATH = DOTFILES_ROOT # For compatibility with the original scripts # Import helper functions sys.path.append(DOTFILES_BIN) -from helpers.functions import printfe, logo +from helpers.functions import printfe, ensure_dependencies + +ensure_dependencies() def run_script(script_path, args): """Run an action script with the given arguments""" diff --git a/bin/helpers/functions.py b/bin/helpers/functions.py index 1401f00..f00b97f 100644 --- a/bin/helpers/functions.py +++ b/bin/helpers/functions.py @@ -5,6 +5,7 @@ import sys import subprocess import math import random +import shutil try: import pyfiglet except ImportError: @@ -83,17 +84,28 @@ def logo(continue_after=False): def run_command(command, shell=False): """Run a shell command and return the result""" try: + if not shell and not shutil.which(command[0]): + return False, f"Command '{command[0]}' not found" + result = subprocess.run(command, shell=shell, check=True, text=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) return True, result.stdout.strip() except subprocess.CalledProcessError as e: return False, e.stderr.strip() + except FileNotFoundError: + return False, f"Command '{command[0]}' not found" def ensure_dependencies(): """Check and install required dependencies for the dotfiles system""" required_packages = [ 'pyfiglet', # For ASCII art generation ] + + # Check if pip is available + success, _ = run_command(['pip', '--version']) + if not success: + printfe("red", "Pip is required to install missing dependencies, try again after running `dotf update`") + return False missing_packages = [] for package in required_packages: @@ -109,16 +121,9 @@ def ensure_dependencies(): printfe("cyan", "Installing missing dependencies...") for package in missing_packages: printfe("blue", f"Installing {package}...") - success, output = run_command(['pip', 'install', '--user', package]) + success, output = run_command(['pip', 'install', '--user', package, '--break-system-packages']) if success: printfe("green", f"Successfully installed {package}") - # Attempt to import the newly installed package - if package == 'pyfiglet': - try: - global pyfiglet - import pyfiglet - except ImportError: - printfe("red", f"Failed to import {package} after installation") else: printfe("red", f"Failed to install {package}: {output}") diff --git a/config/ansible/tasks/global/docker.yml b/config/ansible/tasks/global/docker.yml index e4a22e3..121a3d6 100644 --- a/config/ansible/tasks/global/docker.yml +++ b/config/ansible/tasks/global/docker.yml @@ -14,6 +14,7 @@ - name: Install Docker CE ansible.builtin.shell: bash -c 'set -o pipefail && sh /tmp/get-docker.sh' args: + executable: /bin/bash creates: /usr/bin/docker when: docker_check.rc != 0 diff --git a/config/ansible/tasks/global/global.yml b/config/ansible/tasks/global/global.yml index b6b8d3e..4e70b1b 100644 --- a/config/ansible/tasks/global/global.yml +++ b/config/ansible/tasks/global/global.yml @@ -31,7 +31,6 @@ name: - git - vim - - pipx - trash-cli - curl - wget @@ -39,9 +38,5 @@ - python3 - python3-pip - python3-venv - - lastlog2 # Used for displaying last login information state: present become: true - -- name: Include pipx tasks - ansible.builtin.import_tasks: tasks/global/pipx.yml diff --git a/config/ansible/tasks/global/openssh-server.yml b/config/ansible/tasks/global/openssh-server.yml index 0f9e500..d81b417 100644 --- a/config/ansible/tasks/global/openssh-server.yml +++ b/config/ansible/tasks/global/openssh-server.yml @@ -12,7 +12,6 @@ group: root mode: '0644' validate: '/usr/sbin/sshd -t -f %s' - notify: Restart SSH service register: ssh_config - name: Ensure SSH service is enabled and running diff --git a/config/ansible/tasks/global/pipx.yml b/config/ansible/tasks/global/pipx.yml deleted file mode 100644 index 6fbb0ba..0000000 --- a/config/ansible/tasks/global/pipx.yml +++ /dev/null @@ -1,23 +0,0 @@ -- name: List installed pipx packages - ansible.builtin.shell: set -o pipefail && pipx list --short | awk '{print $1}' - register: installed_pipx_packages - changed_when: false - -- name: Define desired pipx packages - ansible.builtin.set_fact: - desired_pipx_packages: - - ansible - - ansible-lint - - shyaml - -- name: Install/Upgrade pipx packages - community.general.pipx: - name: "{{ item }}" - state: present - loop: "{{ desired_pipx_packages }}" - -- name: Remove undesired pipx packages - community.general.pipx: - name: "{{ item }}" - state: absent - loop: "{{ installed_pipx_packages.stdout_lines | difference(desired_pipx_packages) }}" diff --git a/config/ansible/tasks/global/symlinks.yml b/config/ansible/tasks/global/symlinks.yml index 161f983..7360955 100644 --- a/config/ansible/tasks/global/symlinks.yml +++ b/config/ansible/tasks/global/symlinks.yml @@ -14,6 +14,7 @@ - { src: "$DOTFILES_PATH/config/ssh/config", dest: "~/.ssh/config" } - { src: "$DOTFILES_PATH/config/ssh/config.d", dest: "~/.ssh/config.d" } - { src: "$DOTFILES_PATH/config/starship.toml", dest: "~/.config/starship.toml" } + - { src: "$DOTFILES_PATH/.bashrc", dest: "~/.bashrc.extra" } - name: Create gitconfig symlink ansible.builtin.file: diff --git a/config/ansible/tasks/servers/server.yml b/config/ansible/tasks/servers/server.yml index 83be04c..bc95a38 100644 --- a/config/ansible/tasks/servers/server.yml +++ b/config/ansible/tasks/servers/server.yml @@ -1,6 +1,56 @@ -- name: Ensure common packages are installed +- name: Ensure server common packages are installed ansible.builtin.package: name: - openssh-server state: present become: true + +- name: Check if /mnt/services is a mount point + ansible.builtin.shell: mountpoint -q /mnt/services || echo "not_mounted" + register: mnt_services_check + changed_when: false + ignore_errors: true + become: true + +- name: Check if services git repo already exists + ansible.builtin.stat: + path: "/mnt/services/.git" + register: git_dir_check + become: true + when: mnt_services_check.rc == 0 + +- name: Clean /mnt/services directory + ansible.builtin.shell: find /mnt/services -mindepth 1 -maxdepth 1 -exec rm -rf {} \; + become: true + when: mnt_services_check.rc == 0 and not git_dir_check.stat.exists|default(false) + +- name: Clone /mnt/services repository (initial clone) + ansible.builtin.git: + repo: "https://git.mvl.sh/vleeuwenmenno/services.git" + dest: "/mnt/services" + version: "main" + become: true + register: git_result + changed_when: git_result.changed + when: mnt_services_check.rc == 0 and not git_dir_check.stat.exists|default(false) + +- name: Update /mnt/services repository (if already exists) + ansible.builtin.git: + repo: "https://git.mvl.sh/vleeuwenmenno/services.git" + dest: "/mnt/services" + update: true + version: "main" + force: true + become: true + register: git_result + changed_when: git_result.changed + when: mnt_services_check.rc == 0 and git_dir_check.stat.exists|default(false) + +- name: Ensure /mnt/services ownership to users + ansible.builtin.file: + path: "/mnt/services" + group: "users" + recurse: true + state: directory + become: true + when: mnt_services_check.rc == 0 diff --git a/config/ansible/tasks/workstations/workstation.yml b/config/ansible/tasks/workstations/workstation.yml index 6035aa5..239a507 100644 --- a/config/ansible/tasks/workstations/workstation.yml +++ b/config/ansible/tasks/workstations/workstation.yml @@ -32,7 +32,7 @@ - name: Include MegaSync tasks ansible.builtin.import_tasks: tasks/workstations/megasync.yml -- name: Ensure common packages are installed +- name: Ensure workstation common packages are installed ansible.builtin.package: name: ###### THE FOLLOWING PACKAGES ARE DISABLED DUE TO MISSING ON UBUNTU REPOS ###### @@ -43,6 +43,15 @@ # Statistics HUD for gaming - mangohud # Used for VSCode Extensions - - nodejs + - nodejs + # File Manager + - nemo + # File Manager Extensions + - nemo-compare + - nemo-data + - nemo-fileroller + - nemo-font-manager + - nemo-gtkhash + - nemo-python state: present become: true diff --git a/config/home-manager/packages/common/bash.nix b/config/home-manager/packages/common/bash.nix index d788fdf..aa9aab9 100644 --- a/config/home-manager/packages/common/bash.nix +++ b/config/home-manager/packages/common/bash.nix @@ -4,8 +4,6 @@ let dotfilesPath = builtins.getEnv "DOTFILES_PATH"; in { - home.file.".bashrc.extra".source = "${dotfilesPath}/.bashrc"; - programs.bash = { enable = true; enableCompletion = true; diff --git a/config/home-manager/packages/common/packages.nix b/config/home-manager/packages/common/packages.nix index d9b860d..bb425ce 100644 --- a/config/home-manager/packages/common/packages.nix +++ b/config/home-manager/packages/common/packages.nix @@ -28,8 +28,7 @@ wget fastfetch - # Package management - pipx + # Package management devbox # Development SDKs/Toolkits @@ -49,7 +48,6 @@ # File and directory operations eza # Modern ls bat # Modern cat - zoxide # Smarter cd command broot # Interactive directory navigator du-dust # Modern du duf # Modern df diff --git a/config/ssh/config b/config/ssh/config index a43e15c..e108375 100644 --- a/config/ssh/config +++ b/config/ssh/config @@ -1,5 +1,5 @@ Host * - IdentityFile $DOTFILES_PATH/secrets/ssh_keys/mennos-2025.pem + IdentityFile ~/.dotfiles/secrets/ssh_keys/mennos-2025.pem IdentityAgent ~/.1password/agent.sock AddKeysToAgent yes ForwardAgent yes diff --git a/setup.sh b/setup.sh index 03db50d..724aecf 100755 --- a/setup.sh +++ b/setup.sh @@ -247,27 +247,10 @@ EOF fi } -ensure_pipx() { - if ! command -v pipx >/dev/null 2>&1; then - log_info "Installing pipx..." - - attempt_package_install "pipx" - - # On Arch Linux, install pipx using pacman - if command -v pacman >/dev/null 2>&1; then - sudo pacman -S python-pipx || die "Failed to install pipx" - fi - - # ensurepath - sudo pipx ensurepath || die "Failed to ensure pipx path" - fi -} - setup_ansible() { - ensure_pipx - - log_info "Installing Ansible..." - pipx install ansible || die "Failed to install Ansible" + attempt_package_install "ansible" + attempt_package_install "ansible-lint" + attempt_package_install "ansible-core" } check_command_availibility() {