aptupdate
· 273 B · Text
Raw
#!/bin/sh
sudo apt update
sudo DEBIAN_FRONTEND=noninteractive apt -y upgrade
sudo DEBIAN_FRONTEND=noninteractive apt-get -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" dist-upgrade
sudo apt -y autoremove
sudo apt -y autoclean
sudo apt -y clean
| 1 | #!/bin/sh |
| 2 | sudo apt update |
| 3 | sudo DEBIAN_FRONTEND=noninteractive apt -y upgrade |
| 4 | sudo DEBIAN_FRONTEND=noninteractive apt-get -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" dist-upgrade |
| 5 | sudo apt -y autoremove |
| 6 | sudo apt -y autoclean |
| 7 | sudo apt -y clean |
firstroot.sh
· 6.5 KiB · Bash
Raw
#!/usr/bin/env bash
# Root shell setup for Ubuntu
# Run this script as root.
set -euo pipefail
if [ "$(id -u)" -ne 0 ]; then
echo "Please run as root." >&2
exit 1
fi
# =========================
# Settings
# =========================
PREFER_EDITOR="${PREFER_EDITOR:-vim}"
PACKAGES=(bash-completion vim less)
msg() { printf "\033[1;32m[OK]\033[0m %s\n" "$*"; }
warn() { printf "\033[1;33m[WARN]\033[0m %s\n" "$*"; }
err() { printf "\033[1;31m[ERR]\033[0m %s\n" "$*" >&2; }
backup_file() {
local f="$1"; [ -f "$f" ] || return 0
local ts; ts="$(date +%Y%m%d-%H%M%S)"
cp -a "$f" "${f}.bak.${ts}"
msg "Backup: ${f}.bak.${ts}"
}
append_once() {
# $1=file, $2=unique tag line, $3=payload
local file="$1" tag="$2" payload="$3"
grep -Fqx "$tag" "$file" 2>/dev/null && return 0
printf "\n%s\n%s\n" "$tag" "$payload" >>"$file"
}
# =========================
# 0) Ensure base packages (no sudo needed)
# =========================
if command -v apt-get >/dev/null 2>&1; then
export DEBIAN_FRONTEND=noninteractive
apt-get update -y || true
apt-get install -y "${PACKAGES[@]}" || warn "Some packages failed to install; continuing."
else
warn "apt-get not found; skipping package install."
fi
# =========================
# 1) Target files
# =========================
ROOT_HOME="/root"
BASHRC="${ROOT_HOME}/.bashrc"
INPUTRC="${ROOT_HOME}/.inputrc"
[ -f "$BASHRC" ] || touch "$BASHRC"
[ -f "$INPUTRC" ] || touch "$INPUTRC"
backup_file "$BASHRC"
backup_file "$INPUTRC"
# =========================
# 2) force_color_prompt=yes
# =========================
if grep -Eq '^[[:space:]]*#?[[:space:]]*force_color_prompt[[:space:]]*=' "$BASHRC"; then
sed -i '0,/^[[:space:]]*#\{0,1\}[[:space:]]*force_color_prompt[[:space:]]*=.*/s//force_color_prompt=yes/' "$BASHRC"
else
sed -i '1iforce_color_prompt=yes' "$BASHRC"
fi
msg "Enabled force_color_prompt=yes for root."
# =========================
# 3) bash-completion
# =========================
COMPLETION_TAG="# >>> chatgpt-root: bash-completion enable >>>"
COMPLETION_BLOCK=$(cat <<'EOF'
# >>> chatgpt-root: bash-completion enable >>>
if [ -n "$BASH_VERSION" ] && ! shopt -oq posix; then
if [ -f /usr/share/bash-completion/bash_completion ]; then
. /usr/share/bash-completion/bash_completion
elif [ -f /etc/bash_completion ]; then
. /etc/bash_completion
fi
fi
# <<< chatgpt-root: bash-completion enable <<<
EOF
)
append_once "$BASHRC" "$COMPLETION_TAG" "$COMPLETION_BLOCK"
msg "Ensured bash-completion is sourced for root."
# =========================
# 4) History: timestamps + merge + safer defaults
# =========================
HIST_TAG="# >>> chatgpt-root: history settings >>>"
HIST_BLOCK=$(cat <<'EOF'
# >>> chatgpt-root: history settings >>>
# Timestamps (YYYY-MM-DD HH:MM:SS)
export HISTTIMEFORMAT='%F %T '
# Safer history: ignore duplicates & commands starting with a space; remove duplicate older entries
export HISTCONTROL=ignoredups:ignorespace:erasedups
export HISTSIZE=300000
export HISTFILESIZE=600000
# Merge history across concurrent shells
shopt -s histappend
if [[ -n "${PROMPT_COMMAND:-}" ]]; then
case "$PROMPT_COMMAND" in
*'history -a; history -c; history -r'*) : ;;
*) PROMPT_COMMAND="history -a; history -c; history -r; $PROMPT_COMMAND" ;;
esac
else
PROMPT_COMMAND='history -a; history -c; history -r'
fi
# <<< chatgpt-root: history settings <<<
EOF
)
append_once "$BASHRC" "$HIST_TAG" "$HIST_BLOCK"
msg "Enabled history timestamps and merging for root."
# =========================
# 5) Prompt, aliases, shopt, editor/pager (root-flavored)
# =========================
QOL_TAG="# >>> chatgpt-root: QoL shell block >>>"
QOL_BLOCK=$(cat <<'EOF'
# >>> chatgpt-root: QoL shell block >>>
# Minimal Git branch helper (fast, no heavy libs)
__chatgpt_git_branch() {
local b
b=$(git rev-parse --abbrev-ref HEAD 2>/dev/null) || return 0
[ "$b" = "HEAD" ] && b=$(git rev-parse --short HEAD 2>/dev/null)
[ -n "$b" ] && printf ' (%s)' "$b"
}
# Prompt for root: show exit code when non-zero; root@host in red; cwd in magenta; git branch
__chatgpt_set_ps1_root() {
local exit="$?"
local red="\[\e[31m\]" green="\[\e[32m\]" yellow="\[\e[33m\]" blue="\[\e[34m\]" magenta="\[\e[35m\]" cyan="\[\e[36m\]" reset="\[\e[0m\]"
local code=""
[ "$exit" -ne 0 ] && code="${red}↯${exit}${reset} "
PS1="${code}${red}\u${reset}@${blue}\h${reset}:${magenta}\w${reset}\$(__chatgpt_git_branch)${cyan}# ${reset}"
}
case "${PROMPT_COMMAND:-}" in
*"__chatgpt_set_ps1_root"*) : ;;
"") PROMPT_COMMAND="__chatgpt_set_ps1_root" ;;
*) PROMPT_COMMAND="__chatgpt_set_ps1_root; $PROMPT_COMMAND" ;;
esac
# Useful shopt toggles
shopt -s checkwinsize cdspell autocd globstar
# Root-friendly aliases
alias ls='ls --color=auto -F --group-directories-first'
alias ll='ls -lah'
alias la='ls -A'
alias grep='grep --color=auto'
alias df='df -h'
alias free='free -h'
alias watchd='watch -n1 -d'
alias cp='cp -i'
alias mv='mv -i'
alias rm='rm -I' # prompt once if >3 files
alias ..='cd ..'
alias ...='cd ../..'
# Prefer modern tools if present
command -v batcat >/dev/null 2>&1 && alias bat='batcat'
command -v bat >/dev/null 2>&1 && alias cat='bat --paging=never'
command -v lsd >/dev/null 2>&1 && alias ls='lsd'
# Defaults
export EDITOR="${EDITOR:-vim}"
export VISUAL="$EDITOR"
export PAGER="${PAGER:-less}"
export LESS='-R'
export GPG_TTY="$(tty 2>/dev/null || true)"
# Security hygiene: stricter umask for root
umask 027
# <<< chatgpt-root: QoL shell block <<<
EOF
)
append_once "$BASHRC" "$QOL_TAG" "$QOL_BLOCK"
msg "Added root QoL prompt/aliases/shopt/editor block."
# Ensure the preferred editor is set explicitly
if grep -Fq 'export EDITOR=' "$BASHRC"; then
sed -i "0,/export EDITOR=.*/s//export EDITOR=\"${PREFER_EDITOR}\"/" "$BASHRC"
else
echo "export EDITOR=\"${PREFER_EDITOR}\"" >> "$BASHRC"
fi
msg "Default EDITOR for root set to ${PREFER_EDITOR}"
# =========================
# 6) Readline tweaks for root
# =========================
INPUT_TAG="# >>> chatgpt-root: readline tweaks >>>"
INPUT_BLOCK=$(cat <<'EOF'
# >>> chatgpt-root: readline tweaks >>>
set show-all-if-ambiguous on
set menu-complete-display-prefix on
set colored-stats on
set mark-symlinked-directories on
set completion-ignore-case on
set completion-map-case on
"\e[A": history-search-backward
"\e[B": history-search-forward
# <<< chatgpt-root: readline tweaks <<<
EOF
)
append_once "$INPUTRC" "$INPUT_TAG" "$INPUT_BLOCK"
msg "Improved /root/.inputrc completion/behavior."
# =========================
# Done
# =========================
msg "Root shell setup complete. Open a NEW root shell or run: source /root/.bashrc"
| 1 | #!/usr/bin/env bash |
| 2 | # Root shell setup for Ubuntu |
| 3 | # Run this script as root. |
| 4 | set -euo pipefail |
| 5 | |
| 6 | if [ "$(id -u)" -ne 0 ]; then |
| 7 | echo "Please run as root." >&2 |
| 8 | exit 1 |
| 9 | fi |
| 10 | |
| 11 | # ========================= |
| 12 | # Settings |
| 13 | # ========================= |
| 14 | PREFER_EDITOR="${PREFER_EDITOR:-vim}" |
| 15 | PACKAGES=(bash-completion vim less) |
| 16 | |
| 17 | msg() { printf "\033[1;32m[OK]\033[0m %s\n" "$*"; } |
| 18 | warn() { printf "\033[1;33m[WARN]\033[0m %s\n" "$*"; } |
| 19 | err() { printf "\033[1;31m[ERR]\033[0m %s\n" "$*" >&2; } |
| 20 | |
| 21 | backup_file() { |
| 22 | local f="$1"; [ -f "$f" ] || return 0 |
| 23 | local ts; ts="$(date +%Y%m%d-%H%M%S)" |
| 24 | cp -a "$f" "${f}.bak.${ts}" |
| 25 | msg "Backup: ${f}.bak.${ts}" |
| 26 | } |
| 27 | |
| 28 | append_once() { |
| 29 | # $1=file, $2=unique tag line, $3=payload |
| 30 | local file="$1" tag="$2" payload="$3" |
| 31 | grep -Fqx "$tag" "$file" 2>/dev/null && return 0 |
| 32 | printf "\n%s\n%s\n" "$tag" "$payload" >>"$file" |
| 33 | } |
| 34 | |
| 35 | # ========================= |
| 36 | # 0) Ensure base packages (no sudo needed) |
| 37 | # ========================= |
| 38 | if command -v apt-get >/dev/null 2>&1; then |
| 39 | export DEBIAN_FRONTEND=noninteractive |
| 40 | apt-get update -y || true |
| 41 | apt-get install -y "${PACKAGES[@]}" || warn "Some packages failed to install; continuing." |
| 42 | else |
| 43 | warn "apt-get not found; skipping package install." |
| 44 | fi |
| 45 | |
| 46 | # ========================= |
| 47 | # 1) Target files |
| 48 | # ========================= |
| 49 | ROOT_HOME="/root" |
| 50 | BASHRC="${ROOT_HOME}/.bashrc" |
| 51 | INPUTRC="${ROOT_HOME}/.inputrc" |
| 52 | [ -f "$BASHRC" ] || touch "$BASHRC" |
| 53 | [ -f "$INPUTRC" ] || touch "$INPUTRC" |
| 54 | backup_file "$BASHRC" |
| 55 | backup_file "$INPUTRC" |
| 56 | |
| 57 | # ========================= |
| 58 | # 2) force_color_prompt=yes |
| 59 | # ========================= |
| 60 | if grep -Eq '^[[:space:]]*#?[[:space:]]*force_color_prompt[[:space:]]*=' "$BASHRC"; then |
| 61 | sed -i '0,/^[[:space:]]*#\{0,1\}[[:space:]]*force_color_prompt[[:space:]]*=.*/s//force_color_prompt=yes/' "$BASHRC" |
| 62 | else |
| 63 | sed -i '1iforce_color_prompt=yes' "$BASHRC" |
| 64 | fi |
| 65 | msg "Enabled force_color_prompt=yes for root." |
| 66 | |
| 67 | # ========================= |
| 68 | # 3) bash-completion |
| 69 | # ========================= |
| 70 | COMPLETION_TAG="# >>> chatgpt-root: bash-completion enable >>>" |
| 71 | COMPLETION_BLOCK=$(cat <<'EOF' |
| 72 | # >>> chatgpt-root: bash-completion enable >>> |
| 73 | if [ -n "$BASH_VERSION" ] && ! shopt -oq posix; then |
| 74 | if [ -f /usr/share/bash-completion/bash_completion ]; then |
| 75 | . /usr/share/bash-completion/bash_completion |
| 76 | elif [ -f /etc/bash_completion ]; then |
| 77 | . /etc/bash_completion |
| 78 | fi |
| 79 | fi |
| 80 | # <<< chatgpt-root: bash-completion enable <<< |
| 81 | EOF |
| 82 | ) |
| 83 | append_once "$BASHRC" "$COMPLETION_TAG" "$COMPLETION_BLOCK" |
| 84 | msg "Ensured bash-completion is sourced for root." |
| 85 | |
| 86 | # ========================= |
| 87 | # 4) History: timestamps + merge + safer defaults |
| 88 | # ========================= |
| 89 | HIST_TAG="# >>> chatgpt-root: history settings >>>" |
| 90 | HIST_BLOCK=$(cat <<'EOF' |
| 91 | # >>> chatgpt-root: history settings >>> |
| 92 | # Timestamps (YYYY-MM-DD HH:MM:SS) |
| 93 | export HISTTIMEFORMAT='%F %T ' |
| 94 | # Safer history: ignore duplicates & commands starting with a space; remove duplicate older entries |
| 95 | export HISTCONTROL=ignoredups:ignorespace:erasedups |
| 96 | export HISTSIZE=300000 |
| 97 | export HISTFILESIZE=600000 |
| 98 | # Merge history across concurrent shells |
| 99 | shopt -s histappend |
| 100 | if [[ -n "${PROMPT_COMMAND:-}" ]]; then |
| 101 | case "$PROMPT_COMMAND" in |
| 102 | *'history -a; history -c; history -r'*) : ;; |
| 103 | *) PROMPT_COMMAND="history -a; history -c; history -r; $PROMPT_COMMAND" ;; |
| 104 | esac |
| 105 | else |
| 106 | PROMPT_COMMAND='history -a; history -c; history -r' |
| 107 | fi |
| 108 | # <<< chatgpt-root: history settings <<< |
| 109 | EOF |
| 110 | ) |
| 111 | append_once "$BASHRC" "$HIST_TAG" "$HIST_BLOCK" |
| 112 | msg "Enabled history timestamps and merging for root." |
| 113 | |
| 114 | # ========================= |
| 115 | # 5) Prompt, aliases, shopt, editor/pager (root-flavored) |
| 116 | # ========================= |
| 117 | QOL_TAG="# >>> chatgpt-root: QoL shell block >>>" |
| 118 | QOL_BLOCK=$(cat <<'EOF' |
| 119 | # >>> chatgpt-root: QoL shell block >>> |
| 120 | # Minimal Git branch helper (fast, no heavy libs) |
| 121 | __chatgpt_git_branch() { |
| 122 | local b |
| 123 | b=$(git rev-parse --abbrev-ref HEAD 2>/dev/null) || return 0 |
| 124 | [ "$b" = "HEAD" ] && b=$(git rev-parse --short HEAD 2>/dev/null) |
| 125 | [ -n "$b" ] && printf ' (%s)' "$b" |
| 126 | } |
| 127 | |
| 128 | # Prompt for root: show exit code when non-zero; root@host in red; cwd in magenta; git branch |
| 129 | __chatgpt_set_ps1_root() { |
| 130 | local exit="$?" |
| 131 | local red="\[\e[31m\]" green="\[\e[32m\]" yellow="\[\e[33m\]" blue="\[\e[34m\]" magenta="\[\e[35m\]" cyan="\[\e[36m\]" reset="\[\e[0m\]" |
| 132 | local code="" |
| 133 | [ "$exit" -ne 0 ] && code="${red}↯${exit}${reset} " |
| 134 | PS1="${code}${red}\u${reset}@${blue}\h${reset}:${magenta}\w${reset}\$(__chatgpt_git_branch)${cyan}# ${reset}" |
| 135 | } |
| 136 | case "${PROMPT_COMMAND:-}" in |
| 137 | *"__chatgpt_set_ps1_root"*) : ;; |
| 138 | "") PROMPT_COMMAND="__chatgpt_set_ps1_root" ;; |
| 139 | *) PROMPT_COMMAND="__chatgpt_set_ps1_root; $PROMPT_COMMAND" ;; |
| 140 | esac |
| 141 | |
| 142 | # Useful shopt toggles |
| 143 | shopt -s checkwinsize cdspell autocd globstar |
| 144 | |
| 145 | # Root-friendly aliases |
| 146 | alias ls='ls --color=auto -F --group-directories-first' |
| 147 | alias ll='ls -lah' |
| 148 | alias la='ls -A' |
| 149 | alias grep='grep --color=auto' |
| 150 | alias df='df -h' |
| 151 | alias free='free -h' |
| 152 | alias watchd='watch -n1 -d' |
| 153 | alias cp='cp -i' |
| 154 | alias mv='mv -i' |
| 155 | alias rm='rm -I' # prompt once if >3 files |
| 156 | alias ..='cd ..' |
| 157 | alias ...='cd ../..' |
| 158 | |
| 159 | # Prefer modern tools if present |
| 160 | command -v batcat >/dev/null 2>&1 && alias bat='batcat' |
| 161 | command -v bat >/dev/null 2>&1 && alias cat='bat --paging=never' |
| 162 | command -v lsd >/dev/null 2>&1 && alias ls='lsd' |
| 163 | |
| 164 | # Defaults |
| 165 | export EDITOR="${EDITOR:-vim}" |
| 166 | export VISUAL="$EDITOR" |
| 167 | export PAGER="${PAGER:-less}" |
| 168 | export LESS='-R' |
| 169 | export GPG_TTY="$(tty 2>/dev/null || true)" |
| 170 | |
| 171 | # Security hygiene: stricter umask for root |
| 172 | umask 027 |
| 173 | # <<< chatgpt-root: QoL shell block <<< |
| 174 | EOF |
| 175 | ) |
| 176 | append_once "$BASHRC" "$QOL_TAG" "$QOL_BLOCK" |
| 177 | msg "Added root QoL prompt/aliases/shopt/editor block." |
| 178 | |
| 179 | # Ensure the preferred editor is set explicitly |
| 180 | if grep -Fq 'export EDITOR=' "$BASHRC"; then |
| 181 | sed -i "0,/export EDITOR=.*/s//export EDITOR=\"${PREFER_EDITOR}\"/" "$BASHRC" |
| 182 | else |
| 183 | echo "export EDITOR=\"${PREFER_EDITOR}\"" >> "$BASHRC" |
| 184 | fi |
| 185 | msg "Default EDITOR for root set to ${PREFER_EDITOR}" |
| 186 | |
| 187 | # ========================= |
| 188 | # 6) Readline tweaks for root |
| 189 | # ========================= |
| 190 | INPUT_TAG="# >>> chatgpt-root: readline tweaks >>>" |
| 191 | INPUT_BLOCK=$(cat <<'EOF' |
| 192 | # >>> chatgpt-root: readline tweaks >>> |
| 193 | set show-all-if-ambiguous on |
| 194 | set menu-complete-display-prefix on |
| 195 | set colored-stats on |
| 196 | set mark-symlinked-directories on |
| 197 | set completion-ignore-case on |
| 198 | set completion-map-case on |
| 199 | "\e[A": history-search-backward |
| 200 | "\e[B": history-search-forward |
| 201 | # <<< chatgpt-root: readline tweaks <<< |
| 202 | EOF |
| 203 | ) |
| 204 | append_once "$INPUTRC" "$INPUT_TAG" "$INPUT_BLOCK" |
| 205 | msg "Improved /root/.inputrc completion/behavior." |
| 206 | |
| 207 | # ========================= |
| 208 | # Done |
| 209 | # ========================= |
| 210 | msg "Root shell setup complete. Open a NEW root shell or run: source /root/.bashrc" |
| 211 |
firstrun
· 515 B · Text
Raw
#!/bin/sh
cd ~
# sudo apt-mark hold grub* ssh*
sudo DEBIAN_FRONTEND=noninteractive apt-get -y update
sudo DEBIAN_FRONTEND=noninteractive apt-get -y upgrade
sudo apt -y install gdebi
sudo apt update
sudo apt -y upgrade
sudo apt -y autoremove
sudo apt -y autoclean
sudo apt -y clean
# sudo apt-mark unhold grub* ssh*
sudo curl -L https://gist.yais.me/yaisme/util/raw/HEAD/aptupdate -o /tmp/aptupdate
sudo mv /tmp/aptupdate /usr/bin/aptupdate
sudo chmod +x /usr/bin/aptupdate
sudo apt remove -y unattended-upgrades
| 1 | #!/bin/sh |
| 2 | cd ~ |
| 3 | # sudo apt-mark hold grub* ssh* |
| 4 | sudo DEBIAN_FRONTEND=noninteractive apt-get -y update |
| 5 | sudo DEBIAN_FRONTEND=noninteractive apt-get -y upgrade |
| 6 | sudo apt -y install gdebi |
| 7 | |
| 8 | |
| 9 | sudo apt update |
| 10 | sudo apt -y upgrade |
| 11 | sudo apt -y autoremove |
| 12 | sudo apt -y autoclean |
| 13 | sudo apt -y clean |
| 14 | |
| 15 | # sudo apt-mark unhold grub* ssh* |
| 16 | sudo curl -L https://gist.yais.me/yaisme/util/raw/HEAD/aptupdate -o /tmp/aptupdate |
| 17 | sudo mv /tmp/aptupdate /usr/bin/aptupdate |
| 18 | sudo chmod +x /usr/bin/aptupdate |
| 19 | sudo apt remove -y unattended-upgrades |
| 20 |
firstrunv2.sh
· 7.5 KiB · Bash
Raw
#!/usr/bin/env bash
set -euo pipefail
# =========================
# Settings (adjust freely)
# =========================
PREFER_EDITOR="${PREFER_EDITOR:-vim}"
PACKAGES=(
bash-completion git curl wget ca-certificates gnupg
vim tmux htop tree unzip zip
ripgrep fd-find fzf
build-essential gdebi-core
)
APTUPDATE_PATH="/usr/bin/aptupdate"
APTUPDATE_URL="https://gist.yais.me/yaisme/util/raw/HEAD/aptupdate"
# =========================
# Helpers
# =========================
msg() { printf "\033[1;32m[OK]\033[0m %s\n" "$*"; }
warn() { printf "\033[1;33m[WARN]\033[0m %s\n" "$*"; }
err() { printf "\033[1;31m[ERR]\033[0m %s\n" "$*" >&2; }
backup_file() {
local f="$1"; [ -f "$f" ] || return 0
local ts; ts="$(date +%Y%m%d-%H%M%S)"
cp -a "$f" "${f}.bak.${ts}"
msg "Backup: ${f}.bak.${ts}"
}
append_once() {
# $1=file, $2=tag_line(unique), $3=payload
local file="$1" tag="$2" payload="$3"
grep -Fqx "$tag" "$file" 2>/dev/null && return 0
printf "\n%s\n%s\n" "$tag" "$payload" >>"$file"
}
ensure_local_bin() {
mkdir -p "$HOME/.local/bin"
case ":${PATH:-}:" in
*":$HOME/.local/bin:"*) : ;;
*) echo 'export PATH="$HOME/.local/bin:$PATH"' >> "$HOME/.profile" ;;
esac
}
# =========================
# 0) System update/upgrade
# =========================
cd "$HOME"
export DEBIAN_FRONTEND=noninteractive
sudo apt-get -y update
sudo apt-get -y upgrade || true
# Keep your style (and keep unattended-upgrades removed)
sudo apt -y update
sudo apt -y upgrade || true
sudo apt -y autoremove
sudo apt -y autoclean
sudo apt -y clean
sudo apt remove -y unattended-upgrades || true
msg "Base update/upgrade complete (unattended-upgrades removed)."
# =========================
# 1) Install /usr/bin/aptupdate
# (download; if fails, write a built-in fallback)
# =========================
tmpfile="$(mktemp)"
if command -v curl >/dev/null 2>&1 && curl -fsSL "$APTUPDATE_URL" -o "$tmpfile"; then
sudo mv "$tmpfile" "$APTUPDATE_PATH"
msg "Installed aptupdate from gist."
else
warn "Could not fetch aptupdate; installing fallback script."
cat >"$tmpfile" <<'EOF'
#!/bin/sh
sudo apt update
sudo DEBIAN_FRONTEND=noninteractive apt -y upgrade
sudo DEBIAN_FRONTEND=noninteractive apt-get -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" dist-upgrade
sudo apt -y autoremove
sudo apt -y autoclean
sudo apt -y clean
EOF
sudo mv "$tmpfile" "$APTUPDATE_PATH"
fi
sudo chmod +x "$APTUPDATE_PATH"
# =========================
# 2) Install common packages
# =========================
sudo apt-get update -y
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y "${PACKAGES[@]}" || warn "Some packages failed to install; continuing."
# Map Ubuntu's fdfind → fd for consistency
if command -v fdfind >/dev/null 2>&1 && ! command -v fd >/dev/null 2>&1; then
ensure_local_bin
ln -sf "$(command -v fdfind)" "$HOME/.local/bin/fd"
msg "Linked fdfind → fd at ~/.local/bin/fd"
fi
# =========================
# 3) Shell customization
# =========================
BASHRC="${HOME}/.bashrc"
INPUTRC="${HOME}/.inputrc"
[ -f "$BASHRC" ] || touch "$BASHRC"
[ -f "$INPUTRC" ] || touch "$INPUTRC"
backup_file "$BASHRC"
backup_file "$INPUTRC"
# 3a) force_color_prompt=yes (ensure near top for Ubuntu-style .bashrc)
if grep -Eq '^[[:space:]]*#?[[:space:]]*force_color_prompt[[:space:]]*=' "$BASHRC"; then
sed -i '0,/^[[:space:]]*#\{0,1\}[[:space:]]*force_color_prompt[[:space:]]*=.*/s//force_color_prompt=yes/' "$BASHRC"
else
sed -i '1iforce_color_prompt=yes' "$BASHRC"
fi
msg "Enabled force_color_prompt=yes."
# 3b) bash-completion
COMPLETION_TAG="# >>> chatgpt: bash-completion enable >>>"
COMPLETION_BLOCK=$(cat <<'EOF'
# >>> chatgpt: bash-completion enable >>>
if [ -n "$BASH_VERSION" ] && ! shopt -oq posix; then
if [ -f /usr/share/bash-completion/bash_completion ]; then
. /usr/share/bash-completion/bash_completion
elif [ -f /etc/bash_completion ]; then
. /etc/bash_completion
fi
fi
# <<< chatgpt: bash-completion enable <<<
EOF
)
append_once "$BASHRC" "$COMPLETION_TAG" "$COMPLETION_BLOCK"
msg "Ensured bash-completion is sourced when available."
# 3c) History: timestamps + safe/merged history
HIST_TAG="# >>> chatgpt: history settings >>>"
HIST_BLOCK=$(cat <<'EOF'
# >>> chatgpt: history settings >>>
# Timestamps (YYYY-MM-DD HH:MM:SS)
export HISTTIMEFORMAT='%F %T '
# Safer history
export HISTCONTROL=ignoredups:ignorespace:erasedups
export HISTSIZE=200000
export HISTFILESIZE=400000
# Merge history across concurrent shells
shopt -s histappend
if [[ -n "${PROMPT_COMMAND:-}" ]]; then
case "$PROMPT_COMMAND" in
*'history -a; history -c; history -r'*) : ;;
*) PROMPT_COMMAND="history -a; history -c; history -r; $PROMPT_COMMAND" ;;
esac
else
PROMPT_COMMAND='history -a; history -c; history -r'
fi
# <<< chatgpt: history settings <<<
EOF
)
append_once "$BASHRC" "$HIST_TAG" "$HIST_BLOCK"
msg "Enabled history timestamps and merging."
# 3d) QoL: prompt, aliases, shopt, editor/pager (no Kubernetes)
QOL_TAG="# >>> chatgpt: QoL shell block >>>"
QOL_BLOCK=$(cat <<'EOF'
# >>> chatgpt: QoL shell block >>>
# Minimal Git branch helper
__chatgpt_git_branch() {
local b
b=$(git rev-parse --abbrev-ref HEAD 2>/dev/null) || return 0
[ "$b" = "HEAD" ] && b=$(git rev-parse --short HEAD 2>/dev/null)
[ -n "$b" ] && printf ' (%s)' "$b"
}
# Prompt: exit code + user@host:cwd + (git)
__chatgpt_set_ps1() {
local exit="$?"
local red="\[\e[31m\]" green="\[\e[32m\]" yellow="\[\e[33m\]" blue="\[\e[34m\]" magenta="\[\e[35m\]" cyan="\[\e[36m\]" reset="\[\e[0m\]"
local code=""
[ "$exit" -ne 0 ] && code="${red}↯${exit}${reset} "
PS1="${code}${green}\u${reset}@${blue}\h${reset}:${magenta}\w${reset}\$(__chatgpt_git_branch)${cyan}# ${reset}"
}
case "${PROMPT_COMMAND:-}" in
*"__chatgpt_set_ps1"*) : ;;
"") PROMPT_COMMAND="__chatgpt_set_ps1" ;;
*) PROMPT_COMMAND="__chatgpt_set_ps1; $PROMPT_COMMAND" ;;
esac
# shopt toggles
shopt -s checkwinsize cdspell autocd globstar
# Common aliases
alias ls='ls --color=auto -F --group-directories-first'
alias ll='ls -lah'
alias la='ls -A'
alias grep='grep --color=auto'
alias df='df -h'
alias free='free -h'
alias watchd='watch -n1 -d'
alias cp='cp -i'
alias mv='mv -i'
alias rm='rm -I' # prompt once if >3 files
# Prefer modern tools if present
command -v batcat >/dev/null 2>&1 && alias bat='batcat'
command -v bat >/dev/null 2>&1 && alias cat='bat --paging=never'
command -v lsd >/dev/null 2>&1 && alias ls='lsd'
# Defaults
export EDITOR="${EDITOR:-vim}"
export VISUAL="$EDITOR"
export PAGER="${PAGER:-less}"
export LESS='-R'
export GPG_TTY="$(tty 2>/dev/null || true)"
# <<< chatgpt: QoL shell block <<<
EOF
)
append_once "$BASHRC" "$QOL_TAG" "$QOL_BLOCK"
msg "Added prompt/aliases/shopt/editor QoL block."
# 3e) Ensure desired EDITOR
if grep -Fq 'export EDITOR=' "$BASHRC"; then
sed -i "0,/export EDITOR=.*/s//export EDITOR=\"${PREFER_EDITOR}\"/" "$BASHRC"
else
echo "export EDITOR=\"${PREFER_EDITOR}\"" >> "$BASHRC"
fi
msg "Default EDITOR set to ${PREFER_EDITOR}"
# 3f) ~/.inputrc readline tweaks
INPUT_TAG="# >>> chatgpt: readline tweaks >>>"
INPUT_BLOCK=$(cat <<'EOF'
# >>> chatgpt: readline tweaks >>>
set show-all-if-ambiguous on
set menu-complete-display-prefix on
set colored-stats on
set mark-symlinked-directories on
set completion-ignore-case on
set completion-map-case on
"\e[A": history-search-backward
"\e[B": history-search-forward
# <<< chatgpt: readline tweaks <<<
EOF
)
append_once "$INPUTRC" "$INPUT_TAG" "$INPUT_BLOCK"
msg "Improved interactive completion in ~/.inputrc."
# =========================
# 4) Wrap up
# =========================
msg "First-run setup complete. Open a NEW terminal or run: source ~/.bashrc"
| 1 | #!/usr/bin/env bash |
| 2 | set -euo pipefail |
| 3 | |
| 4 | # ========================= |
| 5 | # Settings (adjust freely) |
| 6 | # ========================= |
| 7 | PREFER_EDITOR="${PREFER_EDITOR:-vim}" |
| 8 | PACKAGES=( |
| 9 | bash-completion git curl wget ca-certificates gnupg |
| 10 | vim tmux htop tree unzip zip |
| 11 | ripgrep fd-find fzf |
| 12 | build-essential gdebi-core |
| 13 | ) |
| 14 | |
| 15 | APTUPDATE_PATH="/usr/bin/aptupdate" |
| 16 | APTUPDATE_URL="https://gist.yais.me/yaisme/util/raw/HEAD/aptupdate" |
| 17 | |
| 18 | # ========================= |
| 19 | # Helpers |
| 20 | # ========================= |
| 21 | msg() { printf "\033[1;32m[OK]\033[0m %s\n" "$*"; } |
| 22 | warn() { printf "\033[1;33m[WARN]\033[0m %s\n" "$*"; } |
| 23 | err() { printf "\033[1;31m[ERR]\033[0m %s\n" "$*" >&2; } |
| 24 | |
| 25 | backup_file() { |
| 26 | local f="$1"; [ -f "$f" ] || return 0 |
| 27 | local ts; ts="$(date +%Y%m%d-%H%M%S)" |
| 28 | cp -a "$f" "${f}.bak.${ts}" |
| 29 | msg "Backup: ${f}.bak.${ts}" |
| 30 | } |
| 31 | |
| 32 | append_once() { |
| 33 | # $1=file, $2=tag_line(unique), $3=payload |
| 34 | local file="$1" tag="$2" payload="$3" |
| 35 | grep -Fqx "$tag" "$file" 2>/dev/null && return 0 |
| 36 | printf "\n%s\n%s\n" "$tag" "$payload" >>"$file" |
| 37 | } |
| 38 | |
| 39 | ensure_local_bin() { |
| 40 | mkdir -p "$HOME/.local/bin" |
| 41 | case ":${PATH:-}:" in |
| 42 | *":$HOME/.local/bin:"*) : ;; |
| 43 | *) echo 'export PATH="$HOME/.local/bin:$PATH"' >> "$HOME/.profile" ;; |
| 44 | esac |
| 45 | } |
| 46 | |
| 47 | # ========================= |
| 48 | # 0) System update/upgrade |
| 49 | # ========================= |
| 50 | cd "$HOME" |
| 51 | |
| 52 | export DEBIAN_FRONTEND=noninteractive |
| 53 | sudo apt-get -y update |
| 54 | sudo apt-get -y upgrade || true |
| 55 | |
| 56 | # Keep your style (and keep unattended-upgrades removed) |
| 57 | sudo apt -y update |
| 58 | sudo apt -y upgrade || true |
| 59 | sudo apt -y autoremove |
| 60 | sudo apt -y autoclean |
| 61 | sudo apt -y clean |
| 62 | sudo apt remove -y unattended-upgrades || true |
| 63 | msg "Base update/upgrade complete (unattended-upgrades removed)." |
| 64 | |
| 65 | # ========================= |
| 66 | # 1) Install /usr/bin/aptupdate |
| 67 | # (download; if fails, write a built-in fallback) |
| 68 | # ========================= |
| 69 | tmpfile="$(mktemp)" |
| 70 | if command -v curl >/dev/null 2>&1 && curl -fsSL "$APTUPDATE_URL" -o "$tmpfile"; then |
| 71 | sudo mv "$tmpfile" "$APTUPDATE_PATH" |
| 72 | msg "Installed aptupdate from gist." |
| 73 | else |
| 74 | warn "Could not fetch aptupdate; installing fallback script." |
| 75 | cat >"$tmpfile" <<'EOF' |
| 76 | #!/bin/sh |
| 77 | sudo apt update |
| 78 | sudo DEBIAN_FRONTEND=noninteractive apt -y upgrade |
| 79 | sudo DEBIAN_FRONTEND=noninteractive apt-get -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" dist-upgrade |
| 80 | sudo apt -y autoremove |
| 81 | sudo apt -y autoclean |
| 82 | sudo apt -y clean |
| 83 | EOF |
| 84 | sudo mv "$tmpfile" "$APTUPDATE_PATH" |
| 85 | fi |
| 86 | sudo chmod +x "$APTUPDATE_PATH" |
| 87 | |
| 88 | # ========================= |
| 89 | # 2) Install common packages |
| 90 | # ========================= |
| 91 | sudo apt-get update -y |
| 92 | sudo DEBIAN_FRONTEND=noninteractive apt-get install -y "${PACKAGES[@]}" || warn "Some packages failed to install; continuing." |
| 93 | |
| 94 | # Map Ubuntu's fdfind → fd for consistency |
| 95 | if command -v fdfind >/dev/null 2>&1 && ! command -v fd >/dev/null 2>&1; then |
| 96 | ensure_local_bin |
| 97 | ln -sf "$(command -v fdfind)" "$HOME/.local/bin/fd" |
| 98 | msg "Linked fdfind → fd at ~/.local/bin/fd" |
| 99 | fi |
| 100 | |
| 101 | # ========================= |
| 102 | # 3) Shell customization |
| 103 | # ========================= |
| 104 | BASHRC="${HOME}/.bashrc" |
| 105 | INPUTRC="${HOME}/.inputrc" |
| 106 | [ -f "$BASHRC" ] || touch "$BASHRC" |
| 107 | [ -f "$INPUTRC" ] || touch "$INPUTRC" |
| 108 | backup_file "$BASHRC" |
| 109 | backup_file "$INPUTRC" |
| 110 | |
| 111 | # 3a) force_color_prompt=yes (ensure near top for Ubuntu-style .bashrc) |
| 112 | if grep -Eq '^[[:space:]]*#?[[:space:]]*force_color_prompt[[:space:]]*=' "$BASHRC"; then |
| 113 | sed -i '0,/^[[:space:]]*#\{0,1\}[[:space:]]*force_color_prompt[[:space:]]*=.*/s//force_color_prompt=yes/' "$BASHRC" |
| 114 | else |
| 115 | sed -i '1iforce_color_prompt=yes' "$BASHRC" |
| 116 | fi |
| 117 | msg "Enabled force_color_prompt=yes." |
| 118 | |
| 119 | # 3b) bash-completion |
| 120 | COMPLETION_TAG="# >>> chatgpt: bash-completion enable >>>" |
| 121 | COMPLETION_BLOCK=$(cat <<'EOF' |
| 122 | # >>> chatgpt: bash-completion enable >>> |
| 123 | if [ -n "$BASH_VERSION" ] && ! shopt -oq posix; then |
| 124 | if [ -f /usr/share/bash-completion/bash_completion ]; then |
| 125 | . /usr/share/bash-completion/bash_completion |
| 126 | elif [ -f /etc/bash_completion ]; then |
| 127 | . /etc/bash_completion |
| 128 | fi |
| 129 | fi |
| 130 | # <<< chatgpt: bash-completion enable <<< |
| 131 | EOF |
| 132 | ) |
| 133 | append_once "$BASHRC" "$COMPLETION_TAG" "$COMPLETION_BLOCK" |
| 134 | msg "Ensured bash-completion is sourced when available." |
| 135 | |
| 136 | # 3c) History: timestamps + safe/merged history |
| 137 | HIST_TAG="# >>> chatgpt: history settings >>>" |
| 138 | HIST_BLOCK=$(cat <<'EOF' |
| 139 | # >>> chatgpt: history settings >>> |
| 140 | # Timestamps (YYYY-MM-DD HH:MM:SS) |
| 141 | export HISTTIMEFORMAT='%F %T ' |
| 142 | # Safer history |
| 143 | export HISTCONTROL=ignoredups:ignorespace:erasedups |
| 144 | export HISTSIZE=200000 |
| 145 | export HISTFILESIZE=400000 |
| 146 | # Merge history across concurrent shells |
| 147 | shopt -s histappend |
| 148 | if [[ -n "${PROMPT_COMMAND:-}" ]]; then |
| 149 | case "$PROMPT_COMMAND" in |
| 150 | *'history -a; history -c; history -r'*) : ;; |
| 151 | *) PROMPT_COMMAND="history -a; history -c; history -r; $PROMPT_COMMAND" ;; |
| 152 | esac |
| 153 | else |
| 154 | PROMPT_COMMAND='history -a; history -c; history -r' |
| 155 | fi |
| 156 | # <<< chatgpt: history settings <<< |
| 157 | EOF |
| 158 | ) |
| 159 | append_once "$BASHRC" "$HIST_TAG" "$HIST_BLOCK" |
| 160 | msg "Enabled history timestamps and merging." |
| 161 | |
| 162 | # 3d) QoL: prompt, aliases, shopt, editor/pager (no Kubernetes) |
| 163 | QOL_TAG="# >>> chatgpt: QoL shell block >>>" |
| 164 | QOL_BLOCK=$(cat <<'EOF' |
| 165 | # >>> chatgpt: QoL shell block >>> |
| 166 | # Minimal Git branch helper |
| 167 | __chatgpt_git_branch() { |
| 168 | local b |
| 169 | b=$(git rev-parse --abbrev-ref HEAD 2>/dev/null) || return 0 |
| 170 | [ "$b" = "HEAD" ] && b=$(git rev-parse --short HEAD 2>/dev/null) |
| 171 | [ -n "$b" ] && printf ' (%s)' "$b" |
| 172 | } |
| 173 | |
| 174 | # Prompt: exit code + user@host:cwd + (git) |
| 175 | __chatgpt_set_ps1() { |
| 176 | local exit="$?" |
| 177 | local red="\[\e[31m\]" green="\[\e[32m\]" yellow="\[\e[33m\]" blue="\[\e[34m\]" magenta="\[\e[35m\]" cyan="\[\e[36m\]" reset="\[\e[0m\]" |
| 178 | local code="" |
| 179 | [ "$exit" -ne 0 ] && code="${red}↯${exit}${reset} " |
| 180 | PS1="${code}${green}\u${reset}@${blue}\h${reset}:${magenta}\w${reset}\$(__chatgpt_git_branch)${cyan}# ${reset}" |
| 181 | } |
| 182 | case "${PROMPT_COMMAND:-}" in |
| 183 | *"__chatgpt_set_ps1"*) : ;; |
| 184 | "") PROMPT_COMMAND="__chatgpt_set_ps1" ;; |
| 185 | *) PROMPT_COMMAND="__chatgpt_set_ps1; $PROMPT_COMMAND" ;; |
| 186 | esac |
| 187 | |
| 188 | # shopt toggles |
| 189 | shopt -s checkwinsize cdspell autocd globstar |
| 190 | |
| 191 | # Common aliases |
| 192 | alias ls='ls --color=auto -F --group-directories-first' |
| 193 | alias ll='ls -lah' |
| 194 | alias la='ls -A' |
| 195 | alias grep='grep --color=auto' |
| 196 | alias df='df -h' |
| 197 | alias free='free -h' |
| 198 | alias watchd='watch -n1 -d' |
| 199 | alias cp='cp -i' |
| 200 | alias mv='mv -i' |
| 201 | alias rm='rm -I' # prompt once if >3 files |
| 202 | |
| 203 | # Prefer modern tools if present |
| 204 | command -v batcat >/dev/null 2>&1 && alias bat='batcat' |
| 205 | command -v bat >/dev/null 2>&1 && alias cat='bat --paging=never' |
| 206 | command -v lsd >/dev/null 2>&1 && alias ls='lsd' |
| 207 | |
| 208 | # Defaults |
| 209 | export EDITOR="${EDITOR:-vim}" |
| 210 | export VISUAL="$EDITOR" |
| 211 | export PAGER="${PAGER:-less}" |
| 212 | export LESS='-R' |
| 213 | export GPG_TTY="$(tty 2>/dev/null || true)" |
| 214 | # <<< chatgpt: QoL shell block <<< |
| 215 | EOF |
| 216 | ) |
| 217 | append_once "$BASHRC" "$QOL_TAG" "$QOL_BLOCK" |
| 218 | msg "Added prompt/aliases/shopt/editor QoL block." |
| 219 | |
| 220 | # 3e) Ensure desired EDITOR |
| 221 | if grep -Fq 'export EDITOR=' "$BASHRC"; then |
| 222 | sed -i "0,/export EDITOR=.*/s//export EDITOR=\"${PREFER_EDITOR}\"/" "$BASHRC" |
| 223 | else |
| 224 | echo "export EDITOR=\"${PREFER_EDITOR}\"" >> "$BASHRC" |
| 225 | fi |
| 226 | msg "Default EDITOR set to ${PREFER_EDITOR}" |
| 227 | |
| 228 | # 3f) ~/.inputrc readline tweaks |
| 229 | INPUT_TAG="# >>> chatgpt: readline tweaks >>>" |
| 230 | INPUT_BLOCK=$(cat <<'EOF' |
| 231 | # >>> chatgpt: readline tweaks >>> |
| 232 | set show-all-if-ambiguous on |
| 233 | set menu-complete-display-prefix on |
| 234 | set colored-stats on |
| 235 | set mark-symlinked-directories on |
| 236 | set completion-ignore-case on |
| 237 | set completion-map-case on |
| 238 | "\e[A": history-search-backward |
| 239 | "\e[B": history-search-forward |
| 240 | # <<< chatgpt: readline tweaks <<< |
| 241 | EOF |
| 242 | ) |
| 243 | append_once "$INPUTRC" "$INPUT_TAG" "$INPUT_BLOCK" |
| 244 | msg "Improved interactive completion in ~/.inputrc." |
| 245 | |
| 246 | # ========================= |
| 247 | # 4) Wrap up |
| 248 | # ========================= |
| 249 | msg "First-run setup complete. Open a NEW terminal or run: source ~/.bashrc" |
| 250 |
getpubkey.sh
· 553 B · Bash
Raw
#!/bin/bash
# Prompt the user for their GitHub username
read -p "Enter your GitHub username: " USERNAME
# Get the GitHub public key URL
KEY_URL="https://github.com/$USERNAME.keys"
pushd ~/.ssh/
# Download the public key
wget -q -O - "$KEY_URL" > ~/.ssh/authorized_keys
# Set appropriate permissions for the authorized_keys file
chmod 600 ~/.ssh/authorized_keys
# Check if the .ssh directory exists and create it if it doesn't
if [ ! -d ~/.ssh ]; then
mkdir -p ~/.ssh
chmod 700 ~/.ssh
fi
echo "Public key successfully added to authorized_keys"
| 1 | #!/bin/bash |
| 2 | |
| 3 | # Prompt the user for their GitHub username |
| 4 | read -p "Enter your GitHub username: " USERNAME |
| 5 | |
| 6 | # Get the GitHub public key URL |
| 7 | KEY_URL="https://github.com/$USERNAME.keys" |
| 8 | |
| 9 | pushd ~/.ssh/ |
| 10 | |
| 11 | # Download the public key |
| 12 | wget -q -O - "$KEY_URL" > ~/.ssh/authorized_keys |
| 13 | |
| 14 | # Set appropriate permissions for the authorized_keys file |
| 15 | chmod 600 ~/.ssh/authorized_keys |
| 16 | |
| 17 | # Check if the .ssh directory exists and create it if it doesn't |
| 18 | if [ ! -d ~/.ssh ]; then |
| 19 | mkdir -p ~/.ssh |
| 20 | chmod 700 ~/.ssh |
| 21 | fi |
| 22 | |
| 23 | echo "Public key successfully added to authorized_keys" |