Sign inSign up

s3tupw1zard/ghost2pdf

By s3tupw1zard

•Updated about 1 year ago

Image
0

1.6K

s3tupw1zard/ghost2pdf repository overview

⁠Ghost2PDF

Ghost2PDF is a lightweight Dockerized service that automatically converts Ghost blog posts into PDFs and uploads them to an S3-compatible storage.


⁠Features

  • Converts Ghost blog posts to PDF automatically via webhooks.
  • Supports multi-architecture Docker images (amd64 and arm64).
  • Automatically organizes PDFs in S3 buckets by year, month, and day.
  • Provides separate endpoints for new posts and updated posts.
  • Easy setup with Docker Compose.

⁠Important Security Note

Do not expose the Ghost2PDF container port 5050 directly to the internet.
Instead, use a internal Docker network and connect both Ghost2PDF and Ghost Stacks to it so that the services can communicate without exposing anything. the service communicates with your Ghost container via a Docker network.

This setup ensures greater security than leaving the port open, which is especially important in case of an emergency or accidental exposure.


⁠Setup

  1. Clone this repository:
git clone https://github.com/s3tupw1zard/ghost2pdf.git
cd ghost2pdf
  1. Copy the .env.example to .env and fill in your S3 and host details:
cp .env.example .env

Environment variables:

  • S3_ENDPOINT – Your S3-compatible endpoint (e.g., Mega S4, MinIO, etc.)
  • S3_ACCESS_KEY – Access key for your S3 storage
  • S3_SECRET_KEY – Secret key for your S3 storage
  • S3_BUCKET – Bucket name for storing PDFs
  • PORT – Port the service should listen on (default: 5050)
  • HOST – Host to bind to (default: localhost inside container)

⁠Create Docker network for Ghost2PDF

Just run this command and replace the subnet and gateway options if theres an overlapping address pool.

docker network create \
  --driver bridge \
  --subnet 172.25.0.0/16 \
  --gateway 172.25.0.1 \
  --ipv6 \ # Omit this if not needed
  ghost-net


⁠Running Ghost2PDF with Docker

You can run Ghost2PDF with plain Docker:

docker run -d \
  --name ghost2pdf \
  --hostname ghost2pdf \
  --env-file .env \
  --network ghost-net \
    --ip 172.25.0.4 \
  -v "$(pwd)/pdfs":/app/pdfs \
  s3tupw1zard/ghost2pdf:latest
⁠docker-compose.yml

Or use Docker Compose for easier management:

services:
  ghost2pdf:
    image: s3tupw1zard/ghost2pdf:latest
    container_name: ghost2pdf
    hostname: ghost2pdf
    volumes:
      - ./pdfs:/app/pdfs:rw
    env_file:
      - .env
    # Optional if you need to expose it, replace or remove 127.0.0.1 only if needed
    #ports:
    #  - "127.0.0.1:${PORT:-5050}:${PORT:-5050}"
    restart: always
    networks:
      ghost-net:
        # IMPORTANT: When you use a hostname for a webhook Ghost will throw an error
        ipv4_address: 172.23.0.4 # Your Network connected to your Ghost container including a static IP

networks:
  ghost-net:
    external: true

Run:

docker-compose up -d

⁠.env.example Template

# Local Storage Configuration
USE_LOCAL=true
LOCAL_PATH=/app/pdfs # Path inside Container

# S3 Storage Configuration
USE_S3=true
S3_ENDPOINT=https://s3.example.com
S3_ACCESS_KEY=your-access-key
S3_SECRET_KEY=your-secret-key
S3_BUCKET=ghost-pdf-bucket
S3_REGION=us-east-1

# Server configuration
PORT=5050
HOST=0.0.0.0

You can decide whether you want to use S3 or local storage, or both at the same time. However, one of the two variables must be set to true.


⁠Webhook Endpoints

After starting the container, Ghost2PDF exposes two endpoints for Ghost webhooks:

  • New posts: http://<HOST>:<PORT>/ghost/published
  • Updated posts: http://<HOST>:<PORT>/ghost/updated

Configure Ghost to call these URLs whenever a post is published or updated.


⁠Notes

  • PDFs are stored in the S3 bucket under YEAR/MONTH/DAY/Post-Slug-YYYY-MM-DD.pdf for new posts and -updated suffix for updates.
  • Puppeteer is used for generating PDFs, so images, styling, and scripts from your Ghost blog are rendered correctly.
  • Multi-arch Docker images ensure compatibility with both x86_64 and ARM64 systems.

⁠Building images locally

If you prefer to build the images for yourself you can follow this reference on how to setup Multi-Architecture builds and how to use the docker-build.sh script.

⁠Create a buildx Builder

A buildx builder is needed if a image should support multiple architectures. If you build the images for amd64 and arm64 seperately it should work without the dedicated buildx builder.

# Create a builder instance if not existing yet
docker buildx create --use --name ghost2pdf-builder

# Check if the builder is active
docker buildx ls

⁠Enable Multi-Architecture Builds with QEMU

Before building ARM64 images on an AMD64 host, you need to register QEMU to emulate different CPU architectures. This allows Docker Buildx to create ARM64 images even if your machine is not natively ARM64.

Run the following command once to set it up:

docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
⁠Build Script Reference

The included build script (docker-build.sh) provides an easy interface for building and pushing Docker images.

CommandDescription
./docker-build.sh build amd64Build only the amd64 image locally
./docker-build.sh build arm64Build only the arm64 image locally
./docker-build.sh build allBuild both architectures locally
./docker-build.sh push amd64Build and push only the amd64 image
./docker-build.sh push arm64Build and push only the arm64 image
./docker-build.sh push allBuild and push a multi-arch manifest (latest + YYYYMMDD)
./docker-build.sh buildpush amd64Build and push amd64 in one step
./docker-build.sh buildpush arm64Build and push arm64 in one step
./docker-build.sh buildpush allBuild and push a multi-arch manifest in one step

This way it is easier for me to update this Docker image.

Tag summary

Content type

Image

Digest

sha256:67071e2a8…

Size

352 MB

Last updated

about 1 year ago

docker pull s3tupw1zard/ghost2pdf