🖨️ A self-hosted printing server webUI with multi-user support
  • Go 75.5%
  • HTML 20.1%
  • CSS 3.2%
  • Dockerfile 0.7%
  • Shell 0.5%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-09-09 14:35:38 +03:00
locales Fixed printing options to reflect reality, added printing option admin lock per option 2026-09-09 14:35:38 +03:00
scrshots Added printer options lock, renewed screenshots 2026-09-08 11:34:58 +03:00
static Fixed printing options to reflect reality, added printing option admin lock per option 2026-09-09 14:35:38 +03:00
templates Fixed printing options to reflect reality, added printing option admin lock per option 2026-09-09 14:35:38 +03:00
.dockerignore Initial commit: WebPrint — Go + HTMX printing server 2026-08-21 06:17:24 +03:00
.env.example Added Autologin 2026-09-07 17:18:23 +03:00
.gitattributes Added LICENSE 2026-08-21 10:02:24 +03:00
.gitignore updated gitignore 2026-08-31 14:41:35 +03:00
accents.go Fixed UI color settings 2026-09-04 22:26:19 +03:00
access.go Implement printer access control, page-based quotas, and debug logging 2026-09-02 22:24:16 +03:00
audit.go Added input sanitization, separate admin panel, auto-fetching printers, csrf token, fixed login, added global rate limiting... 2026-08-26 23:57:06 +03:00
auth.go Added Autologin 2026-09-07 17:18:23 +03:00
cleanup.go Added input sanitization, separate admin panel, auto-fetching printers, csrf token, fixed login, added global rate limiting... 2026-08-26 23:57:06 +03:00
config.go Added Autologin 2026-09-07 17:18:23 +03:00
csrf.go Added input sanitization, separate admin panel, auto-fetching printers, csrf token, fixed login, added global rate limiting... 2026-08-26 23:57:06 +03:00
cups.go Fixed printing options to reflect reality, added printing option admin lock per option 2026-09-09 14:35:38 +03:00
cupsd.conf Added Autologin 2026-09-07 17:18:23 +03:00
database.go Fixed UI color settings 2026-09-04 22:26:19 +03:00
docker-compose.yml Changed apprise image for the 5x smaller linuxserver image. 2026-09-02 04:07:42 +03:00
Dockerfile Added API and healthcheck 2026-09-03 16:16:19 +03:00
entrypoint.sh Added Autologin 2026-09-07 17:18:23 +03:00
go.mod Added support for OIDC registration + authentification 2026-09-04 11:18:23 +03:00
go.sum Added support for OIDC registration + authentification 2026-09-04 11:18:23 +03:00
handlers_admin.go Fixed UI color settings 2026-09-04 22:26:19 +03:00
handlers_api.go Added API and healthcheck 2026-09-03 16:16:19 +03:00
handlers_auth.go Added Autologin 2026-09-07 17:18:23 +03:00
handlers_notifications.go Added API and healthcheck 2026-09-03 16:16:19 +03:00
handlers_oidc.go Added Autologin 2026-09-07 17:18:23 +03:00
handlers_print.go Fixed printing options to reflect reality, added printing option admin lock per option 2026-09-09 14:35:38 +03:00
handlers_printers.go Fixed printing options to reflect reality, added printing option admin lock per option 2026-09-09 14:35:38 +03:00
handlers_settings.go Fixed UI color settings 2026-09-04 22:26:19 +03:00
i18n.go Implement printer access control, page-based quotas, and debug logging 2026-09-02 22:24:16 +03:00
LICENSE Added LICENSE 2026-08-21 10:02:24 +03:00
main.go Fixed printing options to reflect reality, added printing option admin lock per option 2026-09-09 14:35:38 +03:00
middleware.go Added Autologin 2026-09-07 17:18:23 +03:00
models.go Fixed printing options to reflect reality, added printing option admin lock per option 2026-09-09 14:35:38 +03:00
notify.go Added Reverse proxy setup chapter in README.md 2026-08-31 23:14:29 +03:00
print_defaults.go Fixed UI color settings 2026-09-04 22:26:19 +03:00
README.md Added printer options lock, renewed screenshots 2026-09-08 12:42:23 +03:00
sanitize.go Added input sanitization, separate admin panel, auto-fetching printers, csrf token, fixed login, added global rate limiting... 2026-08-26 23:57:06 +03:00
screenshot-mobile-1.jpg Added 3 mobile screenshots 2026-08-21 08:43:30 +03:00
screenshot-mobile-2.jpg Added 3 mobile screenshots 2026-08-21 08:43:30 +03:00
screenshot-mobile-3.jpg Added 3 mobile screenshots 2026-08-21 08:43:30 +03:00
webprint Fixed printing options to reflect reality, added printing option admin lock per option 2026-09-09 14:35:38 +03:00

