Skip to content

JavaDogWebDesign/HealthReceipts

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

42 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

HSA/FSA/DCFSA Expense Tracker

Self-hosted expense tracking for Health Savings Accounts (HSA), Flexible Spending Accounts (FSA), and Dependent Care FSA (DCFSA)

License: AGPL-3.0 Docker Python 3.8+


β˜• Enjoying this project? Buy me a coffee to support development!

πŸš€ Deploy anywhere: Self-host on Fly.io, Railway, Render, or your own server!


Why This Exists

While Google Sheets with linked Drive files works for tracking healthcare expenses, it has significant limitations:

  • ❌ Requires internet connection to access your sensitive financial data
  • ❌ Files scattered across cloud storage
  • ❌ Limited offline functionality
  • ❌ Privacy concerns with health information in the cloud

This tracker solves those problems:

  • βœ… 100% self-hosted - Your data stays on your server
  • βœ… Offline-first - Works without internet, your data is locally secured
  • βœ… Organized exports - CSV reports + all receipts in original file formats (PDF, JPG, PNG)
  • βœ… Reimport capability - Full backup/restore with database + receipts as organized ZIP
  • βœ… Privacy-focused - No third-party services, complete control over your health data

Features

πŸ₯ Multi-Account Expense Tracking

  • HSA (Health Savings Account) - Unlimited, all-time tracking with balance management
  • FSA (Flexible Spending Account) - Plan-year limited with election tracking
  • DCFSA (Dependent Care FSA) - Dependent care expenses with separate plan years

πŸ“Š Complete Expense Lifecycle

  • Full workflow: Open β†’ Pending β†’ Partially Reimbursed β†’ Reimbursed
  • Additional statuses: Rejected, Disputed, Closed
  • Partial reimbursements - Track multiple partial payments for a single expense
  • Claim tracking - Insurance claim numbers and reimbursement documentation

πŸ“Ž Receipt & Document Management

  • Multiple attachments - Unlimited receipts per expense
  • Dual attachment types:
    • Original receipts (proof of expense)
    • Proof-of-reimbursement documents (insurance documentation)
  • Supported formats: PDF, JPG, JPEG, PNG (up to 16MB per file)
  • Organized storage: Files automatically organized by user and year
  • Secure access - Verified file serving ensures users only access their own documents

πŸ“… Flexible Benefit Plan System

  • Custom date ranges - Not limited to calendar years (e.g., April 1 - March 31)
  • Election limits - Set annual election amounts for FSA/DCFSA
  • Automatic linking - Expenses automatically associated with the correct benefit plan
  • Spending tracking - Real-time tracking against election limits
  • Overlap prevention - System prevents conflicting benefit plan configurations

πŸ‘¨β€πŸ‘©β€πŸ‘§β€πŸ‘¦ Family Member Tracking

  • Track expenses by family member
  • Filter and report per household member
  • Useful for dependent care and family healthcare expenses

πŸͺ Provider Management

  • Maintain reusable list of healthcare providers and merchants
  • Quick dropdown selection when adding expenses
  • Prevents typos and ensures consistency

πŸ“ˆ Dashboard Analytics

  • Account summaries - Total paid vs. reimbursed by category
  • Benefit plan progress - Spending against election limits
  • Pending reimbursements - Track outstanding claims
  • Visual breakdowns - Category-based analytics
  • Timezone-aware - Respects your local timezone for accurate date calculations

πŸ”’ Privacy & Security

  • AGPL-3.0 licensed - Free and open source
  • Self-hosted only - No SaaS, no subscription, no data sharing
  • User isolation - Multi-user support with complete data separation
  • Authentication options:
    • Local username/password authentication with secure hashing
    • OIDC/SSO support - Sign in with Google, Microsoft, Okta, Auth0, Keycloak, GitLab, or any OpenID Connect provider
    • Auto-provisioning for OIDC users
    • PKCE and state validation for secure OAuth flows
  • CSRF protection - All forms protected against cross-site request forgery
  • Rate limiting - Prevents brute-force attacks
  • Optional encryption - SQLCipher database encryption + Fernet file encryption

