Home

Awesome

<p align="center"><img src="https://raw.githubusercontent.com/Stirling-Tools/Stirling-PDF/main/docs/stirling.png" width="80"></p> <h1 align="center">Stirling-PDF</h1>

Docker Pulls Discord Docker Image Version (tag latest semver) GitHub Repo stars

<a href="https://www.producthunt.com/posts/stirling-pdf?embed=true&utm_source=badge-featured&utm_medium=badge&utm_souce=badge-stirling&#0045;pdf" target="_blank"><img src="https://api.producthunt.com/widgets/embed-image/v1/featured.svg?post_id=641239&theme=light" alt="Stirling&#0032;PDF - Open&#0032;source&#0032;locally&#0032;hosted&#0032;web&#0032;PDF&#0032;editor | Product Hunt" style="width: 250px; height: 54px;" width="250" height="54" /></a> Deploy to DO

Stirling-PDF is a robust, locally hosted web-based PDF manipulation tool using Docker. It enables you to carry out various operations on PDF files, including splitting, merging, converting, reorganizing, adding images, rotating, compressing, and more. This locally hosted web application has evolved to encompass a comprehensive set of features, addressing all your PDF requirements.

All files and PDFs exist either exclusively on the client side, reside in server memory only during task execution, or temporarily reside in a file solely for the execution of the task. Any file downloaded by the user will have been deleted from the server by that point.

stirling-home

Features

PDF Features

Page Operations

Conversion Operations

Security & Permissions

Other Operations

For an overview of the tasks and the technology each uses, please view Endpoint-groups.md.

A demo of the app is available here.

Technologies Used

How to Use

Windows

For Windows users, download the latest Stirling-PDF.exe from our release section or by clicking here.

Locally

Please view the LocalRunGuide.

Docker / Podman

[!NOTE] https://hub.docker.com/r/stirlingtools/stirling-pdf

Stirling-PDF has three different versions: a full version, an ultra-lite version, and a 'fat' version. Depending on the types of features you use, you may want a smaller image to save on space. To see what the different versions offer, please look at our version mapping. For people who don't mind space optimization, just use the latest tag.

Docker Image Size (tag) Docker Image Size (tag) Docker Image Size (tag)

Please note in the examples below, you may need to change the volume paths as needed, e.g., ./extraConfigs:/configs to /opt/stirlingpdf/extraConfigs:/configs.

Docker Run

docker run -d \
  -p 8080:8080 \
  -v ./trainingData:/usr/share/tessdata \
  -v ./extraConfigs:/configs \
  -v ./logs:/logs \
# Optional customization (not required)
# -v /location/of/customFiles:/customFiles \
  -e DOCKER_ENABLE_SECURITY=false \
  -e INSTALL_BOOK_AND_ADVANCED_HTML_OPS=false \
  -e LANGS=en_GB \
  --name stirling-pdf \
  stirlingtools/stirling-pdf:latest

Docker Compose

version: '3.3'
services:
  stirling-pdf:
    image: stirlingtools/stirling-pdf:latest
    ports:
      - '8080:8080'
    volumes:
      - ./trainingData:/usr/share/tessdata # Required for extra OCR languages
      - ./extraConfigs:/configs
#      - ./customFiles:/customFiles/
#      - ./logs:/logs/
    environment:
      - DOCKER_ENABLE_SECURITY=false
      - INSTALL_BOOK_AND_ADVANCED_HTML_OPS=false
      - LANGS=en_GB

Note: Podman is CLI-compatible with Docker, so simply replace "docker" with "podman".

Kubernetes

See the kubernetes helm chart here

Enable OCR/Compression Feature

Please view the HowToUseOCR.md.

Reuse Stored Files

Certain functionality like Sign supports pre-saved files stored at /customFiles/signatures/. Image files placed here will be accessible via the web UI. Currently, this supports two folder types:

Supported Languages

Stirling-PDF currently supports 38 languages!

