docker-finance | modern accounting for the power-user
Go to file
Aaron Fiore bca788007b
Merge pull request #45 into master
784f576 hledger-flow: ethereum-based: add Aave V2 -> V3 Migration Helper support (Aaron Fiore)
d31ed3a hledger-flow: ethereum-based: add to Ethereum spam rules (Aaron Fiore)
2024-04-08 16:10:13 -07:00
.img docker-finance | modern accounting for the power-user 2024-03-08 23:42:21 -08:00
client Merge pull request #42 into master 2024-03-27 23:23:05 -07:00
container hledger-flow: ethereum-based: add Aave V2 -> V3 Migration Helper support 2024-04-03 00:08:18 -07:00
.gitignore docker-finance | modern accounting for the power-user 2024-03-08 23:42:21 -08:00
docker-finance.dox docker-finance | modern accounting for the power-user 2024-03-08 23:42:21 -08:00 docker-finance | modern accounting for the power-user 2024-03-08 23:42:21 -08:00 README: add support for AdaLite 2024-03-19 21:57:00 -07:00


Modern accounting for the power-user | Crypto, banking, tax prep, meta analysis & more!

  1. What does it do?
  2. What is supported?
  3. How do I get started?
  4. How do I use it?
  5. How do I contribute?
  6. How do I connect?
  7. Where is the legalese?

What does it do?


docker-finance empowers you with a privacy-focused, highly uniform system of financial management - but with a modern twist.

Cryptocurrencies and blockchain metadata are unified with your legacy finances to create a world of best-practice accounting in a highly flexible, time-tested environment.



Client (Host)

The docker in docker-finance.

image: docker-finance

image: dev-tools


The finance in docker-finance.


Ledger (command)

Meta (w/ ROOT C++ analysis)




Help (suite of commands)

What is supported?

Plaintext accounting gives you the power to manage any number of assets or accounts.

However, for accounts that require fetch/import functionality, only the following are supported:


Regularly maintained

Available but requires community maintenance

Available but no longer maintained

  • BlockFi (bankrupt)
  • Celsius Network (bankrupt)


Blockchain explorers / Ecosystems

Supported blockchains (independent of wallet type):





Regularly maintained

Requires community maintenance


How do I get started?


docker-finance is not your typical Docker image in which you simply pull and containerize but rather, its an image-based accounting system that functions almost entirely within your container.

docker-finance should work out-of-the-box on any modern Linux system. For example, if your client (host) is Ubuntu, the default installation of coreutils, shells and utils that came with your system will satisfy requirements. However, you'll still need to manually install Docker (see below).

  1. Install dependencies (most recent stable versions):

    • Docker with post-install configuration
    • GNU Bash 5.2+
      • If you don't have bash installed by default (or if bash is not your default shell), setup bash per your system's documentation
    • Git, for step 3 (strongly advised):
      • git should be available via your package manager (e.g., apt, pacman, etc.).
  2. Open a bash shell, if you haven't already done so.

  3. Copy/paste the following into your shell (one-time repository clone and client preparation):

    if [[ -f "$bashrc" && ! -f "$aliases" ]]; then
      if ! grep -E "(^\. ${aliases}|^source ${aliases})" "$bashrc" 1>/dev/null; then
    if git clone; then
      if ! grep -E "^alias docker-finance=" "$aliases" 1>/dev/null; then
        echo "alias docker-finance='$(pwd)/docker-finance/client/docker.bash archlinux/$(whoami):latest'" >>"$aliases"
        source "$aliases"
  4. Verify your repository (recommended):

    if pushd docker-finance/ 1>/dev/null; then
      gpg --keyserver hkp:// --recv-key 518A22F85BEFD32BCC99C48603F90C4F35E0213E \
        && git verify-commit $(git log -n1 --pretty=format:"%H") \
        && echo -e "\nSUCCESS: now confirm matching key = 518A22F85BEFD32BCC99C48603F90C4F35E0213E" \
        || echo -e "\nFATAL: no key available or possible MITM - do not use!"
      popd 1>/dev/null
  5. Generate client/container environment (see Environment Generation for details):

    docker-finance gen
  6. Build the image and bring up container:

    docker-finance build && docker-finance up
  7. You're inside! See How do I use it? for next steps.

