Scrapes BullionVault (gold, silver) and Coinbase (BTC, ETH) on a background schedule (default every 3600s). Serves Prometheus metrics, a portfolio tracker, and price charts.
-
/→/portfolio— holdings (gold, silver, BTC, ETH, stocks, cash, property), live estimates, multi-currency history charts -
/dashboard— spot price charts (one point per scrape) -
/metrics— Prometheus text (last successful scrape) -
/health,/ready— probes
bundle install
rake serverOpen http://localhost:8080. rake dev adds auto-reload. rake help lists all tasks.
Images are published to quay.io/dkirwan/asset-monitoring.
-
make podman-build/rake podman:buildtags a local build asquay.io/dkirwan/asset-monitoring:dev -
make podman-run/rake podman:runrunsquay.io/dkirwan/asset-monitoring:latest(pulled from Quay if not present locally)
Run the published image:
make podman-runRun a local dev build:
make podman-build
USE_DEV_IMAGE=true make podman-runBinds ./data → /data with SQLite for price and portfolio history (365-day retention by default). Override with DATA_DIR, PRICE_HISTORY_RETENTION_DAYS, PRICE_HISTORY_DB_PATH, PORTFOLIO_DB_PATH.
Override image tags:
BUILD_IMAGE=quay.io/dkirwan/asset-monitoring:dev make podman-build
IMAGE=quay.io/dkirwan/asset-monitoring:latest make podman-runAfter building locally, push the dev image to Quay when you are ready to publish:
podman push quay.io/dkirwan/asset-monitoring:devPodman integrates with systemd through Quadlet.
A .container unit in deploy/asset-monitoring.container describes the service; systemd generates asset-monitoring.service from it at daemon-reload time.
This matches rake podman:run / make podman-run: the Quay :latest image, port 8080, SQLite under /data, and 365-day price history retention.
Quadlet-generated units are transient — do not run systemctl enable on them (that fails with "Unit is transient or generated"). Boot wiring is handled by the [Install] section in the .container file when you run daemon-reload.
-
Podman with Quadlet support (Fedora 38+, RHEL 9+, or recent Podman elsewhere)
-
systemd user session (for a rootless service) or root (for a system service)
Create a data directory, pull the image, and install the Quadlet unit:
mkdir -p ~/.local/share/asset-monitoring/data
podman pull quay.io/dkirwan/asset-monitoring:latest
mkdir -p ~/.config/containers/systemd
cp deploy/asset-monitoring.container ~/.config/containers/systemd/
systemctl --user daemon-reload
systemctl --user start asset-monitoring.servicedaemon-reload reads the .container file, generates the service unit, and applies the [Install] section (WantedBy=default.target) so the service starts on future user logins. Use start (not enable) to run it immediately.
Open http://localhost:8080/portfolio once the service is active.
The default unit stores SQLite data in ~/.local/share/asset-monitoring/data. Edit the Volume= line in ~/.config/containers/systemd/asset-monitoring.container before daemon-reload if you want a different path.
To keep the service running after you log out (and across reboots without a graphical login), enable linger:
loginctl enable-linger "$USER"For a machine-wide service running as root:
sudo mkdir -p /var/lib/asset-monitoring/data
sudo podman pull quay.io/dkirwan/asset-monitoring:latestCopy deploy/asset-monitoring.container to /etc/containers/systemd/asset-monitoring.container, then adjust:
-
Volume=— e.g./var/lib/asset-monitoring/data:/data:Z,U(replace the default%h/.local/share/…path; keep:Uso the container user can write SQLite files) -
[Install]— setWantedBy=multi-user.target
Reload and start:
sudo systemctl daemon-reload
sudo systemctl start asset-monitoring.serviceRootless (per-user) commands:
systemctl --user status asset-monitoring.service
systemctl --user restart asset-monitoring.service
systemctl --user stop asset-monitoring.service
journalctl --user -u asset-monitoring.service -fSystem-wide commands use sudo systemctl and sudo journalctl without --user.
After editing the .container file, reload systemd before restarting:
systemctl --user daemon-reload
systemctl --user restart asset-monitoring.servicePull a newer image and restart:
podman pull quay.io/dkirwan/asset-monitoring:latest
systemctl --user restart asset-monitoring.serviceThe unit sets io.containers.autoupdate=registry so podman auto-update can refresh the image on a schedule if you enable that separately.
To run a local :dev image instead, change Image= in the .container file to quay.io/dkirwan/asset-monitoring:dev (or your own tag), run daemon-reload, then restart the service.
The container runs as UID 1001 (appuser). The Quadlet unit mounts the data directory with :Z,U so Podman relabels it for SELinux and chowns it for the container user — the same :Z,U flags used by make podman-run.
If the service still cannot create asset_history.db or portfolio.db, update the unit file, reload, and restart:
cp deploy/asset-monitoring.container ~/.config/containers/systemd/
systemctl --user daemon-reload
systemctl --user restart asset-monitoring.serviceIf the directory was created before :U was set, fix ownership once on the host:
chown -R 1001:1001 ~/.local/share/asset-monitoring/data
systemctl --user restart asset-monitoring.serviceCheck logs for SQLite errors:
journalctl --user -u asset-monitoring.service -n 50 --no-pager| Path | Purpose
| /api/portfolio.json | GET / PUT / POST portfolio holdings
| /api/portfolio_history.json | Portfolio values over time (EUR, USD, GBP, JPY)
| /api/spot_prices.json | Latest spot prices for valuation
| /api/price_history.json | Dashboard time series
Portfolio snapshots are recorded on save and after each successful scrape. Stocks, cash, and property use FX cross-rates from gold/silver spot quotes.
| Variable | Purpose |
|---|---|
|
Listen port (default |
|
Scrape interval (default |
|
|
|
SQLite path for spot price history (omit for in-memory only) |
|
SQLite path for holdings and portfolio history |
|
History retention in days (default |
|
|
Make/Rake-only variables (not read from .env):
-
USE_DEV_IMAGE— whentrue,1, oryes,podman:runusesquay.io/dkirwan/asset-monitoring:devinstead of:latest -
BUILD_IMAGE— image tag forpodman:build(default:quay.io/dkirwan/asset-monitoring:dev) -
IMAGE— image tag forpodman:runwhenUSE_DEV_IMAGEis unset (default:quay.io/dkirwan/asset-monitoring:latest)