fix: nginx.conf for docker deployment
This commit is contained in:
@@ -2,6 +2,15 @@
|
|||||||
|
|
||||||
The easiest way to self-host BentoPDF in a production environment.
|
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.
|
||||||
|
|
||||||
## Quick Start
|
## Quick Start
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@@ -106,6 +115,10 @@ services:
|
|||||||
- "traefik.http.routers.bentopdf.entrypoints=websecure"
|
- "traefik.http.routers.bentopdf.entrypoints=websecure"
|
||||||
- "traefik.http.routers.bentopdf.tls.certresolver=letsencrypt"
|
- "traefik.http.routers.bentopdf.tls.certresolver=letsencrypt"
|
||||||
- "traefik.http.services.bentopdf.loadbalancer.server.port=8080"
|
- "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"
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -135,6 +148,8 @@ Caddyfile:
|
|||||||
```
|
```
|
||||||
pdf.example.com {
|
pdf.example.com {
|
||||||
reverse_proxy bentopdf:8080
|
reverse_proxy bentopdf:8080
|
||||||
|
header Cross-Origin-Opener-Policy "same-origin"
|
||||||
|
header Cross-Origin-Embedder-Policy "require-corp"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -96,6 +96,7 @@ http {
|
|||||||
add_header X-Content-Type-Options "nosniff" always;
|
add_header X-Content-Type-Options "nosniff" always;
|
||||||
add_header X-XSS-Protection "1; mode=block" always;
|
add_header X-XSS-Protection "1; mode=block" always;
|
||||||
add_header Cross-Origin-Opener-Policy "same-origin" always;
|
add_header Cross-Origin-Opener-Policy "same-origin" always;
|
||||||
|
add_header Cross-Origin-Embedder-Policy "require-corp" always;
|
||||||
add_header Cross-Origin-Resource-Policy "cross-origin" always;
|
add_header Cross-Origin-Resource-Policy "cross-origin" always;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { WorkerBrowserConverter } from '@matbee/libreoffice-converter/browser';
|
import { WorkerBrowserConverter } from '@matbee/libreoffice-converter/browser';
|
||||||
import { getWasmBaseUrl } from '../config/wasm-cdn-config.js';
|
import { getWasmBaseUrl, getWasmFallbackUrl, isCdnEnabled } from '../config/wasm-cdn-config.js';
|
||||||
|
|
||||||
export interface LoadProgress {
|
export interface LoadProgress {
|
||||||
phase: 'loading' | 'initializing' | 'converting' | 'complete' | 'ready';
|
phase: 'loading' | 'initializing' | 'converting' | 'complete' | 'ready';
|
||||||
@@ -24,10 +24,12 @@ export class LibreOfficeConverter {
|
|||||||
private initialized = false;
|
private initialized = false;
|
||||||
private initializing = false;
|
private initializing = false;
|
||||||
private basePath: string;
|
private basePath: string;
|
||||||
|
private localPath: string;
|
||||||
|
|
||||||
constructor(basePath?: string) {
|
constructor(basePath?: string) {
|
||||||
// Use CDN if available, otherwise use provided basePath or default local path
|
// Use CDN if available, otherwise use provided basePath or default local path
|
||||||
this.basePath = basePath || getWasmBaseUrl('libreoffice');
|
this.basePath = basePath || getWasmBaseUrl('libreoffice');
|
||||||
|
this.localPath = getWasmFallbackUrl('libreoffice');
|
||||||
}
|
}
|
||||||
|
|
||||||
async initialize(onProgress?: ProgressCallback): Promise<void> {
|
async initialize(onProgress?: ProgressCallback): Promise<void> {
|
||||||
@@ -47,12 +49,14 @@ export class LibreOfficeConverter {
|
|||||||
try {
|
try {
|
||||||
progressCallback?.({ phase: 'loading', percent: 0, message: 'Loading conversion engine...' });
|
progressCallback?.({ phase: 'loading', percent: 0, message: 'Loading conversion engine...' });
|
||||||
|
|
||||||
|
const workerPath = isCdnEnabled() ? this.localPath : this.basePath;
|
||||||
|
|
||||||
this.converter = new WorkerBrowserConverter({
|
this.converter = new WorkerBrowserConverter({
|
||||||
sofficeJs: `${this.basePath}soffice.js`,
|
sofficeJs: `${this.basePath}soffice.js`,
|
||||||
sofficeWasm: `${this.basePath}soffice.wasm.gz`,
|
sofficeWasm: `${this.basePath}soffice.wasm.gz`,
|
||||||
sofficeData: `${this.basePath}soffice.data.gz`,
|
sofficeData: `${this.basePath}soffice.data.gz`,
|
||||||
sofficeWorkerJs: `${this.basePath}soffice.worker.js`,
|
sofficeWorkerJs: `${workerPath}soffice.worker.js`,
|
||||||
browserWorkerJs: `${this.basePath}browser.worker.global.js`,
|
browserWorkerJs: `${workerPath}browser.worker.global.js`,
|
||||||
verbose: false,
|
verbose: false,
|
||||||
onProgress: (info: { phase: string; percent: number; message: string }) => {
|
onProgress: (info: { phase: string; percent: number; message: string }) => {
|
||||||
if (progressCallback && !this.initialized) {
|
if (progressCallback && !this.initialized) {
|
||||||
|
|||||||
Reference in New Issue
Block a user