# PyKota sample configuration file # # Copy this file into the /etc/pykota/ directory # under the name /etc/pykota/pykota.conf # # PyKota - Print Quotas for CUPS and LPRng # # (c) 2003, 2004, 2005 Jerome Alet # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program 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 General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. # # $Id$ # [global] # Storage backend for quotas # only PGStorage (PostgreSQL) and LDAPStorage (OpenLDAP) are supported. # MySQL and BerkeleyDB are planned. # the 'postgresql' value is deprecated, use 'pgstorage' instead. storagebackend: pgstorage # Quota Storage Server hostname (and optional port) # e.g. db.example.com:5432 storageserver: localhost # # name of the Quota Storage Database storagename: pykota # # Quota Storage normal user's name and password # These two fields contain a username and optional password # which may give readonly access to your print quota database. # # PLEASE ENSURE THAT THIS USER CAN'T WRITE TO YOUR PRINT QUOTA # DATABASE, OTHERWISE ANY USER WHO COULD READ THIS CONFIGURATION # FILE COULD CHANGE HIS PRINT QUOTA. # storageuser: pykotauser # storageuserpw: Comment out if unused, or set to Quota Storage user password # Should the database caching mechanism be enabled or not ? # If unset, caching is disabled. Possible values Y/N/YES/NO # caching mechanism works with both PostgreSQL and OpenLDAP backends # but may be really interesting only with OpenLDAP. # # ACTIVATING CACHE MAY CAUSE PRECISION PROBLEMS IN PRINT ACCOUNTING # IF AN USER PRINTS ON SEVERAL PRINTERS AT THE SAME TIME. # YOU MAY FIND IT INTERESTING ANYWAY, ESPECIALLY FOR LDAP. # # FYI, I ALWAYS SET IT TO YES ! # storagecaching: No # Should full job history be disabled ? # If unset or set to No, full job history is kept in the database. # This will be useful in the future when the report generator # will be written. # Disabling the job history can be useful with heavily loaded # LDAP servers, to not make the LDAP tree grow out of control. # Disabling the job history with the PostgreSQL backend works too # but it's probably less useful than with LDAP. disablehistory: No # LDAP example, uncomment and adapt it to your own configuration : #storagebackend: ldapstorage #storageserver: ldap://ldap.librelogiciel.com:389 #storagename: dc=librelogiciel,dc=com #storageuser: cn=notadmin,dc=librelogiciel,dc=com #storageuserpw: abc.123 # # TLS support for LDAP # # ldaptls can be set to either Yes or No # the default value when not set is No, meaning that TLS won't be used. #ldaptls: No # # cacert points to the CA Certificate file to use for TLS. # Ensure that every user who can launch PyKota commands can read this file. # There's NO default value for this directive. #cacert /etc/pykota/mycertfile # # # Here we define some helpers to know where # to plug into an existing LDAP directory #userbase: ou=People,dc=librelogiciel,dc=com #userrdn: uid #balancebase: ou=People,dc=librelogiciel,dc=com #balancerdn: uid #groupbase: ou=Groups,dc=librelogiciel,dc=com #grouprdn: cn #printerbase: ou=Printers,ou=PyKota,dc=librelogiciel,dc=com #printerrdn: cn #jobbase: ou=Jobs,ou=PyKota,dc=librelogiciel,dc=com #lastjobbase: ou=LastJobs,ou=PyKota,dc=librelogiciel,dc=com # These two fields are special, they either accept a branch # dn, like an ou for example, or the special keywords 'user' # and 'group'. If 'user' or 'group' is used, the print quota # entries will be created below the user or group entry itself, # which will then be used like a branch (you can mix and match # different values depending on what you want to do). #userquotabase: user #userquotabase: ou=UQuotas,ou=PyKota,dc=librelogiciel,dc=com #groupquotabase: group #groupquotabase: ou=GQuotas,ou=PyKota,dc=librelogiciel,dc=com # # How to create new accounts and groups # authorized values are "below" and "attach(objectclass name [, fail|warn])" # # "below" creates the new accounts/groups as standalone entries # below the above defined 'userbase' ou # # attach(objectclass name [, action]) tries to find some existing user/group # using the above defined 'userrdn' or 'grouprdn' and 'userbase' # 'groupbase', and attach the PyKota specific entries to it. # if action is "warn" and no entry exists to attach to, a new # entry is created, and a message is logged. # if action is "fail" and no entry exists to attach to, program # logs an error message and aborts. # if action is not set, the default value is "fail". # # a possible value: newuser: attach(posixAccount, warn) #newuser : below #newgroup : below # # LDAP attribute which stores the user's email address #usermail : mail # # Choose what attribute contains the list of group members # common values are : memberUid, uniqueMember, member #groupmembers: memberUid # Activate low-level LDAP cache yes/no # Nothing to do with "storagecaching" which is higher level # and database independant. # This saves some search queries and may help with heavily # loaded LDAP servers. # This is EXPERIMENTAL. # # BEWARE : SETTING THIS TO 'YES' CAUSES PROBLEMS FOR NOW # BETTER TO LET IT SET TO 'NO' # ldapcache: no # Where to log ? # supported values : stderr, system (system means syslog, but don't use 'syslog' here) # if the value is not set then the default SYSTEM applies. logger: system # Enable debugging ? Put YES or NO there. # From now on, YES is the default in this sample # configuration file, so that debugging is activated # when configuring PyKota. After all works, just # put NO instead to save some disk space in your # logs. # Actually only database queries are logged. debug : Yes # Mail server to use to warn users # If the value is not set then localhost is used. smtpserver: localhost # Crash messages' recipient : in addition to the log files # each software crash can be sent to the author of PyKota # or any other person of your choice. By default this # is disabled. The recipient pykotacrashed@librelogiciel.com # reaches PyKota's author. # The 'adminmail' (defined a bit below) is CCed. # # Privacy concerns : what is sent is only : # # - a copy of the software's traceback # - a copy of the software's command line arguments # - a copy of the software's environment variables # # suggested value # crashrecipient: pykotacrashed@librelogiciel.com # Email domain # If the value is not set, and the mail attribute for the user # is not set in the PyKota storage, be it LDAP (see usermail directive # above) or PostgreSQL, then email messages are sent to # username@smtpserver # # If the value is set, then email messages are sent to # username@maildomain using the SMTP server defined above # # Set the appropriate value below, example.com set as per RFC2606. maildomain: example.com # Should we force usernames to be all lowercase when printing ? # Default is No. # This is a global option only. # Some people reported that WinXP sends mixed case usernames # setting 'utolower: Yes' solves the problem. # Of course you have to use lowercase only when adding # users with edpykota, because ALL database accesses are # still case sensitive. # # If utolower is Yes, the usernames received from the printing # system is converted to lowercase at the start of the cupspykota # backend or of the lprngpykota filter. # # If utolower is No, which is the default, strict case checking # is done, this means that users 'Jerome' and 'jerome' are # different. Printer and groups names are ALWAYS case sensitive. utolower: No # Should we split usernames on a specific separator when printing ? # Default is No, i.e. if the value is unset. # This is a global option only. # This option adds support for Samba's Winbind utility, which # prefixes usernames with domain name and separator character. # Of course if you set this then you have to use NO separator when # adding users with edpykota. # # If winbind_separator is set, the usernames received from the printing # system are split on the separator's value, and only the last part # (real username) is used. # # If winbind_separator is not set, which is the default, strict # username equality checking will be done (modulo the setting # of the 'utolower' directive), this means that users 'DOMAIN1/jerome', # 'Domain2/jerome' and 'jerome' are different. # winbind_separator: / # When creating users or groups accounts, should we reject users # or groups which are unknown from the system ? # The default if unset is NO. This means that by default, you # can create users or groups for which `getent passwd username` # or `getent group groupname` returns nothing. # # Allowed values : Yes | No # Default value : No # # reject_unknown: No # Do we want to hide jobs' title, filename and options for privacy # reasons ? # This may be required in some countries (Italy comes to mind). # Allowed values are YES and NO. # If unset, the default value is NO, meaning that jobs' title, filename # and options will be saved into the history. # This option can't be set on a per printer basis, only into the # [global] section. privacy : no # What is the accounting backend to use # # supported values : # # - hardware : asks the printer for its lifetime page counter # via either SNMP, AppleTalk, or any external # command. This method is the recommended one # in PyKota since its beginning. # # In the lines below "%(printer)s" is automatically replaced # at run time with your printer's Fully Qualified Domain Name # for network printers, if PyKota can extract it from its # environment. # e.g. myprinter.example.com # # Recommended values : # # accounter: hardware(snmp) # # Extracts the printer's internal page counter via SNMP. # # Or : # # accounter: hardware(pjl) # # Extracts the printer's internal page counter via PJL queries over port tcp/9100. # # Other Examples : # # accounter: hardware(/usr/bin/snmpget -v1 -c public -Ov %(printer)s mib-2.43.10.2.1.4.1.1 | cut -f 2,2 -d " ") # # Another untested example, using npadmin : # # accounter: hardware(/usr/bin/npadmin --pagecount %(printer)s) # # Another example, for AppleTalk printers which works fine : # (You may need the pap CUPS backend installed, and copy the # pagecount.ps file from untested/netatalk into /etc or any # appropriate location) # # accounter: hardware(/usr/share/pykota/papwaitprinter.sh "MyPrinter:LaserWriter@*" && /usr/bin/pap -p "MyPrinter:LaserWriter@*" /usr/share/pykota/pagecount.ps 2>/dev/null | /bin/grep -v status | /bin/grep -v Connect | /usr/bin/tail -1) # # An example for parallel printers like the HP Laserjet 5MP : # # accounter: hardware(/bin/cat /usr/share/pykota/pagecount.pjl >/dev/lp0 && /usr/bin/head -2 /dev/null) # # You can use : # # '%(action)s' will contain either WARN or DENY # '%(username)s' will contain the user's name # '%(printername)s' will contain the printer's name # '%(email)s' will contain the user's email address # '%(message)s' will contain the message if you want # to use it. # # On your command line, to pass arguments to your command. # Example : # # mailto: external(/usr/bin/callpager %(username)s "Quota problem on %(printername)s" >/dev/null) # # To automatically send a WinPopup message (this may only work with a PDC, # here the same machine does Samba as PDC + CUPS) : # # mailto: external(echo "%(message)s" | /usr/bin/iconv --to-code utf-8 --from-code iso-8859-15 | /usr/bin/smbclient -M "%(username)s" 2>&1 >/dev/null) # # NB : I use ISO-8859-15, but Windows expects UTF-8, so we pipe the message # into iconv before sending it to the Windows user. # # or more simply : # # mailto: external(/usr/share/pykota/mailandpopup.sh %(username)s %(printername)s "%(email)s" "%(message)s" 2>&1 >/dev/null) # # NB : The mailandpopup.sh shell script is now included in PyKota # # NB : in ANY case, don't forget to redirect your command's standard output # somewhere (e.g. >/dev/null) so that there's no perturbation to the # underlying layer (filter or backend) # mailto: both # # Grace delay in days # This value can be set either globally or per printer or both. # If both are defined, the printer option has priority. # If the value is not set then the default seven (7) days applies. gracedelay: 7 # # Poor man's threshold # If account balance reaches below this amount, # a warning message is sent by email # # If unset, default poor man's threshold is 1.0. # This option can only appear in the global section poorman: 2.0 # Poor man's warning message # The warning message that is sent if the "poorman" value is reached # Again this must appear in the global section poorwarn: Your Print Quota account balance is low. Soon you'll not be allowed to print anymore. # Soft limit reached warning message # The warning message that is sent if the soft quota limit is reached # May appear either globally or on a per-printer basis softwarn: Your Print Quota Soft Limit is reached. This means that you may still be allowed to print for some time, but you must contact your administrator to purchase more print quota. # Hard limit reached error message # The error message that is sent if the hard quota limit is reached # May appear either globally or on a per-printer basis hardwarn: Your Print Quota Hard Limit is reached. This means that you are not allowed to print anymore. Please contact your administrator at root@localhost as soon as possible to solve the problem. # one section per printer, or no other section at all if all options # are defined globally. # Each section's name must be the same as the printer's queue name as defined # in your printing system, be it CUPS or LPRng, between square brackets, for # example a print queue named 'hpmarketing' would appear in this file as # [hpmarketing] # Default policy to apply when either : # # - Printer doesn't exist in PyKota's database # - User doesn't exist in PyKota's database # - User has no quota entry for this Printer in PyKota's database # # Value can be either allow or deny or external(some command here) # # This value can be set either globally or per printer or both. # If both are defined, the printer option has priority. # If the value is not set then the default policy DENY applies. # There's no policy wrt inexistant groups, they are ignored. # # external policy can be used to launch any external command of your choice, # for example to automatically add the user to the quota storage # if he is unknown. Example : # # policy: external(/usr/bin/edpykota --add --printer %(printername)s --softlimit 50 --hardlimit 60 %(username)s >/dev/null) # # NB : If you want to limit users by their account balance value, it is preferable to # use the following policy to automate user account creation on first print : # # policy: external(/usr/bin/autopykota --initbalance 25.0 >/dev/null) # # This will automatically add the user if he doesn't already exist, and # set his initial balance value to 25.0 (for example). If the user already # exists then his balance value will not be modified. # Please don't use autopykota if you want to limit your users by page # quota, and in any case, carefully read autopykota's help or manpage # and understand its goal before using it in your own configuration. # # Of course you can launch any command of your choice with this, e.g. : # # policy: external(/usr/local/bin/myadminscript.sh %(username)s >/dev/null) # You can use : # # '%(username)s' will contain the user's name # '%(printername)s' will contain the printer's name # # On your command line, to pass arguments to your command. # # NB : Don't forget to redirect your command's standard output somewhere # (e.g. >/dev/null) so that there's no perturbation to the underlying # layer (filter or backend) # # If the printer, user, or user quota entry still doesn't exist after # external policy command was launched (the external command didn't add it), # or if an error occured during the execution of the external policy # command, then the job is rejected. # policy: deny # Pre and Post Hooks # These directives allow the easy plug-in of any command of your choice # at different phases of PyKota's execution. # Pre and Post Hooks can access some of PyKota's internal information # by reading environment variables as described below. # The actual phase of PyKota's execution is available in the # PYKOTAPHASE environment variable. # Pre and Post Hooks can be defined either globally, per printer, # or both. If both are defined, the printer specific hook has # priority. # # List of available environment variables : # NB : Most of these variables are also available during the execution # of external commands defined in the accounter and mailto # directives. # # PYKOTAMD5SUM : Contains an hexadecimal digest of the md5 sum of the job's datas # PYKOTAPHASE : BEFORE or AFTER the job is sent to the printer # PYKOTAACTION : ALLOW or DENY or WARN for current print job # PYKOTAUSERNAME : user's name # PYKOTAPRINTERNAME : printer's name # PYKOTAPGROUPS : list of printers groups the current printer is a member of # PYKOTAJOBID : job's id # PYKOTATITLE : job's title # PYKOTAFILENAME : job's filename # PYKOTACOPIES : number of copies # PYKOTAOPTIONS : job's options # PYKOTABALANCE : user's account balance # PYKOTALIFETIMEPAID : user's grand total paid # PYKOTALIMITBY : user print limiting factor, for example 'quota' or 'balance' # PYKOTAPAGECOUNTER : user's page counter on this printer # PYKOTALIFEPAGECOUNTER : user's life time page counter on this printer # PYKOTASOFTLIMIT : user's soft page limit on this printer # PYKOTAHARDLIMIT : user's hard page limit on this printer # PYKOTADATELIMIT : user's soft to hard limit date limit on this printer # PYKOTASTATUS : contains "CANCELLED" when SIGTERM was received by PyKota # else is not set. # PYKOTAJOBSIZEBYTES : contains the job's size in bytes. Always available. # PYKOTAPRECOMPUTEDJOBSIZE : contains the precomputed job's size # PYKOTAPRECOMPUTEDJOBPRICE : contains the precomputed job's price # PYKOTAJOBORIGINATINGHOSTNAME : contains the client's hostname if # it is possible to retrieve it. # PYKOTAPRINTERHOSTNAME : the printer's hostname or IP address for network # printers, or "localhost" if not defined or not # meaningful. # PYKOTAWARNCOUNT : the number of times the user was forbidden to print but a banner # page was still printed on the current printer. # PYKOTAOVERCHARGE : user's overcharging factor. # # PreHook : gets executed after being sure the user, printer and user quota # entry on the printer both exist in the PyKota database, and after # checking if the user is allowed to print or not, but just before # the job is sent to the printer (if allowed) # prehook has access to many environment variables : # # PYKOTAACTION contains either "ALLOW", "WARN" or "DENY" and # represents the action which is to be done wrt the print job. # PYKOTAPHASE contains 'BEFORE' during execution of prehook # # uncomment the line below to see what environment variables are available # prehook: /usr/bin/printenv >/tmp/before # PostHook : gets executed after the job has been added to the history. # posthook has access to all the environment variables defined above, # as well as two additionnal environment variables : PYKOTAJOBPRICE # and PYKOTAJOBSIZE. # PYKOTAPHASE contains 'AFTER' during execution of posthook. # # uncomment the line below to see what environment variables are available # posthook: /usr/bin/printenv >/tmp/after # AccountBanner : how should banner accounting be done ? # # NB : CUPS ONLY FOR NOW ! # # If enabled, banner pages printed from StartingBanner and/or EndingBanner # (depending on the value) will be included in the accounting for the # print job # # If disabled, banner pages printed from StartingBanner and EndingBanner will # *not* be included in the accounting for the print job # # IMPORTANT : CUPS generated banners are ALWAYS accounted for, although you # can refund them by using negative prices on printers. # # Allowed values : Starting | Ending | None | Both # # - Starting : only the starting banner will be accounted for. # - Ending : only the ending banner will be accounted for. # - Both : both starting and ending banners will be accounted for. # - None : banners will not be accounted for. # # Default value : # accountbanner: Both # Maximal number of times the banner will still be printed if # the user is forbidden to print. # # NB : CUPS ONLY FOR NOW ! # # This option can be set either globally or on a per printer basis. # Allowed values are 0 or any positive integer. # Default value is 0, which means that the banner won't be printed # at all if the user is forbidden to print. maxdenybanners: 0 # StartingBanner : if defined will print a banner before the rest of the job # is printed. The argument can be a printable file, or an executable file. # If not executable, the file will be printed as is. If executable, the # file will be executed and its output will be printed. # # NB : CUPS ONLY FOR NOW ! # # In any case, the banner content which will be sent to the printer # MUST be in a format your printer will accept !!! # # The pkbanner command included in PyKota can automatically generate # starting and ending banners in the PostScript format. You can use # this command in a pipe through GhostScript if your printer doesn't # accept PostScript as an input format. # NB : pkbanner's default page size is A4 # # startingbanner: /home/joe/mystaticbanner.ps # startingbanner: /usr/bin/pkbanner --pagesize=A4 --logo="/home/joe/mylogo.jpeg" --url="http://tech.example.com" # startingbanner: /usr/bin/pkbanner | gs -q -dNOPAUSE -dBATCH -dPARANOIDSAFER -sOutputFile=- -sDEVICE=lj5mono - # startingbanner: /usr/bin/pkbanner # EndingBanner : if defined will print a banner before the rest of the job # is printed. The argument can be a printable file, or an executable file. # If not executable, the file will be printed as is. If executable, the # file will be executed and its output will be printed. # # NB : CUPS ONLY FOR NOW ! # # In any case, the banner content which will be sent to the printer # MUST be in a format your printer will accept !!! # # The pkbanner command included in PyKota can automatically generate # starting and ending banners in the PostScript format. You can use # this command in a pipe through GhostScript if your printer doesn't # accept PostScript as an input format. # NB : pkbanner's default page size is A4 # # endingbanner: /home/joe/mystaticbanner.ps # endingbanner: /usr/bin/pkbanner --pagesize=A4 --logo="/home/joe/mylogo.jpeg" --url="http://tech.example.com" # endingbanner: /usr/bin/pkbanner | gs -q -dNOPAUSE -dBATCH -dPARANOIDSAFER -sOutputFile=- -sDEVICE=lj5mono - # endingbanner: /usr/bin/pkbanner # How should enforcement be done for this printer ? # # "laxist" is the default if value is not set, and allows users # to be over quota on their last job. # # "strict" tries to prevent users from ever being over quota. # # Enforcement can be defined either globally, per printer, # or both. If both are defined, the printer specific enforcement # setting has priority. # # valid values : "strict" or "laxist" # # default value # enforcement : laxist enforcement : strict # Should we trust the job size on this printer ? # # "yes" is the default, the jobsize, either computed # by the hardware or by software is trusted. # # ">N:precomputed" : uses the precomputed value if jobsize > N pages # ">N:25" : uses 25 if jobsize is >N pages # # General form : ">n:m" where n is a positive integer, and m is # either the word 'precomputed' or a positive integer. # The special form "yes" is also accepted and is the default. # # This directive can be set either globally or on a per printer # basis. Use this directive when hardware accounting for a particular # printer produces some glitches due to the printer returning # incorrect answers. # # NB : DON'T MODIFY THIS IF YOU DON'T NEED TO. THIS IS ONLY TO BE USED # AS A WORKAROUND FOR SOME PRINTERS. IT'S PROBABLY BETTER TO ALWAYS # SET THIS DIRECTIVE TO 'yes'. THIS DIRECTIVE WILL ONLY BE HONORED # IF PYKOTA DETECTS A DIFFERENCE BETWEEN THE PRECOMPUTED JOB SIZE # AND THE JOB SIZE AS COMPUTED BY PYKOTA EITHER USING HARDWARE OR # SOFTWARE. trustjobsize : yes # Should we deny duplicate jobs ? # # A duplicate is a job sent twice (or more) in a row to the same printer # by the same user. # # This can be defined either globally or on a per printer basis # The default value is 'no', meaning that duplicate jobs are # allowed. # # NB : if an user prints a job, a second user prints another # job, and the first user prints the first job again, # this is NOT considered as a duplicate since the two # identical jobs printed by the first user are not # one just after the other. # # Possible values are 'yes' and 'no' # denyduplicates : no