COPS is a Web application allowing the publishing of a Calibre e-books library as a OPDS catalog (Open Publication Distribution System). It allow to easily download e-books from a Calibre library on a e-reader supporting the OPDS format.

This howto is tested on:

  • Debian 10.0 Buster

This howto is tested with these software’s versions:

  • 1.1.3


This howto requires :

This howto recommends:

This howto recommends one of this tools:


Set the domain name hosting the application:


Set the username used to restrict the access to the software by a login (optional):


Set the method used to setup a HTTPS connnection: “auto” to automatically create a free “Let’s Encrypt (en)” SSL certificate, or the name of a SSL certificate created as described by Create a SSL / TLS certificate on Debian (optional, recommended):


Provide the path to the Calibre library (synchronized by Dropbox, Seafile, or WebDAV, for example):


Set the web site time zone (see List of Supported Timezones on (en)):

timeZone="$(command cat '/etc/timezone')"

Additional settings

Set the library’s owner’s name:

authorName="Firstname Lastname"

Set the library’s owner’s web site URL:


Set the library’s owner’s email address:



Detect if sudo is available (“command” is used if not):

command type -f 'sudo' &>'/dev/null' && cmdProxy='sudo'

Set the software code (used to set the installation paths):


Set the installation path:


Clean-up the Calibre library path (removal of the trailing ‘/’):

calibrePath="$(echo "${calibrePath}" | sed -e 's|/$||g')"

Detect if HTTPS is used:

[[ -n "${sslKeyName}" \
    && ( -e "/etc/ssl/private/${sslKeyName}.key" \
    || "${sslKeyName}" = 'auto' ) ]] && protocol="https"

Create the install path parent folder:

${cmdProxy} mkdir --parent "$(command dirname "${installPath}")"

Environment setup

Install the required software:

${cmdProxy} apt-get install php-gd php-sqlite3 php-json \
    php-intl php-xml php-mbstring php-zip git apg \
    libapache2-mod-xsendfile unzip

Enable xsendfile, expires and rewrite modules for Apache 2:

${cmdProxy} a2enmod xsendfile expires rewrite

Reload PHP and Apache 2 configuration:

${cmdProxy} php-tools --reload
${cmdProxy} systemctl force-reload 'apache2'

Application’s installation

Download the software’s latest stable version:

source="$(${cmdProxy} biapy-downloader \
    --output-path="${installPath}" --extract --forge='github' \
    --file-template='' 'seblucas/cops')"

Application setup

Create the configuration file:

${cmdProxy} cp "${installPath}/config_local.php.example" "${installPath}/config_local.php"

Set the Calibre library path:

${cmdProxy} sed -i \
    -e "s|calibre_directory.*|calibre_directory'] = '${calibrePath}/';|" \

Enable URL rewriting:

${cmdProxy} sed -i \
    -e "s|cops_use_url_rewriting.*|cops_use_url_rewriting'] = '1';|" \

Enable the conversion to kepub format (for Kobo readers):

${cmdProxy} tee -a "${installPath}/config_local.php" \
    <<< "    \$config['cops_provide_kepub'] = '1';"

Enable X-SendFile use:

${cmdProxy} tee -a "${installPath}/config_local.php" \
    <<< "    \$config['cops_x_accel_redirect'] = 'X-Sendfile';"
customConf="  <IfModule mod_xsendfile.c>
    XSendFilePath \"${calibrePath}\"

Enable the update of epub files metadata before download:

${cmdProxy} tee -a "${installPath}/config_local.php" \
    <<< "    \$config['cops_update_epub-metadata'] = '1';"

Setup the “Send to Kindle / Email” functionnality:

${cmdProxy} tee -a "${installPath}/config_local.php" \
    <<< "    \$config['cops_update_epub-metadata'] = array(
      '' => 'localhost',
      'smtp.username' => '',
      'smtp.password' => '',
      '' => '',
      'smtp.from' => '${authorEmail}'

Enhance the search results:

${cmdProxy} tee -a "${installPath}/config_local.php" \
    <<< "    \$config['cops_normalized_search'] = '1';"

Set the OPDS library owner information:

${cmdProxy} tee -a "${installPath}/config_local.php" \
    <<< "    \$config['cops_author_name'] = '${authorName}';
    \$config['cops_author_uri'] = '${authorUrl}';
    \$config['cops_author_email'] = '${authorEmail}';

Access restriction

Generate a random password:

userPassword="$(command apg -q -a 0 -n 1 -M NCL)"

Create a htpasswd file:

[[ -n "${userName}" ]] \
  && ${cmdProxy} htpasswd -cbm "${installPath}/.htpasswd" \
                          "${userName}" "${userPassword}"

Build the proper Apache configuration:

if [[ -n "${userName}" ]]; then
  <FilesMatch \"\\.php\$\">
    AuthUserFile \"${installPath}/.htpasswd\"
    AuthName \"${domain}\"
    AuthType Basic
    Require valid-user

This configuration (stored in the “authConf” variable) will be aded by a2tools to the application VirtualHost configuration.

Automatic updates

Install the updater script :

${cmdProxy} wget --quiet --no-check-certificate \
    --output-document='/usr/local/bin/cops-updater' \

Declare the downloaded file as executable:

${cmdProxy} chmod +x '/usr/local/bin/cops-updater'

Configure biapy-updater automatic updates to check for newer versions of the updater script:

${cmdProxy} tee -a '/etc/biapy-updater.conf' <<< 'cops-updater'

Setup a cron task for checking daily for newer versions of the software:

${cmdProxy} tee "/etc/cron.d/update-${softwareCode}-${domain//./-}" \
  <<< "#
# Regular cron jobs for updating COPS at ${domain}
# Every night at 6 o'clock.
0 6 * * *   root    test -x /usr/local/bin/cops-updater && /usr/local/bin/cops-updater '${domain}'"

Reload cron daemon configuration:

${cmdProxy} systemctl 'restart' 'cron'

VirtualHost setup

Create the HTTP server configuration for the domain:

if [[ -n "${sslKeyName}" \
  && ( -e "/etc/ssl/private/${sslKeyName}.key" \
  || "${sslKeyName}" = 'auto' ) ]]; then
  ${cmdProxy} a2tools --ssl="${sslKeyName}" \
    --custom-options="${customConf}" --overrides='All' \
    "${domain}" "${installPath}"
  ${cmdProxy} a2tools  \
    --custom-options="${customConf}" --overrides='All' \
    "${domain}" "${installPath}"

The software is now available on the domain.

This command show the application access information:

echo "URL: ${protocol}://${domain}/
OPDS feed: ${protocol}://${domain}/feed.php
Username: ${userName}
Password: ${userPassword}"


Backup the installation with Backup Manager (see Install Backup Manager on Debian):

${cmdProxy} backup-manager-tools add "${installPath}"




Leave a Reply

Avatar placeholder

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.