CONVERSATIONS · THE PRESERVED RECORD
A question.
A conversation worth keeping.
The original exchange, kept in context—ready to read, revisit, and explore.
Begin reading ↗We found the complete persistent state:
- Main database: 23 MB
- Chroma vector database: 1.4 MB
- Entire data directory: 429 MB
- Location: buried inside the Python virtual environment
Open WebUI officially defines DATA_DIR as the base location for the database, uploads, cache, and vector storage, and recommends backing it up before updates because startup migrations can be difficult to reverse. citeturn293403search0turn563837search1turn563837search4
Run this block next. It will:
- Stop Open WebUI.
- Create a timestamped backup on
/mnt/storage. - Copy the live data outside the virtual environment.
- Check all three database copies for SQLite corruption.
- Configure the service to use the new persistent location.
- Restart the existing 0.6.36 version as a relocation test.
It does not upgrade Open WebUI or delete the original data.
(
set -euo pipefail
APP="/home/darren/apps/openwebui"
SRC="$APP/venv/lib/python3.11/site-packages/open_webui/data"
DST="$APP/data"
STAMP="$(date +%Y%m%d-%H%M%S)"
BACKUP="/mnt/storage/backups/openwebui/pre-upgrade-$STAMP"
echo "===== STOPPING OPENWEBUI ====="
sudo systemctl stop openwebui
echo
echo "===== CREATING BACKUP ====="
mkdir -p "$BACKUP/data"
cp -a "$SRC/." "$BACKUP/data/"
cp -a /etc/systemd/system/openwebui.service "$BACKUP/openwebui.service"
cp -a "$APP/.webui_secret_key" "$BACKUP/.webui_secret_key"
/home/darren/apps/openwebui/venv/bin/python -m pip freeze \
> "$BACKUP/pip-freeze.txt"
/home/darren/apps/openwebui/venv/bin/python -m pip show open-webui \
> "$BACKUP/openwebui-version.txt"
echo
echo "===== CREATING EXTERNAL DATA DIRECTORY ====="
mkdir -p "$DST"
cp -a "$SRC/." "$DST/"
chown -R darren:darren "$DST" "$BACKUP"
echo
echo "===== CHECKING SQLITE DATABASES ====="
python3 - "$SRC/webui.db" "$DST/webui.db" "$BACKUP/data/webui.db" <<'PY'
import sqlite3
import sys
for path in sys.argv[1:]:
connection = sqlite3.connect(f"file:{path}?mode=ro", uri=True)
result = connection.execute("PRAGMA quick_check;").fetchone()[0]
connection.close()
print(f"{path}: {result}")
if result != "ok":
raise SystemExit(f"Database check failed: {path}")
PY
echo
echo "===== CONFIGURING PERSISTENT DATA PATH ====="
sudo mkdir -p /etc/systemd/system/openwebui.service.d
printf '%s\n' \
'[Service]' \
'Environment=DATA_DIR=/home/darren/apps/openwebui/data' \
'Environment=UVICORN_WORKERS=1' |
sudo tee /etc/systemd/system/openwebui.service.d/data-directory.conf \
>/dev/null
sudo systemctl daemon-reload
echo
echo "===== RESTARTING CURRENT VERSION ====="
sudo systemctl start openwebui
sleep 10
echo
echo "===== SERVICE RESULT ====="
systemctl is-active openwebui
systemctl show openwebui \
-p Environment \
-p ExecStart \
--no-pager
echo
echo "===== VERSION RESPONSE ====="
curl -sS http://127.0.0.1:8080/api/version
echo
echo
echo "===== RECENT LOGS ====="
journalctl -u openwebui -n 30 --no-pager
echo
echo "===== BACKUP LOCATION ====="
echo "$BACKUP"
echo
echo "===== DATA SIZES ====="
du -sh "$SRC" "$DST" "$BACKUP"
)
The three SQLite checks should each end with:
: ok
Paste the final output before we perform the actual package upgrade.
Okay, so we're talking about the database that we haven't actually, the Postgres one, we haven't attached to WebUI yet. Or is this an internal OpenWebUI database? Because remember, we have most of the Postgres stuff on our data storage drive, D.
This is Open WebUI’s own internal database, not the Little Ougway PostgreSQL database.
Your systems are currently separate:
- Little Ougway / TokenSpace PostgreSQL
- PostgreSQL 16 with pgvector
- Data stored under
/mnt/storage/tokenspacedata - Contains the large ingested corpus and embeddings
-
Has not yet been connected to Open WebUI
-
Open WebUI internal storage
webui.db— users, conversations, settings, model configurations, prompts, and related WebUI statevector_db/chroma.sqlite3— Open WebUI’s own document/RAG vector storeuploads/andcache/- Currently buried inside:
text
/home/darren/apps/openwebui/venv/lib/python3.11/site-packages/open_webui/data
So none of this operation alters or relocates your PostgreSQL database. We are protecting Open WebUI’s separate 429 MB internal data directory before upgrading the WebUI software.
And because you intentionally keep persistent data on the large storage drive, we should revise my proposed destination. Rather than putting the relocated WebUI data at:
/home/darren/apps/openwebui/data
we should put it somewhere such as:
/mnt/storage/openwebui/data
That keeps both persistent systems on the storage drive while remaining clearly separated:
/mnt/storage/tokenspacedata ← Little Ougway PostgreSQL
/mnt/storage/openwebui/data ← Open WebUI chats/settings/uploads
/mnt/storage/backups/openwebui ← Open WebUI backups
Do not run the previous large relocation block. I’ll modify it to use /mnt/storage/openwebui/data and leave the PostgreSQL installation completely untouched.
Um, okay, if, if we gotta move it, um, can we move it to the D drive so, that it can have extra room if it needs it? Or do we need to just leave it where it is and move it somewhere on the C drive?
Yes—move it to the D drive, which Linux currently mounts as:
/mnt/storage
That is the better location.
The main reason is not that Open WebUI currently needs much space—it only uses about 429 MB—but that its data is presently buried inside the Python virtual environment. A future upgrade or venv rebuild could damage or erase it.
We’ll use this layout:
/mnt/storage/openwebui/data Open WebUI chats, settings, uploads, vectors
/mnt/storage/backups/openwebui Upgrade backups
/mnt/storage/tokenspacedata Little Ougway PostgreSQL, unchanged
So the two databases remain completely separate.
We should also configure the Open WebUI service with:
RequiresMountsFor=/mnt/storage/openwebui/data
That prevents Open WebUI from starting before the D drive has mounted during boot. Otherwise, Linux could accidentally create an empty /mnt/storage/openwebui/data directory on the C drive and make Open WebUI appear to have lost its data.
Therefore:
- Do not leave the persistent data inside the venv.
- Do not place the new copy on the C drive.
- Move it to
/mnt/storage/openwebui/data. - Leave PostgreSQL exactly where it is.
And do not run the earlier relocation block; it used the wrong destination.
Okay. And the terminal command to make all that happen?
I’m checking the exact Open WebUI service settings, then I’ll give you one pasteable block that relocates the data without touching PostgreSQL.
Yes. Paste this entire block into the terminal exactly as one unit.
It stops Open WebUI, makes a cold backup, copies its internal data to the D drive at /mnt/storage/openwebui/data, verifies the copies, changes the service to use that location, and starts Open WebUI again. The original copy inside the virtual environment remains untouched. Your PostgreSQL database at /mnt/storage/tokenspacedata is not accessed.
Open WebUI defines DATA_DIR as the base directory for its uploads, cache, vector database, and other persistent data; its default SQLite database is ${DATA_DIR}/webui.db. citeturn799471view0 Its backup documentation recommends stopping the service for a consistent file-level copy of webui.db, uploads, and vector_db. citeturn530304view1
(
set -Eeuo pipefail
APP="/home/darren/apps/openwebui"
SRC="$APP/venv/lib/python3.11/site-packages/open_webui/data"
STORAGE="/mnt/storage"
DST="$STORAGE/openwebui/data"
STAMP="$(date +%Y%m%d-%H%M%S)"
BACKUP="$STORAGE/backups/openwebui/pre-relocation-$STAMP"
DROPIN_DIR="/etc/systemd/system/openwebui.service.d"
DROPIN="$DROPIN_DIR/storage-data.conf"
SERVICE_STOPPED=0
recover_on_error() {
rc=$?
echo
echo "===== AN ERROR OCCURRED ====="
if [ "$SERVICE_STOPPED" -eq 1 ]; then
echo "Restoring the original Open WebUI service configuration..."
sudo rm -f "$DROPIN"
sudo systemctl daemon-reload
sudo systemctl start openwebui || true
fi
echo "The original data directory was not deleted."
exit "$rc"
}
trap recover_on_error ERR
echo "===== PREFLIGHT CHECKS ====="
mountpoint -q "$STORAGE" || {
echo "ERROR: $STORAGE is not mounted."
exit 1
}
test -f "$SRC/webui.db" || {
echo "ERROR: Source database not found:"
echo "$SRC/webui.db"
exit 1
}
if [ -e "$DST" ]; then
echo "ERROR: Destination already exists:"
echo "$DST"
echo "Nothing was changed."
exit 1
fi
if sudo test -e "$DROPIN"; then
echo "ERROR: The service override already exists:"
echo "$DROPIN"
echo "Nothing was changed."
exit 1
fi
echo "Storage mount:"
findmnt "$STORAGE"
echo
echo "Source data:"
du -sh "$SRC"
echo
echo "===== STOPPING OPENWEBUI ====="
sudo systemctl stop openwebui
SERVICE_STOPPED=1
echo
echo "===== CREATING COLD BACKUP ====="
sudo install -d -o darren -g darren "$BACKUP"
cp -a "$SRC" "$BACKUP/data"
cp -a /etc/systemd/system/openwebui.service \
"$BACKUP/openwebui.service"
if [ -d /etc/systemd/system/openwebui.service.d ]; then
cp -a /etc/systemd/system/openwebui.service.d \
"$BACKUP/openwebui.service.d-before-relocation"
fi
if [ -f "$APP/.webui_secret_key" ]; then
cp -a "$APP/.webui_secret_key" \
"$BACKUP/.webui_secret_key"
fi
"$APP/venv/bin/python" -m pip freeze \
> "$BACKUP/pip-freeze.txt"
"$APP/venv/bin/python" -m pip show open-webui \
> "$BACKUP/openwebui-version.txt"
echo
echo "===== COPYING DATA TO D DRIVE ====="
sudo install -d -o darren -g darren "$STORAGE/openwebui"
mkdir "$DST"
cp -a "$SRC/." "$DST/"
echo
echo "===== COMPARING SOURCE AND DESTINATION ====="
diff -qr "$SRC" "$DST"
echo "File comparison: identical"
echo
echo "===== CHECKING SQLITE DATABASES ====="
python3 - \
"$SRC/webui.db" \
"$SRC/vector_db/chroma.sqlite3" \
"$DST/webui.db" \
"$DST/vector_db/chroma.sqlite3" \
"$BACKUP/data/webui.db" \
"$BACKUP/data/vector_db/chroma.sqlite3" <<'PY'
import sqlite3
import sys
for path in sys.argv[1:]:
connection = sqlite3.connect(
f"file:{path}?mode=ro",
uri=True,
)
result = connection.execute(
"PRAGMA quick_check;"
).fetchone()[0]
connection.close()
print(f"{path}: {result}")
if result != "ok":
raise SystemExit(
f"SQLite integrity check failed: {path}"
)
PY
echo
echo "===== CONFIGURING OPENWEBUI SERVICE ====="
sudo mkdir -p "$DROPIN_DIR"
sudo tee "$DROPIN" >/dev/null <<'EOF'
[Unit]
RequiresMountsFor=/mnt/storage/openwebui/data
[Service]
Environment=DATA_DIR=/mnt/storage/openwebui/data
Environment=UVICORN_WORKERS=1
EOF
sudo systemctl daemon-reload
echo
echo "===== STARTING OPENWEBUI ====="
sudo systemctl start openwebui
READY=0
for attempt in $(seq 1 60); do
if curl -fsS \
http://127.0.0.1:8080/api/version \
> /tmp/openwebui-version.json 2>/dev/null
then
READY=1
break
fi
sleep 1
done
if [ "$READY" -ne 1 ]; then
echo "Open WebUI did not answer its version endpoint."
journalctl -u openwebui -n 50 --no-pager
false
fi
echo
echo "===== SUCCESS ====="
systemctl is-active openwebui
echo
echo "Open WebUI response:"
cat /tmp/openwebui-version.json
echo
rm -f /tmp/openwebui-version.json
echo
echo "Configured environment:"
systemctl show openwebui \
-p Environment \
--no-pager
echo
echo "Data locations:"
du -sh "$SRC" "$DST" "$BACKUP/data"
echo
echo "Backup location:"
echo "$BACKUP"
echo
echo "Recent Open WebUI logs:"
journalctl -u openwebui -n 25 --no-pager
trap - ERR
)
Success should include:
File comparison: identical
Each SQLite file should report:
: ok
And the configured environment should contain:
DATA_DIR=/mnt/storage/openwebui/data
Paste the resulting output before we upgrade the Open WebUI package.
darren@ougway:~/Desktop$ (
set -Eeuo pipefail
APP="/home/darren/apps/openwebui"
SRC="$APP/venv/lib/python3.11/site-packages/open_webui/data"
STORAGE="/mnt/storage"
DST="$STORAGE/openwebui/data"
STAMP="$(date +%Y%m%d-%H%M%S)"
BACKUP="$STORAGE/backups/openwebui/pre-relocation-$STAMP"
DROPIN_DIR="/etc/systemd/system/openwebui.service.d"
DROPIN="$DROPIN_DIR/storage-data.conf"
SERVICE_STOPPED=0
recover_on_error() {
rc=$?
echo
echo "===== AN ERROR OCCURRED ====="
if [ "$SERVICE_STOPPED" -eq 1 ]; then
echo "Restoring the original Open WebUI service configuration..."
)rap – ERR -u openwebui -n 25 –no-pageragerion endpoint."
===== PREFLIGHT CHECKS =====
[sudo] password for darren:
Storage mount:
TARGET SOURCE FSTYPE OPTIONS
/mnt/storage /dev/sdb ext4 rw,relatime
Source data:
429M /home/darren/apps/openwebui/venv/lib/python3.11/site-packages/open_webui/data
===== STOPPING OPENWEBUI =====
===== CREATING COLD BACKUP =====
===== COPYING DATA TO D DRIVE =====
===== COMPARING SOURCE AND DESTINATION =====
File comparison: identical
===== CHECKING SQLITE DATABASES =====
/home/darren/apps/openwebui/venv/lib/python3.11/site-packages/open_webui/data/webui.db: ok
/home/darren/apps/openwebui/venv/lib/python3.11/site-packages/open_webui/data/vector_db/chroma.sqlite3: ok
/mnt/storage/openwebui/data/webui.db: ok
/mnt/storage/openwebui/data/vector_db/chroma.sqlite3: ok
/mnt/storage/backups/openwebui/pre-relocation-20260731-023905/data/webui.db: ok
/mnt/storage/backups/openwebui/pre-relocation-20260731-023905/data/vector_db/chroma.sqlite3: ok
===== CONFIGURING OPENWEBUI SERVICE =====
===== STARTING OPENWEBUI =====
===== SUCCESS =====
active
Open WebUI response:
{"version":"0.6.36"}
Configured environment:
Environment=ENABLE_PERSISTENT_CONFIG=False ENABLE_IMAGE_GENERATION=True IMAGE_GENERATION_ENGINE=automatic1111 AUTOMATIC1111_BASE_URL=http://192.168.254.14:7860 PYTHONUNBUFFERED=1 DATA_DIR=/mnt/storage/openwebui/data UVICORN_WORKERS=1
Data locations:
429M /home/darren/apps/openwebui/venv/lib/python3.11/site-packages/open_webui/data
429M /mnt/storage/openwebui/data
429M /mnt/storage/backups/openwebui/pre-relocation-20260731-023905/data
Backup location:
/mnt/storage/backups/openwebui/pre-relocation-20260731-023905
Recent Open WebUI logs:
Jul 31 02:39:16 ougway systemd[1]: Started openwebui.service – Open WebUI (native, Python venv).
Jul 31 02:39:16 ougway open-webui[10758]: Loading WEBUI_SECRET_KEY from file, not provided as an environment variable.
Jul 31 02:39:16 ougway open-webui[10758]: Loading WEBUI_SECRET_KEY from /home/darren/apps/openwebui/.webui_secret_key
Jul 31 02:39:19 ougway open-webui[10758]: INFO [alembic.runtime.migration] Context impl SQLiteImpl.
Jul 31 02:39:19 ougway open-webui[10758]: INFO [alembic.runtime.migration] Will assume non-transactional DDL.
Jul 31 02:39:19 ougway open-webui[10758]: WARNI [open_webui.env]
Jul 31 02:39:19 ougway open-webui[10758]: WARNING: CORS_ALLOW_ORIGIN IS SET TO '*' – NOT RECOMMENDED FOR PRODUCTION DEPLOYMENTS.
Jul 31 02:39:19 ougway open-webui[10758]: INFO [open_webui.env] VECTOR_DB: chroma
Jul 31 02:39:19 ougway open-webui[10758]: INFO [open_webui.env] Embedding model set: sentence-transformers/all-MiniLM-L6-v2
Jul 31 02:39:21 ougway open-webui[10758]: WARNI [langchain_community.utils.user_agent] USER_AGENT environment variable not set, consider setting it to identify your requests.
Jul 31 02:39:22 ougway open-webui[10758]: ██████╗ ██████╗ ███████╗███╗ ██╗ ██╗ ██╗███████╗██████╗ ██╗ ██╗██╗
Jul 31 02:39:22 ougway open-webui[10758]: ██╔═══██╗██╔══██╗██╔════╝████╗ ██║ ██║ ██║██╔════╝██╔══██╗██║ ██║██║
Jul 31 02:39:22 ougway open-webui[10758]: ██║ ██║██████╔╝█████╗ ██╔██╗ ██║ ██║ █╗ ██║█████╗ ██████╔╝██║ ██║██║
Jul 31 02:39:22 ougway open-webui[10758]: ██║ ██║██╔═══╝ ██╔══╝ ██║╚██╗██║ ██║███╗██║██╔══╝ ██╔══██╗██║ ██║██║
Jul 31 02:39:22 ougway open-webui[10758]: ╚██████╔╝██║ ███████╗██║ ╚████║ ╚███╔███╔╝███████╗██████╔╝╚██████╔╝██║
Jul 31 02:39:22 ougway open-webui[10758]: ╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═══╝ ╚══╝╚══╝ ╚══════╝╚═════╝ ╚═════╝ ╚═╝
Jul 31 02:39:22 ougway open-webui[10758]: v0.6.36 – building the best AI user interface.
Jul 31 02:39:22 ougway open-webui[10758]: https://github.com/open-webui/open-webui
Jul 31 02:39:24 ougway open-webui[10758]: [149B blob data]
Jul 31 02:39:24 ougway open-webui[10758]: INFO: Started server process [10758]
Jul 31 02:39:24 ougway open-webui[10758]: INFO: Waiting for application startup.
Jul 31 02:39:24 ougway open-webui[10758]: 2026-07-31 02:39:24.845 | INFO | open_webui.utils.logger:start_logger:162 – GLOBAL_LOG_LEVEL: INFO
Jul 31 02:39:24 ougway open-webui[10758]: 2026-07-31 02:39:24.845 | INFO | open_webui.main:lifespan:578 – Installing external dependencies of functions and tools…
Jul 31 02:39:24 ougway open-webui[10758]: 2026-07-31 02:39:24.855 | INFO | open_webui.utils.plugin:install_frontmatter_requirements:283 – No requirements found in frontmatter.
Jul 31 02:39:25 ougway open-webui[10758]: 2026-07-31 02:39:25.378 | INFO | uvicorn.protocols.http.httptools_impl:send:476 – 127.0.0.1:55978 – "GET /api/version HTTP/1.1" 200
darren@ougway:~/Desktop$
The relocation is complete and verified. I’m checking the current official Open WebUI release and upgrade notes before giving you the package-update command.
That relocation completed exactly as intended.
The evidence is solid:
- Source and D-drive copies were identical.
- All six SQLite integrity checks returned
ok. - Open WebUI restarted successfully using
/mnt/storage/openwebui/data. - The service still sees the Automatic1111 settings.
- The cold backup is stored at:
text
/mnt/storage/backups/openwebui/pre-relocation-20260731-023905 - PostgreSQL was not touched.
The mangled text immediately before ===== PREFLIGHT CHECKS ===== was only terminal paste/display noise; the shell received and executed the block successfully.
Upgrade Open WebUI
The latest stable release is Open WebUI 0.11.0, released July 27, 2026. Your Python 3.11.9 environment is supported and is the version the project recommends most strongly. The official pip upgrade method is pip install -U open-webui; pinning it to 0.11.0 makes this upgrade deterministic. citeturn983395view0turn303494search0turn983395view1
Paste this block:
(
set -Eeuo pipefail
APP="/home/darren/apps/openwebui"
PYTHON="$APP/venv/bin/python"
TARGET_VERSION="0.11.0"
STAMP="$(date +%Y%m%d-%H%M%S)"
RECORD="/mnt/storage/backups/openwebui/upgrade-$STAMP"
SERVICE_STOPPED=0
recover_on_error() {
rc=$?
echo
echo "===== UPGRADE ERROR ====="
if [ "$SERVICE_STOPPED" -eq 1 ]; then
echo "Attempting to restart Open WebUI..."
sudo systemctl start openwebui || true
fi
echo
echo "Current service status:"
systemctl status openwebui --no-pager || true
echo
echo "Recent logs:"
journalctl -u openwebui -n 60 --no-pager || true
echo
echo "Upgrade record:"
echo "$RECORD"
exit "$rc"
}
trap recover_on_error ERR
echo "===== CREATING UPGRADE RECORD ====="
mkdir -p "$RECORD"
"$PYTHON" --version \
| tee "$RECORD/python-version-before.txt"
"$PYTHON" -m pip --version \
| tee "$RECORD/pip-version-before.txt"
"$PYTHON" -m pip show open-webui \
> "$RECORD/openwebui-before.txt"
"$PYTHON" -m pip freeze \
> "$RECORD/pip-freeze-before.txt"
systemctl cat openwebui \
> "$RECORD/openwebui-service-before.txt"
sha256sum \
/mnt/storage/openwebui/data/webui.db \
/mnt/storage/openwebui/data/vector_db/chroma.sqlite3 \
> "$RECORD/database-checksums-before.txt"
echo
echo "Installed version before upgrade:"
grep '^Version:' "$RECORD/openwebui-before.txt"
echo
echo "===== STOPPING OPENWEBUI ====="
sudo systemctl stop openwebui
SERVICE_STOPPED=1
echo
echo "===== UPDATING PIP ====="
"$PYTHON" -m pip install --upgrade pip \
2>&1 | tee "$RECORD/pip-upgrade.log"
echo
echo "===== INSTALLING OPEN WEBUI $TARGET_VERSION ====="
"$PYTHON" -m pip install --upgrade \
"open-webui==$TARGET_VERSION" \
2>&1 | tee "$RECORD/openwebui-upgrade.log"
echo
echo "===== VERIFYING INSTALLED PACKAGE ====="
"$PYTHON" -m pip show open-webui \
| tee "$RECORD/openwebui-after.txt"
INSTALLED_VERSION="$(
"$PYTHON" -m pip show open-webui |
awk '/^Version:/ {print $2}'
)"
if [ "$INSTALLED_VERSION" != "$TARGET_VERSION" ]; then
echo "ERROR: Expected $TARGET_VERSION but found $INSTALLED_VERSION"
false
fi
"$PYTHON" -m pip check \
2>&1 | tee "$RECORD/pip-check.txt"
"$PYTHON" -m pip freeze \
> "$RECORD/pip-freeze-after.txt"
echo
echo "===== STARTING OPENWEBUI ====="
sudo systemctl start openwebui
READY=0
for attempt in $(seq 1 180); do
if curl -fsS \
http://127.0.0.1:8080/api/version \
> "$RECORD/version-response.json" 2>/dev/null
then
READY=1
break
fi
if ! systemctl is-active --quiet openwebui; then
echo "Open WebUI stopped during startup."
false
fi
sleep 1
done
if [ "$READY" -ne 1 ]; then
echo "Open WebUI did not answer its version endpoint."
false
fi
echo
echo "===== UPGRADE SUCCESSFUL ====="
systemctl is-active openwebui
echo
echo "API version response:"
cat "$RECORD/version-response.json"
echo
echo
echo "Installed Python package:"
grep -E '^(Name|Version|Location):' \
"$RECORD/openwebui-after.txt"
echo
echo "Persistent data configuration:"
systemctl show openwebui \
-p Environment \
--no-pager
echo
echo "Database integrity after migration:"
python3 - \
/mnt/storage/openwebui/data/webui.db \
/mnt/storage/openwebui/data/vector_db/chroma.sqlite3 <<'PY'
import sqlite3
import sys
for path in sys.argv[1:]:
connection = sqlite3.connect(
f"file:{path}?mode=ro",
uri=True,
)
result = connection.execute(
"PRAGMA quick_check;"
).fetchone()[0]
connection.close()
print(f"{path}: {result}")
if result != "ok":
raise SystemExit(
f"SQLite integrity check failed: {path}"
)
PY
echo
echo "Recent startup and migration logs:"
journalctl -u openwebui -n 80 --no-pager
echo
echo "Upgrade record:"
echo "$RECORD"
trap - ERR
)
The first startup may apply database migrations. Open WebUI documents that these migrations can be one-way, which is why the untouched pre-upgrade backup is important. citeturn983395view1
The expected API result is:
{"version":"0.11.0"}
Paste the final output after the block completes.
darren@ougway:~/Desktop$ (
set -Eeuo pipefail
APP="/home/darren/apps/openwebui"
PYTHON="$APP/venv/bin/python"
TARGET_VERSION="0.11.0"
STAMP="$(date +%Y%m%d-%H%M%S)"
RECORD="/mnt/storage/backups/openwebui/upgrade-$STAMP"
SERVICE_STOPPED=0
recover_on_error() {
rc=$?
echo
echo "===== UPGRADE ERROR ====="
if [ "$SERVICE_STOPPED" -eq 1 ]; then
echo "Attempting to restart Open WebUI..."
sudo systemctl start openwebui || true
fi
echo
)rap – ERRORD"record:"i -n 80 –no-pager"ed: {path}"ite3 <<'PY'VERSION"
===== CREATING UPGRADE RECORD =====
mkdir: cannot create directory ‘/mnt/storage/backups/openwebui/upgrade-20260731-024228’: Permission denied
===== UPGRADE ERROR =====
Current service status:
● openwebui.service – Open WebUI (native, Python venv)
Loaded: loaded (/etc/systemd/system/openwebui.service; enabled; preset: enabled)
Drop-In: /etc/systemd/system/openwebui.service.d
└─storage-data.conf
Active: active (running) since Fri 2026-07-31 02:39:16 PDT; 3min 12s ago
Main PID: 10758 (open-webui)
Tasks: 33 (limit: 34931)
Memory: 631.5M (peak: 633.0M)
CPU: 9.457s
CGroup: /system.slice/openwebui.service
└─10758 /home/darren/apps/openwebui/venv/bin/python /home/darren/a…
Jul 31 02:39:22 ougway open-webui[10758]: ╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚══… ╚═╝
Jul 31 02:39:22 ougway open-webui[10758]: v0.6.36 – building the best AI us…ace.
Jul 31 02:39:22 ougway open-webui[10758]: https://github.com/open-webui/ope…ebui
Jul 31 02:39:24 ougway open-webui[10758]: [149B blob data]
Jul 31 02:39:24 ougway open-webui[10758]: INFO: Started server process …758]
Jul 31 02:39:24 ougway open-webui[10758]: INFO: Waiting for application…tup.
Jul 31 02:39:24 ougway open-webui[10758]: 2026-07-31 02:39:24.845 | INFO …INFO
Jul 31 02:39:24 ougway open-webui[10758]: 2026-07-31 02:39:24.845 | INFO …s…
Jul 31 02:39:24 ougway open-webui[10758]: 2026-07-31 02:39:24.855 | INFO …ter.
Jul 31 02:39:25 ougway open-webui[10758]: 2026-07-31 02:39:25.378 | INFO … 200
Hint: Some lines were ellipsized, use -l to show in full.
Recent logs:
Jul 16 10:35:39 ougway open-webui[1739]: 2026-07-16 10:35:39.857 | INFO | open_webui.utils.logger:start_logger:162 – GLOBAL_LOG_LEVEL: INFO
Jul 16 10:35:39 ougway open-webui[1739]: 2026-07-16 10:35:39.858 | INFO | open_webui.main:lifespan:578 – Installing external dependencies of functions and tools…
Jul 16 10:35:39 ougway open-webui[1739]: 2026-07-16 10:35:39.868 | INFO | open_webui.utils.plugin:install_frontmatter_requirements:283 – No requirements found in frontmatter.
Jul 31 01:37:33 ougway systemd[1]: Stopping openwebui.service – Open WebUI (native, Python venv)…
Jul 31 01:37:34 ougway systemd[1]: openwebui.service: Deactivated successfully.
Jul 31 01:37:34 ougway systemd[1]: Stopped openwebui.service – Open WebUI (native, Python venv).
Jul 31 01:37:34 ougway systemd[1]: openwebui.service: Consumed 20min 5.974s CPU time, 1.4G memory peak, 0B memory swap peak.
— Boot f312764cb40b46eb9026593fed7c4e72 —
Jul 31 01:38:00 ougway systemd[1]: Started openwebui.service – Open WebUI (native, Python venv).
Jul 31 01:38:00 ougway open-webui[1719]: Loading WEBUI_SECRET_KEY from file, not provided as an environment variable.
Jul 31 01:38:00 ougway open-webui[1719]: Loading WEBUI_SECRET_KEY from /home/darren/apps/openwebui/.webui_secret_key
Jul 31 01:38:09 ougway open-webui[1719]: INFO [alembic.runtime.migration] Context impl SQLiteImpl.
Jul 31 01:38:09 ougway open-webui[1719]: INFO [alembic.runtime.migration] Will assume non-transactional DDL.
Jul 31 01:38:09 ougway open-webui[1719]: WARNI [open_webui.env]
Jul 31 01:38:09 ougway open-webui[1719]: WARNING: CORS_ALLOW_ORIGIN IS SET TO '' – NOT RECOMMENDED FOR PRODUCTION DEPLOYMENTS.
Jul 31 01:38:10 ougway open-webui[1719]: INFO [open_webui.env] VECTOR_DB: chroma
Jul 31 01:38:10 ougway open-webui[1719]: INFO [open_webui.env] Embedding model set: sentence-transformers/all-MiniLM-L6-v2
Jul 31 01:38:15 ougway open-webui[1719]: WARNI [langchain_community.utils.user_agent] USER_AGENT environment variable not set, consider setting it to identify your requests.
Jul 31 01:38:16 ougway open-webui[1719]: ██████╗ ██████╗ ███████╗███╗ ██╗ ██╗ ██╗███████╗██████╗ ██╗ ██╗██╗
Jul 31 01:38:16 ougway open-webui[1719]: ██╔═══██╗██╔══██╗██╔════╝████╗ ██║ ██║ ██║██╔════╝██╔══██╗██║ ██║██║
Jul 31 01:38:16 ougway open-webui[1719]: ██║ ██║██████╔╝█████╗ ██╔██╗ ██║ ██║ █╗ ██║█████╗ ██████╔╝██║ ██║██║
Jul 31 01:38:16 ougway open-webui[1719]: ██║ ██║██╔═══╝ ██╔══╝ ██║╚██╗██║ ██║███╗██║██╔══╝ ██╔══██╗██║ ██║██║
Jul 31 01:38:16 ougway open-webui[1719]: ╚██████╔╝██║ ███████╗██║ ╚████║ ╚███╔███╔╝███████╗██████╔╝╚██████╔╝██║
Jul 31 01:38:16 ougway open-webui[1719]: ╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═══╝ ╚══╝╚══╝ ╚══════╝╚═════╝ ╚═════╝ ╚═╝
Jul 31 01:38:16 ougway open-webui[1719]: v0.6.36 – building the best AI user interface.
Jul 31 01:38:16 ougway open-webui[1719]: https://github.com/open-webui/open-webui
Jul 31 01:38:21 ougway open-webui[1719]: [149B blob data]
Jul 31 01:38:21 ougway open-webui[1719]: INFO: Started server process [1719]
Jul 31 01:38:21 ougway open-webui[1719]: INFO: Waiting for application startup.
Jul 31 01:38:21 ougway open-webui[1719]: 2026-07-31 01:38:21.685 | INFO | open_webui.utils.logger:start_logger:162 – GLOBAL_LOG_LEVEL: INFO
Jul 31 01:38:21 ougway open-webui[1719]: 2026-07-31 01:38:21.685 | INFO | open_webui.main:lifespan:578 – Installing external dependencies of functions and tools…
Jul 31 01:38:21 ougway open-webui[1719]: 2026-07-31 01:38:21.698 | INFO | open_webui.utils.plugin:install_frontmatter_requirements:283 – No requirements found in frontmatter.
Jul 31 02:39:13 ougway systemd[1]: Stopping openwebui.service – Open WebUI (native, Python venv)…
Jul 31 02:39:13 ougway systemd[1]: openwebui.service: Deactivated successfully.
Jul 31 02:39:13 ougway systemd[1]: Stopped openwebui.service – Open WebUI (native, Python venv).
Jul 31 02:39:13 ougway systemd[1]: openwebui.service: Consumed 15.109s CPU time, 1.4G memory peak, 0B memory swap peak.
Jul 31 02:39:16 ougway systemd[1]: Started openwebui.service – Open WebUI (native, Python venv).
Jul 31 02:39:16 ougway open-webui[10758]: Loading WEBUI_SECRET_KEY from file, not provided as an environment variable.
Jul 31 02:39:16 ougway open-webui[10758]: Loading WEBUI_SECRET_KEY from /home/darren/apps/openwebui/.webui_secret_key
Jul 31 02:39:19 ougway open-webui[10758]: INFO [alembic.runtime.migration] Context impl SQLiteImpl.
Jul 31 02:39:19 ougway open-webui[10758]: INFO [alembic.runtime.migration] Will assume non-transactional DDL.
Jul 31 02:39:19 ougway open-webui[10758]: WARNI [open_webui.env]
Jul 31 02:39:19 ougway open-webui[10758]: WARNING: CORS_ALLOW_ORIGIN IS SET TO '' – NOT RECOMMENDED FOR PRODUCTION DEPLOYMENTS.
Jul 31 02:39:19 ougway open-webui[10758]: INFO [open_webui.env] VECTOR_DB: chroma
Jul 31 02:39:19 ougway open-webui[10758]: INFO [open_webui.env] Embedding model set: sentence-transformers/all-MiniLM-L6-v2
Jul 31 02:39:21 ougway open-webui[10758]: WARNI [langchain_community.utils.user_agent] USER_AGENT environment variable not set, consider setting it to identify your requests.
Jul 31 02:39:22 ougway open-webui[10758]: ██████╗ ██████╗ ███████╗███╗ ██╗ ██╗ ██╗███████╗██████╗ ██╗ ██╗██╗
Jul 31 02:39:22 ougway open-webui[10758]: ██╔═══██╗██╔══██╗██╔════╝████╗ ██║ ██║ ██║██╔════╝██╔══██╗██║ ██║██║
Jul 31 02:39:22 ougway open-webui[10758]: ██║ ██║██████╔╝█████╗ ██╔██╗ ██║ ██║ █╗ ██║█████╗ ██████╔╝██║ ██║██║
Jul 31 02:39:22 ougway open-webui[10758]: ██║ ██║██╔═══╝ ██╔══╝ ██║╚██╗██║ ██║███╗██║██╔══╝ ██╔══██╗██║ ██║██║
Jul 31 02:39:22 ougway open-webui[10758]: ╚██████╔╝██║ ███████╗██║ ╚████║ ╚███╔███╔╝███████╗██████╔╝╚██████╔╝██║
Jul 31 02:39:22 ougway open-webui[10758]: ╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═══╝ ╚══╝╚══╝ ╚══════╝╚═════╝ ╚═════╝ ╚═╝
Jul 31 02:39:22 ougway open-webui[10758]: v0.6.36 – building the best AI user interface.
Jul 31 02:39:22 ougway open-webui[10758]: https://github.com/open-webui/open-webui
Jul 31 02:39:24 ougway open-webui[10758]: [149B blob data]
Jul 31 02:39:24 ougway open-webui[10758]: INFO: Started server process [10758]
Jul 31 02:39:24 ougway open-webui[10758]: INFO: Waiting for application startup.
Jul 31 02:39:24 ougway open-webui[10758]: 2026-07-31 02:39:24.845 | INFO | open_webui.utils.logger:start_logger:162 – GLOBAL_LOG_LEVEL: INFO
Jul 31 02:39:24 ougway open-webui[10758]: 2026-07-31 02:39:24.845 | INFO | open_webui.main:lifespan:578 – Installing external dependencies of functions and tools…
Jul 31 02:39:24 ougway open-webui[10758]: 2026-07-31 02:39:24.855 | INFO | open_webui.utils.plugin:install_frontmatter_requirements:283 – No requirements found in frontmatter.
Jul 31 02:39:25 ougway open-webui[10758]: 2026-07-31 02:39:25.378 | INFO | uvicorn.protocols.http.httptools_impl:send:476 – 127.0.0.1:55978 – "GET /api/version HTTP/1.1" 200
Upgrade record:
/mnt/storage/backups/openwebui/upgrade-20260731-024228
darren@ougway:~/Desktop$
Nothing was damaged—the script stopped at the first step, before stopping Open WebUI or changing the venv. The fix is simply to create the upgrade-record directory with the correct ownership, then rerun the upgrade.
Nothing changed. The upgrade failed before Open WebUI was stopped, so it is still running normally at version 0.6.36.
The cause is straightforward: the parent backup directory is owned by root, so Darren could not create a new upgrade-record folder beneath it.
Run:
sudo chown darren:darren /mnt/storage/backups/openwebui
sudo chmod 755 /mnt/storage/backups/openwebui
ls -ld /mnt/storage/backups/openwebui
The last line should show darren darren, approximately like:
drwxr-xr-x ... darren darren ... /mnt/storage/backups/openwebui
Then rerun the same complete upgrade block from my previous message. It will generate a new timestamp, so the failed upgrade-20260731-024228 name does not need cleanup because that directory was never created.
Version 0.11.0 remains the latest stable release, and upgrading the Python installation with pip is the documented method. citeturn304363view0turn304363view1
I’m reading the full terminal output you attached, especially the final verification and any error lines, so we can see exactly where the upgrade ended.
The upgrade completed successfully.
- Open WebUI 0.11.0 installed, and
pip checkfound no broken dependencies. fileciteturn1file0L35-L39 fileciteturn1file0L95-L98 - The service is active, and the API responds with version 0.11.0. fileciteturn1file0L100-L111
- It is still using the D-drive data directory:
text
DATA_DIR=/mnt/storage/openwebui/data
Your Automatic1111 settings also remained in place. fileciteturn1file0L113-L114 - Both the Open WebUI database and Chroma vector database passed integrity checks after migration. fileciteturn1file0L116-L118
- The database migrations ran through to completion, and Open WebUI reached normal application startup. fileciteturn1file0L127-L170 fileciteturn1file0L180-L200
- The upgrade record is stored at:
text
/mnt/storage/backups/openwebui/upgrade-20260731-024432
fileciteturn1file0L202-L203
The embeddings.position_ids | UNEXPECTED message is a model-loading notice, not a startup failure; Open WebUI continued running and answered its API immediately afterward. fileciteturn1file0L189-L200
Now reload Open WebUI in the browser—preferably with Ctrl+Shift+R—and verify:
- Your old conversations are present.
- The Ollama model list appears.
- Send a simple message to
qwen3:8b. - Open the image-generation settings and confirm Automatic1111 still shows
http://192.168.254.14:7860.
At the system level, both major upgrades are now complete: Ollama 0.32.5 and Open WebUI 0.11.0.
Now for the tough part. I don't remember the passwords for the database. How do we look into that?
We’ll separate two possibilities: finding a saved application password, or resetting the PostgreSQL role password safely. First we’ll inventory the cluster and roles without changing anything.
This is recoverable. There are two separate approaches:
- Find a password already saved in a project configuration or
.pgpassfile. - Reset the PostgreSQL role password without knowing the old one.
PostgreSQL does not normally retain a readable plaintext password that we can display. It stores a password verifier for each role, so the practical solution is usually to locate the application’s saved credential or assign a new password. PostgreSQL’s interactive \password command is preferable when resetting because it avoids placing the new password directly in shell history. citeturn178302search0turn178302search5
First, let’s identify exactly what database and login roles exist. This block is inspection only and does not show password hashes:
echo "===== POSTGRESQL CLUSTERS ====="
pg_lsclusters
echo
echo "===== DATABASE ROLES ====="
sudo -u postgres psql -X -P pager=off -c '\du+'
echo
echo "===== DATABASES AND OWNERS ====="
sudo -u postgres psql -X -P pager=off -c "
SELECT datname AS database,
pg_get_userbyid(datdba) AS owner
FROM pg_database
WHERE NOT datistemplate
ORDER BY datname;
"
echo
echo "===== LOGIN AND PASSWORD STATUS ====="
sudo -u postgres psql -X -P pager=off -c "
SELECT rolname,
rolcanlogin,
rolvaliduntil,
rolpassword IS NOT NULL AS has_password
FROM pg_authid
ORDER BY rolname;
"
echo
echo "===== POSTGRESQL LOCATIONS ====="
sudo -u postgres psql -X -Atc "
SHOW data_directory;
SHOW config_file;
SHOW hba_file;
SHOW password_encryption;
"
echo
echo "===== SAVED PGPASS FILE ====="
if [ -f /home/darren/.pgpass ]; then
awk -F: 'BEGIN {OFS=\":\"} {$5=\"********\"; print}' \
/home/darren/.pgpass
else
echo "No /home/darren/.pgpass file found."
fi
pg_lsclusters will verify whether PostgreSQL 16 is online and whether its real data directory is still /mnt/storage/tokenspacedata. The local sudo -u postgres psql connection may work without the forgotten database password because PostgreSQL supports local peer authentication using the operating-system identity; the authentication rules themselves are controlled by pg_hba.conf. citeturn178302search1turn178302search3turn178302search6
Paste that output here. Do not paste an actual password if one unexpectedly appears; replace it with [REDACTED]. Once we identify the application role—possibly something like tokenspace, ougway, or darren—we can safely reset only that role rather than disturbing PostgreSQL as a whole.
darren@ougway:~/Desktop$ echo "===== POSTGRESQL CLUSTERS ====="
pg_lsclusters
echo
echo "===== DATABASE ROLES ====="
sudo -u postgres psql -X -P pager=off -c '\du+'
echo
echo "===== DATABASES AND OWNERS ====="
sudo -u postgres psql -X -P pager=off -c "
SELECT datname AS database,
pg_get_userbyid(datdba) AS owner
FROM pg_database
WHERE NOT datistemplate
ORDER BY datname;
"
echo
echo "===== LOGIN AND PASSWORD STATUS ====="
sudo -u postgres psql -X -P pager=off -c "
SELECT rolname,
rolcanlogin,
rolvaliduntil,
fi echo "No /home/darren/.pgpass file found.""; print}' \
===== POSTGRESQL CLUSTERS =====
Ver Cluster Port Status Owner Data directory Log file
16 main 5432 online postgres /mnt/storage/tokenspacedata /var/log/postgresql/postgresql-16-main.log
===== DATABASE ROLES =====
[sudo] password for darren:
List of roles
Role name | Attributes | Description
———–+————————————————————+————-
darren | Create role, Create DB |
postgres | Superuser, Create role, Create DB, Replication, Bypass RLS |
===== DATABASES AND OWNERS =====
database | owner
————+———-
postgres | postgres
tokenspace | darren
(2 rows)
===== LOGIN AND PASSWORD STATUS =====
rolname | rolcanlogin | rolvaliduntil | has_password
—————————–+————-+—————+————–
darren | t | | t
pg_checkpoint | f | | f
pg_create_subscription | f | | f
pg_database_owner | f | | f
pg_execute_server_program | f | | f
pg_monitor | f | | f
pg_read_all_data | f | | f
pg_read_all_settings | f | | f
pg_read_all_stats | f | | f
pg_read_server_files | f | | f
pg_signal_backend | f | | f
pg_stat_scan_tables | f | | f
pg_use_reserved_connections | f | | f
pg_write_all_data | f | | f
pg_write_server_files | f | | f
postgres | t | | t
(16 rows)
===== POSTGRESQL LOCATIONS =====
/mnt/storage/tokenspacedata
/etc/postgresql/16/main/postgresql.conf
/etc/postgresql/16/main/pg_hba.conf
scram-sha-256
===== SAVED PGPASS FILE =====
awk: 1: unexpected character '\'
awk: line 1: runaway string constant ":\"} {$5=\ …
darren@ougway:~/Desktop$
The database itself is fine. We’ve identified the important part: tokenspace is owned by the PostgreSQL role darren, and that role already has a password—we just cannot read it back.
Good news: the database is online and intact.
We now know:
- Cluster: PostgreSQL 16 on port
5432 - Data:
/mnt/storage/tokenspacedata - Database:
tokenspace - Owner/login role:
darren - The
darrenrole already has a password - The
postgresrole also has a password
PostgreSQL cannot reveal either existing password in readable form. We can either find a saved copy in a configuration file or replace the darren password. We should search first, because resetting it could temporarily break scripts still using the old password.
The awk error affected only the attempted masking of .pgpass; it did not affect PostgreSQL.
Run this inspection block:
echo "===== LOCAL DATABASE LOGIN TEST ====="
psql -X -d tokenspace -c '\conninfo'
echo
echo "===== PGPASS FILE ====="
if [ -f "$HOME/.pgpass" ]; then
ls -l "$HOME/.pgpass"
sed -E 's/^(([^:]*:){4}).*/\1********/' "$HOME/.pgpass"
else
echo "No $HOME/.pgpass file found."
fi
echo
echo "===== ACTIVE AUTHENTICATION RULES ====="
sudo awk '
!/^[[:space:]]*#/ &&
!/^[[:space:]]*$ {
print NR ": " $0
}
' /etc/postgresql/16/main/pg_hba.conf
echo
echo "===== FILES THAT MAY CONTAIN DATABASE SETTINGS ====="
grep -RIlE \
--exclude-dir=.git \
--exclude-dir=.cache \
--exclude-dir=venv \
--exclude-dir=node_modules \
--exclude='*.log' \
--exclude='*.sql' \
'DATABASE_URL|DB_PASSWORD|POSTGRES_PASSWORD|PGPASSWORD|postgresql://|postgres://' \
/home/darren 2>/dev/null | head -100
This does not change anything.
The first command may connect successfully without requesting a password because local Linux authentication can identify you as darren. That would mean we already have administrative access to tokenspace, despite not remembering the network/application password.
The last section prints filenames only, not their contents, so it should not expose a password here.
If no saved password is found, we reset only the darren PostgreSQL password with:
sudo -u postgres psql -X -c '\password darren'
That securely asks for the new password twice without putting it into terminal history. Do not run that reset yet; let’s identify which configuration files will need the new password first.
