8000 fix(install): start a fresh microsandbox install on its own volume when an earlier install's data is there by adeelahmad · Pull Request #358 · adeelahmad/lense · GitHub
[go: up one dir, main page]

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions .github/workflows/install.yml
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,25 @@ jobs:
msb exec lens -- chromium --version
curl -fsS -o /dev/null "$(cat setup-url)"

- name: Installing again after the install folder is deleted starts Lens on a volume of its own
run: |
export PATH="$HOME/.local/bin:$HOME/.microsandbox/bin:$PATH"
# the folder held the keys that open lens-data's database; an empty volume of the next name is used as it is
msb volume create lens-data-2
rm -rf "$LENS_DIR"
sh < install.sh | tee fresh.log
grep -q 'Starting Lens on a microsandbox volume of its own, lens-data-2' fresh.log
grep -q '^LENS_VOLUME=lens-data-2$' "$LENS_DIR/.env" || { echo "the new install didn't start on a volume of its own"; exit 1; }
msb volume ls -q | grep -qx lens-data || { echo "the earlier install's volume is gone"; exit 1; }
url="$(grep -Eo 'http://[^ ]+/setup\?code=[A-Za-z0-9]{12}' fresh.log | head -1)"
test -n "$url" || { echo "install.sh didn't hand over a setup address"; exit 1; }
base="http://127.0.0.1:${url##*:}"; base="${base%%/setup*}"
curl -fsS "$base/api/v1/auth/status" | grep -q '"setup_required":true'
# running the line again keeps that volume
LENS_BACKEND='' sh < install.sh >/dev/null
grep -q '^LENS_VOLUME=lens-data-2$' "$LENS_DIR/.env"
curl -fsS -o /dev/null "$url"

- name: What the sandbox said
if: failure()
run: |
Expand Down
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ The backend (`fastapi_backend`) and the frontend (`nextjs-frontend`) are version

## Unreleased

- **A microsandbox install after the install folder was deleted comes up.** The data volume (`lens-data`) outlives
`~/lens`, but its database opens only with the keys in that folder's `.env`. A first install made new keys, mounted
the earlier volume anyway, and waited 30 minutes for a web app whose API couldn't open the database. It now leaves
that volume as it is and starts on one of its own (`lens-data-2`, kept in `.env` as `LENS_VOLUME`); put the earlier
`.env` back to use the earlier data, or remove it with `msb volume rm lens-data`
([microsandbox](docs/microsandbox.md#how-it-runs)).

## 0.8.0 <small>October 11, 2026</small> {id="0.8.0"}

- **A microsandbox's full edition installs LibreOffice and Chromium the first time they're needed.** They were
Expand Down
6 changes: 6 additions & 0 deletions docs/microsandbox.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,12 @@ the sandbox. A sandbox that is started again boots without running Lens, so Lens
which takes several minutes (longer on a Raspberry Pi). Later starts install the packages from the volume and reuse the
build, so they take a minute or two.

The database opens only with the keys in the `.env` of the install that made it, and the volume outlives the install
folder. So a first install (one with no `.env` yet) that finds `lens-data` holding an earlier install's database, say
after `~/lens` was deleted, leaves it as it is and starts on a volume of its own: `lens-data-2`, or the next free name.
`.env` keeps that name (`LENS_VOLUME`), so running the line again uses the same one. Put the earlier `.env` back in the
folder to use the earlier data again, or remove it with `msb volume rm lens-data`.

The sandbox can reach the internet, your network (mail servers, model servers) and this machine. On this machine,
Ollama or LM Studio are at `host.docker.internal`, the same address as with Docker. Only the web app's port and the
sensor ports are published, on the same addresses Docker would use (`LENS_BIND`, `LENS_SENSOR_BIND`).
Expand Down
35 changes: 34 additions & 1 deletion install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,15 @@ msb_ok() {
esac
}
tty_ok() { [ "${LENS_YES:-0}" != 1 ] && (: </dev/tty) 2>/dev/null; }
# has_db VOLUME: whether a microsandbox volume may hold a Lens database. Only one it can see has none counts as without:
# empty, or with run.sh's tools (.lens) and no database (surreal/lens.db) next to them. One it can't look into (not
# where microsandbox keeps them by default) counts as with.
has_db() {
vol="$HOME/.microsandbox/volumes/$1"
[ -d "$vol" ] || return 0
[ -n "$(ls -A "$vol" 2>/dev/null)" ] || return 1
! { [ -d "$vol/.lens" ] && [ ! -e "$vol/surreal/lens.db" ]; }
}

# --- The web installer: a first install at a terminal continues in the browser ----------------------------------------
# It asks everything there (what to install, how Lens runs, the AI model and its key, the extras), then runs this
Expand Down Expand Up @@ -347,7 +356,9 @@ setenv() { # key value: replace the line, or add it
printf '%s=%s\n' "$1" "$2" >>.env
fi
}
fresh=0 # a first install: its keys are new
if [ ! -f .env ]; then
fresh=1
umask 077
printf '# Written by install.sh. Keep it with the volumes.\n' >.env
setenv ACCESS_SECRET_KEY "$(secret)"
Expand Down Expand Up @@ -419,7 +430,29 @@ if [ "$BACKEND" = microsandbox ]; then
if [ "$LENS_HTTPS" = 1 ]; then # Caddy listens on 8443 and 8080 inside (docs/https.md)
set -- "$@" -p "${LENS_HTTPS_BIND:-0.0.0.0}:$HTTPS_PORT:8443" -p "${LENS_HTTPS_BIND:-0.0.0.0}:$HTTP_PORT:8080"
fi
set -- "$@" -v "$PWD:/lens:ro" -v "$PWD/.lens-control:/control" --mount-named lens-data:/data \
# The volume its data is kept in (the database, the archive, the builds). A database opens only with the keys of
# the install that made it, which are in that install's .env. So a first install that finds the volume of an earlier
# one whose folder is gone (deleted, or installed elsewhere) starts on a volume of its own, and leaves that one as it
# is: its data is still there for that install's .env. A volume without a database yet is used as it is.
VOLUME="$(grep '^LENS_VOLUME=' .env | cut -d= -f2- || true)"
if [ -z "$VOLUME" ]; then
VOLUME=lens-data
if [ "$fresh" = 1 ]; then
volumes="$(msb volume ls -q </dev/null 2>/dev/null || true)"
n=1
while printf '%s\n' "$volumes" | grep -qx "$VOLUME" && has_db "$VOLUME"; do
n=$((n + 1))
VOLUME="lens-data-$n"
done
if [ "$VOLUME" != lens-data ]; then
say "Starting Lens on a microsandbox volume of its own, $VOLUME..."
echo " The volume lens-data holds an earlier install's data, which opens only with that install's .env. It's left"
echo " as it is: msb volume rm lens-data removes it."
fi
fi
setenv LENS_VOLUME "$VOLUME"
fi
set -- "$@" -v "$PWD:/lens:ro" -v "$PWD/.lens-control:/control" --mount-named "$VOLUME:/data" \
--entrypoint /bin/sh "$image" -- /lens/microsandbox/run.sh
say "Starting Lens in a microsandbox (the first start installs and builds it, which takes a while)..."
# The command that starts it, kept for a restart of the machine: a sandbox started again (msb start) boots without
Expand Down
Loading
0