I collect all my paperwork in paperless-ngx in order to flexibilize my workflow and have all my documents with me (digitally) all the time. Upload can be done with a web frontend, but there’s friction for me when I have to open the webpage and upload a document I’ve just downloaded.
Brief research pointed at the problem being already solved by some applications. The sort of solution I was looking for was a program that checked a directory for files and uploaded them into my paperless automatically. This would be a polling solution, and polling always comes with the drawback that you have to wait for the poll interval until something happens in the worst case.
Then, someone had implemented the same with Linux’ kernel’s inotify. This API allows to watch a directory or file for certain events: you can put a watch and be called when someone has closed a file handle. Now, you don’t repeatedly check as will polling, but you’re being called.
It felt a bit like overhead to run a program all the time that 99% of time does nothing and only rarely (in a computer’s view) actually performs some sort of action. But you need to run in order to watch the directory.
systemd to the rescue
Turns out - and this is my TIL for today - you can solve it elegantly. Just like a systemd timer, that runs systemd services in a given fixed schedule, you can create a systemd path unit that observes a directory and triggers a systemd service when certain events occur.
I have now created this path unit:
[Unit]
Description=Watch ~/paperless-upload for documents
[Path]
PathModified=%h/paperless-upload
DirectoryNotEmpty=%h/paperless-upload
Unit=paperless-upload.service
[Install]
WantedBy=default.target
This watches the paperless-upload directory in my homedir for changes and triggers paperless-upload.service. That service in return just executes a python program with certain environment variables:
[Unit]
Description=Upload documents to Paperless-ngx
[Service]
Type=oneshot
EnvironmentFile=-%h/.config/paperless-upload.env
ExecStart=%h/bin/paperless-upload.py
Restart=on-failure
RestartSec=30s
Environment="PAPERLESS_URL=https://my.paperless.instance.url"
Environment="PAPERLESS_UPLOAD_DIR=%h/paperless-upload"
Environment="PAPERLESS_ARCHIVE_DIR=%h/.local/share/paperless-uploaded"
LoadCredential=paperless-api-key:%h/.config/paperless-upload-api-key
Voila! I can observe the directory, have almost no overhead of running a program all the time, while still getting the problem solved. Nice!