πŸ“€ Export & Backup

  • CSV Export - Download filtered expense data for spreadsheet analysis
    • Customizable columns (dates, amounts, providers, categories, status, etc.)
    • Filter by year, category, status before exporting
  • Full Database Backup - Complete ZIP export containing:
    • SQLite database with all expense records
    • All receipts organized by year in original file formats
    • Reimport ready - Restore complete system from ZIP backup
  • Organized file structure - Exports maintain clean folder hierarchy for easy navigation

🎨 Modern User Experience

  • Responsive design - Works on desktop, tablet, and mobile
  • Advanced filtering - Filter by year, category, status, provider
  • Bi-directional sorting - Sort by date, amount, provider, status, claim number
  • Accessibility features - ARIA labels, keyboard navigation
  • Multi-currency support - 10 currencies: USD, EUR, GBP, CAD, AUD, JPY, CNY, INR, CHF, MXN
  • Onboarding wizard - Guided setup for new users

Tech Stack

Backend:

  • Flask 3.0 (Python web framework)
  • SQLite with WAL mode (database)
  • Werkzeug (password hashing)
  • Flask-WTF (CSRF protection)
  • Flask-Limiter (rate limiting)
  • Gunicorn (production WSGI server)

Frontend:

  • Vanilla JavaScript (no framework dependencies)
  • HTML5/CSS3
  • Component-based architecture

Storage:

  • Local filesystem organized by user and year
  • SQLite database (simple, reliable, portable)

Quick Start

Option 1: Docker Installation (Recommended) πŸ‹

Docker provides the easiest and most consistent deployment experience across all platforms.

πŸ“– Full Docker Documentation: For complete setup instructions, encryption, production deployment, and troubleshooting, see DOCKER.md

Prerequisites:

  • Docker Engine 20.10+ and Docker Compose 2.0+ (Get Docker)

Quick Start (2 Minutes) - No Git Required!

  1. Download configuration files

    mkdir hsa-tracker && cd hsa-tracker
    curl -O https://raw.githubusercontent.com/JavaDogWebDesign/HealthReceipts/main/docker-compose.yml
    curl -O https://raw.githubusercontent.com/JavaDogWebDesign/HealthReceipts/main/.env.example
  2. Configure environment

    # Copy environment template
    cp .env.example .env
    
    # Generate a secure SECRET_KEY
    docker run --rm python:3.11-slim python -c 'import secrets; print(secrets.token_hex(32))'
    
    # Edit .env and paste the generated key
    nano .env  # or use your preferred editor
  3. Start the application

    docker-compose up -d
  4. Access the tracker Open http://localhost:4123 and create your account! πŸŽ‰


🎯 Quick Deploy with Portainer/Komodo

For Portainer, Komodo, or other Docker management tools:

  1. Copy this docker-compose template:
services:
  hsa-tracker:
    image: ghcr.io/javadogwebdesign/healthreceipts:latest
    container_name: hsa-tracker
    restart: unless-stopped
    ports:
      - "0.0.0.0:${PORT:-4123}:4123"
    environment:
      - SECRET_KEY=${SECRET_KEY}
      - FLASK_ENV=${FLASK_ENV:-production}
      - PORT=${PORT:-4123}
      - HOST=0.0.0.0
    volumes:
      - ${DATA_PATH:-./data}:/app/data
    healthcheck:
      test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:4123/login').read()"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s
    cap_drop:
      - ALL
    cap_add:
      - NET_BIND_SERVICE
    security_opt:
      - no-new-privileges:true
  1. Set environment variables in Portainer/Komodo stack settings:

    Generate a SECRET_KEY:

    docker run --rm python:3.11-slim python -c 'import secrets; print(secrets.token_hex(32))'

    Add these environment variables in your stack:

    SECRET_KEY=paste-your-generated-key-here
    FLASK_ENV=production
    PORT=4123
    DATA_PATH=./data
    

    Or create a .env file in the stack directory:

    SECRET_KEY=paste-your-generated-key-here
    FLASK_ENV=production
    PORT=4123
    DATA_PATH=./data
  2. Deploy the stack and access at http://your-server-ip:4123

