diff --git a/.gitignore b/.gitignore index f554491..e0f43a1 100644 --- a/.gitignore +++ b/.gitignore @@ -59,6 +59,7 @@ artifacts/SupportStack/config/wakaapi/database/*.db artifacts/SupportStack/config/wakaapi/database/*.db-journal artifacts/SupportStack/config/homepage/logs/ artifacts/SupportStack/docker-compose/config/ +artifacts/ToolboxStack/toolbox-base/.build-cache/ # Local Docker volumes .docker-volumes/ @@ -81,4 +82,4 @@ temp/ *.backup # System files -.SynologyWorkingDirectory \ No newline at end of file +.SynologyWorkingDirectory diff --git a/artifacts/ToolboxStack/toolbox-base/Dockerfile b/artifacts/ToolboxStack/toolbox-base/Dockerfile index 57afc77..5a86002 100644 --- a/artifacts/ToolboxStack/toolbox-base/Dockerfile +++ b/artifacts/ToolboxStack/toolbox-base/Dockerfile @@ -3,10 +3,13 @@ FROM ubuntu:24.04 ARG USER_ID=1000 ARG GROUP_ID=1000 ARG USERNAME=toolbox +ARG TEA_VERSION=0.11.1 ENV DEBIAN_FRONTEND=noninteractive -RUN apt-get update \ +RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ + --mount=type=cache,target=/var/lib/apt/lists,sharing=locked \ + apt-get update \ && apt-get install -y --no-install-recommends \ ca-certificates \ curl \ @@ -39,6 +42,13 @@ RUN apt-get update \ RUN ln -sf /usr/bin/fdfind /usr/local/bin/fd \ && ln -sf /usr/bin/batcat /usr/local/bin/bat +# Install Gitea tea CLI +RUN curl -fsSL "https://dl.gitea.io/tea/${TEA_VERSION}/tea-${TEA_VERSION}-linux-amd64" -o /tmp/tea \ + && curl -fsSL "https://dl.gitea.io/tea/${TEA_VERSION}/tea-${TEA_VERSION}-linux-amd64.sha256" -o /tmp/tea.sha256 \ + && sed -n 's/ .*//p' /tmp/tea.sha256 | awk '{print $1 " /tmp/tea"}' | sha256sum -c - \ + && install -m 0755 /tmp/tea /usr/local/bin/tea \ + && rm -f /tmp/tea /tmp/tea.sha256 + # Configure locale to ensure consistent tool behavior RUN locale-gen en_US.UTF-8 ENV LANG=en_US.UTF-8 \ @@ -65,21 +75,23 @@ RUN if getent passwd "${USER_ID}" >/dev/null; then \ fi \ && useradd --uid "${USER_ID}" --gid "${GROUP_ID}" --shell /usr/bin/zsh --create-home "${USERNAME}" -# Install Oh My Zsh for the unprivileged user +# Install Oh My Zsh and configure shells for the unprivileged user RUN su - "${USERNAME}" -c 'git clone --depth=1 https://github.com/ohmyzsh/ohmyzsh.git ~/.oh-my-zsh' \ && su - "${USERNAME}" -c 'cp ~/.oh-my-zsh/templates/zshrc.zsh-template ~/.zshrc' \ && su - "${USERNAME}" -c 'mkdir -p ~/.config' \ && su - "${USERNAME}" -c 'sed -i "s/^plugins=(git)$/plugins=(git fzf)/" ~/.zshrc' \ - && su - "${USERNAME}" -c 'printf "\nexport PATH=\"\$HOME/.local/share/aquaproj-aqua/bin:\$HOME/.local/bin:\$PATH\"\n" >> ~/.zshrc' \ + && su - "${USERNAME}" -c 'printf "\nexport PATH=\"\$HOME/.local/share/aquaproj-aqua/bin:\$HOME/.local/share/mise/shims:\$HOME/.local/bin:\$PATH\"\n" >> ~/.zshrc' \ + && su - "${USERNAME}" -c 'printf "\nexport AQUA_GLOBAL_CONFIG=\"\$HOME/.config/aquaproj-aqua/aqua.yaml\"\n" >> ~/.zshrc' \ && su - "${USERNAME}" -c 'printf "\n# Starship prompt\neval \"\$(starship init zsh)\"\n" >> ~/.zshrc' \ && su - "${USERNAME}" -c 'printf "\n# mise runtime manager\neval \"\$(mise activate zsh)\"\n" >> ~/.zshrc' \ && su - "${USERNAME}" -c 'printf "\n# direnv\nexport DIRENV_LOG_FORMAT=\"\"\neval \"\$(direnv hook zsh)\"\n" >> ~/.zshrc' \ && su - "${USERNAME}" -c 'printf "\n# zoxide\neval \"\$(zoxide init zsh)\"\n" >> ~/.zshrc' \ + && su - "${USERNAME}" -c 'printf "\nexport AQUA_GLOBAL_CONFIG=\"\$HOME/.config/aquaproj-aqua/aqua.yaml\"\n" >> ~/.bashrc' \ && su - "${USERNAME}" -c 'printf "\n# mise runtime manager (bash)\neval \"\$(mise activate bash)\"\n" >> ~/.bashrc' \ && su - "${USERNAME}" -c 'printf "\n# direnv\nexport DIRENV_LOG_FORMAT=\"\"\neval \"\$(direnv hook bash)\"\n" >> ~/.bashrc' \ && su - "${USERNAME}" -c 'printf "\n# zoxide\neval \"\$(zoxide init bash)\"\n" >> ~/.bashrc' \ && su - "${USERNAME}" -c 'mkdir -p ~/.config/fish' \ - && su - "${USERNAME}" -c 'printf "\n# Shell prompt and runtime manager\nstarship init fish | source\nmise activate fish | source\ndirenv hook fish | source\nzoxide init fish | source\n" >> ~/.config/fish/config.fish' + && su - "${USERNAME}" -c 'printf "\nset -gx AQUA_GLOBAL_CONFIG \$HOME/.config/aquaproj-aqua/aqua.yaml\n# Shell prompt and runtime manager\nstarship init fish | source\nmise activate fish | source\ndirenv hook fish | source\nzoxide init fish | source\n" >> ~/.config/fish/config.fish' COPY aqua.yaml /tmp/aqua.yaml @@ -93,6 +105,7 @@ RUN mkdir -p /workspace \ && chown "${USER_ID}:${GROUP_ID}" /workspace ENV SHELL=/usr/bin/zsh \ + 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} WORKDIR /workspace diff --git a/artifacts/ToolboxStack/toolbox-base/PROMPT b/artifacts/ToolboxStack/toolbox-base/PROMPT index 1957c92..addd608 100644 --- a/artifacts/ToolboxStack/toolbox-base/PROMPT +++ b/artifacts/ToolboxStack/toolbox-base/PROMPT @@ -7,12 +7,12 @@ Context snapshot (toolbox-base): - Mounted workspace: current repo at /workspace (rw) Current state: -- Dockerfile installs shell tooling (zsh/bash/fish with Starship & oh-my-zsh), core CLI utilities (curl, wget, git, tmux, screen, httpie, bc, etc.), build-essential + headers, aqua, and mise; aqua now provisions gh, tea, lazygit, direnv, git-delta, zoxide, just, yq, xh, curlie, chezmoi, shfmt, shellcheck, and hadolint, with direnv/zoxide hooks enabled for all shells (direnv logging muted). -- aqua-managed CLI inventory lives in README.md alongside usage notes. +- Dockerfile installs shell tooling (zsh/bash/fish with Starship & oh-my-zsh), core CLI utilities (curl, wget, git, tmux, screen, httpie, tea, bc, etc.), build-essential + headers, aqua, and mise. Aqua is pinned to specific versions for gh, lazygit, direnv, git-delta, zoxide, just, yq, xh, curlie, chezmoi, shfmt, shellcheck, hadolint; direnv/zoxide hooks are enabled for all shells (direnv logging muted). +- aqua-managed CLI inventory lives in README.md alongside usage notes; tea installs via direct download with checksum verification (TEA_VERSION build arg). - mise handles language/tool runtimes; activation wired into zsh, bash, and fish. - docker-compose.yml runs container with host UID/GID, `sleep infinity`, and docker socket mount; run via run.sh/build.sh. - Devcontainer config ( .devcontainer/devcontainer.json ) references the compose service. -- Documentation: README.md (tooling inventory & workflow) and this PROMPT must stay current. +- Documentation: README.md (tooling inventory & workflow) and this PROMPT must stay current. README also notes that build.sh now uses docker buildx with a local cache directory. Collaboration guidelines: 1. Default to non-destructive operations; respect existing scripts run.sh/build.sh. diff --git a/artifacts/ToolboxStack/toolbox-base/README.md b/artifacts/ToolboxStack/toolbox-base/README.md index 9541c43..1308712 100644 --- a/artifacts/ToolboxStack/toolbox-base/README.md +++ b/artifacts/ToolboxStack/toolbox-base/README.md @@ -10,6 +10,7 @@ Daily-driver development container for ToolboxStack work. It provides a reproduc ```bash ./build.sh ``` + > Uses `docker buildx` with a local cache at `.build-cache/` for faster rebuilds. 2. **Start the container** ```bash ./run.sh up @@ -34,8 +35,8 @@ The compose service mounts the current repo to `/workspace` (read/write) and run |----------|---------|-------| | **Shells & Prompts** | ๐Ÿš `zsh` โ€ข ๐ŸŸ `fish` โ€ข ๐Ÿง‘โ€๐Ÿ’ป `bash` โ€ข โญ `starship` โ€ข ๐Ÿ’Ž `oh-my-zsh` | Starship prompt enabled for all shells; oh-my-zsh configured with `git` + `fzf` plugins. | | **Runtime & CLI Managers** | ๐Ÿช„ `mise` โ€ข ๐Ÿ’ง `aqua` | `mise` handles language/tool runtimes (activation wired into zsh/bash/fish); `aqua` manages standalone CLIs with config at `~/.config/aquaproj-aqua/aqua.yaml`. | -| **Core CLI Utilities** | ๐Ÿ“ฆ `curl` โ€ข ๐Ÿ“ฅ `wget` โ€ข ๐Ÿ” `ca-certificates` โ€ข ๐Ÿงญ `git` โ€ข ๐Ÿ”ง `build-essential` + headers (`pkg-config`, `libssl-dev`, `zlib1g-dev`, `libffi-dev`, `libsqlite3-dev`, `libreadline-dev`, `make`) โ€ข ๐Ÿ” `ripgrep` โ€ข ๐Ÿงญ `fzf` โ€ข ๐Ÿ“ `fd` โ€ข ๐Ÿ“– `bat` โ€ข ๐Ÿ”— `openssh-client` โ€ข ๐Ÿงต `tmux` โ€ข ๐Ÿ–ฅ๏ธ `screen` โ€ข ๐Ÿ“Š `jq` โ€ข ๐ŸŒ `httpie` โ€ข ๐Ÿงฎ `bc` | Provides ergonomic defaults plus toolchain deps for compiling runtimes (no global language installs). | -| **Aqua-Managed CLIs** | ๐Ÿ™ `gh` โ€ข ๐Ÿซ– `tea` โ€ข ๐ŸŒ€ `lazygit` โ€ข ๐Ÿช„ `direnv` โ€ข ๐ŸŽจ `git-delta` โ€ข ๐Ÿงญ `zoxide` โ€ข ๐Ÿงฐ `just` โ€ข ๐Ÿงพ `yq` โ€ข โšก `xh` โ€ข ๐ŸŒ `curlie` โ€ข ๐Ÿ  `chezmoi` โ€ข ๐Ÿ› ๏ธ `shfmt` โ€ข โœ… `shellcheck` โ€ข ๐Ÿณ `hadolint` | Extend via `~/.config/aquaproj-aqua/aqua.yaml` and run `aqua install`. Direnv logging is muted and hooks for direnv/zoxide are pre-configured for zsh, bash, and fish. | +| **Core CLI Utilities** | ๐Ÿ“ฆ `curl` โ€ข ๐Ÿ“ฅ `wget` โ€ข ๐Ÿ” `ca-certificates` โ€ข ๐Ÿงญ `git` โ€ข ๐Ÿ”ง `build-essential` + headers (`pkg-config`, `libssl-dev`, `zlib1g-dev`, `libffi-dev`, `libsqlite3-dev`, `libreadline-dev`, `make`) โ€ข ๐Ÿ” `ripgrep` โ€ข ๐Ÿงญ `fzf` โ€ข ๐Ÿ“ `fd` โ€ข ๐Ÿ“– `bat` โ€ข ๐Ÿ”— `openssh-client` โ€ข ๐Ÿงต `tmux` โ€ข ๐Ÿ–ฅ๏ธ `screen` โ€ข ๐Ÿ“Š `jq` โ€ข ๐ŸŒ `httpie` โ€ข โ˜• `tea` โ€ข ๐Ÿงฎ `bc` | Provides ergonomic defaults plus toolchain deps for compiling runtimes (no global language installs). | +| **Aqua-Managed CLIs** | ๐Ÿ™ `gh` โ€ข ๐ŸŒ€ `lazygit` โ€ข ๐Ÿช„ `direnv` โ€ข ๐ŸŽจ `git-delta` โ€ข ๐Ÿงญ `zoxide` โ€ข ๐Ÿงฐ `just` โ€ข ๐Ÿงพ `yq` โ€ข โšก `xh` โ€ข ๐ŸŒ `curlie` โ€ข ๐Ÿ  `chezmoi` โ€ข ๐Ÿ› ๏ธ `shfmt` โ€ข โœ… `shellcheck` โ€ข ๐Ÿณ `hadolint` | Extend via `~/.config/aquaproj-aqua/aqua.yaml` and run `aqua install`. Direnv logging is muted and hooks for direnv/zoxide are pre-configured for zsh, bash, and fish. | | **Container Workflow** | ๐Ÿณ Docker socket mount (`/var/run/docker.sock`) | Enables Docker CLIs inside the container; host Docker daemon required. | | **Runtime Environment** | ๐Ÿ‘ค Non-root user `toolbox` (UID/GID mapped) โ€ข ๐Ÿ—‚๏ธ `/workspace` mount | Maintains host permissions and isolates artifacts under `artifacts/ToolboxStack/toolbox-base`. | diff --git a/artifacts/ToolboxStack/toolbox-base/aqua.yaml b/artifacts/ToolboxStack/toolbox-base/aqua.yaml index 01924df..4f5fcd7 100644 --- a/artifacts/ToolboxStack/toolbox-base/aqua.yaml +++ b/artifacts/ToolboxStack/toolbox-base/aqua.yaml @@ -3,17 +3,16 @@ registries: - type: standard ref: v4.200.0 packages: - - name: cli/cli@latest - - name: go-gitea/tea@latest - - name: jesseduffield/lazygit@latest - - name: direnv/direnv@latest - - name: dandavison/delta@latest - - name: ajeetdsouza/zoxide@latest - - name: casey/just@latest - - name: mikefarah/yq@latest - - name: ducaale/xh@latest - - name: rs/curlie@latest - - name: twpayne/chezmoi@latest - - name: mvdan/sh@latest - - name: koalaman/shellcheck@latest - - name: hadolint/hadolint@latest + - name: cli/cli@v2.82.1 + - name: jesseduffield/lazygit@v0.55.1 + - name: direnv/direnv@v2.37.1 + - name: dandavison/delta@0.18.2 + - name: ajeetdsouza/zoxide@v0.9.8 + - name: casey/just@1.43.0 + - name: mikefarah/yq@v4.48.1 + - name: ducaale/xh@v0.25.0 + - name: rs/curlie@v1.8.2 + - name: twpayne/chezmoi@v2.66.1 + - name: mvdan/sh@v3.12.0 + - name: koalaman/shellcheck@v0.11.0 + - name: hadolint/hadolint@v2.14.0 diff --git a/artifacts/ToolboxStack/toolbox-base/build.sh b/artifacts/ToolboxStack/toolbox-base/build.sh index e129533..664df94 100755 --- a/artifacts/ToolboxStack/toolbox-base/build.sh +++ b/artifacts/ToolboxStack/toolbox-base/build.sh @@ -8,12 +8,29 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" USER_ID="${USER_ID_OVERRIDE:-$(id -u)}" GROUP_ID="${GROUP_ID_OVERRIDE:-$(id -g)}" USERNAME="${USERNAME_OVERRIDE:-toolbox}" +TEA_VERSION="${TEA_VERSION_OVERRIDE:-0.11.1}" +BUILDER_NAME="${BUILDER_NAME:-tsysdevstack-toolboxstack-builder}" +CACHE_DIR="${SCRIPT_DIR}/.build-cache" echo "Building ${IMAGE_NAME} with UID=${USER_ID} GID=${GROUP_ID} USERNAME=${USERNAME}" -docker build \ +if ! docker buildx inspect "${BUILDER_NAME}" >/dev/null 2>&1; then + docker buildx create --driver docker-container --name "${BUILDER_NAME}" --use >/dev/null +else + docker buildx use "${BUILDER_NAME}" >/dev/null +fi + +mkdir -p "${CACHE_DIR}" + +docker buildx build \ + --builder "${BUILDER_NAME}" \ + --load \ + --progress=plain \ --build-arg USER_ID="${USER_ID}" \ --build-arg GROUP_ID="${GROUP_ID}" \ --build-arg USERNAME="${USERNAME}" \ + --build-arg TEA_VERSION="${TEA_VERSION}" \ + --cache-from "type=local,src=${CACHE_DIR}" \ + --cache-to "type=local,dest=${CACHE_DIR},mode=max" \ --tag "${IMAGE_NAME}" \ "${SCRIPT_DIR}" diff --git a/collab/SupportStack/BuildTheStack b/collab/SupportStack/BuildTheStack index 2a0fc09..0ee87eb 100644 --- a/collab/SupportStack/BuildTheStack +++ b/collab/SupportStack/BuildTheStack @@ -103,6 +103,15 @@ Create a proof of concept with docker-socket-proxy, homepage, and wakaapi compon - Implement security scanning during build process (for demo, secrets via environment variables are acceptable) - Define network policies for internal communication only - Use depends_on with health checks to ensure proper startup ordering of services +- Use SQLite for every service that will support it to avoid heavier databases where possible +- For services requiring databases, prefer lightweight SQLite over PostgreSQL, MySQL, or other heavy database systems +- Only use heavier databases when SQLite is not supported or inadequate for the service requirements +- When using SQLite, implement proper volume management for database files using Docker volumes +- Ensure SQLite databases are properly secured with appropriate file permissions and encryption where needed +- Avoid external database dependencies when SQLite can meet the service requirements +- For database-backed services, configure SQLite as the default database engine in environment variables +- When migrating from heavier databases to SQLite, ensure data integrity and performance are maintained +- Implement proper backup strategies for SQLite databases using Docker volume snapshots - Homepage container requires direct Docker socket access (not through proxy) for automatic label discovery - Docker socket proxy provides controlled access for other containers that need Docker access - Portainer can use docker-socket-proxy for read-only access