Environment Generation

docker-finance's environment consists of two scopes: client and container. The client (host) view is confined to the host while the container view confined to the container (though the client can, at times, view from within the container's perspective). Think of the client as a class that inherits the container as a protected class with all the relevant permissions and scope.

In terms of configuration, the client (host) has two primary files, with one of them being mutually shared with the container. The 1st file is the Client (Host) Configuration File and the 2nd file is a joint Client/Container Superscript. Think of this superscript as the glue that binds the client/container scopes.

You'll create these files (and more) when running docker-finance gen, as seen below.

Client generation

Client-side environment found, backup then generate new one?

Generates the client (host) configuration file. See the Client (Host) Configuration File section for details.

  • You can use the generated defaults but make sure your directory layout matches accordingly
  • To easily edit this configuration file after gen is complete, run docker-finance edit type=env

Container generation

Container generation comes after (and must come after) client environment generation.

The container environment contains the bulk of configurations for everything you'll need while inside docker-finance.

Generate (or update) container profile configs and/or accounts?

The container environment is a minimum requirement but here you'll have the option to continue generating or to backup a previous install.

Will this profile be used for development and/or demonstration?

If you're a developer or wish to see the mockup test profile, select 'y' here.

Enter profile name (e.g., family in 'family/alice') Enter subprofile name (e.g., alice in 'family/alice')

Container generation will always be for a specific profile with subprofile, and here is where you input that information.

For example, you could have a family profile with subprofiles of various family members or a business profile with subprofiles of all the various businesses you own.

It should be noted that:

  • all subsequent questions and container generation will relate to this profile/subprofile pairing
  • all output will be sent to the ${DOCKER_FINANCE_CONTAINER_FLOW}/profiles/profile/subprofile path

Generate (or update) joint client/container shell script (superscript)? [Y/n]

Select 'y' if this a first-run. If this is not a first-run but you need to regenerate the file, the select 'y'.

See Superscript for details.

Generate (or update) container hledger-flow configs and/or accounts?

Not limited to hledger-flow data, this option leads to generating all docker-finance journal data (and configurations).

Generate (or update) subprofile's shell script?

The container's subprofile's shell script is where all subprofile commands and aliases exist.

This file is generated on a per-subprofile basis and all custom code on a per-subprofile basis should go here.

Generate (or update) subprofile's fetch configuration?

The container's fetch configuration is what all remote fetching relies on: prices, exchanges, blockchain explorers; all are configured here. See Container Configurations for details.

Generate (or update) subprofile's financial metadata?

The container's per-subprofile metadata file.

This file contains all your custom metadata and can edited with the edit and analyzed with the meta or root command. See Container Configurations for details.

Generate (or update) subprofile's hledger-flow accounts?

The container's hledger-flow accounts to be installed. These are the accounts described in What is supported?.

WARNING: if you plan to use blockchain-based wallets (coinbase-wallet, pera-wallet, ledger, metamask, etc.), you MUST generate their respective chains, as seen during generation (algorand, ethereum-based, tezos, etc).

Configuration Files

Note: Docker volumes aren't used because of chicken-or-the-egg problem, regarding client configuration (among other reasons). docker-finance needs the client environment before building the Docker image and spawning the subsequent container (which would rely on volumes).

Client (host) configuration

The client (host) configuration file:

  • is located in the ${DOCKER_FINANCE_CLIENT_CONF}/client/env/ directory, with subdirectory format of kernel-machine/platform/tag
    • format consists of username@hostname where username is your host username and hostname is your machine's hostname
  • client/container configurations can be stored on shared NFS/CIFS or related network storage (with applicable user permissions)
    • allows for customizable locations of all container data on any mountable filesystem (as a replacement for Docker Volumes)
  • consists solely of variables in the format DOCKER_FINANCE_VARIABLE=value and is used by both Docker and docker-finance
  • default template variables can be found in gen.bash, as described below


