feat(free_games_claimer): store application data in /config/data (#3088)

* feat(free_games_claimer): store application data in /config/data

The add-on kept everything the application writes in its private /data
volume, so the claim database, the screenshots and the browser profiles
could only be reached with a "docker exec" (#3081).

/fgc/data now points at /config/data, which Home Assistant exposes as
/addon_configs/xxx-free_games_claimer/data. This is the pattern the
aurral, maintainerr and nextcloud add-ons already use for the same
problem.

An existing /data payload is copied over once on first start. The copy
is staged in /config/.data-migration and renamed into place, so an
interrupted migration is retried on the next start instead of leaving a
half-copied database or browser profile behind. Nothing is removed from
/data, so a downgrade to 2.1.0 still finds its data.

Two clean-ups in the same script, both consequences of the move: the
"cp -rnf /fgc/* /data/" line copied the whole upstream source tree into
the persistent volume on every start and nothing ever read those copies,
and the recursive "chmod 777" on the configuration directory would now
have made the migrated browser profile and the credentials in config.env
world-writable.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* fix(free_games_claimer): address review findings on the data migration

Three defects found by the Codex and CodeRabbit PR reviewers, all
reproduced before being accepted:

- A CONFIG_LOCATION under /config/data (for example
  /config/data/custom.env) made "mkdir -p $HOME" create the migration's
  own guard directory before the guard was tested, so the migration
  silently skipped itself and the add-on started with no claim history
  and no authenticated sessions. The migration now runs before the
  CONFIG_LOCATION directory is created.

- The copy list held prime-gaming.json but not epic-games.json or
  gog.json, although migrate_vogler_data.py's locate_source() supports
  all three at the data root. A user whose only legacy history was Epic
  or GOG would have had the migrator write a completion marker with zero
  imported records.

- fgc.db-journal was not copied. Upstream sets no PRAGMA journal_mode,
  so SQLite runs in its default rollback-journal mode and a hot journal
  left by an unclean stop is needed to recover the database.

Also: CONFIG_LOCATION=/config/data/config.env made CONFIG_FILE and
RUNTIME_CONFIG the same path, and GNU install refuses a self-copy with
status 1, which aborted the "set -e" init script before the application
started. Verified: "install -m 0600 f f" exits 1 with "are the same
file".

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* fix(free_games_claimer): keep mode 0600 on the runtime config from creation

The self-copy guard added in 4fd0cd5 dropped "install -m 0600" to a bare
"install" followed by a chmod, which left the credentials in
/config/data/config.env at install's default mode 0755 between the two
commands. Restore the mode on install; the chmod stays for the case
where CONFIG_LOCATION already is the runtime path and install is
skipped.

Verified both branches: different paths and same path each end at mode
600 with exit status 0.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Alexandre
2026-09-24 11:10:29 +01:00
committed by GitHub
parent 35dd359202
commit 1c554cd3bc
7 changed files with 104 additions and 16 deletions

View File

@@ -1,3 +1,34 @@
## 2.2.0 (2026-09-24)
- Moved the application data out of the add-on's private `/data` volume and
into `/config/data`, so it is visible from Home Assistant as
`/addon_configs/xxx-free_games_claimer/data` instead of needing a
`docker exec`. Everything the application writes now lands there: `fgc.db`,
the `screenshots/` captures, the `browser/` profiles, `TurboVNC.log` and
upstream's debug dumps (#3081).
- An existing `/data` payload is copied over once on the first start of this
version: `fgc.db` with its rollback journal and its pre-migration backup,
`browser/`, `screenshots/`, the `epic-games.json`, `prime-gaming.json` and
`gog.json` claim histories, the legacy `data/` directory and the migration
marker. Logs and last-run debug dumps are not copied, because the application
regenerates them. The copy is staged and renamed into place, so an interrupted
migration is retried rather than leaving a half-copied database or browser
profile. Nothing is deleted from `/data`: the migration needs temporary free
space roughly equal to the existing data, can take a few minutes for a large
browser profile, and leaves the old copy in place so a downgrade still
works.
- **The migrated `browser/` directory holds authenticated store sessions and
`config.env` holds the account credentials. Both are now readable by any
add-on with access to `addon_configs`, such as File Editor or Samba. Treat
that directory as secret and do not share or back it up publicly.**
- Removed the `cp -rnf /fgc/* /data/` line from `20-folders.sh`, which copied
the whole upstream source tree into the persistent volume on every start.
Nothing read those copies. They are left in `/data` and can be deleted by
hand.
- Stopped applying a recursive `chmod 777` to the configuration directory on
every start, which would otherwise have made the migrated browser profile
and credentials world-writable.
## 2.1.1 (2026-09-12)
- Update to latest version from P-Adamiec/Free-Games-Claimer-Remaster (changelog : https://github.com/P-Adamiec/Free-Games-Claimer-Remaster/releases)

View File

@@ -118,7 +118,7 @@ RUN (curl --proto "=https" --tlsv1.2 -fsSL \
&& chmod 0755 /usr/local/bin/docker-entrypoint.sh \
&& rm -f /tmp/free-games-claimer-remaster.tar.gz \
&& rm -rf /fgc/data \
&& ln -s /data /fgc/data
&& ln -s /config/data /fgc/data
# Add Home Assistant integration files and shared helper modules.
COPY rootfs/ /

View File

@@ -67,6 +67,31 @@ the default and preserves the behavior of the former vogler-based add-on.
With `RUN_ONCE: false`, the remaster remains running and uses its internal
scheduler. Set `SCHEDULER_HOURS` in `config.env` to control the interval.
## Application data
The add-on stores everything the application writes in `/config/data`, which
Home Assistant exposes as `/addon_configs/xxx-free_games_claimer/data`. It can
be inspected with a file browser add-on without a `docker exec`, and contains:
| Path | Contents |
|------|----------|
| `fgc.db` | SQLite claim history |
| `screenshots/<store>/` | Screenshots taken during a claiming run |
| `browser/` | Chromium profiles, one per store |
| `TurboVNC.log` | Virtual display server log |
| `config.env` | Runtime copy of `CONFIG_LOCATION` |
**This directory is secret.** `browser/` holds signed-in store sessions and
`config.env` holds the account credentials, so anyone with access to
`addon_configs` — the File Editor and Samba add-ons, for instance — can use
them. Do not share or publish it.
Versions up to 2.1.1 kept this data in the private `/data` volume. An existing
payload is copied to `/config/data` once, on the first start of version 2.2.0. The copy needs temporary free space roughly equal to the
existing data and can take a few minutes when the browser profile is large.
Nothing is removed from `/data`, so a downgrade keeps working; the old copy can
be deleted by hand once the new location is confirmed to work.
## Environment configuration
The add-on keeps its configuration in `CONFIG_LOCATION`, which defaults to
@@ -124,12 +149,13 @@ The add-on performs the following migration automatically on first start:
1. The existing `config.env` remains at the same configured location.
2. Legacy `epic-games.json`, `prime-gaming.json`, and `gog.json` claim history
is imported into the remaster SQLite database at `/data/fgc.db`.
is imported into the remaster SQLite database at `/config/data/fgc.db`.
3. Existing database rows are detected and are not duplicated if migration is
retried.
4. A pre-migration database backup is created when an existing `fgc.db` is
present.
5. All old files remain under `/data/data` for rollback or manual recovery.
5. All old files remain under `/config/data/data` for rollback or manual
recovery.
Browser sessions cannot be converted because the old add-on used a shared
Firefox profile while the remaster uses separate Chromium profiles per store.

View File

@@ -96,5 +96,5 @@ schema:
slug: free_games_claimer
udev: true
url: https://github.com/alexbelgium/hassio-addons
version: "2.1.1"
version: "2.2.0"
webui: "[PROTO:ssl]://[HOST]:[PORT:6080]"

View File

@@ -2,14 +2,41 @@
# shellcheck shell=bash
set -e
# Up to version 2.1.1 the application stored its data in the add-on's private
# /data volume, which is only reachable with "docker exec". It now lives in
# /config/data, which Home Assistant exposes as
# /addon_configs/xxx-free_games_claimer/data. Copy an existing payload over
# once. The copy is staged and renamed into place, so an interrupted migration
# is retried on the next start instead of leaving a half-copied database or
# browser profile behind. Nothing is removed from /data, so downgrading still
# finds its data.
#
# This runs before the CONFIG_LOCATION directory is created below: a
# CONFIG_LOCATION under /config/data would otherwise create the destination
# and make the migration skip itself.
if [ ! -d /config/data ]; then
legacy=()
for entry in fgc.db fgc.db-journal fgc.db.pre-vogler-migration \
.vogler-remaster-migrated-v1.json browser screenshots data \
epic-games.json prime-gaming.json gog.json; do
if [ -e "/data/$entry" ]; then
legacy+=("/data/$entry")
fi
done
if [ "${#legacy[@]}" -gt 0 ]; then
echo "Copying the application data to /config/data, this can take a few minutes ..."
rm -rf /config/.data-migration
mkdir -p /config/.data-migration
cp -a "${legacy[@]}" /config/.data-migration/
mv /config/.data-migration /config/data
fi
fi
mkdir -p /config/data
# Define home
# Creating config location
echo "Creating config location ..."
HOME="$(bashio::config "CONFIG_LOCATION")"
HOME="$(dirname "$HOME")"
mkdir -p "$HOME"
chmod -R 777 "$HOME"
# Copy files to data
echo "Copying files if needed..."
cp -rnf /fgc/* /data/

View File

@@ -7,9 +7,9 @@ if bashio::config.has_value 'CONFIG_LOCATION'; then
CONFIG_FILE="$(bashio::config 'CONFIG_LOCATION')"
fi
CONFIG_DIR="$(dirname "${CONFIG_FILE}")"
RUNTIME_CONFIG="/data/config.env"
RUNTIME_CONFIG="/config/data/config.env"
mkdir -p "${CONFIG_DIR}" /data
mkdir -p "${CONFIG_DIR}" /config/data
# Recover from an old add-on bug that could create config.env as a directory.
if [ -d "${CONFIG_FILE}" ]; then
@@ -25,9 +25,13 @@ else
bashio::log.info "Using configuration from ${CONFIG_FILE}"
fi
# The remaster reads /fgc/data/config.env. /fgc/data is linked to Home
# Assistant's persistent /data volume by the Dockerfile.
install -m 0600 "${CONFIG_FILE}" "${RUNTIME_CONFIG}"
# The remaster reads /fgc/data/config.env. /fgc/data is linked to /config/data
# by the Dockerfile, so the runtime copy is visible under /addon_configs.
# CONFIG_LOCATION may itself be /config/data/config.env, in which case the two
# paths are the same file and install would fail. install applies the mode as it
# creates the file; the chmod is for that same-file case.
[ "${CONFIG_FILE}" -ef "${RUNTIME_CONFIG}" ] || install -m 0600 "${CONFIG_FILE}" "${RUNTIME_CONFIG}"
chmod 0600 "${RUNTIME_CONFIG}"
sed -i 's/\r$//' "${RUNTIME_CONFIG}"
# Export values needed by the VNC entrypoint as well as by the Python app.

View File

@@ -12,7 +12,7 @@ from datetime import datetime, timezone
from pathlib import Path
from typing import Any, Iterator
DATA_DIR = Path(os.environ.get("FGC_DATA_DIR", "/data"))
DATA_DIR = Path(os.environ.get("FGC_DATA_DIR", "/config/data"))
LEGACY_DIR = DATA_DIR / "data"
DATABASE = DATA_DIR / "fgc.db"
MARKER = DATA_DIR / ".vogler-remaster-migrated-v1.json"
@@ -220,7 +220,7 @@ def migrate() -> int:
if legacy_browser.exists():
log(
"Legacy Firefox browser data remains in /data/data/browser. It is "
"Legacy Firefox browser data remains in /config/data/data/browser. It is "
"not compatible with Chromium, so use noVNC for a one-time login if needed."
)