EspoCRM related shell scripts, initial versions
This commit is contained in:
34
backup_espocrm.sh
Executable file
34
backup_espocrm.sh
Executable file
@@ -0,0 +1,34 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# To be run by user mkt to back up the EspoCRM pod: a MariaDB dump and a
|
||||||
|
# tarball of the EspoCRM data dir (config.php with crypt/passwordSalt key,
|
||||||
|
# data/upload, custom). Manual invocation only (no timer, no cron).
|
||||||
|
|
||||||
|
# Environment variables
|
||||||
|
POD_NAME='espocrm_pod'
|
||||||
|
DB_CTR='mariadb_ctr'
|
||||||
|
DB_NAME='espocrm'
|
||||||
|
BIND_DIR="$HOME/.local/share/$POD_NAME"
|
||||||
|
ESPO_DATA_DIR="$BIND_DIR/espocrm" # /var/www/html
|
||||||
|
BAK_DIR="$HOME/bak"
|
||||||
|
TS=$(date +%Y%m%d-%H%M%S)
|
||||||
|
|
||||||
|
mkdir -p "$BAK_DIR"
|
||||||
|
|
||||||
|
# DB dump: run inside the container so no password is needed in this script;
|
||||||
|
# MARIADB_ROOT_PASSWORD is taken from the container's own environment.
|
||||||
|
DB_BAK="$BAK_DIR/espocrm-db-$TS.sql.gz"
|
||||||
|
podman exec "$DB_CTR" sh -c \
|
||||||
|
'exec mariadb-dump --single-transaction --routines --triggers -uroot -p"$MARIADB_ROOT_PASSWORD" '"$DB_NAME" \
|
||||||
|
| gzip > "$DB_BAK"
|
||||||
|
echo "Wrote DB dump $DB_BAK (rc=$?)"
|
||||||
|
|
||||||
|
# File backup of the EspoCRM data directory
|
||||||
|
FILES_BAK="$BAK_DIR/espocrm-files-$TS.tar.gz"
|
||||||
|
tar -czf "$FILES_BAK" -C "$ESPO_DATA_DIR" .
|
||||||
|
echo "Wrote files backup $FILES_BAK (rc=$?)"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Backup complete:"
|
||||||
|
echo " $DB_BAK"
|
||||||
|
echo " $FILES_BAK"
|
||||||
169
create_pod_espocrm.sh
Executable file
169
create_pod_espocrm.sh
Executable file
@@ -0,0 +1,169 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# To be run by user mkt to create the EspoCRM pod (MariaDB + web + scheduler
|
||||||
|
# daemon) as a rootless Podman pod and to create/enable the systemd --user
|
||||||
|
# services for autostart. Podman 4.3.1 (no Quadlet): uses
|
||||||
|
# `podman generate systemd --files --new`.
|
||||||
|
|
||||||
|
# Environment variables
|
||||||
|
POD_NAME='espocrm_pod'
|
||||||
|
DB_CTR='mariadb_ctr'
|
||||||
|
WEB_CTR='espocrm_ctr'
|
||||||
|
DAEMON_CTR='espocrm_daemon_ctr'
|
||||||
|
|
||||||
|
ESPO_IMAGE='docker.io/espocrm/espocrm:9.3.8'
|
||||||
|
DB_IMAGE='docker.io/library/mariadb:11.4.12'
|
||||||
|
|
||||||
|
HOST_LOCAL_IP='127.0.0.1'
|
||||||
|
WEB_HOST_PORT='8093' # -> container port 80 (EspoCRM web)
|
||||||
|
DB_HOST_PORT='8094' # -> container port 3306 (host-side DB access)
|
||||||
|
|
||||||
|
NET_OPTS='slirp4netns:allow_host_loopback=true,port_handler=slirp4netns'
|
||||||
|
|
||||||
|
# Data (bind mounts, no named volumes)
|
||||||
|
BIND_DIR="$HOME/.local/share/$POD_NAME"
|
||||||
|
DB_DATA_DIR="$BIND_DIR/mariadb" # -> /var/lib/mysql
|
||||||
|
ESPO_DATA_DIR="$BIND_DIR/espocrm" # -> /var/www/html
|
||||||
|
|
||||||
|
# systemd --user paths
|
||||||
|
USER_SYSTEMD_DIR="$HOME/.config/systemd/user"
|
||||||
|
WEB_UNIT_FILE="$USER_SYSTEMD_DIR/container-${WEB_CTR}.service"
|
||||||
|
DAEMON_UNIT_FILE="$USER_SYSTEMD_DIR/container-${DAEMON_CTR}.service"
|
||||||
|
|
||||||
|
# Credentials (plaintext deliberately accepted: private repo / company secret)
|
||||||
|
MARIADB_ROOT_PASSWORD='KqHZUEih4FQY9bTX1VqjS2VbrScrYyi+'
|
||||||
|
ESPOCRM_DB_PASSWORD='hsILtz+BLs/+8T8MEjO9tIt4fDPPRgB7'
|
||||||
|
ESPOCRM_ADMIN_PASSWORD='Mb5/toETVFzdn+kX6iRxllzXNbcIQIUT'
|
||||||
|
|
||||||
|
DB_NAME='espocrm'
|
||||||
|
DB_USER='espocrm'
|
||||||
|
ADMIN_USER='admin'
|
||||||
|
SITE_URL="http://${HOST_LOCAL_IP}:${WEB_HOST_PORT}"
|
||||||
|
|
||||||
|
# Prepare directories
|
||||||
|
mkdir -p "$DB_DATA_DIR" "$ESPO_DATA_DIR" "$USER_SYSTEMD_DIR"
|
||||||
|
|
||||||
|
# Create pod if not yet existing
|
||||||
|
if ! podman pod exists "$POD_NAME"; then
|
||||||
|
podman pod create \
|
||||||
|
-n "$POD_NAME" \
|
||||||
|
--network "$NET_OPTS" \
|
||||||
|
-p ${HOST_LOCAL_IP}:${WEB_HOST_PORT}:80 \
|
||||||
|
-p ${HOST_LOCAL_IP}:${DB_HOST_PORT}:3306
|
||||||
|
echo "Pod '$POD_NAME' created (rc=$?)"
|
||||||
|
else
|
||||||
|
echo "Pod '$POD_NAME' already exists."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# MariaDB container (start first)
|
||||||
|
podman rm -f "$DB_CTR"
|
||||||
|
podman run -d --name "$DB_CTR" --pod "$POD_NAME" \
|
||||||
|
-e MARIADB_ROOT_PASSWORD="$MARIADB_ROOT_PASSWORD" \
|
||||||
|
-e MARIADB_DATABASE="$DB_NAME" \
|
||||||
|
-e MARIADB_USER="$DB_USER" \
|
||||||
|
-e MARIADB_PASSWORD="$ESPOCRM_DB_PASSWORD" \
|
||||||
|
-v "$DB_DATA_DIR":/var/lib/mysql \
|
||||||
|
"$DB_IMAGE" \
|
||||||
|
--character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
|
||||||
|
echo "Started $DB_CTR container (rc=$?)"
|
||||||
|
|
||||||
|
# Wait for the DB to be ready
|
||||||
|
echo "Waiting for MariaDB to be ready..."
|
||||||
|
for i in $(seq 1 60); do
|
||||||
|
podman exec "$DB_CTR" mariadb-admin ping --silent >/dev/null 2>&1 && break
|
||||||
|
sleep 2
|
||||||
|
done
|
||||||
|
echo "MariaDB ping ready (rc=$?)"
|
||||||
|
|
||||||
|
# EspoCRM web container (start after the DB)
|
||||||
|
podman rm -f "$WEB_CTR"
|
||||||
|
podman run -d --name "$WEB_CTR" --pod "$POD_NAME" \
|
||||||
|
-e ESPOCRM_DATABASE_PLATFORM=Mysql \
|
||||||
|
-e ESPOCRM_DATABASE_HOST="$HOST_LOCAL_IP" \
|
||||||
|
-e ESPOCRM_DATABASE_PORT=3306 \
|
||||||
|
-e ESPOCRM_DATABASE_NAME="$DB_NAME" \
|
||||||
|
-e ESPOCRM_DATABASE_USER="$DB_USER" \
|
||||||
|
-e ESPOCRM_DATABASE_PASSWORD="$ESPOCRM_DB_PASSWORD" \
|
||||||
|
-e ESPOCRM_ADMIN_USERNAME="$ADMIN_USER" \
|
||||||
|
-e ESPOCRM_ADMIN_PASSWORD="$ESPOCRM_ADMIN_PASSWORD" \
|
||||||
|
-e ESPOCRM_SITE_URL="$SITE_URL" \
|
||||||
|
-e ESPOCRM_CONFIG_USE_WEB_SOCKET=false \
|
||||||
|
-v "$ESPO_DATA_DIR":/var/www/html \
|
||||||
|
"$ESPO_IMAGE"
|
||||||
|
echo "Started $WEB_CTR container (rc=$?)"
|
||||||
|
|
||||||
|
# Wait for EspoCRM install/response (HTTP 200/302, max ~3 min)
|
||||||
|
echo "Waiting for EspoCRM to install and respond..."
|
||||||
|
for i in $(seq 1 90); do
|
||||||
|
code=$(curl -s -o /dev/null -w '%{http_code}' "${SITE_URL}/" 2>/dev/null)
|
||||||
|
case "$code" in
|
||||||
|
200|302) break ;;
|
||||||
|
esac
|
||||||
|
sleep 2
|
||||||
|
done
|
||||||
|
echo "EspoCRM responded with HTTP $code (rc=$?)"
|
||||||
|
|
||||||
|
# EspoCRM scheduler/daemon container (start last; reads data/config.php)
|
||||||
|
podman rm -f "$DAEMON_CTR"
|
||||||
|
podman run -d --name "$DAEMON_CTR" --pod "$POD_NAME" \
|
||||||
|
--entrypoint docker-daemon.sh \
|
||||||
|
-v "$ESPO_DATA_DIR":/var/www/html \
|
||||||
|
"$ESPO_IMAGE"
|
||||||
|
echo "Started $DAEMON_CTR container (rc=$?)"
|
||||||
|
|
||||||
|
# Generate systemd service files
|
||||||
|
cd "$USER_SYSTEMD_DIR"
|
||||||
|
podman generate systemd --files --new --name "$POD_NAME"
|
||||||
|
echo "Generated systemd service files (rc=$?)"
|
||||||
|
|
||||||
|
# Enforce start order: web waits for DB port, daemon waits for web port.
|
||||||
|
# Insert an ExecStartPre wait loop immediately BEFORE the container run line.
|
||||||
|
awk -v ip="$HOST_LOCAL_IP" -v port="$DB_HOST_PORT" '
|
||||||
|
BEGIN { inserted=0 }
|
||||||
|
/^ExecStart=\/usr\/bin\/podman run/ && inserted==0 {
|
||||||
|
print "ExecStartPre=/bin/bash -ceu \047for i in $(seq 1 60); do (exec 3<>/dev/tcp/" ip "/" port ") 2>/dev/null && exit 0; sleep 2; done; echo \"dep " ip ":" port " not up\" >&2; exit 1\047"
|
||||||
|
inserted=1
|
||||||
|
}
|
||||||
|
{ print }
|
||||||
|
' "$WEB_UNIT_FILE" > "${WEB_UNIT_FILE}.tmp"
|
||||||
|
mv "${WEB_UNIT_FILE}.tmp" "$WEB_UNIT_FILE"
|
||||||
|
echo "Injected DB readiness check (${HOST_LOCAL_IP}:${DB_HOST_PORT}) into ${WEB_CTR} unit"
|
||||||
|
|
||||||
|
awk -v ip="$HOST_LOCAL_IP" -v port="$WEB_HOST_PORT" '
|
||||||
|
BEGIN { inserted=0 }
|
||||||
|
/^ExecStart=\/usr\/bin\/podman run/ && inserted==0 {
|
||||||
|
print "ExecStartPre=/bin/bash -ceu \047for i in $(seq 1 90); do (exec 3<>/dev/tcp/" ip "/" port ") 2>/dev/null && exit 0; sleep 2; done; echo \"dep " ip ":" port " not up\" >&2; exit 1\047"
|
||||||
|
inserted=1
|
||||||
|
}
|
||||||
|
{ print }
|
||||||
|
' "$DAEMON_UNIT_FILE" > "${DAEMON_UNIT_FILE}.tmp"
|
||||||
|
mv "${DAEMON_UNIT_FILE}.tmp" "$DAEMON_UNIT_FILE"
|
||||||
|
echo "Injected web readiness check (${HOST_LOCAL_IP}:${WEB_HOST_PORT}) into ${DAEMON_CTR} unit"
|
||||||
|
|
||||||
|
# Stop & remove the live pod and containers
|
||||||
|
podman pod stop --time 15 "$POD_NAME"
|
||||||
|
podman pod rm -f --ignore "$POD_NAME"
|
||||||
|
if podman pod exists "$POD_NAME"; then
|
||||||
|
echo "ERROR: Pod $POD_NAME still exists."
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
echo "Stopped & removed live pod $POD_NAME and containers"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Enable systemd services (the systemd-managed instance is what runs in the end)
|
||||||
|
systemctl --user daemon-reload
|
||||||
|
systemctl --user enable --now "pod-${POD_NAME}.service"
|
||||||
|
echo "Enabled systemd service pod-${POD_NAME}.service (rc=$?)"
|
||||||
|
systemctl --user enable --now "container-${DB_CTR}.service"
|
||||||
|
echo "Enabled systemd service container-${DB_CTR}.service (rc=$?)"
|
||||||
|
systemctl --user enable --now "container-${WEB_CTR}.service"
|
||||||
|
echo "Enabled systemd service container-${WEB_CTR}.service (rc=$?)"
|
||||||
|
systemctl --user enable --now "container-${DAEMON_CTR}.service"
|
||||||
|
echo "Enabled systemd service container-${DAEMON_CTR}.service (rc=$?)"
|
||||||
|
|
||||||
|
# Closing hints
|
||||||
|
echo ""
|
||||||
|
echo "EspoCRM is reachable at ${SITE_URL} (admin / see ESPOCRM_ADMIN_PASSWORD)"
|
||||||
|
echo "Status: systemctl --user status pod-${POD_NAME}.service"
|
||||||
|
echo "Status: systemctl --user status container-${DB_CTR}.service container-${WEB_CTR}.service container-${DAEMON_CTR}.service"
|
||||||
|
echo "View logs: journalctl --user -u container-${WEB_CTR}.service -f"
|
||||||
49
reset_pod_espocrm.sh
Executable file
49
reset_pod_espocrm.sh
Executable file
@@ -0,0 +1,49 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# To be run by user mkt. DANGEROUS: disables and removes the EspoCRM pod,
|
||||||
|
# all containers, the generated systemd units AND ALL DATA (DB + files).
|
||||||
|
# Requires an exact confirmation phrase.
|
||||||
|
|
||||||
|
# Environment variables
|
||||||
|
POD_NAME='espocrm_pod'
|
||||||
|
DB_CTR='mariadb_ctr'
|
||||||
|
WEB_CTR='espocrm_ctr'
|
||||||
|
DAEMON_CTR='espocrm_daemon_ctr'
|
||||||
|
BIND_DIR="$HOME/.local/share/$POD_NAME"
|
||||||
|
USER_SYSTEMD_DIR="$HOME/.config/systemd/user"
|
||||||
|
|
||||||
|
# Extra safety prompt
|
||||||
|
read -r -p "WARNING: this deletes the pod, containers, and ALL data under $BIND_DIR. To confirm, type 'RESET espocrm_pod': " C
|
||||||
|
[ "$C" = "RESET espocrm_pod" ] || { echo "Aborted."; exit 1; }
|
||||||
|
|
||||||
|
# Disable & stop the systemd-managed services
|
||||||
|
systemctl --user disable --now "container-${DAEMON_CTR}.service"
|
||||||
|
echo "Disabled container-${DAEMON_CTR}.service (rc=$?)"
|
||||||
|
systemctl --user disable --now "container-${WEB_CTR}.service"
|
||||||
|
echo "Disabled container-${WEB_CTR}.service (rc=$?)"
|
||||||
|
systemctl --user disable --now "container-${DB_CTR}.service"
|
||||||
|
echo "Disabled container-${DB_CTR}.service (rc=$?)"
|
||||||
|
systemctl --user disable --now "pod-${POD_NAME}.service"
|
||||||
|
echo "Disabled pod-${POD_NAME}.service (rc=$?)"
|
||||||
|
|
||||||
|
# Remove the live pod and containers (if any)
|
||||||
|
podman pod rm -f --ignore "$POD_NAME"
|
||||||
|
echo "Removed pod $POD_NAME (rc=$?)"
|
||||||
|
|
||||||
|
# Delete the generated unit files
|
||||||
|
rm -f \
|
||||||
|
"$USER_SYSTEMD_DIR/pod-${POD_NAME}.service" \
|
||||||
|
"$USER_SYSTEMD_DIR/container-${DB_CTR}.service" \
|
||||||
|
"$USER_SYSTEMD_DIR/container-${WEB_CTR}.service" \
|
||||||
|
"$USER_SYSTEMD_DIR/container-${DAEMON_CTR}.service"
|
||||||
|
echo "Removed generated systemd unit files (rc=$?)"
|
||||||
|
|
||||||
|
systemctl --user daemon-reload
|
||||||
|
echo "Reloaded systemd --user daemon (rc=$?)"
|
||||||
|
|
||||||
|
# Delete all data (point of no return)
|
||||||
|
rm -rf "$BIND_DIR"
|
||||||
|
echo "Deleted data directory $BIND_DIR (rc=$?)"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Reset complete. Run create_pod_espocrm.sh again to reinstall EspoCRM."
|
||||||
24
stop_pod_espocrm.sh
Executable file
24
stop_pod_espocrm.sh
Executable file
@@ -0,0 +1,24 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# To be run by user mkt to stop the systemd-managed EspoCRM pod and
|
||||||
|
# containers. Does NOT disable the services: autostart stays in place.
|
||||||
|
|
||||||
|
# Environment variables
|
||||||
|
POD_NAME='espocrm_pod'
|
||||||
|
DB_CTR='mariadb_ctr'
|
||||||
|
WEB_CTR='espocrm_ctr'
|
||||||
|
DAEMON_CTR='espocrm_daemon_ctr'
|
||||||
|
|
||||||
|
# Stop in reverse dependency order: daemon -> web -> db -> pod
|
||||||
|
systemctl --user stop "container-${DAEMON_CTR}.service"
|
||||||
|
echo "Stopped container-${DAEMON_CTR}.service (rc=$?)"
|
||||||
|
systemctl --user stop "container-${WEB_CTR}.service"
|
||||||
|
echo "Stopped container-${WEB_CTR}.service (rc=$?)"
|
||||||
|
systemctl --user stop "container-${DB_CTR}.service"
|
||||||
|
echo "Stopped container-${DB_CTR}.service (rc=$?)"
|
||||||
|
systemctl --user stop "pod-${POD_NAME}.service"
|
||||||
|
echo "Stopped pod-${POD_NAME}.service (rc=$?)"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "EspoCRM stopped (autostart still enabled)."
|
||||||
|
echo "Start again: systemctl --user start pod-${POD_NAME}.service container-${DB_CTR}.service container-${WEB_CTR}.service container-${DAEMON_CTR}.service"
|
||||||
Reference in New Issue
Block a user