Skip to content

Commit

Permalink
Ubuntu base. Add printer drivers. DSM7
Browse files Browse the repository at this point in the history
  • Loading branch information
ziwork committed Mar 17, 2023
1 parent b359765 commit 10fbb6f
Show file tree
Hide file tree
Showing 9 changed files with 203 additions and 48 deletions.
47 changes: 31 additions & 16 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,21 +1,33 @@
FROM ubuntu:zesty
FROM ubuntu:jammy
LABEL maintainer="[email protected]"
LABEL version="0.3"
LABEL description="AIRPRINT FROM SYNOLOGY DSM 7 (HP, SAMSUNG, ETC)"

# Add repos
RUN echo 'deb http://us.archive.ubuntu.com/ubuntu/ zesty multiverse' >> /etc/apt/sources.list.d/multiverse.list && \
echo 'deb-src http://us.archive.ubuntu.com/ubuntu/ zesty multiverse' >> /etc/apt/sources.list.d/multiverse.list && \
echo 'deb http://us.archive.ubuntu.com/ubuntu/ zesty-updates multiverse' >> /etc/apt/sources.list.d/multiverse.list && \
echo 'deb-src http://us.archive.ubuntu.com/ubuntu/ zesty-updates multiverse' >> /etc/apt/sources.list.d/multiverse.list && \
echo 'deb http://archive.ubuntu.com/ubuntu/ zesty-security multiverse' >> /etc/apt/sources.list.d/multiverse.list && \
echo 'deb-src http://archive.ubuntu.com/ubuntu/ zesty-security multiverse' >> /etc/apt/sources.list.d/multiverse.list

# Install the packages we need. Avahi will be included
RUN apt-get update && apt-get install -y \
locales \
brother-lpr-drivers-extra brother-cups-wrapper-extra \
printer-driver-splix \
printer-driver-gutenprint \
gutenprint-doc \
gutenprint-locales \
libgutenprint9 \
libgutenprint-doc \
ghostscript \
hplip \
cups \
cups-pdf \
cups-client \
cups-filters \
inotify-tools \
python-cups \
&& rm -rf /var/lib/apt/lists/*
avahi-daemon \
avahi-discover \
python3 \
python3-dev \
python3-pip \
python3-cups \
wget \
rsync \
&& rm -rf /var/lib/apt/lists/*

# This will use port 631
EXPOSE 631
Expand All @@ -27,14 +39,17 @@ VOLUME /services
# Add scripts
ADD root /
RUN chmod +x /root/*

#Run Script
CMD ["/root/run_cups.sh"]

# Baked-in config file changes
RUN sed -i 's/Listen localhost:631/Listen 0.0.0.0:631/' /etc/cups/cupsd.conf && \
sed -i 's/Browsing Off/Browsing On/' /etc/cups/cupsd.conf && \
RUN sed -i 's/Listen localhost:631/Listen *:631/' /etc/cups/cupsd.conf && \
sed -i 's/Browsing No/Browsing On/' /etc/cups/cupsd.conf && \
sed -i 's/<Location \/>/<Location \/>\n Allow All/' /etc/cups/cupsd.conf && \
sed -i 's/<Location \/admin>/<Location \/admin>\n Allow All\n Require user @SYSTEM/' /etc/cups/cupsd.conf && \
sed -i 's/<Location \/admin\/conf>/<Location \/admin\/conf>\n Allow All/' /etc/cups/cupsd.conf && \
sed -i 's/.*enable\-dbus=.*/enable\-dbus\=no/' /etc/avahi/avahi-daemon.conf && \
echo "ServerAlias *" >> /etc/cups/cupsd.conf && \
echo "DefaultEncryption Never" >> /etc/cups/cupsd.conf

echo "DefaultEncryption Never" >> /etc/cups/cupsd.conf && \
echo "BrowseWebIF Yes" >> /etc/cups/cupsd.conf
68 changes: 45 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,34 +1,56 @@
# quadportnick/cups-airprint
# znetwork/cups-avahi-airprint [docker-image](https://hub.docker.com/r/znetwork/synology-airprint)

This Ubuntu-based Docker image runs a CUPS instance that is meant as an AirPrint relay for printers that are already on the network but not AirPrint capable. I'm using it on a Synology NAS because the built in server doesn't work properly with my printers. The local Avahi will be utilized for advertising the printers on the network.
# Working on Synology DSM 7 (!!!) and AMD64

This is also an excuse to dip my toes into GitHub/Docker more, so why not? Hopefully someone else finds this useful.
Fork from [quadportnick/docker-cups-airprint](https://github.com/quadportnick/docker-cups-airprint) and [chuckcharlie/docker-cups-airprint](https://github.com/chuckcharlie/docker-cups-airprint)

Update: Clearly I haven't been maintaining this as I no longer use Synology for printing -- Recommend trying this fork instead: https://github.com/chuckcharlie/cups-avahi-airprint
This Ubuntu-based Docker image runs a CUPS instance that is meant as an AirPrint relay for printers that are already on the network but not AirPrint capable.
* `Included drivers HP, Samsung, Canon, Xerox, etc.`

## Prereqs
* No other printers should be shared under Control Panel>External Devices>Printer so that the DSM's CUPS is not running.
* `Enable Bonjour service discovery` needs to be marked under Control Panel>Network>DSM Settings
## Easy run command (use username and password: admin/admin):
```docker run --name airprint --restart unless-stopped --net host znetwork/synology-airprint:latest```

## Configuration
### Before run docker conteiner on DSM7 Synology run this commands in ssh terminal:
* `sudo synosystemctl stop cupsd`
* `sudo synosystemctl stop cups-lpd`
* `sudo synosystemctl stop cups-service-handler`
* `sudo synosystemctl disable cupsd`
* `sudo synosystemctl disable cups-lpd`
* `sudo synosystemctl disable cups-service-handler`

### Add and setup printer:
* CUPS will be configurable at http://[host ip]:631 using the CUPSADMIN/CUPSPASSWORD.
* Make sure you select `Share This Printer` when configuring the printer in CUPS.
* ***After configuring your printer, you need to close the web browser for at least 60 seconds. CUPS will not write the config files until it detects the connection is closed for as long as a minute.***

### After setup and testing AirPrint, you can back run on services. (maybe you will need restart nas)
* `sudo synosystemctl start cupsd`
* `sudo synosystemctl start cups-lpd`
* `sudo synosystemctl start cups-service-handler`
* `sudo synosystemctl anable cupsd`
* `sudo synosystemctl anable cups-lpd`
* `sudo synosystemctl anable cups-service-handler`

## Manual Configuration

### Volumes:
* `/config`: where the persistent printer configs will be stored
* `/services`: where the Avahi service files will be generated

### Variables:
* `CUPSADMIN`: the CUPS admin user you want created
* `CUPSPASSWORD`: the password for the CUPS admin user

### Ports:
* `631`: the TCP port for CUPS must be exposed

## Using
CUPS will be configurable at http://[diskstation]:631 using the CUPSADMIN/CUPSPASSWORD when you do something administrative.

If the `/services` volume isn't mapping to `/etc/avahi/services` then you will have to manually copy the .service files to that path at the command line.

## Notes
* CUPS doesn't write out `printers.conf` immediately when making changes even though they're live in CUPS. Therefore it will take a few moments before the services files update
* Don't stop the container immediately if you intend to have a persistent configuration for this same reason

* `CUPSADMIN`: the CUPS admin user you want created - default is `admin` if unspecified
* `CUPSPASSWORD`: the password for the CUPS admin user - default is `admin` username if unspecified

### Ports/Network:
* Must be run on host network. This is required to support multicasting which is needed for Airprint.


### Example run env command:
```
docker run --name cups --restart unless-stopped --net host\
-v <your services dir>:/services \
-v <your config dir>:/config \
-e CUPSADMIN="<username>" \
-e CUPSPASSWORD="<password>" \
znetwork/cups-avahi-airprint:latest
```
35 changes: 35 additions & 0 deletions buildspec-manifest.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
version: 0.2
#Buildspec file for AWS Codebuild
#Generates multi-arch manifest

env:
secrets-manager:
DOCKERHUB_PASS: "/dockerhub/credentials:password"
DOCKERHUB_USERNAME: "/dockerhub/credentials:username"
phases:
install:
commands:
- yum update -y
pre_build:
commands:
- echo Logging in to DOCKER...
- docker login --username $DOCKERHUB_USERNAME --password $DOCKERHUB_PASS
build:
commands:
- echo Build started on `date`
- echo Building the Docker manifest...
- VERSION=$(cat version.txt)
- export DOCKER_CLI_EXPERIMENTAL=enabled
- docker manifest create $DOCKERHUB_USERNAME/$IMAGE_REPO_NAME:$VERSION $DOCKERHUB_USERNAME/$IMAGE_REPO_NAME:$VERSION-arm64 $DOCKERHUB_USERNAME/$IMAGE_REPO_NAME:$VERSION-amd64
- docker manifest annotate --arch arm64 $DOCKERHUB_USERNAME/$IMAGE_REPO_NAME:$VERSION $DOCKERHUB_USERNAME/$IMAGE_REPO_NAME:$VERSION-arm64
- docker manifest annotate --arch amd64 $DOCKERHUB_USERNAME/$IMAGE_REPO_NAME:$VERSION $DOCKERHUB_USERNAME/$IMAGE_REPO_NAME:$VERSION-amd64
- docker manifest create $DOCKERHUB_USERNAME/$IMAGE_REPO_NAME:latest $DOCKERHUB_USERNAME/$IMAGE_REPO_NAME:$VERSION-arm64 $DOCKERHUB_USERNAME/$IMAGE_REPO_NAME:$VERSION-amd64
- docker manifest annotate --arch arm64 $DOCKERHUB_USERNAME/$IMAGE_REPO_NAME:$VERSION $DOCKERHUB_USERNAME/$IMAGE_REPO_NAME:$VERSION-arm64
- docker manifest annotate --arch amd64 $DOCKERHUB_USERNAME/$IMAGE_REPO_NAME:$VERSION $DOCKERHUB_USERNAME/$IMAGE_REPO_NAME:$VERSION-amd64

post_build:
commands:
- echo Build completed on `date`
- echo Pushing the Docker image...
- docker manifest push $DOCKERHUB_USERNAME/$IMAGE_REPO_NAME:$VERSION
- docker manifest push $DOCKERHUB_USERNAME/$IMAGE_REPO_NAME:latest
26 changes: 26 additions & 0 deletions buildspec.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
version: 0.2
#Generic buildspec file for AWS Codebuild
#Works for both ARM and AMD builds
env:
secrets-manager:
DOCKERHUB_PASS: "/dockerhub/credentials:password"
DOCKERHUB_USERNAME: "/dockerhub/credentials:username"
phases:
install:
commands:
- yum update -y
pre_build:
commands:
- echo Logging in to DOCKER...
- docker login --username $DOCKERHUB_USERNAME --password $DOCKERHUB_PASS
build:
commands:
- echo Build started on `date`
- echo Building the Docker image...
- VERSION=$(cat version.txt)
- docker build -t $DOCKERHUB_USERNAME/$IMAGE_REPO_NAME:$VERSION-$ARCH -t $DOCKERHUB_USERNAME/$IMAGE_REPO_NAME:$IMAGE_TAG-$ARCH .
post_build:
commands:
- echo Build completed on `date`
- echo Pushing the Docker image...
- docker push $DOCKERHUB_USERNAME/$IMAGE_REPO_NAME --all-tags
15 changes: 15 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
version: '3.5'

services:
airprint:
container_name: airprint
image: znetwork/synology-airprint:0.3
build: .
restart: always
network_mode: "host"
environment:
CUPSADMIN: admin
CUPSPASSWORD: admin
volumes:
- "./services:/services"
- "./config:/config"
22 changes: 17 additions & 5 deletions root/root/airprint-generate.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3

"""
Copyright (c) 2010 Timothy J Fontaine <[email protected]>
Expand All @@ -22,9 +22,10 @@
THE SOFTWARE.
"""

import cups, os, optparse, re, urlparse
import cups, os, optparse, re
import urllib.parse as urlparse
import os.path
from StringIO import StringIO
from io import StringIO

from xml.dom.minidom import parseString
from xml.dom import minidom
Expand All @@ -43,7 +44,8 @@
from elementtree import Element, ElementTree, tostring
etree = None
except:
raise 'Failed to find python libxml or elementtree, please install one of those or use python >= 2.5'
print('Failed to find python libxml or elementtree, please install one of those or use python >= 2.5')
raise

XML_TEMPLATE = """<!DOCTYPE service-group SYSTEM "avahi-service.dtd">
<service-group>
Expand Down Expand Up @@ -121,7 +123,7 @@ def generate(self):

printers = conn.getPrinters()

for p, v in printers.items():
for p, v in list(printers.items()):
if v['printer-is-shared']:
attrs = conn.getPrinterAttributes(p)
uri = urlparse.urlparse(v['printer-uri-supported'])
Expand Down Expand Up @@ -179,6 +181,16 @@ def generate(self):
ptype.text = 'printer-type=%s' % (hex(v['printer-type']))
service.append(ptype)

if attrs['color-supported']:
color = Element('txt-record')
color.text = 'Color=T'
service.append(color)

if attrs['media-default'] == 'iso_a4_210x297mm':
max_paper = Element('txt-record')
max_paper.text = 'PaperMax=legal-A4'
service.append(max_paper)

pdl = Element('txt-record')
fmts = []
defer = []
Expand Down
11 changes: 9 additions & 2 deletions root/root/printer-update.sh
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
#!/bin/bash
inotifywait -m -e close_write,moved_to,create /etc/cups |
#!/bin/sh
/usr/bin/inotifywait -m -e close_write,moved_to,create /etc/cups |
while read -r directory events filename; do
if [ "$filename" = "printers.conf" ]; then
rm -rf /services/AirPrint-*.service
/root/airprint-generate.py -d /services
cp /etc/cups/printers.conf /config/printers.conf
rsync -avh /services/ /etc/avahi/services/
chmod 755 /var/cache/cups
rm -rf /var/cache/cups/*
fi
if [ "$filename" = "cupsd.conf" ]; then
cp /etc/cups/cupsd.conf /config/cupsd.conf
fi
done
#/usr/sbin/lpinfo --include-schemes dnssd -v
26 changes: 24 additions & 2 deletions root/root/run_cups.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,41 @@
set -e
set -x

# Is CUPSADMIN set? If not, set to default
if [ -z "$CUPSADMIN" ]; then
CUPSADMIN="admin"
fi

# Is CUPSPASSWORD set? If not, set to $CUPSADMIN
if [ -z "$CUPSPASSWORD" ]; then
CUPSPASSWORD=$CUPSADMIN
fi

if [ $(grep -ci $CUPSADMIN /etc/shadow) -eq 0 ]; then
useradd -r -G lpadmin -M $CUPSADMIN
#adduser -S -G lpadmin --no-create-home $CUPSADMIN
useradd -r -G lpadmin -M $CUPSADMIN
fi
echo $CUPSADMIN:$CUPSPASSWORD | chpasswd

mkdir -p /config/ppd
mkdir -p /services
rm -rf /etc/avahi/services/*
rm -rf /etc/cups/ppd
ln -s /config/ppd /etc/cups
if [ ! -f /config/printers.conf ]; then

if [ `ls -l /services/*.service 2>/dev/null | wc -l` -gt 0 ]; then
cp -f /services/*.service /etc/avahi/services/
fi

if [ `ls -l /config/printers.conf 2>/dev/null | wc -l` -eq 0 ]; then
touch /config/printers.conf
fi
cp /config/printers.conf /etc/cups/printers.conf

if [ `ls -l /config/cupsd.conf 2>/dev/null | wc -l` -ne 0 ]; then
cp /config/cupsd.conf /etc/cups/cupsd.conf
fi

/usr/sbin/avahi-daemon --daemonize
/root/printer-update.sh &
exec /usr/sbin/cupsd -f
1 change: 1 addition & 0 deletions version.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0.3.0

0 comments on commit 10fbb6f

Please sign in to comment.