Skip to content

davidkirwan/asset_monitoring

Repository files navigation

Asset monitoring

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

Run locally

bundle install
rake server

Open http://localhost:8080. rake dev adds auto-reload. rake help lists all tasks.

Run with Podman

Images are published to quay.io/dkirwan/asset-monitoring.

  • make podman-build / rake podman:build tags a local build as quay.io/dkirwan/asset-monitoring:dev

  • make podman-run / rake podman:run runs quay.io/dkirwan/asset-monitoring:latest (pulled from Quay if not present locally)

Run the published image:

make podman-run

Run a local dev build:

make podman-build
USE_DEV_IMAGE=true make podman-run

Binds ./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-run

After building locally, push the dev image to Quay when you are ready to publish:

podman push quay.io/dkirwan/asset-monitoring:dev

Running as a systemd service

Podman 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.

Requirements

  • 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)

Install (rootless, per user)

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.service

daemon-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"

Install (system-wide)

For a machine-wide service running as root:

sudo mkdir -p /var/lib/asset-monitoring/data
sudo podman pull quay.io/dkirwan/asset-monitoring:latest

Copy 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 :U so the container user can write SQLite files)

  • [Install] — set WantedBy=multi-user.target

Reload and start:

sudo systemctl daemon-reload
sudo systemctl start asset-monitoring.service

Interacting with the service

Rootless (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 -f

System-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.service

Updating the image

Pull a newer image and restart:

podman pull quay.io/dkirwan/asset-monitoring:latest
systemctl --user restart asset-monitoring.service

The 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.

SQLite data directory permissions

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.service

If 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.service

Check logs for SQLite errors:

journalctl --user -u asset-monitoring.service -n 50 --no-pager

API

| 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.

Configuration

Variable Purpose

PORT

Listen port (default 8080)

METRICS_SCRAPE_INTERVAL_SECONDS

Scrape interval (default 3600; 0 = initial scrape only)

METRICS_SCHEDULER_DISABLED

1 disables the background scraper

PRICE_HISTORY_DB_PATH

SQLite path for spot price history (omit for in-memory only)

PORTFOLIO_DB_PATH

SQLite path for holdings and portfolio history

PRICE_HISTORY_RETENTION_DAYS

History retention in days (default 7; rake podman:run uses 365)

RACK_ENV

production / development / test

Make/Rake-only variables (not read from .env):

  • USE_DEV_IMAGE — when true, 1, or yes, podman:run uses quay.io/dkirwan/asset-monitoring:dev instead of :latest

  • BUILD_IMAGE — image tag for podman:build (default: quay.io/dkirwan/asset-monitoring:dev)

  • IMAGE — image tag for podman:run when USE_DEV_IMAGE is unset (default: quay.io/dkirwan/asset-monitoring:latest)

Kubernetes

Example manifests in kubernetes/. When using SQLite persistence:

  • Mount a writable volume at the DB directory (readOnlyRootFilesystem needs this)

  • Use replicas: 1 for a single shared history file, or accept per-pod SQLite

See commented volume examples in kubernetes/deployment.yaml.

About

Example of using the Openshift monitoring, Prometheus, Alertmanager to monitor crypto prices

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors