Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
887e6f95e1 |
@@ -1,192 +0,0 @@
|
|||||||
# epub2pdf — Document → PDF Converter
|
|
||||||
|
|
||||||
> A small, self-hosted web app that turns 27 document formats — EPUB3 ebooks, Office
|
|
||||||
> documents, TeX/LaTeX, Org, AsciiDoc, RST, Markdown, HTML, plain text, CSV/TSV, JSON, XML,
|
|
||||||
> SVG, images, and existing PDFs — into PDFs. **No file ever leaves your machine.**
|
|
||||||
|
|
||||||
Built for people who want a private, on-premise conversion pipeline: run it behind a firewall,
|
|
||||||
on your own server, with no data egress and no account required.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Contents
|
|
||||||
|
|
||||||
- [What it does](#what-it-does)
|
|
||||||
- [Features](#features)
|
|
||||||
- [How it works](#how-it-works)
|
|
||||||
- [Security](#security)
|
|
||||||
- [Quick start](#quick-start)
|
|
||||||
- [Docker (recommended)](#docker-recommended)
|
|
||||||
- [Local (no Docker)](#local-no-docker)
|
|
||||||
- [Coolify](#coolify)
|
|
||||||
- [Command line](#command-line)
|
|
||||||
- [Live sites](#live-sites)
|
|
||||||
- [Documentation](#documentation)
|
|
||||||
- [Source repository](#source-repository)
|
|
||||||
- [Attribution](#attribution)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## What it does
|
|
||||||
|
|
||||||
doc2pdf takes a single uploaded file and produces a single PDF. It is **self-hosted**:
|
|
||||||
you run the container on your own hardware, so nothing you upload is processed anywhere else.
|
|
||||||
|
|
||||||
The web UI accepts a drop-and-go upload; an HTTP API and a CLI let you automate it. Every
|
|
||||||
format is detected from the file's real bytes (magic-byte detection), not its extension.
|
|
||||||
|
|
||||||
For a complete format-by-format breakdown, the web UI tour, troubleshooting tables, and the
|
|
||||||
full settings reference, read the [USER_GUIDE.md](USER_GUIDE.md). It is the primary,
|
|
||||||
detailed documentation — this README is only the front door.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- **27 input formats → PDF.** EPUB3, HTML/HTML5, Markdown, Office (`.docx`, `.odt`, `.rtf`),
|
|
||||||
TeX/LaTeX, Org, AsciiDoc, reStructuredText, plain text, CSV/TSV, JSON, XML, SVG, images
|
|
||||||
(PNG/JPEG/WebP/TIFF/BMP), and existing PDF.
|
|
||||||
- **No file ever leaves your machine.** There is no data egress — uploads and generated PDFs
|
|
||||||
stay on the host that runs the app.
|
|
||||||
- **Self-hosted and private.** No account, no login, no telemetry. Deploy behind your firewall.
|
|
||||||
- **CJK support.** Ships with Noto CJK fonts so Chinese, Japanese, and Korean render correctly.
|
|
||||||
- **RTL support.** Right-to-left books render correctly for Arabic and Hebrew.
|
|
||||||
- **Faithful Office rendering.** The Office trio renders with **Rich** mode (default) through
|
|
||||||
LibreOffice — preserving fonts, page size, and colors — or falls back to **Standard** mode
|
|
||||||
through pandoc.
|
|
||||||
- **Fast and concurrency-safe.** A single gunicorn worker with 8 threads provides 4
|
|
||||||
concurrent conversion slots. Uploads cap at 400 MB, output caps at 200 MB.
|
|
||||||
- **Tested.** 27 formats supported with 152/152 tests green.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## How it works
|
|
||||||
|
|
||||||
A browser upload becomes a server-side job that flows through a small, well-defined pipeline:
|
|
||||||
|
|
||||||
```mermaid
|
|
||||||
flowchart TD
|
|
||||||
Browser[Browser — upload a file] --> API[/api/convert/]
|
|
||||||
API --> Queue[Job queue: 1 worker · 4 slots]
|
|
||||||
Queue --> Family{File family?}
|
|
||||||
Family -->|EPUB, HTML, Markdown, JSON, XML, SVG, images, text| W[WeasyPrint renderer]
|
|
||||||
Family --> Office[".docx · .odt · .rtf"]
|
|
||||||
Office --> Mode{Render mode?}
|
|
||||||
Mode -->|Rich (default)| LO[LibreOffice headless]
|
|
||||||
Mode -->|Standard| PC[Pandoc]
|
|
||||||
W --> Guards[Security guards]
|
|
||||||
LO --> Guards
|
|
||||||
PC --> Guards
|
|
||||||
Guards --> Finalize[finalize PDF tail]
|
|
||||||
Finalize --> Download[Download PDF]
|
|
||||||
```
|
|
||||||
|
|
||||||
Every path — whether EPUB/HTML/Markdown renders through WeasyPrint, or the Office trio renders
|
|
||||||
through LibreOffice or pandoc — passes through the same security guards before the final PDF is
|
|
||||||
written. See the [security section](#security) for details.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Security
|
|
||||||
|
|
||||||
This release ships with every previously identified finding fixed. The pipeline applies these
|
|
||||||
guards before writing output:
|
|
||||||
|
|
||||||
- **Decompression-bomb guard.** Uploads stream through a byte-counted extractor that aborts
|
|
||||||
mid-stream if extraction exceeds its budget.
|
|
||||||
- **SSRF / data-egress blocking.** Remote resources are validated before rendering, and remote
|
|
||||||
schemes (http, https, ftp, ws, wss, file) are blocked — local `data:` resources still render.
|
|
||||||
- **Stored-XSS stripping.** `<script>` tags are stripped from HTML, SVG, EPUB, Markdown, CSV, XML,
|
|
||||||
and other render paths before they reach the renderer.
|
|
||||||
- **Output cap.** Output PDFs are capped at 200 MB; uploads are capped at 400 MB.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Quick start
|
|
||||||
|
|
||||||
### Docker (recommended)
|
|
||||||
|
|
||||||
Build the image, then run it with a persistent data volume:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker build -t epub2pdf .
|
|
||||||
docker run -d --name epub2pdf \
|
|
||||||
-p 8030:8030 \
|
|
||||||
-v epub2pdf-data:/app/data \
|
|
||||||
epub2pdf
|
|
||||||
```
|
|
||||||
|
|
||||||
The `epub2pdf-data` volume keeps uploads and generated PDFs across restarts. Open
|
|
||||||
http://localhost:8030 in a browser.
|
|
||||||
|
|
||||||
To iterate locally without committing to Docker, `./start.sh` runs the app in the foreground
|
|
||||||
with an auto-restart loop:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
./start.sh # http://0.0.0.0:8030
|
|
||||||
PORT=9000 ./start.sh # custom port
|
|
||||||
```
|
|
||||||
|
|
||||||
### Local (no Docker)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 1. install dependencies (Python 3.11+)
|
|
||||||
pip install -r requirements.txt
|
|
||||||
|
|
||||||
# 2. start the web server
|
|
||||||
python app.py # -> http://localhost:8030
|
|
||||||
```
|
|
||||||
|
|
||||||
WeasyPrint also needs the pango system libraries. On Debian/Ubuntu, install at least
|
|
||||||
`libpango-1.0-0 libpangoft2-1.0-0 libharfbuzz0b fontconfig fonts-noto-cjk shared-mime-info`
|
|
||||||
plus `pandoc` for the office/TeX/markup formats.
|
|
||||||
|
|
||||||
### Coolify
|
|
||||||
|
|
||||||
Deploy as a Dockerfile-based service: publish port **8030** and mount a volume at **`/app/data`**.
|
|
||||||
For the exact three-step walkthrough, read [COOLIFY.md](COOLIFY.md).
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Command line
|
|
||||||
|
|
||||||
Convert a file and exit, without the web server:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
python app.py --cli book.epub --output ./out
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Live sites
|
|
||||||
|
|
||||||
| Environment | URL |
|
|
||||||
|---|---|
|
|
||||||
| Production (main) | http://epub2pdf.209.126.10.202.sslip.io |
|
|
||||||
| Testing (DEV-TEST) | http://epub2pdftest.209.126.10.202.sslip.io |
|
|
||||||
|
|
||||||
Both run on Coolify and report `running:healthy`.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Documentation
|
|
||||||
|
|
||||||
- **[USER_GUIDE.md](USER_GUIDE.md)** — the primary, full documentation: format reference, web UI
|
|
||||||
tour, rendering modes, HTTP API, configuration, fonts, and troubleshooting.
|
|
||||||
- **[COOLIFY.md](COOLIFY.md)** — deployment guide for Coolify (Dockerfile service, port, volume).
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Source repository
|
|
||||||
|
|
||||||
The source lives at:
|
|
||||||
|
|
||||||
https://gitea.network-ewee.com/sirdave73/epub2pdf.git
|
|
||||||
|
|
||||||
Gitea Actions runs the pytest suite on every push and pull request to `main`.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Attribution
|
|
||||||
|
|
||||||
epub2pdf is a project of **Network-Ewee.com**.
|
|
||||||
@@ -49,7 +49,7 @@ for _d in (UPLOAD_DIR, OUTPUT_DIR, WORK_DIR):
|
|||||||
MAX_UPLOAD_MB = 400
|
MAX_UPLOAD_MB = 400
|
||||||
|
|
||||||
# Semantic version exposed by /health so the UI can show "vX.Y.Z" in the footer.
|
# Semantic version exposed by /health so the UI can show "vX.Y.Z" in the footer.
|
||||||
APP_VERSION = "2.1.3"
|
APP_VERSION = "2.1.2"
|
||||||
|
|
||||||
# req 3 (health): supported formats advertised to clients. Additive key — the
|
# req 3 (health): supported formats advertised to clients. Additive key — the
|
||||||
# existing /health contract asserts only status + max_upload_mb.
|
# existing /health contract asserts only status + max_upload_mb.
|
||||||
|
|||||||
Reference in New Issue
Block a user