Skip to content
Β 
Β 

Latest commit

Β 

History

1,463 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

VoucherVault Plus+ logo

VoucherVault Plus+

Store and manage vouchers, coupons, loyalty and gift cards β€” digitally, privately, on your own server.

License: GPL-3.0 Security scanned with bandit Last commit Open issues Stars Forks

449 features and fixes added on top of upstream Installable PWA AI-assisted scanning REST API OIDC SSO Multi-user

Note

VoucherVault Plus+ is gregbtm's fork of l4rm4nd/VoucherVault β€” a mobile-optimized, installable PWA for storing vouchers, coupons, gift cards, and loyalty cards, with offline support, QR/barcode scanning, multi-user login with OIDC SSO, and Apprise expiry notifications out of the box (see Features for the complete original list).

This fork is a strict superset: 94 rounds of work adding 436 individual features and fixes on top of upstream's own image, from a full REST API and AI-assisted scanning to shared wallets, digital wallet passes, and a rules-based notification engine β€” without touching a line of upstream's own code. See What's New in This Fork for the complete list, or jump to a setup guide for a specific integration.

πŸ“‘ Table of Contents

⭐ Features

  • User-friendly, mobile-optimized web portal with PWA support
  • Manual offline mode with 48h caching supported
  • Light and dark theme support
  • Integration of vouchers, coupons, gift cards and loyalty cards
  • Transaction history tracking (gift cards only)
  • Item-specific file uploads (images and PDFs)
  • Item sharing between users
  • Display of redeem codes as QR codes or barcodes (many types supported), or as plain text for cards with no scannable barcode at all
  • Client-side redeem code scanning (1D/2D) during item creation with automatic type detection using camera or file upload
  • Expiry notifications via Apprise
  • Multi-user support
  • Multi-language support (English, German, French, Italian)
  • Single Sign-On (SSO) via OIDC
  • Database compatibility with SQLite3 and PostgreSQL
  • Multi-currency support via free fixer.io API

πŸš€ What's New in This Fork

Everything below is additive β€” nothing upstream was rewritten, so this fork stays a strict superset and can be rebased against upstream at any time. 9 categories, 65+ features β€” click a section to expand it; the full phase-by-phase technical changelog (root causes, code, tests, commit links) lives in FORK_CHANGES.md if you want the deep dive.

πŸ”Œ API, Integrations & AI Assistants
  • Full REST API β€” token-authenticated CRUD for items, wallets, tags, transactions, webhooks, wallet memberships, and wallet activity, every endpoint scoped to the authenticated user. Interactive Swagger/OpenAPI docs live at /api/v1/docs/ β€” browse and try every endpoint from your browser, no Postman required. Great for a Home Assistant sensor, a personal dashboard, or your own automation. Generate, regenerate, or revoke your own API token from Profile menu β†’ Developer β€” no shell access needed.
  • MCP server β€” a standalone, opt-in service exposing your vault to Claude Desktop, Claude Code, and other MCP clients: search items, check what's expiring, log a gift-card spend, create items, manage wallets and tags, view webhook config, and browse the wallet activity audit log β€” all through your existing API token. See the setup guide.
  • Zero-code n8n integration β€” the same OpenAPI schema that powers the Swagger docs plugs straight into n8n's HTTP Request Tool or AI Agent node, no custom node needed. See the setup guide. A recipe for syncing gift card/voucher balances to a self-hosted Firefly III budget is also included β€” see docs/FIREFLY_III_SETUP.md.
  • Webhook lifecycle events β€” item created, used, archived, balance changed, or shared, a wallet invite, a Next Up item due today, a merchant health alert, a recurring item renewing, or a wallet going over its monthly budget, for wiring VoucherVault into n8n, Home Assistant, or anything else that speaks webhooks. Manage your own webhooks per-user under Webhooks in the sidebar β€” no admin role required.
  • Rate limiting on every API write endpoint.
πŸ€– AI-Assisted "Scan with AI" & Smart Barcode Detection

