Independent fork of sbs20/scanservjs. Added features needed for a homelab environment that are outside the scope of upstream. All credit for the original scanner UI goes to Sam Strachan and contributors.
| Feature | Description |
|---|---|
| OIDC authentication | Login via any OpenID Connect provider (Pocket-ID, Authentik, Keycloak, etc.). Fully env-configured — no code changes needed per provider. |
| Per-user persistent settings | Scan parameters saved server-side and restored on any device at next login. |
| Ephemeral downloads | Guests and users without an assigned output directory get an automatic browser download instead. File exists only for the duration of the session. |
| Admin panel | Assign output directories to users. Access controlled by OIDC group membership. |
| Quick scan button | One-click single-page scan using current settings — no batch dialog. |
| Scan lock | Prevents concurrent scans from different sessions. Same session can batch uninterrupted. Auto-releases after 5 minutes if abandoned. |
This fork is Docker-only. Images are published to GHCR on every push to master and on version tags.
ghcr.io/tinkermesomething/scanservjs-plus:latest
ghcr.io/tinkermesomething/scanservjs-plus:v1.0.0
services:
scanservjs:
image: ghcr.io/tinkermesomething/scanservjs-plus:latest
restart: unless-stopped
ports:
- "8080:8080"
volumes:
- /var/run/dbus:/var/run/dbus
- scanservjs-data:/var/lib/scanservjs
privileged: true # required for USB scanner access
env_file: .env
volumes:
scanservjs-data:# ── Scanner ──────────────────────────────────────────────────────────────────
# Manually specify network scanners if not auto-discovered
# DEVICES=net:192.168.1.10:airscan:e0:My Scanner
# ── Output directories ────────────────────────────────────────────────────────
# Admin-assigned mount points available for logged-in users.
# Format: "Label|/path;Label2|/path2"
# OUTPUT_DIRECTORIES=Family|/mnt/nas/family;Archive|/mnt/nas/archive
# ── OIDC authentication ───────────────────────────────────────────────────────
OIDC_ENABLED=true
OIDC_ISSUER=https://your-pocket-id.example.com
OIDC_CLIENT_ID=scanservjs
OIDC_CLIENT_SECRET=your-client-secret
OIDC_REDIRECT_URI=https://scanservjs.example.com/auth/callback
# OIDC_POST_LOGOUT_REDIRECT_URI=https://scanservjs.example.com
# OIDC_SCOPE=openid profile email groups
# OIDC_GROUPS_CLAIM=groups
# Group name (from your OIDC provider) that grants admin access
ADMIN_GROUP=scanservjs-admins
# ── Session ───────────────────────────────────────────────────────────────────
SESSION_SECRET=change-me-to-a-long-random-string
# SESSION_SECURE=true # set false if not behind HTTPS (dev only)- Create a new OIDC client in Pocket-ID
- Set redirect URI to
https://<your-host>/auth/callback - Enable the
groupsclaim in the token - Create a group matching
ADMIN_GROUPand add admin users to it - Copy the client ID and secret into
.env
Leave OIDC_ENABLED unset (or false). The app runs as a single shared user, identical to upstream behaviour. Optional basic auth is still available via the upstream users config.
- Flatbed and ADF scanning
- Output formats: TIF, JPG, PNG, PDF, TXT (Tesseract OCR)
- Filters: auto-level, threshold, blur
- Multipage and batch scanning with collation
- Cropping and paper size presets
- Light and dark mode, responsive UI
- International translations
- Docker images for
amd64,arm64,arm/v7 - OpenAPI documentation at
/api-docs
Requires a SANE-compatible scanner and a Linux host (physical or VM with USB passthrough).
The following docs from the original project apply to the base app:
git tag v1.2.3
git push origin v1.2.3This triggers:
- Docker image pushed to GHCR with
v1.2.3,1.2,1, andlatesttags - GitHub Release created automatically with changelog
- sbs20/scanservjs — original project, copyright 2016-2026 Sam Strachan
- phpsane — the original genesis of scanservjs
- Everyone who contributed translations, bug reports and fixes to the upstream project