Optional customization:

  • Change port: Update PORT environment variable (e.g., PORT=8080)
  • Custom data location: Change DATA_PATH (e.g., DATA_PATH=/mnt/storage/hsa-data)

Essential Docker Commands:

# View logs
docker-compose logs -f

# Stop
docker-compose down

# Restart
docker-compose restart

# Update to latest version
docker-compose pull && docker-compose up -d

πŸ“¦ Docker Compose Files:

πŸ’Ύ Data Persistence: Your data is stored in ./data/:

  • data/hsa_tracker.db - SQLite database
  • data/receipts/ - Receipt files (organized by user/year)

⚠️ Always backup ./data/ before updates!

Development/Build from Source: If you want to build from source or customize the application:

git clone https://github.com/JavaDogWebDesign/HealthReceipts.git
cd HealthReceipts
cp .env.example .env
# Edit .env with your SECRET_KEY
docker-compose -f docker-compose.build.yml up -d

Advanced Setup: For production deployment with Nginx, SSL/TLS, encryption, network access, and more, see DOCKER.md.


Option 2: Local Linux Server Installation

Install directly on Ubuntu, Debian, CentOS, or any Linux distribution.

Prerequisites:

  • Python 3.8 or higher (python3 --version)
  • pip package manager
  • Git

Steps:

  1. Clone the repository

    git clone https://github.com/yourusername/hsa-tracker-v2.git
    cd hsa-tracker-v2
  2. Run the automated setup script (Linux/Mac)

    chmod +x run.sh
    ./run.sh

    This script will:

    • Create a Python virtual environment
    • Install all dependencies from requirements.txt
    • Initialize the SQLite database
    • Start the development server on http://localhost:4123
  3. Access the tracker

    Open http://localhost:4123 and create your account!

Manual Installation (if you prefer more control):

  1. Create virtual environment

    python3 -m venv venv
    source venv/bin/activate
  2. Install dependencies

    pip install -r requirements.txt
  3. Configure environment

    cp .env.example .env

    Generate and set a secure SECRET_KEY:

    python -c 'import secrets; print(secrets.token_hex(32))'

    Edit .env:

    FLASK_ENV=development
    SECRET_KEY=your-generated-key
    PORT=4123
  4. Initialize the database

    cd app
    python database.py
    cd ..
  5. Run the application

    Development mode:

    cd app
    python app.py

    Production mode (recommended for server deployment):

    # Update .env to set FLASK_ENV=production
    pip install gunicorn
    cd app
    gunicorn -w 4 -b 0.0.0.0:4123 app:app
  6. Access the tracker

    Navigate to http://localhost:4123 or http://your-server-ip:4123

Running as a service (systemd):

Create /etc/systemd/system/hsa-tracker.service:

[Unit]
Description=HSA/FSA Expense Tracker
After=network.target

[Service]
Type=simple
User=your-username
WorkingDirectory=/path/to/hsa-tracker-v2/app
Environment="PATH=/path/to/hsa-tracker-v2/venv/bin"
ExecStart=/path/to/hsa-tracker-v2/venv/bin/gunicorn -w 4 -b 127.0.0.1:4123 app:app
Restart=always

[Install]
WantedBy=multi-user.target

Enable and start:

sudo systemctl daemon-reload
sudo systemctl enable hsa-tracker
sudo systemctl start hsa-tracker
sudo systemctl status hsa-tracker

Production Deployment

Self-Hosting Platforms

This application can be deployed on various hosting platforms:

Fly.io