Stop retyping redeem codes off a photo. Upload a picture of a physical voucher, coupon, or gift card β€” or a screenshot of an emailed gift card, a retailer app screen, or a digital wallet pass β€” and let it pre-fill the form for you. One upload does two things at once: a real client-side barcode/QR decode (ground truth) and an AI read of the text fields, with the decoded barcode always winning over the AI's guess when both are available.

  • Three backends, your choice: Claude or OpenAI (vision models β€” code, merchant, issuer, expiry, PIN, value, currency, card number) or Tesseract (100% free, fully local, code-only, no API key). See the setup guide.
  • Brand-aware logo extraction β€” a reseller's card gets the actual brand's logo, not the reseller's, and a printed balance-check URL is pulled straight off the card if there is one.
  • Live duplicate detection as you scan or type β€” a code match, a photo-hash match (catches "I scanned this exact card twice" even if OCR reads it slightly differently each time), and a fuzzy near-match warning for a code that's suspiciously close to one you already have. All friendly warnings, never a hard block.
  • Confidence warnings β€” the AI re-verifies its own code read character-by-character, and a low-confidence or easily-confused read (0/O, 1/I/l) shows a visible "double-check this" flag.
  • Every auto-filled field is visibly highlighted until you've reviewed it; editing an existing item's code never gets silently clobbered by a rescan.
  • Issuer autocomplete and a one-click Swap Name/Issuer button for when a scan gets the two backwards.
  • 16 barcode symbologies with smart auto-detection β€” the code type is auto-selected from what was actually decoded, never left as a guess you have to make yourself.
  • "No Barcode" code type for gift cards that are just a printed number with nothing to scan.
  • Processed synchronously, nothing persisted server-side beyond the item's own attached image.
