feat: add uninstall/teardown scripts + uninstall section in README

This commit is contained in:
gramps
2026-07-19 15:38:28 -07:00
parent 6946619bc5
commit f5d020e39a
4 changed files with 379 additions and 1 deletions
+125
View File
@@ -0,0 +1,125 @@
#!/usr/bin/env bash
# cAIc — nuclear clean uninstall
# Removes every trace of cAIc: bare-metal systemd install AND Docker stack.
# Prompts for each step. Use -y to skip ALL prompts (fully automatic).
# Use with extreme caution — will delete data and model files.
set -euo pipefail
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m'
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
SKIP=false
[ "${1:-}" = "-y" ] && SKIP=true
prompt_yn() {
if $SKIP; then return 0; fi
local msg=$1; local default=${2:-n}
if [[ "$default" == "y" ]]; then
read -p "$msg [Y/n] " r; [[ -z "$r" || "$r" =~ ^[Yy] ]]
else
read -p "$msg [y/N] " r; [[ "$r" =~ ^[Yy] ]]
fi
}
warn() { echo -e "${YELLOW}$1${NC}"; }
if ! $SKIP; then
echo ""
echo "${RED}================================================${NC}"
echo "${RED} cAIc NUCLEAR CLEAN - removes all traces${NC}"
echo "${RED} This will delete data, models, and the app.${NC}"
echo "${RED}================================================${NC}"
echo ""
echo "cAIc NUCLEAR CLEAN"
echo "=================="
read -p "Type 'yes' to continue: " confirm
if [ "$confirm" != "yes" ]; then
echo "Aborted."
exit 1
else
SKIP=true
fi
fi
if ! $SKIP; then
prompt_yn "Run nuclear clean?" y || { echo "Aborted."; exit 0; }
fi
echo ""
echo "========== PART 1: Docker stack =========="
if command -v docker &>/dev/null; then
# Stop all cAIc-related containers
docker compose down 2>/dev/null || docker-compose down 2>/dev/null || echo " no compose stack running"
docker ps --filter name=cai[c] --filter name=searxng --filter name=qdrant --filter name=rabbit --filter name=llama-server --filter name=ollama --filter name=caic -aq 2>/dev/null \
| xargs -r docker rm -f 2>/dev/null || true
docker volume rm caic_data caic_uploads searxng_config qdrant_storage rabbitmq_data ollama_models 2>/dev/null || echo " volumes already gone"
docker rmi caic:latest 2>/dev/null || echo " caic image already gone"
echo " Docker stack removed"
else
echo " Docker not installed — skipping"
fi
echo ""
echo "========== PART 2: Systemd service ========="
SERVICE_FILE="/etc/systemd/system/caic.service"
if [ -f "$SERVICE_FILE" ]; then
stop caic 2>/dev/null || true
systemctl disable caic 2>/dev/null || true
rm -f "$SERVICE_FILE"
systemctl daemon-reload
echo " systemd service removed"
else
echo " no systemd service found"
fi
echo ""
echo "========== PART 3: Install directory ========"
for dir in /opt/caic /var/lib/caic; do
if [ -d "$dir" ]; then
rm -rf "$dir"
echo " Removed: $dir"
else
echo " Skipped: $dir"
fi
done
echo ""
echo "========== PART 4: Config and state files ========"
for f in \
/home/gramps/.caic_amqp_secret \
hardware_state.json \
setup.log \
.env; do
rm -f "$f" 2>/dev/null || true
done
echo " Config/state files cleaned"
echo ""
echo "========== PART 5: Temp data ==========="
rm -rf /tmp/caic_uploads 2>/dev/null || true
echo " Temp data cleaned"
echo ""
echo "========== PART 6: User data (prompt each) ========="
if prompt_yn "Remove the repository (current dir)?" n; then
cd ..
rm -rf "$SCRIPT_DIR"
echo " Repository removed"
else
echo " Repository preserved"
fi
echo ""
echo "${GREEN}cAIc nuclear clean complete.${NC}"
echo ""
echo "Manually verify:"
echo " - ls /opt/caic/"
echo " - ls /etc/systemd/system/caic*"
echo " - docker images | grep -E \"caic|searx|qdrant|rabbit|llama|ollama\""
echo " - docker ps -a"
echo ""
echo "To remove Docker Engine itself:"
echo " sudo apt remove docker.io containerd runc"
echo " sudo rm -rf /var/lib/docker"
echo ""
echo "To remove python packages:"
echo " pip uninstall fastapi uvicorn httpx psutil jinja2 python-multipart pypdf aio-pika"
+109
View File
@@ -0,0 +1,109 @@
#!/usr/bin/env bash
# cAIc — Docker stack teardown
# Removes all containers, volumes, images, and generated files
# created by setup-wizard / docker compose.
# Run from the docker deployment directory. Use -y to skip prompts.
set -euo pipefail
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m'
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
prompt_yn() {
if [ "${1:-}" = "-y" ]; then return 0; fi
[ "$SKIP" = true ] && return 0
local msg=$1; local default=${2:-n}
if [[ "$default" == "y" ]]; then
read -p "$msg [Y/n] " r; [[ -z "$r" || "$r" =~ ^[Yy] ]]
else
read -p "$msg [y/N] " r; [[ "$r" =~ ^[Yy] ]]
fi
}
SKIP=false
[ "${1:-}" = "-y" ] && SKIP=true
echo "cAIc Docker stack teardown"
echo "=========================="
# ---- Step 1: docker compose down -v ----
if [ -f docker-compose.yml ] || [ -f compose.yml ]; then
if prompt_yn "Stop Docker stack and remove volumes?" n; then
docker compose down -v 2>/dev/null || docker-compose down -v 2>/dev/null || true
echo " Docker stack stopped and volumes removed"
else
warn " Skipped: Docker stack left intact"
fi
else
echo " Skipped: no compose file found"
fi
# ---- Step 2: Remove Docker images ----
if prompt_yn "Remove cAIc Docker image?" n; then
docker rmi caic:latest 2>/dev/null || true
echo " Removed caic:latest"
warn "Remove SearXNG / Qdrant / RabbitMQ / llama-server / Ollama images?"
if prompt_yn " Remove service images?" n; then
for tag in searxng/searxng qdrant/qdrant rabbitmq:4-management \
ghcr.io/ggml-org/llama.cpp ollama/ollama; do
docker rmi "$tag" 2>/dev/null || true
done
echo " Service images removed"
fi
fi
# ---- Step 3: Volumes ----
if prompt_yn "Remove remaining Docker volumes?" n; then
for vol in caic_data caic_uploads searxng_config qdrant_storage rabbitmq_data ollama_models; do
docker volume rm "$vol" 2>/dev/null || true
done
echo " Docker volumes removed"
fi
# ---- Step 4: .env ----
if [ -f .env ]; then
if prompt_yn "Remove .env file?" n; then
rm -f .env
echo " .env removed"
fi
fi
# ---- Step 5: generated directories ----
for dir in secrets searxng; do
if [ -d "$dir" ]; then
if prompt_yn "Remove $dir/ directory?" n; then
rm -rf "$dir"
echo " $dir/ removed"
fi
fi
done
# ---- Step 6: generated files ----
for f in setup.log docker-compose.yml compose.yml; do
[ -f "$f" ] || continue
if prompt_yn "Remove $f?" n; then
rm -f "$f"
echo " $f removed"
fi
done
# ---- Step 7: model files (with big warning) ----
if [ -d models ]; then
echo ""
echo -e "${RED}WARNING: model files (*.gguf) can be gigabytes each.${NC}"
if prompt_yn "Remove all model files from ./models/?" n; then
rm -rf models
echo " models/ removed"
else
echo " models/ preserved"
fi
fi
echo ""
echo -e "${GREEN}cAIc Docker stack teardown complete.${NC}"
echo "Preserved:"
echo " - ./models/ (unless you accepted removal)"
echo ""
echo "Note: Docker Engine itself is not removed. To remove it:"
echo " sudo apt-get remove docker docker-engine docker.io containerd runc"
+98
View File
@@ -0,0 +1,98 @@
#!/usr/bin/env bash
# cAIc — bare-metal/systemd uninstall
# Removes the cAIc install deployed via the README Fresh Install path.
# Run as root or with sudo. Use -y to skip prompts.
set -euo pipefail
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m'
SKIP_PROMPT=false
[ "${1:-}" = "-y" ] && SKIP_PROMPT=true
prompt_yn() {
if $SKIP_PROMPT; then return 0; fi
local msg=$1; local default=${2:-n}
if [[ "$default" == "y" ]]; then
read -p "$msg [Y/n] " r; [[ -z "$r" || "$r" =~ ^[Yy] ]]
else
read -p "$msg [y/N] " r; [[ "$r" =~ ^[Yy] ]]
fi
}
warn() { echo -e "${YELLOW}$1${NC}"; }
echo "cAIc Bare-metal / systemd uninstall"
echo "===================================="
# ---- Step 1: systemd service ----
SERVICE_FILE="/etc/systemd/system/caic.service"
if [ -f "$SERVICE_FILE" ]; then
warn "Stopping and disabling caic service..."
systemctl stop caic 2>/dev/null || true
systemctl disable caic 2>/dev/null || true
if prompt_yn "Remove caic systemd service?" n; then
rm -f "$SERVICE_FILE" /etc/systemd/system/caic.service
systemctl daemon-reload
echo " Removed systemd service"
fi
else
echo " Skipped: no systemd service at $SERVICE_FILE"
fi
# ---- Step 2: /opt/caic directory ----
CAIC_DIR="/opt/caic"
if [ -d "$CAIC_DIR" ]; then
if prompt_yn "Remove cAIc installation directory ($CAIC_DIR)?" n; then
rm -rf "$CAIC_DIR"
echo " Removed $CAIC_DIR"
else
warn " Skipped: $CAIC_DIR preserved"
fi
else
echo " Skipped: $CAIC_DIR does not exist"
fi
# ---- Step 3: AMQP secret file ----
if [ -f "/home/gramps/.caic_amqp_secret" ]; then
if prompt_yn "Remove AMQP secret file (/home/gramps/.caic_amqp_secret)?" n; then
rm -f /home/gramps/.caic_amqp_secret
echo " Removed AMQP secret"
fi
fi
# ---- Step 4: Upload temp directory ----
UPLOAD_DIR="/tmp/caic_uploads"
if [ -d "$UPLOAD_DIR" ]; then
if prompt_yn "Remove upload temp directory ($UPLOAD_DIR)?" n; then
rm -rf "$UPLOAD_DIR"
echo " Removed upload temp"
fi
fi
# ---- Step 5: hardware_state.json in cwd ----
if [ -f "hardware_state.json" ]; then
if prompt_yn "Remove cached hardware state?" n; then
rm -f hardware_state.json
echo " Removed cached hardware state"
fi
fi
# ---- Step 6: pip packages if user wants ----
if command -v pip &>/dev/null; then
if prompt_yn "Attempt to uninstall cAIc-related pip packages?" n; then
pip uninstall -y fastapi uvicorn httpx psutil aio-pika jinja2 python-multipart pypdf 2>/dev/null || true
echo " Uninstalled pip packages"
fi
fi
echo ""
echo -e "${GREEN}cAIc bare-metal/uninstall complete.${NC}"
echo "The following may remain:"
echo " - /opt/caic/ (if you chose to preserve)"
echo " - ~/.caic_amqp_secret (if preserved)"
echo " - hardware_state.json (if preserved)"
echo " - installed pip packages (if you chose to skip)"
echo " - Python venv at /opt/caic/venv (removed with /opt/caic)"
echo ""
echo "Caic data stored outside install:"
echo " - caic.db (if configured via CAIC_DB_PATH)"
echo " - claude/opencode .jsonc updates (not tracked by this script)"