diff --git a/cups/CHANGELOG.md b/cups/CHANGELOG.md new file mode 100644 index 0000000..3455d98 --- /dev/null +++ b/cups/CHANGELOG.md @@ -0,0 +1,136 @@ +# Changelog + +## 2.0.0 -- 18.12.2022 + +* Changed `init` to `false` to make it at least starting. + +--- + +Original Changelog: + +## 1.0.0-alpha.25 + +- Used documented ingress path header for rewrites, removed JS + +## 1.0.0-alpha.24 + +- Modified Nginx configuration to get the authentication token from JS + +## 1.0.0-alpha.23 + +- Fixed Avahi config to use D-Bus again +- Made Nginx authenticate supervisor requests +- Used container fqdn instead of Home Assistant hostname for certificate filenames + +## 1.0.0-alpha.22 + +- Removed debug log level in CUPS +- Made Avahi wait to be configured before starting + +## 1.0.0-alpha.21 + +- Debug: increased CUPS log level + +## 1.0.0-alpha.20 + +- Removed debugging print statements from run.sh +- Added export statement to http.js +- Mapped Home Assistant hostname into avahi-daemon.conf +- Removed DNSSDHostName key from cupsd.conf (introduced in later version) + +## 1.0.0-alpha.19 + +- Replaced const with var in http.js +- Automatically generated /data/cups on first run + +## 1.0.0-alpha.18 + +- Fixed nginx.conf typo +- Debug: print debugging in run.sh + +## 1.0.0-alpha.17 + +- Persisted all CUPS configuration +- Refreshed all certificates on startup +- Added a CSP on ingress to disable the CUPS frame-blocker +- Rewrote absolute page URLs on ingress to point to the proxied URL +- Redirected printer advertisements to the domain name of the Home Assistant installation +- Disabled mDNS address responses for the container +- Added more default drivers + +## 1.0.0-alpha.16 + +- Flipped order of arguments in ln command + +## 1.0.0-alpha.15 + +- Fixed bug in run.sh caused by a variable in an if statement + +## 1.0.0-alpha.14 + +- Added D-Bus back +- Fixed SSL support for CUPS - new config options +- Added startup dependencies for CUPS and Avahi + +## 1.0.0-alpha.13 + +- Added a delay so CUPS starts after Avahi is up +- Debug: removed IP filter on ingress controller + +## 1.0.0-alpha.12 + +- Attempted to remove D-Bus + +## 1.0.0-alpha.11 + +- Turned off D-Bus support in Avahi +- Created a folder for D-Bus to store its socket + +## 1.0.0-alpha.10 + +- Added a D-Bus daemon into the container directly + +## 1.0.0-alpha.9 + +- Mapped the host D-Bus service into the container +- Added an events section to nginx.conf + +## 1.0.0-alpha.8 + +- Fixed shebang to point to /bin/sh instead of /usr/bin/sh + +## 1.0.0-alpha.7 + +- Normalized line endings to LF + +## 1.0.0-alpha.6 + +- Replaced execlineb with sh +- Removed debug info for ingress +- Added nginx to proxy requests for ingress + +## 1.0.0-alpha.5 + +- Replaced bashio with execlineb in service script +- Added debug info for ingress + +## 1.0.0-alpha.4 + +- Moved this changelog into the correct directory +- Added exec command to run script +- Fixed external hostname mapping + +## 1.0.0-alpha.3 + +- Added this changelog +- Added all configured hostnames to allowlist +- Added avahi-daemon service + +## 1.0.0-alpha.2 + +- Updated link to repository +- Fixed unescaped newlines causing container start to fail in run.sh + +## 1.0.0-alpha.1 + +- Initial release \ No newline at end of file diff --git a/cups/Dockerfile b/cups/Dockerfile new file mode 100644 index 0000000..6cde750 --- /dev/null +++ b/cups/Dockerfile @@ -0,0 +1,37 @@ +ARG BUILD_FROM +FROM $BUILD_FROM + +LABEL io.hass.version="1" io.hass.type="addon" io.hass.arch="armhf|aarch64|i386|amd64" + +RUN apt-get update \ + && apt-get install -y --no-install-recommends \ + cups \ + avahi-daemon \ + libnss-mdns \ + dbus \ + colord \ + printer-driver-all \ + printer-driver-gutenprint \ + openprinting-ppds \ + hpijs-ppds \ + hp-ppd \ + hplip \ + printer-driver-foo2zjs \ + gnupg2 \ + lsb-release \ + nano \ + samba \ + bash-completion \ + && echo "deb http://nginx.org/packages/debian `lsb_release -cs` nginx" \ + | tee /etc/apt/sources.list.d/nginx.list \ + && curl -fsSL https://nginx.org/keys/nginx_signing.key | apt-key add - \ + && apt-get update \ + && apt-get install nginx nginx-module-njs \ + && apt-get clean -y \ + && rm -rf /var/lib/apt/lists/* + +COPY rootfs / + +EXPOSE 631 445 137 139 + +CMD ["/run.sh"] diff --git a/cups/README.md b/cups/README.md new file mode 100644 index 0000000..f5b9454 --- /dev/null +++ b/cups/README.md @@ -0,0 +1,10 @@ +# Home Assistant Add-on: CUPS Printer server + +Buy Me a Coffee at ko-fi.com + +## Credits +This Add-On is based on the work of https://github.com/Luk164/addon-repository - and just slighty adjusted to make it work. Thanks <3 + +## Known Issues 🚨 + * mDNS is not working, therefore e.g. printeres are not announced via Avahi / Bonjour - see [#128](https://github.com/MaxWinterstein/homeassistant-addons/issues/128) + * Ingress is not working, so I disabled it for now. Please access the Webinterface via port 631, e.g. https://192.168.1.2:631 - see [#129](https://github.com/MaxWinterstein/homeassistant-addons/issues/129) diff --git a/cups/build.json b/cups/build.json new file mode 100644 index 0000000..31876df --- /dev/null +++ b/cups/build.json @@ -0,0 +1,7 @@ +{ + "build_from": { + "armhf": "ghcr.io/home-assistant/armhf-base-debian:bullseye", + "aarch64": "ghcr.io/home-assistant/aarch64-base-debian:bullseye", + "amd64": "ghcr.io/home-assistant/amd64-base-debian:bullseye" + } +} \ No newline at end of file diff --git a/cups/config.yaml b/cups/config.yaml new file mode 100644 index 0000000..60a1809 --- /dev/null +++ b/cups/config.yaml @@ -0,0 +1,38 @@ +--- +name: CUPS Print Server +version: 2.0.0 +stage: experimental +slug: cups +image: ghcr.io/maxwinterstein/homeassistant-addon-cups-{arch} +description: A CUPS print server with Avahi installed +url: https://github.com/MaxWinterstein/homeassistant-addons/ +arch: +- armhf +- aarch64 +- amd64 +startup: application +boot: auto +usb: 'true' +init: 'false' +homeassistant_api: true +# host_network: false +ports: + 631/tcp: 631 + 631/udp: 631 +ports_description: + 631/tcp: For other devices on the local network to print to this server + 631/udp: For other devices on the local network to print to this server +ingress: false +map: +- ssl +options: + ssl: true + certfile: fullchain.pem + keyfile: privkey.pem + require_ssl: true +schema: + ssl: bool + cafile: str? + certfile: str + keyfile: str + require_ssl: bool diff --git a/cups/icon.png b/cups/icon.png new file mode 100644 index 0000000..aefa10e Binary files /dev/null and b/cups/icon.png differ diff --git a/cups/logo.png b/cups/logo.png new file mode 100644 index 0000000..aefa10e Binary files /dev/null and b/cups/logo.png differ diff --git a/cups/rootfs/etc/cont-init.d/dbus-setup b/cups/rootfs/etc/cont-init.d/dbus-setup new file mode 100644 index 0000000..a706c93 --- /dev/null +++ b/cups/rootfs/etc/cont-init.d/dbus-setup @@ -0,0 +1,2 @@ +#!/bin/sh +mkdir -p /var/run/dbus \ No newline at end of file diff --git a/cups/rootfs/etc/nginx/nginx.conf b/cups/rootfs/etc/nginx/nginx.conf new file mode 100644 index 0000000..71869c1 --- /dev/null +++ b/cups/rootfs/etc/nginx/nginx.conf @@ -0,0 +1,19 @@ +events { +} + +http { + + server { + listen 8099; + + location / { + proxy_pass https://localhost:631; + proxy_hide_header X-Frame-Options; + proxy_hide_header Content-Security-Policy; + add_header Content-Security-Policy "sandbox allow-forms allow-modals allow-popups allow-popups-to-escape-sandbox allow-scripts"; + sub_filter '"/' '"$http_x_ingress_path/'; + sub_filter "'/" "'$http_x_ingress_path/"; + sub_filter_once off; + } + } +} \ No newline at end of file diff --git a/cups/rootfs/etc/services.d/avahi/run b/cups/rootfs/etc/services.d/avahi/run new file mode 100644 index 0000000..63ad826 --- /dev/null +++ b/cups/rootfs/etc/services.d/avahi/run @@ -0,0 +1,8 @@ +#!/bin/sh + +# Wait until D-Bus is up and the init script has mapped in the external hostname +until [ -e /var/run/dbus/system_bus_socket ] && [ -e /var/run/avahi_configured ]; do + sleep 1s +done + +exec avahi-daemon \ No newline at end of file diff --git a/cups/rootfs/etc/services.d/dbus/run b/cups/rootfs/etc/services.d/dbus/run new file mode 100644 index 0000000..811b394 --- /dev/null +++ b/cups/rootfs/etc/services.d/dbus/run @@ -0,0 +1,2 @@ +#!/bin/sh +exec dbus-daemon --system --nofork \ No newline at end of file diff --git a/cups/rootfs/etc/services.d/nginx/run b/cups/rootfs/etc/services.d/nginx/run new file mode 100644 index 0000000..1f2bade --- /dev/null +++ b/cups/rootfs/etc/services.d/nginx/run @@ -0,0 +1,2 @@ +#!/bin/sh +exec nginx -g "daemon off;" \ No newline at end of file diff --git a/cups/rootfs/run.sh b/cups/rootfs/run.sh new file mode 100644 index 0000000..a971ebd --- /dev/null +++ b/cups/rootfs/run.sh @@ -0,0 +1,57 @@ +#!/usr/bin/with-contenv bashio + +# Create links for certificates with CUPS' expected filenames +bashio::config.require.ssl + +keyfile=$(bashio::config keyfile) +certfile=$(bashio::config certfile) +cafile=$(bashio::config cafile) +hostname=$(bashio::info.hostname) +fqdn=$(hostname --fqdn) + +mkdir -p /data/ssl + +if [ $cafile != null ] && [ -e "/ssl/$cafile" ]; then + rm -f /data/ssl/site.crt + ln -s "/ssl/$cafile" /data/ssl/site.crt +fi + +if bashio::config.true ssl; then + rm -f "/data/ssl/$fqdn.key" + rm -f "/data/ssl/$fqdn.crt" + ln -s "/ssl/$keyfile" "/data/ssl/$fqdn.key" + ln -s "/ssl/$certfile" "/data/ssl/$fqdn.crt" +fi + +# Get all possible hostnames from configuration +result=$(bashio::api.supervisor GET /core/api/config true || true) +internal=$(bashio::jq "$result" '.internal_url' | cut -d'/' -f3 | cut -d':' -f1) +external=$(bashio::jq "$result" '.external_url' | cut -d'/' -f3 | cut -d':' -f1) + +# Fill config file templates with runtime data +config=$(jq --arg internal "$internal" --arg external "$external" --arg hostname "$hostname" \ + '{ssl: .ssl, require_ssl: .require_ssl, internal: $internal, external: $external, hostname: $hostname}' \ + /data/options.json) + +echo "$config" | tempio \ + -template /usr/share/cupsd.conf.tempio \ + -out /etc/cups/cupsd.conf + +echo "$config" | tempio \ + -template /usr/share/cups-files.conf.tempio \ + -out /etc/cups/cups-files.conf + +echo "$config" | tempio \ + -template /usr/share/avahi-daemon.conf.tempio \ + -out /etc/avahi/avahi-daemon.conf + +mkdir -p /data/cups + +# Start Avahi, wait for it to start up +touch /var/run/avahi_configured +until [ -e /var/run/avahi-daemon/socket ]; do + sleep 1s +done + +# Start CUPS +/usr/sbin/cupsd -f diff --git a/cups/rootfs/usr/share/avahi-daemon.conf.tempio b/cups/rootfs/usr/share/avahi-daemon.conf.tempio new file mode 100644 index 0000000..d668620 --- /dev/null +++ b/cups/rootfs/usr/share/avahi-daemon.conf.tempio @@ -0,0 +1,68 @@ +# This file is part of avahi. +# +# avahi is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation; either version 2 of the +# License, or (at your option) any later version. +# +# avahi is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +# License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with avahi; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA. + +# See avahi-daemon.conf(5) for more information on this configuration +# file! + +[server] +host-name={{.hostname}} +#domain-name=local +#browse-domains=0pointer.de, zeroconf.org +use-ipv4=yes +use-ipv6=yes +#allow-interfaces=eth0 +#deny-interfaces=eth1 +#check-response-ttl=no +#use-iff-running=no +#enable-dbus=yes +#disallow-other-stacks=no +#allow-point-to-point=no +#cache-entries-max=4096 +#clients-max=4096 +#objects-per-client-max=1024 +#entries-per-entry-group-max=32 +ratelimit-interval-usec=1000000 +ratelimit-burst=1000 + +[wide-area] +enable-wide-area=yes + +[publish] +#disable-publishing=no +#disable-user-service-publishing=no +#add-service-cookie=no +publish-addresses=no +publish-hinfo=no +publish-workstation=no +publish-domain=no +#publish-dns-servers=192.168.50.1, 192.168.50.2 +#publish-resolv-conf-dns-servers=yes +#publish-aaaa-on-ipv4=yes +#publish-a-on-ipv6=no + +[reflector] +#enable-reflector=no +#reflect-ipv=no + +[rlimits] +#rlimit-as= +#rlimit-core=0 +#rlimit-data=8388608 +#rlimit-fsize=0 +#rlimit-nofile=768 +#rlimit-stack=8388608 +#rlimit-nproc=3 diff --git a/cups/rootfs/usr/share/cups-files.conf.tempio b/cups/rootfs/usr/share/cups-files.conf.tempio new file mode 100644 index 0000000..ee04db8 --- /dev/null +++ b/cups/rootfs/usr/share/cups-files.conf.tempio @@ -0,0 +1,3 @@ +ServerRoot /data/cups +ServerKeychain /data/ssl +CreateSelfSignedCerts {{if .ssl}}no{{else}}yes{{end}} \ No newline at end of file diff --git a/cups/rootfs/usr/share/cupsd.conf.tempio b/cups/rootfs/usr/share/cupsd.conf.tempio new file mode 100644 index 0000000..c1aa4d1 --- /dev/null +++ b/cups/rootfs/usr/share/cupsd.conf.tempio @@ -0,0 +1,164 @@ +# +# +# Sample configuration file for the CUPS scheduler. See "man cupsd.conf" for a +# complete description of this file. +# + +# Log general information in error_log - change "warn" to "debug" +# for troubleshooting... +LogLevel warn + +# Deactivate CUPS' internal logrotating, as we provide a better one, especially +# LogLevel debug2 gets usable now +MaxLogSize 0 + +# Listen to all +Port 631 +Listen /var/run/cups/cups.sock + +# Show shared printers on the local network. +Browsing On +BrowseLocalProtocols all + +# Default authentication type, when authentication is required... +DefaultAuthType Basic +DefaultEncryption Required + +# Host header validation + +ServerAlias {{.hostname}}.local {{.internal}} {{.external}} + +ServerName {{.hostname}} + +# Web interface setting... +WebInterface Yes + +# Restrict access to the server... + + Order allow,deny + Allow all + Encryption {{if .require_ssl}}Required{{else}}IfRequested{{end}} + + +# Restrict access to the admin pages... + + Order allow,deny + Allow all + + +# Restrict access to configuration files... + + AuthType Default + Require user @SYSTEM + Order allow,deny + Allow 172.0.0.1 + Satisfy any + + +# Set the default printer/job policies... + + # Job/subscription privacy... + JobPrivateAccess default + JobPrivateValues default + SubscriptionPrivateAccess default + SubscriptionPrivateValues default + + # Job-related operations must be done by the owner or an administrator... + + Order deny,allow + + + + Require user @OWNER @SYSTEM + Order allow,deny + Allow 172.0.0.1 + Satisfy any + + + # All administration operations require an administrator to authenticate... + + AuthType Default + Require user @SYSTEM + Order allow,deny + Allow 172.0.0.1 + Satisfy any + + + # All printer operations require a printer operator to authenticate... + + AuthType Default + Require user @SYSTEM + Order allow,deny + Allow 172.0.0.1 + Satisfy any + + + # Only the owner or an administrator can cancel or authenticate a job... + + Require user @OWNER @SYSTEM + Order allow,deny + Allow 172.0.0.1 + Satisfy any + + + + Order deny,allow + + + +# Set the authenticated printer/job policies... + + # Job/subscription privacy... + JobPrivateAccess default + JobPrivateValues default + SubscriptionPrivateAccess default + SubscriptionPrivateValues default + + # Job-related operations must be done by the owner or an administrator... + + AuthType Default + Order deny,allow + + + + AuthType Default + Require user @OWNER @SYSTEM + Order allow,deny + Allow 172.0.0.1 + Satisfy any + + + # All administration operations require an administrator to authenticate... + + AuthType Default + Require user @SYSTEM + Order allow,deny + Allow 172.0.0.1 + Satisfy any + + + # All printer operations require a printer operator to authenticate... + + AuthType Default + Require user @SYSTEM + Order allow,deny + Allow 172.0.0.1 + Satisfy any + + + # Only the owner or an administrator can cancel or authenticate a job... + + AuthType Default + Require user @OWNER @SYSTEM + Order allow,deny + Allow 172.0.0.1 + Satisfy any + + + + Order deny,allow + + + +# +# \ No newline at end of file