πŸ—‚οΈ Organization β€” Wallets, Tags, Notes & Bulk Actions
  • Wallets β€” named folders ("Travel", "Groceries", "Kids' Cards") to group items however makes sense to you. Set a monthly budget amount on a wallet to track spend against it with a dashboard progress bar, and get notified/webhooked once if you go over it for the month.
  • Tags β€” free-form, colour-coded labels, many-to-many with items, with a clickable filter chip row (live counts!) above the Inventory grid.
  • Notes β€” a free-text field on every item for anything the built-in fields don't capture. Inventory search covers it too, along with name, issuer, redeem code, card number, tags, and any text OCR-extracted from an attached document (e.g. a scanned receipt).
  • Shared wallets β€” invite another user by username to collaborate, with a viewer or editor role: editors can create, edit, and delete items; viewers can only read. Both roles can see everything inside the wallet, no admin access required.
  • Item comments β€” dated, attributed notes any collaborator on a shared item (owner, editor, or viewer) can add and read, separate from the single-value Notes field so nobody's message gets overwritten by the next edit. The comment's author or the item's owner can delete it.
  • Archiving β€” retire an item without deleting it, and last-used tracking for a real "most recently used" sort.
  • Bulk actions β€” a checkbox select mode with a sticky action bar for archiving, tagging, moving to a wallet, or deleting several items at once.
  • Card number vs. barcode payload β€” a separate field for when a printed member number differs from what's actually encoded in the barcode.
  • Gift-card balance-check link β€” a bookmarked link per merchant, remembered and auto-suggested on future cards from the same issuer, with a one-tap "Check Balance" button.
  • "Next Up" widget β€” point it at one or more wallets (e.g. "Train Tickets") and Inventory highlights a queue of the soonest-expiring items across them (up to 3, configurable), barcode included, ready to scan, with a one-tap "mark as used" on each card. Off by default; opt in from Preferences. Pair it with a "Next Up Item Due Today" notification rule for a same-day reminder.
  • "Active Today" widget β€” built for a daily round-trip ticket (e.g. a train commute): before your configured cutoff time it shows today's outward leg, then automatically switches to the return leg after it, only ever on the day the ticket is actually valid for. Set a home station in Preferences and tag a ticket's Journey From/To fields (auto-filled by "Scan with AI" for a photographed train ticket) to use it. Off by default.
  • "Nearby" widget (opt-in) β€” a one-shot location check on Inventory load: if a shop near you (via OpenStreetMap, free and no API key) matches one of your item issuers, it surfaces in a "Nearby" card β€” walk into Tesco and see your Tesco gift card without searching for it. Never watches your location continuously and never stores your coordinates.
  • "Travel Pass" item type β€” a purpose-built layout for train/transport tickets: Journey From/To and an optional Time of Travel, with Value, Currency, Card Number, and PIN all hidden since they don't apply. Issue Date falls back to the expiry date when left blank (many tickets are valid and expire same-day), and every item of this type is filed straight into a "Travel Pass" wallet automatically.
  • PDF eTicket import (UK rail) β€” "Scan with AI" also accepts a PDF eTicket, not just photos: the Aztec barcode UK rail tickets use is decoded server-side and the journey/price fields pre-filled, ready to review and save. The same endpoint powers a fully unattended n8n workflow that watches an inbox for booking confirmation emails and creates the Travel Pass item automatically β€” re-submitting the same PDF is idempotent (HTTP 409 with the existing item, so the n8n workflow correctly labels the email as "processed" rather than "failed"). See docs/RAIL_TICKET_IMPORT_SETUP.md.
  • Auto-assign new items to a wallet by issuer β€” set a wallet's "auto-assign" match text (e.g. "National Rail") and any new item whose issuer contains it β€” scanned or typed β€” is filed straight into that wallet unless you pick one yourself.
  • Auto-suggest from recent activity β€” after "Scan with AI" fills in what it could read from a photo, any of Issuer, Logo, Wallet, or Currency it left blank get suggested from your habits: the issuer you use most across your last 10 items of that type, with the companion fields taken from your newest matching item. Suggestions wear their own dashed-amber styling so they're never mistaken for values read off the photo. Manual entry (no photo scan) is never auto-suggested.
  • Self-learning scans β€” correct a scan's mistake once (a misread operator name, an Aztec code labelled as QR, a blank field you always fill the same way) and it's remembered per-user and silently fixed on every future scan, flagged with a "learned from your past corrections" chip. Corrections are scoped to the merchant they were learned from, so a fix for one issuer's cards never bleeds into another's. A different typo of an already-learned misreading heals too (fuzzy matching), and each healed field gets a one-click Undo to revert it and un-teach the correction if it was wrong. Keep a scanned value as-is and any stale correction for it is retired automatically. If several different users independently teach the identical correction for the same merchant, it's promoted into a shared fix that helps everyone, not just the users who taught it.
  • Per-type fields β€” the create/edit form shows only the fields relevant to the selected item type, with animated collapse/expand. Gift cards get a Face Value field (original purchase value vs. current balance); loyalty cards get Points Balance and Membership Tier; vouchers and coupons get Minimum Spend; travel passes get Seat / Coach. All per-type fields are surfaced on the item detail page too.
  • Share Message β€” an optional text note on any item ("Use before 31 July", "One-time use only") that appears as a highlighted block on the public share page, so you can give context to whoever you share the link with.
πŸ”” Notifications & Automation

