π Filesystem Structure
LibreFolio stores all persistent data in a structured directory under backend/data/. Understanding this structure is important for backup, debugging, and maintenance.
ποΈ Directory Layout
backend/data/
βββ π prod/ # Production data (default)
β βββ ποΈ sqlite/
β β βββ π app.db # Main SQLite database (WAL mode)
β βββ πΌοΈ custom-uploads/ # User-uploaded files
β β βββ π {uuid}.{ext} # Binary file (image, document, etc.)
β β βββ π {uuid}.json # Metadata sidecar (uploader, date, MIME type)
β βββ π broker_reports/
β β βββ π₯ uploaded/ # Reports waiting to be parsed
β β βββ β
parsed/ # Successfully parsed reports
β β βββ β failed/ # Reports that failed parsing
β βββ π logs/ # Application log files
β
βββ π§ͺ test/ # Test data (completely isolated)
βββ ποΈ sqlite/app.db
βββ πΌοΈ custom-uploads/
βββ π broker_reports/
βββ π logs/
π What's in Each Directory
ποΈ sqlite/app.db
The main SQLite database. Contains all application data: users, brokers, transactions, FX rates, settings, etc.
- π Uses WAL (Write-Ahead Logging) journal mode for better concurrent access
- π The
.db-waland.db-shmfiles are temporary WAL files β they're expected and managed by SQLite
Developer deep-dive: Database Schema
πΌοΈ custom-uploads/
Files uploaded by users through the Files page. Each upload creates two files:
- π
{uuid}.{ext}β The actual binary file (e.g.,a1b2c3d4.png) - π
{uuid}.jsonβ Metadata including: original filename, MIME type, file size, upload date, uploader user ID
Developer deep-dive: File Upload Component
π broker_reports/
Broker report files for the BRIM (Broker Report Import Manager) system:
- π₯
uploaded/β Raw files as uploaded by users (CSV, Excel) - β
parsed/β Files that have been successfully processed (transactions extracted) - β
failed/β Files that failed parsing (kept for debugging β check logs for details)
Developer deep-dive: BRIM Architecture
π logs/
Application logs in structured JSON format (via structlog).
π Environment Variables
| Variable | Default | Description |
|---|---|---|
LIBREFOLIO_DATA_DIR |
./backend/data/prod |
Override the production data directory path |
LIBREFOLIO_TEST_MODE |
0 |
Set to 1 to use backend/data/test/ instead of prod/ |
PORT |
8000 |
Production server port |
TEST_PORT |
8001 |
Test server port (used when LIBREFOLIO_TEST_MODE=1) |
πΎ Backup
π¦ Simple Backup
The easiest way to back up LibreFolio is to copy the entire data directory:
# Stop the server first (to ensure database consistency)
cp -r backend/data/prod/ /path/to/backup/librefolio-$(date +%Y%m%d)/
π³ Docker Backup
If running via Docker, the data directory is typically mounted as a volume:
# Find the volume
docker volume inspect librefolio_data
# Copy data out
docker cp librefolio-container:/app/backend/data/prod/ ./backup/
β What to Back Up
At minimum, back up:
sqlite/app.dbβ All your data (users, transactions, settings, FX rates)custom-uploads/β User-uploaded files (avatars, documents)broker_reports/uploaded/β Original broker reports (in case you need to re-parse)
Database-only backup
If storage is limited, backing up just sqlite/app.db preserves all structured data. Files can always be re-uploaded.
π§ Maintenance from Host Terminal
π³ Docker exec
# Access the container shell
docker exec -it librefolio-container /bin/bash
# Run dev.py commands inside the container
./dev.py user list
./dev.py user reset admin newpassword
./dev.py db upgrade
π» Direct access (non-Docker)
# From the project root
./dev.py user list # List all users
./dev.py user reset <user> <pw> # Reset a user's password
./dev.py user promote <user> # Grant superuser privileges
./dev.py user demote <user> # Remove superuser privileges
./dev.py db upgrade # Apply pending migrations
./dev.py db create-clean # Reset database (WARNING: deletes all data)
For a full list of CLI commands, see CLI Tools.