# Install flyctl
curl -L https://fly.io/install.sh | sh

# Launch app (follow prompts)
fly launch

# Deploy
fly deploy

# Set secrets
fly secrets set SECRET_KEY=$(python -c 'import secrets; print(secrets.token_hex(32))')

Railway

  1. Connect your GitHub repository
  2. Railway auto-detects the Python app
  3. Set environment variables in the dashboard:
    • SECRET_KEY
    • FLASK_ENV=production
  4. Add a volume for persistent storage at /app/data

Render

  1. Create a new Web Service
  2. Connect your repository
  3. Set build command: pip install -r requirements.txt
  4. Set start command: cd app && gunicorn -w 4 -b 0.0.0.0:$PORT app:app
  5. Add environment variables (SECRET_KEY, FLASK_ENV=production)
  6. Add disk storage for /app/data

DigitalOcean App Platform

  1. Create app from GitHub repository
  2. Configure as Python app
  3. Add managed database or use attached volume for SQLite
  4. Set environment variables
  5. Deploy!

Any VPS (DigitalOcean, Linode, Vultr, AWS EC2, etc.)

  • Minimum requirements: 512MB RAM, 1 CPU core, 5GB storage
  • Use Docker Compose or manual installation
  • Works on Ubuntu, Debian, CentOS, Fedora, etc.
  • Set up Nginx reverse proxy for HTTPS (see production checklist below)

Production Checklist

  • Set FLASK_ENV=production in environment variables
  • Generate strong SECRET_KEY with secrets.token_hex(32)
  • Enable HTTPS/TLS with Let's Encrypt or similar
  • Use Gunicorn or similar production WSGI server
  • Configure reverse proxy (Nginx or Apache) with SSL
  • Set up automated backups (see Backup Strategy below)
  • Configure firewall rules (allow only 80/443, block direct access to 4123)
  • Review file permissions on data/ directory
  • Set up monitoring and logging
  • Consider enabling optional encryption (SQLCipher + Fernet)
  • Use strong passwords for user accounts
  • Keep application updated (git pull + restart)

Reverse Proxy Setup (Nginx + SSL)

Install Nginx and Certbot:

sudo apt update
sudo apt install nginx certbot python3-certbot-nginx

Configure Nginx (/etc/nginx/sites-available/hsa-tracker):

