Files
discourse-hledger/README.md
T
raucao aeafc4c54a
CI / lint (push) Successful in 1m48s
CI / tests (push) Successful in 2m56s
Add screenshots
2026-09-27 17:45:13 +02:00

149 lines
5.4 KiB
Markdown

# **hledger** Discourse Plugin
[![CI](https://gitea.kosmos.org/raucao/discourse-hledger/actions/workflows/ci.yml/badge.svg?branch=main&event=push)](https://gitea.kosmos.org/raucao/discourse-hledger/actions)
[![Release](https://img.shields.io/gitea/v/release/raucao/discourse-hledger?gitea_url=https://gitea.kosmos.org)](https://gitea.kosmos.org/raucao/discourse-hledger/releases)
Render [hledger](https://hledger.org) journal reports inside Discourse topics.
Put an hledger journal in a fenced `hledger` code block in a topic's first
post. The block is replaced by a dashboard with five reports, generated live
by the `hledger` command line tool:
- 📋 Accounts and balances (a full account tree, each name capitalized)
- ⚖️ Balance sheet (indented account tree under each section)
- 📈 Profit & loss / P&L (indented account tree under each section)
- 👥 Equity distribution (account tree with per-commodity shares from absolute
balances; contributed capital, not legal ownership)
- 🧾 Journal (a detailed transaction log: date, description and postings)
## Screenshots
Rendered from the [example journal](docs/example.journal):
| Accounts | P&L | Journal |
| - | - | - |
| [![Accounts](docs/screenshots/accounts.png)](docs/screenshots/accounts.png) | [![P&L](docs/screenshots/pnl.png)](docs/screenshots/pnl.png) | [![Journal](docs/screenshots/journal.png)](docs/screenshots/journal.png) |
## Installation
The plugin requires the `hledger` executable on the server.
### Default Docker deployment
The recommended self-hosted setup runs Discourse in a container built from an
`app.yml` file ([install guide](https://github.com/discourse/discourse/blob/main/docs/INSTALL-cloud.md)).
Add the plugin and the `hledger` package to `/var/discourse/containers/app.yml`:
```yaml
hooks:
after_code:
- exec:
cd: $home/plugins
cmd:
- git clone https://gitea.kosmos.org/raucao/discourse-hledger.git
- exec:
cd: $home
cmd:
- apt-get update
- DEBIAN_FRONTEND=noninteractive apt-get install -y hledger
```
Then rebuild the container to apply the changes:
```sh
cd /var/discourse
./launcher rebuild app
```
The `after_code` hook runs on every rebuild, so the plugin and `hledger` stay
installed across rebuilds.
### Other installs
Follow the [plugin installation guide](https://meta.discourse.org/t/install-a-plugin/19157).
Install `hledger` with your package manager (for example
`apt-get install hledger`) and point the `hledger path` site setting at it if it
is not on the default `PATH`.
### Docker development environment
Inside the Discourse dev container, install the plugin's system dependencies
(hledger, Chromium and the Playwright browser used by the test suite) with:
```sh
docker exec -u root discourse_dev bash /src/plugins/discourse-hledger/bin/setup-dev
```
## How to use
1. Enable the plugin under `Admin > Settings > Plugins` (`hledger enabled`).
2. Add an hledger journal to the first post of a topic:
````
```hledger
2024-01-01 Opening balances
assets:bank:checking 1000.00 EUR
equity:alice -600.00 EUR
equity:bob -400.00 EUR
```
````
3. The code block is replaced by the report dashboard. Reports can be filtered
by a start and end date; the end date is inclusive.
Reports are generated on demand and cached per post revision, so editing the
journal refreshes them.
Account names can reference Discourse users: a path segment written as
`@username` (for example `equity:@alice`) is rendered as a mention link, with the
same profile card as mentions in posts. Only segments matching an existing user
are linked; anything else stays plain text.
## Security
Journals are untrusted input. The plugin runs `hledger` as an unprivileged
subprocess with a scrubbed environment, a private working directory, a hard
timeout, CPU, file-size and memory limits and an output cap, and it rejects
`include` directives so a journal cannot read arbitrary server files.
Defenses are layered: Discourse authorization, a per-IP rate limit and the
global rate limit, the journal size and line limits, the execution timeout, the
resource limits and the output cap.
For installations where untrusted users can create public topics, additionally
sandbox `hledger` at the OS or container level — for example a systemd unit with
`ProtectSystem=strict`, `ProtectHome=true`, `PrivateTmp=true`,
`NoNewPrivileges=true`, `RestrictAddressFamilies=AF_UNIX`, `MemoryMax=` and
`TasksMax=`, or a dedicated container runtime. Those controls are stronger than
in-process resource limits.
### Relevant settings
- `hledger max journal bytes` and `hledger max journal lines` limit the size of
an accepted journal.
- `hledger timeout seconds` limits the wall-clock time of each `hledger`
invocation.
- `hledger memory limit mb` caps the process memory (`0` disables it).
- `hledger max output bytes` caps the captured output.
- `hledger global rate limit per minute` throttles report generation across all
users (`0` disables it).
## Development
```sh
# Ruby specs (run `bin/setup-dev` first for the integration specs)
bin/rspec plugins/discourse-hledger/spec/lib plugins/discourse-hledger/spec/requests
bin/rspec plugins/discourse-hledger/spec/system
# Frontend tests
DISCOURSE_DISABLE_BROWSER_SANDBOX=1 bin/qunit plugins/discourse-hledger/test/javascripts
```
## License
MIT
## Contact
E-Mail, Chat, Social, Lightning: raucao@kosmos.org