WebPrint

WebPrint

Your printers. On the web.

Self-hosted print server webUI · AGPLv3 · Docker

🖨️ WebPrint

A lightweight, self-hosted printing server WebUI with multi-user support, built with Go + HTMX powered by CUPS. Designed to be simple to deploy, configure, and use.

✨ Features

  • Multi-user support - registration with admin approval workflow
  • Print options - copies, duplex, color mode, orientation
  • Print history - track all printed documents
  • Admin panel - approve/reject users, promote/demote admins
  • Healthcheck - get your container's health
  • API - call the app to get current stats
  • OIDC - register and authenticate via OIDC providers
  • Multi-language UI - English, French, German, Finnish
  • Runtime configuration - change settings via environment variables, no rebuilds needed
  • Tiny footprint - ~40MB Docker image (and ~300MB for CUPS)
  • CUPS integration - leverages the proven CUPS printing system
  • Secure - JWT auth with secure cookies, HTTPS-ready

🖼️ Screenshots

Login page on mobile:

The login page with its login and regestration forms

Print page on desktop with the upload button and options:

The print page where to upload the documents includes printing options

The admin page:

The admin page with the user management

The printers page:

The printers page is admin only, there you can lock options and chose who sees which printer

The settings page:

The settings page very every user, where you can reset you password, select default printing options and add notifications

🚀 Quick Start

🐳 Pre-built Docker Image

Multi-arch image (amd64, arm64v8) available from the self-hosted registry:

image: https://forged.hel.alfredolin.eu/webprint:latest

Just use the docker-compose.yml file, grab the cups config file, prepare your .env file and from the folder do:

docker compose up

Build

# Clone the repo
git clone https://forgejo.hel.alfredolin.eu/Alfredolin/WebPrint.git
cd WebPrint

# Build and run
docker compose up -d --build

# Access the UI
# http://localhost:3001
# Default login: admin / (set ADMIN_PASS in docker-compose.yml)

⚙️ Configuration

All configuration is done via environment variables in .env, most important variables are:

Variable Default Description
JWT_SECRET "" Secret for JWT token signing. Default is empty, WebPrint won't start if you don't change it.
ADMIN_USER admin Default admin username
ADMIN_PASS change-this-password Default admin password
HOST_URL "" https:// enables secure cookies, a path suffix (e.g. /print) enables subpath deployment.
OIDC_ISSUER "" Optional, your OIDC provider's URL. If empty, OIDC options will not be displayed.
OIDC_CLIENT_ID "" Your OIDC client ID
OIDC_CLIENT_SECRET "" Your OIDC client secret
OIDC_NAME "SSO" An arbitrary name to your OIDC provider
AUTOLOGIN_USER "" Automatically logs in to a pre-set user. User should be configured beforehand and not be an admin account.

No rebuild needed — change any variable and just restart the container.

API use example

You can use the API for example to display the status on Homepage (with docker socket access) by adding this labels in the docker compose:

    labels:
      - homepage.group=YourGroup
      - homepage.name=WebPrint
      - homepage.icon=https://forgejo.hel.alfredolin.eu/Alfredolin/WebPrint/raw/branch/phase7-dev/static/logo-dark.svg
      - homepage.href=YourHostUrl
      - homepage.description=Web UI for printers
      - homepage.widgets[0].type=customapi
      - homepage.widgets[0].url=YourHostUrl/api/stats
      - homepage.widgets[0].refreshInterval=10000 # optional - in milliseconds, defaults to 10s
      - homepage.widgets[0].headers.Authorization=Bearer YourApiTokenGeneratedInTheSettingsPage
      - homepage.widgets[0].method=GET # optional, e.g. POST
      - homepage.widgets[0].mappings[0].field=pagesToday
      - homepage.widgets[0].mappings[0].label=Printed 📄
      - homepage.widgets[0].mappings[0].format=number
      - homepage.widgets[0].mappings[1].field=pendingUsers
      - homepage.widgets[0].mappings[1].label=Pending 🧑🏽
      - homepage.widgets[0].mappings[1].format=number
      - homepage.widgets[0].mappings[2].field=printers
      - homepage.widgets[0].mappings[2].label=🖨️
      - homepage.widgets[0].mappings[2].format=number