server {
    listen 80;
    server_name yourdomain.com;

    location / {
        proxy_pass http://127.0.0.1:4123;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Enable site and get SSL certificate:

sudo ln -s /etc/nginx/sites-available/hsa-tracker /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
sudo certbot --nginx -d yourdomain.com

Usage Guide

First-Time Setup (Onboarding)

When you first log in, you'll be guided through:

  1. Currency & Timezone - Set your preferred currency and timezone
  2. HSA Balance - Enter your current HSA balance (optional)
  3. Benefit Plans - Configure FSA/DCFSA benefit plans with election amounts
  4. Family Members - Add household members for expense tracking

Adding Expenses

  1. Click "+ Add Expense" in the navigation
  2. Fill in expense details:
    • Date of Service (required) - When the medical service occurred
    • Amount Paid (required) - How much you paid out-of-pocket
    • Category - HSA, FSA, or DCFSA
    • Status - Open, Pending, Reimbursed, etc.
    • Provider - Select from dropdown or add new
    • Family Member - Who the expense is for
    • Description - Notes about the expense
    • Claim Number - Insurance claim reference
  3. Attach receipts - Upload PDF, JPG, or PNG files
  4. Click "Save Expense"

Managing Reimbursements

  1. Find the expense in your expenses list
  2. Click to edit
  3. Update status as your claim progresses:
    • Open β†’ Pending (submitted to insurance)
    • Pending β†’ Partially Reimbursed (received partial payment)
    • Partially Reimbursed β†’ Reimbursed (fully paid)
  4. Enter reimbursement amounts as you receive them
  5. Upload proof-of-reimbursement documents (insurance EOB, payment confirmation)
  6. Track pending and completed reimbursements on the dashboard

Setting Up Benefit Plans (FSA/DCFSA)

  1. Navigate to Dashboard
  2. Scroll to Benefit Plan Management section
  3. Click "Add Benefit Plan"
  4. Select account type (FSA or DCFSA)
  5. Set custom date range (e.g., January 1 - December 31, or April 1 - March 31)
  6. Enter annual election amount
  7. Save

Expenses within the benefit plan will automatically track against your election limit on the dashboard.

Exporting Data

CSV Export (for spreadsheet analysis):

  1. Go to Dashboard or Expenses page
  2. Apply filters if desired (year, category, status)
  3. Click "Export CSV"
  4. Download opens in Excel, Google Sheets, LibreOffice, etc.

Full Backup (database + receipts):

  1. Go to Settings
  2. Scroll to Data Export section
  3. Click "Export DB"
  4. Download ZIP file containing:
    • Complete SQLite database
    • All receipts organized by year in original formats
    • Reimport ready - Can be used to restore complete system

Backup/Restore Process:

# Backup (manual)
zip -r hsa-backup-$(date +%Y%m%d).zip data/

# Restore
unzip hsa-backup-20240101.zip
# Restart application

Configuration

Environment Variables

Configure via .env file:

# Required
FLASK_ENV=production              # Use 'production' in production, 'development' for dev
SECRET_KEY=your-secret-key        # Generate with: python -c 'import secrets; print(secrets.token_hex(32))'

# Optional
PORT=4123                         # Port to run on (defaults to 4123)
APP_URL=http://localhost:4123     # Application URL (required for OIDC)

# OIDC Authentication (Optional)
OIDC_ENABLED=false                # Enable OIDC/SSO authentication
OIDC_ALLOW_LOCAL_AUTH=true        # Keep local auth as fallback (recommended)

# Example: Google OAuth
# GOOGLE_CLIENT_ID=your-client-id.apps.googleusercontent.com
# GOOGLE_CLIENT_SECRET=your-client-secret

OIDC/SSO Authentication Setup

The application supports OpenID Connect (OIDC) authentication with multiple providers:

  • Supported providers: Google, Microsoft, Okta, Auth0, Keycloak, GitLab, and any OIDC-compliant provider
  • Auto-provisioning: New users are automatically created on first OIDC login
  • Local fallback: Username/password auth can remain enabled as backup
  • Secure: Implements PKCE, state validation, and secure session management

πŸ“– Complete OIDC Setup Guide: See OIDC_SETUP.md for detailed instructions on configuring each provider.

Quick Example (Google):

  1. Create OAuth credentials at Google Cloud Console
  2. Set redirect URI: https://your-domain.com/auth/oidc/callback/google
  3. Add to .env:
    OIDC_ENABLED=true
    APP_URL=https://your-domain.com
    GOOGLE_CLIENT_ID=your-client-id.apps.googleusercontent.com
    GOOGLE_CLIENT_SECRET=your-client-secret
  4. Run migration: python app/migrations/001_add_oidc_fields.py
  5. Restart application

User Settings

Per-user preferences (configured in Settings page):

  • Timezone - Defaults to America/New_York (supports all pytz timezones)
  • Currency - Defaults to USD (supports 10 major currencies)
  • HSA Balance - Track current HSA account balance

Data Storage Locations

  • Database: data/hsa_tracker.db (SQLite)
  • Receipts: data/receipts/USER_ID/YEAR/ (organized by user and year)

Security

This application implements multiple layers of security:

  • βœ… Password hashing - Werkzeug secure password hashing
  • βœ… CSRF protection - Flask-WTF tokens on all state-changing operations
  • βœ… Rate limiting - Prevents brute-force attacks (5 login attempts/min, 3 registrations/hour)
  • βœ… Session security - HttpOnly, SameSite cookies; secure flag in production
  • βœ… User isolation - Complete data separation between users
  • βœ… Verified file serving - Users can only access their own receipts
  • βœ… Security headers - HSTS, X-Content-Type-Options, X-Frame-Options, X-XSS-Protection
  • βœ… Optional encryption - SQLCipher database encryption + Fernet file encryption

Enable Optional Encryption:

# Generate encryption keys
cd app/utils
python encryption.py

# Add to .env file
DB_ENCRYPTION_KEY=your-generated-db-key
FILE_ENCRYPTION_KEY=your-generated-file-key

For complete security documentation, see SECURITY.md.


Backup Strategy

Recommended: Set up automated backups to prevent data loss.

Automated Backups (Linux cron)

# Edit crontab
crontab -e

# Add daily backup at 2 AM
0 2 * * * cd /path/to/hsa-tracker-v2 && zip -r backups/backup_$(date +\%Y\%m\%d).zip data/

Automated Backups (Docker)

Add to your docker-compose.yml:

services:
  backup:
    image: alpine:latest
    volumes:
      - ./data:/data:ro
      - ./backups:/backups
    command: sh -c "zip -r /backups/backup_$(date +%Y%m%d).zip /data"

Run with cron:

0 2 * * * cd /path/to/hsa-tracker-v2 && docker-compose run --rm backup

Manual Backup

Use the built-in "Export DB" feature in Settings, or manually copy the data/ directory:

cp -r data/ backups/backup_$(date +%Y%m%d)/

Database Schema

Core Tables:

  • users - User accounts with authentication, timezone, currency preferences
  • expenses - Expense records with status tracking, amounts, claim numbers
  • attachments - Receipt and proof-of-reimbursement file references
  • plan_years - FSA/DCFSA benefit plan tracking with custom date ranges
  • providers - Healthcare providers and merchants
  • family_members - Family member tracking for household expenses

Optimized with indexes for fast filtering by category, status, year, and date range.


Troubleshooting

Database doesn't exist:

cd app
python database.py

Port already in use: Edit .env and change PORT=5001 (or any available port)

Can't access from other devices on network: Ensure Flask is running with host='0.0.0.0' and your firewall allows the port:

sudo ufw allow 4123

Docker container won't start:

# Check logs
docker-compose logs -f

# Common issues:
# - Missing SECRET_KEY in .env
# - Port 4123 already in use (change PORT in .env)
# - Permission issues with ./data directory (run: sudo chown -R 1000:1000 data/)

File upload fails:

  • Check file size (max 16MB per file)
  • Supported formats: PDF, JPG, JPEG, PNG
  • Verify data/receipts directory has write permissions

Forgot password: Currently no self-service password reset. Admin can reset via database:

cd app
python
>>> from werkzeug.security import generate_password_hash
>>> generate_password_hash('newpassword')
# Copy hash and update users table in database

Contributing

This is an AGPL-3.0 licensed open source project. Contributions are welcome!

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

Development setup:

git clone https://github.com/yourusername/hsa-tracker-v2.git
cd hsa-tracker-v2
python -m venv venv
source venv/bin/activate
pip install -r requirements.txt
cd app
python database.py
python app.py

License

AGPL-3.0 License - Free and open source software.

This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

Important: Any modifications or network use requires making the source code available under the same license. This ensures the software remains free and open for everyone.

See LICENSE for full license text.


Support

β˜• Enjoying this project? Consider supporting development:

  • Buy me a coffee
  • Star this repository on GitHub
  • Share with others who need healthcare expense tracking
  • Contribute code or documentation improvements

Acknowledgments

Built with:

  • Flask - Python web framework
  • SQLite - Reliable embedded database
  • Gunicorn - Production WSGI server
  • Docker - Containerization platform

πŸ“ Note: This application is designed for self-hosting. Always maintain regular backups of your data and receipts. Not affiliated with any financial institution or insurance provider.

About

No description, website, or topics provided.

Resources

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages