Skip to content

Commit b1c5732

Browse files
authored
Merge pull request #838 from jasonacox-sam/feat/restore-script
feat: add restore.sh.sample — companion restore script for backup.sh
2 parents d74c291 + 5607bf9 commit b1c5732

6 files changed

Lines changed: 580 additions & 112 deletions

File tree

RELEASE.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,36 @@
11
# RELEASE NOTES
22

3+
## v5.2.1 - Restore Script: Companion restore.sh for backup.sh
4+
5+
### Upgrading
6+
7+
* **Grafana datasource UID change** — auto-provisioned InfluxDB and Sun/Moon datasources now have explicit, stable UIDs (`pwd-influxdb-auto` and `pwd-sunandmoon-auto`) instead of Grafana-generated ones. This prevents UID collisions and drift across reprovisioning. **Existing installs:** after upgrading, Grafana will create new datasource entries with the pinned UIDs. If dashboards show "datasource not found" on affected panels, either re-import the dashboard or re-link the panel datasource to the same-named entry in the Grafana UI. ([PR #840](https://github.com/jasonacox/Powerwall-Dashboard/pull/840) by **@youzer-name**)
8+
9+
### New Features
10+
11+
* **Restore script** — new `backups/restore.sh.sample`, an automated companion to `backup.sh.sample`, based on `restore_v16a.sh` by **@JonMurphy** ([#836](https://github.com/jasonacox/Powerwall-Dashboard/issues/836)). One command restores a backup archive on the same machine or migrates to a new one:
12+
- Auto-detects the Powerwall-Dashboard directory from the script's own location
13+
- Checks staging disk space before extracting (warns and offers `TMPDIR` override — protects RAM-backed `/tmp` from multi-GB archives)
14+
- Non-destructive — moves existing InfluxDB `data`/`meta`/`wal` and `grafana.db` aside as `.pre-restore.<timestamp>` copies (rollback path) instead of deleting
15+
- Restores InfluxDB from the `influxd backup -portable` snapshot into a clean instance, then re-creates continuous queries from the archive's `continuous_queries.txt` (live CQ state, including customizations) with `influxdb.sql` as fallback — `influxd restore -portable` does not reliably restore CQs (known InfluxDB 1.x limitation). CQ replay output is checked for errors (the influx CLI exits 0 even on failed statements).
16+
- Restores Grafana database and provisioning files with correct ownership, deriving `PWD_USER` as the invoking user's `uid:gid` (`SUDO_UID:SUDO_GID`) — the same convention `setup.sh` uses — with a guard against running from a root shell
17+
- Restores user configuration files (`*.env`, `telegraf.local`, etc.) while **skipping git-managed project files** (`powerwall.yml`, `telegraf.conf`, `influxdb.conf`, `VERSION`) so an older backup can never downgrade the stack or break future `git pull`/upgrades
18+
- Restores `weather/weather411.conf` and `.auth/` Tesla cloud tokens (when present in the archive), so cross-machine migrations keep weather and cloud-mode credentials without re-authenticating
19+
- Finishes with `compose-dash.sh up -d` so containers are **recreated** and restored settings (including the rewritten `PWD_USER`) actually take effect
20+
* **Backup script**`backup.sh.sample` now auto-detects the dashboard directory (no more editing `DASHBOARD=` by hand), verifies the influxdb container is running and checks dashboard-disk free space *before* taking the snapshot, exports live continuous queries into the archive as a safety net, captures `weather/weather411.conf` and `.auth/` tokens, checks the exit code of `influxd backup` (no more silently archiving a failed snapshot), verifies archive integrity after creation, creates archives with mode 600 (they contain credentials), and aborts with a clear message if the staging area can't hold the snapshot (with `TMPDIR` override).
21+
22+
### Documentation
23+
24+
* `backups/README.md` — documents the restore script as the recommended method; manual restore steps retained as a fallback and corrected to exclude git-managed files and use `compose-dash.sh up -d`.
25+
26+
### Contributors
27+
28+
Thanks to **@JonMurphy** for the original `restore_v16a.sh` script, testing, and the detailed restore-procedure feedback in [#836](https://github.com/jasonacox/Powerwall-Dashboard/issues/836).
29+
30+
### Links
31+
32+
* Reported in [#836](https://github.com/jasonacox/Powerwall-Dashboard/issues/836)
33+
* Added in [PR #838](https://github.com/jasonacox/Powerwall-Dashboard/pull/838)
334
## v5.2.0 - Backup Overhaul, Outage Export, verify.sh Fixes & More
435

536
### Backup Script Improvements

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
5.2.0
1+
5.2.1

backups/README.md

Lines changed: 67 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -35,55 +35,75 @@ Backup the Powerwall-Dashboard folder. In that folder are two important folders:
3535
* grafana - This is the folder for the dashboard which holds your setup and customization.
3636

3737
The backup script creates a consistent snapshot of:
38-
1. **InfluxDB** — uses `influxd backup` to create a proper snapshot (not a copy of live data files)
39-
2. **Grafana** — uses `sqlite3 .backup` for a consistent copy of `grafana.db` (falls back to direct copy if sqlite3 is not installed on the host: `sudo apt install sqlite3`)
38+
1. **InfluxDB** — uses `influxd backup -portable` to create a proper online snapshot (not a copy of live data files), plus an export of the live continuous queries
39+
2. **Grafana** — uses `sqlite3 .backup` for a consistent copy of `grafana.db` (falls back to direct copy if sqlite3 is not installed on the host: `sudo apt install sqlite3`), plus provisioning files
4040
3. **Configuration files** — all `.env`, `.conf`, and `.yml` files needed to restore your setup
41+
4. **Weather service**`weather/weather411.conf` (if present)
42+
5. **Tesla cloud tokens** — the `.auth/` directory (if present), so cloud-mode installs migrate without re-authenticating
43+
44+
> **Security note:** backup archives contain credentials (`.env` files, Tesla tokens). The script creates them with mode 600 — keep them protected, especially if you copy them off-machine.
4145
4246
The following shows an example of how to set up automated backups (see backup.sh):
4347

4448
1. Copy backup.sh.sample to backup.sh (cp backup.sh.sample backup.sh)
45-
2. Edit the line that says DASHBOARD="/home/user/Powerwall-Dashboard" to have your dashboard location.
46-
3. Make the script executable with `chmod +x backup.sh`
47-
4. Add to crontab for daily backups: `0 2 * * * /home/user/Powerwall-Dashboard/backups/backup.sh`
49+
2. Make the script executable with `chmod +x backup.sh` (the script auto-detects the dashboard location by finding `compose-dash.sh`)
50+
3. Add to crontab for daily backups: `0 2 * * * /home/user/Powerwall-Dashboard/backups/backup.sh`
51+
52+
The `influxdb` container must be running when the backup runs — the snapshot is taken online with no downtime.
53+
54+
> **Large datasets:** both `backup.sh` and `restore.sh` stage data in a temporary directory (`mktemp -d`, usually under `/tmp`). If your InfluxDB history is large (multi-GB) and `/tmp` is a RAM-backed tmpfs, staging there can exhaust memory. Both scripts check available space first — backup aborts and restore warns — and you can point staging at a disk with more room: `sudo TMPDIR=/path/with/space ./backup.sh`
4855
4956
## Backup Script Example
5057

51-
```bash
52-
#!/bin/bash
53-
# Daily Backup for Powerwall-Dashboard Data
54-
if [ "$EUID" -ne 0 ]
55-
then echo "Must run as root"
56-
exit
57-
fi
58-
59-
# Set values for your environment
60-
DASHBOARD="/home/user/Powerwall-Dashboard" # Location of Dashboard to backup
61-
BACKUP_FOLDER="${DASHBOARD}/backups" # Destination folder for backups
62-
KEEP="5" # Days to keep backup
63-
64-
# ... (see backup.sh.sample for full script)
65-
66-
# The improved backup script:
67-
# 1. Creates an InfluxDB snapshot via influxd backup (avoids "file changed" errors)
68-
# 2. Creates a consistent Grafana DB copy via sqlite3 .backup
69-
# 3. Backs up all config files (compose.env, pypowerwall.env, telegraf.local, etc.)
70-
```
58+
The full script is in `backup.sh.sample`. To set up automated daily backups:
59+
60+
1. `cp backup.sh.sample backup.sh && chmod +x backup.sh`
61+
2. Add to crontab: `0 2 * * * /home/user/Powerwall-Dashboard/backups/backup.sh`
62+
63+
The script auto-detects the dashboard location from its own path (must live in `Powerwall-Dashboard/backups/`). It creates an InfluxDB snapshot, backs up Grafana, captures config files, weather/Alexa settings, and Tesla cloud tokens, then prunes archives older than 5 days. Archives are mode 600 (they contain credentials).
7164

7265
## Restore Backup
7366

7467
Naturally, whatever backup plan you decide to do, make sure you test it. Copy the backup to another VM or box, install Powerwall-Dashboard and restore the backup to see if it all comes back up without any data loss.
7568

76-
### Using the backup script archive
69+
### Using the restore script (recommended)
70+
71+
A companion `restore.sh.sample` is provided to automate the restore process. It handles permissions, pre-restore safety copies, and the correct InfluxDB restore sequence.
72+
73+
1. Copy restore.sh.sample to restore.sh (cp restore.sh.sample restore.sh)
74+
2. Make the script executable with `chmod +x restore.sh`
75+
3. Run as root:
76+
```bash
77+
# Restore from the most recent backup archive
78+
sudo ./restore.sh
79+
80+
# Or specify a specific archive
81+
sudo ./restore.sh /path/to/Powerwall-Dashboard.2026-01-15.tar.xz
82+
```
83+
84+
The restore script will:
85+
1. **Auto-detect** the Powerwall-Dashboard directory by locating `compose-dash.sh`
86+
2. **Check staging disk space** and warn before extracting a large archive into a location that can't hold it (use `sudo TMPDIR=/path/with/space ./restore.sh` to relocate staging)
87+
3. **Stop all containers** before touching data
88+
4. **Restore InfluxDB** from the `influxd backup -portable` snapshot, moving existing data aside first (not deleted — you get a rollback path), then re-create continuous queries from the archive (with `influxdb.sql` as fallback)
89+
5. **Restore Grafana** database and provisioning files with correct ownership
90+
6. **Restore configuration files**, rewriting `PWD_USER` in `compose.env` to match this host's actual user and primary group (same `uid:gid` convention as `setup.sh`). Project files managed by git (`powerwall.yml`, `telegraf.conf`, `influxdb.conf`, `VERSION`) are kept in the archive for reference but are NOT restored over the current checkout — this prevents an older backup from downgrading the stack or breaking future upgrades.
91+
7. **Restore weather411.conf and .auth tokens** (when present in the archive — older archives without them restore fine)
92+
8. **Recreate the stack** (`compose-dash.sh up -d`, so restored settings take effect) and print a list of pre-restore backup paths to clean up once confirmed
93+
94+
### Manual restore from a backup script archive
7795

7896
The backup script creates an archive with this structure:
7997

8098
```
81-
influxdb/ # InfluxDB snapshot files (from influxd backup)
99+
influxdb/ # InfluxDB portable snapshot + continuous_queries.txt
82100
grafana/ # grafana.db (consistent copy) + provisions
83101
config/ # configuration files (.env, .conf, .yml)
102+
weather/ # weather411.conf (if present)
103+
auth/ # .auth Tesla cloud tokens (if present)
84104
```
85105
86-
To restore from a backup script archive:
106+
To restore manually from a backup script archive:
87107
88108
1. Install a fresh instance of Powerwall-Dashboard per [Setup instructions](https://github.com/jasonacox/Powerwall-Dashboard#setup), then start it once so the `influxdb` container is running and the default `powerwall` database exists.
89109
2. Stop **telegraf and grafana** only — keep `influxdb` running so `docker exec` works:
@@ -107,20 +127,35 @@ To restore from a backup script archive:
107127
docker exec influxdb influx -database powerwall -execute "DROP DATABASE powerwall"
108128
# Restore using -portable to match the backup format:
109129
docker exec influxdb influxd restore -portable /var/lib/influxdb/backups
130+
# Re-create continuous queries (influxd restore does not reliably restore CQs):
131+
grep '^CREATE CONTINUOUS QUERY' "${DASHBOARD}/influxdb/influxdb.sql" \
132+
| docker exec -i influxdb influx -database powerwall
110133
111134
# Restore Grafana
112135
sudo cp -a /tmp/pwd-restore/grafana/grafana.db "${DASHBOARD}/grafana/"
113136
sudo cp -a /tmp/pwd-restore/grafana/provisions/. "${DASHBOARD}/grafana/provisions/" 2>/dev/null
114137
115-
# Restore config files
116-
sudo cp -a /tmp/pwd-restore/config/. "${DASHBOARD}/"
138+
# Restore config files (exclude git-managed project files - restoring an
139+
# older powerwall.yml/telegraf.conf/VERSION would downgrade the stack and
140+
# cause git pull conflicts on future upgrades)
141+
for f in /tmp/pwd-restore/config/* /tmp/pwd-restore/config/.*.env; do
142+
case "$(basename "$f")" in
143+
powerwall.yml|telegraf.conf|influxdb.conf|VERSION|_config.yml) continue ;;
144+
esac
145+
[ -f "$f" ] && sudo cp -a "$f" "${DASHBOARD}/"
146+
done
147+
148+
# Restore weather411 config and Tesla cloud tokens (newer archives)
149+
[ -f /tmp/pwd-restore/weather/weather411.conf ] && sudo cp -a /tmp/pwd-restore/weather/weather411.conf "${DASHBOARD}/weather/"
150+
[ -d /tmp/pwd-restore/auth ] && sudo mkdir -p "${DASHBOARD}/.auth" && sudo cp -a /tmp/pwd-restore/auth/. "${DASHBOARD}/.auth/"
117151
118152
# Clean up
119153
sudo rm -rf /tmp/pwd-restore
120154
```
121-
4. Start containers
155+
4. Recreate containers so restored settings take effect ('start' alone would
156+
resume the old containers with stale configuration)
122157
```bash
123-
./compose-dash.sh start
158+
./compose-dash.sh up -d
124159
```
125160
126161
### Using a full directory backup (transfer method)

0 commit comments

Comments
 (0)