A high-performance, containerized PDF generation service built with Ruby and Puppeteer. This microservice provides a simple HTTP API for converting HTML to PDF with extensive customization options.
- π Fast PDF generation using Puppeteer and Grover
- π¦ Containerized with Docker for easy deployment
- π§ Highly configurable page settings and margins
- π‘οΈ Token-based authentication
- π Production-ready with health checks
- π― Kamal deployment configuration included
This service uses:
- Sinatra - Lightweight web framework
- Grover - Ruby wrapper around Puppeteer for PDF generation
- Puppeteer - Headless Chrome for rendering
- Puma - High-performance web server
- Docker - Containerization
- Kamal - Zero-downtime deployment
For local development:
- Ruby v3.3.5 (exact version needed)
- Node.js (for Puppeteer)
- Redis (optional, for caching)
# Install Ruby version manager
brew install rbenv ruby-build
# Initialize rbenv
rbenv init
# Install Ruby 3.3.5
rbenv install 3.3.5
rbenv local 3.3.5
# Install dependencies
gem install bundler
bundle install
npm install
# Additional tools
brew install poppler
brew install redis
brew services start redis
# For ARM processors (M1/M2 Macs)
softwareupdate --install-rosetta- Clone the repository:
git clone https://github.com/rebelcolony/PupPDF.git
cd PupPDF- Create environment file:
cp .env.example .env
# Edit .env with your configuration- Install dependencies:
bundle install
npm install# Start the server
ruby app.rb
# Or use the Procfile
heroku localThe service will be available at http://localhost:4567
POST /generateHeaders:
X-Authentication-Token: Your secret tokenContent-Type: application/x-www-form-urlencoded
Parameters:
html(required): HTML content to convertoptions(optional): JSON string with PDF options
Example:
curl -X POST http://localhost:4567/generate \
-H "X-Authentication-Token: your-secret-token" \
-d "html=<h1>Hello World</h1>" \
-d 'options={"format":"A4","margin":{"top":"20px"}}' \
--output document.pdfAvailable Options:
{
"format": "A4|LETTER|LEGAL",
"margin": {
"top": "20px",
"bottom": "20px",
"left": "20px",
"right": "20px"
},
"displayHeaderFooter": true,
"headerTemplate": "<div>Header</div>",
"footerTemplate": "<div>Footer</div>",
"printBackground": true,
"landscape": false,
"scale": 1.0,
"pageRanges": "1-5",
"preferCSSPageSize": true
}GET /healthzReturns 200 OK if service is healthy.
# Build image
docker build -t pdf-generator .
# Run container
docker run -p 4567:4567 -e SECRET_TOKEN=your-token pdf-generatorversion: '3.8'
services:
pdf-generator:
build: .
ports:
- "4567:4567"
environment:
- SECRET_TOKEN=your-secret-tokenThis project includes Kamal configuration for easy deployment:
# Setup Kamal
kamal setup
# Deploy
kamal deploy| Variable | Description | Required |
|---|---|---|
SECRET_TOKEN |
Authentication token for API access | Yes |
PORT |
Port to run the service on (default: 4567) | No |
RACK_ENV |
Environment (production/development) | No |
Default PDF settings can be modified in config/grover.rb.
We welcome contributions! Please see our Contributing Guidelines for details.
# Run tests
bundle exec rspec
# Run with coverage
COVERAGE=true bundle exec rspecThe service can handle approximately:
- 50-100 concurrent PDF generations (depending on complexity)
- Average response time: 1-3 seconds for standard documents
- Memory usage: ~200MB per worker
- Token-based authentication
- No data persistence - all processing is stateless
- Runs Puppeteer with
--no-sandboxflag in container (secure in Docker context) - Input sanitization for HTML content
This project is licensed under the MIT License - see the LICENSE file for details.
- Grover for the excellent Puppeteer wrapper
- Puppeteer for headless Chrome automation
- Sinatra for the lightweight web framework
For issues and feature requests, please use the GitHub issue tracker.