Skip to content

Instantly share code, notes, and snippets.

@AlexAtkinson
Last active January 5, 2026 06:04
Show Gist options
  • Select an option

  • Save AlexAtkinson/27b12f4dfda31b1b74fcab3fc9a6d192 to your computer and use it in GitHub Desktop.

Select an option

Save AlexAtkinson/27b12f4dfda31b1b74fcab3fc9a6d192 to your computer and use it in GitHub Desktop.
PC Setup

PC Setup

Codified PC Setup.

Usage

source <(curl -s https://gist.githubusercontent.com/AlexAtkinson/27b12f4dfda31b1b74fcab3fc9a6d192/raw/init.sh)
[defaults]
timeout = 60
inventory = ~/.ansible/hosts
remote_tmp = ~/.ansible/tmp
forks = 150
transport = smart
gathering = smart
roles_path = ~/.ansible/roles
host_key_checking = False
log_path = /var/log/ansible.log
module_name = shell
fact_caching = jsonfile
fact_caching_connection = $HOME/.ansible/facts
fact_caching_timeout = 600
retry_files_save_path = ~/.ansible/retry
[ssh_connection]
pipelining = True
scp_if_ssh = True
[accelerate]
accelerate_port = 5099
accelerate_timeout = 30
accelerate_connect_timeout = 5.0
accelerate_daemon_timeout = 30
- name: "Apt: Safe upgrade"
ansible.builtin.apt:
upgrade: safe
update_cache: true
cache_valid_time: 600
- name: "Apt: Install Packages"
ansible.builtin.apt:
pkg:
- util-linux
- iptables-persistent
- apparmor-utils
- nvtop
- vim
- shellcheck
- openssl
- python3
- python3-pip
- python3-pytest
- curl
- wget
- whois
- netcat-openbsd
- tar
- gzip
- unzip
- bat
- bc
- yq
- jq
- less
- findutils
- ca-certificates
- apt-transport-https
- software-properties-common
- g++
- gccgo
- pkg-config
- make
- cmake
- extra-cmake-modules
- check
- valgrind
- build-essential
- libbz2-dev
- libcurl4-openssl-dev
- libjson-c-dev
- libmilter-dev
- libncurses5-dev
- libpcre2-dev
- libxml2-dev
- libasound2-dev
- qt6-base-dev
- qt6-base-dev-tools
- qt6-declarative-dev
- qt6-tools-dev
- qt6-scxml-dev
- qt6-svg-dev
- libkf6archive-dev
- libkf6config-dev
- libkf6crash-dev
- libkf6dbusaddons-dev
- libkf6globalaccel-dev
- libkf6i18n-dev
- libkf6iconthemes-dev
- libkf6kio-dev
- libkf6newstuff-dev
- libkf6statusnotifieritem-dev
- libkf6notifyconfig-dev
- libplasma-dev
- libkf6parts-dev
- wayland-protocols
- kwayland-dev
- mplayer
- vlc
- multitail
- mise
- nordvpn-gui
- wipe
- tmux
- btop
- cursor
- ansible
- ansible-lint
- dconf-cli
- xclip
- figlet
- krita
- gimp
# Mise
# ----
- name: "Apt: Download Mise Key"
ansible.builtin.get_url:
url: https://mise.jdx.dev/gpg-key.pub
dest: /tmp/mise-gpg-key.pub
mode: '0644'
when: "'/etc/apt/trusted.gpg.d/mise.gpg' is not exists"
- name: "Apt: Dearmor Mise Key"
ansible.builtin.shell: gpg --batch --dearmor -o /etc/apt/trusted.gpg.d/mise.gpg /tmp/mise-gpg-key.pub
args:
creates: /etc/apt/trusted.gpg.d/mise.gpg
when: "'/etc/apt/trusted.gpg.d/mise.gpg' is not exists"
- name: "Apt: Add Mise repository"
ansible.builtin.apt_repository:
repo: deb [signed-by=/etc/apt/trusted.gpg.d/mise.gpg arch=amd64] https://mise.jdx.dev/deb stable main
state: present
filename: mise
# NordVPN
# -------
- name: "NordVPN: Download Key"
ansible.builtin.get_url:
url: https://repo.nordvpn.com/gpg/nordvpn_public.asc
dest: /etc/apt/trusted.gpg.d/nordvpn_public.asc
mode: '0644'
when: "'/etc/apt/trusted.gpg.d/nordvpn_public.asc' is not exists"
- name: "NordVPN: Add Repository"
ansible.builtin.apt_repository:
repo: deb https://repo.nordvpn.com/deb/nordvpn/debian stable main
state: present
filename: nordvpn-app
# Opera
# -----
# Though Opera self-updates... Still doing this.
- name: "Opera: Check Latest Version"
shell: |
curl -sS https://blogs.opera.com/desktop/ | \
grep 'Stable update' | \
sed -nre 's/^[^0-9]*(([0-9]+\.)*[0-9]+).*/\1/p' | \
head -n 1
ignore_errors: yes
changed_when: false
register: opera_latest_version
- name: "Opera: Check installed version"
ansible.builtin.shell: opera --version | sed -nre 's/^[^0-9]*(([0-9]+\.)*[0-9]+).*/\1/p'
ignore_errors: true
changed_when: false
register: opera_installed_version
- name: "Opera: Report Versions"
ansible.builtin.debug:
msg: "Installed: {{ opera_installed_version.stdout }}, Latest: {{ opera_latest_version.stdout }}"
- name: "Opera: Download"
ansible.builtin.get_url:
url: "https://download5.operacdn.com/ftp/pub/opera/desktop/{{ opera_latest_version.stdout }}/linux/opera-stable_{{ opera_latest_version.stdout }}_amd64.deb"
dest: /tmp/opera-{{ opera_latest_version.stdout }}_amd64.deb
mode: '0644'
when: opera_latest_version.stdout != opera_latest_version.stdout
- name: "Opera: Install"
ansible.builtin.apt:
deb: /tmp/opera-{{ opera_latest_version.stdout }}_amd64.deb
when: opera_installed_version.stdout != opera_latest_version.stdout
ignore_errors: true
# Vivaldi
# -------
- name: "Vivaldi: Check installed version"
ansible.builtin.shell: vivaldi --version | sed -nre 's/^[^0-9]*(([0-9]+\.)*[0-9]+).*/\1/p'
ignore_errors: true
changed_when: false
register: installed_vivaldi_version
- name: "Vivaldi: Report version"
ansible.builtin.debug:
msg: "Installed: {{ installed_vivaldi_version.stdout }}"
- name: "Vivaldi: Download"
ansible.builtin.get_url:
url: "https://vivaldi.com/download/vivaldi-stable_amd64.deb"
dest: "{{ download_dir }}"
mode: '0644'
register: vivaldi_download
when: installed_vivaldi_version.stdout == ""
- name: "Vivaldi: Install"
ansible.builtin.apt:
deb: "{{ vivaldi_download.dest }}"
ignore_errors: true
when: installed_vivaldi_version.stdout == ""
# Chrome
# -------
- name: "Chrome: Check installed version"
ansible.builtin.shell: google-chrome --version | sed -nre 's/^[^0-9]*(([0-9]+\.)*[0-9]+).*/\1/p'
ignore_errors: true
changed_when: false
register: installed_chrome_version
- name: "Chrome: Report version"
ansible.builtin.debug:
msg: "Installed: {{ installed_chrome_version.stdout }}"
- name: "Chrome: Download"
ansible.builtin.get_url:
url: "https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb"
dest: "{{ download_dir }}"
mode: '0644'
register: chrome_download
when: installed_chrome_version.stdout == ""
- name: "Chrome: Install"
ansible.builtin.apt:
deb: "{{ chrome_download.dest }}"
ignore_errors: true
when: installed_chrome_version.stdout == ""
# VScode
# ------
- name: "VS Code: Check Latest Version"
shell: |
curl -sSkIL "https://code.visualstudio.com/sha/download?build=stable&os=linux-deb-x64" | \
grep Content-Disposition | \
cut -d'_' -f2 | \
cut -d'-' -f1
ignore_errors: yes
changed_when: false
register: vscode_latest_version
- name: "VS Code: Check Installed Version"
shell: |
/usr/bin/code --version | head -n1
ignore_errors: yes
changed_when: false
register: vscode_installed_version
- name: "VS Code: Report Versions"
debug:
msg: "Installed: {{ vscode_installed_version.stdout }}, Latest: {{ vscode_latest_version.stdout }}"
- name: "VS Code: Check Latest Version"
shell: |
curl -sSkIL "https://code.visualstudio.com/sha/download?build=stable&os=linux-deb-x64" | \
grep Content-Disposition | \
cut -d'_' -f2 | \
cut -d'-' -f1
ignore_errors: yes
changed_when: false
register: vscode_latest_version
- name: "VS Code: Check Installed Version"
shell: |
/usr/bin/code --no-sandbox --user-data-dir="$HOME/.vscode" --version | head -n1
ignore_errors: yes
changed_when: false
register: vscode_installed_version
- name: "VS Code: Report Versions"
debug:
msg: "Installed: {{ vscode_installed_version.stdout }}, Latest: {{ vscode_latest_version.stdout }}"
- name: "VS Code: Download"
ansible.builtin.get_url:
url: https://code.visualstudio.com/sha/download?build=stable&os=linux-deb-x64
dest: temp_assets_dir.path
mode: '0644'
register: vscode_deb_download
when: vscode_installed_version.stdout != vscode_latest_version.stdout
- name: "VS Code: Install"
ansible.builtin.apt:
deb: vscode_deb_download.dest
when: vscode_installed_version.stdout != vscode_latest_version.stdout
# Bash # TODO: Re-enable once $- bug is resolved in 5.3
# - name: "BASH - Check installed version"
# shell: /bin/bash -c "echo \$BASH_VERSION | sed -nre 's/^[^0-9]*(([0-9]+\.)*[0-9]+).*/\1/p'"
# ignore_errors: yes
# changed_when: false
# register: installed_bash_version
# - name: "BASH - Report version"
# debug:
# msg: "Installed Version: {{ installed_bash_version.stdout }}"
# - name: "BASH - Download bash-{{ bash_version_asset_label }}.tar.gz"
# ansible.builtin.get_url:
# #url: https://ftp.gnu.org/gnu/bash/bash-{{ bash_version_asset_label }}.tar.gz
# url: https://mirror.csclub.uwaterloo.ca/gnu/bash/bash-{{ bash_version_asset_label }}.tar.gz
# dest: /tmp/
# register: bash_download
# when: bash_version != installed_bash_version.stdout
# - name: "BASH - Unpack bash-{{ bash_version_asset_label }}.tar.gz"
# ansible.builtin.unarchive:
# src: "{{ bash_download.dest }}"
# dest: /tmp/
# when: bash_version != installed_bash_version.stdout
# - name: "BASH - Run ./configure"
# ansible.builtin.shell: ./configure
# args:
# chdir: /tmp/bash-{{ bash_version_asset_label }}
# creates: Makefile
# when: bash_version != installed_bash_version.stdout
# - name: "BASH - Run make"
# ansible.builtin.shell: make
# args:
# chdir: /tmp/bash-{{ bash_version_asset_label }}
# creates: Makefile
# when: bash_version != installed_bash_version.stdout
# - name: "BASH - Run make prefix=/ install"
# ansible.builtin.shell: make prefix=/ install
# args:
# chdir: /tmp/bash-{{ bash_version_asset_label }}
# when: bash_version != installed_bash_version.stdout
# ffmpeg
# ------
- name: "ffmpeg - Create directories"
ansible.builtin.file:
path: "{{ item }}"
state: directory
owner: "{{ ansible_env.SUDO_USER }}"
group: "{{ ansible_env.SUDO_USER }}"
mode: '0775'
when: item is not exists and item is defined
loop: "{{ ffmpeg_dirs }}"
- name: "ffmpeg - Check installed version"
shell: "cat {{ ffmpeg_dirs[0] }}/ffmpeg.version 2>/dev/null"
ignore_errors: yes
changed_when: false
register: installed_ffmpeg_version
- name: "ffmpeg - Check latest version"
shell: |
curl -Ss "https://api.github.com/repos/nwjs-ffmpeg-prebuilt/nwjs-ffmpeg-prebuilt/tags" \
| jq -r '.[].name' \
| grep -E "^[v]?(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$" \
| head -n 1
ignore_errors: yes
changed_when: false
register: latest_ffmpeg_version
- name: "ffmpeg - Report Versions"
debug:
msg: "Installed: {{ installed_ffmpeg_version.stdout}}, Latest: {{ latest_ffmpeg_version.stdout }}"
- name: "ffmpeg - Extract"
ansible.builtin.unarchive:
src: "https://github.com/nwjs-ffmpeg-prebuilt/nwjs-ffmpeg-prebuilt/releases/download/{{ latest_ffmpeg_version.stdout }}/{{ latest_ffmpeg_version.stdout }}-linux-x64.zip"
dest: "{{ item }}"
remote_src: yes
loop: "{{ ffmpeg_dirs }}"
when: installed_ffmpeg_version.stdout != latest_ffmpeg_version.stdout
- name: "ffmpeg - Create version files"
copy:
dest: "{{ item }}/ffmpeg.version"
owner: "{{ ansible_env.SUDO_USER }}"
group: "{{ ansible_env.SUDO_USER }}"
mode: '0775'
content: |
{{ latest_ffmpeg_version.stdout }}
loop: "{{ ffmpeg_dirs }}"
when: installed_ffmpeg_version.stdout != latest_ffmpeg_version.stdout
# yq
# --
- name: "yq - Check installed version"
shell: |
yq --version | awk '{print $NF}'
ignore_errors: yes
changed_when: false
register: installed_yq_version
- name: "yq - Check latest version"
shell: |
curl -Ss "https://api.github.com/repos/mikefarah/yq/tags" \
| jq -r '.[].name' \
| grep -E "^[v]?(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$" \
| head -n 1
ignore_errors: yes
changed_when: false
register: latest_yq_version
- name: "yq - Report Versions"
debug:
msg: "Installed: {{ installed_yq_version.stdout}}, Latest: {{ latest_yq_version.stdout }}"
# Downloads multiple times... It's fine for this small package. For larger packages, dl to /tmp/foo.
# Cause: Multiple '-C' args are not permitted with tar.
- name: "yq - Download and install"
ansible.builtin.unarchive:
src: "https://github.com/mikefarah/yq/releases/download/{{ latest_yq_version.stdout }}/yq_{{ ansible_system|lower }}_{{ 'amd64' if ansible_architecture == 'x86_64' else ansible_architecture }}.tar.gz"
dest: /usr/local/bin
remote_src: yes
extra_opts:
- --transform
- s/yq_linux_amd64/yq/
- -C
- /usr/local/bin
- ./yq_linux_amd64
when: installed_yq_version.stdout != latest_yq_version.stdout
- name: "yq - Download and install yq man page"
ansible.builtin.unarchive:
src: "https://github.com/mikefarah/yq/releases/download/{{ latest_yq_version.stdout }}/yq_{{ ansible_system|lower }}_{{ 'amd64' if ansible_architecture == 'x86_64' else ansible_architecture }}.tar.gz"
dest: /usr/share/man/man1
remote_src: yes
extra_opts:
- -C
- /usr/share/man/man1
- yq.1
# pCloud
# ------
- name: "pCloud - Ensure {{ pcloud_local_share_dir }} directory exists"
ansible.builtin.file:
path: "{{ pcloud_local_share_dir }}"
state: directory
owner: "{{ ansible_env.SUDO_USER }}"
group: "{{ ansible_env.SUDO_USER }}"
mode: '0775'
when: pcloud_local_share_dir is not exists
- name: "pCloud - Get Download URL"
shell: |
curl -sS 'https://api.pcloud.com/getpublinkdownload?code=XZNtR95ZctUIq8zYVD7eSKotwGMx7kDWVtzV' \
| jq -r '"https://" + .hosts[0] + .path'
register: pcloud_dl_url
- name: "pCloud - Report Download URL"
debug:
msg: "URL: {{ pcloud_dl_url.stdout }}"
- name: "pCloud - Download"
ansible.builtin.get_url:
url: "{{ pcloud_dl_url.stdout }}"
force: true
dest: "{{ local_bin_dir }}/pcloud"
owner: "{{ ansible_env.SUDO_USER }}"
group: "{{ ansible_env.SUDO_USER }}"
mode: u=rwx,g=rwx,o=rx
register: pcloud_download
- name: "pCloud - Download Icon"
ansible.builtin.get_url:
url: https://gist.githubusercontent.com/AlexAtkinson/86e7530f9a0b7c2744592e9fab54764b/raw/pcloud.svg
dest: /home/{{ ansible_env.SUDO_USER }}/.local/share/pCloud/pcloud.svg
owner: "{{ ansible_env.SUDO_USER }}"
group: "{{ ansible_env.SUDO_USER }}"
mode: u=rw,g=rw,o=r
# Defend against pcloud download process changes...
- name: "pCloud - Check Download File Type"
shell: file -b {{ pcloud_download.dest }} | cut -d' ' -f1
register: pcloud_download_check
failed_when:
- '"ELF" not in pcloud_download_check.stdout'
- name: "pCloud - Create Menu Entry"
copy:
dest: /home/{{ ansible_env.SUDO_USER }}/.local/share/applications/pcloud.desktop
owner: "{{ ansible_env.SUDO_USER }}"
group: "{{ ansible_env.SUDO_USER }}"
mode: '0775'
content: |
[Desktop Entry]
Icon="{{ local_applications_dir }}/pCloud/pcloud.svg"
Exec="{{ local_bin_dir }}/pcloud %u"
Version=1.0
Type=Application
Categories=Network
Name=pCloud
StartupWMClass=pcloud
MimeType=application/x-executable
X-GNOME-Autostart-enabled=true
StartupNotify=true
X-GNOME-Autostart-Delay=10
X-MATE-Autostart-Delay=10
X-KDE-autostart-after=panel
# qBittorrent
# -----------
- name: "qBittorrent - Check installed version"
shell: qBittorrent --version 2>/dev/null | cut -d' ' -f2
ignore_errors: yes
changed_when: false
register: qbittorrent_installed_version
- name: "qBittorrent - Check latest version"
shell: |
curl -s https://www.qbittorrent.org/download | \
grep "Current version" | \
awk '{print $NF}' | \
cut -d'<' -f1 | \
sed 's/^v//'
ignore_errors: yes
changed_when: false
register: qbittorrent_latest_version
- name: "qBittorrent - Report Versions"
debug:
msg: "Installed: {{ qbittorrent_installed_version.stdout }}, Latest: v{{ qbittorrent_latest_version.stdout }}"
- name: "qBittorrent - Create {{ qbittorrent_dir }} directory"
ansible.builtin.file:
path: "{{ qbittorrent_dir }}"
state: directory
owner: "{{ ansible_env.SUDO_USER }}"
group: "{{ ansible_env.SUDO_USER }}"
mode: '0775'
when: qbittorrent_dir is not exists
- name: "qBittorrent - Download"
ansible.builtin.get_url:
url: https://gigenet.dl.sourceforge.net/project/qbittorrent/qbittorrent-appimage/qbittorrent-{{ qbittorrent_latest_version.stdout }}/qbittorrent-{{ qbittorrent_latest_version.stdout }}_x86_64.AppImage
dest: /usr/local/bin/qBittorrent
owner: "{{ ansible_env.SUDO_USER }}"
group: "{{ ansible_env.SUDO_USER }}"
mode: u=rwx,g=rwx,o=rx
when: ( 'v' + qbittorrent_latest_version.stdout ) != qbittorrent_installed_version.stdout
- name: "qBittorrent - Download Icon"
ansible.builtin.get_url:
url: "{{ qbittorrent_icon_url }}"
dest: "{{ qbittorrent_icon }}"
owner: "{{ ansible_env.SUDO_USER }}"
group: "{{ ansible_env.SUDO_USER }}"
mode: u=rw,g=rw,o=r
when: qbittorrent_icon is not exists
- name: "qBittorrent - Create Menu Entry"
copy:
dest: "{{ qbittorrent_menu_entry }}"
owner: "{{ ansible_env.SUDO_USER }}"
group: "{{ ansible_env.SUDO_USER }}"
mode: '0775'
content: |
[Desktop Entry]
Icon={{ qbittorrent_icon }}
Exec="{{ local_bin_dir }}/qBittorrent %u"
Version=1.0
Type=Application
Terminal=false
Categories=Network
Name=qBittorrent
Keywords=web;internet;torrent
StartupWMClass=qbittorrent
MimeType=application/x-executable
X-GNOME-Autostart-enabled=false
StartupNotify=true
X-GNOME-Autostart-Delay=10
X-MATE-Autostart-Delay=10
X-KDE-autostart-after=panel
when: qbittorrent_menu_entry is not exists
# Libre Office
# ------------
- name: "Libre Office - Check installed version"
shell: |
libreoffice --version \
| head -n 1 \
| grep -oE "[v]?(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*(\.(0|[1-9][0-9]*))?)"
ignore_errors: yes
changed_when: false
register: installed_libreoffice_version
- name: "Libre Office - Check latest version"
shell: |
curl -sS http://downloadarchive.documentfoundation.org/libreoffice/old/latest/deb/x86_64/ \
| grep -o \"LibreOffice_.*_Linux_x86-64_deb.tar.gz\" \
| tr -d \" \
| grep -oE '[v]?(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*(\.(0|[1-9][0-9]*))?)'
ignore_errors: yes
changed_when: false
register: latest_libreoffice_version
- name: "Libre Office - Report Versions"
debug:
msg: "Installed: {{ installed_libreoffice_version.stdout }}, Latest: {{ latest_libreoffice_version.stdout }}"
# Zen Browser
# -----------
- name: "Zen Browser - Check installed version"
shell: |
zen-browser --version | sed -nre 's/^[^0-9]*(([0-9]+\.)*[0-9]+).*/\1/p'
ignore_errors: yes
changed_when: false
register: zen_installed_version
- name: "Zen Browser - Check latest version"
shell: |
curl -Ss "https://api.github.com/repos/zen-browser/desktop/tags" \
| jq -r '.[].name' \
| grep -E "^[v]?(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)[a-z]?$" \
| head -n 1
ignore_errors: yes
changed_when: false
register: zen_latest_version
- name: "Zen Browser - Report Versions"
debug:
msg: "Installed: {{ zen_installed_version.stdout}}, Latest: {{ zen_latest_version.stdout }}"
- name: "Create {{ zen_dir }} directory"
ansible.builtin.file:
path: "{{ zen_dir }}"
state: directory
owner: "{{ ansible_env.SUDO_USER }}"
group: "{{ ansible_env.SUDO_USER }}"
mode: '0775'
when: zen_dir is not exists
- name: "Zen Browser - Download"
ansible.builtin.get_url:
url: "https://github.com/zen-browser/desktop/releases/download/{{ zen_latest_version.stdout }}/zen-{{ ansible_architecture }}.AppImage"
dest: /usr/local/bin/zen
owner: "{{ ansible_env.SUDO_USER }}"
group: "{{ ansible_env.SUDO_USER }}"
mode: u=rwx,g=rwx,o=rx
when: zen_latest_version.stdout != zen_installed_version.stdout
- name: "Zen Browser - Download Icon"
ansible.builtin.get_url:
url: "{{ zen_icon_url }}"
dest: "{{ zen_icon }}"
owner: "{{ ansible_env.SUDO_USER }}"
group: "{{ ansible_env.SUDO_USER }}"
mode: u=rw,g=rw,o=r
when: zen_icon is not exists
- name: "Zen Browser - Create Menu Entry"
copy:
dest: "{{ zen_menu_entry }}"
owner: "{{ ansible_env.SUDO_USER }}"
group: "{{ ansible_env.SUDO_USER }}"
mode: '0775'
content: |
[Desktop Entry]
Name=Zen Browser
Comment=Experience tranquillity while browsing the web without people tracking you!
Keywords=web;browser;internet
Exec="{{ local_bin_dir }}/zen %u"
Icon={{ zen_icon }}
Terminal=false
StartupNotify=true
StartupWMClass=zen
NoDisplay=false
Type=Application
MimeType=text/html;text/xml;application/xhtml+xml;application/vnd.mozilla.xul+xml;text/mml;x-scheme-handler/http;x-scheme-handler/https;
Categories=Network;WebBrowser;
Actions=new-window;new-private-window;profile-manager-window;
[Desktop Action new-window]
Name=Open a New Window
Exec=$executable_path --new-window %u
[Desktop Action new-private-window]
Name=Open a New Private Window
Exec=$executable_path --private-window %u
[Desktop Action profile-manager-window]
Name=Open the Profile Manager
Exec=$executable_path --ProfileManager
when: zen_menu_entry is not exists
# kubectl
# -------
- name: "Kubectl Browser - Check installed version"
shell: |
kubectl version --client --output json | jq -r .clientVersion.gitVersion
ignore_errors: yes
changed_when: false
register: kubectl_installed_version
- name: "Kubectl - Check latest version"
shell: |
curl -sSL "https://dl.k8s.io/release/stable.txt"
ignore_errors: yes
changed_when: false
register: kubectl_latest_version
- name: "Kubectl - Report Versions"
debug:
msg: "Installed: {{ kubectl_installed_version.stdout}}, Latest: {{ kubectl_latest_version.stdout }}"
- name: "Kubectl - Download"
ansible.builtin.get_url:
url: "https://dl.k8s.io/release/{{ kubectl_latest_version.stdout }}/bin/linux/amd64/kubectl"
dest: /usr/local/bin/kubectl
owner: "{{ ansible_env.SUDO_USER }}"
group: "{{ ansible_env.SUDO_USER }}"
mode: u=rwx,g=rwx,o=rx
when: kubectl_latest_version.stdout != kubectl_installed_version.stdout
---
- name: "Install Packages"
hosts: localhost
gather_facts: true
vars:
download_dir: /tmp/ansible/downloads
assets_dir: /tmp/ansible/assets
# The private config url may be any private repo or "secret" gist and must contain
# a bash script which can be sourced.
private_config_git_url: [email protected]:AlexAtkinson/private_config.git
local_applications_dir: /home/{{ ansible_env.SUDO_USER }}/.local/share/applications
local_bin_dir: /home/{{ ansible_env.SUDO_USER }}/.local/bin
bash_version: 5.3.0
bash_version_asset_label: 5.3
ffmpeg_dirs:
- /usr/local/bin/ffmpeg
- /usr/lib/chromium-browser
- /usr/lib/x86_64-linux-gnu/opera
pcloud_local_share_dir: /home/{{ ansible_env.SUDO_USER }}/.local/share/pCloud
qbittorrent_dir: /home/{{ ansible_env.SUDO_USER }}/.local/share/qBittorrent
qbittorrent_icon: /home/{{ ansible_env.SUDO_USER }}/.local/share/qBittorrent/qBittorrent.svg
qbittorrent_menu_entry: /home/{{ ansible_env.SUDO_USER }}/.local/share/applications/qbittorrent.desktop
qbittorrent_icon_url: https://gist.githubusercontent.com/AlexAtkinson/f0bf8c89dda97ef42b5ba3575ab20363/raw/icon_qbittorrent.svg
zen_dir: /home/{{ ansible_env.SUDO_USER }}/.local/share/zen
zen_icon: /home/{{ ansible_env.SUDO_USER }}/.local/share/zen/zen.svg
zen_menu_entry: /home/{{ ansible_env.SUDO_USER }}/.local/share/applications/zen.desktop
zen_icon_url: https://gist.githubusercontent.com/AlexAtkinson/f0bf8c89dda97ef42b5ba3575ab20363/raw/zen-browser-icon.svg
tasks:
- name: "Ansible: Create temp directory for this build"
ansible.builtin.tempfile:
state: directory
prefix: "ansible_{{ now(utc=true, fmt='%Y-%m-%dT%H-%M-%SZ') }}_"
register: temp_dir
- name: "Ansible: Create download directory for use across multiple builds"
ansible.builtin.file:
path: "{{ download_dir }}"
state: directory
mode: '0755'
register: temp_assets_dir
- name: "Ansible: Create assets directory for use across multiple builds"
ansible.builtin.file:
path: "{{ assets_dir }}"
state: directory
mode: '0755'
register: temp_assets_dir
- name: "System: Create {{ local_applications_dir }} directory"
ansible.builtin.file:
path: "{{ local_applications_dir }}"
state: directory
owner: "{{ ansible_env.SUDO_USER }}"
group: "{{ ansible_env.SUDO_USER }}"
mode: '0775'
when: local_applications_dir is not exists
- name: "System: Create {{ local_bin_dir }} directory"
ansible.builtin.file:
path: "{{ local_bin_dir }}"
state: directory
owner: "{{ ansible_env.SUDO_USER }}"
group: "{{ ansible_env.SUDO_USER }}"
mode: '0775'
when: local_bin_dir is not exists
- name: "System: Configure rsyslog conf"
ansible.builtin.include_tasks:
file: ansible_rsyslog_config.yml
when: ansible_facts['os_family'] == 'Debian'
- name: "System: Configure Swap File"
ansible.builtin.include_tasks:
file: ansible_system_config.yml
when: ansible_facts['os_family'] == 'Debian'
- name: "Apt: Install Packages"
ansible.builtin.include_tasks:
file: ansible_apt.yml
when: ansible_facts['os_family'] == 'Debian'
- name: "Permissions"
ansible.builtin.include_tasks:
file: ansible_permissions.yml
- name: "Custom Installs"
ansible.builtin.include_tasks:
file: ansible_custom_installs.yml
- name: "Ansible Roles"
ansible.builtin.include_tasks:
file: ansible_roles.yml
handlers:
- name: restart rsyslog
ansible.builtin.service:
name: rsyslog.service
state: restarted
- name: "System - Ensure group 'docker' exists"
ansible.builtin.group:
name: docker
state: present
- name: "System - Add user '{{ ansible_env.SUDO_USER }}' to 'docker' group"
ansible.builtin.user:
name: '{{ ansible_env.SUDO_USER }}'
groups: docker
append: true
- name: "System - Ensure group 'nordvpn' exists"
ansible.builtin.group:
name: nordvpn
state: present
- name: "System - Add user '{{ ansible_env.SUDO_USER }}' to 'nordvpn' group"
ansible.builtin.user:
name: '{{ ansible_env.SUDO_USER }}'
groups: nordvpn
append: true
- name: Roles - Includes
ansible.builtin.include_role:
name: "{{ item }}"
loop:
- geerlingguy.docker
- name: "rsyslog - Application Excludes"
ansible.builtin.copy:
dest: /etc/rsyslog.d/10-app-excludes.conf
owner: "root"
group: "root"
mode: '0644'
content: |
# vivaldi
# -------
# Eject known bug entries
if $programname == 'vivaldi-stable' and $msg contains 'jffbochibkahlbbmanpmndnhmeliecah for an unknown event' then stop
if $programname == 'vivaldi-stable' and $msg contains 'invalid perl operator' then stop
force: true
notify:
- restart rsyslog
- name: "rsyslog - System Excludes"
ansible.builtin.copy:
dest: /etc/rsyslog.d/10-sys-excludes.conf.conf
owner: "root"
group: "root"
mode: '0644'
content: |
# NetworkManager
:msg,contains,"IPv6 is disabled on this device" then stop
:msg,contains,"unable to configure IPv6 route" then stop
:msg,contains,"no IPv6 link local address" then stop
force: true
notify:
- restart rsyslog
- name: "rsyslog - Nordvpn"
ansible.builtin.copy:
dest: /etc/rsyslog.d/20-nordvpn.conf
owner: "root"
group: "root"
mode: '0644'
content: |
if ($programname == "nordvpnd") then {
action(type="omfile" file="/var/log/nordvpn.log")
stop
}
force: true
notify:
- restart rsyslog
# Swap File
- name: "System: Configure Swap File"
shell: |
SWAPFILE=/swapfile
if [ ! -f $SWAPFILE ]; then
fallocate -l 2G $SWAPFILE
chmod 600 $SWAPFILE
mkswap $SWAPFILE
swapon $SWAPFILE
echo "$SWAPFILE none swap sw 0 0" >> /etc/fstab
fi
ignore_errors: yes
changed_when: false
register: installed_libreoffice_version
#!/usr/bin/env bash
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Clone the GIST and run setup.sh
#
# AUTHOR : Alex Atkinson
# AUTHOR_EMAIL :
# AUTHOR_GITHUB : https://github.com/AlexAtkinson
# AUTHOR_LINKEDIN : https://www.linkedin.com/in/alex--atkinson
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# shellcheck disable=SC1090
source <(curl -sS https://gist.githubusercontent.com/AlexAtkinson/8faea55ff26574b8ca96f0656f70b022/raw/common_func.sh)
GIST='27b12f4dfda31b1b74fcab3fc9a6d192'
TMP_DIR=$(mktemp -d)
TASK="Changing to temporary directory ${TMP_DIR}"; et
cd "$TMP_DIR" || return 1; rc 0 KILL
TASK="Cloning GIST ${GIST}"; et
git clone "[email protected]:${GIST}.git"; rc 0 KILL
TASK="Changing to GIST directory"; et
cd "$GIST" || return 1; rc 0 KILL
# shellcheck disable=SC2034
TASK="Running setup.sh"; et
./setup.sh; rc 0
#!/usr/bin/env bash
# shellcheck disable=2001
# ----------------------------------------------------------------------------------------------------------------------
#
# setup.sh
#
# SYNOPSIS
# Setup a local linux environment.
#
# ----------------------------------------------------------------------------------------------------------------------
# Traps
# ----------------------------------------------------------------------------------------------------------------------
trap cd - || true EXIT
# ----------------------------------------------------------------------------------------------------------------------
# Environment Settings
# ----------------------------------------------------------------------------------------------------------------------
set u
set -o pipefail
# ----------------------------------------------------------------------------------------------------------------------
# Variables
# ----------------------------------------------------------------------------------------------------------------------
THIS_SCRIPT="${0##*/}"
DIR_NAME="${PWD##*/}"
PARENT_DIR_PATH="${PWD%/*}"
PARENT_DIR_NAME="${PARENT_DIR_PATH##*/}"
LOG_TO_FILE="true"
[[ "$LOG_TO_FILE" == "true" ]] && LOG_FILE="$HOME/pc_setup.log"
ANSIBLE_LOCALHOST_WARNING=False
ANSIBLE_INVENTORY_UNPARSED_WARNING=False
CONFIG_REPO='[email protected]:AlexAtkinson/pc_configs_personal.git'
# ----------------------------------------------------------------------------------------------------------------------
# Functions
# ----------------------------------------------------------------------------------------------------------------------
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Helper for `date` -- format for logging
# Outputs:
# - Date format compliant with ISO8601 + nano to the third
# place in UTC. IE: 1970-01-01T00:00:00.000Z
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function dts() { date --utc +'%FT%T.%3NZ'; }
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Syslog style error code handling with colors to improve
# DX.
# Notes:
# - User friendly way of achieving consistent log and
# script feedback.
# - Named loggerx to avoid clobbering logger if present.
# - There is no 9th severity level in RFC5424.
# - Delimiter sequence: space-hyphen-space ( - )
# - Accepts multi-line logging.
# IE: loggerx INFO "This is a
# multi-line
# log entry"
# Globals:
# LOG_TO_FILE
# LOG_FILE
# Arguments:
# - $1 Log Level
# - $2- Message
# Depends On:
# - function: dts
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# shellcheck disable=2034
function loggerx() {
local MSG LOG RAW S C C_EMERGENCY C_ALERT C_CRITICAL \
C_ERROR C_WARNING C_NOTICE C_INFO C_DEBUG C_SUCCESS
# Reverse lookup dict
C_EMERGENCY='\e[01;30;41m' # EMERGENCY
C_ALERT='\e[01;31;43m' # ALERT
C_CRITICAL='\e[01;97;41m' # CRITICAL
C_ERROR='\e[01;31m' # ERROR
C_WARNING='\e[01;33m' # WARNING
C_NOTICE='\e[01;30;107m' # NOTICE
C_INFO='\e[01;39m' # INFO
C_DEBUG='\e[01;97;46m' # DEBUG
C_SUCCESS='\e[01;32m' # SUCCESS
# Color lookup & spacing
case $1 in
"EMERGENCY") C="C_${1}"; S=$(printf "%-38s" '') ;;
"ALERT") C="C_${1}"; S=$(printf "%-34s" '') ;;
"CRITICAL") C="C_${1}"; S=$(printf "%-37s" '') ;;
"ERROR") C="C_${1}"; S=$(printf "%-34s" '') ;;
"WARNING") C="C_${1}"; S=$(printf "%-36s" '') ;;
"NOTICE") C="C_${1}"; S=$(printf "%-35s" '') ;;
"INFO") C="C_${1}"; S=$(printf "%-33s" '') ;;
"DEBUG") C="C_${1}"; S=$(printf "%-34s" '') ;;
"SUCCESS") C="C_${1}"; S=$(printf "%-36s" '') ;;
esac
# Final formatting
MSG=$(echo -e "$(dts) - ${!C}${1}\e[0m - $(sed 's/ */ /g'<<<"${*:2}")")
LOG=$(sed -z 's/\n$//g'<<<"${MSG}" | sed -z "s/\n/\n${S}/g")
RAW="$THIS_SCRIPT - $1 - $(sed 's/ */ /g'<<<"${*:2}")"
# Main Operation
if [[ "$LOG_TO_FILE" == "true" ]]; then
echo "$LOG" | tee -a "$LOG_FILE"
else
echo "$LOG"
fi
echo "$RAW" | logger
}
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# The `et` and `rc` functions are used to provide a simple
# and consistent method of including basic exit code
# validation and logging.
# - et Echo Task
# - rc Result Check
# Arguments:
# $TASK
# Depends On:
# - function: loggerx
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
et() { loggerx INFO "TASK START: $TASK..."; }
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Arguments:
# - $1 The expected exit code.
# - $2 Passed in $? exit code.
# - $3 If KILL is passed then exit with passed exit
# code.
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
rc() {
local EXIT_CODE=$?
if [[ "$1" -eq "$EXIT_CODE" ]] ; then
loggerx SUCCESS "TASK END: $TASK."
else
loggerx ERROR "TASK END: $TASK (exit code: $EXIT_CODE -- expected code: $1)"
if [[ "$2" == "KILL" ]]; then
# If function, then return
if [[ "${FUNCNAME[*]:1}" != "" ]] && [[ "${FUNCNAME[-1]}" != "main" ]]; then
return "$EXIT_CODE"
fi
exit "$EXIT_CODE"
fi
fi
}
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Report the name of the OS distribution.
# Outputs:
# The NAME field from the /etc/*-release file
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function check_os_distro() {
DISTRO=$(awk -F= '$1=="NAME" { gsub(/"/,"",$2); print $2 }' /etc/*-release)
export DISTRO
echo "$DISTRO"
}
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Report the architecture of the system.
# Outputs:
# Print the system architecture as defined by `uname -m`
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function check_os_arch() {
case $(uname -m) in
arm64|aarch64) ARCH="ARM64" ;;
armhf|armv7*) ARCH="ARM32_COMPAT" ;;
armv8*) ARCH="ARM64_COMPAT" ;;
i*86*) ARCH="x86" ;;
amd64|x86_64*) ARCH="x64" ;;
*) ARCH="unknown: $ARCH" ;;
esac
export ARCH
echo "$ARCH"
}
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Report the OS Type
# Outputs:
# The type of system as defined by the $OSTYPE variable.
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function check_os_type() {
case "$OSTYPE" in
solaris*) OS_TYPE="SOLARIS" ;;
darwin*) OS_TYPE="OSX" ;;
linux*) OS_TYPE="LINUX" ;;
bsd*) OS_TYPE="BSD" ;;
msys*) OS_TYPE="WINDOWS" ;;
cygwin*) OS_TYPE="CYGWIN" ;;
*) OS_TYPE="unknown: $OSTYPE" ;;
esac;
export OS_TYPE
echo "$OS_TYPE"
}
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# DX friendly user prompts.
# Arguments:
# $1 Quoted prompt. IE: "Proceed?"
# $2 Default Option. IE: Y
# Outputs:
# Exit Code matching response.
# Example:
# ask "Proceed?" Y
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function ask {
while true; do
if [ "${2:-}" = "Y" ]; then
prompt="Y/n"
default=Y
elif [ "${2:-}" = "N" ]; then
prompt="y/N"
default=N
elif [ "${2:-}" = "Range" ]; then
prompt="${3:-}"
default=0
else
prompt="y/n"
default=
fi
read -rp $"$1 [$prompt]: " reply
if [ -z "$reply" ]; then
reply=$default
fi
case "$reply" in
Y*|y*|^[1-9][0-9]*$) return 0 ;;
N*|n*|0*) return 1 ;;
esac
done
}
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Check SSH Authentication to Github
# Notes:
# - As a function to facilitate use with `while`
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function check_ssh_authentication_to_github() {
TASK="Test SSH Authentication to GitHub"; et
ssh -o "StrictHostKeyChecking accept-new" -T [email protected] 2>&1 | grep -q 'successfully authenticated'
rc 0
}
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Check SSH Authentication to CONFIG_REPO
# Notes:
# - As a function to facilitate use with `while`
# Arguments:
# $CONFIG_REPO
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function check_ssh_authentication_to_config_repo() {
TASK="Test SSH Authentication to Private Config Repo"; et
git ls-remote "$CONFIG_REPO" >/dev/null 2>&1
rc 0
}
# ----------------------------------------------------------------------------------------------------------------------
# Main Operations
# ----------------------------------------------------------------------------------------------------------------------
TASK="Confirm script execution"
if ! ask "This script configures a Debian based OS to the preferences of Alex Atkinson. Proceed?" Y; then
false; rc 0 KILL
fi
# A
TASK="Confirm installation of private configurations"
if ! ask "Additionally install private configurations" N; then
false; rc 0
else
CONFIG_INSTALL=true
TASK="Prompt for configuration archive password"
read -rs -p "Enter configuration archive password: " CONFIG_ARCHIVE_PASS
rc 0
fi
TASK="Confirm sudo privilege"
loggerx WARNING "SUDO privilege required.
By proceeding you agree that you have reviewed the script content and trust the author.
Note specifically that this program is provided without any warranty or guarantee."
if ! ask "Confirm SUDO privilege" Y; then
false; rc 0 KILL
else
sudo true; rc 0
fi
TASK="Create SSH Key"; et
if [[ ! -f "$HOME/.ssh/id_ed25519" ]]; then
ssh-keygen -t ed25519 -C "[email protected]" -f "$HOME/.ssh/id_ed25519" -N "" -y
rc 0
else
loggerx NOTICE "SSH Key already exists. Skipping creation."
true; rc 0
fi
# Setup User bashrc
# ------------
TASK="Detect target rc file"; et
[[ -f $HOME/.bash_profile && ${SHELL##*/} =~ "bash" ]] && TARG="$HOME/.bash_profile" # MacOS Bash
[[ -f $HOME/.zshrc && ${SHELL##*/} =~ "zsh" ]] && TARG="$HOME/.zshrc" # MacOS ZSH
[[ -f $HOME/.bashrc && ${SHELL##*/} =~ "bash" ]] && TARG="$HOME/.bashrc" # Linux
rc 0 KILL
TARG_BACKUP="$TARG.$(date -u +"%FT%H-%M-%S").bak"
cp "$TARG" "$TARG_BACKUP" \
&& loggerx NOTICE "Your $TARG file has been backed up to $TARG_BACKUP!"
find "$HOME/" -type f -name "\.bashrc*.bak" | sort -r | tail -n +5 | tr '\n' '\0' | xargs -0 rm -f --
loggerx NOTICE "Only the five most recent $TARG.*.bak files have been kept."
TASK="Retrieve remote user bashrc file"; et
wget -q https://gist.githubusercontent.com/AlexAtkinson/bc765a0c143ab2bba69a738955d90abd/raw/.bashrc -O ~/.bashrc_user_gist; rc 0 KILL
START='# RCCTRLTEST - AUTOCONFIG START ----------------------------------------------------'
CONTENT=()
# shellcheck disable=SC2179
CONTENT+='# WARNING: Changes to this section will be overwritten.\n'
# shellcheck disable=SC2179
CONTENT+='# Last Updated: '"'$(date -u +"%FT%H-%M-%S")'"'\n'
# shellcheck disable=SC2179
CONTENT+='#\n'
# shellcheck disable=SC2179
CONTENT+='# NOTICE: Apply manual bashrc changes to ~\/.bashrc_user.\n'
# shellcheck disable=SC2179
CONTENT+='if \[ -f ~\/.bashrc_user \]; then\n'
# shellcheck disable=SC2179
CONTENT+=' . ~\/.bashrc_user\n'
# shellcheck disable=SC2179
CONTENT+='fi\n'
# shellcheck disable=SC2179
CONTENT+='# NOTICE: Apply remotely maintained bashrc changes to ~\/.bashrc_user_gist.\n'
# shellcheck disable=SC2179
CONTENT+='# Replace with any remote source as needed.\n'
# shellcheck disable=SC2179
CONTENT+='if \[ -f ~\/.bashrc_user_gist \]; then\n'
# shellcheck disable=SC2179
CONTENT+=' . ~\/.bashrc_user_gist\n'
# shellcheck disable=SC2179
CONTENT+='fi\n'
END='# RCCTRLTEST - AUTOCONFIG END ------------------------------------------------------'
TASK="Add control flags if not already present (user)"; et
if [[ $(grep -c "$START" "$TARG") == 0 ]]; then
echo -e "\n$START\n\n$END" >> "$TARG"; rc 0
else
true; rc 0
fi
TASK="Add control flags if not already present (root)"; et
if [[ $(grep -c "$START" "$TARG") == 0 ]]; then
echo -e "\n$START\n\n$END" >> "/root/.bashrc"; rc 0
else
true; rc 0
fi
# WARNING: This sed command is invalid on MacOS. Ensure gsed is installed and aliased to sed.
# sed: 1: "...": unterminated substitute in regular expression
sed -ni "/${START}/{p;:a;N;/${END}/!ba;s/.*\n/${CONTENT[*]}/};p" "$TARG"; rc 0 KILL
loggerx SUCCESS "Your $TARG file has been updated!"
loggerx INFO "Run 'source $TARG' to make your commands available in this terminal session."
# Update Operating System
# -----------------------
# Ensure this section runs only on linux hosts.
if [[ $(check_os_type) != "LINUX" ]]; then
loggerx ERROR "The remainder of this script supports LINUX only."
exit 1
fi
if [[ ! -f /etc/debian_version ]]; then
loggerx ERROR "The remainder of this script supports Debian based distributions only."
exit 1
fi
TASK="System: apt update"; et
sudo apt update; rc 0 KILL
TASK="System: apt full-upgrade"; et
sudo apt full-upgrade -y ; rc 0 KILL
TASK="Update Operating System"; et
true; rc 0
# Install Prerequisites
# ---------------
TASK="Install packages"; et
sudo apt install \
ansible \
jq
rc 0 KILL
# Ansible
# -------
TASK="Ansible: Install Roles"; et
sudo ansible-galaxy role install geerlingguy.docker; rc 0 KILL
TASK="Ansible: Install Apt Packages"; et
sudo ansible-playbook ansible_main.yml; rc 0
# Private Configuration
# ---------------------
if [[ "$CONFIG_INSTALL" == "true" ]]; then
while ! check_ssh_authentication_to_github; do
loggerx ERROR "Could not authenticate to Github.
Add you SSH key (~/.ssh/id_ed25519) to your GitHub account at https://github.com/settings/keys.
REF: https://docs.github.com/en/authentication/connecting-to-github-with-ssh/adding-a-new-ssh-key-to-your-github-account"
ask "Retry?" Y || break
done
if check_ssh_authentication_to_config_repo; then
TASK="Ansible: Install Private Configuration"; et
sudo ansible-playbook ansible_private.yml; rc 0 KILL
else
loggerx ERROR "You do not have access to $CONFIG_REPO"
fi
fi
# Cleanup
# -------
loggerx INFO "Setup is complete."
TASK="Confirm computer restart"; et
if ask "Would you like to restart now" N; then
shutdown -r 0
else
loggerx WARNING "Some applications may not function correctly without logging out/in, or restarting."
false; rc 0
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment