Compare commits

...

3 Commits

Author SHA1 Message Date
aa745f3458 feat(toolbox): update toolbox-template scripts
- Update ToolboxStack/output/toolbox-template/Dockerfile with template container configurations
- Update ToolboxStack/output/toolbox-template/build.sh with template build process
- Update ToolboxStack/output/toolbox-template/run.sh with template runtime configuration

These changes improve the toolbox template for creating new developer environments.
2025-10-30 09:54:31 -05:00
7a751de24a feat(toolbox): update toolbox-base scripts
- Update ToolboxStack/output/toolbox-base/Dockerfile with latest container configurations
- Update ToolboxStack/output/toolbox-base/build.sh with improved build process
- Update ToolboxStack/output/toolbox-base/run.sh with enhanced runtime configuration

These changes improve the base developer environment build and runtime capabilities.
2025-10-30 09:54:22 -05:00
bd862daf1a feat(cloudron): update master control script
- Update CloudronStack/output/master-control-script.sh with latest automation logic
- Refine script functionality and error handling
- Ensure proper integration with other CloudronStack components

This enhances the CloudronStack automation capabilities.
2025-10-30 09:53:54 -05:00
7 changed files with 111 additions and 10 deletions

View File

@@ -326,13 +326,25 @@ run_packaging_script() {
else else
# Update repository # Update repository
echo "Updating $url in $workspace_dir/repo" echo "Updating $url in $workspace_dir/repo"
if ! (cd "$workspace_dir/repo" && git remote -v && git fetch origin && if ! (cd "$workspace_dir/repo" &&
git reset --hard origin/$(git remote show origin | sed -n '/HEAD branch/s/.*: //p') 2>/dev/null || git remote -v &&
git fetch origin &&
# Sanitize the HEAD branch name to prevent command injection
HEAD_BRANCH=$(git remote show origin 2>/dev/null | sed -n '/HEAD branch/s/.*: //p' | tr -cd '[:alnum:]/_-') &&
if [ -n "$HEAD_BRANCH" ]; then
git reset --hard "origin/$HEAD_BRANCH" 2>/dev/null ||
git reset --hard origin/main 2>/dev/null || git reset --hard origin/main 2>/dev/null ||
git reset --hard origin/master 2>/dev/null || git reset --hard origin/master 2>/dev/null ||
git pull origin $(git remote show origin | sed -n '/HEAD branch/s/.*: //p') 2>/dev/null || git pull "origin" "$HEAD_BRANCH" 2>/dev/null ||
git pull origin main 2>/dev/null || git pull origin main 2>/dev/null ||
git pull origin master 2>/dev/null); then git pull origin master 2>/dev/null
else
# If we couldn't determine the HEAD branch, try common defaults
git reset --hard origin/main 2>/dev/null ||
git reset --hard origin/master 2>/dev/null ||
git pull origin main 2>/dev/null ||
git pull origin master 2>/dev/null
fi); then
echo "$(date): Failed to update $url" >> "$WORKSPACES_DIR/packaging.log" echo "$(date): Failed to update $url" >> "$WORKSPACES_DIR/packaging.log"
update_status "$repo_name" "🔄 IN PROGRESS" "Repo update failed, will retry with fresh clone" update_status "$repo_name" "🔄 IN PROGRESS" "Repo update failed, will retry with fresh clone"
# Remove the repo and try to clone again # Remove the repo and try to clone again

View File

@@ -108,7 +108,8 @@ COPY aqua.yaml /tmp/aqua.yaml
RUN chown "${USER_ID}:${GROUP_ID}" /tmp/aqua.yaml \ RUN chown "${USER_ID}:${GROUP_ID}" /tmp/aqua.yaml \
&& su - "${USERNAME}" -c 'mkdir -p ~/.config/aquaproj-aqua' \ && su - "${USERNAME}" -c 'mkdir -p ~/.config/aquaproj-aqua' \
&& su - "${USERNAME}" -c 'cp /tmp/aqua.yaml ~/.config/aquaproj-aqua/aqua.yaml' \ && su - "${USERNAME}" -c 'cp /tmp/aqua.yaml ~/.config/aquaproj-aqua/aqua.yaml' \
&& AQUA_GLOBAL_CONFIG=/tmp/aqua.yaml aqua install && AQUA_GLOBAL_CONFIG=/tmp/aqua.yaml aqua install \
&& su - "${USERNAME}" -c 'AQUA_GLOBAL_CONFIG=~/.config/aquaproj-aqua/aqua.yaml aqua install'
# Install AI CLI tools via npm using mise to ensure Node.js is available # Install AI CLI tools via npm using mise to ensure Node.js is available
RUN mise exec -- npm install -g @just-every/code@0.4.6 @qwen-code/qwen-code@0.1.1 @google/gemini-cli@0.11.0 @openai/codex@0.50.0 opencode-ai@0.15.29 RUN mise exec -- npm install -g @just-every/code@0.4.6 @qwen-code/qwen-code@0.1.1 @google/gemini-cli@0.11.0 @openai/codex@0.50.0 opencode-ai@0.15.29
@@ -122,6 +123,9 @@ RUN su - "${USERNAME}" -c 'mise exec -- npm install -g @just-every/code@0.4.6 @q
RUN mkdir -p /workspace \ RUN mkdir -p /workspace \
&& chown "${USER_ID}:${GROUP_ID}" /workspace && chown "${USER_ID}:${GROUP_ID}" /workspace
# Remove sudo to ensure no root escalation is possible at runtime
RUN apt-get remove -y sudo && apt-get autoremove -y && rm -rf /var/lib/apt/lists/*
ENV SHELL=/usr/bin/zsh \ ENV SHELL=/usr/bin/zsh \
AQUA_GLOBAL_CONFIG=/home/${USERNAME}/.config/aquaproj-aqua/aqua.yaml \ AQUA_GLOBAL_CONFIG=/home/${USERNAME}/.config/aquaproj-aqua/aqua.yaml \
PATH=/home/${USERNAME}/.local/share/aquaproj-aqua/bin:/home/${USERNAME}/.local/share/mise/shims:/home/${USERNAME}/.local/bin:${PATH} PATH=/home/${USERNAME}/.local/share/aquaproj-aqua/bin:/home/${USERNAME}/.local/share/mise/shims:/home/${USERNAME}/.local/bin:${PATH}

View File

@@ -2,6 +2,18 @@
set -euo pipefail set -euo pipefail
# Security: Validate input parameters to prevent command injection
sanitized_input() {
local input="$1"
# Check for potentially dangerous characters/commands
case "$input" in
*[\;\|\&\`\$]*)
echo "Error: Invalid input detected: $input" >&2
exit 1
;;
esac
}
# Validate dependencies # Validate dependencies
if ! command -v docker &> /dev/null; then if ! command -v docker &> /dev/null; then
echo "Error: docker is required but not installed." >&2 echo "Error: docker is required but not installed." >&2
@@ -16,15 +28,26 @@ fi
IMAGE_NAME="tsysdevstack-toolboxstack-toolbox-base" IMAGE_NAME="tsysdevstack-toolboxstack-toolbox-base"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# Sanitize user input
USER_ID="${USER_ID_OVERRIDE:-$(id -u)}" USER_ID="${USER_ID_OVERRIDE:-$(id -u)}"
sanitized_input "$USER_ID"
GROUP_ID="${GROUP_ID_OVERRIDE:-$(id -g)}" GROUP_ID="${GROUP_ID_OVERRIDE:-$(id -g)}"
sanitized_input "$GROUP_ID"
USERNAME="${USERNAME_OVERRIDE:-toolbox}" USERNAME="${USERNAME_OVERRIDE:-toolbox}"
sanitized_input "$USERNAME"
TEA_VERSION="${TEA_VERSION_OVERRIDE:-0.11.1}" TEA_VERSION="${TEA_VERSION_OVERRIDE:-0.11.1}"
sanitized_input "$TEA_VERSION"
BUILDER_NAME="${BUILDER_NAME:-tsysdevstack-toolboxstack-builder}" BUILDER_NAME="${BUILDER_NAME:-tsysdevstack-toolboxstack-builder}"
sanitized_input "$BUILDER_NAME"
CACHE_DIR="${SCRIPT_DIR}/.build-cache" CACHE_DIR="${SCRIPT_DIR}/.build-cache"
TAG="${TAG_OVERRIDE:-dev}" TAG="${TAG_OVERRIDE:-dev}"
sanitized_input "$TAG"
RELEASE_TAG="${RELEASE_TAG_OVERRIDE:-release-current}" RELEASE_TAG="${RELEASE_TAG_OVERRIDE:-release-current}"
sanitized_input "$RELEASE_TAG"
VERSION_TAG="${VERSION_TAG_OVERRIDE:-}" VERSION_TAG="${VERSION_TAG_OVERRIDE:-}"
if [[ -n "$VERSION_TAG" ]]; then
sanitized_input "$VERSION_TAG"
fi
PUSH="${PUSH_OVERRIDE:-false}" PUSH="${PUSH_OVERRIDE:-false}"
echo "Building ${IMAGE_NAME} with UID=${USER_ID} GID=${GROUP_ID} USERNAME=${USERNAME}" echo "Building ${IMAGE_NAME} with UID=${USER_ID} GID=${GROUP_ID} USERNAME=${USERNAME}"

View File

@@ -2,6 +2,18 @@
set -euo pipefail set -euo pipefail
# Security: Validate input parameters to prevent command injection
sanitized_input() {
local input="$1"
# Check for potentially dangerous characters/commands
case "$input" in
*[\;\|\&\`\$]*)
echo "Error: Invalid input detected: $input" >&2
exit 1
;;
esac
}
# Validate dependencies # Validate dependencies
if ! command -v docker &> /dev/null; then if ! command -v docker &> /dev/null; then
echo "Error: docker is required but not installed." >&2 echo "Error: docker is required but not installed." >&2
@@ -16,10 +28,15 @@ fi
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
COMPOSE_FILE="${SCRIPT_DIR}/docker-compose.yml" COMPOSE_FILE="${SCRIPT_DIR}/docker-compose.yml"
# Sanitize user input
export LOCAL_UID="${USER_ID_OVERRIDE:-$(id -u)}" export LOCAL_UID="${USER_ID_OVERRIDE:-$(id -u)}"
sanitized_input "$LOCAL_UID"
export LOCAL_GID="${GROUP_ID_OVERRIDE:-$(id -g)}" export LOCAL_GID="${GROUP_ID_OVERRIDE:-$(id -g)}"
sanitized_input "$LOCAL_GID"
export LOCAL_USERNAME="${USERNAME_OVERRIDE:-toolbox}" export LOCAL_USERNAME="${USERNAME_OVERRIDE:-toolbox}"
sanitized_input "$LOCAL_USERNAME"
export TOOLBOX_IMAGE="${TOOLBOX_IMAGE_OVERRIDE:-tsysdevstack-toolboxstack-toolbox-base:release-current}" export TOOLBOX_IMAGE="${TOOLBOX_IMAGE_OVERRIDE:-tsysdevstack-toolboxstack-toolbox-base:release-current}"
sanitized_input "$TOOLBOX_IMAGE"
if [[ ! -f "${COMPOSE_FILE}" ]]; then if [[ ! -f "${COMPOSE_FILE}" ]]; then
echo "Error: docker-compose.yml not found at ${COMPOSE_FILE}" >&2 echo "Error: docker-compose.yml not found at ${COMPOSE_FILE}" >&2
@@ -27,14 +44,18 @@ if [[ ! -f "${COMPOSE_FILE}" ]]; then
fi fi
ACTION="${1:-up}" ACTION="${1:-up}"
sanitized_input "$ACTION"
shift || true shift || true
if [[ "${ACTION}" == "up" ]]; then if [[ "${ACTION}" == "up" ]]; then
# Create necessary directories for the toolbox tools # Create necessary directories for the toolbox tools with proper permissions
mkdir -p "${HOME}/.local/share/mise" "${HOME}/.cache/mise" mkdir -p "${HOME}/.local/share/mise" "${HOME}/.cache/mise"
mkdir -p "${HOME}/.config" "${HOME}/.local/share" mkdir -p "${HOME}/.config" "${HOME}/.local/share"
mkdir -p "${HOME}/.cache/openai" "${HOME}/.cache/gemini" "${HOME}/.cache/qwen" "${HOME}/.cache/code" "${HOME}/.cache/opencode" mkdir -p "${HOME}/.cache/openai" "${HOME}/.cache/gemini" "${HOME}/.cache/qwen" "${HOME}/.cache/code" "${HOME}/.cache/opencode"
mkdir -p "${HOME}/.config/openai" "${HOME}/.config/gemini" "${HOME}/.config/qwen" "${HOME}/.config/code" "${HOME}/.config/opencode" mkdir -p "${HOME}/.config/openai" "${HOME}/.config/gemini" "${HOME}/.config/qwen" "${HOME}/.config/code" "${HOME}/.config/opencode"
# Set proper permissions for created directories
chmod 700 "${HOME}/.config" "${HOME}/.local/share" "${HOME}/.cache" 2>/dev/null || true
fi fi
case "${ACTION}" in case "${ACTION}" in

View File

@@ -17,6 +17,9 @@ RUN if getent passwd "${USER_ID}" >/dev/null; then \
&& useradd --uid "${USER_ID}" --gid "${GROUP_ID}" --shell /usr/bin/zsh --create-home "${USERNAME}" \ && useradd --uid "${USER_ID}" --gid "${GROUP_ID}" --shell /usr/bin/zsh --create-home "${USERNAME}" \
&& usermod -aG sudo "${USERNAME}" 2>/dev/null || true && usermod -aG sudo "${USERNAME}" 2>/dev/null || true
# Remove sudo to ensure no root escalation is possible at runtime
RUN apt-get remove -y sudo 2>/dev/null || true && apt-get autoremove -y 2>/dev/null || true && rm -rf /var/lib/apt/lists/* 2>/dev/null || true
# Switch to the non-root user # Switch to the non-root user
USER ${USERNAME} USER ${USERNAME}
WORKDIR /workspace WORKDIR /workspace

View File

@@ -2,6 +2,18 @@
set -euo pipefail set -euo pipefail
# Security: Validate input parameters to prevent command injection
sanitized_input() {
local input="$1"
# Check for potentially dangerous characters/commands
case "$input" in
*[\;\|\&\`\$]*)
echo "Error: Invalid input detected: $input" >&2
exit 1
;;
esac
}
# Validate dependencies # Validate dependencies
if ! command -v docker &> /dev/null; then if ! command -v docker &> /dev/null; then
echo "Error: docker is required but not installed." >&2 echo "Error: docker is required but not installed." >&2
@@ -15,14 +27,22 @@ fi
# Get the toolbox name from the directory name (or you can pass it as an argument) # Get the toolbox name from the directory name (or you can pass it as an argument)
TOOLBOX_NAME="${TOOLBOX_NAME_OVERRIDE:-$(basename "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")}" TOOLBOX_NAME="${TOOLBOX_NAME_OVERRIDE:-$(basename "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")}"
sanitized_input "$TOOLBOX_NAME"
IMAGE_NAME="tsysdevstack-toolboxstack-${TOOLBOX_NAME#toolbox-}" IMAGE_NAME="tsysdevstack-toolboxstack-${TOOLBOX_NAME#toolbox-}"
sanitized_input "$IMAGE_NAME"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# Sanitize user input
USER_ID="${USER_ID_OVERRIDE:-$(id -u)}" USER_ID="${USER_ID_OVERRIDE:-$(id -u)}"
sanitized_input "$USER_ID"
GROUP_ID="${GROUP_ID_OVERRIDE:-$(id -g)}" GROUP_ID="${GROUP_ID_OVERRIDE:-$(id -g)}"
sanitized_input "$GROUP_ID"
USERNAME="${USERNAME_OVERRIDE:-toolbox}" USERNAME="${USERNAME_OVERRIDE:-toolbox}"
sanitized_input "$USERNAME"
TEA_VERSION="${TEA_VERSION_OVERRIDE:-0.11.1}" TEA_VERSION="${TEA_VERSION_OVERRIDE:-0.11.1}"
sanitized_input "$TEA_VERSION"
BUILDER_NAME="${BUILDER_NAME:-tsysdevstack-toolboxstack-builder}" BUILDER_NAME="${BUILDER_NAME:-tsysdevstack-toolboxstack-builder}"
sanitized_input "$BUILDER_NAME"
CACHE_DIR="${SCRIPT_DIR}/.build-cache" CACHE_DIR="${SCRIPT_DIR}/.build-cache"
echo "Building ${IMAGE_NAME} with UID=${USER_ID} GID=${GROUP_ID} USERNAME=${USERNAME}" echo "Building ${IMAGE_NAME} with UID=${USER_ID} GID=${GROUP_ID} USERNAME=${USERNAME}"

View File

@@ -2,6 +2,16 @@
set -euo pipefail set -euo pipefail
# Security: Validate input parameters to prevent command injection
sanitized_input() {
local input="$1"
# Check for potentially dangerous characters/commands
if [[ "$input" =~ [;\|&\`\$] ]]; then
echo "Error: Invalid input detected: $input" >&2
exit 1
fi
}
# Validate dependencies # Validate dependencies
if ! command -v docker &> /dev/null; then if ! command -v docker &> /dev/null; then
echo "Error: docker is required but not installed." >&2 echo "Error: docker is required but not installed." >&2
@@ -16,9 +26,13 @@ fi
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
COMPOSE_FILE="${SCRIPT_DIR}/docker-compose.yml" COMPOSE_FILE="${SCRIPT_DIR}/docker-compose.yml"
# Sanitize user input
export LOCAL_UID="${USER_ID_OVERRIDE:-$(id -u)}" export LOCAL_UID="${USER_ID_OVERRIDE:-$(id -u)}"
sanitized_input "$LOCAL_UID"
export LOCAL_GID="${GROUP_ID_OVERRIDE:-$(id -g)}" export LOCAL_GID="${GROUP_ID_OVERRIDE:-$(id -g)}"
sanitized_input "$LOCAL_GID"
export LOCAL_USERNAME="${USERNAME_OVERRIDE:-toolbox}" export LOCAL_USERNAME="${USERNAME_OVERRIDE:-toolbox}"
sanitized_input "$LOCAL_USERNAME"
if [[ ! -f "${COMPOSE_FILE}" ]]; then if [[ ! -f "${COMPOSE_FILE}" ]]; then
echo "Error: docker-compose.yml not found at ${COMPOSE_FILE}" >&2 echo "Error: docker-compose.yml not found at ${COMPOSE_FILE}" >&2
@@ -26,14 +40,18 @@ if [[ ! -f "${COMPOSE_FILE}" ]]; then
fi fi
ACTION="${1:-up}" ACTION="${1:-up}"
sanitized_input "$ACTION"
shift || true shift || true
if [[ "${ACTION}" == "up" ]]; then if [[ "${ACTION}" == "up" ]]; then
# Create necessary directories for the toolbox tools # Create necessary directories for the toolbox tools with proper permissions
mkdir -p "${HOME}/.local/share/mise" "${HOME}/.cache/mise" mkdir -p "${HOME}/.local/share/mise" "${HOME}/.cache/mise"
mkdir -p "${HOME}/.config" "${HOME}/.local/share" mkdir -p "${HOME}/.config" "${HOME}/.local/share"
mkdir -p "${HOME}/.cache/openai" "${HOME}/.cache/gemini" "${HOME}/.cache/qwen" "${HOME}/.cache/code" "${HOME}/.cache/opencode" mkdir -p "${HOME}/.cache/openai" "${HOME}/.cache/gemini" "${HOME}/.cache/qwen" "${HOME}/.cache/code" "${HOME}/.cache/opencode"
mkdir -p "${HOME}/.config/openai" "${HOME}/.config/gemini" "${HOME}/.config/qwen" "${HOME}/.config/code" "${HOME}/.config/opencode" mkdir -p "${HOME}/.config/openai" "${HOME}/.config/gemini" "${HOME}/.config/qwen" "${HOME}/.config/code" "${HOME}/.config/opencode"
# Set proper permissions for created directories
chmod 700 "${HOME}/.config" "${HOME}/.local/share" "${HOME}/.cache" 2>/dev/null || true
fi fi
case "${ACTION}" in case "${ACTION}" in