initial commit
This commit is contained in:
50
scripts/odoo/README.md
Normal file
50
scripts/odoo/README.md
Normal file
@@ -0,0 +1,50 @@
|
||||
# odoo init helper
|
||||
|
||||
This folder contains helper scripts used to initialize the Odoo container on
|
||||
first boot. The `odoo-init` one-shot runs a small wrapper (`init-wrapper.sh`)
|
||||
that fixes filesystem ownerships for the Odoo named volumes and then runs the
|
||||
actual initialization script (`init-odoo.sh`).
|
||||
|
||||
Why the wrapper runs as root
|
||||
---------------------------
|
||||
- The wrapper must run as `root` so it can chown the Docker named volumes after
|
||||
they are created. Named volumes are created with root ownership by Docker on
|
||||
many hosts, which causes Odoo (a non-root process inside the container) to
|
||||
fail when writing the filestore.
|
||||
- The wrapper drops to the `odoo` user before executing the init script so the
|
||||
actual Odoo commands run with the correct, unprivileged uid/gid.
|
||||
|
||||
What it does
|
||||
-----------
|
||||
- Creates any missing directories the image expects (filestore, web, addons,
|
||||
logs, config) and sets their ownership to the numeric `odoo` UID:GID.
|
||||
- Writes a marker file `/var/lib/odoo/.odoo-init-done` to indicate the
|
||||
one-shot ran successfully.
|
||||
- Checks `/init-odoo.sh` is present and readable. If the script is missing or
|
||||
unreadable the wrapper exits with status `2` and logs an error.
|
||||
|
||||
Troubleshooting
|
||||
---------------
|
||||
- If you see PermissionError writing `/var/lib/odoo/filestore/*`:
|
||||
- Ensure the named volumes are not mounted on the host with root-only
|
||||
permissions. The wrapper attempts to chown them on container start; if that
|
||||
fails check the host mount permissions.
|
||||
- You can run the wrapper manually in a container to inspect output:
|
||||
|
||||
```sh
|
||||
docker compose run --rm --entrypoint /bin/sh odoo-init -c /init-wrapper.sh
|
||||
```
|
||||
|
||||
- If the wrapper logs `ERROR: /init-odoo.sh missing or not readable`:
|
||||
- Verify `./scripts/odoo/init-odoo.sh` exists in the repo and that it is
|
||||
mounted into the container in `odoo-init.yml` at `/init-odoo.sh`.
|
||||
|
||||
Notes
|
||||
-----
|
||||
- `odoo-init.yml` intentionally runs the `odoo-init` service as `root` so the
|
||||
wrapper can perform chown. The wrapper drops privileges before running the
|
||||
init logic.
|
||||
- The marker file is a simple heuristic other tooling (or manual checks) can
|
||||
use to detect that initialization already ran. Removing the named volumes
|
||||
and re-creating them will require re-running the wrapper (it runs on every
|
||||
start of the `odoo-init` one-shot service).
|
||||
20
scripts/odoo/init-odoo-with-perms.sh
Executable file
20
scripts/odoo/init-odoo-with-perms.sh
Executable file
@@ -0,0 +1,20 @@
|
||||
#!/bin/sh
|
||||
# Wrapper for odoo init: fix named volume ownership then run the original init script
|
||||
set -eu
|
||||
|
||||
OG="$(id -u odoo 2>/dev/null || id -u):$(id -g odoo 2>/dev/null || id -g)"
|
||||
echo "Fixing Odoo volumes to UID:GID=$OG"
|
||||
for d in /var/lib/odoo /etc/odo; do
|
||||
echo " -> chown $OG $d"
|
||||
chown -R "$OG" "$d" || true
|
||||
ls -ldn "$d" || true
|
||||
done
|
||||
|
||||
echo "Running Odoo init script"
|
||||
if command -v su >/dev/null 2>&1; then
|
||||
echo "Dropping to 'odoo' user to run init script via su"
|
||||
su -s /bin/sh odoo -c "/init-odoo.sh $*"
|
||||
else
|
||||
echo "su not available; running init script as current user"
|
||||
exec /init-odoo.sh "$@"
|
||||
fi
|
||||
33
scripts/odoo/init-odoo.sh
Executable file
33
scripts/odoo/init-odoo.sh
Executable file
@@ -0,0 +1,33 @@
|
||||
#!/bin/sh
|
||||
|
||||
echo "Checking if Odoo DB '$DB_NAME' exists and base module is installed..."
|
||||
retries=0
|
||||
max_retries=10
|
||||
|
||||
install_base_via_odoo() {
|
||||
echo "Installing base module into '$DB_NAME' via Odoo CLI"
|
||||
# Use --stop-after-init so the command exits after installing
|
||||
if odoo -d "$DB_NAME" -i base --stop-after-init --db_host="$HOST" --db_user="$USER" --db_password="$PASSWORD"; then
|
||||
echo "Base module installed successfully"
|
||||
return 0
|
||||
fi
|
||||
echo "Failed to install base module via Odoo CLI"
|
||||
return 1
|
||||
}
|
||||
|
||||
while true; do
|
||||
# Try to install base into the DB. If the DB exists and base is already
|
||||
# installed this will succeed or be a no-op. If the DB doesn't exist
|
||||
# the command will fail and we'll proceed to initialize it.
|
||||
if install_base_via_odoo; then
|
||||
echo "Odoo DB '$DB_NAME' is ready with base module installed."
|
||||
break
|
||||
fi
|
||||
retries=$((retries+1))
|
||||
if [ "$retries" -ge "$max_retries" ]; then
|
||||
echo "Initialization failed after $retries attempts. Exiting with error."
|
||||
exit 1
|
||||
fi
|
||||
echo "Retry #$retries: waiting before next attempt..."
|
||||
sleep 2
|
||||
done
|
||||
90
scripts/odoo/init-wrapper.sh
Executable file
90
scripts/odoo/init-wrapper.sh
Executable file
@@ -0,0 +1,90 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
log() { printf '%s %s\n' "$(date -u +%Y-%m-%dT%H:%M:%SZ)" "$*"; }
|
||||
|
||||
# Determine the numeric UID:GID for the odoo user if present; otherwise
|
||||
# fall back to the UID:GID of the current user (likely root when the
|
||||
# wrapper runs as root inside the container).
|
||||
OG_UID="$(id -u odoo 2>/dev/null || true)"
|
||||
OG_GID="$(id -g odoo 2>/dev/null || true)"
|
||||
if [ -n "$OG_UID" ] && [ -n "$OG_GID" ]; then
|
||||
OG="$OG_UID:$OG_GID"
|
||||
else
|
||||
OG="$(id -u):$(id -g)"
|
||||
fi
|
||||
|
||||
log "Fixing Odoo volumes to UID:GID=$OG"
|
||||
|
||||
# Paths we expect to ensure ownership for. If a path is missing we create it
|
||||
# with sensible defaults so Odoo can write into it later.
|
||||
for d in /var/lib/odo /etc/odoo; do
|
||||
if [ -e "$d" ]; then
|
||||
log " -> chown $OG $d"
|
||||
if chown -R "$OG" "$d"; then
|
||||
log " chown succeeded for $d"
|
||||
else
|
||||
log " WARNING: chown failed for $d (continuing)"
|
||||
fi
|
||||
ls -ldn "$d" || true
|
||||
else
|
||||
log " -> path $d does not exist, creating"
|
||||
if mkdir -p "$d"; then
|
||||
log " created $d"
|
||||
chown -R "$OG" "$d" || log " WARNING: chown failed after creating $d"
|
||||
ls -ldn "$d" || true
|
||||
else
|
||||
log " ERROR: failed to create $d"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
# Touch a marker so other tooling can detect that the one-shot ran.
|
||||
MARKER=/var/lib/odoo/.odoo-init-done
|
||||
log "Creating marker $MARKER"
|
||||
if touch "$MARKER"; then
|
||||
chown "$OG" "$MARKER" || true
|
||||
else
|
||||
log "WARNING: could not create marker $MARKER"
|
||||
fi
|
||||
|
||||
# Ensure the init script exists and is readable. If not, fail early with
|
||||
# a clear exit code so upstream tooling can detect the problem.
|
||||
if [ ! -r /init-odoo.sh ]; then
|
||||
log "ERROR: /init-odoo.sh missing or not readable"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# Try to make it executable for the target user only if the file is writable.
|
||||
# This avoids noisy "Read-only file system" errors when /init-odoo.sh is mounted
|
||||
# read-only from the host.
|
||||
if [ -w /init-odoo.sh ]; then
|
||||
chmod +x /init-odoo.sh || log "WARNING: chmod /init-odoo.sh failed"
|
||||
else
|
||||
log "Skipping chmod: /init-odoo.sh is not writable (read-only mount)"
|
||||
fi
|
||||
|
||||
log "Executing init script as 'odoo' user"
|
||||
# Run the init script as the odoo user while passing DB env vars inline so
|
||||
# they are visible even when using su which doesn't preserve the current
|
||||
# environment by default.
|
||||
exec su -s /bin/sh -c "DB_NAME=\"$DB_NAME\" HOST=\"$HOST\" USER=\"$USER\" PASSWORD=\"$PASSWORD\" /init-odoo.sh" odoo
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
OG="$(id -u odoo 2>/dev/null || id -u):$(id -g odoo 2>/dev/null || id -g)"
|
||||
|
||||
echo "Fixing Odoo volumes to UID:GID=$OG"
|
||||
|
||||
for d in /var/lib/odo /etc/odoo; do
|
||||
echo " -> chown $OG $d"
|
||||
chown -R "$OG" "$d" || true
|
||||
ls -ldn "$d" || true
|
||||
done
|
||||
|
||||
# Execute the original init script as the 'odoo' user (we run this wrapper as root).
|
||||
# When switching user with su, the target user's environment is reset; pass the
|
||||
# needed DB env vars inline so the init script sees them.
|
||||
exec su -s /bin/sh -c \
|
||||
"DB_NAME=\"$DB_NAME\" HOST=\"$HOST\" USER=\"$USER\" PASSWORD=\"$PASSWORD\" /init-odoo.sh" \
|
||||
odoo
|
||||
Reference in New Issue
Block a user