The original Apprise-only expiry check still works exactly as before β€” this adds a second, more flexible layer covering the item's whole lifecycle.

  • Rules-based engine with four extra delivery backends beyond Apprise: ntfy, a generic webhook, native browser/OS Web Push (opt-in, requires VAPID keys β€” generate a pair with one command, no third-party relay needed), and a native Firefly III backend.
  • Per-item thresholds β€” one item can warn 60 days out, another only 7, plus a final reminder as the deadline gets close.
  • Rules can also fire on item created (including n8n-imported rail tickets), used, archived, balance changed, or shared, a wallet invite/removal, a Next Up item due today, an unused-gift-card reminder, a merchant health alert, a recurring item renewing, or a wallet going over its monthly budget β€” not just expiry.
  • Firefly III native backend β€” link any item to a Firefly III asset account with a one-click "Auto-link" button, then set a notification rule with the balance_changed event type. Every balance update posts a withdrawal or deposit transaction to Firefly III automatically, keeping your gift card and voucher balances in sync with your personal finance ledger. Sync status (synced / pending) is displayed per-transaction on the item detail page with a pulsing indicator for unsynced rows. A "Test Connection" button in the rule form validates your URL + token without leaving the page. Value edits and archiving also trigger the right Firefly actions automatically. See docs/FIREFLY_III_SETUP.md.
  • Web Push status card β€” a persistent "Browser Notifications β€” This Device" card at the top of the rules page shows whether push is active on the current browser, with Enable/Disable buttons. No more hunting for a subscribe button buried inside a form.
  • Web Push deep-links β€” tapping a push notification now opens the specific item, not the app homepage.
  • Daily digest mode β€” batch a rule's notifications into a single once-a-day summary instead of one push per event, for a rule covering a busy wallet.
  • A complete delivery log so you can see exactly what fired, when, and whether it succeeded.
  • Managed entirely from the web UI, no config file editing.
🍏🟒 Digital Wallet Passes
  • Apple Wallet β€” download a signed .pkpass for any item, or go the other way and pre-fill a new item by uploading an existing pass. Export needs your own Apple Developer certificate (see the setup guide); import needs no setup at all.
  • Google Wallet β€” a one-tap "Add to Google Wallet" link, set up once by whoever runs the container (see the setup guide). Passes update live β€” editing the item's balance or details pushes the change straight to an already-issued pass, not just a snapshot frozen at export time.
  • The item detail page shows only the button your current device can actually use β€” Apple on Safari/iOS, Google on Android/Chromium β€” never a dead link.
πŸ“€ Sharing, Public Links & Merchant Branding
  • Share content into VoucherVault β€” VoucherVault registers as a target in your device's native share sheet (PWA Web Share Target API). Share a retailer page, a confirmation email, or any URL from your browser or another app and it opens the "Add Item" form with the title and URL pre-filled, ready to review and save. Works on Android and desktop Chromium whenever the PWA is installed.
  • Native OS/browser sharing β€” a "Share via…" button hands an item off to your device's real share sheet (Messages, Mail, AirDrop, etc.), with a clipboard-copy fallback on desktop, and a choice between a bare link or one that also includes the code/PIN/balance.
  • A no-login-required public link β€” works for someone with zero VoucherVault account, with view tracking and regenerate/revoke controls. Links auto-expire (configurable), rate-limit repeat requests, and can optionally require an access PIN.
  • Real merchant brand logos in link previews on WhatsApp/iMessage/Slack β€” not a generic icon β€” without ever exposing the code/PIN/balance to that app's preview crawler.
  • The public link page offers an "Add to Wallet" button for whichever of Apple/Google Wallet is both configured and usable on the recipient's device.
πŸ“Š Analytics, Import & Backup
  • Analytics dashboard β€” KPI tiles, an expiry calendar heatmap, and a live "value at risk" figure so nothing quietly expires unnoticed.
  • Import from a Catima CSV export, an existing Apple Wallet .pkpass, or this app's own CSV/JSON β€” background-processed with per-row error reporting, so one bad row doesn't sink the rest.
  • Export to CSV/JSON any time, or a Full Backup (with files) β€” a .zip bundling every item, its attached files, transaction history, and account settings, for a restore that doesn't lose anything the text-only formats can't carry.
  • A nightly scheduled backup (opt-out) runs the same Full Backup format automatically with rotation. See docs/BACKUP_RESTORE.md.
  • A subscribe-able .ics calendar feed of your active items' expiry dates for Google Calendar, Apple Calendar, etc. β€” each event carries the wallet as its location, tags as categories, a link back to the item, and a built-in reminder alarm matching your notification threshold. Never includes the redeem code, PIN, or card number, since a subscribed feed typically syncs to your calendar provider's own cloud.
