Addon docs
11
website/site/content/docs/addons/_index.md
Normal file
@ -0,0 +1,11 @@
|
||||
+++
|
||||
title = "Addons"
|
||||
insert_anchor_links = "right"
|
||||
description = "Describes how addons work."
|
||||
weight = 55
|
||||
template = "pages.html"
|
||||
sort_by = "weight"
|
||||
redirect_to = "docs/addons/basics"
|
||||
+++
|
||||
|
||||
No content here.
|
BIN
website/site/content/docs/addons/addon-install-01.png
Normal file
After Width: | Height: | Size: 105 KiB |
BIN
website/site/content/docs/addons/addon-install-01_dark.png
Normal file
After Width: | Height: | Size: 109 KiB |
BIN
website/site/content/docs/addons/addon-install-02.png
Normal file
After Width: | Height: | Size: 155 KiB |
BIN
website/site/content/docs/addons/addon-install-02_dark.png
Normal file
After Width: | Height: | Size: 164 KiB |
BIN
website/site/content/docs/addons/addon-install-03.png
Normal file
After Width: | Height: | Size: 100 KiB |
BIN
website/site/content/docs/addons/addon-install-03_dark.png
Normal file
After Width: | Height: | Size: 100 KiB |
BIN
website/site/content/docs/addons/addon-install-04.png
Normal file
After Width: | Height: | Size: 238 KiB |
BIN
website/site/content/docs/addons/addon-install-04_dark.png
Normal file
After Width: | Height: | Size: 242 KiB |
149
website/site/content/docs/addons/basics.md
Normal file
@ -0,0 +1,149 @@
|
||||
+++
|
||||
title = "Basics"
|
||||
insert_anchor_links = "right"
|
||||
description = "Docspell Addons."
|
||||
weight = 10
|
||||
template = "docs.html"
|
||||
+++
|
||||
|
||||
# Addons
|
||||
|
||||
Addons allow to execute custom software within a defined context in
|
||||
Docspell. The idea is to be able to support new features and amend
|
||||
existing ones.
|
||||
|
||||
{% warningbubble(title="Experimental") %} Addons are considered
|
||||
experimental. The interaction between addons and Docspell is still
|
||||
subject to change.
|
||||
|
||||
The intended audience for addons are developers (to create addons) and
|
||||
technically inclined users to install, configure and use them.
|
||||
{% end %}
|
||||
|
||||
Despite the warning above, addons are a nice way to amend your
|
||||
docspell server with new things, you are encouraged to try it out and
|
||||
give feedback ;-).
|
||||
|
||||
{% infobubble(title="Enable addons manually") %}
|
||||
Addons are disabled by default. They must be enabled in the config
|
||||
file of the restserver!
|
||||
{% end %}
|
||||
|
||||
|
||||
## What is an Addon?
|
||||
|
||||
An addon is a zip file that contains a `docspell-addon.yml` (or .yaml
|
||||
or .json) file in its root. The `docspell-addon.yml` is the *addon
|
||||
descriptor* telling how to run and optionally build the addon. In the
|
||||
ZIP file, an addon provides a program that expects one argument which
|
||||
is a file containing the user input for the addon. Addons can
|
||||
communicate back to docspell via their stdout and/or via directly
|
||||
calling the docspell server as part of their program.
|
||||
|
||||
|
||||
## What can Addons do?
|
||||
|
||||
Addons can accept user input and are arbitrary external programs that
|
||||
can do whatever they want. However, Docspell can embed running addons
|
||||
in restricted environments, where they don't have network for example.
|
||||
Addons can safely communicate to Docspell via their stdout output
|
||||
returning instructions that Docspell will realise.
|
||||
|
||||
Running addons is managed by docspell. Currently they can be executed:
|
||||
|
||||
- as the final step when processing or re-procssing an item. They then
|
||||
have access to all the item data that has been collected during
|
||||
processing (id, extracted text, converted pdfs, etc) and it can work
|
||||
with that. It may, for example, set more tags or custom fields.
|
||||
- trigger manually on some existing item
|
||||
- periodically defined by a schedule. This executes the addons only
|
||||
with the configured user input.
|
||||
- … (maybe more to come)
|
||||
|
||||
Since an addon may not make sense to run on all these situations, it
|
||||
must define a sensible subset via the `triggers` option in its
|
||||
descriptor.
|
||||
|
||||
|
||||
## How are they run
|
||||
|
||||
Addons are always executed by the joex component as an external
|
||||
process, therefore they can be written in any programming or scripting
|
||||
language.
|
||||
|
||||
That means the machine running joex possibly needs to match the
|
||||
requirements of each addon. To ease this, addons can provide a [nix
|
||||
descripton](https://nixos.wiki/wiki/Flakes) or a `Dockerfile`. Then
|
||||
you need to prepare the machine only with two things (nix and docker)
|
||||
to have the prerequisites for running many addons.
|
||||
|
||||
|
||||
# More …
|
||||
|
||||
Addons are a flexible way to extend Docspell and require some
|
||||
technical affinity. However, only "using" addons should not be that
|
||||
hard, but it will always depend on the documentation of the addon and
|
||||
its own complexity.
|
||||
|
||||
As the user, you may have different views: preparing the server to be
|
||||
able to run addons, writing your own addons and finally using them
|
||||
|
||||
The following sections are divided these perspectives:
|
||||
|
||||
## Using Addons
|
||||
|
||||
Addons must be installed and then configured in order before they can
|
||||
be used. [Using Addons](@/docs/addons/using.md) describes this
|
||||
perspective.
|
||||
|
||||
{{ buttonright(href="/docs/addons/using", text="More…") }}
|
||||
|
||||
## Control how addons are run
|
||||
|
||||
As the owner of your server, you want to [control how addons are
|
||||
run](@/docs/addons/control.md). Since addons are arbitrary programs,
|
||||
potentially downloaded from the internet, they can be run in a
|
||||
restricted environment.
|
||||
|
||||
{{ buttonright(href="/docs/addons/control", text="More…") }}
|
||||
|
||||
|
||||
## Write custom addons
|
||||
|
||||
Finally, [writing addons](@/docs/addons/writing.md) requires (among
|
||||
other things) to know how to interact with Docspell and what package
|
||||
format is expected.
|
||||
|
||||
{{ buttonright(href="/docs/addons/writing", text="More…") }}
|
||||
|
||||
|
||||
|
||||
<!-- ## Goals -->
|
||||
|
||||
<!-- - Convenient for addon creators. Addons can be written in any -->
|
||||
<!-- programming language and have a very light contract: they receive -->
|
||||
<!-- one input argument and _may_ return structured data to instruct -->
|
||||
<!-- docspell what to do. If not they can execute abritrary code to call -->
|
||||
<!-- the server directly. -->
|
||||
<!-- - Server administrators control how they are executed. Since addons -->
|
||||
<!-- may run anything, the execution should be able to locked down when -->
|
||||
<!-- wanted. -->
|
||||
<!-- - Users can install and configure addons via the web interface easily. -->
|
||||
<!-- It should be easy for addon creators to document how users can use -->
|
||||
<!-- them. -->
|
||||
|
||||
|
||||
<!-- # TODOs -->
|
||||
|
||||
<!-- - what if joex is running inside a container alread? -->
|
||||
<!-- - some use cases: -->
|
||||
<!-- - I want an addon to do some stuff when processing files -->
|
||||
<!-- - my files named "something_bla" are always this specific document -->
|
||||
<!-- and so very specific processing would be great -->
|
||||
<!-- - I want XYZ files to work (e.g. mp3?) -->
|
||||
<!-- - I want to generate previews for video files -->
|
||||
<!-- - Example Addons: -->
|
||||
<!-- - swiss qr code detection on invoices -->
|
||||
<!-- - tags via regexes -->
|
||||
<!-- - text extraction from audio? -->
|
||||
<!-- - preview generation for video? -->
|
238
website/site/content/docs/addons/control.md
Normal file
@ -0,0 +1,238 @@
|
||||
+++
|
||||
title = "Control Runtime"
|
||||
insert_anchor_links = "right"
|
||||
description = "Control how addons are run"
|
||||
weight = 30
|
||||
template = "docs.html"
|
||||
+++
|
||||
|
||||
# Control runtime of addons
|
||||
|
||||
Addons are run by the joex component as background tasks in an
|
||||
external process. Depending on the machine it is running on, the addon
|
||||
can be run
|
||||
|
||||
- inside a docker container
|
||||
- inside a systemd-nspawn container
|
||||
- directly on the machine
|
||||
|
||||
Addons can be provided as source packages, where the final program may
|
||||
need to be built. They also can depend on other software. In order to
|
||||
not prepare for each addon, it is recommended to install
|
||||
[nix](https://nixos.org) with [flakes](https://nixos.wiki/wiki/Flakes)
|
||||
and docker on the machine running joex.
|
||||
|
||||
Please also look at addon section in the [default
|
||||
configuration](@/docs/configure/main.md#joex) for joex.
|
||||
|
||||
You need to explicitly enable addons in the restserver config file.
|
||||
|
||||
Docspell uses "runners" to execute an addon. This includes building it
|
||||
if necessary. The following runner exist:
|
||||
|
||||
- `docker`: uses docker to build an run the addon
|
||||
- `nix-flake`: builds via `nix build` and runs the executable in
|
||||
`$out/bin`
|
||||
- `trivial`: simply executes a file inside the addon (as specified in
|
||||
the descriptor)
|
||||
|
||||
In the joex configuration you can specify which runners your system
|
||||
supports.
|
||||
|
||||
## Prepare for *running* addons
|
||||
|
||||
Depending on how you want addons to be run, you need to install either
|
||||
docker and/or systemd-nspawn on the machine running joex.
|
||||
Additionally, the user running joex must be able to use these tools.
|
||||
For docker it usually means to add the user to some group. For
|
||||
systemd-nspawn you most likely want to configure `sudo` to run
|
||||
passwordless the `systemd-nspawn` command.
|
||||
|
||||
Without this, an addon can only be run "directly" on the machine that
|
||||
hosts joex (which might be perfectly fine). The addon then "sees" all
|
||||
files on the machine and could potentially do harm.
|
||||
|
||||
It is recommended to install `nix` and `docker`, if possible. Addons
|
||||
may only run with docker or only without, so supporting both leaves
|
||||
more options.
|
||||
|
||||
|
||||
## Prepare for *building* addons
|
||||
|
||||
Addons can be packaged as source or binary packages. For the former,
|
||||
joex will build the addon first. There are two supported ways to do
|
||||
so:
|
||||
|
||||
- via `docker build` when the addons provides a `Dockerfile` (use
|
||||
runner `docker`)
|
||||
- via `nix build` when the addon provides a `flake.nix` file (use
|
||||
runner `nix-flake`)
|
||||
|
||||
Both build strategies will cache the resulting artifact, so subsequent
|
||||
builds will be (almost) no-ops.
|
||||
|
||||
{% infobubble(title="Note") %}
|
||||
*Building* addons requires to be connected to the internet! Running
|
||||
them may not require a network connection.
|
||||
{% end %}
|
||||
|
||||
If the addon is packaged as a binary, then usually the `trivial`
|
||||
runner (possibly in combination with `systemd-nspawn`) can be used.
|
||||
|
||||
# Runtime
|
||||
|
||||
## Cache directory
|
||||
|
||||
Addons can use a "cache directory" to store data between runs. This
|
||||
directory is not cleaned by docspell. If you have concerns about
|
||||
space, use a cron job or systemd-timer to periodically clean this
|
||||
directory.
|
||||
|
||||
## "Pure" vs "Impure"
|
||||
|
||||
Addons can talk back to Docspell in these ways: they can use the http
|
||||
api, for example with [dsc](@/docs/tools/cli.md), or they can return
|
||||
data to instruct Docspell to apply changes.
|
||||
|
||||
The former requires the addon to be connected to the network to reach
|
||||
the Docspell *restserver*. This allows the addon to do arbitrary
|
||||
changes at any time - this is the "impure" variant.
|
||||
|
||||
The second approach can be run without network connectivity. When
|
||||
using docker or systemd-nspawn, Docspell will run these addons without
|
||||
any network. Thus they can't do anything really, except return data
|
||||
back to Docspell.
|
||||
|
||||
The pure way is much preferred! It allows for more consistent
|
||||
behaviour, because Docspell is in charge for applying any changes.
|
||||
Docspell can apply changes *only if* the addon returned successfully.
|
||||
Addons can also be retried on error, because no changes happened yet.
|
||||
|
||||
It's the decision of the addon author, how the addon will work. It
|
||||
should document whether it is pure or impure. You can also look into
|
||||
the descriptor and check for a `networking: false` setting. As the
|
||||
server administrator, you can configure Docspell to only accept pure
|
||||
addons.
|
||||
|
||||
|
||||
## Runners
|
||||
|
||||
### nix flake runner
|
||||
|
||||
For addons providing a `flake.nix` this runner can build it and find
|
||||
the file to execute. With this `flake.nix` file addons can declare how
|
||||
they should be build and what dependencies are required to run them.
|
||||
|
||||
The resulting executable can be executed via `systemd-nspawn` in a
|
||||
restricted environment or directly on the machine.
|
||||
|
||||
{% infobubble(title="Requires") %}
|
||||
You need to install [nix](https://nixos.org) and enable
|
||||
[flakes](https://nixos.wiki/wiki/Flakes) to use this runner.
|
||||
{% end %}
|
||||
|
||||
### docker
|
||||
|
||||
Addons can provide a Dockerfile or an image. If no image is given,
|
||||
`docker build` will be run to build an image from the `Dockerfile`.
|
||||
Then `docker run` is used to run the addon.
|
||||
|
||||
{% infobubble(title="Requires") %}
|
||||
You need to install `docker` to use this runner.
|
||||
{% end %}
|
||||
|
||||
### trivial
|
||||
|
||||
Addons can simply declare a file to execute. Docspell can use
|
||||
`systemd-nspawn` to run it in an restricted environment, or it can be
|
||||
run directly on the machine. This variant is only useful for very
|
||||
simple addons, that don't require any special dependencies.
|
||||
|
||||
{% infobubble(title="Requires") %}
|
||||
You need to check each addon for its requirements and prepare the
|
||||
machine accordingly.
|
||||
{% end %}
|
||||
|
||||
### Choosing runners
|
||||
|
||||
The config `addons.executor-config.runners` accepts a list of runners.
|
||||
It specifies the preferred runner first. If an addon can be executed
|
||||
via docker and nix, Docspell will choose the runner first in the list.
|
||||
|
||||
If you don't have nix installed, remove the `nix-flake` runner from
|
||||
this list and same for docker, of course.
|
||||
|
||||
|
||||
### systemd-nspawn
|
||||
|
||||
The `systemd-nspawn` can be used to run programs in a lightweight
|
||||
ad-hoc container. It is available on most linux distributions (it is
|
||||
part of systemd…). It doesn't require an image to exist first; this
|
||||
makes it very convenient for running addons in a restricted
|
||||
environment.
|
||||
|
||||
If you enable it in the config file, then all addons are either run
|
||||
via `systemd-nspawn` or docker - and thus always in a restricted
|
||||
environment, where they can only access their own files and the files
|
||||
provided by Docspell.
|
||||
|
||||
The downside is that `systemd-nspawn` needs to be run as root (as far
|
||||
as I know). Therfore, configure `sudo` to allow the user that is
|
||||
running joex to execute `systemd-nspawn` non-interactively.
|
||||
|
||||
{% infobubble(title="Requires") %}
|
||||
Install `systemd-nspawn` and enable the user running joex to use it
|
||||
password-less via sudo.
|
||||
{% end %}
|
||||
|
||||
# Within Docker
|
||||
|
||||
If joex itself is run as a docker container, things get a bit
|
||||
complicated. The default image for joex does not contain `nix`, so the
|
||||
`nix-flake` runner cannot be used out of the box.
|
||||
|
||||
In order to use the `docker` runner, the container must be configured
|
||||
to access the hosts docker daemon. On most systems this can be
|
||||
achieved by bind-mounting the unix socket (usually at
|
||||
`/var/run/docker.sock`) into the container. Here is a snippet from the
|
||||
provided `docker-compose` file:
|
||||
|
||||
```yaml
|
||||
joex:
|
||||
image: docspell/joex:latest
|
||||
# ... left out for brevity
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- /tmp:/tmp
|
||||
```
|
||||
|
||||
Additionally to `/var/run/docker.sock`, it also bind mounts the `/tmp`
|
||||
directory. This is necessary, because docker will be invoked with bind
|
||||
mounts from inside the continer - but these must be available on the
|
||||
host, because the docker client in the container actually runs the
|
||||
command on the host.
|
||||
|
||||
The addon executor uses the systems temp-directory (which is usually
|
||||
`/tmp`) as a base for creating a working and cache directory. Should
|
||||
you change this in joex config file (or your system uses a different
|
||||
default temp-dir), then the bind mount must be adapted as well.
|
||||
|
||||
Another variant is to extend the default joex image and add more
|
||||
programs as needed by addons and then use the `trivial` runner.
|
||||
|
||||
# Summary / tl;dr
|
||||
|
||||
When joex is not inside a container:
|
||||
|
||||
- (optional) Install `systemd-nspawn` - it is provided on many
|
||||
GNU/Linux distributions
|
||||
- Configure `sudo` to allow the user running the joex component to
|
||||
execute `systemd-nspawn` non-interactively (without requiring a
|
||||
password)
|
||||
- Install docker
|
||||
- Install [nix](https://nixos.org) and enable
|
||||
[flakes](https://nixos.wiki/wiki/Flakes)
|
||||
- Allow the user who runs the joex component to use docker and nix. If
|
||||
you install nix as multi-user, then this is already done.
|
||||
- Check the section on addons in the [default
|
||||
configuration](@/docs/configure/main.md#joex) for joex
|
103
website/site/content/docs/addons/using.md
Normal file
@ -0,0 +1,103 @@
|
||||
+++
|
||||
title = "Usage"
|
||||
insert_anchor_links = "right"
|
||||
description = "How to use addons"
|
||||
weight = 20
|
||||
template = "docs.html"
|
||||
+++
|
||||
|
||||
# Using Addons
|
||||
|
||||
This shows with an example, how to install and use an addon. If the ui
|
||||
doesn't show these forms, addons are probably disabled. Addons need to
|
||||
be enabled in the config file of the rest server.
|
||||
|
||||
## Discovering
|
||||
|
||||
Addons can be installed from any URL to a zip file. One way is to use
|
||||
URLs generated by forges like github or gitlab. They provide zip files
|
||||
containing the repository contents. Alternatively an addon may provide
|
||||
specific files in their release section.
|
||||
|
||||
For example, this is the url to the first release of the rotate-pdf
|
||||
addon:
|
||||
|
||||
- <https://github.com/docspell/rotate-pdf-addon/archive/refs/tags/v0.1.0.zip>
|
||||
|
||||
This url points to a fixed version. It is also possible to use urls
|
||||
that are "moving targets":
|
||||
|
||||
- <https://github.com/docspell/rotate-pdf-addon/archive/refs/heads/master.zip>
|
||||
|
||||
The contents behind the above url will very likely change over time.
|
||||
|
||||
For better discoverability, repositories for addons on public forges
|
||||
can be tagged with *docspell-addon*.
|
||||
|
||||
## Install
|
||||
|
||||
With an URL like above, you can go to *Manage Data -> Addons -> New*
|
||||
and insert the url:
|
||||
|
||||
{{ figure2(light="addon-install-01.png", dark="addon-install-01_dark.png") }}
|
||||
|
||||
It might take a while for Docspell to download, extract and verify the
|
||||
addon. The addon will be downloaded into the database. Once installed,
|
||||
the given URL is not used anymore, unless a manual update is issued.
|
||||
|
||||
After this finishes, you cannot change the URL anymore:
|
||||
|
||||
{{ figure2(light="addon-install-02.png", dark="addon-install-02_dark.png") }}
|
||||
|
||||
When using URLs pointing to "moving targets", you could click the
|
||||
*Update Addon* button to re-download the contents at the url. This
|
||||
doesn't make much sense for URLs to fixed versions (in *theory* these
|
||||
could change as well, of course) and it is not without risk. It can be
|
||||
useful for own addons to have them quickly updated.
|
||||
|
||||
Now the addon is installed. It can now be used by creating a *run configuration*.
|
||||
|
||||
## Run Configuration
|
||||
|
||||
A run configuration is comprised of one or more addons, their inputs
|
||||
and some settings regarding their runtime environment.
|
||||
|
||||
The name is used for displaying in the webapp. You can disable/enable
|
||||
a run configuration.
|
||||
|
||||
It is possible that addons use [dsc](@/docs/tools/cli.md) or call the
|
||||
rest-server otherwise. Usually a valid session is required (to set
|
||||
tags or do searches). When selecting to run *on behalf of a user*, a
|
||||
valid authenticator for that user is injected into the environment of
|
||||
the addon run.
|
||||
|
||||
The *Trigger Run* setting specfies when this run configuraiton should
|
||||
be executed. You can choose from options that all addons in the list
|
||||
must support. In this example, only `existing-item` is used. This
|
||||
means the run configuration can be selected to run on any item.
|
||||
|
||||
Other options include:
|
||||
- `final-process-item`: executes automatically as the last step when
|
||||
processing uploaded files
|
||||
- `final-reprocess-item`: like `final-process-item` but applies when
|
||||
an existing item is reprocessed.
|
||||
- `scheduled`: runs periodically based on a schedule (and independent
|
||||
from any item)
|
||||
|
||||
Each addon may require arguments. Click on *Configure* to enable the
|
||||
*Arguments* section and add arguments for the corresponding addon.
|
||||
What to insert here is completely specific to the addon. In this case,
|
||||
it expects a JSON object with only one field `"degree"` that indicates
|
||||
how to rotate. In this example, it should be rotated by 90°
|
||||
counter-clockwise. You need to click *Update* to set it into the addon
|
||||
and then *Submit* to save everything.
|
||||
|
||||
{{ figure2(light="addon-install-03.png", dark="addon-install-03_dark.png") }}
|
||||
|
||||
|
||||
With this run configuration in place, you can try it out on some item:
|
||||
|
||||
{{ figure2(light="addon-install-04.png", dark="addon-install-04_dark.png") }}
|
||||
|
||||
This example configured the *rotate-pdf-addon* to rotate left by 90°.
|
||||
Create a simlar run configuration to rotate to the right.
|
376
website/site/content/docs/addons/writing.md
Normal file
@ -0,0 +1,376 @@
|
||||
+++
|
||||
title = "Writing"
|
||||
insert_anchor_links = "right"
|
||||
description = "How to write addons"
|
||||
weight = 20
|
||||
template = "docs.html"
|
||||
+++
|
||||
|
||||
# Writing Addons
|
||||
|
||||
Writing an addon can be divided into two things:
|
||||
|
||||
- create the program
|
||||
- define how to package and run it
|
||||
|
||||
The next sections describe both parts. For a quick start, check out
|
||||
the example addons.
|
||||
|
||||
As previously written, you can choose a language. The interaction with
|
||||
docspell happens by exchanging JSON data. So, whatever you choose, it
|
||||
should be possible to read and produce JSON with some convenience.
|
||||
|
||||
|
||||
# Writing the program
|
||||
|
||||
## Interface to Docspell
|
||||
|
||||
The interface to Docspell is JSON data. The addon receives all inputs
|
||||
as JSON and may return a JSON object as output (via stdout).
|
||||
|
||||
An addon can be executed in different contexts. Depending on this, the
|
||||
available inputs differ. The addon always receives one argument, which
|
||||
is a file containing the user supplied data (it may be empty). A user
|
||||
is able to provide data to every addon from the web-ui.
|
||||
|
||||
All other things are provided as environment variables. There are
|
||||
environment variables that are always provided and some are only
|
||||
available for specific contexts.
|
||||
|
||||
For example, an addon that is executed in the context of an item
|
||||
(maybe after processing or when a user selects an addon to run "on an
|
||||
item"), Docspell prepares all data for the corresponding item and
|
||||
makes it available to the addon. In contrast, an addon executed
|
||||
periodically by a schedule, won't have this data available.
|
||||
|
||||
|
||||
## Basic Environment
|
||||
|
||||
The following environment variables are always provided by Docspell:
|
||||
|
||||
- `ADDON_DIR` points to the directory containing the extracted addon
|
||||
zip file
|
||||
- `TMPDIR` / `TMP_DIR` a directory for storing temporary data
|
||||
- `OUTPUT_DIR` a directory for storing files that should be processed
|
||||
by docspell
|
||||
- `CACHE_DIR` a directory for storing data that should stay between
|
||||
addon runs
|
||||
|
||||
It is very much recommended to always use these environment variables
|
||||
when reading and writing data. This keeps Docspell in control about
|
||||
the exact location.
|
||||
|
||||
The working directory will be set to a directory that is also
|
||||
temporary, but please don't rely on that. Use the environment
|
||||
variables.
|
||||
|
||||
## Item data
|
||||
|
||||
When executed in the context of an item. Meaning for triggers:
|
||||
`final-process-item`, `final-reprocess-item`, `existing-item`.
|
||||
|
||||
### `ITEM_DATA_JSON`
|
||||
|
||||
This environment variable points to a JSON file containing information
|
||||
about the current item. If it is run at processing time, it includes
|
||||
all information gathered so far by Docspell.
|
||||
|
||||
**Example**
|
||||
{{ incl_json(path="templates/shortcodes/item-data") }}
|
||||
|
||||
|
||||
### `ITEM_ARGS_JSON`
|
||||
|
||||
This environment variable points to a JSON file that contains the user
|
||||
supplied information with an upload request. That is, a user may
|
||||
specify tags or a language when uploading files. This would be in this
|
||||
file.
|
||||
|
||||
*This is only available for uploads. Trigger `final-process-item`.*
|
||||
|
||||
**Example**
|
||||
{{ incl_json(path="templates/shortcodes/item-args") }}
|
||||
|
||||
|
||||
### `ITEM_ORIGINAL_JSON` and `ITEM_PDF_JSON`
|
||||
|
||||
These JSON files contains a list of objects. Each object provides
|
||||
properties about a file - either the original file or the converted
|
||||
pdf. The structure is the same.
|
||||
|
||||
**Example**
|
||||
{{ incl_json(path="templates/shortcodes/file-meta") }}
|
||||
|
||||
|
||||
|
||||
### Directories
|
||||
|
||||
These environment variables point to directories that contain the attachment files.
|
||||
|
||||
- `ITEM_PDF_DIR` contains all converted pdf files, the attachment id is the filename
|
||||
- `ITEM_ORIGINAL_DIR` contains all original files, the attachment id is the filename
|
||||
|
||||
For example, to obtain a converted pdf file, lookup the id in
|
||||
`ITEM_PDF_JSON` and then construct the file name via
|
||||
`ITEM_PDF_DIR/{id}`.
|
||||
|
||||
|
||||
## Session for dsc
|
||||
|
||||
An addon may use [dsc](@/docs/tools/cli.md) which requires for many
|
||||
commands a valid session identifier. Usually this is obtained by
|
||||
logging in (i.e. using `dsc login`). This is not really feasible from
|
||||
inside an addon, of course. Therefore you can configure an addon to
|
||||
run on behalf of some user when creating the run configuration.
|
||||
Docspell then generates a valid session identifier and puts it into
|
||||
the environment. The [dsc](@/docs/tools/cli.md) tool will pick them up
|
||||
automatically.
|
||||
|
||||
It will also setup the URL to connect to some restserver. (If you have
|
||||
multiple rest-servers running, it will pick one randomly).
|
||||
|
||||
- `DSC_SESSION` env variable containing a session identifier. It's
|
||||
validity is coupled on the configured timeout.
|
||||
- `DSC_DOCSPELL_URL` the base url to some rest server
|
||||
|
||||
That means when using an addon in this way, you can simply use `dsc`
|
||||
without worrying about authentication or the correct URL to connect
|
||||
to.
|
||||
|
||||
|
||||
## Output
|
||||
|
||||
Docspell doesn't interpret the returncode of an addon, except checking
|
||||
for being equal to `0` which indicates a successful run.
|
||||
|
||||
In order to do change data in Docspell, the addon program can run
|
||||
`dsc` (for example) to change some state - like setting tags etc. But
|
||||
the preferred approach would be to return instructions for Docspell.
|
||||
Docspell will execute the instructions when the addon terminates
|
||||
successfully - that is with return code `0`.
|
||||
|
||||
These instructions are in a JSON object which needs to go to stdout.
|
||||
You can use stderr in an addon for logging/debugging purposes. But if
|
||||
you specify `collectOutput: true` in the descriptior, then stdout must
|
||||
only return this specific JSON (or nothing, empty output is ignored).
|
||||
|
||||
You find the complete structure below. It consists of these parts:
|
||||
|
||||
- `commands`: let's you declare actions to do for an item or attachment
|
||||
- `files`: defines files relative to `OUTPUT_DIR` that should be
|
||||
processed
|
||||
- `newItems`: declares files relative to `OUTPUT_DIR` that should be
|
||||
processed as new uploads
|
||||
|
||||
The `commands` allows to set tags, fields and other things. All parts
|
||||
are optional, you don't need to return the complete structure. Just
|
||||
returning `commands` or only `files` is ok.
|
||||
|
||||
**Example**
|
||||
{{ incl_json(path="templates/shortcodes/addon-output") }}
|
||||
|
||||
|
||||
# Descriptor
|
||||
|
||||
An addon must provide an *addon descriptior*, which is a yaml or json
|
||||
file looking like this:
|
||||
|
||||
```yaml
|
||||
# The meta section is required. Name and version must not contain
|
||||
# whitespace
|
||||
meta:
|
||||
name: "name-of-addon"
|
||||
version: "2.21"
|
||||
description: |
|
||||
Describe the purpose and how it must be used here
|
||||
|
||||
# Defining when this addon is run. This is used to guide the user
|
||||
# interface in selecting an addon. At least one is required to specify.
|
||||
#
|
||||
# Possible values:
|
||||
# - scheduled: requires to enter a timer to run this addon periodically
|
||||
# - final-process-item: the final step when processing an item
|
||||
# - final-reprocess-item: the final step when reprocessing an item
|
||||
# - existing-item: A user selects the addon to run on an item
|
||||
triggers:
|
||||
- final-process-item
|
||||
- final-reprocess-item
|
||||
- existing-item
|
||||
|
||||
# How to build and run this addon (optional). If missing, auto
|
||||
# detection will enable a nix runner if a `flake.nix` is found in the
|
||||
# source root and docker if a `Dockerfile` is found.
|
||||
#
|
||||
# Both runners are compared to what is enabled at the server.
|
||||
runner:
|
||||
# Building the program using nix flakes. This requires a flake.nix
|
||||
# file in the source root with a default package and a flake-enabled
|
||||
# nix on the joex machine.
|
||||
#
|
||||
# The program is build via `nix build`. If the joex machine has
|
||||
# systemd-nspawn installed, it is used to run the addon inside a
|
||||
# container. Otherwise the addon is run directly on the machine.
|
||||
nix:
|
||||
enable: true
|
||||
|
||||
# Docker based runner can define a custom image to use. If a `build`
|
||||
# key exists pointing to a Dockerfile, the image is build before. If
|
||||
# the docker image is complex, you can build it independently and
|
||||
# provide the pre-build image.
|
||||
#
|
||||
# The program is run via `docker run` passing the arguments to the
|
||||
# addon. Thus it expects the entrypoint to be correctly configured
|
||||
# to the executable. You may use `args` in order to prepend
|
||||
# additional arguments, like the path to an executable if the image
|
||||
# requires that. The joex machine must have docker installed and the
|
||||
# user running joex must be allowed to use docker. You must either
|
||||
# define an image with an appropriate entry point or a dockerfile.
|
||||
docker:
|
||||
enable: false
|
||||
#image: myorg/myimage:latest
|
||||
build: Dockerfile
|
||||
|
||||
# Trivial runner that simply executes the file specified with
|
||||
# `exec`. Nothing is build before. This runner usually requires that
|
||||
# the joex machine contains all dependencies needed to run the
|
||||
# addon. You may need to install additional software on the machine
|
||||
# running joex.
|
||||
trivial:
|
||||
enable: false
|
||||
exec: src/addon.sh
|
||||
|
||||
# Optional arguments/options given to the program. The program
|
||||
# receives at least one argument, which is a file to the user input as
|
||||
# supplied in the application. The arguments here are prepended.
|
||||
args:
|
||||
|
||||
|
||||
options:
|
||||
# If false, the program is run inside a private network, blocking
|
||||
# traffic to the host and networks reachable from there. This only
|
||||
# applies if the addon can be run inside a container.
|
||||
#
|
||||
# If the addon runs side effects (such as using dsc to set tags),
|
||||
# this must be set to `true`.
|
||||
#
|
||||
# Default is false.
|
||||
networking: true
|
||||
|
||||
# If true, the stdout of the program is parsed into a JSON structure
|
||||
# that is interpreted as actions executed by the task that runs the
|
||||
# addon. If the addon runs side effects only, set this to `false`
|
||||
# and the output is ignored.
|
||||
#
|
||||
# It is recommended to use this approach, if possible. It allows
|
||||
# docspell itself to apply any changes and the addon can run
|
||||
# completely isolated.
|
||||
#
|
||||
# Default is false.
|
||||
collectOutput: true
|
||||
```
|
||||
|
||||
|
||||
# Packaging
|
||||
|
||||
Docspell can use different ways to build and run the addon:
|
||||
`nix-flake`, `docker` and `trivial`. The first two allow to package
|
||||
the addon in a defined way (with a single dependency, either nix or
|
||||
docker) and then execute it independently from the underlying system.
|
||||
This makes it possible to execute the addon on a variety of systems.
|
||||
This is especially useful for addons that are meant to be public and
|
||||
reusable by different people.
|
||||
|
||||
The "trivial" runner is only executing some program specified in
|
||||
`docspell-addon.yaml`, directly on the joex machine (or via
|
||||
`systemd-nspawn`). The machine running joex must then provide all
|
||||
necessary dependencies and it must be compatible to run the addon. It
|
||||
may be useful especially for personal addons.
|
||||
|
||||
|
||||
## nix flake
|
||||
|
||||
Using [nix](https://nixos.org) with
|
||||
[flakes](https://nixos.wiki/wiki/Flakes) enabled, is the recommended
|
||||
approach. It is very flexible and reproducible while sharing most
|
||||
dependencies (in contrast to docker where each image contains the same
|
||||
packages again and again).
|
||||
|
||||
Docspell runs `nix build` to build the addon and then executes the
|
||||
file produced to `$out/bin`.
|
||||
|
||||
|
||||
## docker
|
||||
|
||||
For docker it is recommended to provide pre-build images. Docspell can
|
||||
build images from provided `Dockerfile`, but for larger images it
|
||||
might be better to do this apriori.
|
||||
|
||||
Docspell will run the addon using `docker run …` passing it only the
|
||||
user-input file as argument. Thus the image must define an appropriate
|
||||
`ENTRYPOINT`.
|
||||
|
||||
# Examples
|
||||
## Minimal Addon
|
||||
|
||||
The steps below create a minimal addon:
|
||||
|
||||
1. Create a bash script `addon.sh` with this content:
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
echo "Hello world!"
|
||||
```
|
||||
2. Make it executable:
|
||||
```bash
|
||||
chmod +x addon.sh
|
||||
```
|
||||
3. Create a yaml file `docspell-addon.yaml` with this content:
|
||||
|
||||
```yaml
|
||||
meta:
|
||||
name: "minimal-addon"
|
||||
version: "0.1.0"
|
||||
triggers:
|
||||
- existing-item
|
||||
- scheduled
|
||||
runner:
|
||||
trivial:
|
||||
enable: true
|
||||
exec: addon.sh
|
||||
```
|
||||
4. Create a zip file containing these two files:
|
||||
```bash
|
||||
zip addon.zip docspell-addon.yaml addon.sh
|
||||
```
|
||||
|
||||
The addon is now ready. Make it available via an url (use some file
|
||||
sharing tool, upload it somewhere etc) and then it can be installed
|
||||
and run.
|
||||
|
||||
## Non-Minimal Addon
|
||||
|
||||
The minimal example above is good to see what is required, but it is
|
||||
not very useful…. Please see this post about the [audio file
|
||||
addon](@/blog/2022-05-16_audio_file_addon.md) that walks through a
|
||||
more useful addon.
|
||||
|
||||
# Misc
|
||||
|
||||
## Advantages of "pure" addons
|
||||
|
||||
Although the output structure is not set in stone, it is recommended
|
||||
to use this in contrast to directly changing state via `dsc`.
|
||||
|
||||
- outputs of all addons are collected and only applied if all were
|
||||
successful; in contrast side effects are always applied even if the
|
||||
addon fails shortly after
|
||||
- since addons are executed as joex tasks, their result can be send as
|
||||
events to another http server for further processing.
|
||||
- addons can run in an isolated environment without network (no data
|
||||
can go out)
|
||||
|
||||
## Use addons in other addons?
|
||||
|
||||
This can be achieved very conveniently by using `nix`. If addons are
|
||||
defined as a nik flake, they can be easily consumed by each other.
|
@ -82,6 +82,7 @@ template = "docs.html"
|
||||
- zip
|
||||
- [eml](https://en.wikipedia.org/wiki/Email#Filename_extensions)
|
||||
(e-mail files in plain text MIME)
|
||||
- Extend Docspell via [addons](@/docs/addons/basics.md)
|
||||
- Tooling:
|
||||
- [Command Line Interface](@/docs/tools/cli.md) allowing to upload
|
||||
files, watch folders and many more!
|
||||
|