Author: Dr. Henning Dickten (@hensing)
A lightweight, secure, and Dockerized bridge designed for Raspberry Pi and generic Linux servers. It provides a Samba (SMB) share for hardware document scanners.
Once a scan is saved to the share, this container detects the completed file, uploads it directly to Paperless-ngx via API, and optionally archives or cleans up the local file.
Supports both single-user (simple env var config) and multi-user mode (one share and API key per person).
Single-user mode
graph LR
A[π¨οΈ Hardware Scanner] -- SMB Port 445 --> B(π /data/inbox)
B --> C[π³ Container Watcher]
C -- API Token --> D[π Paperless-NGX]
C -- Move/Delete --> E(π¦ /data/archive)
Multi-user mode
graph TD
SCAN[π¨οΈ Hardware Scanner]
subgraph alice [Alice]
direction TB
AI(π alice_scans)
AW[π³ Watcher]
AA(π¦ archive)
AI --> AW --> AA
end
subgraph bob [Bob]
direction TB
BI(π bob_docs)
BW[π³ Watcher]
BA(π¦ archive)
BI --> BW --> BA
end
PL[π Paperless-NGX]
SCAN -- SMB: alice_scans --> AI
SCAN -- SMB: bob_docs --> BI
AW -- Alice's API Key --> PL
BW -- Bob's API Key --> PL
- π Multi-Arch Support: Optimized for
linux/amd64andlinux/arm64(Raspberry Pi). - π₯ Multi-User Support: Each user gets their own Samba share, SMB credentials, and Paperless-NGX API key.
- π Secure by Default: Binds to privileged SMB port 445 but drops privileges to run as a non-root user (configurable
PUID/PGID). - π Samba Integration: Built-in SMB server compliant with modern scanners.
- β‘ Smart Detection: Uses
inotifyto detectclose_writeevents (prevents processing incomplete files). - π·οΈ Auto-Tagging: Automatically apply tags to uploaded documents β configurable per user in multi-user mode.
- π§Ή Auto-Cleanup: Options to archive or delete files after successful upload.
- π‘οΈ SSL Support: Full support for HTTPS and self-signed certificates.
This tool works best as part of a modern document management ecosystem. We highly recommend checking out:
- Paperless-ngx Documentation: The official documentation for the backend system.
- Paperless-GPT: An amazing tool to add AI-powered analysis, tagging, and renaming to your documents after they have been uploaded.
Create your .env file based on the example:
cp .env.example .envMinimal .env example:
PAPERLESS_URL=https://paperless.local:8000
PAPERLESS_API_KEY=your-super-secret-token
SMB_USER=scanner
SMB_PASSWORD=scan123
PUID=1000
PGID=1000Create a docker-compose.yml (or use the one provided):
services:
scan-to-paperless:
image: ghcr.io/hensing/scan-to-paperless:latest
container_name: scan-to-paperless
restart: unless-stopped
ports:
- "445:445"
env_file:
- .env
volumes:
- ./data:/data
- ./config:/config:roStart the container:
docker compose up -dConfigure your physical scanner (Brother, Canon, HP, etc.) with these settings:
- Protocol: SMB / CIFS
- Server: IP of your Docker host
- Port: 445
- Share Name:
scanner(default) - Username:
scanner(default) - Password:
scan123(default)
Multi-user mode activates automatically when ./config/users.conf exists. Each user gets an isolated Samba share and uploads to Paperless with their own API key.
mkdir -p config
cp config/users.conf.example config/users.confEdit config/users.conf β one user per line, colon-separated:
# smb_user:smb_password:smb_share:paperless_api_key:paperless_tags(optional)
alice:secretpassword1:alice_scans:paperless-api-token-alice:scanned,alice
bob:secretpassword2:bob_docs:paperless-api-token-bob:scanned,bob
Only PAPERLESS_URL and optional processing settings are needed. The SMB_* and PAPERLESS_API_KEY variables are ignored in multi-user mode.
PAPERLESS_URL=https://paperless.local:8000
PUID=1000
PGID=1000docker compose up -dEach user's files land in /data/<smb_user>/inbox and are archived to /data/<smb_user>/archive.
Upgrading from single-user: No changes required. Single-user mode is auto-detected when
users.confis absent.
| Variable | Description | Default | Required |
|---|---|---|---|
PAPERLESS_URL |
Full URL to Paperless-NGX (e.g., http://192.168.1.5:8000) |
- | β |
PAPERLESS_VERIFY_SSL |
Verify SSL certificates (false for self-signed) |
true |
β |
WHITELIST |
Allowed file extensions | pdf,jpg,png,bmp |
β |
ARCHIVE |
true = Move to archive folder, false = Delete after upload |
true |
β |
UPLOAD_TIMEOUT |
Max time (seconds) for API upload | 30 |
β |
SCAN_SETTLE_TIME |
Seconds to wait after detection before upload | 5 |
β |
PUID |
User ID to run as (matches host user) | 1000 |
β |
PGID |
Group ID to run as (matches host group) | 1000 |
β |
Ignored when config/users.conf is present.
| Variable | Description | Default |
|---|---|---|
PAPERLESS_API_KEY |
API Token from Paperless Settings β API Tokens | - |
PAPERLESS_TAGS |
Comma-separated tags to apply | "" |
SMB_USER |
Username for the scanner to login | scanner |
SMB_PASSWORD |
Password for the scanner | scan123 |
SMB_SHARE |
Name of the SMB share | scanner |
| Field | Description | Required |
|---|---|---|
smb_user |
Linux/SMB username β unique, no spaces | β |
smb_password |
Password for the SMB share | β |
smb_share |
Share name visible to the scanner | β |
paperless_api_key |
API Token from Paperless Settings β API Tokens | β |
paperless_tags |
Comma-separated tags (optional, can be empty) | β |
Note on Permissions: This container starts as root to fix volume permissions and bind port 445, then immediately drops privileges to the user specified in
PUID/PGID.
Single-user mode
/data
βββ inbox/ <-- Scanner saves files here (monitored)
βββ archive/ <-- Processed files are moved here (if ARCHIVE=true)
Multi-user mode
/data
βββ alice/
β βββ inbox/ <-- alice's Samba share (monitored)
β βββ archive/ <-- alice's processed files
βββ bob/
βββ inbox/ <-- bob's Samba share (monitored)
βββ archive/ <-- bob's processed files
π "Upload failed" in logs
- Check if
PAPERLESS_URLis reachable from inside the container. - Verify the API key (
PAPERLESS_API_KEYor the key inusers.conf). - If using a self-signed cert, try setting
PAPERLESS_VERIFY_SSL=false. - Increase
SCAN_SETTLE_TIME. Some network scanners report "finished" before the file is fully flushed to disk.
π« Scanner cannot connect (Network Error)
- Ensure port 445 is not blocked by a firewall on the host.
- Windows/Mac hosts might use port 445 for their own sharing service. Ensure port 445 is free or use a different external port (note: many scanners hardcode 445).
π File is ignored
- Check the
WHITELISTin.env. - The container waits for the
close_writeevent. Ensure the scanner finishes writing the file completely.
π₯ Multi-user: user cannot connect
- Verify the share name in
users.confmatches what the scanner is configured with. - Check the container logs for
[INIT] Configured N user(s).β if N is 0, the config file has a parsing issue. - Ensure all four required fields (
smb_user:smb_password:smb_share:paperless_api_key) are present.
Contributions, improvements, and bug fixes are welcome!
- Fork the project.
- Create your feature branch (
git checkout -b feature/AmazingFeature). - Commit your changes (
git commit -m 'Add some AmazingFeature'). - Push to the branch (
git push origin feature/AmazingFeature). - Open a Pull Request.
Note to Forks: Please ensure that the original author credit remains intact in the license and documentation when forking or redistributing this project.
Build the image locally:
docker build -t scan-to-paperless .Distributed under the MIT License. See LICENSE for more information.