feat: add custom branding, air-gapped deployment script, and updated self-hosting docs
This commit is contained in:
123
README.md
123
README.md
@@ -38,6 +38,7 @@
|
||||
- [Docker Compose / Podman Compose](#-run-with-docker-compose--podman-compose-recommended)
|
||||
- [Podman Quadlet](#-podman-quadlet-systemd-integration)
|
||||
- [Simple Mode](#-simple-mode-for-internal-use)
|
||||
- [Custom Branding](#-custom-branding)
|
||||
- [WASM Configuration](#wasm-configuration)
|
||||
- [Air-Gapped / Offline Deployment](#air-gapped--offline-deployment)
|
||||
- [Security Features](#-security-features)
|
||||
@@ -472,7 +473,69 @@ Users can also override these defaults per-browser via **Advanced Settings** in
|
||||
|
||||
<h3 id="air-gapped--offline-deployment">🔒 Air-Gapped / Offline Deployment</h3>
|
||||
|
||||
For networks with no internet access (government, healthcare, financial, etc.), you need to prepare everything on a machine **with** internet, then transfer it into the isolated network.
|
||||
For networks with no internet access (government, healthcare, financial, etc.), you need to prepare everything on a machine **with** internet, then transfer the bundle into the isolated network.
|
||||
|
||||
#### Automated Script (Recommended)
|
||||
|
||||
The included `prepare-airgap.sh` script automates the entire process — downloading WASM packages, building the Docker image, exporting everything into a self-contained bundle with a setup script.
|
||||
|
||||
```bash
|
||||
git clone https://github.com/alam00000/bentopdf.git
|
||||
cd bentopdf
|
||||
|
||||
# Interactive mode — prompts for all options
|
||||
bash scripts/prepare-airgap.sh
|
||||
|
||||
# Or fully automated
|
||||
bash scripts/prepare-airgap.sh --wasm-base-url https://internal.example.com/wasm
|
||||
```
|
||||
|
||||
This produces a bundle directory containing:
|
||||
|
||||
```
|
||||
bentopdf-airgap-bundle/
|
||||
bentopdf.tar # Docker image
|
||||
*.tgz # WASM packages (PyMuPDF, Ghostscript, CoherentPDF)
|
||||
setup.sh # Setup script for the air-gapped side
|
||||
README.md # Instructions
|
||||
```
|
||||
|
||||
**Transfer the bundle** into the air-gapped network via USB, internal artifact repo, or approved method. Then run the included setup script:
|
||||
|
||||
```bash
|
||||
cd bentopdf-airgap-bundle
|
||||
bash setup.sh
|
||||
```
|
||||
|
||||
The setup script loads the Docker image, extracts WASM files, and optionally starts the container.
|
||||
|
||||
<details>
|
||||
<summary><strong>Script options</strong></summary>
|
||||
|
||||
| Flag | Description | Default |
|
||||
| ----------------------- | ------------------------------------------------ | --------------------------------- |
|
||||
| `--wasm-base-url <url>` | Where WASMs will be hosted internally | _(required, prompted if missing)_ |
|
||||
| `--image-name <name>` | Docker image tag | `bentopdf` |
|
||||
| `--output-dir <path>` | Output bundle directory | `./bentopdf-airgap-bundle` |
|
||||
| `--simple-mode` | Enable Simple Mode | off |
|
||||
| `--base-url <path>` | Subdirectory base URL (e.g. `/pdf/`) | `/` |
|
||||
| `--language <code>` | Default UI language (e.g. `fr`, `de`) | _(none)_ |
|
||||
| `--brand-name <name>` | Custom brand name | _(none)_ |
|
||||
| `--brand-logo <path>` | Logo path relative to `public/` | _(none)_ |
|
||||
| `--footer-text <text>` | Custom footer text | _(none)_ |
|
||||
| `--dockerfile <path>` | Dockerfile to use | `Dockerfile` |
|
||||
| `--skip-docker` | Skip Docker build and export | off |
|
||||
| `--skip-wasm` | Skip WASM download (reuse existing `.tgz` files) | off |
|
||||
|
||||
</details>
|
||||
|
||||
> [!IMPORTANT]
|
||||
> WASM files must be served from the **same origin** as the BentoPDF app. Web Workers use `importScripts()` which cannot load scripts cross-origin. For example, if BentoPDF runs at `https://internal.example.com`, the WASM base URL should also be `https://internal.example.com/wasm`.
|
||||
|
||||
#### Manual Steps
|
||||
|
||||
<details>
|
||||
<summary>If you prefer to do it manually without the script</summary>
|
||||
|
||||
**Step 1: Download the WASM packages** (on a machine with internet)
|
||||
|
||||
@@ -482,14 +545,9 @@ npm pack @bentopdf/gs-wasm
|
||||
npm pack coherentpdf
|
||||
```
|
||||
|
||||
This creates three `.tgz` files in your current directory.
|
||||
|
||||
**Step 2: Build the Docker image with internal URLs** (on a machine with internet)
|
||||
|
||||
Point the WASM URLs to where you'll host the files inside the air-gapped network:
|
||||
**Step 2: Build the Docker image with internal URLs**
|
||||
|
||||
```bash
|
||||
# Clone and build
|
||||
git clone https://github.com/alam00000/bentopdf.git
|
||||
cd bentopdf
|
||||
|
||||
@@ -522,19 +580,18 @@ Copy these files via USB drive, internal artifact repository, or approved transf
|
||||
docker load -i bentopdf.tar
|
||||
|
||||
# Extract the WASM packages
|
||||
mkdir -p /var/www/wasm/pymupdf /var/www/wasm/gs /var/www/wasm/cpdf
|
||||
tar xzf bentopdf-pymupdf-wasm-0.11.14.tgz -C /var/www/wasm/pymupdf --strip-components=1
|
||||
tar xzf bentopdf-gs-wasm-*.tgz -C /var/www/wasm/gs --strip-components=1
|
||||
tar xzf coherentpdf-*.tgz -C /var/www/wasm/cpdf --strip-components=1
|
||||
|
||||
# Serve the WASM files on your internal web server (e.g., nginx, Apache)
|
||||
# Make sure they're accessible at the URLs you configured in Step 2
|
||||
mkdir -p ./wasm/pymupdf ./wasm/gs ./wasm/cpdf
|
||||
tar xzf bentopdf-pymupdf-wasm-0.11.14.tgz -C ./wasm/pymupdf --strip-components=1
|
||||
tar xzf bentopdf-gs-wasm-*.tgz -C ./wasm/gs --strip-components=1
|
||||
tar xzf coherentpdf-*.tgz -C ./wasm/cpdf --strip-components=1
|
||||
|
||||
# Run BentoPDF
|
||||
docker run -d -p 3000:8080 --restart unless-stopped bentopdf
|
||||
```
|
||||
|
||||
Users open their browser, access BentoPDF on the internal network, and the browser fetches WASM files from the internal server. No internet required at any point.
|
||||
Make sure the WASM files are accessible at the URLs you configured in Step 2.
|
||||
|
||||
</details>
|
||||
|
||||
> [!NOTE]
|
||||
> If you're building from source instead of Docker, set the variables in `.env.production` before running `npm run build`:
|
||||
@@ -684,6 +741,42 @@ For organizations that want a clean, distraction-free interface focused solely o
|
||||
|
||||
For more details, see [SIMPLE_MODE.md](SIMPLE_MODE.md).
|
||||
|
||||
### 🎨 Custom Branding
|
||||
|
||||
Replace the default BentoPDF logo, name, and footer text with your own. Branding is configured via environment variables at **build time** and works across all deployment methods (Docker, static hosting, air-gapped VMs).
|
||||
|
||||
| Variable | Description | Default |
|
||||
| ------------------ | --------------------------------------- | --------------------------------------- |
|
||||
| `VITE_BRAND_NAME` | Brand name shown in header and footer | `BentoPDF` |
|
||||
| `VITE_BRAND_LOGO` | Path to logo file relative to `public/` | `images/favicon-no-bg.svg` |
|
||||
| `VITE_FOOTER_TEXT` | Custom footer/copyright text | `© 2026 BentoPDF. All rights reserved.` |
|
||||
|
||||
**Docker:**
|
||||
|
||||
```bash
|
||||
docker build \
|
||||
--build-arg VITE_BRAND_NAME="AcmePDF" \
|
||||
--build-arg VITE_BRAND_LOGO="images/acme-logo.svg" \
|
||||
--build-arg VITE_FOOTER_TEXT="© 2026 Acme Corp. Internal use only." \
|
||||
-t acmepdf .
|
||||
```
|
||||
|
||||
**Building from source:**
|
||||
|
||||
Place your logo in the `public/` folder, then build:
|
||||
|
||||
```bash
|
||||
VITE_BRAND_NAME="AcmePDF" \
|
||||
VITE_BRAND_LOGO="images/acme-logo.svg" \
|
||||
VITE_FOOTER_TEXT="© 2026 Acme Corp. Internal use only." \
|
||||
npm run build
|
||||
```
|
||||
|
||||
Or set the values in `.env.production` before building.
|
||||
|
||||
> [!TIP]
|
||||
> Branding works in both full mode and Simple Mode. You can combine it with other build-time options like `SIMPLE_MODE`, `BASE_URL`, and `VITE_DEFAULT_LANGUAGE`.
|
||||
|
||||
### 🔒 Security Features
|
||||
|
||||
BentoPDF runs as a non-root user using nginx-unprivileged for enhanced security:
|
||||
|
||||
Reference in New Issue
Block a user