Skip to content

Commit f7b28d4

Browse files
Merge origin/main into feature/custom-subject
2 parents b7dd70d + f3a507e commit f7b28d4

34 files changed

Lines changed: 3286 additions & 536 deletions

.gitignore

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ cwa-wiki/
2424
docs/
2525
.venv-activate.sh
2626
test_venv
27+
cwa.code-workspace
28+
2729

2830

2931
# Test Scripts
@@ -80,6 +82,7 @@ htmlcov/
8082
.cache
8183
nosetests.xml
8284
coverage.xml
85+
coverage.md
8386
*.cover
8487
*.py,cover
8588
.hypothesis/
@@ -156,7 +159,7 @@ celerybeat.pid
156159
*.sage.py
157160

158161
# Environments
159-
.env
162+
*.env
160163
.venv
161164
env/
162165
venv/
@@ -193,4 +196,7 @@ cython_debug/
193196
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
194197
# and can be added to the global gitignore or merged into this file. For a more nuclear
195198
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
196-
#.idea/
199+
#.idea/
200+
201+
# Dev instance files for testing in the same folder
202+
instance/

CONTRIBUTORS

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
CONTRIBUTORS
22

33
This file is automatically generated. DO NOT EDIT MANUALLY.
4-
Generated on: 2025-11-26T16:02:57.818004Z
54

65
Upstream project: https://github.com/janeczku/calibre-web
76
Fork project (Calibre-Web Automated, since 2024): https://github.com/crocodilestick/calibre-web-automated

Dockerfile

Lines changed: 169 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,5 @@
11
# syntax=docker/dockerfile:1
22

3-
FROM ghcr.io/linuxserver/unrar:latest AS unrar
4-
FROM ghcr.io/linuxserver/baseimage-ubuntu:noble
5-
6-
# Set the default shell for the following RUN instructions to bash instead of sh
7-
SHELL ["/bin/bash", "-c"]
8-
93
# Simple Example Build Command:
104
# docker build \
115
# --tag crocodilestick/calibre-web-automated:dev \
@@ -23,18 +17,17 @@ SHELL ["/bin/bash", "-c"]
2317
# --build-arg="VERSION=2.1.0" \
2418
# --tag crocodilestick/calibre-web-automated:latest .
2519

26-
ARG BUILD_DATE
27-
ARG VERSION
28-
ARG CALIBREWEB_RELEASE=0.6.24
20+
# ============================================================================
21+
# STAGE 1: Dependencies - Install system packages and Python dependencies
22+
# ============================================================================
23+
FROM ghcr.io/linuxserver/baseimage-ubuntu:noble AS dependencies
24+
2925
ARG CALIBRE_RELEASE=8.9.0
3026
ARG KEPUBIFY_RELEASE=v4.0.4
31-
LABEL build_version="Version:- ${VERSION}"
32-
LABEL build_date="${BUILD_DATE}"
33-
LABEL CW-base-version="${CALIBREWEB_RELEASE}"
34-
LABEL maintainer="CrocodileStick"
3527

