Add README, customization snapshot, and snapshot/restore tooling
Provisioning now restores all GUI customizations on reset+reprovision: - create_pod_espocrm.sh: deploy the version-controlled espocrm-custom/ tree (CTag entity, layouts, i18n, clientDefs, custom views, custom CSS) into the pod, then chown www-data and rebuild. Replaces the earlier inline CSS-only step. Adds a live-phase cache rebuild so customizations and the client cacheTimestamp are refreshed on every run. - espocrm-custom/: snapshot of custom/ and client/custom/ (source of truth). - snapshot_espocrm_custom.sh: refresh the snapshot from a running pod. - readme.md: usage, first-time host setup, image-update and reset workflows. - Include the task/instruction notes and plan.md for reference. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
276
readme.md
276
readme.md
@@ -1 +1,275 @@
|
||||
user mkt folder /home/mkt/bin git repository
|
||||
# EspoCRM on DesTEngSsv006 — rootless Podman pod
|
||||
|
||||
This repository contains the shell scripts that run **EspoCRM** as a **rootless
|
||||
Podman pod** under the local user `mkt`, plus the version-controlled snapshot of
|
||||
all GUI customizations. Everything is driven by a handful of `*.sh` scripts; you
|
||||
do not edit anything inside the running container by hand.
|
||||
|
||||
> This is a **private** repository classified as a company secret. Plaintext
|
||||
> passwords live directly in `create_pod_espocrm.sh` on purpose — keep the repo
|
||||
> private.
|
||||
|
||||
---
|
||||
|
||||
## 1. What gets deployed
|
||||
|
||||
`create_pod_espocrm.sh` builds one pod with three containers:
|
||||
|
||||
| Container | Image | Role |
|
||||
|-----------------------|-----------------------------------------|---------------------------------------|
|
||||
| `mariadb_ctr` | `docker.io/library/mariadb:11.4.12` | Database (utf8mb4 / utf8mb4_unicode_ci) |
|
||||
| `espocrm_ctr` | `docker.io/espocrm/espocrm:9.3.8` | Web app (Apache) |
|
||||
| `espocrm_daemon_ctr` | `docker.io/espocrm/espocrm:9.3.8` | Scheduler / cron loop |
|
||||
|
||||
Pod name: **`espocrm_pod`**. Images are **pinned** (no auto-updates).
|
||||
|
||||
**Ports — loopback only** (reach them via an SSH tunnel or a local reverse proxy):
|
||||
|
||||
| Host address | → | Container | Purpose |
|
||||
|-----------------------|----|-----------|-------------------------------|
|
||||
| `127.0.0.1:8093` | → | `:80` | EspoCRM web UI |
|
||||
| `127.0.0.1:8094` | → | `:3306` | MariaDB (host-side DB access) |
|
||||
|
||||
Web UI: **http://127.0.0.1:8093** · Admin user: **`admin`** (password = the
|
||||
`ESPOCRM_ADMIN_PASSWORD` value in `create_pod_espocrm.sh`).
|
||||
|
||||
**Data lives in bind mounts on the host** (not in named volumes):
|
||||
|
||||
```
|
||||
~/.local/share/espocrm_pod/mariadb -> /var/lib/mysql (database files)
|
||||
~/.local/share/espocrm_pod/espocrm -> /var/www/html (app, uploads, config, customizations)
|
||||
```
|
||||
|
||||
**Autostart:** Podman 4.3.1 has no Quadlet, so the scripts generate
|
||||
`systemd --user` units (`podman generate systemd --files --new`) and enable them.
|
||||
The systemd-managed instance is what actually runs after provisioning.
|
||||
|
||||
---
|
||||
|
||||
## 2. The scripts at a glance
|
||||
|
||||
| Script | What it does |
|
||||
|------------------------------|-----------------------------------------------------------------------------|
|
||||
| `create_pod_espocrm.sh` | Create/recreate the pod, deploy GUI customizations, rebuild, enable autostart. **Safe to re-run.** |
|
||||
| `stop_pod_espocrm.sh` | Stop the running containers + pod (autostart stays enabled). |
|
||||
| `backup_espocrm.sh` | Write a timestamped DB dump + a tarball of the app data dir to `~/bak`. |
|
||||
| `restore_espocrm.sh` | Restore a backup set (DB + files). `--list` shows sets, `--yes` skips the prompt. |
|
||||
| `snapshot_espocrm_custom.sh` | Refresh the `espocrm-custom/` snapshot from the running pod after GUI edits. |
|
||||
| `reset_pod_espocrm.sh` | **DANGER:** delete the pod, units **and all data**. Requires typing a phrase.|
|
||||
| `create_pod_traefik.sh` | Unrelated reference script (Traefik pod) — kept as the house-style template. |
|
||||
|
||||
All scripts are run **as user `mkt`**, from this directory:
|
||||
|
||||
```bash
|
||||
cd ~/bin
|
||||
./create_pod_espocrm.sh
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. First-time setup on a freshly installed host
|
||||
|
||||
The scripts assume the rootless-Podman groundwork is already in place. On a brand
|
||||
new host, verify these **prerequisites** first (one-time, usually needs root):
|
||||
|
||||
1. **Podman installed** (4.3.x is what this was built for):
|
||||
```bash
|
||||
podman --version
|
||||
```
|
||||
2. **User `mkt` exists** and has **subuid/subgid ranges** (needed for rootless
|
||||
user-namespace mapping):
|
||||
```bash
|
||||
grep '^mkt:' /etc/subuid /etc/subgid # each should print a line
|
||||
# if missing (as root): usermod --add-subuids 524288-589823 --add-subgids 524288-589823 mkt
|
||||
```
|
||||
3. **Linger enabled** for `mkt`, so the user's systemd services start at boot and
|
||||
keep running without an active login:
|
||||
```bash
|
||||
loginctl show-user mkt -p Linger # want: Linger=yes
|
||||
# if not: sudo loginctl enable-linger mkt
|
||||
```
|
||||
4. **A user systemd session is reachable.** When working over plain SSH you may
|
||||
need:
|
||||
```bash
|
||||
export XDG_RUNTIME_DIR=/run/user/$(id -u)
|
||||
systemctl --user status # should respond
|
||||
```
|
||||
|
||||
Then, as `mkt`:
|
||||
|
||||
```bash
|
||||
cd ~/bin
|
||||
./create_pod_espocrm.sh
|
||||
```
|
||||
|
||||
On this **first run** the script will:
|
||||
|
||||
- pull the pinned images,
|
||||
- run the EspoCRM installer against an empty database (creates the schema and the
|
||||
`admin` user from the credentials in the script),
|
||||
- deploy all GUI customizations from `espocrm-custom/`,
|
||||
- run a cache rebuild,
|
||||
- generate and enable the `systemd --user` services (autostart).
|
||||
|
||||
When it finishes, open **http://127.0.0.1:8093** and log in as `admin`.
|
||||
|
||||
> Reaching the UI from your workstation: it only listens on loopback. Use an SSH
|
||||
> tunnel, e.g. `ssh -L 8093:127.0.0.1:8093 mkt@DesTEngSsv006`, then browse to
|
||||
> `http://127.0.0.1:8093` locally.
|
||||
|
||||
---
|
||||
|
||||
## 4. Everyday operations
|
||||
|
||||
```bash
|
||||
# Start (after a stop) — the systemd units stay enabled, so this also happens on boot:
|
||||
systemctl --user start pod-espocrm_pod.service \
|
||||
container-mariadb_ctr.service container-espocrm_ctr.service container-espocrm_daemon_ctr.service
|
||||
|
||||
# Stop everything (autostart remains enabled):
|
||||
./stop_pod_espocrm.sh
|
||||
|
||||
# Status:
|
||||
systemctl --user status pod-espocrm_pod.service
|
||||
systemctl --user status container-espocrm_ctr.service
|
||||
|
||||
# Live logs:
|
||||
journalctl --user -u container-espocrm_ctr.service -f
|
||||
```
|
||||
|
||||
Re-running `./create_pod_espocrm.sh` at any time is safe: it recreates the
|
||||
containers from the persisted data, redeploys customizations, and rebuilds.
|
||||
|
||||
---
|
||||
|
||||
## 5. Backups and restore
|
||||
|
||||
Backups are **manual** (no timer/cron). Each run writes two timestamped files to
|
||||
`~/bak`: a gzipped SQL dump and a tarball of the app data dir (which includes
|
||||
`config.php` with the crypt key, uploads, and customizations).
|
||||
|
||||
```bash
|
||||
./backup_espocrm.sh # creates ~/bak/espocrm-db-<TS>.sql.gz and ...-files-<TS>.tar.gz
|
||||
|
||||
./restore_espocrm.sh --list # list available backup sets
|
||||
./restore_espocrm.sh # restore the latest set (asks for confirmation)
|
||||
./restore_espocrm.sh 20260606-1346 # restore a specific set by timestamp
|
||||
```
|
||||
|
||||
`restore_espocrm.sh` checks the archives, drops & re-imports the database, and
|
||||
replaces the app data dir, then rebuilds. **Take a backup before any risky
|
||||
operation** (image update, reset, major change).
|
||||
|
||||
---
|
||||
|
||||
## 6. GUI customizations (important workflow)
|
||||
|
||||
All customizations made through the EspoCRM GUI (Entity Manager, Layout Manager,
|
||||
Label Manager, custom fields/views, custom CSS, …) are stored in
|
||||
**`espocrm-custom/`** in this repo and deployed by `create_pod_espocrm.sh`. This
|
||||
snapshot is the **single source of truth** — a reset + reprovision restores it.
|
||||
|
||||
Current customizations captured here include the `CTag` tag entity and its
|
||||
relationships, the Tags panels (Create `+` button removed, row menu reduced to
|
||||
*Unlink*), the signature-editor image button, and variable-width Markdown tables.
|
||||
|
||||
**The golden rule:** after you change anything in the EspoCRM GUI, capture it:
|
||||
|
||||
```bash
|
||||
./snapshot_espocrm_custom.sh # pull current customizations into espocrm-custom/
|
||||
git add espocrm-custom && git commit -m "Update EspoCRM customizations snapshot"
|
||||
```
|
||||
|
||||
If you skip this, the next `create_pod_espocrm.sh` run will **revert** your
|
||||
un-captured GUI changes back to whatever is in `espocrm-custom/`.
|
||||
|
||||
> Note: customizations are *files*. Your actual records (tags, opportunities,
|
||||
> contacts, …) are *data* and live only in the database — protect those with
|
||||
> `backup_espocrm.sh`, not the snapshot.
|
||||
|
||||
---
|
||||
|
||||
## 7. Updating the container images
|
||||
|
||||
Images are pinned, so updates are deliberate. **Always back up first.**
|
||||
|
||||
```bash
|
||||
./backup_espocrm.sh
|
||||
```
|
||||
|
||||
### EspoCRM (e.g. 9.3.8 → a newer 9.x)
|
||||
|
||||
1. Edit the version in `create_pod_espocrm.sh` (the web and daemon share the same
|
||||
`ESPO_IMAGE` variable, so one change covers both):
|
||||
```bash
|
||||
ESPO_IMAGE='docker.io/espocrm/espocrm:<new-version>'
|
||||
```
|
||||
2. Pull and reprovision:
|
||||
```bash
|
||||
podman pull docker.io/espocrm/espocrm:<new-version>
|
||||
./create_pod_espocrm.sh
|
||||
```
|
||||
The EspoCRM container entrypoint **auto-runs its upgrade** when the image
|
||||
version is newer than the installed version (it migrates the database and app
|
||||
files on the bind mount). The script then redeploys customizations and
|
||||
rebuilds.
|
||||
3. Verify the UI and your customizations. If you tweaked anything in the GUI as
|
||||
part of the upgrade, re-run `./snapshot_espocrm_custom.sh` and commit.
|
||||
|
||||
### MariaDB (e.g. 11.4.12 → a newer 11.4.x patch)
|
||||
|
||||
Patch/minor updates **within the same 11.4 LTS series** are data-compatible:
|
||||
|
||||
```bash
|
||||
# edit DB_IMAGE in create_pod_espocrm.sh, then:
|
||||
podman pull docker.io/library/mariadb:<new-11.4.x>
|
||||
./create_pod_espocrm.sh
|
||||
```
|
||||
|
||||
For a **major** MariaDB jump (e.g. 11.x → 12.x) do not just swap the tag —
|
||||
back up, then dump/restore into a fresh data dir, and test. When in doubt, take
|
||||
a backup and try it on a throwaway copy first.
|
||||
|
||||
### After any image change
|
||||
|
||||
```bash
|
||||
podman ps # all three containers Up
|
||||
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8093/ # expect 200
|
||||
podman image prune # optionally drop the old images
|
||||
```
|
||||
|
||||
Commit the bumped image tag(s) in `create_pod_espocrm.sh`.
|
||||
|
||||
---
|
||||
|
||||
## 8. Resetting / uninstalling
|
||||
|
||||
`reset_pod_espocrm.sh` **destroys the pod, the systemd units, and ALL data**
|
||||
(database + uploads). It asks you to type `RESET espocrm_pod` to proceed.
|
||||
|
||||
```bash
|
||||
./backup_espocrm.sh # do this first if you might want the data back
|
||||
./reset_pod_espocrm.sh
|
||||
./create_pod_espocrm.sh # fresh install; customizations are restored from espocrm-custom/
|
||||
# (optional) restore your data:
|
||||
./restore_espocrm.sh
|
||||
```
|
||||
|
||||
After a reset, a fresh `create_pod_espocrm.sh` gives you a clean install with all
|
||||
**customizations** back in place; **records** come back only via `restore`.
|
||||
|
||||
---
|
||||
|
||||
## 9. Repository layout
|
||||
|
||||
```
|
||||
create_pod_espocrm.sh # provision + autostart + deploy customizations
|
||||
stop_pod_espocrm.sh # stop the pod
|
||||
backup_espocrm.sh # back up DB + files to ~/bak
|
||||
restore_espocrm.sh # restore a backup set
|
||||
snapshot_espocrm_custom.sh # refresh espocrm-custom/ from the running pod
|
||||
reset_pod_espocrm.sh # DANGER: delete pod + units + all data
|
||||
espocrm-custom/ # version-controlled GUI customizations (source of truth)
|
||||
create_pod_traefik.sh # unrelated reference script (house-style template)
|
||||
*.md # task/instruction notes and this readme
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user