🎨 Design & Everyday Polish
  • True-black OLED dark theme β€” an extra toggle on top of the regular light/dark theme, for phones with an OLED/AMOLED screen.
  • Barcode zoom β€” pinch or on-screen +/βˆ’ controls for codes that scan poorly at the default size.
  • Screen wake lock β€” the screen stays on while a barcode is shown to a cashier.
  • A configurable code-blur toggle for privacy in public β€” hides just the barcode/QR image behind a tap-to-reveal, never the code text itself, which stays legible so it can always be tapped to copy.
  • Tap the redeem code or card number anywhere to copy it β€” no separate copy button to hunt for; a long code clips to a few lines with a "Show full code" toggle instead of stretching the page.
  • View original uploads and attached documents inline β€” a "View" button opens an image or PDF in a fullscreen overlay, no download required just to check what you scanned.
  • Tilt-to-scan detection (opt-in) β€” tilt your phone forward to present a barcode to a reader (train barriers, a till scanner) and a dismissible "Mark Used?" prompt appears on its own; it only ever suggests, never marks an item used without an explicit tap.
  • Floating toast messages instead of a page-top banner.
  • Smooth, modern animations everywhere β€” staggered fade-up entrances on cards, form sections, and widgets (powered by the self-hosted Motion library, hardware-accelerated so it stays fluid on low-end phones), pop-in toasts and chips, and tactile press feedback on buttons. Fully respects your OS's reduced-motion setting.
  • A modern color picker for wallet, tag, and item-tile colours β€” a curated swatch grid plus a hex field, replacing the jarring native browser/OS colour picker <input type="color"> otherwise falls back to.
βš™οΈ Admin, Deployment & Reliability
  • In-app Site Settings page β€” every app-level setting (OCR backend and API keys, Apple/Google Wallet config, notification defaults, backup schedule, and more) is editable from a superuser-only page in the app itself, not just Portainer environment variables. Changes apply immediately, no redeploy needed. Secret fields never round-trip back into the page β€” they show a "currently set" hint instead of the actual value.
  • Update-available banner + one-click redeploy β€” a periodic, opt-out check against this repo's GitHub Releases surfaces a "new version available" banner to admins. If you're running this as a git-based Portainer stack, an optional webhook adds a "Redeploy now" button, plus a companion GitHub Action that can trigger the same webhook automatically on every push to main. See docs/AUTO_DEPLOY.md.
  • Upstream sync tracking β€” see how far behind upstream's latest release this install is, right from Site Settings.
  • Production error logging, so an unhandled exception doesn't just vanish silently.
  • GBP as the default currency for new items and preferences.
  • TOTP two-factor authentication β€” each user can enrol a TOTP authenticator app (Google Authenticator, Authy, etc.) from their Profile β†’ Security page. On enrolment, eight single-use backup/recovery codes are shown once for safe offline storage. Session Management lists every active login, device type, and browser, with a one-tap "Sign out everywhere" β€” useful when you've lost a device. 2FA can be disabled by the user themselves, or by an admin via the Django admin panel.
  • Login brute-force lockout β€” locks an account out after repeated failed login attempts (django-axes), configurable via AXES_FAILURE_LIMIT/AXES_COOLOFF_TIME_HOURS. Locks by username rather than IP, so one attacker on a shared/CGNAT network can't lock out everyone behind the same address.

πŸ“š Setup Guides

A handful of features need a one-time setup by whoever runs the container β€” not something each person using your instance has to do themselves:

πŸ“· Screenshots

Analytics dashboard β€” KPI tiles, at-risk value, item distribution, expiry calendar heatmap
Inventory β€” status/type filters, the clickable tag filter, wallet badges
Bulk actions β€” checkbox select mode with the sticky action bar
Item Details β€” tags/notes/wallet, document attachments, transaction ledger
True-black OLED dark theme
Notification Rules β€” ntfy/webhook/Apprise/Web Push, per-item event types
Import / Export β€” CSV/JSON, Full Backup, and the .ics calendar feed
Wallets β€” grouping items, sharing a wallet with another user
Sharing Center β€” items shared with you and by you

🐳 Usage