LanguageProgress
Arabic (العربية) (ar_AR)94%
Azerbaijani (Azərbaycan Dili) (az_AZ)92%
Basque (Euskara) (eu_ES)53%
Bulgarian (Български) (bg_BG)89%
Catalan (Català) (ca_CA)84%
Croatian (Hrvatski) (hr_HR)91%
Czech (Česky) (cs_CZ)90%
Danish (Dansk) (da_DK)89%
Dutch (Nederlands) (nl_NL)89%
English (English) (en_GB)100%
English (US) (en_US)100%
French (Français) (fr_FR)92%
German (Deutsch) (de_DE)100%
Greek (Ελληνικά) (el_GR)90%
Hindi (हिंदी) (hi_IN)88%
Hungarian (Magyar) (hu_HU)91%
Indonesian (Bahasa Indonesia) (id_ID)90%
Irish (Gaeilge) (ga_IE)82%
Italian (Italiano) (it_IT)99%
Japanese (日本語) (ja_JP)93%
Korean (한국어) (ko_KR)89%
Norwegian (Norsk) (no_NB)82%
Persian (فارسی) (fa_IR)99%
Polish (Polski) (pl_PL)90%
Portuguese (Português) (pt_PT)90%
Portuguese Brazilian (Português) (pt_BR)98%
Romanian (Română) (ro_RO)84%
Russian (Русский) (ru_RU)90%
Serbian Latin alphabet (Srpski) (sr_LATN_RS)67%
Simplified Chinese (简体中文) (zh_CN)93%
Slovakian (Slovensky) (sk_SK)78%
Spanish (Español) (es_ES)91%
Swedish (Svenska) (sv_SE)90%
Thai (ไทย) (th_TH)90%
Traditional Chinese (繁體中文) (zh_TW)99%
Turkish (Türkçe) (tr_TR)86%
Ukrainian (Українська) (uk_UA)76%
Vietnamese (Tiếng Việt) (vi_VN)83%

Contributing (Creating Issues, Translations, Fixing Bugs, etc.)

Please see our Contributing Guide.

Stirling PDF Enterprise

Stirling PDF offers an Enterprise edition of its software. This is the same great software but with added features and comforts.

What's included

Check out our docs on it or our official website

Customization

Stirling-PDF allows easy customization of the app, including things like:

There are two options for this, either using the generated settings file settings.yml, which is located in the /configs directory and follows standard YAML formatting, or using environment variables, which would override the settings file.

For example, in settings.yml, you might have:

security:
  enableLogin: 'true'

To have this via an environment variable, you would use SECURITY_ENABLELOGIN.

The current list of settings is:

security:
  enableLogin: false # set to 'true' to enable login
  csrfDisabled: true # set to 'true' to disable CSRF protection (not recommended for production)
  loginAttemptCount: 5 # lock user account after 5 tries; when using e.g. Fail2Ban you can deactivate the function with -1
  loginResetTimeMinutes: 120 # lock account for 2 hours after x attempts
  loginMethod: all # 'all' (Login Username/Password and OAuth2[must be enabled and configured]), 'normal'(only Login with Username/Password) or 'oauth2'(only Login with OAuth2)
  initialLogin:
    username: '' # initial username for the first login
    password: '' # initial password for the first login
  oauth2:
    enabled: false # set to 'true' to enable login (Note: enableLogin must also be 'true' for this to work)
    client:
      keycloak:
        issuer: '' # URL of the Keycloak realm's OpenID Connect Discovery endpoint
        clientId: '' # client ID for Keycloak OAuth2
        clientSecret: '' # client secret for Keycloak OAuth2
        scopes: openid, profile, email # scopes for Keycloak OAuth2
        useAsUsername: preferred_username # field to use as the username for Keycloak OAuth2
      google:
        clientId: '' # client ID for Google OAuth2
        clientSecret: '' # client secret for Google OAuth2
        scopes: https://www.googleapis.com/auth/userinfo.email, https://www.googleapis.com/auth/userinfo.profile # scopes for Google OAuth2
        useAsUsername: email # field to use as the username for Google OAuth2
      github:
        clientId: '' # client ID for GitHub OAuth2
        clientSecret: '' # client secret for GitHub OAuth2
        scopes: read:user # scope for GitHub OAuth2
        useAsUsername: login # field to use as the username for GitHub OAuth2
    issuer: '' # set to any provider that supports OpenID Connect Discovery (/.well-known/openid-configuration) endpoint
    clientId: '' # client ID from your provider
    clientSecret: '' # client secret from your provider
    autoCreateUser: false # set to 'true' to allow auto-creation of non-existing users
    blockRegistration: false # set to 'true' to deny login with SSO without prior registration by an admin
    useAsUsername: email # default is 'email'; custom fields can be used as the username
    scopes: openid, profile, email # specify the scopes for which the application will request permissions
    provider: google # set this to your OAuth provider's name, e.g., 'google' or 'keycloak'
  saml2:
    enabled: false # currently in alpha, not recommended for use yet, enableAlphaFunctionality must be set to true
    autoCreateUser: false # set to 'true' to allow auto-creation of non-existing users
    blockRegistration: false # set to 'true' to deny login with SSO without prior registration by an admin
    registrationId: stirling
    idpMetadataUri: https://dev-XXXXXXXX.okta.com/app/externalKey/sso/saml/metadata
    idpSingleLogoutUrl: https://dev-XXXXXXXX.okta.com/app/dev-XXXXXXXX_stirlingpdf_1/externalKey/slo/saml
    idpSingleLoginUrl: https://dev-XXXXXXXX.okta.com/app/dev-XXXXXXXX_stirlingpdf_1/externalKey/sso/saml
    idpIssuer: http://www.okta.com/externalKey
    idpCert: classpath:okta.crt
    privateKey: classpath:saml-private-key.key
    spCert: classpath:saml-public-cert.crt

