Compare commits

...
9 Commits
Author SHA1 Message Date
alam00000 36b98eb1af Release v1.16.1 2026-01-26 13:52:17 +05:30
alam00000 b059ac6ada chore: migrate Docker Hub to bentopdfteam, add Podman/Quadlet support
- Migrate Docker Hub account from bentopdf to bentopdfteam
- Make GHCR the recommended container registry
- Add Podman and Podman Compose support
- Add Podman Quadlet (systemd) documentation
- Add Table of Contents to README
2026-01-26 13:34:50 +05:30
github-actions[bot] 21b9b58610 @JaL-P has signed the CLA in alam00000/bentopdf#410 2026-01-20 21:00:50 +00:00
github-actions[bot] bf6e212a2d @LoganK has signed the CLA in alam00000/bentopdf#405 2026-01-19 09:14:32 +00:00
alam00000 fb8c8c07ae chore: update licensing information and readme 2026-01-15 21:53:01 +05:30
github-actions[bot] b9b98294b5 @spwoodcock has signed the CLA in alam00000/bentopdf#388 2026-01-15 11:54:02 +00:00
github-actions[bot] 61390d97fe @sheing-google has signed the CLA in alam00000/bentopdf#386 2026-01-14 21:38:20 +00:00
alam00000 8f628e2b5a ci(docker): refactor build workflow to separate platform builds and merge manifests 2026-01-14 22:38:56 +05:30
alam00000 7787e1d9ac chore(docker,docs): improve npm reliability and update feature documentation
- Configure npm fetch retries and timeouts in Dockerfile to handle network issues during dependency installation
- Set fetch-retries to 5, fetch-retry-mintimeout to 60s, fetch-retry-maxtimeout to 300s, and fetch-timeout to 600s
- Update README.md feature descriptions for improved clarity and accuracy
- Add bookmark preservation notes to Merge PDFs and Alternate & Mix Pages tools
- Add new features: Rotate by Custom Degrees, PDF Booklet, PDF Form Filler, Deskew PDF, and Font to Outline
- Enhance PDF Editor description with specific capabilities (annotate, highlight, redact, comment, shapes, images, search)
- Reorganize feature table entries for better logical grouping
- Remove duplicate "Fill Forms" entry in favor of new PDF Form Filler tool
2026-01-14 22:20:41 +05:30
13 changed files with 958 additions and 284 deletions
+186 -26
View File
@@ -51,10 +51,11 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
docker-build-and-push:
# Build each platform natively in parallel, then merge manifests
build-amd64:
runs-on: ubuntu-latest
permissions:
contents: write
contents: read
packages: write
strategy:
matrix:
@@ -69,9 +70,6 @@ jobs:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
@@ -88,7 +86,7 @@ jobs:
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract version and determine release type
- name: Extract version
id: version
run: |
if [[ $GITHUB_REF == refs/tags/v* ]]; then
@@ -103,8 +101,7 @@ jobs:
echo "is_release=false" >> $GITHUB_OUTPUT
fi
# Build and push for releases (with 'latest' tag)
- name: Build and push ${{ matrix.mode.name }} image (release)
- name: Build and push amd64 ${{ matrix.mode.name }} (release)
if: steps.version.outputs.is_release == 'true'
uses: docker/build-push-action@v6
with:
@@ -112,18 +109,13 @@ jobs:
build-args: |
SIMPLE_MODE=${{ matrix.mode.simple_mode }}
tags: |
bentopdf/bentopdf${{ matrix.mode.suffix }}:latest
bentopdf/bentopdf${{ matrix.mode.suffix }}:${{ steps.version.outputs.version_without_v }}
bentopdf/bentopdf${{ matrix.mode.suffix }}:${{ steps.version.outputs.version }}
ghcr.io/${{ github.repository_owner }}/bentopdf${{ matrix.mode.suffix }}:latest
ghcr.io/${{ github.repository_owner }}/bentopdf${{ matrix.mode.suffix }}:${{ steps.version.outputs.version_without_v }}
ghcr.io/${{ github.repository_owner }}/bentopdf${{ matrix.mode.suffix }}:${{ steps.version.outputs.version }}
platforms: linux/amd64,linux/arm64
cache-from: type=gha
cache-to: type=gha,mode=max
bentopdfteam/bentopdf${{ matrix.mode.suffix }}:${{ steps.version.outputs.version }}-amd64
ghcr.io/${{ github.repository_owner }}/bentopdf${{ matrix.mode.suffix }}:${{ steps.version.outputs.version }}-amd64
platforms: linux/amd64
cache-from: type=gha,scope=amd64-${{ matrix.mode.name }}
cache-to: type=gha,mode=max,scope=amd64-${{ matrix.mode.name }}
# Build and push for main branch (with 'edge' tag)
- name: Build and push ${{ matrix.mode.name }} image (edge)
- name: Build and push amd64 ${{ matrix.mode.name }} (edge)
if: steps.version.outputs.is_release == 'false'
uses: docker/build-push-action@v6
with:
@@ -131,10 +123,178 @@ jobs:
build-args: |
SIMPLE_MODE=${{ matrix.mode.simple_mode }}
tags: |
bentopdf/bentopdf${{ matrix.mode.suffix }}:edge
bentopdf/bentopdf${{ matrix.mode.suffix }}:sha-${{ steps.version.outputs.short_sha }}
ghcr.io/${{ github.repository_owner }}/bentopdf${{ matrix.mode.suffix }}:edge
ghcr.io/${{ github.repository_owner }}/bentopdf${{ matrix.mode.suffix }}:sha-${{ steps.version.outputs.short_sha }}
platforms: linux/amd64,linux/arm64
cache-from: type=gha
cache-to: type=gha,mode=max
bentopdfteam/bentopdf${{ matrix.mode.suffix }}:edge-amd64
ghcr.io/${{ github.repository_owner }}/bentopdf${{ matrix.mode.suffix }}:edge-amd64
platforms: linux/amd64
cache-from: type=gha,scope=amd64-${{ matrix.mode.name }}
cache-to: type=gha,mode=max,scope=amd64-${{ matrix.mode.name }}
build-arm64:
runs-on: ubuntu-24.04-arm # Native ARM64 runner
permissions:
contents: read
packages: write
strategy:
matrix:
mode:
- name: default
simple_mode: false
suffix: ""
- name: simple
simple_mode: true
suffix: "-simple"
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_TOKEN }}
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract version
id: version
run: |
if [[ $GITHUB_REF == refs/tags/v* ]]; then
VERSION=${GITHUB_REF#refs/tags/}
echo "version=${VERSION}" >> $GITHUB_OUTPUT
echo "version_without_v=${VERSION#v}" >> $GITHUB_OUTPUT
echo "is_release=true" >> $GITHUB_OUTPUT
else
SHORT_SHA=${GITHUB_SHA::7}
echo "version=edge" >> $GITHUB_OUTPUT
echo "short_sha=${SHORT_SHA}" >> $GITHUB_OUTPUT
echo "is_release=false" >> $GITHUB_OUTPUT
fi
- name: Build and push arm64 ${{ matrix.mode.name }} (release)
if: steps.version.outputs.is_release == 'true'
uses: docker/build-push-action@v6
with:
push: true
build-args: |
SIMPLE_MODE=${{ matrix.mode.simple_mode }}
tags: |
bentopdfteam/bentopdf${{ matrix.mode.suffix }}:${{ steps.version.outputs.version }}-arm64
ghcr.io/${{ github.repository_owner }}/bentopdf${{ matrix.mode.suffix }}:${{ steps.version.outputs.version }}-arm64
platforms: linux/arm64
cache-from: type=gha,scope=arm64-${{ matrix.mode.name }}
cache-to: type=gha,mode=max,scope=arm64-${{ matrix.mode.name }}
- name: Build and push arm64 ${{ matrix.mode.name }} (edge)
if: steps.version.outputs.is_release == 'false'
uses: docker/build-push-action@v6
with:
push: true
build-args: |
SIMPLE_MODE=${{ matrix.mode.simple_mode }}
tags: |
bentopdfteam/bentopdf${{ matrix.mode.suffix }}:edge-arm64
ghcr.io/${{ github.repository_owner }}/bentopdf${{ matrix.mode.suffix }}:edge-arm64
platforms: linux/arm64
cache-from: type=gha,scope=arm64-${{ matrix.mode.name }}
cache-to: type=gha,mode=max,scope=arm64-${{ matrix.mode.name }}
# Merge manifests after both platforms are built
merge-manifests:
runs-on: ubuntu-latest
needs: [build-amd64, build-arm64]
permissions:
contents: write
packages: write
strategy:
matrix:
mode:
- name: default
suffix: ""
- name: simple
suffix: "-simple"
steps:
- name: Login to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_TOKEN }}
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract version
id: version
run: |
if [[ $GITHUB_REF == refs/tags/v* ]]; then
VERSION=${GITHUB_REF#refs/tags/}
echo "version=${VERSION}" >> $GITHUB_OUTPUT
echo "version_without_v=${VERSION#v}" >> $GITHUB_OUTPUT
echo "is_release=true" >> $GITHUB_OUTPUT
else
SHORT_SHA=${GITHUB_SHA::7}
echo "version=edge" >> $GITHUB_OUTPUT
echo "short_sha=${SHORT_SHA}" >> $GITHUB_OUTPUT
echo "is_release=false" >> $GITHUB_OUTPUT
fi
- name: Create and push manifest (release)
if: steps.version.outputs.is_release == 'true'
run: |
# DockerHub manifests
docker buildx imagetools create -t bentopdfteam/bentopdf${{ matrix.mode.suffix }}:latest \
bentopdfteam/bentopdf${{ matrix.mode.suffix }}:${{ steps.version.outputs.version }}-amd64 \
bentopdfteam/bentopdf${{ matrix.mode.suffix }}:${{ steps.version.outputs.version }}-arm64
docker buildx imagetools create -t bentopdfteam/bentopdf${{ matrix.mode.suffix }}:${{ steps.version.outputs.version }} \
bentopdfteam/bentopdf${{ matrix.mode.suffix }}:${{ steps.version.outputs.version }}-amd64 \
bentopdfteam/bentopdf${{ matrix.mode.suffix }}:${{ steps.version.outputs.version }}-arm64
docker buildx imagetools create -t bentopdfteam/bentopdf${{ matrix.mode.suffix }}:${{ steps.version.outputs.version_without_v }} \
bentopdfteam/bentopdf${{ matrix.mode.suffix }}:${{ steps.version.outputs.version }}-amd64 \
bentopdfteam/bentopdf${{ matrix.mode.suffix }}:${{ steps.version.outputs.version }}-arm64
# GHCR manifests
docker buildx imagetools create -t ghcr.io/${{ github.repository_owner }}/bentopdf${{ matrix.mode.suffix }}:latest \
ghcr.io/${{ github.repository_owner }}/bentopdf${{ matrix.mode.suffix }}:${{ steps.version.outputs.version }}-amd64 \
ghcr.io/${{ github.repository_owner }}/bentopdf${{ matrix.mode.suffix }}:${{ steps.version.outputs.version }}-arm64
docker buildx imagetools create -t ghcr.io/${{ github.repository_owner }}/bentopdf${{ matrix.mode.suffix }}:${{ steps.version.outputs.version }} \
ghcr.io/${{ github.repository_owner }}/bentopdf${{ matrix.mode.suffix }}:${{ steps.version.outputs.version }}-amd64 \
ghcr.io/${{ github.repository_owner }}/bentopdf${{ matrix.mode.suffix }}:${{ steps.version.outputs.version }}-arm64
docker buildx imagetools create -t ghcr.io/${{ github.repository_owner }}/bentopdf${{ matrix.mode.suffix }}:${{ steps.version.outputs.version_without_v }} \
ghcr.io/${{ github.repository_owner }}/bentopdf${{ matrix.mode.suffix }}:${{ steps.version.outputs.version }}-amd64 \
ghcr.io/${{ github.repository_owner }}/bentopdf${{ matrix.mode.suffix }}:${{ steps.version.outputs.version }}-arm64
- name: Create and push manifest (edge)
if: steps.version.outputs.is_release == 'false'
run: |
# DockerHub manifests
docker buildx imagetools create -t bentopdfteam/bentopdf${{ matrix.mode.suffix }}:edge \
bentopdfteam/bentopdf${{ matrix.mode.suffix }}:edge-amd64 \
bentopdfteam/bentopdf${{ matrix.mode.suffix }}:edge-arm64
docker buildx imagetools create -t bentopdfteam/bentopdf${{ matrix.mode.suffix }}:sha-${{ steps.version.outputs.short_sha }} \
bentopdfteam/bentopdf${{ matrix.mode.suffix }}:edge-amd64 \
bentopdfteam/bentopdf${{ matrix.mode.suffix }}:edge-arm64
# GHCR manifests
docker buildx imagetools create -t ghcr.io/${{ github.repository_owner }}/bentopdf${{ matrix.mode.suffix }}:edge \
ghcr.io/${{ github.repository_owner }}/bentopdf${{ matrix.mode.suffix }}:edge-amd64 \
ghcr.io/${{ github.repository_owner }}/bentopdf${{ matrix.mode.suffix }}:edge-arm64
docker buildx imagetools create -t ghcr.io/${{ github.repository_owner }}/bentopdf${{ matrix.mode.suffix }}:sha-${{ steps.version.outputs.short_sha }} \
ghcr.io/${{ github.repository_owner }}/bentopdf${{ matrix.mode.suffix }}:edge-amd64 \
ghcr.io/${{ github.repository_owner }}/bentopdf${{ matrix.mode.suffix }}:edge-arm64
+5 -1
View File
@@ -8,7 +8,11 @@ WORKDIR /app
COPY package*.json ./
COPY vendor ./vendor
ENV HUSKY=0
RUN npm ci
RUN npm config set fetch-retries 5 && \
npm config set fetch-retry-mintimeout 60000 && \
npm config set fetch-retry-maxtimeout 300000 && \
npm config set fetch-timeout 600000 && \
npm ci
COPY . .
# Build without type checking (vite build only)
+212 -90
View File
@@ -3,13 +3,47 @@
**BentoPDF** is a powerful, privacy-first, client-side PDF toolkit that is self hostable and allows you to manipulate, edit, merge, and process PDF files directly in your browser. No server-side processing is required, ensuring your files remain secure and private.
![Docker Pulls](https://img.shields.io/docker/pulls/bentopdf/bentopdf) [![Ko-fi](https://img.shields.io/badge/Buy%20me%20a%20Coffee-yellow?logo=kofi&style=flat-square)](https://ko-fi.com/alio01) ![GitHub Stars](https://img.shields.io/github/stars/alam00000/bentopdf?style=social)
![Docker Pulls](https://img.shields.io/docker/pulls/bentopdfteam/bentopdf) [![Ko-fi](https://img.shields.io/badge/Buy%20me%20a%20Coffee-yellow?logo=kofi&style=flat-square)](https://ko-fi.com/alio01) ![GitHub Stars](https://img.shields.io/github/stars/alam00000/bentopdf?style=social)
[![Sponsor me on GitHub](https://img.shields.io/badge/Sponsor-%E2%9D%A4-ff69b4)](https://github.com/sponsors/alam00000)
![BentoPDF Tools](public/images/bentopdf-tools.png)
---
## Table of Contents
- [Join Us on Discord](#-join-us-on-discord)
- [Documentation](#-documentation)
- [Licensing](#-licensing)
- [Stargazers over time](#-stargazers-over-time)
- [Thank You to Our Sponsors](#-thank-you-to-our-sponsors)
- [Why BentoPDF?](#-why-bentopdf)
- [Features / Tools Supported](#️-features--tools-supported)
- [Organize & Manage PDFs](#organize--manage-pdfs)
- [Edit & Modify PDFs](#edit--modify-pdfs)
- [Convert to PDF](#convert-to-pdf)
- [Convert from PDF](#convert-from-pdf)
- [Secure & Optimize PDFs](#secure--optimize-pdfs)
- [Translations](#-translations)
- [Getting Started](#-getting-started)
- [Prerequisites](#prerequisites)
- [Quick Start](#-quick-start)
- [Static Hosting](#static-hosting-using-netlify-vercel-and-github-pages)
- [Self-Hosting Locally](#-self-hosting-locally)
- [Docker Compose / Podman Compose](#-run-with-docker-compose--podman-compose-recommended)
- [Podman Quadlet](#-podman-quadlet-systemd-integration)
- [Simple Mode](#-simple-mode-for-internal-use)
- [Security Features](#-security-features)
- [Digital Signature CORS Proxy](#digital-signature-cors-proxy-required)
- [Version Management](#-version-management)
- [Development Setup](#-development-setup)
- [Tech Stack & Background](#️-tech-stack--background)
- [Roadmap](#️-roadmap)
- [Contributing](#-contributing)
- [Special Thanks](#special-thanks)
---
## 📢 Join Us on Discord
[![Discord](https://img.shields.io/badge/Discord-Join%20Server-7289da?style=for-the-badge&logo=discord&logoColor=white)](https://discord.gg/Bgq3Ay3f2w)
@@ -34,12 +68,22 @@ Visit our [Documentation](https://bentopdf.com/docs/) for:
## 📜 Licensing
BentoPDF is dual-licensed:
BentoPDF is **dual-licensed** to fit your needs:
- **AGPL-3.0** for open-source projects where you share your full source code publicly
- **Commercial License** for proprietary/closed-source applications - **[Get Lifetime License for $49](https://ko-fi.com/s/f32ca4cb75)** (a one-time lifetime purchase, includes all feature updates forever)
| License | Best For | Price |
| -------------- | -------------------------------------------- | ------------------ |
| **AGPL-3.0** | Open-source projects with public source code | **Free** |
| **Commercial** | Proprietary / closed-source applications | **$49** (lifetime) |
For more details, see our [Licensing Page](https://bentopdf.com/licensing.html)
<p align="center">
<a href="https://buy.polar.sh/polar_cl_ThDfffbl733x7oAodcIryCzhlO57ZtcWPq6HJ1qMChd">
<img src="https://img.shields.io/badge/🚀_Get_Commercial_License-$49_Lifetime-6366f1?style=for-the-badge&labelColor=1f2937" alt="Get Commercial License">
</a>
</p>
> **One-time purchase** · **Unlimited devices & users** · **Lifetime updates** · **No AGPL obligations**
📖 For more details, see our [Licensing Page](https://bentopdf.com/licensing.html)
<hr>
@@ -76,44 +120,48 @@ BentoPDF offers a comprehensive suite of tools to handle all your PDF needs.
### Organize & Manage PDFs
| Tool Name | Description |
| :------------------------- | :------------------------------------------------------------------------------------------------------ |
| **Merge PDFs** | Combine multiple PDF files into one. |
| **Split PDFs** | Extract specific pages or divide a document into smaller files. |
| **Organize Pages** | Reorder, duplicate, or delete pages with a simple drag-and-drop interface. |
| **Extract Pages** | Save a specific range of pages as a new PDF. |
| **Delete Pages** | Remove unwanted pages from your document. |
| **Rotate PDF** | Rotate individual or all pages in a document. |
| **N-Up PDF** | Combine multiple pages onto a single page. |
| **View PDF** | A powerful, integrated PDF viewer. |
| **Alternate & Mix pages** | Merge pages by alternating pages from each PDF. |
| **Posterize PDF** | Split a PDF into multiple smaller pages for print. |
| **PDF Multi Tool** | Merge, Split, Organize, Delete, Rotate, Add Blank Pages, Extract and Duplicate in an unified interface. |
| **Add Attachments** | Embed one or more files into your PDF. |
| **Extract Attachments** | Extract all embedded files from PDF(s) as a ZIP. |
| **Edit Attachments** | View or remove attachments in your PDF. |
| **Divide Pages** | Divide pages horizontally or vertically. |
| **Combine to Single Page** | Stitch all pages into one continuous scroll. |
| **Add Blank Page** | Insert an empty page anywhere in your PDF. |
| **Reverse Pages** | Flip the order of all pages in your document. |
| **View Metadata** | Inspect the hidden properties of your PDF. |
| **PDFs to ZIP** | Package multiple PDF files into a ZIP archive. |
| **Compare PDFs** | Compare two PDFs side by side. |
| Tool Name | Description |
| :--------------------------- | :------------------------------------------------------------------------------------------------------ |
| **Merge PDFs** | Combine multiple PDF files into one. Preserves Bookmarks. |
| **Split PDFs** | Extract specific pages or divide a document into smaller files. |
| **Organize Pages** | Reorder, duplicate, or delete pages with a simple drag-and-drop interface. |
| **Extract Pages** | Save a specific range of pages as a new PDF. |
| **Delete Pages** | Remove unwanted pages from your document. |
| **Rotate PDF** | Rotate individual or all pages in a document. |
| **Rotate by Custom Degrees** | Rotate pages by any custom angle. |
| **N-Up PDF** | Combine multiple pages onto a single page. |
| **View PDF** | A powerful, integrated PDF viewer. |
| **Alternate & Mix Pages** | Merge pages by alternating pages from each PDF. Preserves Bookmarks. |
| **Posterize PDF** | Split a PDF into multiple smaller pages for print. |
| **PDF Multi Tool** | Merge, Split, Organize, Delete, Rotate, Add Blank Pages, Extract and Duplicate in an unified interface. |
| **PDF Booklet** | Rearrange pages for double-sided booklet printing. Fold and staple to create a booklet. |
| **Add Attachments** | Embed one or more files into your PDF. |
| **Extract Attachments** | Extract all embedded files from PDF(s) as a ZIP. |
| **Edit Attachments** | View or remove attachments in your PDF. |
| **Divide Pages** | Divide pages horizontally or vertically. |
| **Combine to Single Page** | Stitch all pages into one continuous scroll. |
| **Add Blank Page** | Insert an empty page anywhere in your PDF. |
| **Reverse Pages** | Flip the order of all pages in your document. |
| **View Metadata** | Inspect the hidden properties of your PDF. |
| **PDFs to ZIP** | Package multiple PDF files into a ZIP archive. |
| **Compare PDFs** | Compare two PDFs side by side. |
### Edit & Modify PDFs
| Tool Name | Description |
| :------------------------ | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **PDF Editor** | A comprehensive editor to modify your PDFs. |
| **PDF Editor** | Annotate, highlight, redact, comment, add shapes/images, search, and view PDFs. |
| **Create Fillable Forms** | Create professional fillable PDF forms with text fields, checkboxes, dropdowns, radio buttons, signatures, and more. Fully compliant with PDF standards for compatibility with all PDF viewers. |
| **PDF Form Filler** | Fill in forms directly in the browser. Also supports XFA forms. |
| **Add Page Numbers** | Easily add page numbers with customizable formatting. |
| **Add Watermark** | Add text or image watermarks to protect your documents. |
| **Header & Footer** | Add customizable headers and footers. |
| **Crop PDF** | Crop specific pages or the entire document. |
| **Deskew PDF** | Automatically straighten tilted scanned pages using OpenCV. |
| **Font to Outline** | Convert all fonts to vector outlines for consistent rendering across all devices. |
| **Invert Colors** | Invert the colors of your PDF pages for better readability. |
| **Change Background** | Modify the background color of your PDF. |
| **Change Text Color** | Change the color of text content within the PDF. |
| **Fill Forms** | Fill out PDF forms directly in your browser. |
| **Flatten PDF** | Flatten form fields and annotations into static content. |
| **Remove Annotations** | Remove comments, highlights, and other annotations. |
| **Remove Blank Pages** | Auto detect and remove blank pages in a PDF. |
@@ -124,20 +172,41 @@ BentoPDF offers a comprehensive suite of tools to handle all your PDF needs.
### Convert to PDF
| Tool Name | Description |
| :------------------ | :-------------------------------------------------------------- |
| **Image to PDF** | Convert JPG, PNG, WebP, SVG, BMP, HEIC, and TIFF images to PDF. |
| **JPG to PDF** | Convert JPG images to PDF. |
| **PNG to PDF** | Convert PNG images to PDF. |
| **WebP to PDF** | Convert WebP images to PDF. |
| **SVG to PDF** | Convert SVG images to PDF. |
| **BMP to PDF** | Convert BMP images to PDF. |
| **HEIC to PDF** | Convert HEIC images to PDF. |
| **TIFF to PDF** | Convert TIFF images to PDF. |
| **Markdown to PDF** | Convert `.md` files into professional PDF documents. |
| **Text to PDF** | Convert plain text files into a PDF. |
| **EPUB to PDF** | Convert EPUB e-books to PDF format. |
| **JSON to PDF** | Convert JSON to PDF. |
| Tool Name | Description |
| :-------------------- | :----------------------------------------------------------------------------------------------------- |
| **Image to PDF** | Convert JPG, PNG, BMP, GIF, TIFF, PNM, PGM, PBM, PPM, PAM, JXR, JPX, JP2, PSD, SVG, HEIC, WebP to PDF. |
| **JPG to PDF** | Convert JPG, JPEG, and JPEG2000 (JP2/JPX) images to PDF. |
| **PNG to PDF** | Convert PNG images to PDF. |
| **WebP to PDF** | Convert WebP images to PDF. |
| **SVG to PDF** | Convert SVG images to PDF. |
| **BMP to PDF** | Convert BMP images to PDF. |
| **HEIC to PDF** | Convert HEIC images to PDF. |
| **TIFF to PDF** | Convert TIFF images to PDF. |
| **PSD to PDF** | Convert Adobe Photoshop (PSD) files to PDF. |
| **Word to PDF** | Convert Word documents (DOCX, DOC, ODT, RTF) to PDF. |
| **Excel to PDF** | Convert Excel spreadsheets (XLSX, XLS, ODS, CSV) to PDF. |
| **PowerPoint to PDF** | Convert PowerPoint presentations (PPTX, PPT, ODP) to PDF. |
| **ODT to PDF** | Convert OpenDocument Text files to PDF. |
| **ODS to PDF** | Convert OpenDocument Spreadsheet (ODS) files to PDF. |
| **ODP to PDF** | Convert OpenDocument Presentation (ODP) files to PDF. |
| **ODG to PDF** | Convert OpenDocument Graphics (ODG) files to PDF. |
| **RTF to PDF** | Convert Rich Text Format documents to PDF. |
| **CSV to PDF** | Convert CSV spreadsheet files to PDF. |
| **Markdown to PDF** | Write or paste Markdown and export it as a beautifully formatted PDF. |
| **Text to PDF** | Convert plain text files into a PDF. |
| **JSON to PDF** | Convert JSON files to PDF. |
| **XML to PDF** | Convert XML documents to PDF. |
| **EPUB to PDF** | Convert EPUB e-books to PDF. |
| **MOBI to PDF** | Convert MOBI e-books to PDF. |
| **FB2 to PDF** | Convert FictionBook (FB2) e-books to PDF. |
| **CBZ to PDF** | Convert comic book archives (CBZ/CBR) to PDF. |
| **XPS to PDF** | Convert XPS/OXPS documents to PDF. |
| **Email to PDF** | Convert email files (EML, MSG) to PDF. Supports Outlook exports. |
| **Pages to PDF** | Convert Apple Pages documents to PDF. |
| **WPD to PDF** | Convert WordPerfect documents (WPD) to PDF. |
| **WPS to PDF** | Convert WPS Office documents to PDF. |
| **PUB to PDF** | Convert Microsoft Publisher (PUB) files to PDF. |
| **VSD to PDF** | Convert Microsoft Visio (VSD, VSDX) files to PDF. |
### Convert from PDF
@@ -149,30 +218,35 @@ BentoPDF offers a comprehensive suite of tools to handle all your PDF needs.
| **PDF to WebP** | Convert each PDF page into a WebP image. |
| **PDF to BMP** | Convert each PDF page into a BMP image. |
| **PDF to TIFF** | Convert each PDF page into a TIFF image. |
| **PDF to SVG** | Convert each page into a scalable vector graphic (SVG) for perfect quality. |
| **PDF to Greyscale** | Convert a color PDF into a black-and-white version. |
| **OCR PDF** | Make scanned PDFs searchable and copyable using Optical Character Recognition. |
| **PDF to Text** | Extract text from PDF files and save as plain text (.txt). |
| **PDF to JSON** | Convert PDF files to JSON format. |
| **PDF to CSV** | Extract tables from PDF and convert to CSV format. |
| **PDF to Excel** | Extract tables from PDF and convert to Excel (XLSX) format. |
| **Extract Tables** | Extract tables from PDF files and export as CSV, JSON, or Markdown. |
| **OCR PDF** | Make scanned PDFs searchable and copyable using Optical Character Recognition. |
### Secure & Optimize PDFs
| Tool Name | Description |
| :---------------------- | :----------------------------------------------------------------------------------------------- |
| **Compress PDF** | Reduce file size while maintaining quality. |
| **Repair PDF** | Attempt to repair and recover data from a corrupted PDF. |
| **Encrypt PDF** | Add a password to protect your PDF from unauthorized access. |
| **Decrypt PDF** | Remove password protection from a PDF (password required). |
| **Change Permissions** | Set or modify user permissions for printing, copying, and editing. |
| **Sign PDF** | Add your digital signature to a document. |
| **Digital Signature** | Add cryptographic digital signatures using X.509 certificates (PFX/PEM). |
| **Validate Signature** | Verify digital signatures and view certificate details. |
| **Redact Content** | Permanently remove sensitive content from your PDFs. |
| **Edit Metadata** | View and modify PDF metadata (author, title, keywords, etc.). |
| **Remove Metadata** | Strip all metadata from your PDF for privacy. |
| **Linearize PDF** | Optimize PDF for fast web view. |
| **Sanitize PDF** | Remove potentially unwanted or malicous files from PDF. |
| **Fix Page Size** | Standardize all pages to a uniform size. |
| **Page Dimensions** | Analyze page size, orientation, and units. |
| **Remove Restrictions** | Remove password protection and security restrictions associated with digitally signed PDF files. |
| Tool Name | Description |
| :---------------------- | :--------------------------------------------------------------------------------------------------------- |
| **Compress PDF** | Reduce file size while maintaining quality. |
| **Repair PDF** | Attempt to repair and recover data from a corrupted PDF. |
| **Encrypt PDF** | Add a password to protect your PDF from unauthorized access. |
| **Decrypt PDF** | Remove password protection from a PDF (password required). |
| **Change Permissions** | Set or modify user permissions for printing, copying, and editing. |
| **Sign PDF** | Draw, type, or upload your signature. |
| **Digital Signature** | Add cryptographic digital signatures using X.509 certificates (PFX/PEM). Private key never leaves browser. |
| **Validate Signature** | Verify digital signatures, check certificate validity, and confirm document integrity. |
| **Redact Content** | Permanently remove sensitive content from your PDFs. |
| **Edit Metadata** | View and modify PDF metadata (author, title, keywords, etc.). |
| **Remove Metadata** | Strip all metadata from your PDF for privacy. |
| **Linearize PDF** | Optimize PDF for fast web viewing. |
| **Sanitize PDF** | Remove metadata, annotations, scripts, and more. |
| **Fix Page Size** | Standardize all pages to a uniform size. |
| **Page Dimensions** | Analyze page size, orientation, and units. |
| **Remove Restrictions** | Remove password protection and security restrictions associated with digitally signed PDF files. |
---
@@ -207,22 +281,9 @@ You can run BentoPDF locally for development or personal use.
- [npm](https://www.npmjs.com/) (or yarn/pnpm)
- [Docker](https://www.docker.com/) & [Docker Compose](https://docs.docker.com/compose/install/) (for containerized setup)
### 🚀 Quick Start with Docker
### 🚀 Quick Start
[![Deploy on Zeabur](https://zeabur.com/button.svg)](https://zeabur.com/templates/K4AU2B)
You can run BentoPDF directly from Docker Hub or GitHub Container Registry without cloning the repository:
You can also watch the video on how to set it up 👉
[BentoPDF Docker Setup](https://drive.google.com/file/d/1C4eJ2nqeaH__1Tlad-xuBHaF2Ha4fSBf/view?usp=drive_link)
**Using Docker Hub:**
```bash
docker run -p 3000:8080 bentopdf/bentopdf:latest
```
**Using GitHub Container Registry:**
Run BentoPDF instantly from GitHub Container Registry (Recommended):
```bash
docker run -p 3000:8080 ghcr.io/alam00000/bentopdf:latest
@@ -230,11 +291,34 @@ docker run -p 3000:8080 ghcr.io/alam00000/bentopdf:latest
Open your browser at: http://localhost:3000
This is the fastest way to try BentoPDF without setting up a development environment.
<details>
<summary><b>Alternative: Using Docker Hub or Podman</b></summary>
**Docker Hub:**
```bash
docker run -p 3000:8080 bentopdfteam/bentopdf:latest
```
**Podman (GHCR):**
```bash
podman run -p 3000:8080 ghcr.io/alam00000/bentopdf:latest
```
**Podman (Docker Hub):**
```bash
podman run -p 3000:8080 docker.io/bentopdfteam/bentopdf:latest
```
> **Note:** All `docker` commands in this documentation work with Podman by replacing `docker` with `podman`.
</details>
### Static Hosting using Netlify, Vercel, and GitHub Pages
It is very straightforward to host your own instance of BentoPDF using a static web page hosting service. Plus, services such as Netlify, Vercel, and GitHub Pages all offer a free tier for getting started. See [Static Hosting](https://github.com/alam00000/bentopdf/blob/main/STATIC-HOSTING.md)) for details.
It is very straightforward to host your own instance of BentoPDF using a static web page hosting service. Plus, services such as Netlify, Vercel, and GitHub Pages all offer a free tier for getting started. See [Static Hosting](https://github.com/alam00000/bentopdf/blob/main/STATIC-HOSTING.md) for details.
### 🏠 Self-Hosting Locally
@@ -391,7 +475,7 @@ docker run -p 3000:8080 bentopdf-simple
> - Always include trailing slashes in `BASE_URL` (e.g., `/bentopdf/` not `/bentopdf`)
> - The default value is `/` for root deployment
### 🚀 Run with Docker Compose (Recommended)
### 🚀 Run with Docker Compose / Podman Compose (Recommended)
For a more robust setup with auto-restart capabilities:
@@ -400,7 +484,8 @@ For a more robust setup with auto-restart capabilities:
```yaml
services:
bentopdf:
image: bentopdf/bentopdf:latest
image: ghcr.io/alam00000/bentopdf:latest # Recommended
# image: bentopdfteam/bentopdf:latest # Alternative: Docker Hub
container_name: bentopdf
ports:
- '3000:8080'
@@ -410,11 +495,48 @@ services:
2. **Start the application**:
```bash
# Docker Compose
docker-compose up -d
# Podman Compose
podman-compose up -d
```
The application will be available at `http://localhost:3000`.
### 🐧 Podman Quadlet (Systemd Integration)
For Linux production deployments, you can run BentoPDF as a systemd service using [Podman Quadlet](https://docs.podman.io/en/latest/markdown/podman-systemd.unit.5.html).
Create `~/.config/containers/systemd/bentopdf.container`:
```ini
[Unit]
Description=BentoPDF - Privacy-first PDF toolkit
After=network-online.target
[Container]
Image=ghcr.io/alam00000/bentopdf:latest
ContainerName=bentopdf
PublishPort=3000:8080
AutoUpdate=registry
[Service]
Restart=always
[Install]
WantedBy=default.target
```
Then enable and start:
```bash
systemctl --user daemon-reload
systemctl --user enable --now bentopdf
```
For detailed Quadlet configuration, see [Self-Hosting Docker Guide](https://bentopdf.com/docs/self-hosting/docker).
### 🏢 Simple Mode for Internal Use
For organizations that want a clean, distraction-free interface focused solely on PDF tools, BentoPDF supports a **Simple Mode** that hides all branding and marketing content.
@@ -534,20 +656,20 @@ VITE_CORS_PROXY_SECRET=your-secret npm run build
### 📦 Version Management
BentoPDF supports semantic versioning with multiple Docker tags available on both Docker Hub and GitHub Container Registry:
BentoPDF supports semantic versioning with multiple container tags available:
**Docker Hub:**
- **Latest**: `bentopdf/bentopdf:latest`
- **Specific Version**: `bentopdf/bentopdf:1.0.0`
- **Version with Prefix**: `bentopdf/bentopdf:v1.0.0`
**GitHub Container Registry:**
**GitHub Container Registry (Recommended):**
- **Latest**: `ghcr.io/alam00000/bentopdf:latest`
- **Specific Version**: `ghcr.io/alam00000/bentopdf:1.0.0`
- **Version with Prefix**: `ghcr.io/alam00000/bentopdf:v1.0.0`
**Docker Hub:**
- **Latest**: `bentopdfteam/bentopdf:latest`
- **Specific Version**: `bentopdfteam/bentopdf:1.0.0`
- **Version with Prefix**: `bentopdfteam/bentopdf:v1.0.0`
#### Quick Release
```bash
+4 -4
View File
@@ -215,16 +215,16 @@ git reset --hard HEAD~1
1. **GitHub Actions Triggered**: Workflow starts building Docker image
2. **Docker Build**: Multi-architecture image created
3. **Docker Push**: Images pushed to Docker Hub with tags:
- `bentopdf/bentopdf:latest`
- `bentopdf/bentopdf:1.0.1`
- `bentopdf/bentopdf:v1.0.1`
- `bentopdfteam/bentopdf:latest`
- `bentopdfteam/bentopdf:1.0.1`
- `bentopdfteam/bentopdf:v1.0.1`
### **End Result:**
Users can immediately pull your new version:
```bash
docker pull bentopdf/bentopdf:1.0.1
docker pull bentopdfteam/bentopdf:1.0.1
```
---
+79 -35
View File
@@ -23,27 +23,35 @@ When enabled, Simple Mode will:
Use the pre-built Simple Mode image directly:
**Using GitHub Container Registry (Recommended):**
```bash
# Docker
docker run -p 3000:8080 ghcr.io/alam00000/bentopdf-simple:latest
# Podman
podman run -p 3000:8080 ghcr.io/alam00000/bentopdf-simple:latest
```
**Using Docker Hub:**
```bash
docker run -p 3000:8080 bentopdf/bentopdf-simple:latest
# Docker
docker run -p 3000:8080 bentopdfteam/bentopdf-simple:latest
# Podman
podman run -p 3000:8080 docker.io/bentopdfteam/bentopdf-simple:latest
```
**Using GitHub Container Registry:**
```bash
docker run -p 3000:8080 ghcr.io/alam00000/bentopdf-simple:latest
```
Or with Docker Compose:
Or with Docker Compose / Podman Compose:
```yaml
services:
bentopdf:
# Using Docker Hub
image: bentopdf/bentopdf-simple:latest
# Or using GitHub Container Registry
# image: ghcr.io/alam00000/bentopdf-simple:latest
# Using GitHub Container Registry (Recommended)
image: ghcr.io/alam00000/bentopdf-simple:latest
# Or using Docker Hub
# image: bentopdfteam/bentopdf-simple:latest
container_name: bentopdf
restart: unless-stopped
ports:
@@ -105,9 +113,13 @@ This automatically builds and serves Simple Mode on `http://localhost:3000`.
### Method 2: Using Pre-built Image (Easiest for Production)
```bash
# Pull and run the Simple Mode image
docker pull bentopdf/bentopdf-simple:latest
docker run -p 3000:8080 bentopdf/bentopdf-simple:latest
# Docker - Pull and run the Simple Mode image
docker pull ghcr.io/alam00000/bentopdf-simple:latest
docker run -p 3000:8080 ghcr.io/alam00000/bentopdf-simple:latest
# Podman
podman pull ghcr.io/alam00000/bentopdf-simple:latest
podman run -p 3000:8080 ghcr.io/alam00000/bentopdf-simple:latest
```
Open `http://localhost:3000` in your browser.
@@ -127,11 +139,13 @@ Open `http://localhost:3000` in your browser.
### Method 4: Compare Both Modes
```bash
# Test Normal Mode
docker run -p 3000:8080 bentopdf/bentopdf:latest
# Test Normal Mode (Docker)
docker run -p 3000:8080 ghcr.io/alam00000/bentopdf:latest
# Test Simple Mode
docker run -p 3001:8080 bentopdf/bentopdf-simple:latest
# Test Simple Mode (Docker)
docker run -p 3001:8080 ghcr.io/alam00000/bentopdf-simple:latest
# Podman users: replace 'docker' with 'podman'
```
- Normal Mode: `http://localhost:3000`
@@ -149,52 +163,82 @@ When Simple Mode is working correctly, you should see:
- ❌ No hero section with "The PDF Toolkit built for privacy"
- ❌ No features, FAQ, testimonials, or footer sections
## 📦 Available Docker Images
## 📦 Available Container Images
### Normal Mode (Full Branding)
**Docker Hub:**
- `bentopdf/bentopdf:latest`
- `bentopdf/bentopdf:v1.0.0` (versioned)
**GitHub Container Registry:**
**GitHub Container Registry (Recommended):**
- `ghcr.io/alam00000/bentopdf:latest`
- `ghcr.io/alam00000/bentopdf:v1.0.0` (versioned)
### Simple Mode (Clean Interface)
**Docker Hub:**
- `bentopdf/bentopdf-simple:latest`
- `bentopdf/bentopdf-simple:v1.0.0` (versioned)
- `bentopdfteam/bentopdf:latest`
- `bentopdfteam/bentopdf:v1.0.0` (versioned)
**GitHub Container Registry:**
### Simple Mode (Clean Interface)
**GitHub Container Registry (Recommended):**
- `ghcr.io/alam00000/bentopdf-simple:latest`
- `ghcr.io/alam00000/bentopdf-simple:v1.0.0` (versioned)
**Docker Hub:**
- `bentopdfteam/bentopdf-simple:latest`
- `bentopdfteam/bentopdf-simple:v1.0.0` (versioned)
## 🚀 Production Deployment Examples
### Internal Company Tool
### Docker Compose / Podman Compose
```yaml
services:
bentopdf:
image: bentopdf/bentopdf-simple:latest
image: ghcr.io/alam00000/bentopdf-simple:latest # Recommended
# image: bentopdfteam/bentopdf-simple:latest # Alternative: Docker Hub
container_name: bentopdf
restart: unless-stopped
ports:
- '80:80'
- '80:8080'
environment:
- PUID=1000
- PGID=1000
```
### Podman Quadlet (Linux Systemd)
Create `~/.config/containers/systemd/bentopdf-simple.container`:
```ini
[Unit]
Description=BentoPDF Simple Mode
After=network-online.target
[Container]
Image=ghcr.io/alam00000/bentopdf-simple:latest
ContainerName=bentopdf-simple
PublishPort=80:8080
AutoUpdate=registry
[Service]
Restart=always
[Install]
WantedBy=default.target
```
Enable and start:
```bash
systemctl --user daemon-reload
systemctl --user enable --now bentopdf-simple
```
## ⚠️ Important Notes
- **Pre-built images**: Use `bentopdf/bentopdf-simple:latest` for Simple Mode
- **Pre-built images**: Use `ghcr.io/alam00000/bentopdf-simple:latest` for Simple Mode (recommended)
- **Environment variables**: `SIMPLE_MODE=true` only works during build, not runtime
- **Build-time optimization**: Simple Mode uses dead code elimination for smaller bundles
- **Same functionality**: All PDF tools work identically in both modes
+7 -3
View File
@@ -1,8 +1,12 @@
services:
bentopdf:
# simple mode - bentopdf/bentopdf-simple:latest
# default mode - bentopdf/bentopdf:latest
image: bentopdf/bentopdf-simple:latest
# GitHub Container Registry (Recommended)
# simple mode - ghcr.io/alam00000/bentopdf-simple:latest
# default mode - ghcr.io/alam00000/bentopdf:latest
# Docker Hub (Alternative)
# simple mode - bentopdfteam/bentopdf-simple:latest
# default mode - bentopdfteam/bentopdf:latest
image: ghcr.io/alam00000/bentopdf-simple:latest
container_name: bentopdf
restart: unless-stopped
ports:
+179 -29
View File
@@ -1,27 +1,38 @@
# Deploy with Docker
# Deploy with Docker / Podman
The easiest way to self-host BentoPDF in a production environment.
> [!IMPORTANT]
> **Required Headers for Office File Conversion**
>
>
> LibreOffice-based tools (Word, Excel, PowerPoint conversion) require these HTTP headers for `SharedArrayBuffer` support:
>
> - `Cross-Origin-Opener-Policy: same-origin`
> - `Cross-Origin-Embedder-Policy: require-corp`
>
> The official Docker images include these headers. If using a reverse proxy (Traefik, Caddy, etc.), ensure these headers are preserved or added.
>
> The official container images include these headers. If using a reverse proxy (Traefik, Caddy, etc.), ensure these headers are preserved or added.
> [!TIP]
> **Podman Users:** All `docker` commands work with Podman by replacing `docker` with `podman` and `docker-compose` with `podman-compose`.
## Quick Start
```bash
# Docker
docker run -d \
--name bentopdf \
-p 3000:8080 \
--restart unless-stopped \
ghcr.io/alam00000/bentopdf:latest
# Podman
podman run -d \
--name bentopdf \
-p 3000:8080 \
ghcr.io/alam00000/bentopdf:latest
```
## Docker Compose
## Docker Compose / Podman Compose
Create `docker-compose.yml`:
@@ -31,10 +42,10 @@ services:
image: ghcr.io/alam00000/bentopdf:latest
container_name: bentopdf
ports:
- "3000:8080"
- '3000:8080'
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080"]
test: ['CMD', 'curl', '-f', 'http://localhost:8080']
interval: 30s
timeout: 10s
retries: 3
@@ -43,7 +54,11 @@ services:
Run:
```bash
# Docker Compose
docker compose up -d
# Podman Compose
podman-compose up -d
```
## Build Your Own Image
@@ -73,10 +88,10 @@ docker run -d -p 3000:8080 bentopdf:custom
## Environment Variables
| Variable | Description | Default |
|----------|-------------|---------|
| Variable | Description | Default |
| ------------- | ------------------------------- | ------- |
| `SIMPLE_MODE` | Build without LibreOffice tools | `false` |
| `BASE_URL` | Deploy to subdirectory | `/` |
| `BASE_URL` | Deploy to subdirectory | `/` |
Example:
@@ -94,15 +109,15 @@ services:
traefik:
image: traefik:v2.10
command:
- "--providers.docker=true"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "[email protected]"
- "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
- "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web"
- '--providers.docker=true'
- '--entrypoints.web.address=:80'
- '--entrypoints.websecure.address=:443'
- '[email protected]'
- '--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json'
- '--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web'
ports:
- "80:80"
- "443:443"
- '80:80'
- '443:443'
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./letsencrypt:/letsencrypt
@@ -110,15 +125,15 @@ services:
bentopdf:
image: ghcr.io/alam00000/bentopdf:latest
labels:
- "traefik.enable=true"
- "traefik.http.routers.bentopdf.rule=Host(`pdf.example.com`)"
- "traefik.http.routers.bentopdf.entrypoints=websecure"
- "traefik.http.routers.bentopdf.tls.certresolver=letsencrypt"
- "traefik.http.services.bentopdf.loadbalancer.server.port=8080"
- 'traefik.enable=true'
- 'traefik.http.routers.bentopdf.rule=Host(`pdf.example.com`)'
- 'traefik.http.routers.bentopdf.entrypoints=websecure'
- 'traefik.http.routers.bentopdf.tls.certresolver=letsencrypt'
- 'traefik.http.services.bentopdf.loadbalancer.server.port=8080'
# Required headers for SharedArrayBuffer (LibreOffice WASM)
- "traefik.http.routers.bentopdf.middlewares=bentopdf-headers"
- "traefik.http.middlewares.bentopdf-headers.headers.customresponseheaders.Cross-Origin-Opener-Policy=same-origin"
- "traefik.http.middlewares.bentopdf-headers.headers.customresponseheaders.Cross-Origin-Embedder-Policy=require-corp"
- 'traefik.http.routers.bentopdf.middlewares=bentopdf-headers'
- 'traefik.http.middlewares.bentopdf-headers.headers.customresponseheaders.Cross-Origin-Opener-Policy=same-origin'
- 'traefik.http.middlewares.bentopdf-headers.headers.customresponseheaders.Cross-Origin-Embedder-Policy=require-corp'
restart: unless-stopped
```
@@ -129,12 +144,12 @@ services:
caddy:
image: caddy:2
ports:
- "80:80"
- "443:443"
- '80:80'
- '443:443'
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- caddy_data:/data
bentopdf:
image: ghcr.io/alam00000/bentopdf:latest
restart: unless-stopped
@@ -169,6 +184,141 @@ services:
memory: 128M
```
## Podman Quadlet (Systemd Integration)
[Quadlet](https://docs.podman.io/en/latest/markdown/podman-systemd.unit.5.html) allows you to run Podman containers as systemd services. This is ideal for production deployments on Linux systems.
### Basic Quadlet Setup
Create a container unit file at `~/.config/containers/systemd/bentopdf.container` (user) or `/etc/containers/systemd/bentopdf.container` (system):
```ini
[Unit]
Description=BentoPDF - Privacy-first PDF toolkit
After=network-online.target
Wants=network-online.target
[Container]
Image=ghcr.io/alam00000/bentopdf:latest
ContainerName=bentopdf
PublishPort=3000:8080
AutoUpdate=registry
[Service]
Restart=always
TimeoutStartSec=300
[Install]
WantedBy=default.target
```
### Enable and Start
```bash
# Reload systemd to detect new unit
systemctl --user daemon-reload
# Start the service
systemctl --user start bentopdf
# Enable on boot
systemctl --user enable bentopdf
# Check status
systemctl --user status bentopdf
# View logs
journalctl --user -u bentopdf -f
```
> [!TIP]
> For system-wide deployment, use `systemctl` without `--user` flag and place the file in `/etc/containers/systemd/`.
### Simple Mode Quadlet
For Simple Mode deployment, create `bentopdf-simple.container`:
```ini
[Unit]
Description=BentoPDF Simple Mode - Clean PDF toolkit
After=network-online.target
Wants=network-online.target
[Container]
Image=ghcr.io/alam00000/bentopdf-simple:latest
ContainerName=bentopdf-simple
PublishPort=3000:8080
AutoUpdate=registry
[Service]
Restart=always
TimeoutStartSec=300
[Install]
WantedBy=default.target
```
### Quadlet with Health Check
```ini
[Unit]
Description=BentoPDF with health monitoring
After=network-online.target
Wants=network-online.target
[Container]
Image=ghcr.io/alam00000/bentopdf:latest
ContainerName=bentopdf
PublishPort=3000:8080
AutoUpdate=registry
HealthCmd=curl -f http://localhost:8080 || exit 1
HealthInterval=30s
HealthTimeout=10s
HealthRetries=3
[Service]
Restart=always
TimeoutStartSec=300
[Install]
WantedBy=default.target
```
### Auto-Update with Quadlet
Podman can automatically update containers when new images are available:
```bash
# Enable auto-update timer
systemctl --user enable --now podman-auto-update.timer
# Check for updates manually
podman auto-update
# Dry run (check without updating)
podman auto-update --dry-run
```
### Quadlet Network Configuration
For custom network configuration, create a network file `bentopdf.network`:
```ini
[Network]
Subnet=10.89.0.0/24
Gateway=10.89.0.1
```
Then reference it in your container file:
```ini
[Container]
Image=ghcr.io/alam00000/bentopdf:latest
ContainerName=bentopdf
PublishPort=3000:8080
Network=bentopdf.network
```
## Updating
```bash
+43 -9
View File
@@ -2,15 +2,19 @@
BentoPDF can be self-hosted on your own infrastructure. This guide covers various deployment options.
## Quick Start with Docker
## Quick Start with Docker / Podman
The fastest way to self-host BentoPDF:
```bash
# Docker
docker run -d -p 3000:8080 ghcr.io/alam00000/bentopdf:latest
# Podman
podman run -d -p 3000:8080 ghcr.io/alam00000/bentopdf:latest
```
Or with Docker Compose:
Or with Docker Compose / Podman Compose:
```yaml
# docker-compose.yml
@@ -18,14 +22,43 @@ services:
bentopdf:
image: ghcr.io/alam00000/bentopdf:latest
ports:
- "3000:8080"
- '3000:8080'
restart: unless-stopped
```
```bash
# Docker Compose
docker compose up -d
# Podman Compose
podman-compose up -d
```
## Podman Quadlet (Linux Systemd)
Run BentoPDF as a systemd service. Create `~/.config/containers/systemd/bentopdf.container`:
```ini
[Container]
Image=ghcr.io/alam00000/bentopdf:latest
ContainerName=bentopdf
PublishPort=3000:8080
AutoUpdate=registry
[Service]
Restart=always
[Install]
WantedBy=default.target
```
```bash
systemctl --user daemon-reload
systemctl --user enable --now bentopdf
```
See [Docker deployment guide](/self-hosting/docker) for full Quadlet documentation.
## Building from Source
```bash
@@ -45,6 +78,7 @@ npm run build
Simple Mode is designed for internal organizational use where you want to hide all branding and marketing content, showing only the essential PDF tools.
**What Simple Mode hides:**
- Navigation bar
- Hero section with marketing content
- Features, FAQ, testimonials sections
@@ -56,7 +90,7 @@ Simple Mode is designed for internal organizational use where you want to hide a
SIMPLE_MODE=true npm run build
# Or use the pre-built Docker image
docker run -p 3000:8080 bentopdf/bentopdf-simple:latest
docker run -p 3000:8080 bentopdfteam/bentopdf-simple:latest
```
See [SIMPLE_MODE.md](https://github.com/alam00000/bentopdf/blob/main/SIMPLE_MODE.md) for full details.
@@ -85,11 +119,11 @@ Choose your platform:
## System Requirements
| Requirement | Minimum |
|-------------|---------|
| Storage | ~500 MB (with all WASM modules) |
| RAM | 512 MB |
| CPU | Any modern processor |
| Requirement | Minimum |
| ----------- | ------------------------------- |
| Storage | ~500 MB (with all WASM modules) |
| RAM | 512 MB |
| CPU | Any modern processor |
::: tip
BentoPDF is a static site—there's no database or backend server required!
+203 -81
View File
@@ -94,6 +94,131 @@
</p>
</section>
<!-- Prominent Pricing Section -->
<section id="pricing-hero" class="py-12 max-w-3xl mx-auto">
<div class="bg-gray-900 rounded-2xl p-8 md:p-10 border border-gray-700">
<!-- Badge -->
<span
class="inline-block bg-indigo-500 text-white text-xs font-bold px-4 py-1.5 rounded-full mb-6"
>
LIFETIME LICENSE
</span>
<!-- Title -->
<h2 class="text-3xl md:text-4xl font-bold text-white mb-6">
Commercial License
</h2>
<!-- Divider -->
<div class="border-t border-gray-700 mb-8"></div>
<!-- Features Grid -->
<div class="grid grid-cols-1 md:grid-cols-2 gap-x-8 gap-y-4 mb-8">
<div class="flex items-center gap-3">
<div
class="w-6 h-6 rounded-full bg-indigo-500/20 flex items-center justify-center flex-shrink-0"
>
<i data-lucide="check" class="w-4 h-4 text-indigo-400"></i>
</div>
<span class="text-gray-200">Proprietary Use</span>
</div>
<div class="flex items-center gap-3">
<div
class="w-6 h-6 rounded-full bg-indigo-500/20 flex items-center justify-center flex-shrink-0"
>
<i data-lucide="check" class="w-4 h-4 text-indigo-400"></i>
</div>
<span class="text-gray-200">Unlimited Devices</span>
</div>
<div class="flex items-center gap-3">
<div
class="w-6 h-6 rounded-full bg-indigo-500/20 flex items-center justify-center flex-shrink-0"
>
<i data-lucide="check" class="w-4 h-4 text-indigo-400"></i>
</div>
<span class="text-gray-200">Enterprise Support</span>
</div>
<div class="flex items-center gap-3">
<div
class="w-6 h-6 rounded-full bg-indigo-500/20 flex items-center justify-center flex-shrink-0"
>
<i data-lucide="check" class="w-4 h-4 text-indigo-400"></i>
</div>
<span class="text-gray-200">Unlimited Users</span>
</div>
<div class="flex items-center gap-3">
<div
class="w-6 h-6 rounded-full bg-indigo-500/20 flex items-center justify-center flex-shrink-0"
>
<i data-lucide="check" class="w-4 h-4 text-indigo-400"></i>
</div>
<span class="text-gray-200">Early Access Features</span>
</div>
<div class="flex items-center gap-3">
<div
class="w-6 h-6 rounded-full bg-indigo-500/20 flex items-center justify-center flex-shrink-0"
>
<i data-lucide="check" class="w-4 h-4 text-indigo-400"></i>
</div>
<span class="text-gray-200">Lifetime Updates</span>
</div>
<div class="flex items-center gap-3">
<div
class="w-6 h-6 rounded-full bg-indigo-500/20 flex items-center justify-center flex-shrink-0"
>
<i data-lucide="check" class="w-4 h-4 text-indigo-400"></i>
</div>
<span class="text-gray-200">No AGPL Obligations</span>
</div>
<div class="flex items-center gap-3">
<div
class="w-6 h-6 rounded-full bg-indigo-500/20 flex items-center justify-center flex-shrink-0"
>
<i data-lucide="check" class="w-4 h-4 text-indigo-400"></i>
</div>
<span class="text-gray-200">Flexible Terms</span>
</div>
</div>
<!-- Divider -->
<div class="border-t border-gray-700 mb-6"></div>
<!-- Price and CTA -->
<div
class="flex flex-col sm:flex-row items-center justify-between gap-4"
>
<div class="flex items-baseline gap-2">
<span class="text-gray-500 text-xl line-through">$99</span>
<span class="text-white text-4xl font-bold">$49</span>
<span class="text-gray-400 text-lg"> one-time</span>
</div>
<a
href="https://buy.polar.sh/polar_cl_ThDfffbl733x7oAodcIryCzhlO57ZtcWPq6HJ1qMChd"
target="_blank"
rel="noopener noreferrer"
class="inline-flex items-center gap-2 px-8 py-3 rounded-full bg-indigo-500 text-white font-semibold hover:bg-indigo-400 transition-all duration-200 group"
>
Get License Now
<svg
xmlns="http://www.w3.org/2000/svg"
width="18"
height="18"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2.5"
stroke-linecap="round"
stroke-linejoin="round"
class="transition-transform group-hover:translate-x-1"
>
<path d="M5 12h14" />
<path d="m12 5 7 7-7 7" />
</svg>
</a>
</div>
</div>
</section>
<div class="section-divider"></div>
<section id="licensing-options" class="py-16 max-w-6xl mx-auto">
@@ -242,72 +367,31 @@
</div>
</div>
</div>
<div
class="mt-8 bg-gradient-to-r from-indigo-900/40 to-purple-900/40 rounded-lg p-6 border border-indigo-500/50"
<!-- CTA Button -->
<a
href="https://buy.polar.sh/polar_cl_ThDfffbl733x7oAodcIryCzhlO57ZtcWPq6HJ1qMChd"
target="_blank"
rel="noopener noreferrer"
class="mt-8 inline-flex items-center gap-2 px-8 py-3 rounded-full bg-indigo-500 text-white font-semibold hover:bg-indigo-400 transition-all duration-200 group"
>
<div class="text-center">
<div
class="inline-block bg-red-500 text-white text-xs font-bold px-3 py-1 rounded-full mb-3 animate-pulse"
>
LIMITED TIME OFFER
</div>
<p class="text-white text-2xl font-bold mb-2">
Lifetime License
</p>
<div class="flex items-center justify-center gap-3 mb-3">
<span class="text-gray-400 text-2xl line-through">$99</span>
<span class="text-indigo-300 text-4xl font-bold">$49</span>
<span class="text-lg font-normal text-gray-400"
>one-time</span
>
</div>
<p class="text-gray-300 text-sm mb-4">
Includes all feature updates forever
</p>
<!-- Unlimited Usage Info -->
<div
class="bg-indigo-900/30 rounded-lg p-4 mb-4 border border-indigo-500/30"
>
<div class="flex items-start gap-3 text-left">
<i
data-lucide="infinity"
class="w-6 h-6 text-indigo-400 flex-shrink-0 mt-0.5"
></i>
<div>
<h4 class="text-white font-semibold text-sm mb-2">
Unlimited Usage
</h4>
<p class="text-gray-300 text-xs leading-relaxed">
The BentoPDF commercial license permits use on an
<strong class="text-white"
>unrestricted, unlimited number of devices, servers,
and user machines</strong
>
within your organization. There are
<strong class="text-white"
>no per-user, per-machine, or per-seat
limitations</strong
>. Once you purchase the license, all your internal
users may use BentoPDF through your browser-based system
without requiring additional licenses.
</p>
</div>
</div>
</div>
<a
href="https://ko-fi.com/s/f32ca4cb75"
target="_blank"
rel="noopener noreferrer"
class="inline-block px-8 py-3 rounded-lg bg-indigo-600 text-white font-semibold hover:bg-indigo-700 transition-colors shadow-lg hover:shadow-indigo-500/50 transform hover:scale-105 transition-all duration-200"
>
Purchase Lifetime License
</a>
</div>
</div>
<p class="mt-4 text-sm text-gray-400 italic text-center">
Get Commercial License
<svg
xmlns="http://www.w3.org/2000/svg"
width="18"
height="18"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2.5"
stroke-linecap="round"
stroke-linejoin="round"
class="transition-transform group-hover:translate-x-1"
>
<path d="M5 12h14" />
<path d="m12 5 7 7-7 7" />
</svg>
</a>
<p class="mt-4 text-sm text-gray-400 italic">
💡 Custom requests and development are available for separate
charges.
<a href="contact.html" class="text-indigo-400 hover:underline"
@@ -468,6 +552,29 @@
</div>
<div class="mt-8 text-center">
<a
href="https://buy.polar.sh/polar_cl_ThDfffbl733x7oAodcIryCzhlO57ZtcWPq6HJ1qMChd"
target="_blank"
rel="noopener noreferrer"
class="inline-flex items-center gap-2 px-8 py-3 rounded-full bg-indigo-500 text-white font-semibold hover:bg-indigo-400 transition-all duration-200 group mb-4"
>
Get Commercial License - $49
<svg
xmlns="http://www.w3.org/2000/svg"
width="18"
height="18"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2.5"
stroke-linecap="round"
stroke-linejoin="round"
class="transition-transform group-hover:translate-x-1"
>
<path d="M5 12h14" />
<path d="m12 5 7 7-7 7" />
</svg>
</a>
<p class="text-gray-400 text-sm">
Still not sure?
<a
@@ -791,8 +898,10 @@
BentoPDF is available under a lifetime, one-time purchase
commercial license. You can purchase it directly here:
<a
href="https://ko-fi.com/s/f32ca4cb75"
class="text-indigo-400 hover:underline"
href="https://buy.polar.sh/polar_cl_ThDfffbl733x7oAodcIryCzhlO57ZtcWPq6HJ1qMChd"
target="_blank"
rel="noopener noreferrer"
class="text-indigo-400 hover:underline font-semibold"
>Buy Commercial License</a
>. <br /><br />
If you have specific requirements or want a custom licensing
@@ -956,10 +1065,17 @@
<ul class="space-y-3 text-gray-400">
<li class="flex items-start gap-3">
<i
data-lucide="info"
class="w-5 h-5 text-blue-400 flex-shrink-0 mt-0.5"
data-lucide="check-circle"
class="w-5 h-5 text-green-400 flex-shrink-0 mt-0.5"
></i>
<span>Ko-fi does not automatically issue invoices.</span>
<span
>We use <strong class="text-white">Polar</strong> for
payments, which
<strong class="text-white"
>automatically sends invoices</strong
>
via email after purchase.</span
>
</li>
<li class="flex items-start gap-3">
<i
@@ -967,20 +1083,26 @@
class="w-5 h-5 text-green-400 flex-shrink-0 mt-0.5"
></i>
<span
>An official invoice will be provided immediately upon
request.</span
>Polar handles
<strong class="text-white">VAT invoices</strong> for
businesses in applicable regions.</span
>
</li>
<li class="flex items-start gap-3">
<i
data-lucide="info"
class="w-5 h-5 text-blue-400 flex-shrink-0 mt-0.5"
></i>
<span
>For VAT invoices, select
<strong class="text-white"
>"I'm purchasing as a business"</strong
>
during checkout and enter your billing address and Tax/VAT
number.</span
>
</li>
</ul>
<p class="mt-4 text-gray-300">
<strong class="text-white">Contact us:</strong>
<a
href="mailto:[email protected]"
class="text-indigo-400 hover:underline"
>[email protected]</a
>
with your purchase details.
</p>
</div>
</div>
</section>
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "bento-pdf",
"private": true,
"version": "1.16.0",
"version": "1.16.1",
"license": "AGPL-3.0-only",
"type": "module",
"scripts": {
+4 -2
View File
@@ -80,7 +80,9 @@ function main() {
execSync('npm run update-version', { stdio: 'inherit' });
// 3. Add and commit changes
execSync('git add package.json *.html src/pages/*.html', { stdio: 'inherit' });
execSync('git add package.json *.html src/pages/*.html', {
stdio: 'inherit',
});
execSync(`git commit -m "Release v${newVersion}"`, { stdio: 'inherit' });
console.log(`💾 Committed version change`);
@@ -98,7 +100,7 @@ function main() {
execSync(`git push origin ${tagName}`, { stdio: 'inherit' });
console.log(`🎉 Release v${newVersion} complete!`);
console.log(`📦 Docker image: bentopdf/bentopdf:${newVersion}`);
console.log(`📦 Docker image: bentopdfteam/bentopdf:${newVersion}`);
console.log(`📦 Distribution: dist-${newVersion}.zip`);
console.log(
`🏷️ GitHub release: https://github.com/alam00000/bentopdf/releases/tag/${tagName}`
+32
View File
@@ -255,6 +255,38 @@
"created_at": "2026-01-11T10:30:42Z",
"repoId": 1074785178,
"pullRequestNo": 380
},
{
"name": "sheing-google",
"id": 231310897,
"comment_id": 3751831626,
"created_at": "2026-01-14T21:38:06Z",
"repoId": 1074785178,
"pullRequestNo": 386
},
{
"name": "spwoodcock",
"id": 78538841,
"comment_id": 3754368312,
"created_at": "2026-01-15T11:53:51Z",
"repoId": 1074785178,
"pullRequestNo": 388
},
{
"name": "LoganK",
"id": 1298025,
"comment_id": 3767178117,
"created_at": "2026-01-19T08:56:58Z",
"repoId": 1074785178,
"pullRequestNo": 405
},
{
"name": "JaL-P",
"id": 10429222,
"comment_id": 3774929591,
"created_at": "2026-01-20T21:00:39Z",
"repoId": 1074785178,
"pullRequestNo": 410
}
]
}
+3 -3
View File
@@ -1,8 +1,8 @@
<?xml version="1.0"?>
<Container version="2">
<Name>bentopdf</Name>
<Repository>bentopdf/bentopdf</Repository>
<Registry>https://hub.docker.com/r/bentopdf/bentopdf/</Registry>
<Repository>bentopdfteam/bentopdf</Repository>
<Registry>https://hub.docker.com/r/bentopdfteam/bentopdf/</Registry>
<Network>bridge</Network>
<MyIP/>
<Shell>sh</Shell>
@@ -12,7 +12,7 @@
<Overview>Uploaded on behalf of creator: alam00000&#13;
BentoPDF is a privacy first PDF Toolkit&#13;
&#13;
https://hub.docker.com/r/bentopdf/bentopdf/</Overview>
https://hub.docker.com/r/bentopdfteam/bentopdf/</Overview>
<Category>Tools:</Category>
<WebUI>http://[IP]:[PORT:8080]/</WebUI>
<TemplateURL/>