For installation and Docker Compose setup, see the upstream wiki (still accurate β€” this fork doesn't change how the container itself is deployed): READ THE WIKI - UNRAID SUPPORTED

For this fork's own feature guides, see this fork's wiki.

# create volume dir for persistence
mkdir -p ./volume-data/database

# adjust volume ownership to www-data
sudo chown -R 33:33 volume-data/*

# spawn the container stack
docker compose -f docker/docker-compose-sqlite.yml up -d

Once the container is up and running, you can access the web portal at http://127.0.0.1:8000.

The default username is admin. The default password is auto-generated. You can obtain the auto-generated password via the Docker container logs:

docker compose -f docker/docker-compose-sqlite.yml logs -f

Warning

The container runs as low-privileged www-data user with UID/GID 33. So you have to adjust the permissions for the persistent database bind mount volume. A command like sudo chown -R 33:33 <path-to-volume-data-dir> should work. Afterwards, please restart the container.

Tip

This fork doesn't publish its own Docker Hub image β€” deploy it as a git-based Portainer stack that builds docker/Dockerfile straight from this repo (see docs/UPGRADE.md if you're moving over from upstream's published image). The in-app update banner and one-click redeploy button track new commits on main for you, so there's no image tag to pin or track manually.

🌍 Environment Variables

The docker container takes various environment variables. Most of the app-level ones below (everything except domain/database/session/SSO settings) can also be configured from the in-app Site Settings page (/admin-tools/site-settings/, superuser-only, linked from the sidebar) instead β€” changes there take effect immediately, no redeploy required, and are stored in the database rather than the container's environment. The env vars below are what a fresh install starts from; once you've edited a setting in Site Settings, that's the value that's actually used.

Show all environment variables (55 total β€” domain/database/session/SSO plus every app-level default)
Variable Description Default Optional/Mandatory
DOMAIN Your Fully Qualified Domain Name (FQDN) or IP address. Used to define ALLOWED_HOSTS and CSRF_TRUSTED_ORIGINS for the Django framework. May define multiple ones by using a comma as delimiter. localhost Mandatory
SECURE_COOKIES Set to True if you use a reverse proxy with TLS. Enables the secure cookie flag and HSTS HTTP response header. False Optional
SESSION_EXPIRE_AT_BROWSER_CLOSE Set to False if you want to keep sessions valid after browser close. True Optional
SESSION_COOKIE_AGE Define the maximum cookie age in minutes. 30 Optional
EXPIRY_THRESHOLD_DAYS Defines the days prior item expiry when an Apprise expiry notification should be sent out. 30 Optional
EXPIRY_LAST_NOTIFICATION_DAYS Defines the days prior item expiry when another final Apprise expiry notification should be sent out. 7 Optional
TZ Defines the TIME_ZONE variable in Django's settings.py. Europe/Berlin Optional
SECRET_KEY Defines a fixed secret key for the Django framework. If missing, a secure secret is auto-generated on the server-side each time the container starts. <auto-generated> Optional
PORT Defines a custom port. Used to set CSRF_TRUSTED_ORIGINS in conjunction with the DOMAIN environment variable for the Django framework. Only necessary, if VoucherVault is operated on a different port than 8000, 80 or 443. 8000 Optional
REDIS_URL Defines the Redis URL to use for Django-Celery-Beat task processing. redis://redis:6379/0 Optional
CSP_FRAME_ANCESTORS Comma-separated list of allowed sources for the CSP frame-ancestors directive. 'none' Optional
OIDC_ENABLED Set to True to enable OIDC authentication. False Optional
OIDC_AUTOLOGIN Set to True if you want to automatically trigger OIDC flow on login page False Optional
OIDC_CREATE_USER Set to True to allow the creation of new users through OIDC. True Optional
OIDC_RP_SIGN_ALGO The signing algorithm used by the OIDC provider (e.g., RS256, HS256). HS256 Optional
OIDC_OP_JWKS_ENDPOINT URL of the JWKS endpoint for the OIDC provider. Mandatory if RS256 signing algo is used. None Optional
OIDC_RP_CLIENT_ID Client ID for your OIDC RP. None Optional
OIDC_RP_CLIENT_SECRET Client secret for your OIDC RP. None Optional
OIDC_OP_AUTHORIZATION_ENDPOINT Authorization endpoint URL of the OIDC provider. None Optional
OIDC_OP_TOKEN_ENDPOINT Token endpoint URL of the OIDC provider. None Optional
OIDC_OP_USER_ENDPOINT User info endpoint URL of the OIDC provider. None Optional
DB_ENGINE Database engine to use (e.g., postgres for PostgreSQL or sqlite3 for SQLite3). sqlite3 Optional
POSTGRES_HOST Hostname for the PostgreSQL database. db Optional
POSTGRES_PORT Port number for the PostgreSQL database. 5432 Optional
POSTGRES_USER PostgreSQL database user. vouchervault Optional
POSTGRES_PASSWORD PostgreSQL database password. vouchervault Optional
POSTGRES_DB PostgreSQL database name. vouchervault Optional
CELERY_WORKER_CONCURRENCY Celery worker concurrency. 1 Optional
CELERY_WORKER_PREFETCH_MULTIPLIER Celery worker prefetch multiplier. 1 Optional
DEBUG Enable HTTP debug logging. False Optional
NTFY_DEFAULT_SERVER Default ntfy server pre-filled when a user creates a new ntfy notification rule. https://ntfy.sh Optional
MERCHANT_LOGOS_ENABLED Set to False to disable auto-fetching merchant logos on item cards. True Optional
OCR_BACKEND Set to claude, openai, or tesseract to enable the "Scan with AI" button on the item form. none Optional
ANTHROPIC_API_KEY Required if OCR_BACKEND=claude. Get one at console.anthropic.com. None Optional
ANTHROPIC_OCR_MODEL Overrides the Claude model used for OCR extraction. claude-sonnet-5 Optional
OPENAI_API_KEY Required if OCR_BACKEND=openai. Get one at platform.openai.com. None Optional
OPENAI_OCR_MODEL Overrides the OpenAI model used for OCR extraction. gpt-4o-mini is the cost-efficient default; a full-tier vision model reads small print (expiry dates, long codes) noticeably more reliably if accuracy matters more than cost. gpt-4o-mini Optional
SCHEDULED_BACKUP_ENABLED Set to False to disable the nightly local backup task. See docs/BACKUP_RESTORE.md. True Optional
BACKUP_RETENTION_COUNT How many backups to keep per user before rotating out the oldest. 7 Optional
PKPASS_CERT_PATH Path to your Apple Pass Type ID certificate (.p12). Enables Apple Wallet export when set. None Optional
PKPASS_CERT_PASSWORD Password for PKPASS_CERT_PATH, if any. None Optional
PKPASS_WWDR_CERT_PATH Path to Apple's WWDR intermediate certificate. Required if PKPASS_CERT_PATH is set. None Optional
PKPASS_TEAM_ID Your Apple Developer Team ID. Required if PKPASS_CERT_PATH is set. None Optional
PKPASS_PASS_TYPE_ID Your registered Pass Type ID, e.g. pass.com.example.vouchervault. Required if PKPASS_CERT_PATH is set. None Optional
PKPASS_ORGANIZATION_NAME Organization name shown on the generated pass. VoucherVault Plus+ Optional
GOOGLE_WALLET_SERVICE_ACCOUNT_KEY_PATH Path to your Google Wallet API service account JSON key. Enables Google Wallet export when set along with the issuer ID below. None Optional
GOOGLE_WALLET_ISSUER_ID Your Google Wallet API issuer ID, from the Google Wallet Business Console. Required if GOOGLE_WALLET_SERVICE_ACCOUNT_KEY_PATH is set. None Optional
GOOGLE_WALLET_CLASS_ID Optional override for the generic pass class ID. <issuer id>.vouchervault_generic Optional
WEBPUSH_VAPID_PUBLIC_KEY VAPID public key. Enables the "Web Push" notification backend when set along with the private key below. Generate a pair with python manage.py generate_vapid_keys. None Optional
WEBPUSH_VAPID_PRIVATE_KEY VAPID private key. See above. None Optional
WEBPUSH_VAPID_CLAIMS_EMAIL Contact email sent to push services as the VAPID claim. mailto:admin@example.com Optional
UPDATE_CHECK_ENABLED Set to False to disable the periodic GitHub Releases check (footer version + update banner for superusers). True Optional
UPDATE_CHECK_REPO owner/repo to check for releases. Only change this if you're running a fork of this fork. gregbtm/VoucherVault Optional
VERSION Overrides the version shown in the footer. Normally unset - the VERSION file baked into the image is the source of truth. <VERSION file> Optional
PORTAINER_WEBHOOK_URL Your Portainer stack's redeploy webhook URL. Adds a "Redeploy now" button to the update banner for superusers. For a prebuilt-image stack, auto-redeploy on push to main instead uses the PORTAINER_URL/PORTAINER_API_KEY/PORTAINER_STACK_IDS/PORTAINER_ENDPOINT_IDS GitHub repo secrets, not this env var. See docs/AUTO_DEPLOY.md. None Optional

You can find detailed instructions on how to setup OIDC SSO in the wiki.

For the GOOGLE_WALLET_* variables, see the full walkthrough in docs/GOOGLE_WALLET_SETUP.md β€” it's a one-time setup you do as the operator, not something each user of your instance needs to do themselves.

πŸ”” Notifications

Notifications are handled by Apprise. May read the wiki.

You can define custom Apprise URLs in the user profile settings. The input form takes a single or a comma-separated list of multiple Apprise URLs.

The interval, how often items are checked against a potential expiry, is pre-defined (daily at 9AM) in the Django admin area. Here, we are utilizing Django-Celery-Beat + a Redis instance for periodic task execution.

An item will trigger an expiry notification if the expiry date is within the number of days defined by the environment variable EXPIRY_THRESHOLD_DAYS. By default, this threshold is set to 30 days. Additionally, a final reminder is sent out another time if the item expires within the next 7 days.

For per-item thresholds and three more delivery backends (ntfy, webhooks, Web Push), see Notification Rules in the app β€” the section above covers the original, simpler Apprise-only check.

πŸ” Multi-User Setup

VoucherVault is initialized with a default superuser account named admin and a secure auto-generated password.

This administrative account has full privileges to the Django admin panel, located at /admin.

Therefore, all database model entries can be read and modified by this user. Additionally, new user accounts and groups can be freely created too.

Finally, Single-Sign-On (SSO) via OIDC is supported. Check out the environment variables above as well as the wiki.

πŸ’Ύ Backups

All application data is stored within a Docker bind mount volume.

This volume is defined in the example Docker Compose files given. The default location is defined as ./volume-data/database.

Therefore, by backing up this bind mount volume, all your application data is saved.

Warning

Read the official SQLite3 documentation or PostgreSQL documentation regarding backups.

On top of a volume-level backup, this fork also runs a nightly, per-user application-level backup (a Full Backup zip β€” every item, its files, transaction history, and settings) with automatic rotation, independent of whichever database engine you run. See docs/BACKUP_RESTORE.md for where those live, how to restore one, how to disable the schedule (SCHEDULED_BACKUP_ENABLED=False), and β€” importantly β€” how to copy them off the box for real disaster recovery, since both the live database and its backups otherwise sit on the same volume.

πŸ’› About This Fork & Support

VoucherVault Plus+ is built on top of l4rm4nd/VoucherVault, which provides the original core app (see the note at the top of this page for what that covers). Everything on top (FORK_CHANGES.md) is additive and opt-in β€” upstream's own code is never modified, so this fork can be rebased against upstream at any time.

Feature requests and bug reports are welcome β€” open an issue.

If this fork has been useful to you, tips are always appreciated:

Donate via PayPal

πŸ€– Repo Statistics

Alt

About

Django web application to store and manage vouchers, coupons, loyalty and gift cards digitally. Supports PWA, offline caching, expiry notifications, transaction histories, file uploads and OIDC SSO.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages