Skip to content

Kosztyk/PrinterManager

Repository files navigation

favicon

Printamos Email2Print

Printamos Email2Print is a self-hosted printing gateway that combines a web interface, CUPS integration, email-to-print workflows, user management, API access, and optional antivirus scanning before printing.

What this application is for

This application is designed for environments where you want centralized and controlled printing from a browser or from email attachments.

Typical use cases:

  • upload a file in a web interface and print it to a configured CUPS printer
  • send attachments by email and have them printed automatically
  • control which senders are allowed to use Email2Print
  • expose printing functionality through an internal API
  • manage users from the web UI
  • optionally scan uploaded files and email attachments with ClamAV before printing
  • route printing through a separate CUPS server instead of the local container

Main features

  • Web UI for file upload and printing
  • Email2Print worker for processing email attachments
  • CUPS integration through a configured remote or local CUPS server
  • User authentication and session handling
  • Existing users management page
  • API page for programmatic usage
  • Optional ClamAV scanning before printing
  • Persistent app data and configuration directories
  • PostgreSQL backend support
Screenshot 2026-03-18 at 12 24 03

Requirements

Before installing, make sure you have:

  • Docker and Docker Compose installed
  • A reachable CUPS server
  • A PostgreSQL database
  • Optional: a ClamAV REST API endpoint or container if you want antivirus scanning
  • Optional: an IMAP/SMTP-capable mailbox for Email2Print workflows

Example deployment layout

In this example:

  • the application runs on 192.168.68.xxx:8097
  • the CUPS server is available at 192.168.68.yyy:631
  • PostgreSQL runs in Docker on the same Compose stack
  • pgAdmin runs in Docker for database administration
  • ClamAV runs in Docker and exposes an HTTP scan endpoint for the app

Example docker-compose.yml

Start from services: as requested:

services:
  printamos_email2print:
    container_name: printamos-mail2print
    image: kosztyk/printer:postgres
    restart: unless-stopped
    depends_on:
      - postgres
      - clamav
    ports:
      - "192.168.68.xxx:8097:8097"
    environment:
      TZ: "Europe/Bucharest"
      KTOR_PORT: "8097"
      EXTRA_ALLOWED_ORIGINS: "http://192.168.68.xxx:8097"

      # CUPS target used by the app and CUPS Admin redirect
      CUPS_SERVER: "192.168.68.yyy:631"

      # PostgreSQL
      DB_HOST: "postgres"
      DB_PORT: "5432"
      DB_NAME: "printamos"
      DB_USER: "printamos_user"
      DB_PASSWORD: "CHANGE_ME"

      # App URL and secrets
      APP_BASE_URL: "http://192.168.68.xxx:8097"
      APP_ENCRYPTION_KEY: "REPLACE_WITH_A_LONG_RANDOM_HEX_OR_SECRET_VALUE"
      SESSION_SECRET: "REPLACE_WITH_A_LONG_RANDOM_SECRET_VALUE"

      # Optional antivirus scanning
      # To disable ClamAV scanning entirely, set CLAMAV_URL to an empty string
      CLAMAV_URL: "http://clamav:3000/api/v1/scan"
      CLAMAV_TIMEOUT_SECONDS: "30"
      CLAMAV_REJECT_ON_ERROR: "true"
      CLAMAV_FORM_FIELD: "FILES"

      # Optional email worker settings
      # ENABLE_EMAIL2PRINT: "true"
      # IMAP_HOST: "mail.example.com"
      # IMAP_PORT: "993"
      # IMAP_USER: "printer@example.com"
      # IMAP_PASSWORD: "CHANGE_ME"
      # IMAP_USE_SSL: "true"
      # SMTP_HOST: "mail.example.com"
      # SMTP_PORT: "587"
      # SMTP_USER: "printer@example.com"
      # SMTP_PASSWORD: "CHANGE_ME"

    volumes:
      - ./cups/client.conf:/etc/cups/client.conf:ro
      - ./data:/app/data
      - ./config:/app/config

    tmpfs:
      - /run
      - /tmp

  postgres:
    container_name: printamos-postgres
    image: postgres:16
    restart: unless-stopped
    environment:
      POSTGRES_DB: "printamos"
      POSTGRES_USER: "printamos_user"
      POSTGRES_PASSWORD: "CHANGE_ME"
      TZ: "Europe/Bucharest"
    volumes:
      - ./postgres-data:/var/lib/postgresql/data
    ports:
      - "127.0.0.1:5432:5432"

  pgadmin:
    container_name: printamos-pgadmin
    image: dpage/pgadmin4:latest
    restart: unless-stopped
    depends_on:
      - postgres
    environment:
      PGADMIN_DEFAULT_EMAIL: "admin@example.com"
      PGADMIN_DEFAULT_PASSWORD: "CHANGE_ME"
      PGADMIN_LISTEN_PORT: "8081"
    volumes:
      - ./pgadmin-data:/var/lib/pgadmin
    ports:
      - "192.168.68.xxx:8081:8081"

  clamav:
    container_name: printamos-clamav
    image: your-clamav-rest-image:latest
    restart: unless-stopped
    environment:
      TZ: "Europe/Bucharest"
    ports:
      - "192.168.68.xxx:3000:3000"
    volumes:
      - ./clamav-data:/var/lib/clamav

About the ClamAV service

ClamAV support is optional.

You can run the application in two modes:

1. Without ClamAV

If you do not want antivirus scanning:

  • remove the clamav service from the Compose file
  • remove the depends_on reference to clamav
  • set CLAMAV_URL to an empty string, or omit all CLAMAV_* variables

Example:

CLAMAV_URL: ""

In that mode:

  • uploaded files are printed without antivirus scanning
  • email attachments are printed without antivirus scanning

2. With ClamAV enabled

If you want malware scanning before printing:

  • keep the clamav service
  • set CLAMAV_URL
  • keep the CLAMAV_* variables configured

In that mode:

  • uploaded files are scanned before printing
  • email attachments are scanned before printing
  • infected files are rejected
  • clean files are allowed to continue

Notes about the ClamAV container

The application expects an HTTP endpoint compatible with:

/api/v1/scan

and a multipart upload field named:

FILES

Because ClamAV REST containers vary, replace:

image: your-clamav-rest-image:latest

with the image you actually want to use in your environment, as long as it exposes a compatible HTTP scan API.

Example cups/client.conf

If your app should use a remote CUPS server, create ./cups/client.conf with content similar to:

ServerName 192.168.68.yyy:631
Encryption IfRequested

How to install

1. Prepare directories

Create a working directory and subfolders:

mkdir -p printamos/cups printamos/data printamos/config printamos/postgres-data printamos/pgadmin-data printamos/clamav-data
cd printamos

2. Create the CUPS client configuration

Create cups/client.conf:

cat > cups/client.conf <<'EOF'
ServerName 192.168.68.yyy:631
Encryption IfRequested
EOF

3. Create the Compose file

Save the example above as docker-compose.yml and adapt:

  • IP addresses
  • database credentials
  • application secrets
  • ClamAV container image if you want antivirus scanning
  • mail settings if Email2Print is enabled

4. Start the application stack

docker compose up -d

5. Check logs

docker compose logs -f

If needed, inspect individual services:

docker compose logs -f printamos_email2print
docker compose logs -f postgres
docker compose logs -f pgadmin
docker compose logs -f clamav

First login and basic use

After startup, open the application in your browser:

http://192.168.68.xxx:8097

Optional:

  • pgAdmin: http://192.168.68.xxx:8081

From the main app you can:

  • sign in to the app
  • upload a document and print it
  • open the Users page and manage users
  • access the API page if enabled
  • open CUPS Admin from the menu
  • configure or use Email2Print if your mailbox settings are present

How to use the web upload flow

  1. Open the main web UI.
  2. Choose a file to upload.
  3. Select the target printer and print options if exposed by the UI.
  4. Submit the print job.
  5. If ClamAV scanning is enabled, the file is scanned before printing.
  6. If the file is clean, printing continues.
  7. If malware is detected, the job is rejected.

How to use Email2Print

  1. Configure the mailbox environment variables used by the worker.
  2. Allow the sender address or use the application logic you configured for allowed senders.
  3. Send an email with one or more supported attachments.
  4. The worker fetches the email, scans the attachments if ClamAV is enabled, and prints only approved attachments.

Antivirus scanning behavior

When ClamAV scanning is enabled:

  • uploaded files are scanned before printing
  • email attachments are scanned before printing
  • infected files are rejected
  • clean files are allowed
  • if CLAMAV_REJECT_ON_ERROR=true, files are rejected when the antivirus service cannot be reached or returns an invalid result

Recommended settings:

CLAMAV_URL: "http://clamav:3000/api/v1/scan"
CLAMAV_TIMEOUT_SECONDS: "30"
CLAMAV_REJECT_ON_ERROR: "true"
CLAMAV_FORM_FIELD: "FILES"

If you do not want ClamAV scanning:

CLAMAV_URL: ""

Supported infrastructure overview

This app is typically used with:

  • a remote CUPS server
  • a PostgreSQL database
  • optional ClamAV REST API
  • optional mail account for Email2Print

Security notes

For production or shared-network use:

  • replace all placeholder secrets with strong random values
  • do not expose the app publicly without a reverse proxy and authentication controls
  • keep database credentials out of version control
  • use HTTPS when publishing the app externally
  • restrict allowed senders for Email2Print
  • keep CLAMAV_REJECT_ON_ERROR=true if you want fail-closed malware protection
  • review CUPS access rules on the CUPS host

Updating the containers

Pull the latest images and recreate:

docker compose pull
docker compose up -d

Or rebuild if you are using a custom local app image:

docker compose build --no-cache
docker compose up -d

Troubleshooting

Check application logs

docker compose logs -f printamos_email2print

Check PostgreSQL logs

docker compose logs -f postgres

Check pgAdmin logs

docker compose logs -f pgadmin

Check ClamAV logs

docker compose logs -f clamav

Check ClamAV API manually

curl -F 'FILES=@/path/to/file.pdf' http://192.168.68.xxx:3000/api/v1/scan

Check CUPS connectivity

From the Docker host, confirm that the remote CUPS server is reachable:

curl http://192.168.68.yyy:631

Common issues

  • CUPS Admin opens localhost
    • make sure the application is configured to use CUPS_SERVER
  • all files are rejected by antivirus
    • verify CLAMAV_FORM_FIELD matches the API expectation, for your service this should be FILES
  • clean files are not printing
    • check application logs and the ClamAV API response
  • email attachments are not printing
    • verify IMAP settings, sender restrictions, and worker logs
  • the app should run without ClamAV
    • set CLAMAV_URL to an empty string and remove the optional ClamAV service

Credits

This application uses and builds on code from:

About

Printamos Email2Print is a self-hosted printing gateway that combines a web interface, CUPS integration, email-to-print workflows, user management, API access, and optional antivirus scanning before printing.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors