Deploying Fava
Introduction
Fava is a modern, feature-rich web interface for Beancount, a powerful double-entry accounting system implemented in Python. Unlike traditional accounting software that hides data in proprietary databases, Fava embraces plain text accounting—your entire financial history lives in simple, version-controllable text files that you can edit with any text editor.
Fava transforms Beancount’s plain text ledgers into interactive dashboards with beautiful charts, real-time balance calculations, and powerful query capabilities. It’s perfect for personal finance tracking, small business accounting, investment portfolio management, or anyone who values transparency and control over their financial data.
Key Features
- Plain Text Accounting - Your financial data stored in human-readable text files
- Double-Entry Bookkeeping - Professional-grade accounting principles built-in
- Interactive Dashboards - Real-time balance sheets, income statements, and cash flow reports
- Multi-Currency Support - Track accounts in different currencies with automatic conversion
- Investment Tracking - Monitor stock portfolios, calculate returns, and track cost basis
- Budget Planning - Set budgets and compare actual vs. planned spending
- Tag-Based Organization - Flexible categorization with tags, payees, and custom metadata
- Query Interface - SQL-like queries for custom financial reports
- Import Tools - Import transactions from CSV files and bank statements
- Document Attachments - Link receipts and invoices to transactions
- Version Control Friendly - Track financial history with Git
- Mobile Responsive - Manage finances from any device
- Extensible - Python-based plugins and custom scripts
- Privacy First - No data leaves your server, no subscriptions, no vendor lock-in
Why Deploy Fava on Klutch.sh?
Deploying Fava on Klutch.sh provides significant advantages for managing your financial data:
- Complete Privacy - Your financial records stay on your infrastructure, never shared with third parties
- Always Accessible - Access your accounts from anywhere with HTTPS security
- Fast Deployment - Automatic Dockerfile detection gets you running in minutes
- Persistent Storage - Reliable storage for years of transaction history and documents
- No Recurring Costs - Predictable infrastructure pricing without per-user or per-account fees
- Version Control Integration - Easy Git integration for tracking financial history
- Automatic Backups - Built-in volume backup capabilities for peace of mind
- Custom Domains - Professional access at your own domain
- Scalable - Handles decades of transaction data without slowdown
Prerequisites
Before deploying Fava on Klutch.sh, ensure you have:
- A Klutch.sh account
- Basic familiarity with Docker and environment variables
- Understanding of double-entry accounting principles (helpful but not required)
- Beancount ledger files or willingness to create them
- Optional: Git repository for version-controlling your ledgers
Understanding Fava and Beancount
Fava is built on top of Beancount, which uses a simple text format for recording transactions:
; Example Beancount ledger
; Account declarations2024-01-01 open Assets:Bank:Checking2024-01-01 open Assets:Bank:Savings2024-01-01 open Income:Salary2024-01-01 open Expenses:Groceries2024-01-01 open Expenses:Rent
; Transactions2024-01-15 * "Paycheck" Assets:Bank:Checking 3500.00 USD Income:Salary -3500.00 USD
2024-01-16 * "Grocery Store" "Weekly shopping" Expenses:Groceries 156.32 USD Assets:Bank:Checking -156.32 USD
2024-01-01 * "Landlord" "January rent" Expenses:Rent 1200.00 USD Assets:Bank:Checking -1200.00 USDFava reads these files and presents them in a user-friendly web interface with charts, reports, and editing capabilities.
Preparing Your Repository
Create a new repository for your Fava deployment with the following structure:
fava-deployment/├── Dockerfile├── ledger/│ ├── main.beancount│ └── documents/└── .gitignoreDockerfile
Create a Dockerfile in your repository root:
# Multi-stage build for FavaFROM python:3.11-slim AS builder
# Set working directoryWORKDIR /app
# Install build dependenciesRUN apt-get update && apt-get install -y --no-install-recommends \ gcc \ g++ \ && rm -rf /var/lib/apt/lists/*
# Install Fava and BeancountRUN pip install --no-cache-dir --upgrade pip && \ pip install --no-cache-dir \ fava \ beancount \ smart_importer
# Production stageFROM python:3.11-slim
# Install runtime dependenciesRUN apt-get update && apt-get install -y --no-install-recommends \ ca-certificates \ && rm -rf /var/lib/apt/lists/*
# Create non-root userRUN useradd -m -u 1000 -s /bin/bash fava
# Copy Python packages from builderCOPY --from=builder /usr/local/lib/python3.11/site-packages /usr/local/lib/python3.11/site-packagesCOPY --from=builder /usr/local/bin/fava /usr/local/bin/favaCOPY --from=builder /usr/local/bin/bean-* /usr/local/bin/
# Create necessary directoriesRUN mkdir -p /data/ledger /data/documents && \ chown -R fava:fava /data
# Switch to non-root userUSER favaWORKDIR /data
# Environment variables with defaultsENV FAVA_HOST=0.0.0.0 \ FAVA_PORT=5000 \ BEANCOUNT_FILE=/data/ledger/main.beancount
# Expose portEXPOSE 5000
# Health checkHEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \ CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:5000').read()" || exit 1
# Start FavaCMD ["sh", "-c", "fava --host ${FAVA_HOST} --port ${FAVA_PORT} ${BEANCOUNT_FILE}"]Sample Beancount Ledger
Create ledger/main.beancount as your starting ledger file:
; Fava Configuration Optionsoption "title" "My Personal Finances"option "operating_currency" "USD"
; Account Declarations2024-01-01 open Assets:Bank:Checking USD2024-01-01 open Assets:Bank:Savings USD2024-01-01 open Assets:Cash USD2024-01-01 open Liabilities:CreditCard USD2024-01-01 open Equity:Opening-Balances USD2024-01-01 open Income:Salary USD2024-01-01 open Income:Interest USD2024-01-01 open Expenses:Groceries USD2024-01-01 open Expenses:Rent USD2024-01-01 open Expenses:Utilities USD2024-01-01 open Expenses:Transportation USD2024-01-01 open Expenses:Entertainment USD
; Opening Balances2024-01-01 * "Opening Balance" Assets:Bank:Checking 5000.00 USD Assets:Bank:Savings 10000.00 USD Equity:Opening-Balances -15000.00 USD
; Sample Transactions2024-01-15 * "Employer Inc" "January Paycheck" Assets:Bank:Checking 3500.00 USD Income:Salary -3500.00 USD
2024-01-16 * "Supermarket" "Weekly groceries" Expenses:Groceries 156.32 USD Assets:Bank:Checking -156.32 USD
2024-01-01 * "Property Management" "January rent" Expenses:Rent 1200.00 USD Assets:Bank:Checking -1200.00 USD
2024-01-05 * "Electric Company" "December electricity" Expenses:Utilities 85.50 USD Assets:Bank:Checking -85.50 USD
2024-01-10 * "Gas Station" "Fuel" Expenses:Transportation 45.00 USD Liabilities:CreditCard -45.00 USD
; Budget for 20242024-01-01 custom "budget" Expenses:Groceries "monthly" 600.00 USD2024-01-01 custom "budget" Expenses:Rent "monthly" 1200.00 USD2024-01-01 custom "budget" Expenses:Utilities "monthly" 150.00 USD2024-01-01 custom "budget" Expenses:Transportation "monthly" 200.00 USD2024-01-01 custom "budget" Expenses:Entertainment "monthly" 100.00 USD.gitignore
Create a .gitignore file to exclude sensitive or generated files:
# Python__pycache__/*.py[cod]*$py.class*.so.Python
# Environment.env.venvvenv/
# Fava cache.fava-cache/
# Documents (if containing sensitive receipts)# Uncomment if you don't want to commit documents# ledger/documents/
# IDE.vscode/.idea/*.swp*.swoDocker Compose for Local Development
For local testing before deploying to Klutch.sh, create a docker-compose.yml:
version: '3.8'
services: fava: build: . ports: - "5000:5000" volumes: - ./ledger:/data/ledger - ./ledger/documents:/data/documents environment: - BEANCOUNT_FILE=/data/ledger/main.beancount restart: unless-stoppedTest locally:
# Build and start Favadocker-compose up -d
# View logsdocker-compose logs -f fava
# Stopdocker-compose downAccess Fava at http://localhost:5000
Environment Variables Reference
Fava supports the following environment variables:
Server Configuration:
FAVA_HOST- Host to bind to (default:0.0.0.0)FAVA_PORT- Port to listen on (default:5000)BEANCOUNT_FILE- Path to main Beancount ledger file (required)
Optional Configuration:
FAVA_OPTIONS- Additional Fava command-line options (e.g.,--read-only)
Deploying on Klutch.sh
Now that your repository is ready, let’s deploy Fava to Klutch.sh.
Step 1: Create a New App
- Log in to your Klutch.sh dashboard
- Navigate to your project or create a new one
- Click "New App" and select "Deploy from GitHub"
- Authorize Klutch.sh to access your GitHub repositories
- Select the repository containing your Fava Dockerfile and ledger files
- Klutch.sh will automatically detect the Dockerfile in your repository
Step 2: Configure Environment Variables
- In the app configuration, navigate to the "Environment Variables" section
- Add the following environment variables:
FAVA_HOST=0.0.0.0FAVA_PORT=5000BEANCOUNT_FILE=/data/ledger/main.beancount
- Optional: Add
FAVA_OPTIONS=--read-onlyif you want to disable editing through the web interface
Step 3: Configure Traffic and Networking
- In the "Traffic" section, select HTTP
- Set the internal port to
5000(matchesFAVA_PORT) - Klutch.sh will automatically provide HTTPS access via your app's URL
Step 4: Attach Persistent Volumes
Fava needs persistent storage for your ledger files and document attachments.
- Navigate to the "Volumes" section in your app configuration
- Click "Add Volume" and configure:
- Mount Path:
/data/ledger - Size:
5 GB(adjust based on your needs)
- Mount Path:
- Add a second volume for documents and receipts:
- Mount Path:
/data/documents - Size:
10 GB(adjust based on the number of attachments)
- Mount Path:
Volume sizing recommendations:
- Ledger volume: 1-5 GB (text files are small; even decades of transactions fit in megabytes)
- Documents volume: 5-20 GB depending on the number of receipts, invoices, and attachments
Step 5: Deploy the App
- Review your configuration to ensure all settings are correct
- Click "Deploy" to start the deployment
- Klutch.sh will build your Docker image and deploy Fava
- Monitor the deployment logs for any errors
- Once deployed, access your Fava instance at
https://your-app-name.klutch.sh
Step 6: Upload Your Ledger Files
After deployment, you need to populate your ledger files:
Option A: Using Git (Recommended)
If your ledger files are in your Git repository, they’ll be copied during the Docker build. However, for updates, you’ll need to rebuild the container. A better approach is to use persistent volumes:
- Use
kubectlor a file manager to copy your ledger files to the persistent volume - Alternatively, create an initialization script in your Dockerfile that clones a Git repository
Option B: Manual Upload via Shell
- Access your container's shell through the Klutch.sh dashboard
- Create your ledger file:
cat > /data/ledger/main.beancount << 'EOF' ; Your Beancount transactions here option "title" "My Finances" option "operating_currency" "USD"2024-01-01 open Assets:Bank:Checking 2024-01-01 open Income:Salary EOF - Restart the Fava container to load the new ledger
Option C: Using a Git Repository in Dockerfile
Modify your Dockerfile to clone your ledger repository:
# Add this before the CMD instructionRUN apt-get update && apt-get install -y git && \ rm -rf /var/lib/apt/lists/*
# Clone your private ledger repository (use environment variables for credentials)ARG GIT_REPO_URLRUN if [ -n "$GIT_REPO_URL" ]; then \ git clone $GIT_REPO_URL /data/ledger; \ fiThen add GIT_REPO_URL as an environment variable in Klutch.sh.
Initial Setup and Configuration
After deployment, configure Fava for your needs:
First Access
- Navigate to
https://your-app-name.klutch.sh - Fava will load your
main.beancountfile - You'll see the main dashboard with your accounts and balances
Dashboard Overview
Fava’s interface includes several key sections:
- Income Statement - Shows income, expenses, and net profit/loss
- Balance Sheet - Assets, liabilities, and net worth
- Trial Balance - Lists all accounts with their balances
- Journal - Chronological list of all transactions
- Query - SQL-like interface for custom reports
- Statistics - Charts and visualizations of your financial data
- Documents - File attachments linked to transactions
- Import - Tools for importing transactions from CSV files
- Editor - Text editor for modifying your Beancount files directly
Adding Your First Transaction
- Click on the "Editor" tab in Fava
- Scroll to the bottom of your ledger file
- Add a new transaction:
2024-12-20 * "Coffee Shop" "Morning coffee" Expenses:Food:Coffee 5.50 USD Assets:Bank:Checking -5.50 USD - Click "Save"
- Fava will automatically reload and show the new transaction
Understanding Beancount Syntax
Account Types:
Assets- Things you own (bank accounts, cash, investments)Liabilities- Things you owe (credit cards, loans)Income- Money coming in (salary, interest, gifts)Expenses- Money going out (rent, groceries, utilities)Equity- Opening balances and retained earnings
Transaction Format:
YYYY-MM-DD [flag] "Payee" "Narration" Account1 Amount1 Currency Account2 Amount2 CurrencyFlags:
*- Cleared/completed transaction!- Pending transaction
Tags and Links:
2024-12-20 * "Restaurant" "Team dinner" ^invoice-123 #work #meals Expenses:Meals 125.00 USD Assets:Bank:Checking -125.00 USDUsage Examples
Recording Daily Transactions
Salary Deposit:
2024-12-15 * "Acme Corp" "December salary" Assets:Bank:Checking 4500.00 USD Income:Salary:Gross -5000.00 USD Income:Salary:Tax 500.00 USDCredit Card Purchase:
2024-12-16 * "Amazon" "Office supplies" Expenses:Office:Supplies 87.65 USD Liabilities:CreditCard -87.65 USDPaying Off Credit Card:
2024-12-20 * "Credit Card Payment" Liabilities:CreditCard 500.00 USD Assets:Bank:Checking -500.00 USDMulti-Currency Transactions
; Define exchange rates2024-12-20 price EUR 1.09 USD
2024-12-20 * "Hotel in Paris" "Business trip accommodation" Expenses:Travel:Lodging 150.00 EUR @ 1.09 USD Liabilities:CreditCard -163.50 USDInvestment Tracking
; Open investment accounts2024-01-01 open Assets:Investments:Brokerage:Cash USD2024-01-01 open Assets:Investments:Brokerage:AAPL AAPL2024-01-01 open Income:Investments:Capital-Gains USD
; Buy stock2024-12-01 * "Brokerage" "Buy Apple stock" Assets:Investments:Brokerage:AAPL 10 AAPL {150.00 USD} Assets:Investments:Brokerage:Cash -1500.00 USD
; Record current price2024-12-20 price AAPL 155.00 USD
; Sell stock2024-12-20 * "Brokerage" "Sell Apple stock" Assets:Investments:Brokerage:AAPL -10 AAPL {150.00 USD} @ 155.00 USD Assets:Investments:Brokerage:Cash 1550.00 USD Income:Investments:Capital-Gains -50.00 USDBudget Tracking
; Set monthly budgets2024-01-01 custom "budget" Expenses:Groceries "monthly" 600.00 USD2024-01-01 custom "budget" Expenses:Entertainment "monthly" 100.00 USD2024-01-01 custom "budget" Expenses:Transportation "monthly" 200.00 USDView budget vs. actual in Fava’s Statistics tab.
Attaching Documents
Link receipts and invoices to transactions:
2024-12-20 * "Office Depot" "Printer" Expenses:Office:Equipment 299.99 USD Assets:Bank:Checking -299.99 USD document: "/data/documents/2024-12-20-printer-receipt.pdf"Upload the PDF to /data/documents/ and Fava will link it to the transaction.
Python API for Automation
Automate financial tracking with Python scripts:
from beancount import loaderfrom beancount.core import datafrom beancount.core.amount import Amountfrom decimal import Decimalfrom datetime import date
# Load ledgerentries, errors, options = loader.load_file('/data/ledger/main.beancount')
# Create a new transactionnew_txn = data.Transaction( meta={'lineno': 0, 'filename': '/data/ledger/main.beancount'}, date=date(2024, 12, 20), flag='*', payee='Coffee Shop', narration='Morning coffee', tags=set(), links=set(), postings=[ data.Posting( account='Expenses:Food:Coffee', units=Amount(Decimal('5.50'), 'USD'), cost=None, price=None, flag=None, meta={} ), data.Posting( account='Assets:Bank:Checking', units=Amount(Decimal('-5.50'), 'USD'), cost=None, price=None, flag=None, meta={} ), ])
# Append to ledger filewith open('/data/ledger/main.beancount', 'a') as f: f.write(f"\n{new_txn.date} {new_txn.flag} \"{new_txn.payee}\" \"{new_txn.narration}\"\n") for posting in new_txn.postings: f.write(f" {posting.account:40} {posting.units.number:>10} {posting.units.currency}\n")CSV Import Script
Automate importing transactions from bank CSV exports:
import csvfrom datetime import datetimefrom decimal import Decimal
def import_csv(csv_path, output_path): transactions = []
with open(csv_path, 'r') as f: reader = csv.DictReader(f) for row in reader: date = datetime.strptime(row['Date'], '%m/%d/%Y').strftime('%Y-%m-%d') description = row['Description'] amount = Decimal(row['Amount'])
# Categorize based on description (customize as needed) if 'grocery' in description.lower(): expense_account = 'Expenses:Groceries' elif 'gas' in description.lower(): expense_account = 'Expenses:Transportation' elif 'amazon' in description.lower(): expense_account = 'Expenses:Shopping' else: expense_account = 'Expenses:Other'
# Generate transaction txn = f'{date} * "{description}"\n' txn += f' {expense_account:40} {abs(amount):>10.2f} USD\n' txn += f' Assets:Bank:Checking{"":<40} {-abs(amount):>10.2f} USD\n' transactions.append(txn)
# Append to ledger with open(output_path, 'a') as f: f.write('\n; Imported transactions\n') for txn in transactions: f.write(txn + '\n')
print(f"Imported {len(transactions)} transactions")
# Usageimport_csv('/data/documents/bank-export.csv', '/data/ledger/main.beancount')Query Interface Examples
Fava includes a powerful query interface (BQL - Beancount Query Language):
Monthly Expenses:
SELECT date, payee, account, sum(position) AS amountWHERE account ~ 'Expenses:' AND date >= 2024-01-01 AND date < 2024-02-01GROUP BY date, payee, accountORDER BY date DESCNet Worth Over Time:
SELECT date, sum(convert(position, 'USD')) AS net_worthWHERE account ~ 'Assets:' OR account ~ 'Liabilities:'GROUP BY dateORDER BY dateTop Expense Categories:
SELECT account, sum(position) AS totalWHERE account ~ 'Expenses:' AND year = 2024GROUP BY accountORDER BY total DESCLIMIT 10Tax-Deductible Expenses:
SELECT date, payee, narration, account, positionWHERE account ~ 'Expenses:' AND '#tax-deductible' IN tagsORDER BY dateProduction Best Practices
Security Hardening
1. Authentication (Optional but Recommended)
Fava doesn’t include built-in authentication. Add authentication via a reverse proxy:
Nginx with Basic Auth (Dockerfile addition):
# Install nginxRUN apt-get update && apt-get install -y nginx apache2-utils
# Create htpasswd file (do this in deployment, not in Dockerfile)# htpasswd -c /etc/nginx/.htpasswd yourusername
# Configure nginx as reverse proxyCOPY nginx.conf /etc/nginx/nginx.confnginx.conf:
events { worker_connections 1024;}
http { upstream fava { server localhost:5000; }
server { listen 8080;
location / { auth_basic "Fava Login"; auth_basic_user_file /etc/nginx/.htpasswd;
proxy_pass http://fava; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }}2. Read-Only Mode
For viewing without editing, enable read-only mode:
FAVA_OPTIONS="--read-only"3. File Permissions
Ensure proper file ownership:
# In containerchown -R fava:fava /data/ledgerchmod 600 /data/ledger/*.beancount4. Version Control
Track changes with Git for audit trails:
cd /data/ledgergit initgit add .git commit -m "Initial ledger"
# Create post-save hook to auto-commitcat > .git/hooks/post-commit << 'EOF'#!/bin/shgit add -Agit commit -m "Auto-commit: $(date)"EOFchmod +x .git/hooks/post-commitPerformance Optimization
1. Large Ledger Optimization
For ledgers with thousands of transactions:
; Use include to split ledgers by yearinclude "2022.beancount"include "2023.beancount"include "2024.beancount"2. Caching
Fava caches parsed ledgers. Increase cache efficiency:
# Pre-load ledger on container startbean-check /data/ledger/main.beancount3. Resource Limits
For large ledgers, allocate sufficient memory:
# In Dockerfile, no specific Python memory limits needed# Beancount is efficient even with decades of data4. Index Optimization
Beancount automatically indexes accounts. No manual optimization needed, but keep transactions chronologically sorted for faster parsing.
Backup Strategy
1. Automated Git Backups
Create a backup script:
#!/bin/bashcd /data/ledger
# Commit any changesif [[ -n $(git status -s) ]]; then git add -A git commit -m "Auto-backup: $(date '+%Y-%m-%d %H:%M:%S')"fi
# Push to remote (configure git remote first)git push origin main
echo "Backup completed: $(date)"Run via cron or manually:
chmod +x backup.sh./backup.sh2. Volume Snapshots
Use Klutch.sh’s volume backup features:
- Navigate to the "Volumes" section in your app
- Select your ledger volume
- Click "Create Snapshot"
- Schedule regular snapshots (daily recommended)
3. Export to Multiple Formats
Regularly export your data:
# Export to CSVbean-query /data/ledger/main.beancount "SELECT * FROM transactions" > backup.csv
# Export to SQLbean-query /data/ledger/main.beancount "SELECT * FROM transactions" -o json > backup.json4. Document Backups
Backup attached receipts and documents:
# Sync documents to external storagetar -czf documents-backup-$(date +%Y%m%d).tar.gz /data/documentsMonitoring and Alerts
1. Health Checks
Monitor Fava availability:
#!/bin/bashFAVA_URL="https://your-app-name.klutch.sh"
if curl -f -s "$FAVA_URL" > /dev/null; then echo "Fava is healthy"else echo "Fava health check failed" # Send alert (email, Slack, etc.)fi2. Ledger Validation
Regularly validate your ledger for errors:
# Check ledger integritybean-check /data/ledger/main.beancount
# Check for balance assertionsbean-doctor /data/ledger/main.beancount3. Transaction Monitoring
Alert on unusual transactions:
from beancount import loaderfrom decimal import Decimal
def check_large_transactions(ledger_path, threshold=1000.00): entries, errors, options = loader.load_file(ledger_path)
large_txns = [] for entry in entries: if hasattr(entry, 'postings'): for posting in entry.postings: if posting.units and abs(posting.units.number) > Decimal(threshold): large_txns.append({ 'date': entry.date, 'payee': entry.payee, 'amount': posting.units })
if large_txns: print(f"Found {len(large_txns)} transactions over ${threshold}") for txn in large_txns: print(f" {txn['date']} - {txn['payee']}: {txn['amount']}")
return large_txns
# Run dailycheck_large_transactions('/data/ledger/main.beancount', threshold=1000.00)4. Balance Reconciliation
Add balance assertions to catch errors:
; Check balance on specific dates2024-12-20 balance Assets:Bank:Checking 2345.67 USD2024-12-31 balance Assets:Bank:Savings 10000.00 USDBeancount will error if balances don’t match, alerting you to missing transactions or errors.
Troubleshooting
Common Issues and Solutions
1. Ledger File Not Found
Symptom: Fava fails to start with “Error: file not found”
Solutions:
-
Verify
BEANCOUNT_FILEpath is correct:/data/ledger/main.beancount -
Check that persistent volume is mounted at
/data/ledger -
Ensure ledger file exists and has correct permissions
-
Test with shell access:
Terminal window ls -la /data/ledger/cat /data/ledger/main.beancount
2. Syntax Errors in Ledger
Symptom: Fava shows “Parse Error” or fails to load
Solutions:
-
Validate ledger file:
Terminal window bean-check /data/ledger/main.beancount -
Check for common errors:
- Missing account declarations
- Unbalanced transactions (debits ≠ credits)
- Invalid date formats (must be YYYY-MM-DD)
- Missing currency codes
-
Use Fava’s editor with syntax highlighting to fix errors
3. Container Out of Memory
Symptom: Container crashes or becomes unresponsive with large ledgers
Solutions:
-
Split ledger into multiple files by year:
include "2022.beancount"include "2023.beancount"include "2024.beancount" -
Increase container memory allocation in Klutch.sh dashboard
-
Optimize queries (avoid
SELECT *on huge datasets)
4. Permission Denied Errors
Symptom: Cannot save changes or write files
Solutions:
-
Verify volume permissions:
Terminal window chown -R fava:fava /data/ledgerchmod -R u+rw /data/ledger -
Check that Fava is running as correct user (UID 1000)
-
Ensure volumes are mounted with read-write permissions
5. Import Failures
Symptom: CSV import doesn’t work or creates malformed transactions
Solutions:
-
Verify CSV format matches expected structure
-
Check date format in CSV (MM/DD/YYYY vs YYYY-MM-DD)
-
Use smart_importer for better automatic categorization:
Terminal window pip install smart_importer -
Review imported transactions before committing
6. Currency Conversion Issues
Symptom: Multi-currency transactions show errors or wrong values
Solutions:
-
Define exchange rates explicitly:
2024-12-20 price EUR 1.09 USD2024-12-20 price GBP 1.27 USD -
Use
@for transaction-time rates:Expenses:Travel 100.00 EUR @ 1.09 USD -
Update exchange rates regularly (daily for volatile currencies)
7. Slow Performance
Symptom: Fava takes a long time to load or query
Solutions:
-
Split large ledger files by year
-
Close old periods (prevent edits to old data):
2024-01-01 close Assets:Bank:OldAccount -
Use specific date ranges in queries instead of full history
-
Cache frequently used queries as separate files
8. Documents Not Loading
Symptom: Attached documents show 404 or broken links
Solutions:
-
Verify document path in transactions:
document: "/data/documents/receipt.pdf" -
Check that documents volume is mounted at
/data/documents -
Ensure files have correct permissions:
Terminal window chmod 644 /data/documents/*.pdf -
Use relative paths from the documents directory
Debug Mode
Enable verbose logging for troubleshooting:
# Start Fava with debug loggingFAVA_OPTIONS="--debug" fava /data/ledger/main.beancount
# Check Beancount versionpython -m beancount.scripts.doctor
# Validate entire ledgerbean-check -v /data/ledger/main.beancountGetting Help
If you encounter issues not covered here:
- Check the Beancount documentation
- Review the Fava GitHub Issues
- Join the Beancount mailing list
- Visit the Plain Text Accounting subreddit
- Contact Klutch.sh support for platform-specific issues
Additional Resources
- Fava GitHub Repository
- Beancount Official Website
- Beancount Documentation
- Plain Text Accounting
- Smart Importer for Automatic Categorization
- Fava Wiki
- Klutch.sh Persistent Volumes
- Klutch.sh Deployments
Take Control of Your Finances - With Fava on Klutch.sh, you have complete ownership of your financial data in a transparent, version-controlled format. No subscriptions, no vendor lock-in, just pure double-entry accounting perfection. Start tracking your finances the right way today.