changes to bash app
This commit is contained in:
@@ -33,6 +33,46 @@ Commands:
|
|||||||
EOF
|
EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Ensure a path exists as a directory.
|
||||||
|
#
|
||||||
|
# This deliberately fails if the path already exists as a file. We don't want
|
||||||
|
# to silently replace a file with a directory because Docker bind mounts are
|
||||||
|
# sensitive to source/target types.
|
||||||
|
ensure_dir() {
|
||||||
|
local path="$1"
|
||||||
|
|
||||||
|
if [ -e "$path" ] && [ ! -d "$path" ]; then
|
||||||
|
echo "ERROR: expected directory, but found a non-directory:" >&2
|
||||||
|
echo " $path" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p "$path"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Ensure a path exists as a regular file.
|
||||||
|
#
|
||||||
|
# This deliberately fails if the path already exists as a directory. Docker
|
||||||
|
# will otherwise produce the confusing:
|
||||||
|
#
|
||||||
|
# not a directory: Are you trying to mount a directory onto a file
|
||||||
|
#
|
||||||
|
ensure_file() {
|
||||||
|
local path="$1"
|
||||||
|
|
||||||
|
if [ -e "$path" ] && [ ! -f "$path" ]; then
|
||||||
|
echo "ERROR: expected regular file, but found a directory or other type:" >&2
|
||||||
|
echo " $path" >&2
|
||||||
|
echo >&2
|
||||||
|
echo "Remove or rename the incorrect path, then run ./claudaris start again." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -e "$path" ]; then
|
||||||
|
touch "$path"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
cmd_config() {
|
cmd_config() {
|
||||||
echo "claudaris config — press enter to keep the current/default value."
|
echo "claudaris config — press enter to keep the current/default value."
|
||||||
echo
|
echo
|
||||||
@@ -71,42 +111,67 @@ cmd_build() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cmd_start() {
|
cmd_start() {
|
||||||
# Seed host copies of .bashrc and bash_aliases, without clobbering any
|
echo "Preparing persistent directories and files under:"
|
||||||
# customization already made on this host. Both are bind-mounted as
|
echo " $DATA_DIR"
|
||||||
# single files below so they can be tweaked per-host (e.g. a coworker
|
echo
|
||||||
# importing their own aliases) without rebuilding the image.
|
|
||||||
mkdir -p "$DATA_DIR/home"
|
|
||||||
[ -f "$DATA_DIR/home/.bashrc" ] || cp "$REPO_DIR/files/bashrc" "$DATA_DIR/home/.bashrc"
|
|
||||||
[ -f "$DATA_DIR/home/bash_aliases" ] || cp "$REPO_DIR/files/bash_aliases" "$DATA_DIR/home/bash_aliases"
|
|
||||||
|
|
||||||
# Two files carry everything needed to stay logged in: .credentials.json
|
# ---------------------------------------------------------------------------
|
||||||
# (the OAuth token) and claude.json (account/onboarding state — Claude Code
|
# Home / Bash
|
||||||
# checks this too, so persisting the token alone isn't enough to avoid a
|
# ---------------------------------------------------------------------------
|
||||||
# re-login prompt after a rebuild). Each is bind-mounted individually,
|
|
||||||
# same as .bashrc above, seeded empty on first run so Docker doesn't create
|
|
||||||
# a directory in its place. Individual file mounts (rather than a directory
|
|
||||||
# volume + in-container symlink) matter here: Claude Code likely saves
|
|
||||||
# these atomically (write a temp file, then rename() over the target), and
|
|
||||||
# rename() onto a symlink replaces the symlink instead of writing through
|
|
||||||
# it — silently breaking persistence after the first write. A bind mount
|
|
||||||
# doesn't have that failure mode.
|
|
||||||
mkdir -p "$DATA_DIR/claude"
|
|
||||||
[ -f "$DATA_DIR/claude/credentials.json" ] || touch "$DATA_DIR/claude/credentials.json"
|
|
||||||
[ -f "$DATA_DIR/claude/claude.json" ] || touch "$DATA_DIR/claude/claude.json"
|
|
||||||
|
|
||||||
# OpenCode stores provider credentials (API keys/OAuth tokens) in a single
|
# /data/claudaris/home must be a directory.
|
||||||
# auth.json, same atomic-write concern as Claude Code above, so it gets the
|
ensure_dir "$DATA_DIR/home"
|
||||||
# same individual-file bind mount treatment.
|
|
||||||
mkdir -p "$DATA_DIR/opencode"
|
# .bashrc is bind-mounted to /root/.bashrc, so it MUST be a file.
|
||||||
[ -f "$DATA_DIR/opencode/auth.json" ] || touch "$DATA_DIR/opencode/auth.json"
|
if [ ! -e "$DATA_DIR/home/.bashrc" ]; then
|
||||||
|
cp "$REPO_DIR/files/bashrc" "$DATA_DIR/home/.bashrc"
|
||||||
|
elif [ ! -f "$DATA_DIR/home/.bashrc" ]; then
|
||||||
|
echo "ERROR: $DATA_DIR/home/.bashrc exists but is not a regular file." >&2
|
||||||
|
echo "Please remove or rename it, then run ./claudaris start again." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# bash_aliases is bind-mounted to /opt/dotfiles/bash_aliases, which is a
|
||||||
|
# regular file in the image, so the host source MUST also be a regular file.
|
||||||
|
if [ ! -e "$DATA_DIR/home/bash_aliases" ]; then
|
||||||
|
cp "$REPO_DIR/files/bash_aliases" "$DATA_DIR/home/bash_aliases"
|
||||||
|
elif [ ! -f "$DATA_DIR/home/bash_aliases" ]; then
|
||||||
|
echo "ERROR: $DATA_DIR/home/bash_aliases exists but is not a regular file." >&2
|
||||||
|
echo "Please remove or rename it, then run ./claudaris start again." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Claude Code
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
ensure_dir "$DATA_DIR/claude"
|
||||||
|
|
||||||
|
# Both of these are individual file bind mounts. They MUST be files.
|
||||||
|
# Empty files are intentional on first run; Claude Code will populate them.
|
||||||
|
ensure_file "$DATA_DIR/claude/credentials.json"
|
||||||
|
ensure_file "$DATA_DIR/claude/claude.json"
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# OpenCode
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
ensure_dir "$DATA_DIR/opencode"
|
||||||
|
|
||||||
|
# Individual file bind mount; MUST be a file.
|
||||||
|
ensure_file "$DATA_DIR/opencode/auth.json"
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Optional SSH mount
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
# Optional: mount ~/.ssh into the container (read-only) for connecting out to
|
# Optional: mount ~/.ssh into the container (read-only) for connecting out to
|
||||||
# other nodes. Opt in by creating $DATA_DIR/ssh and populating it with
|
# other nodes. Opt in by creating $DATA_DIR/ssh and populating it with
|
||||||
# keys/config before starting the container. docker-compose.yml doesn't
|
# keys/config before starting the container.
|
||||||
# list this mount (compose can't make a volume conditional on a host path
|
#
|
||||||
# existing), so it's added via a gitignored override file that compose
|
# docker-compose.yml doesn't list this mount because Compose can't make a
|
||||||
# picks up automatically when present, and removed when the opt-in host
|
# volume conditional on a host path existing. Instead, create a gitignored
|
||||||
# dir isn't there.
|
# override file that Compose picks up automatically.
|
||||||
if [ -d "$DATA_DIR/ssh" ]; then
|
if [ -d "$DATA_DIR/ssh" ]; then
|
||||||
cat > "$REPO_DIR/docker-compose.override.yml" <<EOF
|
cat > "$REPO_DIR/docker-compose.override.yml" <<EOF
|
||||||
services:
|
services:
|
||||||
@@ -114,10 +179,33 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
- $DATA_DIR/ssh:/root/.ssh:ro
|
- $DATA_DIR/ssh:/root/.ssh:ro
|
||||||
EOF
|
EOF
|
||||||
|
elif [ -e "$DATA_DIR/ssh" ]; then
|
||||||
|
echo "ERROR: $DATA_DIR/ssh exists but is not a directory." >&2
|
||||||
|
echo "Please remove or rename it, then run ./claudaris start again." >&2
|
||||||
|
exit 1
|
||||||
else
|
else
|
||||||
rm -f "$REPO_DIR/docker-compose.override.yml"
|
rm -f "$REPO_DIR/docker-compose.override.yml"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Show mount sources before Docker starts.
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
echo "Persistent paths:"
|
||||||
|
printf ' %-15s %s\n' "home/" "$DATA_DIR/home/"
|
||||||
|
printf ' %-15s %s\n' ".bashrc" "$DATA_DIR/home/.bashrc"
|
||||||
|
printf ' %-15s %s\n' "bash_aliases/" "$DATA_DIR/home/bash_aliases/"
|
||||||
|
printf ' %-15s %s\n' "credentials" "$DATA_DIR/claude/credentials.json"
|
||||||
|
printf ' %-15s %s\n' "claude.json" "$DATA_DIR/claude/claude.json"
|
||||||
|
printf ' %-15s %s\n' "auth.json" "$DATA_DIR/opencode/auth.json"
|
||||||
|
|
||||||
|
if [ -d "$DATA_DIR/ssh" ]; then
|
||||||
|
printf ' %-15s %s\n' "ssh/" "$DATA_DIR/ssh/"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "Starting container..."
|
||||||
|
|
||||||
docker compose up -d
|
docker compose up -d
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,4 +237,4 @@ case "${1:-help}" in
|
|||||||
usage >&2
|
usage >&2
|
||||||
exit 1
|
exit 1
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
Reference in New Issue
Block a user