Client (host) configuration path. Parent directory for client configuration files.

  • Example: DOCKER_FINANCE_CLIENT_CONF=/home/${USER}/.config/docker-finance.d


Client (host) hledger-flow path. Parent directory for all profiles.

  • Example: DOCKER_FINANCE_CLIENT_FLOW=/net/nfs4/hledger-flow


Client (host) path for the docker-finance code repository (from the host's perspective).

This parent directory is where the client and container directories are located.

  • Example: DOCKER_FINANCE_CLIENT_REPO=/net/nfs4/git/docker-finance


Client (host) path for the client/container shared directory.

The bind-mount is used exclusively for non-essential file sharing (custom scripts or any file you wish).

  • Example: DOCKER_FINANCE_CLIENT_SHARED=/mnt/share.d


The container's finance command (useful for experimental implementations).

Default: finance.bash (internally aliased to finance)

  • Example: DOCKER_FINANCE_CONTAINER_CMD=finance.bash


The container's configuration path (bind-mounted to client's (host's) configuration path).

  • Example: DOCKER_FINANCE_CONTAINER_CONF=/home/${USER}/.config/docker-finance.d


The container's default text editor.



The container's hledger-flow path from the container's perspective.

This path is bind-mounted to the client's (host's) hledger-flow path.

  • Example: DOCKER_FINANCE_CONTAINER_FLOW=/home/${USER}/hledger-flow


The container's docker-finance code repository path (as viewed from the container).

This path is bind-mounted to the client's (host's) docker-finance/container path.

  • Example: DOCKER_FINANCE_CONTAINER_REPO=/home/${USER}/docker-finance