enterpriseEdition:
  enabled: false # set to 'true' to enable enterprise edition
  key: 00000000-0000-0000-0000-000000000000
  CustomMetadata:
    autoUpdateMetadata: false # set to 'true' to automatically update metadata with below values
    author: username # supports text such as 'John Doe' or types such as username to autopopulate with user's username
    creator: Stirling-PDF # supports text such as 'Company-PDF'
    producer: Stirling-PDF # supports text such as 'Company-PDF'

legal:
  termsAndConditions: https://www.stirlingpdf.com/terms-and-conditions # URL to the terms and conditions of your application (e.g. https://example.com/terms). Empty string to disable or filename to load from local file in static folder
  privacyPolicy: https://www.stirlingpdf.com/privacy-policy # URL to the privacy policy of your application (e.g. https://example.com/privacy). Empty string to disable or filename to load from local file in static folder
  accessibilityStatement: '' # URL to the accessibility statement of your application (e.g. https://example.com/accessibility). Empty string to disable or filename to load from local file in static folder
  cookiePolicy: '' # URL to the cookie policy of your application (e.g. https://example.com/cookie). Empty string to disable or filename to load from local file in static folder
  impressum: '' # URL to the impressum of your application (e.g. https://example.com/impressum). Empty string to disable or filename to load from local file in static folder

system:
  defaultLocale: en-US # set the default language (e.g. 'de-DE', 'fr-FR', etc)
  googlevisibility: false # 'true' to allow Google visibility (via robots.txt), 'false' to disallow
  enableAlphaFunctionality: false # set to enable functionality which might need more testing before it fully goes live (this feature might make no changes)
  showUpdate: false # see when a new update is available
  showUpdateOnlyAdmin: false # only admins can see when a new update is available, depending on showUpdate it must be set to 'true'
  customHTMLFiles: false # enable to have files placed in /customFiles/templates override the existing template HTML files
  tessdataDir: /usr/share/tessdata # path to the directory containing the Tessdata files. This setting is relevant for Windows systems. For Windows users, this path should be adjusted to point to the appropriate directory where the Tessdata files are stored.
  enableAnalytics: undefined # set to 'true' to enable analytics, set to 'false' to disable analytics; for enterprise users, this is set to true

ui:
  appName: '' # application's visible name
  homeDescription: '' # short description or tagline shown on the homepage
  appNameNavbar: '' # name displayed on the navigation bar

endpoints:
  toRemove: [] # list endpoints to disable (e.g. ['img-to-pdf', 'remove-pages'])
  groupsToRemove: [] # list groups to disable (e.g. ['LibreOffice'])

metrics:
  enabled: true # 'true' to enable Info APIs (`/api/*`) endpoints, 'false' to disable

# Automatically Generated Settings (Do Not Edit Directly)
AutomaticallyGenerated:
  key: example
  UUID: example

There is an additional config file /configs/custom_settings.yml where users familiar with Java and Spring application.properties can input their own settings on top of Stirling-PDF's existing ones.

Extra Notes

Environment-Only Parameters

API

For those wanting to use Stirling-PDF's backend API to link with their own custom scripting to edit PDFs, you can view all existing API documentation here, or navigate to /swagger-ui/index.html of your Stirling-PDF instance for your version's documentation (or by following the API button in the settings of Stirling-PDF).

Login Authentication

stirling-login

Prerequisites

Once the above has been done, on restart, a new stirling-pdf-DB.mv.db will show if everything worked.

When you log in to Stirling-PDF, you will be redirected to the /login page to log in with those default credentials. After login, everything should function as normal.

To access your account settings, go to Account Settings in the settings cog menu (top right in the navbar). This Account Settings menu is also where you find your API key.

To add new users, go to the bottom of Account Settings and hit 'Admin Settings'. Here, you can add new users. The different roles mentioned within this are for rate limiting. This is a work in progress and will be expanded on more in the future.

For API usage, you must provide a header with X-API-KEY and the associated API key for that user.

FAQ

Q1: What are your planned features?

Q2: Why is my application downloading .htm files? Why am I getting HTTP error 413?

This is an issue commonly caused by your NGINX configuration. The default file upload size for NGINX is 1MB. You need to add the following in your Nginx sites-available file: client_max_body_size SIZE; (where "SIZE" is 50M, for example, for 50MB files).

Q3: Why is my download timing out?

NGINX has timeout values by default, so if you are running Stirling-PDF behind NGINX, you may need to set a timeout value, such as adding the config proxy_read_timeout 3600;.