From 11c13b788c8a38aa08b31569cc3b15821fc40c40 Mon Sep 17 00:00:00 2001 From: drew Date: Mon, 18 May 2026 16:28:09 -0400 Subject: [PATCH] Add CLI standardization --- playbook.yml | 8 +- roles/adguard/templates/adguard.container.j2 | 1 + roles/caddy/templates/Caddyfile.j2 | 2 +- roles/cli_productivity/defaults/main.yml | 115 ++++++++++++ roles/cli_productivity/tasks/main.yml | 164 ++++++++++++++++++ .../cli_productivity/templates/config.fish.j2 | 92 ++++++++++ roles/cli_productivity/templates/gitconfig.j2 | 43 +++++ .../templates/starship.toml.j2 | 100 +++++++++++ roles/cli_productivity/templates/tmux.conf.j2 | 66 +++++++ roles/matrix_synapse/tasks/main.yml | 9 - ...lverr.container.j2 => byparr.container.j2} | 9 +- roles/vpn/templates/gluetun.container.j2 | 4 +- 12 files changed, 596 insertions(+), 17 deletions(-) create mode 100644 roles/cli_productivity/defaults/main.yml create mode 100644 roles/cli_productivity/tasks/main.yml create mode 100644 roles/cli_productivity/templates/config.fish.j2 create mode 100644 roles/cli_productivity/templates/gitconfig.j2 create mode 100644 roles/cli_productivity/templates/starship.toml.j2 create mode 100644 roles/cli_productivity/templates/tmux.conf.j2 rename roles/servarr/templates/{flaresolverr.container.j2 => byparr.container.j2} (52%) diff --git a/playbook.yml b/playbook.yml index 7a9cc70..01d3d2b 100644 --- a/playbook.yml +++ b/playbook.yml @@ -52,4 +52,10 @@ - base_os - firewall_base - container_runtime - - matrix_synapse \ No newline at end of file + - matrix_synapse + +- name: Configure RHEL machines + hosts: rhel + become: true + roles: + - cli_productivity \ No newline at end of file diff --git a/roles/adguard/templates/adguard.container.j2 b/roles/adguard/templates/adguard.container.j2 index c90dbd1..4885ea5 100644 --- a/roles/adguard/templates/adguard.container.j2 +++ b/roles/adguard/templates/adguard.container.j2 @@ -14,6 +14,7 @@ Volume={{ adguard_dir }}/conf:/opt/adguardhome/conf PublishPort=53:53/tcp PublishPort=53:53/udp +PublishPort=3000:3000/tcp [Service] Restart=always diff --git a/roles/caddy/templates/Caddyfile.j2 b/roles/caddy/templates/Caddyfile.j2 index fa83f3d..8a2b592 100644 --- a/roles/caddy/templates/Caddyfile.j2 +++ b/roles/caddy/templates/Caddyfile.j2 @@ -1,7 +1,7 @@ # Adguard {{ adguard_domain }} { tls internal - reverse_proxy {{ adguard_upstream }} + reverse_proxy {{ adguad_upstream }} } # QBittorrent diff --git a/roles/cli_productivity/defaults/main.yml b/roles/cli_productivity/defaults/main.yml new file mode 100644 index 0000000..3c4d47a --- /dev/null +++ b/roles/cli_productivity/defaults/main.yml @@ -0,0 +1,115 @@ +--- +# cli_productivity/defaults/main.yml +cli_user: "{{ container_user }}" +cli_group: "{{ cli_user }}" + +cli_install_epel: true +cli_use_epel: "{{ cli_install_epel | bool and ansible_os_family == 'RedHat' and ansible_distribution != 'Fedora' }}" + +cli_set_fish_as_default_shell: true + +cli_enable_starship: true +cli_enable_fish_config: true +cli_enable_tmux_config: true +cli_enable_ssh_config: false +cli_enable_git_config: true + +cli_editor: nano +cli_visual: nano + +cli_config_home: "/home/{{ cli_user }}" +cli_fish_config_dir: "{{ cli_config_home }}/.config/fish" +cli_starship_config_dir: "{{ cli_config_home }}/.config" +cli_ssh_config_dir: "{{ cli_config_home }}/.ssh" + +cli_base_packages: + - fish + - git + - curl + - wget + - unzip + - tar + - rsync + - tree + - tmux + - vim-enhanced + - nano + - jq + - bind-utils + - traceroute + - tcpdump + - lsof + - iotop + - htop + - ncdu + - mtr + - nmap-ncat + - python3 + - python3-pip + +cli_extra_packages: + - ripgrep + - fd-find + - bat + - fzf + - btop + +cli_optional_packages: + - zoxide + - duf + - httpie + - yq + - direnv + - just + - git-delta + - lazygit + - eza + - procs + - dust + - bottom + - sd + - xh + - age + - sops + - shellcheck + - shfmt + +cli_starship_install_method: "script" +cli_starship_bin_path: "/usr/local/bin/starship" + +cli_git_user_name: "" +cli_git_user_email: "" + +cli_fish_abbreviations: + - name: ll + expansion: "ls -lah" + - name: la + expansion: "ls -A" + - name: gs + expansion: "git status" + - name: ga + expansion: "git add" + - name: gc + expansion: "git commit" + - name: gp + expansion: "git push" + - name: gl + expansion: "git log --oneline --graph --decorate --all" + - name: k + expansion: "kubectl" + - name: tf + expansion: "terraform" + - name: dcu + expansion: "docker compose up -d" + - name: dcd + expansion: "docker compose down" + - name: pcu + expansion: "podman compose up -d" + - name: pcd + expansion: "podman compose down" + - name: ta + expansion: "tmux attach" + - name: tls + expansion: "tmux ls" + - name: tn + expansion: "tmux new -s" \ No newline at end of file diff --git a/roles/cli_productivity/tasks/main.yml b/roles/cli_productivity/tasks/main.yml new file mode 100644 index 0000000..c052ce5 --- /dev/null +++ b/roles/cli_productivity/tasks/main.yml @@ -0,0 +1,164 @@ +--- +# cli_productivity/tasks/main.yml +- name: Enable EPEL repository + become: true + ansible.builtin.dnf: + name: epel-release + state: latest + update_cache: true + when: cli_use_epel | bool + +- name: Refresh DNF metadata after enabling EPEL + become: true + ansible.builtin.command: dnf makecache + changed_when: false + when: cli_use_epel | bool + +- name: Install base CLI productivity packages + become: true + ansible.builtin.dnf: + name: "{{ cli_base_packages }}" + state: present + +- name: Install common CLI productivity packages + become: true + ansible.builtin.dnf: + name: "{{ cli_extra_packages }}" + state: present + update_cache: true + +- name: Install optional CLI productivity packages when available + become: true + ansible.builtin.dnf: + name: "{{ item }}" + state: present + loop: "{{ cli_optional_packages }}" + register: cli_optional_package_install + failed_when: false + +- name: Report optional CLI packages that could not be installed + ansible.builtin.debug: + msg: "Optional package was not installed: {{ item.item }} - {{ item.failures | default(item.msg | default('unknown reason')) }}" + loop: "{{ cli_optional_package_install.results | default([]) }}" + when: + - item.rc is defined + - item.rc != 0 + +- name: Check whether Starship is installed + ansible.builtin.stat: + path: "{{ cli_starship_bin_path }}" + register: cli_starship_binary + when: cli_enable_starship | bool + +- name: Install Starship prompt + become: true + ansible.builtin.shell: | + set -o pipefail + curl -fsSL https://starship.rs/install.sh | sh -s -- --yes --bin-dir "$(dirname {{ cli_starship_bin_path }})" + args: + executable: /bin/bash + when: + - cli_enable_starship | bool + - not cli_starship_binary.stat.exists + changed_when: true + +- name: Ensure fish config directory exists + become: true + ansible.builtin.file: + path: "{{ cli_fish_config_dir }}" + state: directory + owner: "{{ cli_user }}" + group: "{{ cli_group }}" + mode: "0755" + when: cli_enable_fish_config | bool + +- name: Ensure Starship config directory exists + become: true + ansible.builtin.file: + path: "{{ cli_starship_config_dir }}" + state: directory + owner: "{{ cli_user }}" + group: "{{ cli_group }}" + mode: "0755" + when: cli_enable_starship | bool + +- name: Deploy Starship config + become: true + ansible.builtin.template: + src: starship.toml.j2 + dest: "{{ cli_starship_config_dir }}/starship.toml" + owner: "{{ cli_user }}" + group: "{{ cli_group }}" + mode: "0644" + when: cli_enable_starship | bool + +- name: Deploy fish config + become: true + ansible.builtin.template: + src: config.fish.j2 + dest: "{{ cli_fish_config_dir }}/config.fish" + owner: "{{ cli_user }}" + group: "{{ cli_group }}" + mode: "0644" + when: cli_enable_fish_config | bool + +- name: Deploy tmux config + become: true + ansible.builtin.template: + src: tmux.conf.j2 + dest: "{{ cli_config_home }}/.tmux.conf" + owner: "{{ cli_user }}" + group: "{{ cli_group }}" + mode: "0644" + when: cli_enable_tmux_config | bool + +- name: Ensure SSH config directory exists + become: true + ansible.builtin.file: + path: "{{ cli_ssh_config_dir }}" + state: directory + owner: "{{ cli_user }}" + group: "{{ cli_group }}" + mode: "0700" + when: cli_enable_ssh_config | bool + +#- name: Deploy SSH client config +# become: true +# ansible.builtin.template: +# src: ssh_config.j2 +# dest: "{{ cli_ssh_config_dir }}/config" +# owner: "{{ cli_user }}" +# group: "{{ cli_group }}" +# mode: "0600" +# when: cli_enable_ssh_config | bool + +- name: Deploy Git config + become: true + ansible.builtin.template: + src: gitconfig.j2 + dest: "{{ cli_config_home }}/.gitconfig" + owner: "{{ cli_user }}" + group: "{{ cli_group }}" + mode: "0644" + when: cli_enable_git_config | bool + +- name: Get fish shell path + ansible.builtin.command: command -v fish + register: cli_fish_path + changed_when: false + when: cli_set_fish_as_default_shell | bool + +- name: Ensure fish is listed in /etc/shells + become: true + ansible.builtin.lineinfile: + path: /etc/shells + line: "{{ cli_fish_path.stdout }}" + state: present + when: cli_set_fish_as_default_shell | bool + +- name: Set fish as default shell + become: true + ansible.builtin.user: + name: "{{ cli_user }}" + shell: "{{ cli_fish_path.stdout }}" + when: cli_set_fish_as_default_shell | bool \ No newline at end of file diff --git a/roles/cli_productivity/templates/config.fish.j2 b/roles/cli_productivity/templates/config.fish.j2 new file mode 100644 index 0000000..86c97e0 --- /dev/null +++ b/roles/cli_productivity/templates/config.fish.j2 @@ -0,0 +1,92 @@ +# Managed by Ansible + +set -gx EDITOR {{ cli_editor | quote }} +set -gx VISUAL {{ cli_visual | quote }} +set -gx PAGER less + +# Better less defaults +set -gx LESS "-R --use-color -Dd+r -Du+b" + +# Local user bin paths +fish_add_path $HOME/.local/bin +fish_add_path /usr/local/bin + +# Starship prompt +if type -q starship + starship init fish | source +end + +# Smarter cd +if type -q zoxide + zoxide init fish | source +end + +# Direnv integration +if type -q direnv + direnv hook fish | source +end + +# fzf key bindings +if type -q fzf + fzf --fish | source 2>/dev/null +end + +# Prefer modern tools when available +if type -q eza + alias ls "eza --icons --group-directories-first" + alias ll "eza -lah --icons --group-directories-first --git" + alias tree "eza --tree --icons" +else if type -q exa + alias ls "exa --icons --group-directories-first" + alias ll "exa -lah --icons --group-directories-first --git" +else + alias ll "ls -lah" + alias la "ls -A" +end + +if type -q bat + alias cat "bat --paging=never" +end + +if type -q rg + alias grep "rg" +end + +if type -q fd + alias find "fd" +else if type -q fdfind + alias fd "fdfind" +end + +# Common navigation +alias .. "cd .." +alias ... "cd ../.." +alias .... "cd ../../.." + +# Git helpers +alias gst "git status" +alias glog "git log --oneline --graph --decorate --all" +alias gd "git diff" +alias gds "git diff --staged" + +# Tmux helpers +alias t "tmux" +alias ta "tmux attach" +alias tls "tmux ls" +alias tn "tmux new -s" + +# Podman helpers +alias p "podman" +alias pc "podman compose" +{% raw %} +alias pps "podman ps --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}'" +{% endraw %} + +# System helpers +alias ports "ss -tulpn" +alias myip "curl -4 ifconfig.me" + +# Fish abbreviations +{% for abbr in cli_fish_abbreviations %} +abbr --add {{ abbr.name | quote }} {{ abbr.expansion | quote }} +{% endfor %} \ No newline at end of file diff --git a/roles/cli_productivity/templates/gitconfig.j2 b/roles/cli_productivity/templates/gitconfig.j2 new file mode 100644 index 0000000..7f0d7c6 --- /dev/null +++ b/roles/cli_productivity/templates/gitconfig.j2 @@ -0,0 +1,43 @@ +# Managed by Ansible + +[user] +{% if cli_git_user_name | length > 0 %} + name = {{ cli_git_user_name }} +{% endif %} +{% if cli_git_user_email | length > 0 %} + email = {{ cli_git_user_email }} +{% endif %} + +[init] + defaultBranch = main + +[pull] + rebase = false + +[push] + autoSetupRemote = true + +[fetch] + prune = true + +[diff] + colorMoved = default + +[merge] + conflictstyle = zdiff3 + +[rerere] + enabled = true + +[color] + ui = auto + +[alias] + st = status + co = checkout + sw = switch + br = branch + ci = commit + lg = log --oneline --graph --decorate --all + last = log -1 HEAD --stat + unstage = restore --staged \ No newline at end of file diff --git a/roles/cli_productivity/templates/starship.toml.j2 b/roles/cli_productivity/templates/starship.toml.j2 new file mode 100644 index 0000000..0842599 --- /dev/null +++ b/roles/cli_productivity/templates/starship.toml.j2 @@ -0,0 +1,100 @@ +# Managed by Ansible + +add_newline = true +command_timeout = 1000 + +format = """ +$username\ +$hostname\ +$directory\ +$git_branch\ +$git_status\ +$container\ +$docker_context\ +$python\ +$nodejs\ +$golang\ +$rust\ +$terraform\ +$kubernetes\ +$cmd_duration\ +$line_break\ +$character""" + +[character] +success_symbol = "[➜](bold green)" +error_symbol = "[➜](bold red)" +vimcmd_symbol = "[❮](bold green)" + +[username] +show_always = false +style_user = "bold blue" +style_root = "bold red" +format = "[$user]($style) " + +[hostname] +ssh_only = true +style = "bold dimmed green" +format = "on [$hostname]($style) " + +[directory] +style = "bold cyan" +truncation_length = 4 +truncate_to_repo = false +read_only = " 󰌾" +format = "[$path]($style)[$read_only]($read_only_style) " + +[git_branch] +symbol = " " +style = "bold purple" +format = "on [$symbol$branch]($style) " + +[git_status] +style = "bold yellow" +format = "[$all_status$ahead_behind]($style) " + +[cmd_duration] +min_time = 1000 +style = "bold yellow" +format = "took [$duration]($style) " + +[container] +symbol = "⬢ " +style = "bold red" +format = "[$symbol$name]($style) " + +[docker_context] +symbol = " " +style = "blue bold" +format = "via [$symbol$context]($style) " + +[kubernetes] +disabled = false +symbol = "☸ " +style = "bold blue" +format = "[$symbol$context( \\($namespace\\))]($style) " + +[python] +symbol = " " +style = "yellow bold" +format = "via [$symbol$pyenv_prefix$version( \\($virtualenv\\))]($style) " + +[nodejs] +symbol = " " +style = "green bold" +format = "via [$symbol$version]($style) " + +[golang] +symbol = " " +style = "cyan bold" +format = "via [$symbol$version]($style) " + +[rust] +symbol = " " +style = "red bold" +format = "via [$symbol$version]($style) " + +[terraform] +symbol = " " +style = "purple bold" +format = "via [$symbol$workspace]($style) " \ No newline at end of file diff --git a/roles/cli_productivity/templates/tmux.conf.j2 b/roles/cli_productivity/templates/tmux.conf.j2 new file mode 100644 index 0000000..7f07983 --- /dev/null +++ b/roles/cli_productivity/templates/tmux.conf.j2 @@ -0,0 +1,66 @@ +# Managed by Ansible + +# General quality of life +set -g mouse on +set -g history-limit 50000 +set -g set-clipboard on +set -g renumber-windows on +set -g escape-time 10 +set -g focus-events on + +# Use 1-based indexes +set -g base-index 1 +setw -g pane-base-index 1 + +# Better terminal/color support +set -g default-terminal "tmux-256color" +set -ga terminal-overrides ",xterm-256color:Tc" + +# Vi-style copy mode +setw -g mode-keys vi + +# Status bar +set -g status on +set -g status-interval 5 +set -g status-position bottom +set -g status-style "bg=colour235,fg=colour250" + +set -g status-left-length 80 +set -g status-right-length 120 + +set -g status-left "#[fg=colour82,bold] #S #[fg=colour240]|#[default] " +set -g status-right "#[fg=colour245]%Y-%m-%d #[fg=colour82]%H:%M #[fg=colour240]| #[fg=colour39]#H " + +setw -g window-status-format "#[fg=colour245] #I:#W " +setw -g window-status-current-format "#[fg=colour235,bg=colour82,bold] #I:#W " + +# Pane borders +set -g pane-border-style "fg=colour240" +set -g pane-active-border-style "fg=colour82" + +# Easier reload +bind r source-file ~/.tmux.conf \; display-message "Reloaded ~/.tmux.conf" + +# Splits using current directory +bind | split-window -h -c "#{pane_current_path}" +bind - split-window -v -c "#{pane_current_path}" + +# New windows keep current directory +bind c new-window -c "#{pane_current_path}" + +# Vim-like pane movement +bind h select-pane -L +bind j select-pane -D +bind k select-pane -U +bind l select-pane -R + +# Resize panes +bind -r H resize-pane -L 5 +bind -r J resize-pane -D 5 +bind -r K resize-pane -U 5 +bind -r L resize-pane -R 5 + +# Copy mode bindings +bind-key -T copy-mode-vi v send-keys -X begin-selection +bind-key -T copy-mode-vi y send-keys -X copy-selection-and-cancel +bind-key -T copy-mode-vi Escape send-keys -X cancel \ No newline at end of file diff --git a/roles/matrix_synapse/tasks/main.yml b/roles/matrix_synapse/tasks/main.yml index 9639889..3573f16 100644 --- a/roles/matrix_synapse/tasks/main.yml +++ b/roles/matrix_synapse/tasks/main.yml @@ -17,15 +17,6 @@ name: selinux_containers tasks_from: labels -#- name: Ensure container app config directories are owned by container UID -# become: true -# file: -# path: "{{ synapse_config_dir }}" -# state: directory -# owner: "{{ container_user }}" -# group: "{{ container_group }}" -# recurse: true - - name: Deploy homesever configuration template template: src: homeserver.yaml.j2 diff --git a/roles/servarr/templates/flaresolverr.container.j2 b/roles/servarr/templates/byparr.container.j2 similarity index 52% rename from roles/servarr/templates/flaresolverr.container.j2 rename to roles/servarr/templates/byparr.container.j2 index 05cd7ad..294bddb 100644 --- a/roles/servarr/templates/flaresolverr.container.j2 +++ b/roles/servarr/templates/byparr.container.j2 @@ -1,15 +1,16 @@ [Unit] -Description=Flaresolverr Cloudflare Solver +Description=Byparr - Cloudflare Bypass Proxy Requires=gluetun.service After=gluetun.service [Container] -ContainerName=flaresolverr -Image=ghcr.io/flaresolverr/flaresolverr:latest +ContainerName=byparr +Image=ghcr.io/thephaseless/byparr:latest Environment=TZ=America/New_York Environment=LOG_LEVEL=info Network=container:gluetun +Restart=always [Install] -WantedBy=default.target \ No newline at end of file +WantedBy=multi-user.target \ No newline at end of file diff --git a/roles/vpn/templates/gluetun.container.j2 b/roles/vpn/templates/gluetun.container.j2 index 0531c13..05a3035 100644 --- a/roles/vpn/templates/gluetun.container.j2 +++ b/roles/vpn/templates/gluetun.container.j2 @@ -17,7 +17,7 @@ AddDevice=/dev/net/tun:/dev/net/tun # 6767 Bazarr # 7878 Radarr # 8080 qBittorrent -# 8191 Flaresolverr +# 8191 Byparr # 8989 Sonarr # 9696 Prowlarr @@ -30,11 +30,11 @@ PublishPort=9696:9696 Environment=VPN_SERVICE_PROVIDER=mullvad Environment=VPN_TYPE=wireguard +Environment=SERVER_COUNTRIES={{ vpn_countries }} Environment=WIREGUARD_PRIVATE_KEY={{ vault_vpn_private_key }} Environment=WIREGUARD_ADDRESSES={{ vpn_addresses }} Environment=FIREWALL_ENABLED=on -#Environment=FIREWALL_ENABLED_DISABLING_IT_SHOOTS_YOU_IN_YOUR_FOOT=off Environment=DNS_ENABLED=false Environment=FIREWALL_INPUT_PORTS=6767,7878,8080,8191,8989,9696