The container's share.d path, bind-mounted to client's (host's) share.d path.

  • Example: DOCKER_FINANCE_CONTAINER_FLOW=/home/${USER}/share.d


Docker daemon/container setting: number of CPUs to use.



Enable/disable debugging code paths (e.g., debug logging)

  • Example: DOCKER_FINANCE_DEBUG=true


hledger-web client-side (host) port



root client-side (host) port for web interface



docker-finance container memory limit (see Docker documentation).

  • Example: 5G


Group ID for bind mount. MUST have write permissions to rw bind-mounts.

  • Example: DOCKER_FINANCE_GID=998


User ID for bind mount. MUST have write permissions to rw bind-mounts.

  • Example: DOCKER_FINANCE_UID=1001


docker-finance container user.

Container user's UID/GID SHOULD match DOCKER_FINANCE_UID and DOCKER_FINANCE_GID. This is automatically determined during Environment Generation.

User MUST have write permissions to rw bind-mounts.

  • Example: DOCKER_FINANCE_USER=alice


Expected docker-finance configuration version.

Don't manually change this unless you were born with the UNIX Bible in your hand.


Client/Container Superscript

The client/container shell script (Superscript) is a bind-mounted (by directory) script that:

  • is the intermediary between client and container
  • is unique to each client (host) user (/home/alice, /home/bob, etc.)
  • is the glue that ties together all container Subprofile scripts
  • is generated on a per-client basis: all custom code on a per-client basis should go here

See the in-file comments for further documentation:

Note: as described in Client (host) command format, to edit this file, issue the client (host) command: docker-finance edit type=shell

Container Configurations

These configurations are confined solely to the container.


The Subprofile script is unique to each subprofile for each profile/subprofile within the profiles parent directory.

By default, this file will contain user aliases for all container commands. These aliases are mostly useful for small setups or setups with uniquely named subprofiles among all profiles.

See the in-file comments for further documentation:


The source of all remote API fetching configurations (exchanges, blockchains, market prices). This file is used by both the fetch and edit type=fetch commands.

See the in-file comments for further documentation:


The source of all custom metadata information (typically used to store cryptocurrency metadata information). This file is used by the meta, edit type=meta and root commands, as seen in Meta (w/ ROOT C++ analysis).

See the in-file comments for further documentation:

How do I use it?

Mostly-Unified CLI

You'll only need to call two different scripts throughout your time using docker-finance:

  1. The client script which handles the client-side system: docker.bash
  2. The container script which handles the container-side system: finance.bash

These two scripts can be rationalized by the following format:

<script> <super/sub> <command> [args]

Note: for your convenience, command arguments [args] can be arranged in any order.

For example, these Screenshots describe a setup with mockup data where the client (host) user named personal, along with container $DOCKER_FINANCE_USER named personal, engage in client/container activity. The container profile named testprofile and its subprofile named testuser can be described as <super/sub> portion of the format (testprofile/testuser).

Note: mockup data can be found in the mockup directories within this repository.

Client (Host) Command Format

The client (host) command format consists of:

docker.bash <platform/username:tag> <command> [args]


  • docker.bash is located in ${DOCKER_FINANCE_CLIENT_REPO}/client
  • <platform/username:tag>
    • platform is the image platform (archlinux, ubuntu)
    • username is the client (host) username with read/write permissions to the container (see Configuration Files)
    • tag is a custom tag you can use to delineate any number of images that you wish you create (latest, dev, etc.)
  • <command> is the command to pass to docker.bash
  • [args] are the (optional) arguments to pass to <command>

For a complete list of commands and usage help:

${DOCKER_FINANCE_CLIENT_REPO}/client/docker.bash archlinux/$(whoami):latest help

Or, if the Installation alias was properly created:

docker-finance help

You can also view the help usage of, for example, the edit command:

docker-finance edit help

Container Command Format

The container command format consists of:

finance.bash <profile/subprofile> <command> [args]


  • finance.bash is located in ${DOCKER_FINANCE_CLIENT_REPO}/container
  • <profile/subprofile>
  • <command> is the command to pass to finance.bash
  • [args] are the (optional) arguments to pass to <command>

Note: by default, the finance command can be called by either finance.bash or finance.

For a complete list of commands and usage help:

finance help

You can also view the help usage of, for example, the fetch command (notice the need for <profile/subprofile>):

finance testprofile/testuser fetch help

Note: the finance alias is named to avoid confusion with the client (host) command docker-finance - but you can still use the alias docker-finance within the container in place of all finance commands.

Or, use a subprofile alias, as described in Subprofile:

testuser_fetch help

Flow Layout

A primary read through of hledger and hledger-flow documentation should bring you up to speed on the essentials.

As for docker-finance specifics, create a test profile during Environment Generation to see what your flow's layout should look like.

Note: be sure to select 'y' when asked if this will be a development profile, and then go on to create account(s).

Once inside the container, assuming you created a profile named testprofile and subprofile named testuser, issue the following commands:

finance testprofile/testuser fetch all=price year=all && finance testprofile/testuser import year=2018

Note: you MUST import from 2018 as there are mockup accounts that begin from that year

All profiles/subprofiles are installed into the parent directory ${DOCKER_FINANCE_CONTAINER_FLOW}/profiles.

Peeking inside ${DOCKER_FINANCE_CONTAINER_FLOW}/profiles/profile/subprofile, you'll see the following:

  • all-years.journal and directives.journal

    • These top-level journals are generated by hledger-flow. Ignore these and use the edit command for journal editing.
  • docker-finance.d

    • Location of all docker-finance configuration files (see edit help for details).
  • import

    • Location of all CSV data and real journals. This is where you'll place CSV files and custom account/subaccount changes (see edit help for details).
  • prices

    • Location of all market price data, by year, as acquired by fetch price (see fetch help for details).
  • reports

    • Location of all generated reports, by year, as generated by reports (see reports help for details).
  • taxes

    • Location of all generated taxes, by year, as generated by taxes (see taxes help for details).

Regarding any profile you create:

  • For manual CSV downloads, place you CSV file into your ${DOCKER_FINANCE_CONTAINER_FLOW}/profiles/profile/subprofile/import/subprofile/account/subaccount/1-in/year directory - replacing year with the year of data that the file/data represents (see import help for details).
  • When you want to edit custom settings for an account or a subaccount, use the edit command (see edit help for details).
  • Your hledger-flow will contain a symlink called src which links to all the internal mechanics that process your data. Do not delete this link.

Caveats & Oddities

Flow Layout


Before you try to infer market prices, be sure to fetch prices before you do your first import (or first import of the year). If you do not fetch, the prices journal will not be included within the import and, if you have a previous year of prices, you will unwittingly infer against that previous year instead of your expected year!

Accounts: Trezor

In the "Trezor Suite" app, change your wallet name to your subaccount(s). For example, to delineate between your Trezor One from several Trezor T devices, and to delineate between their separate wallets within every device, follow these steps:

Example, using your #2 Trezor T device and one of its BTC "storage" wallets:

  1. Change wallet name in app to t-2:storage-1 as it's your Trezor T device #2, 1st bitcoin wallet named storage-1 (versus your 2nd bitcoin wallet named storage-2, etc.)
  2. Export the CSV file to the appropriate directory. It will be in the format of t_2_storage_1_20230629T230013.csv (timestamp will be different)
  3. Rename the file to t-2:storage-1_BTC.csv (be sure to append the currency ticker to the file. So, _BTC if bitcoin or _LTC if litecoin, etc).

Note: see Trezor mockup data within this repository, for a working example.

docker-finance relies on Amount unit within the file for the actual symbol/currency so, this file naming convention serves at least two purposes:

  1. This allows you to maintain device continuity by reusing wallet names for different currencies.
  2. This allows you to export, in the future, to the correct file from the associated hardware wallet because each hardware wallet exports its own unique CSV.


  • If you have a wallets designated for SPENDing/GIFTing or INCOME, you can use custom rules to mark all outgoing/incoming transactions as such (ex., using tags taxed_as:SPEND/taxed_as:GIFT/taxed_as:INCOME/etc.). See implementation for details.
  • WARNING: all GIFTIN cost-basis must be manually entered from the corresponding GIFT results/calculations (as gifted from another).
    • For blockchain-related transactions, you can easily add cost-basis of a gift received (GIFTIN) by TXID in your custom rules
      • Example: despite Electrum providing fiat_value, you'll need to manually enter in your custom rules the correct GIFT value (if divergent)

How do I contribute?



Your input is valuable and appreciated. Come, make this project your own!


100% of your donations go to the docker-finance funding pool.

This pool is reserved for the docker-finance ecosystem (developers & operating costs).


Donate with Coinbase Commerce


Donate with PayPal


For alternative donation methods, including your crypto/token of choice, please open a request in the issue tracker or reach out to Evergreen Crypto LLC.


To donate to the wonderful projects that docker-finance gratefully depends upon, please donate to them directly:

For other dependencies, please see their individual contributing guidelines.


You'll greatly benefit from building the dev-tools image, as seen in docker-finance help.

Additionally, when developing with the docker-finance image, please test your work with mockups as described in Environment Generation and Flow Layout.

Note: mockup CSVs will intentionally have multiple years within in a 1-in/year directory in order to test for year parsing.

Pull Request

The following assumes that the command docker-finance_dev-tools has been properly aliased, per docker-finance help.

Before sending a pull request:

  1. If you created a new file, please run docker-finance_dev-tools license file=/path/to/new/file.ext and update the copyright date and author.
  2. For any work that utilizes Bash/C++/PHP, please run the linter for your respective language (e.g., docker-finance_dev-tools linter type=bash).
    • See docker-finance_dev-tools linter help for details.
  3. As for style guidelines, these are recommended:
  4. If you can, please document the code in Doxygen style where applicable and run docker-finance_dev-tools doxygen gen to see your code documentation.


  • As described in Mostly-Unified CLI, to use a developer version of the finance image (not a dev-tools image), simply build and tag a new finance image with dev (or whatever you see fit), and reset the docker-finance alias at your discretion.
  • Run DOCKER_FINANCE_DEBUG=true docker-finance <cmd> [args] to debug before the Client (Host) Configuration File file is read.
  • The .C files you see in the repository are macro files, not C-language files.

How do I connect?

Join the docker-finance Matrix community.

Evergreen Crypto LLC

Where is the legalese?

License and Disclaimer


  • is not a Docker product
  • is not a Docker trademark
  • is not an endorsement of what is supported
  • is not a tax-advising product (consult your tax adviser)
  • is not a financial-advising product (consult your financial adviser)
  • is licensed under the GPLv3 but...