diff --git a/DOCKER_HUB.md b/DOCKER_HUB.md index 3c35cca..3a87ffa 100644 --- a/DOCKER_HUB.md +++ b/DOCKER_HUB.md @@ -467,7 +467,7 @@ docker compose run --rm devbox bash # interactive shell ## Shell defaults -The image ships baked shell defaults in `~/.bash_aliases` and `~/.inputrc`: +The image ships baked `.bash_aliases` and `.inputrc` in `/etc/skel-devbox/`. On first container start the entrypoint copies them to `/home/developer/` **only if the target file does not already exist**, so your host bind-mounts or any in-container customization are preserved across upgrades. - **Prefix history search** on Up/Down arrows (type `git `, press Up, walk back through prior `git ...` commands only). Ctrl-Up / Ctrl-Down still step through full history. - **Persistent history** via `$HISTFILE=~/.cache/bash/history`, backed by the `devbox-shell-history` named volume. Survives container recreate. 100 000 entries, time-stamped, dedup. @@ -476,7 +476,7 @@ The image ships baked shell defaults in `~/.bash_aliases` and `~/.inputrc`: - **Integrations** — `zoxide` (`z `), `fzf` key bindings (`Ctrl-R`, `Ctrl-T`). - **`[devbox]` prompt prefix** so you always know you're in the container. -To override with your host's own `~/.bash_aliases` / `~/.inputrc`, uncomment the matching bind-mount lines in `docker-compose.yml`. +To override with your host's own files, uncomment the matching bind-mount lines in `docker-compose.yml`. To restore the baked defaults any time: `cp /etc/skel-devbox/.bash_aliases ~/` (or delete the file and recreate the container). ## What's Included diff --git a/Dockerfile b/Dockerfile index 7a761fc..7954552 100644 --- a/Dockerfile +++ b/Dockerfile @@ -205,13 +205,17 @@ RUN mkdir -p /workspace \ chown -R ${USER_NAME}:${USER_NAME} /workspace /home/${USER_NAME} # ── Shell defaults (bash history, aliases, readline) ───────────────── -# Baked into the image so a fresh container has sensible history and -# readline behaviour out of the box. Users can override by bind-mounting -# their host ~/.inputrc or ~/.bash_aliases via docker-compose.yml. +# Shipped under /etc/skel-devbox/ rather than copied directly to the +# user's home. The entrypoint copies them to /home/developer/ only if +# the target file does not already exist, so host bind-mounts and +# previously-customized files are never overwritten. Users can restore +# the baked defaults anytime via: +# cp /etc/skel-devbox/.bash_aliases ~/.bash_aliases # History itself persists via the devbox-shell-history named volume # mounted at ~/.cache/bash (HISTFILE points there). -COPY --chown=${USER_UID}:${USER_GID} rootfs/home/developer/.bash_aliases /home/${USER_NAME}/.bash_aliases -COPY --chown=${USER_UID}:${USER_GID} rootfs/home/developer/.inputrc /home/${USER_NAME}/.inputrc +RUN mkdir -p /etc/skel-devbox +COPY rootfs/home/developer/.bash_aliases /etc/skel-devbox/.bash_aliases +COPY rootfs/home/developer/.inputrc /etc/skel-devbox/.inputrc # ── Entrypoint ──────────────────────────────────────────────────────── COPY entrypoint.sh /usr/local/bin/entrypoint.sh diff --git a/README.md b/README.md index 95554fb..2c39225 100644 --- a/README.md +++ b/README.md @@ -440,7 +440,9 @@ SSO sessions typically last 8–12 hours before requiring re-authentication. Sin ## Shell defaults -The image ships a baked `~/.bash_aliases` and `~/.inputrc` with quality-of-life defaults: +The image ships a baked `.bash_aliases` and `.inputrc` with quality-of-life defaults. On first container start they are copied from `/etc/skel-devbox/` into `/home/developer/` **only if the target file does not already exist** — so host bind-mounts and any version you've customized inside the container are never overwritten on upgrade. + +Defaults you get out of the box: - **Prefix history search** on Up/Down arrows (type `git `, press Up, walk back through prior `git ...` commands only). Ctrl-Up / Ctrl-Down still step through full history. - **Persistent history** — `$HISTFILE` points at `~/.cache/bash/history`, backed by the `devbox-shell-history` named volume so history survives container recreation. Timestamps, 100 000 entries, dedup. @@ -449,13 +451,36 @@ The image ships a baked `~/.bash_aliases` and `~/.inputrc` with quality-of-life - **Integrations** — `zoxide` (`z ` to jump), `fzf` Ctrl-R / Ctrl-T key bindings. - **Prompt marker** — `[devbox]` prefix so it's always obvious you're inside the container. -To override with your own host config, uncomment the bind-mount lines in `docker-compose.yml`: +### Overriding the defaults + +**Option A — bind-mount host files.** Uncomment the bind-mount lines in `docker-compose.yml`: ```yaml - ~/.bash_aliases:/home/developer/.bash_aliases:ro - ~/.inputrc:/home/developer/.inputrc:ro ``` +**Option B — customize inside the container.** Just edit `~/.bash_aliases` or `~/.inputrc` as normal. Pair this with a bind-mount or named volume on the home dir if you want the edits to survive container recreation. + +### Restoring or diffing defaults + +The skel files remain available inside every container at `/etc/skel-devbox/`. Useful commands: + +```bash +# See what the image currently ships +cat /etc/skel-devbox/.bash_aliases + +# Diff your current config against the upstream defaults +diff ~/.bash_aliases /etc/skel-devbox/.bash_aliases + +# Reset to the baked defaults +cp /etc/skel-devbox/.bash_aliases ~/.bash_aliases + +# …or delete the file and recreate the container — the entrypoint +# copies from /etc/skel-devbox/ on next start if the target is absent +rm ~/.bash_aliases +``` + ## Secret Scanning A [gitleaks](https://github.com/gitleaks/gitleaks) pre-commit hook prevents accidentally committing API keys, passwords, or other secrets. diff --git a/deploy/README.md b/deploy/README.md index c0e11e4..9f3cc58 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -198,6 +198,18 @@ After editing `docker-compose.yml` on the VM to uncomment the bind mounts you ne The script reads `docker-compose.yml` on the remote VM, detects which bind mounts are active, and syncs only those directories from your local machine. It also creates the remote directories if they don't exist. +### Shell defaults inside the container + +The image ships baked `.bash_aliases` and `.inputrc` in `/etc/skel-devbox/` — quality-of-life defaults (prefix history search on Up/Down arrows, persistent history across container recreates via the `devbox-shell-history` named volume, `[devbox]` prompt marker, sensible aliases). On first container start the entrypoint copies them to `/home/developer/` **only if the target file does not already exist**. + +This means: + +- Fresh containers get the defaults automatically. +- If you bind-mount your host's `~/.bash_aliases` / `~/.inputrc` (see the commented lines in `docker-compose.yml`), your host versions win. +- If you edit the files inside a running container and store them via a home-dir bind-mount or equivalent, subsequent upgrades never overwrite them. +- To restore the baked defaults any time: `cp /etc/skel-devbox/.bash_aliases ~/` (or delete the file and recreate the container). +- To diff your current config against what the image ships: `diff ~/.bash_aliases /etc/skel-devbox/.bash_aliases`. + ### Troubleshooting: SSH hangs or "banner exchange" timeouts If SSH to the VM intermittently fails with `Connection timed out during banner exchange` or pure TCP connect timeouts — especially after the first few successful connects in a short window — the cause is almost certainly your ISP's CGNAT (Carrier-Grade NAT), not the VM. diff --git a/entrypoint-user.sh b/entrypoint-user.sh index ef3281b..359368e 100644 --- a/entrypoint-user.sh +++ b/entrypoint-user.sh @@ -1,6 +1,20 @@ #!/usr/bin/env bash set -euo pipefail +# ── Shell defaults: copy baked files from /etc/skel-devbox/ if absent +# Respects host bind-mounts and user customizations — existing files +# are never overwritten. To restore defaults: rm ~/.bash_aliases (or +# .inputrc) and recreate the container, or cp from /etc/skel-devbox/ +# directly. +SKEL_DIR="/etc/skel-devbox" +if [ -d "$SKEL_DIR" ]; then + for f in .bash_aliases .inputrc; do + if [ -f "$SKEL_DIR/$f" ] && [ ! -e "$HOME/$f" ]; then + cp "$SKEL_DIR/$f" "$HOME/$f" + fi + done +fi + # ── Git config defaults ────────────────────────────────────────────── if [ -n "${GIT_USER_NAME:-}" ] && ! git config --global user.name &>/dev/null; then git config --global user.name "$GIT_USER_NAME"