add x64 bins and arm64 bin

This commit is contained in:
Your Name
2026-08-03 02:08:58 -04:00
parent a53ba0a68e
commit cf7ba2d58a
25 changed files with 3565 additions and 48 deletions
+13 -8
View File
@@ -78,6 +78,9 @@ Linux_post_install/
├── completions/
│ └── pos.bash # Bash tab-completion for the pos CLI
├── config/
│ └── authorized_keys # SSH public keys (gitignored)
├── compose/
│ └── scale-tail/ # Git submodule → ScaleTail templates (119+ services)
@@ -266,8 +269,10 @@ ScaleTail provides 119+ Docker Compose templates with a Tailscale sidecar patter
- `apps/install.sh` auto-discovers all `apps/<category>/*.sh` files (excluding itself)
- Three modes: interactive (default), `--all`, or specific app names as arguments
- `--uninstall` switches to uninstall mode (same selection, invokes app scripts with `uninstall` argument)
- Interactive TUI groups apps by category with section headers
- Each app script is standalone, idempotent, sources `lib/common.sh`
- Every app script defines `install_<name>()` **and** `uninstall_<name>()`, dispatched via `case "${1:-}" in uninstall) ...`
### Installation Methods
@@ -391,18 +396,18 @@ Use conventional prefixes: `feat:`, `fix:`, `docs:`, `refactor:`, `chore:`
| File | Lines | Purpose |
|------|-------|---------|
| `install.sh` | ~120 | Main orchestrator — 4 phases with CLI flags |
| `preinstall.sh` | ~52 | System packages + yt-dlp + fail2ban |
| `postinstall.sh` | ~65 | fail2ban config, PATH, bash completion, systemd |
| `install.sh` | 149 | Main orchestrator — 4 phases with CLI flags |
| `preinstall.sh` | 52 | System packages + yt-dlp + fail2ban |
| `postinstall.sh` | 90 | fail2ban config, PATH, bash completion, systemd |
| `lib/common.sh` | 121 | Shared library |
| `bin/pos` | ~130 | CLI dispatcher with smart arg matching + logging |
| `bin/pos-docker-compose` | 317 | Largest script — full compose management |
| `bin/pos` | 145 | CLI dispatcher with smart arg matching + logging |
| `bin/pos-docker-compose` | 363 | Largest script — full compose management |
| `bin/pos-system-firewall` | 284 | Interactive UFW manager |
| `bin/pos-docker-ps` | 127 | Enhanced container overview |
| `bin/pos-docker-health` | ~90 | Quick health dashboard |
| `bin/pos-vbox` | ~160 | Docker-based disposable VMs (label-filtered, auto-enter prompt) |
| `bin/pos-docker-health` | 109 | Quick health dashboard |
| `bin/pos-vbox` | 156 | Docker-based disposable VMs (label-filtered, auto-enter prompt) |
| `completions/pos.bash` | 118 | Dynamic bash completion |
| `apps/install.sh` | 99 | App picker/orchestrator |
| `apps/install.sh` | 171 | App install/uninstall picker/orchestrator |
---
+16 -4
View File
@@ -153,7 +153,16 @@ install_myapp() {
spawn "Installing myapp" sudo apt install -y myapp
}
install_myapp
uninstall_myapp() {
command -v myapp &>/dev/null || { log "myapp not installed"; return 0; }
spawn "Removing myapp" sudo apt purge -y myapp
spawn "Cleaning up dependencies" sudo apt autoremove -y
}
case "${1:-}" in
uninstall) uninstall_myapp ;;
*) install_myapp ;;
esac
```
Place it in `apps/<category>/<name>.sh`. It auto-appears in the picker — no registration needed.
@@ -162,11 +171,14 @@ Place it in `apps/<category>/<name>.sh`. It auto-appears in the picker — no re
### 2. Conventions
- Idempotent: check `command -v` before installing
- APT packages → `sudo apt install -y` inside `spawn`
- Idempotent: check `command -v` (or `flatpak list` / file existence) before installing **and** uninstalling
- Every app **must** provide an `uninstall_<name>()` function and dispatch on `uninstall` via the `case` above — `apps/install.sh --uninstall` depends on it
- APT packages → `sudo apt install -y` inside `spawn`, remove with `sudo apt purge -y` + `sudo apt autoremove -y`
- Repo-based apps (apt repo added at install) → also remove the `.list` file and keyring in uninstall
- Official scripts → `curl ... | sh` inside `spawn`
- Flatpak → `flatpak install -y flathub <app-id>` inside `spawn`
- Flatpak → `flatpak install -y flathub <app-id>` inside `spawn`, remove with `flatpak uninstall -y <app-id>`
- `.deb` files → download to temp, `sudo apt install -y ./file.deb` inside `spawn`
- File/AppImage installs → remove the installed files, symlinks, and desktop entries in uninstall
- `usermod` for groups → print re-login reminder
---
+8 -1
View File
@@ -173,7 +173,14 @@ These still work and forward to `pos`: `wr-ip`, `wr-checkport`, `wr-scan-ping`,
## Optional Apps
Install with `./apps/install.sh` (interactive), `./apps/install.sh --all`, or by name:
Install with `./apps/install.sh` (interactive), `./apps/install.sh --all`, or by name.
Uninstall the same way with `--uninstall`:
```bash
./apps/install.sh --uninstall # interactive uninstall selection
./apps/install.sh --uninstall --all # uninstall everything
./apps/install.sh --uninstall brave vscode # uninstall specific apps
```
| Category | Apps |
|----------|------|
+11 -1
View File
@@ -15,4 +15,14 @@ install_brave() {
spawn "Installing brave-browser" sudo apt install -y brave-browser
}
install_brave
uninstall_brave() {
command -v brave-browser &>/dev/null || { log "brave not installed"; return 0; }
spawn "Removing brave-browser" sudo apt purge -y brave-browser
spawn "Cleaning up dependencies" sudo apt autoremove -y
spawn "Removing brave apt repo" sudo rm -f /etc/apt/sources.list.d/brave-browser-release.list /usr/share/keyrings/brave-browser-archive-keyring.gpg
}
case "${1:-}" in
uninstall) uninstall_brave ;;
*) install_brave ;;
esac
+10 -1
View File
@@ -13,4 +13,13 @@ install_opencode() {
log "Add to PATH: export PATH=\"\$HOME/.opencode/bin:\$PATH\""
}
install_opencode
uninstall_opencode() {
[ -d "$HOME/.opencode" ] || { log "opencode not installed"; return 0; }
spawn "Removing opencode" rm -rf "$HOME/.opencode"
warn "Config/data remains in ~/.config/opencode — remove manually if desired"
}
case "${1:-}" in
uninstall) uninstall_opencode ;;
*) install_opencode ;;
esac
+11 -1
View File
@@ -15,4 +15,14 @@ install_vscode() {
spawn "Installing code" sudo apt install -y code
}
install_vscode
uninstall_vscode() {
command -v code &>/dev/null || { log "vscode not installed"; return 0; }
spawn "Removing code" sudo apt purge -y code
spawn "Cleaning up dependencies" sudo apt autoremove -y
spawn "Removing vscode apt repo" sudo rm -f /etc/apt/sources.list.d/vscode.list /usr/share/keyrings/packages.microsoft.gpg
}
case "${1:-}" in
uninstall) uninstall_vscode ;;
*) install_vscode ;;
esac
+47 -19
View File
@@ -6,26 +6,32 @@ usage() {
cat <<EOF
Usage: bash apps/install.sh [OPTIONS] [app ...]
Install optional desktop applications.
Install or uninstall optional desktop applications.
Options:
--all Install all available apps without prompting
-h, --help Show this help message
--all Apply action to all available apps without prompting
--uninstall Uninstall the selected apps instead of installing
-h, --help Show this help message
Examples:
bash apps/install.sh # interactive selection
bash apps/install.sh --all # install everything
bash apps/install.sh brave vscode # install specific apps
bash apps/install.sh # interactive install selection
bash apps/install.sh --all # install everything
bash apps/install.sh brave vscode # install specific apps
bash apps/install.sh --uninstall # interactive uninstall selection
bash apps/install.sh --uninstall --all # uninstall everything
bash apps/install.sh --uninstall brave # uninstall specific apps
EOF
exit 0
}
ALL=0
UNINSTALL=0
POSITIONAL=()
while [[ $# -gt 0 ]]; do
case "$1" in
--all) ALL=1; shift ;;
--uninstall) UNINSTALL=1; shift ;;
-h|--help) usage ;;
-*) err "Unknown option: $1" ;;
*) POSITIONAL+=("$1"); shift ;;
@@ -62,11 +68,11 @@ for cat_dir in "$APPS_DIR"/*/; do
[ "$has_apps" -eq 0 ] && continue
CATEGORIES+=("$cat_name")
CAT_APPS["$cat_name"]=()
CAT_APPS["$cat_name"]=""
for f in "$cat_dir"*.sh; do
[ -f "$f" ] || continue
app_name=$(basename "$f" .sh)
CAT_APPS["$cat_name"]+=("$app_name")
CAT_APPS["$cat_name"]+=" $app_name"
done
done
@@ -74,7 +80,7 @@ done
find_app_category() {
local app="$1"
for cat in "${CATEGORIES[@]}"; do
for a in "${CAT_APPS[$cat]}"; do
for a in ${CAT_APPS[$cat]}; do
[ "$a" == "$app" ] && { echo "$cat"; return 0; }
done
done
@@ -96,7 +102,7 @@ if [ "${#POSITIONAL[@]}" -gt 0 ]; then
# ── Mode 2: --all ─────────────────────────────────────────────
elif [ "$ALL" -eq 1 ]; then
for cat in "${CATEGORIES[@]}"; do
for app in "${CAT_APPS[$cat]}"; do
for app in ${CAT_APPS[$cat]}; do
SELECTED+=("$app")
done
done
@@ -104,14 +110,22 @@ elif [ "$ALL" -eq 1 ]; then
# ── Mode 3: interactive TUI ───────────────────────────────────
else
section "Optional Applications"
echo "Select apps to install (y/n for each):"
if [ "$UNINSTALL" -eq 1 ]; then
echo "Select apps to uninstall (y/n for each):"
else
echo "Select apps to install (y/n for each):"
fi
echo
for cat in "${CATEGORIES[@]}"; do
display="${CAT_NAMES[$cat]:-$cat}"
echo " $display"
for app in "${CAT_APPS[$cat]}"; do
read -rp " Install ${app}? [y/N]: " yn
for app in ${CAT_APPS[$cat]}; do
if [ "$UNINSTALL" -eq 1 ]; then
read -rp " Remove ${app}? [y/N]: " yn
else
read -rp " Install ${app}? [y/N]: " yn
fi
if [[ "$yn" =~ ^[Yy] ]]; then
SELECTED+=("$app")
fi
@@ -120,11 +134,15 @@ else
done
fi
# ── Install selected apps ──────────────────────────────────────
# ── Apply action to selected apps ─────────────────────────────
[ "${#SELECTED[@]}" -eq 0 ] && { warn "No apps selected"; exit 0; }
echo
section "Installing ${SELECTED[*]}"
if [ "$UNINSTALL" -eq 1 ]; then
section "Uninstalling ${SELECTED[*]}"
else
section "Installing ${SELECTED[*]}"
fi
timer_start
count=1
@@ -132,12 +150,22 @@ total=${#SELECTED[@]}
for app in "${SELECTED[@]}"; do
cat=$(find_app_category "$app")
step "$count" "$total" "$app"
bash "$APPS_DIR/$cat/$app.sh"
if [ "$UNINSTALL" -eq 1 ]; then
bash "$APPS_DIR/$cat/$app.sh" uninstall
else
bash "$APPS_DIR/$cat/$app.sh"
fi
count=$((count + 1))
echo
done
echo
echo "${GREEN}════════════════════════════════════════════${RESET}"
echo "${GREEN} Apps installed ($(timer_stop))${RESET}"
echo "${GREEN}════════════════════════════════════════════${RESET}"
if [ "$UNINSTALL" -eq 1 ]; then
echo "${GREEN}════════════════════════════════════════════${RESET}"
echo "${GREEN} Apps uninstalled ($(timer_stop))${RESET}"
echo "${GREEN}════════════════════════════════════════════${RESET}"
else
echo "${GREEN}════════════════════════════════════════════${RESET}"
echo "${GREEN} Apps installed ($(timer_stop))${RESET}"
echo "${GREEN}════════════════════════════════════════════${RESET}"
fi
+10 -1
View File
@@ -7,4 +7,13 @@ install_obs() {
spawn "Installing obs-studio" sudo apt install -y obs-studio
}
install_obs
uninstall_obs() {
command -v obs &>/dev/null || { log "obs-studio not installed"; return 0; }
spawn "Removing obs-studio" sudo apt purge -y obs-studio
spawn "Cleaning up dependencies" sudo apt autoremove -y
}
case "${1:-}" in
uninstall) uninstall_obs ;;
*) install_obs ;;
esac
+10 -1
View File
@@ -50,4 +50,13 @@ EOF
log "scrcpy $version installed (adb included in the bundle)"
}
install_scrcpy
uninstall_scrcpy() {
command -v scrcpy &>/dev/null || { log "scrcpy not installed"; return 0; }
spawn "Removing scrcpy files" sudo rm -rf /usr/local/lib/scrcpy-* /usr/local/bin/scrcpy /usr/share/applications/scrcpy.desktop
log "scrcpy removed (bundled adb was removed with it)"
}
case "${1:-}" in
uninstall) uninstall_scrcpy ;;
*) install_scrcpy ;;
esac
+10 -1
View File
@@ -7,4 +7,13 @@ install_vlc() {
spawn "Installing vlc" sudo apt install -y vlc
}
install_vlc
uninstall_vlc() {
command -v vlc &>/dev/null || { log "vlc not installed"; return 0; }
spawn "Removing vlc" sudo apt purge -y vlc
spawn "Cleaning up dependencies" sudo apt autoremove -y
}
case "${1:-}" in
uninstall) uninstall_vlc ;;
*) install_vlc ;;
esac
+11 -1
View File
@@ -11,4 +11,14 @@ install_netbird() {
log "Join a network: sudo netbird up --setup-key <key>"
}
install_netbird
uninstall_netbird() {
command -v netbird &>/dev/null || { log "netbird not installed"; return 0; }
spawn "Removing netbird" sudo apt purge -y netbird
spawn "Cleaning up dependencies" sudo apt autoremove -y
spawn "Removing netbird apt repo" sudo rm -f /etc/apt/sources.list.d/netbird.list
}
case "${1:-}" in
uninstall) uninstall_netbird ;;
*) install_netbird ;;
esac
+11 -1
View File
@@ -11,4 +11,14 @@ install_tailscale() {
log "Start tailscale: sudo tailscale up"
}
install_tailscale
uninstall_tailscale() {
command -v tailscale &>/dev/null || { log "tailscale not installed"; return 0; }
spawn "Removing tailscale" sudo apt purge -y tailscale
spawn "Cleaning up dependencies" sudo apt autoremove -y
spawn "Removing tailscale apt repo" sudo rm -f /etc/apt/sources.list.d/tailscale.list /usr/share/keyrings/tailscale-archive-keyring.gpg
}
case "${1:-}" in
uninstall) uninstall_tailscale ;;
*) install_tailscale ;;
esac
+11 -1
View File
@@ -11,4 +11,14 @@ install_zerotier() {
log "Join a network: sudo zerotier-cli join <network-id>"
}
install_zerotier
uninstall_zerotier() {
command -v zerotier-one &>/dev/null || { log "zerotier not installed"; return 0; }
spawn "Removing zerotier" sudo apt purge -y zerotier-one
spawn "Cleaning up dependencies" sudo apt autoremove -y
spawn "Removing zerotier apt repo" sudo rm -f /etc/apt/sources.list.d/zerotier.list
}
case "${1:-}" in
uninstall) uninstall_zerotier ;;
*) install_zerotier ;;
esac
+10 -1
View File
@@ -17,4 +17,13 @@ install_termius() {
log "Termius installed — launch with 'termius'"
}
install_termius
uninstall_termius() {
command -v termius &>/dev/null || { log "termius not installed"; return 0; }
spawn "Removing termius" sudo apt purge -y termius
spawn "Cleaning up dependencies" sudo apt autoremove -y
}
case "${1:-}" in
uninstall) uninstall_termius ;;
*) install_termius ;;
esac
+10 -1
View File
@@ -7,4 +7,13 @@ install_vnc_viewer() {
spawn "Installing tigervnc-viewer" sudo apt install -y tigervnc-viewer
}
install_vnc_viewer
uninstall_vnc_viewer() {
command -v vncviewer &>/dev/null || { log "tigervnc-viewer not installed"; return 0; }
spawn "Removing tigervnc-viewer" sudo apt purge -y tigervnc-viewer
spawn "Cleaning up dependencies" sudo apt autoremove -y
}
case "${1:-}" in
uninstall) uninstall_vnc_viewer ;;
*) install_vnc_viewer ;;
esac
+20 -1
View File
@@ -12,4 +12,23 @@ install_docker() {
warn "Log out and back in for docker group to take effect"
}
install_docker
uninstall_docker() {
command -v docker &>/dev/null || { log "docker not installed"; return 0; }
local pkgs=(docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin docker-compose-v2)
local installed=()
for p in "${pkgs[@]}"; do
dpkg -s "$p" &>/dev/null && installed+=("$p")
done
if [ "${#installed[@]}" -gt 0 ]; then
spawn "Removing docker engine" sudo apt purge -y "${installed[@]}"
spawn "Cleaning up dependencies" sudo apt autoremove -y
fi
spawn "Removing docker apt repo" sudo rm -f /etc/apt/sources.list.d/docker.list /etc/apt/keyrings/docker.asc /etc/apt/keyrings/docker.gpg
warn "Docker data remains in /var/lib/docker — remove manually if desired"
}
case "${1:-}" in
uninstall) uninstall_docker ;;
*) install_docker ;;
esac
+13 -1
View File
@@ -15,4 +15,16 @@ install_qemu() {
warn "Log out and back in for libvirt/kvm groups to take effect"
}
install_qemu
uninstall_qemu() {
command -v qemu-system-x86_64 &>/dev/null || { log "qemu not installed"; return 0; }
spawn "Removing qemu and libvirt" sudo apt purge -y \
qemu-system qemu-utils qemu-kvm \
libvirt-daemon-system libvirt-clients \
bridge-utils virt-manager
spawn "Cleaning up dependencies" sudo apt autoremove -y
}
case "${1:-}" in
uninstall) uninstall_qemu ;;
*) install_qemu ;;
esac
+9 -1
View File
@@ -32,4 +32,12 @@ EOF
"
}
install_affine
uninstall_affine() {
command -v affine &>/dev/null || { log "affine not installed"; return 0; }
spawn "Removing AFFiNE" sudo rm -rf /opt/affine /usr/local/bin/affine /usr/share/applications/affine.desktop
}
case "${1:-}" in
uninstall) uninstall_affine ;;
*) install_affine ;;
esac
+10 -1
View File
@@ -7,4 +7,13 @@ install_btop() {
spawn "Installing btop" sudo apt install -y btop
}
install_btop
uninstall_btop() {
command -v btop &>/dev/null || { log "btop not installed"; return 0; }
spawn "Removing btop" sudo apt purge -y btop
spawn "Cleaning up dependencies" sudo apt autoremove -y
}
case "${1:-}" in
uninstall) uninstall_btop ;;
*) install_btop ;;
esac
+12 -1
View File
@@ -16,4 +16,15 @@ install_localsend() {
spawn "Installing localsend" sudo flatpak install -y flathub org.localsend.localsend_app
}
install_localsend
uninstall_localsend() {
if ! flatpak list 2>/dev/null | grep -q org.localsend.localsend_app; then
log "localsend not installed"
return 0
fi
spawn "Removing localsend" sudo flatpak uninstall -y org.localsend.localsend_app
}
case "${1:-}" in
uninstall) uninstall_localsend ;;
*) install_localsend ;;
esac
+5
View File
@@ -34,6 +34,11 @@ Options:
(1=preinstall, 2=scripts, 3=postinstall, 4=scalepoint)
--no-color Disable colored output
-h, --help Show this help message
Uninstall optional apps later with:
./apps/install.sh --uninstall # interactive uninstall selection
./apps/install.sh --uninstall --all # uninstall everything
./apps/install.sh --uninstall <app>... # uninstall specific apps
EOF
exit 0
}
+1249
View File
File diff suppressed because one or more lines are too long
+2044
View File
File diff suppressed because it is too large Load Diff
+4
View File
@@ -0,0 +1,4 @@
#!/bin/sh
# Start wihotspot-gui
/usr/bin/wihotspot-gui
BIN
View File
Binary file not shown.