🖨️ Printer Setup

Make sure your printer is configured in CUPS. You can use the CUPS web interface at http://localhost:631 or the command line:

Adding a Network Printer

  1. Find your printer's IP address (check your router's DHCP table or the printer's built-in menu)

  2. Enter the CUPS container:

    docker compose exec cups bash
    
  3. Remove existing printer (if reconfiguring):

    lpadmin -x YourPrinterName 2>/dev/null || true
    
  4. Add the printer using one of these protocols:

    IPP (recommended for modern printers):

    lpadmin -p YourPrinterName -E -v "ipp://192.168.1.50/ipp/print" -m everywhere
    

    Socket / JetDirect (HP and others):

    lpadmin -p YourPrinterName -E -v "socket://192.168.1.50:9100" -m everywhere
    

    LPD (older printers):

    lpadmin -p YourPrinterName -E -v "lpd://192.168.1.50/queue" -m everywhere
    

    Replace 192.168.1.50 with your printer's actual IP address. The -m everywhere flag tells CUPS to auto-detect capabilities via IPP. The -E flag tells CUPS to enable the printer and accept jobs.

  5. Set as system default (optional):

    lpoptions -d YourPrinterName
    
  6. Verify the printer is working:

    lpstat -p YourPrinterName -d
    lpoptions -p YourPrinterName -l
    
  7. Sync from WebPrint:

    Either automatically on container start or go to Admin → Printers and click "Sync with CUPS" to import the printer into WebPrint.

🔧 Using Host CUPS (Without the Containerized CUPS Service)

If you already have CUPS installed on your host system, you can skip the containerized cups service and mount the host socket directly.

1. Check your socket permissions

ls -la /run/cups/cups.sock

If permissions are srw-rw-rw- (666) → no LP_GID needed If permissions are srw-rw---- (660) → continue to step 2

2. Find your host's lp group GID

getent group lp
# lp:x:7:

3. Configure WebPrint

Set LP_GID in your .env to match the GID above, and remove the cups service from your docker-compose.yml:

LP_GID=7

📄 Supported File Types

PDF, PNG, JPEG, TIFF, BMP, TXT (or at least in the theory. It actually depends on CUPS and your printer, this is still being tested)

🌍 Reverse Proxy Setup

Set HOST_URL to the public URL users type in their browser:

Deployment HOST_URL Apache
Subdomain https://printer.site.eu ProxyPass / http://localhost:3001/
Subpath https://site.eu/print ProxyPass /print http://localhost:3001/print
Local/dev http://10.0.0.7:3001 no proxy needed

Apache example with subdomain:

<VirtualHost *:80 [::]:80>
ServerName printer.domain.com

RewriteEngine On

RewriteCond %{SERVER_NAME} =printer.domain.com
RewriteCond %{HTTP_HOST} =printer.domain.com
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>


<VirtualHost *:443 [::]:443>
ServerName printer.domain.com

ProxyPreserveHost On

ProxyPass / http://localhost:3001/
ProxyPassReverse / http://localhost:3001/

#managed by e.g. certbot
Include /etc/letsencrypt/options-ssl-apache.conf
SSLCertificateFile /etc/letsencrypt/live/printer.domain.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/printer.domain.com/privkey.pem
</VirtualHost>

Nginx example with subpath (no trailing slash):

location /printer {
        proxy_pass http://127.0.0.1:3311/printer;
}

Contact

Please open issues in Forgejo or come ask questions on matrix in the space: #webprint:matrix.alfredolin.eu.

🌐 Languages

English, Français, Deutsch, Suomi

Add a new language by creating locales/xx.json and adding the code to the supported list in i18n.go.

🙏 Credits

📝 License

This project is licensed under the GNU Affero General Public License v3.0 (AGPLv3). See LICENSE file for details.