diff --git a/debian13/Dockerfile b/debian13/Dockerfile index 6a832e5..77a41e6 100644 --- a/debian13/Dockerfile +++ b/debian13/Dockerfile @@ -824,3 +824,13 @@ RUN mkdir -p ${PREFIX}/share/source-stack \ && sed "s|@MULTIARCH@|$(gcc -dumpmachine)|" /tmp/source-stack.cmake.in \ > ${PREFIX}/share/source-stack/source-stack.cmake \ && rm /tmp/source-stack.cmake.in + +RUN useradd --create-home develop +USER develop + +ENV CLAUDE_CONFIG_DIR="$HOME/my-claude" +ENV DISABLE_AUTOUPDATER="1" +RUN bash -c 'curl -fsSL https://claude.ai/install.sh | bash' + +ARG CLAUDE_CODE_OAUTH_TOKEN +ENV CLAUDE_CODE_OAUTH_TOKEN=${CLAUDE_CODE_OAUTH_TOKEN} diff --git a/debian13/build.sh b/debian13/build.sh index d9c50bf..a597409 100755 --- a/debian13/build.sh +++ b/debian13/build.sh @@ -1,10 +1,38 @@ #!/bin/sh +# Usage: +# ./build.sh build the image, asking for the password that unlocks the token +# ./build.sh --encrypt encrypt a token and print the value to paste into ENCRYPTED_TOKEN set -eu IMAGE_NAME="${IMAGE_NAME:-debian13-source-stack}" PREFIX="${PREFIX:-/opt/local}" SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd) + +# CLAUDE_CODE_OAUTH_TOKEN encrypted with AES-256-CBC (PBKDF2, base64). Generate with --encrypt. +ENCRYPTED_TOKEN='U2FsdGVkX1/BCTASs0tR40hsT+sngp46zANCbGZnklLN1M0wSJs/DxbQ6JDg593G09A+cVtVius4hJHRzB6caOO2KwBV0/+i7yUjr/PfreZksrdkz1DnFc7oorxXfvB7azuNEkQfAE2fZg8cnYL5jy3/LKRdAm11SUm83fU8ke8=' + +OPENSSL_ARGS="enc -aes-256-cbc -pbkdf2 -iter 600000 -a -A" + +if ! command -v openssl >/dev/null 2>&1; then + echo "Error: OpenSSL is required." >&2 + exit 1 +fi + +# read_secret PROMPT VARNAME: read the input with echo on, so it stays visible while typing. +read_secret() { + printf '%s' "$1" >&2 + IFS= read -r "$2" +} + +if [ "${1:-}" = "--encrypt" ]; then + read_secret "OAuth token: " token + read_secret "Password: " BUILD_PASSWORD + export BUILD_PASSWORD + printf '%s' "$token" | openssl $OPENSSL_ARGS -pass env:BUILD_PASSWORD + echo + exit 0 +fi SOURCES_DIR="${SOURCES_DIR:-$SCRIPT_DIR/../sources}" FETCH_SCRIPT="$SCRIPT_DIR/../fetch-sources.sh" @@ -13,6 +41,22 @@ if ! command -v podman >/dev/null 2>&1; then exit 1 fi +if [ -z "$ENCRYPTED_TOKEN" ]; then + echo "Error: ENCRYPTED_TOKEN is empty; run './build.sh --encrypt' and paste the output into build.sh." >&2 + exit 1 +fi + +read_secret "Password for CLAUDE_CODE_OAUTH_TOKEN: " BUILD_PASSWORD +export BUILD_PASSWORD +if ! CLAUDE_CODE_OAUTH_TOKEN=$(printf '%s' "$ENCRYPTED_TOKEN" | openssl $OPENSSL_ARGS -d -pass env:BUILD_PASSWORD 2>/dev/null); then + echo "Error: wrong password or corrupted token." >&2 + exit 1 +fi +unset BUILD_PASSWORD + +# Exported so podman reads the value from the environment and it never appears in the command line. +export CLAUDE_CODE_OAUTH_TOKEN + SOURCES_DIR="$SOURCES_DIR" "$FETCH_SCRIPT" # macOS reports arm64 where Linux (and Debian multiarch) call it aarch64. @@ -20,6 +64,8 @@ ARCH=$(uname -m) [ "$ARCH" = arm64 ] && ARCH=aarch64 echo "Building image $IMAGE_NAME with podman (prefix $PREFIX) ..." -exec podman build --build-context sources="$SOURCES_DIR" \ +exec podman build \ + --build-arg CLAUDE_CODE_OAUTH_TOKEN \ + --build-context sources="$SOURCES_DIR" \ --build-arg PREFIX="$PREFIX" --build-arg MULTIARCH="$ARCH-linux-gnu" \ --tag "$IMAGE_NAME" "$SCRIPT_DIR"