Ship shell defaults via /etc/skel-devbox so user files are preserved
Publish Docker Image / build-base (push) Successful in 40m28s
Publish Docker Image / build-omos (push) Successful in 50m37s
Publish Docker Image / update-description (push) Successful in 15s

Previous behaviour (e4063b5) COPY'd .bash_aliases and .inputrc
directly into /home/developer/ during image build. That silently
shadowed any host bind-mount or in-container customization for users
upgrading from v1.14.19b — if you'd written your own .bash_aliases
and rebuilt the container, our baked version would overwrite it
without warning.

Ship the files to /etc/skel-devbox/ instead. The entrypoint copies
them to $HOME only if the target file does not already exist, so:

- Fresh containers get the defaults automatically (unchanged)
- Host bind-mounts win (they materialize before the entrypoint runs)
- Existing in-container customizations survive upgrades
- Defaults remain discoverable at /etc/skel-devbox/ for anyone who
  wants to copy, diff, or reset back to upstream

Docs (README.md, DOCKER_HUB.md, deploy/README.md) describe the new
skel layout and the restore/diff commands.
This commit is contained in:
2026-04-21 19:44:29 +02:00
parent e4063b5559
commit 8535f73ad3
5 changed files with 64 additions and 9 deletions
+2 -2
View File
@@ -467,7 +467,7 @@ docker compose run --rm devbox bash # interactive shell
## Shell defaults ## 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. - **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. - **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 <fragment>`), `fzf` key bindings (`Ctrl-R`, `Ctrl-T`). - **Integrations** — `zoxide` (`z <fragment>`), `fzf` key bindings (`Ctrl-R`, `Ctrl-T`).
- **`[devbox]` prompt prefix** so you always know you're in the container. - **`[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 ## What's Included
+9 -5
View File
@@ -205,13 +205,17 @@ RUN mkdir -p /workspace \
chown -R ${USER_NAME}:${USER_NAME} /workspace /home/${USER_NAME} chown -R ${USER_NAME}:${USER_NAME} /workspace /home/${USER_NAME}
# ── Shell defaults (bash history, aliases, readline) ───────────────── # ── Shell defaults (bash history, aliases, readline) ─────────────────
# Baked into the image so a fresh container has sensible history and # Shipped under /etc/skel-devbox/ rather than copied directly to the
# readline behaviour out of the box. Users can override by bind-mounting # user's home. The entrypoint copies them to /home/developer/ only if
# their host ~/.inputrc or ~/.bash_aliases via docker-compose.yml. # 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 # History itself persists via the devbox-shell-history named volume
# mounted at ~/.cache/bash (HISTFILE points there). # mounted at ~/.cache/bash (HISTFILE points there).
COPY --chown=${USER_UID}:${USER_GID} rootfs/home/developer/.bash_aliases /home/${USER_NAME}/.bash_aliases RUN mkdir -p /etc/skel-devbox
COPY --chown=${USER_UID}:${USER_GID} rootfs/home/developer/.inputrc /home/${USER_NAME}/.inputrc COPY rootfs/home/developer/.bash_aliases /etc/skel-devbox/.bash_aliases
COPY rootfs/home/developer/.inputrc /etc/skel-devbox/.inputrc
# ── Entrypoint ──────────────────────────────────────────────────────── # ── Entrypoint ────────────────────────────────────────────────────────
COPY entrypoint.sh /usr/local/bin/entrypoint.sh COPY entrypoint.sh /usr/local/bin/entrypoint.sh
+27 -2
View File
@@ -440,7 +440,9 @@ SSO sessions typically last 812 hours before requiring re-authentication. Sin
## Shell defaults ## 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. - **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. - **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 <fragment>` to jump), `fzf` Ctrl-R / Ctrl-T key bindings. - **Integrations** — `zoxide` (`z <fragment>` to jump), `fzf` Ctrl-R / Ctrl-T key bindings.
- **Prompt marker** — `[devbox]` prefix so it's always obvious you're inside the container. - **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 ```yaml
- ~/.bash_aliases:/home/developer/.bash_aliases:ro - ~/.bash_aliases:/home/developer/.bash_aliases:ro
- ~/.inputrc:/home/developer/.inputrc: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 ## Secret Scanning
A [gitleaks](https://github.com/gitleaks/gitleaks) pre-commit hook prevents accidentally committing API keys, passwords, or other secrets. A [gitleaks](https://github.com/gitleaks/gitleaks) pre-commit hook prevents accidentally committing API keys, passwords, or other secrets.
+12
View File
@@ -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. 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 ### 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. 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.
+14
View File
@@ -1,6 +1,20 @@
#!/usr/bin/env bash #!/usr/bin/env bash
set -euo pipefail 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 ────────────────────────────────────────────── # ── Git config defaults ──────────────────────────────────────────────
if [ -n "${GIT_USER_NAME:-}" ] && ! git config --global user.name &>/dev/null; then if [ -n "${GIT_USER_NAME:-}" ] && ! git config --global user.name &>/dev/null; then
git config --global user.name "$GIT_USER_NAME" git config --global user.name "$GIT_USER_NAME"