Make direct setup reruns preserve user state

This commit is contained in:
Nick Sweeting 2026-08-01 03:13:26 -07:00
parent e086f01d74
commit f3e4459fb8
No known key found for this signature in database
2 changed files with 64 additions and 24 deletions

View File

@ -15,7 +15,7 @@ def test_setup_script_creates_archivebox_user_instead_of_rejecting_root():
def test_setup_script_never_recursively_chowns_collection_data():
script = SETUP_SCRIPT.read_text()
assert 'chown "$ARCHIVEBOX_SYSTEM_UID:$ARCHIVEBOX_SYSTEM_GID" "$HOME/archivebox" "$HOME/archivebox/data"' in script
assert 'chown "$ARCHIVEBOX_SYSTEM_UID:$ARCHIVEBOX_SYSTEM_GID" "$ARCHIVEBOX_HOME_DIR" "$ARCHIVEBOX_DATA_DIR"' in script
assert "chown -R" not in "\n".join(line for line in script.splitlines() if "archivebox/data" in line)
@ -23,3 +23,23 @@ def test_setup_script_bootstraps_locked_abxpkg_version():
script = SETUP_SCRIPT.read_text()
assert 'ABXPKG_PACKAGE="${ABXPKG_PACKAGE:-abxpkg==1.12.41}"' in script
def test_setup_script_preserves_collection_and_compose_ownership_boundaries():
script = SETUP_SCRIPT.read_text()
assert "data|docker-compose.yml|compose.yml|compose.yaml|.env|Caddyfile)" in script
assert 'mv -n "$path" "$ARCHIVEBOX_DATA_DIR/"' in script
assert "if [ ! -f docker-compose.yml ]; then" in script
assert 'chown "$ARCHIVEBOX_SYSTEM_UID:$ARCHIVEBOX_SYSTEM_GID" docker-compose.yml' in script
assert 'mv -i "$HOME"/archivebox/*' not in script
def test_setup_script_prints_root_safe_runtime_commands():
script = SETUP_SCRIPT.read_text()
assert 'echo " cd $ARCHIVEBOX_DATA_DIR' in script
assert "server --daemonize 0.0.0.0:8000" in script
assert 'nohup "$ARCHIVEBOX_BINARY" server' not in script
assert '"$DOCKER_BINARY" rm -f archivebox' in script
assert "--connect-timeout 1 --max-time 2" in script

View File

@ -76,6 +76,8 @@ ARCHIVEBOX_PLATFORM="${ARCHIVEBOX_PLATFORM:-}"
ARCHIVEBOX_COMPOSE_URL="${ARCHIVEBOX_COMPOSE_URL:-https://raw.githubusercontent.com/ArchiveBox/ArchiveBox/${ARCHIVEBOX_BRANCH}/docker-compose.yml}"
ABXPKG_PACKAGE="${ABXPKG_PACKAGE:-abxpkg==1.12.41}"
ABXPKG_LIB_DIR="${ABXPKG_LIB_DIR:-$HOME/.cache/archivebox/setup-abxpkg}"
ARCHIVEBOX_HOME_DIR="$HOME/archivebox"
ARCHIVEBOX_DATA_DIR="$ARCHIVEBOX_HOME_DIR/data"
BOOTSTRAP_UV_BINARY=""
UV_BINARY=""
DOCKER_BINARY=""
@ -106,12 +108,30 @@ fix_root_install_ownership() {
}
ensure_archivebox_data_dir() {
mkdir -p "$HOME/archivebox/data"
mkdir -p "$ARCHIVEBOX_DATA_DIR"
if [ "$RUNNING_AS_ROOT" = "true" ]; then
chown "$ARCHIVEBOX_SYSTEM_UID:$ARCHIVEBOX_SYSTEM_GID" "$HOME/archivebox" "$HOME/archivebox/data"
chown "$ARCHIVEBOX_SYSTEM_UID:$ARCHIVEBOX_SYSTEM_GID" "$ARCHIVEBOX_HOME_DIR" "$ARCHIVEBOX_DATA_DIR"
fi
}
migrate_legacy_collection_dir() {
if [ ! -f "$ARCHIVEBOX_HOME_DIR/index.sqlite3" ]; then
return 0
fi
for path in "$ARCHIVEBOX_HOME_DIR"/* "$ARCHIVEBOX_HOME_DIR"/.[!.]* "$ARCHIVEBOX_HOME_DIR"/..?*; do
if [ ! -e "$path" ] && [ ! -L "$path" ]; then
continue
fi
case "$(basename "$path")" in
data|docker-compose.yml|compose.yml|compose.yaml|.env|Caddyfile)
continue
;;
esac
mv -n "$path" "$ARCHIVEBOX_DATA_DIR/"
done
}
docker_pull_archivebox() {
if [ -n "$ARCHIVEBOX_PLATFORM" ]; then
"$DOCKER_BINARY" pull --platform "$ARCHIVEBOX_PLATFORM" "$ARCHIVEBOX_IMAGE"
@ -159,7 +179,7 @@ wait_for_archivebox() {
attempt=1
while [ "$attempt" -le "$attempts" ]; do
if "$CURL_BINARY" -fsS -H "Host: ${host_header}" "$url" >/dev/null 2>&1; then
if "$CURL_BINARY" -fsS --connect-timeout 1 --max-time 2 -H "Host: ${host_header}" "$url" >/dev/null 2>&1; then
return 0
fi
sleep 1
@ -167,7 +187,7 @@ wait_for_archivebox() {
done
echo "[!] Server process started, but health check did not become ready at $url after ${attempts}s."
echo " Run the logs command below to inspect startup progress."
echo " Inspect $ARCHIVEBOX_DATA_DIR/logs/ or run 'docker compose logs' to diagnose startup."
return 1
}
@ -288,11 +308,14 @@ if [ -n "$DOCKER_BINARY" ] && "$DOCKER_BINARY" compose version > /dev/null && do
resolve_setup_curl
echo "[+] Initializing an ArchiveBox data folder at ~/archivebox/data using Docker Compose..."
ensure_archivebox_data_dir || exit 1
cd "$HOME/archivebox"
if [ -f "./index.sqlite3" ]; then
mv -i "$HOME"/archivebox/* "$HOME/archivebox/data/"
cd "$ARCHIVEBOX_HOME_DIR"
migrate_legacy_collection_dir
if [ ! -f docker-compose.yml ]; then
"$CURL_BINARY" -fsSL "$ARCHIVEBOX_COMPOSE_URL" > docker-compose.yml
if [ "$RUNNING_AS_ROOT" = "true" ]; then
chown "$ARCHIVEBOX_SYSTEM_UID:$ARCHIVEBOX_SYSTEM_GID" docker-compose.yml
fi
fi
"$CURL_BINARY" -fsSL "$ARCHIVEBOX_COMPOSE_URL" > docker-compose.yml
export ARCHIVEBOX_IMAGE ARCHIVEBOX_PLATFORM
docker_compose_run_archivebox init
docker_compose_run_archivebox install
@ -303,7 +326,7 @@ if [ -n "$DOCKER_BINARY" ] && "$DOCKER_BINARY" compose version > /dev/null && do
open_archivebox
echo
echo "[√] Server started on http://0.0.0.0:8000 and data directory initialized in ~/archivebox/data. Usage:"
echo " cd ~/archivebox"
echo " cd $ARCHIVEBOX_HOME_DIR"
echo " docker compose ps"
echo " docker compose down"
echo " ARCHIVEBOX_IMAGE=$ARCHIVEBOX_IMAGE docker compose pull"
@ -317,23 +340,22 @@ elif [ -n "$DOCKER_BINARY" ] && docker_pull_archivebox; then
resolve_setup_curl
echo "[+] Initializing an ArchiveBox data folder at ~/archivebox/data using Docker..."
ensure_archivebox_data_dir || exit 1
cd "$HOME/archivebox"
if [ -f "./index.sqlite3" ]; then
mv -i "$HOME"/archivebox/* "$HOME/archivebox/data/"
fi
cd "$ARCHIVEBOX_HOME_DIR"
migrate_legacy_collection_dir
cd ./data
docker_run_archivebox_init
docker_run_archivebox_install
echo
echo "[+] Starting ArchiveBox server using: docker run -d $ARCHIVEBOX_IMAGE..."
"$DOCKER_BINARY" rm -f archivebox >/dev/null 2>&1 || true
docker_run_archivebox_server
wait_for_archivebox
open_archivebox
echo
echo "[√] Server started on http://0.0.0.0:8000 and data directory initialized in ~/archivebox/data. Usage:"
echo " cd ~/archivebox/data"
echo " cd $ARCHIVEBOX_DATA_DIR"
echo " docker ps --filter name=archivebox"
echo " docker kill archivebox"
echo " docker rm -f archivebox"
echo " docker pull $ARCHIVEBOX_IMAGE"
echo " docker run $DOCKER_PLATFORM_ARGS -v $PWD:/data -d -p 8000:8000 --name=archivebox $ARCHIVEBOX_IMAGE"
echo " docker run $DOCKER_PLATFORM_ARGS -v $PWD:/data -it $ARCHIVEBOX_IMAGE manage createsuperuser"
@ -382,27 +404,25 @@ install_archivebox_with_uv
echo
echo "[+] Initializing ArchiveBox data folder at ~/archivebox/data..."
ensure_archivebox_data_dir || exit 1
cd "$HOME/archivebox"
if [ -f "./index.sqlite3" ]; then
mv -i "$HOME"/archivebox/* "$HOME/archivebox/data/"
fi
cd "$ARCHIVEBOX_HOME_DIR"
migrate_legacy_collection_dir
cd ./data
: | "$ARCHIVEBOX_BINARY" init # pipe in empty command to make sure stdin is closed
"$ARCHIVEBOX_BINARY" install
# init shows version output at the end too
echo
echo "[+] Starting ArchiveBox server using: nohup archivebox server &..."
nohup "$ARCHIVEBOX_BINARY" server 0.0.0.0:8000 > ./logs/server.log 2>&1 &
echo "[+] Starting ArchiveBox server using: archivebox server --daemonize..."
"$ARCHIVEBOX_BINARY" server --daemonize 0.0.0.0:8000
wait_for_archivebox
open_archivebox
echo
echo "[√] Server started on http://0.0.0.0:8000 and data directory initialized in ~/archivebox/data. Usage:"
echo " cd ~/archivebox/data # see your data dir"
echo " cd $ARCHIVEBOX_DATA_DIR # see your data dir"
echo " archivebox server --quick-init 0.0.0.0:8000 # start server process"
echo " archivebox manage createsuperuser # add an admin user+pass"
echo " ps aux | grep archivebox # see server process pid"
echo " pkill -f archivebox # stop the server"
echo " uv tool install --python $ARCHIVEBOX_PYTHON --upgrade '$ARCHIVEBOX_PACKAGE'; archivebox init; archivebox install # update versions"
echo " curl -fsSL 'https://raw.githubusercontent.com/ArchiveBox/ArchiveBox/dev/bin/setup.sh' | bash # update versions"
echo " archivebox add 'https://example.com'" # archive a new URL
echo " archivebox list # see URLs archived"
echo " archivebox help # see more help & examples"