VoucherVault
Overview
VoucherVault is an open source, self-hosted web application for keeping vouchers, gift cards and loyalty cards in one place. For each item it records the balance, expiry date, codes and barcodes or QR codes, and lets you attach the original document or image. A dashboard summarizes what you hold and what is about to expire, and a built-in scheduler can remind you before a card lapses.
This SecureAnyCloud image installs VoucherVault as a Django 5.2 application in a dedicated Python virtual environment, served by gunicorn behind an nginx reverse proxy with TLS. gunicorn is bound to loopback 127.0.0.1:8000 and never exposed directly. nginx is the only way in, terminating TLS on :443 (with :80 redirecting to https) and serving an unauthenticated /healthz endpoint for load balancer probes. The datastore is SQLite, so the appliance runs standalone with no external database.
VoucherVault has its own built-in authentication, and this image is secure by default. No shared or default credential ships. On the first boot of every VM, a fresh Django secret key is generated and the administrator account is created with a unique, randomly generated password written to a root-only file.
What you get:
- VoucherVault 1.30.1 installed in a dedicated Python virtual environment and running as the
vouchervaultgunicorn systemd service - The full VoucherVault web application behind an nginx TLS reverse proxy on
:443, with gunicorn bound to loopback only and:80redirecting to https - Built-in Django authentication with no default account, and a unique administrator password generated on first boot
- A per-VM Django secret key generated on first boot, never baked into the image
- Host settings configured so sign-in works on the public IP address or a custom domain, with no baked-in hostname
- A loopback Redis plus a Celery worker and beat scheduler powering the expiry reminder feature
- A small set of example voucher, gift card and loyalty card entries, so the dashboard, inventory and item views are populated from the start
- An unauthenticated
/healthzendpoint for Azure Load Balancer health probes vouchervault.service(gunicorn),vouchervault-celery.service,vouchervault-beat.service,redis-server.serviceandnginx.serviceas enabled, active systemd units- 24/7 SecureAnyCloud support
Prerequisites
You need an active Azure subscription, an SSH key pair, and a VNet with a subnet in the target region.
Standard_B2s (2 vCPU / 4 GiB RAM) is a comfortable starting size, because VoucherVault is light on resources.
Configure the NSG to allow inbound 22/tcp from your management network and 443/tcp for the TLS web application. Also allow 80/tcp, so the http-to-https redirect and the health probe work.
The image ships a self-signed certificate, so you can sign in immediately over https. For production, add your own domain and certificate (see Maintenance).
Step 1 - Deploy from the Azure Marketplace
Sign in to the Azure Portal, choose Create a resource, search the Marketplace for VoucherVault by SecureAnyCloud, and select Create.
On the Basics tab, pick your subscription, resource group, region and size. Under Administrator account, choose SSH public key and paste your key. Under Inbound port rules, allow SSH (22), HTTP (80) and HTTPS (443). Then select Review + create and Create.
Step 2 - Deploy from the Azure CLI
# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:vouchervault:default:latest
az vm create \
--resource-group <your-rg> \
--name vouchervault \
--image sac1647283583153:vouchervault:default:latest \
--size Standard_B2s \
--admin-username azureuser \
--generate-ssh-keys \
--public-ip-sku StandardOpen ports 443 and 80 to your network so that you can reach the web application:
az vm open-port --resource-group <your-rg> --name vouchervault --port 443 --priority 900
az vm open-port --resource-group <your-rg> --name vouchervault --port 80 --priority 901Step 3 - Connect to your VM
Connect to the VM over SSH:
ssh azureuser@<vm-public-ip>Step 4 - Confirm the services are running
Check that all five services are active:
systemctl is-active vouchervault.service vouchervault-celery.service vouchervault-beat.service redis-server.service nginx.serviceAll five report active. VoucherVault runs under gunicorn on the loopback address 127.0.0.1:8000. A loopback Redis backs the Celery worker and beat scheduler, and nginx fronts the application with TLS. gunicorn and Redis are never bound to a public interface, so nginx is the only way in.
Step 5 - Retrieve your admin password
VoucherVault uses its own Django login. The username is admin. A unique password is generated on the first boot of your VM and written to a root-only file:
sudo cat /root/vouchervault-credentials.txtThe file contains VOUCHERVAULT_USERNAME, VOUCHERVAULT_PASSWORD and the VOUCHERVAULT_URL to open in a browser. The file is mode 0600 root:root.
No default account ships in the image. The per-VM Django secret key is generated on first boot and lives in /opt/vouchervault/vouchervault.env (mode 0640 root:vouchervault). It is never baked into the image.
Store the password somewhere safe, and change it after your first sign-in (see Maintenance).
Step 6 - Confirm the health endpoint
nginx serves an unauthenticated health endpoint for load balancers and probes:
curl -s http://localhost/healthzIt returns ok. This endpoint never requires authentication, so it is safe to use as an Azure Load Balancer health probe.
Step 7 - Confirm authentication is required
VoucherVault manages its own login, so the application cannot be reached without signing in. An unauthenticated request to a protected page returns HTTP 302 and redirects to the sign-in page, while the health endpoint stays open. The -k flag tells curl to accept the image's self-signed certificate:
echo "health : $(curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1/healthz)"
echo "dashboard: $(curl -sk -o /dev/null -w '%{http_code}' https://127.0.0.1/en/dashboard)"It prints health : 200 and dashboard : 302. Every voucher, gift card and loyalty card view requires the per-VM admin password, and only the health endpoint is open. gunicorn is bound to loopback, and nginx is the only way in.
Step 8 - Confirm the installed version and components
VoucherVault runs on Django in a dedicated virtual environment. Confirm the framework version and that the core components are in place:
/opt/vouchervault/venv/bin/python -c "import django; print('Django', django.get_version())" cat /opt/vouchervault/app/package.json
sudo ls /opt/vouchervault/venv/bin/gunicorn /opt/vouchervault/app/database/db.sqlite3 /etc/systemd/system/vouchervault.serviceThe output reports Django 5.2 and the VoucherVault version, and lists the gunicorn binary, the SQLite database on the OS disk and the systemd unit. The image ships VoucherVault 1.30.1 with a small set of example cards, so the inventory is not empty on first boot.
Step 9 - Sign in
Browse to https://<vm-public-ip>/. The first time, your browser warns about the self-signed certificate. Accept the warning to continue. For production, add your own domain and certificate (see Maintenance).
VoucherVault shows its sign-in page. Enter admin and the password from Step 5.
After you sign in, you land on the dashboard. It summarizes your collection: the total value across your available items, a breakdown by type (gift cards, coupons, vouchers and loyalty cards), an item distribution chart and a status overview. All of it is populated from the example cards that ship with the image.
Step 10 - Browse your inventory
Choose Inventory from the sidebar to see every card as a tile with its issuer, name, value, expiry date and type.
Use the filters along the top to narrow the list by status (available, expiring soon, used, expired) or by type. Use the search box to find a card by name or issuer.
Step 11 - Open an item and scan to redeem
Select any card to open its detail view. It shows the issue and expiry dates, the value, a description, and a generated barcode or QR code under Scan to Redeem. The code stays blurred by default so it is not exposed on screen. Tap it to reveal the code.
From the detail view, you can edit, duplicate, share, mark the card as used, or delete it. You can also record part redemptions as transactions, so the remaining balance stays accurate.
Step 12 - Add your own cards and remove the examples
The image ships a few example cards so the dashboard is not empty. When you are ready, add your own from Create New Item in the sidebar.
Pick the type (voucher, gift card, coupon or loyalty card). Enter the name, issuer, value, currency, expiry date and the redeem code. Optionally, attach a document or image. VoucherVault generates the barcode or QR code for you.
To remove an example once you have your own cards, open it from the inventory and choose Delete.
Step 13 - Enable expiry reminders (optional)
The image ships a loopback Redis with a Celery worker and beat scheduler. A daily "Periodic Expiry Check" task is pre-created and enabled, so the reminder infrastructure is already running.
To receive reminders, add a notification channel. Sign in, open the user menu and choose Notifications. Enter one or more Apprise URLs (for example an SMTP, Telegram, Discord or ntfy target) and save. VoucherVault then notifies you before your cards expire. You can review or change when reminders fire, and the expiry threshold, from the same area.
Maintenance
- Password: The administrator password is generated on first boot and stored in
/root/vouchervault-credentials.txt(mode0600 root:root). Change it from the web interface after you sign in, or reset it from the command line:cd /opt/vouchervault/app && sudo runuser -u vouchervault -- env DJANGO_SETTINGS_MODULE=myproject.settings SECRET_KEY=$(grep '^SECRET_KEY=' /opt/vouchervault/vouchervault.env | cut -d= -f2-) DB_ENGINE=sqlite3 DOMAIN=localhost /opt/vouchervault/venv/bin/python manage.py changepassword admin. - Custom domain and TLS: The image ships a self-signed certificate. For production, point a DNS name at the VM and install your own certificate (for example with certbot). Then add your domain to
DOMAINin/opt/vouchervault/vouchervault.env(comma-separated with the existing values) so that it is accepted for sign-in, and runsudo systemctl restart vouchervault. nginx trustsX-Forwarded-Proto, so sign-in works over TLS on any host without further changes. - Reminders: The Celery worker and beat scheduler run as
vouchervault-celery.serviceandvouchervault-beat.serviceagainst the loopback Redis. Add an Apprise notification URL under Notifications in the app to receive reminders (see Step 13). - Loopback binding: gunicorn is bound to
127.0.0.1:8000and Redis to127.0.0.1:6379, so nginx is the only path in. Keep it that way, and do not change the bind addresses to a public interface. - Database: The SQLite database and uploaded documents live under
/opt/vouchervault/app/database/(ownedvouchervault:vouchervault). Back it up by copying the directory while the service is stopped. - Upgrades: VoucherVault is installed from a pinned release into its virtual environment. To upgrade, replace the source under
/opt/vouchervault/appand reinstall requirements with/opt/vouchervault/venv/bin/pip. Then runmanage.py migrateandmanage.py collectstatic, followed bysudo systemctl restart vouchervault. - Security patches: unattended-upgrades remains enabled, so the OS continues to receive security updates automatically.
Support
SecureAnyCloud provides 24/7 expert support for this image. Contact sales@secureanycloud.com.
Deploy on Azure
Launch VoucherVault on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.
View this image
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com