A high-accuracy, self-hosted Node.js Express API for converting DOC, DOCX, DOCM, RTF, and ODT documents to PDF using LibreOffice.
- High Accuracy: Uses LibreOffice for professional-quality conversions
- No External Dependencies: Completely self-hosted solution
- Multiple Formats: Supports DOC, DOCX, DOCM, RTF, ODT
- Production Ready: Includes logging, health checks, rate limiting
- Docker Support: Easy deployment with Docker
- TypeScript Support: Full TypeScript integration for Next.js
# Clone or create the project directory
mkdir pdf-conversion-api && cd pdf-conversion-api
# Create all the files (copy the provided code)
# Run the installation script
chmod +x install.sh
./install.sh- Node.js 16+
- LibreOffice installed on your system
Ubuntu/Debian:
sudo apt-get update
sudo apt-get install -y libreoffice default-jre fonts-liberationCentOS/RHEL:
sudo yum install -y libreoffice java-1.8.0-openjdkmacOS:
brew install --cask libreofficeWindows: Download from LibreOffice.org
npm install# Start in development mode
npm run dev
# or
./dev.sh
# Start in production mode
npm start
# or
./start.sh# Build and run with Docker Compose
docker-compose up --build
# Or build manually
docker build -t pdf-converter .
docker run -p 3001:3001 pdf-converterPOST /api/convert/to-pdf
Content-Type: multipart/form-data
file: [document file]Example:
curl -X POST \
-F "file=@document.docx" \
-o converted.pdf \
http://localhost:3001/api/convert/to-pdfGET /api/health # Basic health check
GET /api/health/detailed # Detailed system info
GET /api/health/libreoffice # LibreOffice-specific checkPOST /api/convert/validate
Content-Type: multipart/form-data
file: [document file]Add to .env.local:
CONVERSION_SERVICE_URL=http://localhost:3001The provided Next.js API route (app/api/convert-to-pdf/route.ts) will automatically use your conversion service.
Your existing NewDocumentDialog component should work without changes! The conversion will now happen through your accurate LibreOffice-powered service.
| Format | Extension | MIME Type |
|---|---|---|
| Microsoft Word | .doc |
application/msword |
| Microsoft Word | .docx |
application/vnd.openxmlformats-officedocument.wordprocessingml.document |
| Word Macro-Enabled | .docm |
application/vnd.ms-word.document.macroEnabled.12 |
| Rich Text Format | .rtf |
application/rtf |
| OpenDocument Text | .odt |
application/vnd.oasis.opendocument.text |
# Server Configuration
NODE_ENV=development|production
PORT=3001
ALLOWED_ORIGINS=http://localhost:3000,http://localhost:3001
LOG_LEVEL=info|debug|warn|error
# File Upload Limits
MAX_FILE_SIZE=50MB
MAX_FILES=1
UPLOAD_TIMEOUT=60000environment:
- NODE_ENV=production
- PORT=3001
- ALLOWED_ORIGINS=http://localhost:3000# Install LibreOffice on your server
sudo apt-get install libreoffice default-jre
# Clone your application
git clone your-repo
cd your-app
# Install dependencies
npm ci --only=production
# Start with PM2 (recommended)
npm install -g pm2
pm2 start ecosystem.config.js# Use the provided Docker setup
docker-compose up -d
# Or with custom settings
docker run -d \
--name pdf-converter \
-p 3001:3001 \
-e NODE_ENV=production \
-v ./logs:/app/logs \
your-pdf-converter-imageapiVersion: apps/v1
kind: Deployment
metadata:
name: pdf-converter
spec:
replicas: 2
selector:
matchLabels:
app: pdf-converter
template:
metadata:
labels:
app: pdf-converter
spec:
containers:
- name: pdf-converter
image: your-pdf-converter:latest
ports:
- containerPort: 3001
env:
- name: NODE_ENV
value: "production"
resources:
requests:
memory: "512Mi"
cpu: "250m"
limits:
memory: "1Gi"
cpu: "500m"Monitor the /api/health/detailed endpoint for:
- LibreOffice conversion functionality
- System resource usage
- File system accessibility
- Response times
Logs are written to:
logs/combined.log- All logslogs/error.log- Error logs only- Console output in development
The API provides metrics via health endpoints:
- Conversion times
- Memory usage
- System load
- Success/failure rates
Error: "LibreOffice not found"
# Check if LibreOffice is installed
libreoffice --version
# Check if it's in PATH
which libreofficeError: "Conversion timeout"
- Increase timeout in configuration
- Check system resources
- Verify LibreOffice fonts are installed
High memory usage:
- LibreOffice can use significant memory for complex documents
- Consider implementing queue system for high load
- Monitor with health endpoints
Unsupported file error:
- Check MIME type detection
- Verify file isn't corrupted
- Test with simple documents first
- Adequate RAM (2GB+ recommended)
- SSD storage for temporary files
- Multiple CPU cores for concurrent conversions
- Implement conversion queues for high load
- Add Redis for job management
- Scale horizontally with load balancer
- Pre-installed fonts for consistent rendering
- Headless mode (automatically enabled)
- Regular cleanup of temporary files
- File Validation: Strict MIME type checking
- Size Limits: Configurable file size limits
- Rate Limiting: Built-in rate limiting
- Sanitization: Temporary file cleanup
- Non-root User: Docker runs as non-root user
MIT License - see LICENSE file for details.