36-
# Copy local files into the container
37-
COPY --chown=abc:abc . /app/calibre-web-automated/
28+
# Set the default shell for the following RUN instructions to bash instead of sh
29+
SHELL ["/bin/bash", "-c"]
30+
3831
# STEP 1 - Install Required Packages
3932
RUN \
4033
# STEP 1.1 - Add deadsnakes PPA for Python 3.13 and install required apt packages
@@ -67,6 +60,21 @@ RUN \
6760
nano \
6861
sqlite3 \
6962
zip && \
63+
# STEP 1.2 - Install additional Calibre required packages
64+
apt-get install -y --no-install-recommends \
65+
libxtst6 \
66+
libxrandr2 \
67+
libxkbfile1 \
68+
libxcomposite1 \
69+
libopengl0 \
70+
libnss3 \
71+
libxkbcommon0 \
72+
libegl1 \
73+
libxdamage1 \
74+
libgl1 \
75+
libglx-mesa0 \
76+
xz-utils \
77+
binutils && \
7078
# Install lsof 4.99.5 from source to fix hanging issue with 4.95 (issue #654)
7179
echo "**** install lsof 4.99.5 from source ****" && \
7280
LSOF_VERSION="4.99.5" && \
@@ -83,53 +91,30 @@ RUN \
8391
# Create python3 symlink to point to python3.13
8492
ln -sf /usr/bin/python3.13 /usr/bin/python3 && \
8593
# Install pip for Python 3.13
86-
curl -sS https://bootstrap.pypa.io/get-pip.py | python3.13 && \
87-
# STEP 1.2 - Set up a python virtual environment and install pip and wheel packages
88-
cd /app/calibre-web-automated && \
94+
curl -sS https://bootstrap.pypa.io/get-pip.py | python3.13
95+
96+
# STEP 2 - Set up Python virtual environment
97+
RUN \
8998
python3.13 -m venv /lsiopy && \
9099
/lsiopy/bin/pip install -U --no-cache-dir \
91100
pip \
92-
wheel && \
93-
# STEP 1.3 - Installing the required python packages listed in 'requirements.txt' and 'optional-requirements.txt'
101+
wheel
102+
103+
# STEP 3 - Copy requirements files and install Python packages
104+
# Copy only requirements files first to leverage Docker layer caching
105+
COPY --chown=abc:abc requirements.txt optional-requirements.txt /app/calibre-web-automated/
106+
107+
RUN \
108+
# STEP 3.1 - Installing the required python packages listed in 'requirements.txt' and 'optional-requirements.txt'
94109
# HOWEVER, they are not pulled from PyPi directly, they are pulled from linuxserver's Ubuntu Wheel Index
95110
# This is essentially a repository of precompiled some of the most popular packages with C/C++ source code
96111
# This provides the install maximum compatibility with multiple different architectures including: x86_64, armv71 and aarch64
97112
# You can read more about python wheels here: https://realpython.com/python-wheels/
98113
/lsiopy/bin/pip install -U --no-cache-dir --find-links https://wheel-index.linuxserver.io/ubuntu/ -r \
99-
requirements.txt -r optional-requirements.txt && \
100-
# STEP 2 - Move contents of /app/calibre-web-automated/root to / and delete the /app/calibre-web-automated/root directory
101-
cp -R /app/calibre-web-automated/root/* / && \
102-
rm -R /app/calibre-web-automated/root/ && \
103-
# STEP 3 - Run CWA install script to make required dirs, set script permissions and add aliases for CLI commands ect.
104-
chmod +x /app/calibre-web-automated/scripts/setup-cwa.sh && \
105-
/app/calibre-web-automated/scripts/setup-cwa.sh && \
106-
# STEP 4 - Create koplugin.zip from KOReader plugin folder
107-
echo "~~~~ Creating koplugin.zip from KOReader plugin folder... ~~~~" && \
108-
if [ -d "/app/calibre-web-automated/koreader/plugins/cwasync.koplugin" ]; then \
109-
cd /app/calibre-web-automated/koreader/plugins && \
110-
# Calculate digest of all files in the plugin for debugging purposes
111-
echo "Calculating digest of plugin files..." && \
112-
PLUGIN_DIGEST=$(find cwasync.koplugin -type f -name "*.lua" -o -name "*.json" | sort | xargs sha256sum | sha256sum | cut -d' ' -f1) && \
113-
echo "Plugin digest: $PLUGIN_DIGEST" && \
114-
# Create a file named after the digest inside the plugin folder
115-
echo "Plugin files digest: $PLUGIN_DIGEST" > cwasync.koplugin/${PLUGIN_DIGEST}.digest && \
116-
echo "Build date: $(date)" >> cwasync.koplugin/${PLUGIN_DIGEST}.digest && \
117-
echo "Files included:" >> cwasync.koplugin/${PLUGIN_DIGEST}.digest && \
118-
find cwasync.koplugin -type f -name "*.lua" -o -name "*.json" | sort >> cwasync.koplugin/${PLUGIN_DIGEST}.digest && \
119-
zip -r koplugin.zip cwasync.koplugin/ && \
120-
echo "Created koplugin.zip from cwasync.koplugin folder with digest file: ${PLUGIN_DIGEST}.digest"; \
121-
else \
122-
echo "Warning: cwasync.koplugin folder not found, skipping zip creation"; \
123-
fi && \
124-
# STEP 4.1 - Move koplugin.zip to static directory
125-
if [ -f "/app/calibre-web-automated/koreader/plugins/koplugin.zip" ]; then \
126-
mkdir -p /app/calibre-web-automated/cps/static && \
127-
cp /app/calibre-web-automated/koreader/plugins/koplugin.zip /app/calibre-web-automated/cps/static/ && \
128-
echo "Moved koplugin.zip to static directory"; \
129-
else \
130-
echo "Warning: koplugin.zip not found, skipping move to static directory"; \
131-
fi && \
132-
# STEP 5 - Installs kepubify
114+
/app/calibre-web-automated/requirements.txt -r /app/calibre-web-automated/optional-requirements.txt
115+
116+
# STEP 4 - Install kepubify
117+
RUN \
133118
echo "**** install kepubify ****" && \
134119
if [[ $KEPUBIFY_RELEASE == 'newest' ]]; then \
135120
KEPUBIFY_RELEASE=$(curl -sX GET "https://api.github.com/repos/pgaskin/kepubify/releases/latest" \
@@ -144,27 +129,13 @@ RUN \
144129
/usr/bin/kepubify -L \
145130
https://github.com/pgaskin/kepubify/releases/download/${KEPUBIFY_RELEASE}/kepubify-linux-arm64; \
146131
fi && \
147-
# STEP 6 - Install Calibre
148-
# STEP 6.1 - Install additional required packages
149-
apt-get update && \
150-
apt-get install -y --no-install-recommends \
151-
libxtst6 \
152-
libxrandr2 \
153-
libxkbfile1 \
154-
libxcomposite1 \
155-
libopengl0 \
156-
libnss3 \
157-
libxkbcommon0 \
158-
libegl1 \
159-
libxdamage1 \
160-
libgl1 \
161-
libglx-mesa0 \
162-
xz-utils \
163-
binutils && \
164-
# STEP 6.2 - Make the /app/calibre directory for the installed files
165-
mkdir -p \
166-
/app/calibre && \
167-
# STEP 6.3 - Download the desired version of Calibre, determined by the CALIBRE_RELEASE variable and the architecture of the build environment
132+
chmod +x /usr/bin/kepubify
133+
134+
# STEP 5 - Install Calibre
135+
RUN \
136+
# STEP 5.1 - Make the /app/calibre directory for the installed files
137+
mkdir -p /app/calibre && \
138+
# STEP 5.2 - Download the desired version of Calibre, determined by the CALIBRE_RELEASE variable and the architecture of the build environment
168139
if [ "$(uname -m)" == "x86_64" ]; then \
169140
curl -o \
170141
/calibre.txz -L \
@@ -174,46 +145,149 @@ RUN \
174145
/calibre.txz -L \
175146
"https://download.calibre-ebook.com/${CALIBRE_RELEASE}/calibre-${CALIBRE_RELEASE}-arm64.txz"; \
176147
fi && \
177-
# STEP 6.4 - Extract the downloaded file to /app/calibre
148+
# STEP 5.3 - Extract the downloaded file to /app/calibre
178149
tar xf \
179150
/calibre.txz -C \
180151
/app/calibre && \
181-
# STEP 6.4.1 - Remove the ABI tag from the extracted libQt6* files to allow them to be used on older kernels
152+
# STEP 5.3.1 - Remove the ABI tag from the extracted libQt6* files to allow them to be used on older kernels
182153
# Removed in V3.1.4 because it was breaking Calibre features that require Qt6. Replaced with a kernel check in the cwa-init service
183-
# STEP 6.5 - Delete the extracted calibre.txz to save space in final image
184-
rm /calibre.txz && \
185-
# STEP 7 - ADD files referencing the versions of the installed main packages
186-
echo "$VERSION" >| /app/CWA_RELEASE && \
187-
echo "$KEPUBIFY_RELEASE" >| /app/KEPUBIFY_RELEASE && \
188-
echo "$CALIBRE_RELEASE" > /CALIBRE_RELEASE
154+
# STEP 5.4 - Delete the extracted calibre.txz to save space in final image
155+
rm /calibre.txz
156+
157+
# ============================================================================
158+
# STAGE 2: Final - Build the final runtime image
159+
# ============================================================================
160+
FROM ghcr.io/linuxserver/baseimage-ubuntu:noble AS unrar-stage
161+
FROM ghcr.io/linuxserver/unrar:latest AS unrar
162+
163+
FROM ghcr.io/linuxserver/baseimage-ubuntu:noble
164+
165+
ARG BUILD_DATE
166+
ARG VERSION
167+
ARG CALIBREWEB_RELEASE=0.6.24
168+
ARG CALIBRE_RELEASE=8.9.0
169+
ARG KEPUBIFY_RELEASE=v4.0.4
170+
171+
LABEL build_version="Version:- ${VERSION}"
172+
LABEL build_date="${BUILD_DATE}"
173+
LABEL CW-base-version="${CALIBREWEB_RELEASE}"
174+
LABEL maintainer="CrocodileStick"
189175

190-
# Removes packages that are no longer required, also emptying dirs used to build the image that are no longer needed
176+
# Set the default shell for the following RUN instructions to bash instead of sh
177+
SHELL ["/bin/bash", "-c"]
178+
179+
# Copy installed dependencies from the dependencies stage
180+
COPY --from=dependencies /lsiopy /lsiopy
181+
COPY --from=dependencies /usr/bin/kepubify /usr/bin/kepubify
182+
COPY --from=dependencies /app/calibre /app/calibre
183+
COPY --from=dependencies /usr/bin/lsof /usr/bin/lsof
184+
COPY --from=dependencies /usr/bin/python3.13 /usr/bin/python3.13
185+
COPY --from=dependencies /usr/lib/python3.13 /usr/lib/python3.13
186+
187+
# Install only runtime packages (no build tools)
191188
RUN \
192-
echo "**** cleanup ****" && \
193-
apt-get -y purge \
194-
build-essential \
195-
libldap2-dev \
196-
libsasl2-dev \
197-
gettext \
198-
python3.13-dev \
199-
software-properties-common && \
189+
echo "**** add deadsnakes PPA for Python 3.13 runtime ****" && \
190+
apt-get update && \
191+
apt-get install -y --no-install-recommends software-properties-common && \
192+
add-apt-repository ppa:deadsnakes/ppa && \
193+
apt-get update && \
194+
echo "**** install runtime packages ****" && \
195+
apt-get install -y --no-install-recommends \
196+
imagemagick \
197+
ghostscript \
198+
libldap2 \
199+
libmagic1 \
200+
libsasl2-2 \
201+
libxi6 \
202+
libxslt1.1 \
203+
xdg-utils \
204+
inotify-tools \
205+
python3.13 \
206+
nano \
207+
sqlite3 \
208+
zip \
209+
libxtst6 \
210+
libxrandr2 \
211+
libxkbfile1 \
212+
libxcomposite1 \
213+
libopengl0 \
214+
libnss3 \
215+
libxkbcommon0 \
216+
libegl1 \
217+
libxdamage1 \
218+
libgl1 \
219+
libglx-mesa0 \
220+
xz-utils \
221+
curl && \
222+
# Create python3 symlink to point to python3.13
223+
ln -sf /usr/bin/python3.13 /usr/bin/python3 && \
224+
# Cleanup
225+
apt-get -y purge software-properties-common && \
200226
apt-get -y autoremove && \
201227
rm -rf \
202228
/tmp/* \
203229
/var/lib/apt/lists/* \
204230
/var/tmp/* \
205231
/root/.cache
206232

207-
# add unrar
233+
# STEP 6 - Copy application files
234+
# Copy the rest of the application code (changes most frequently)
235+
COPY --chown=abc:abc . /app/calibre-web-automated/
236+
237+
# STEP 7 - Configure application
238+
RUN \
239+
# STEP 7.1 - Move contents of /app/calibre-web-automated/root to / and delete the /app/calibre-web-automated/root directory
240+
cp -R /app/calibre-web-automated/root/* / && \
241+
rm -R /app/calibre-web-automated/root/ && \
242+
# STEP 7.2 - Run CWA install script to make required dirs, set script permissions and add aliases for CLI commands ect.
243+
chmod +x /app/calibre-web-automated/scripts/setup-cwa.sh && \
244+
/app/calibre-web-automated/scripts/setup-cwa.sh && \
245+
# STEP 7.3 - Create koplugin.zip from KOReader plugin folder
246+
echo "~~~~ Creating koplugin.zip from KOReader plugin folder... ~~~~" && \
247+
if [ -d "/app/calibre-web-automated/koreader/plugins/cwasync.koplugin" ]; then \
248+
cd /app/calibre-web-automated/koreader/plugins && \
249+
# Calculate digest of all files in the plugin for debugging purposes
250+
echo "Calculating digest of plugin files..." && \
251+
PLUGIN_DIGEST=$(find cwasync.koplugin -type f -name "*.lua" -o -name "*.json" | sort | xargs sha256sum | sha256sum | cut -d' ' -f1) && \
252+
echo "Plugin digest: $PLUGIN_DIGEST" && \
253+
# Create a file named after the digest inside the plugin folder
254+
echo "Plugin files digest: $PLUGIN_DIGEST" > cwasync.koplugin/${PLUGIN_DIGEST}.digest && \
255+
echo "Build date: $(date)" >> cwasync.koplugin/${PLUGIN_DIGEST}.digest && \
256+
echo "Files included:" >> cwasync.koplugin/${PLUGIN_DIGEST}.digest && \
257+
find cwasync.koplugin -type f -name "*.lua" -o -name "*.json" | sort >> cwasync.koplugin/${PLUGIN_DIGEST}.digest && \
258+
zip -r koplugin.zip cwasync.koplugin/ && \
259+
echo "Created koplugin.zip from cwasync.koplugin folder with digest file: ${PLUGIN_DIGEST}.digest"; \
260+
else \
261+
echo "Warning: cwasync.koplugin folder not found, skipping zip creation"; \
262+
fi && \
263+
# STEP 7.4 - Move koplugin.zip to static directory
264+
if [ -f "/app/calibre-web-automated/koreader/plugins/koplugin.zip" ]; then \
265+
mkdir -p /app/calibre-web-automated/cps/static && \
266+
cp /app/calibre-web-automated/koreader/plugins/koplugin.zip /app/calibre-web-automated/cps/static/ && \
267+
echo "Moved koplugin.zip to static directory"; \
268+
else \
269+
echo "Warning: koplugin.zip not found, skipping move to static directory"; \
270+
fi && \
271+
# STEP 7.5 - ADD files referencing the versions of the installed main packages
272+
echo "$VERSION" >| /app/CWA_RELEASE && \
273+
echo "$KEPUBIFY_RELEASE" >| /app/KEPUBIFY_RELEASE && \
274+
echo "$CALIBRE_RELEASE" > /CALIBRE_RELEASE
275+
276+
# Add unrar from unrar stage
208277
COPY --from=unrar /usr/bin/unrar-ubuntu /usr/bin/unrar
209278

210-
# set calibre environment variable
279+
# Set calibre environment variable
211280
ENV CALIBRE_CONFIG_DIR=/config/.config/calibre
212281

213-
# ports and volumes
282+
# Ports and volumes
214283
WORKDIR /config
215284
# The default port CWA listens on. Can be overridden with the CWA_PORT_OVERRIDE environment variable.
216285
EXPOSE 8083
217286
VOLUME /config
218287
VOLUME /cwa-book-ingest
219288
VOLUME /calibre-library
289+
290+
# Health check for container orchestration
291+
# Uses shell form to support environment variable substitution for CWA_PORT_OVERRIDE
292+
HEALTHCHECK --interval=30s --timeout=3s --start-period=120s --retries=3 \
293+
CMD curl -f http://localhost:${CWA_PORT_OVERRIDE:-8083}/ || exit 1

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ ___
7373
\
7474
[![](https://dcbadge.limes.pink/api/server/https://discord.gg/EjgSeek94R)](https://discord.gg/EjgSeek94R)
7575

76-
- Or alternativly make your own companion project, come hang out and or come get help if you're facing issues :)
76+
- Or alternatively make your own companion project, come hang out and or come get help if you're facing issues :)
7777

7878
## 🚨 To users planning to deploy via Network Shares (particularly NFS) 🚨
7979

cps/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@
4343
mimetypes.add_type('application/epub+zip', '.epub')
4444
mimetypes.add_type('application/epub+zip', '.kepub')
4545
mimetypes.add_type('text/xml', '.fb2')
46-
mimetypes.add_type('application/octet-stream', '.mobi')
47-
mimetypes.add_type('application/octet-stream', '.prc')
46+
mimetypes.add_type('application/x-mobipocket-ebook', '.mobi')
47+
mimetypes.add_type('application/x-mobipocket-ebook', '.prc')
4848
mimetypes.add_type('application/vnd.amazon.ebook', '.azw')
4949
mimetypes.add_type('application/x-mobi8-ebook', '.azw3')
5050
mimetypes.add_type('application/x-cbr', '.cbr')

0 commit comments

Comments
 (0)