Compare commits

...
17 changed files with 1833 additions and 0 deletions
+168
View File
@@ -0,0 +1,168 @@
name: Chocolatey Publish
on:
release:
types: [released]
workflow_dispatch:
inputs:
tag:
description: 'Release tag to publish (e.g. v1.2.3)'
required: true
package:
description: "Which package to publish"
required: true
default: "both"
type: choice
options:
- both
- desktop
- server
permissions:
contents: read
jobs:
# ── Shared version extraction ─────────────────────────────────────────────
version:
runs-on: ubuntu-latest
outputs:
version: ${{ steps.ver.outputs.version }}
steps:
- name: Harden Runner
uses: step-security/harden-runner@v2
with:
egress-policy: audit
- name: Extract version from release tag
id: ver
run: |
if [[ "${{ github.event_name }}" == "release" ]]; then
TAG="${{ github.event.release.tag_name }}"
else
TAG="${{ inputs.tag }}"
fi
echo "version=${TAG#v}" >> "$GITHUB_OUTPUT"
# ── Desktop package (MSI) ─────────────────────────────────────────────────
chocolatey-desktop:
name: Pack & push stirling-pdf (desktop)
needs: version
if: >
github.event_name == 'release' ||
(github.event_name == 'workflow_dispatch' &&
(github.event.inputs.package == 'desktop' || github.event.inputs.package == 'both'))
runs-on: windows-latest
environment: chocolatey
steps:
- name: Harden Runner
uses: step-security/harden-runner@v2
with:
egress-policy: audit
- uses: actions/checkout@v4
- name: Compute MSI checksum
id: msi-hash
shell: bash
run: |
VERSION="${{ needs.version.outputs.version }}"
MSI_URL="https://github.com/Stirling-Tools/Stirling-PDF/releases/download/v${VERSION}/Stirling-PDF-windows-x86_64.msi"
curl -fsSL "$MSI_URL" -o stirling-pdf.msi
SHA256=$(sha256sum stirling-pdf.msi | awk '{print $1}')
echo "sha256=${SHA256}" >> $GITHUB_OUTPUT
- name: Update nuspec version and checksum
shell: bash
run: |
VERSION="${{ needs.version.outputs.version }}"
SHA256="${{ steps.msi-hash.outputs.sha256 }}"
NUSPEC="manifests/chocolatey/stirling-pdf/stirling-pdf.nuspec"
INSTALL="manifests/chocolatey/stirling-pdf/tools/chocolateyInstall.ps1"
sed -i "s|<version>.*</version>|<version>${VERSION}</version>|" "$NUSPEC"
sed -i "s|^\$version\s*=.*|\$version = '${VERSION}'|" "$INSTALL"
sed -i "s|PLACEHOLDER_SHA256_UPDATED_BY_CI|${SHA256}|" "$INSTALL"
- name: Pack Chocolatey package
working-directory: manifests/chocolatey/stirling-pdf
run: choco pack stirling-pdf.nuspec
shell: cmd
- name: Push to Chocolatey community feed
working-directory: manifests/chocolatey/stirling-pdf
run: |
choco push stirling-pdf.${{ needs.version.outputs.version }}.nupkg `
--source https://push.chocolatey.org/ `
--api-key $env:CHOCOLATEY_API_KEY
shell: powershell
env:
CHOCOLATEY_API_KEY: ${{ secrets.CHOCOLATEY_API_KEY }}
- name: Upload nupkg artifact
uses: actions/upload-artifact@v4
with:
name: chocolatey-desktop-nupkg
path: manifests/chocolatey/stirling-pdf/*.nupkg
retention-days: 14
# ── Server package (JAR + NSSM service) ──────────────────────────────────
chocolatey-server:
name: Pack & push stirling-pdf-server
needs: version
if: >
github.event_name == 'release' ||
(github.event_name == 'workflow_dispatch' &&
(github.event.inputs.package == 'server' || github.event.inputs.package == 'both'))
runs-on: windows-latest
environment: chocolatey
steps:
- name: Harden Runner
uses: step-security/harden-runner@v2
with:
egress-policy: audit
- uses: actions/checkout@v4
- name: Compute JAR checksum
id: jar-hash
shell: bash
run: |
VERSION="${{ needs.version.outputs.version }}"
JAR_URL="https://github.com/Stirling-Tools/Stirling-PDF/releases/download/v${VERSION}/Stirling-PDF-server.jar"
curl -fsSL "$JAR_URL" -o stirling-pdf.jar
SHA256=$(sha256sum stirling-pdf.jar | awk '{print $1}')
echo "sha256=${SHA256}" >> $GITHUB_OUTPUT
- name: Update nuspec version and checksum
shell: bash
run: |
VERSION="${{ needs.version.outputs.version }}"
SHA256="${{ steps.jar-hash.outputs.sha256 }}"
NUSPEC="manifests/chocolatey/stirling-pdf-server/stirling-pdf-server.nuspec"
INSTALL="manifests/chocolatey/stirling-pdf-server/tools/chocolateyInstall.ps1"
sed -i "s|<version>.*</version>|<version>${VERSION}</version>|" "$NUSPEC"
sed -i "s|^\$version\s*=.*|\$version = '${VERSION}'|" "$INSTALL"
sed -i "s|PLACEHOLDER_SHA256_UPDATED_BY_CI|${SHA256}|" "$INSTALL"
- name: Pack Chocolatey package
working-directory: manifests/chocolatey/stirling-pdf-server
run: choco pack stirling-pdf-server.nuspec
shell: cmd
- name: Push to Chocolatey community feed
working-directory: manifests/chocolatey/stirling-pdf-server
run: |
choco push stirling-pdf-server.${{ needs.version.outputs.version }}.nupkg `
--source https://push.chocolatey.org/ `
--api-key $env:CHOCOLATEY_API_KEY
shell: powershell
env:
CHOCOLATEY_API_KEY: ${{ secrets.CHOCOLATEY_API_KEY }}
- name: Upload nupkg artifact
uses: actions/upload-artifact@v4
with:
name: chocolatey-server-nupkg
path: manifests/chocolatey/stirling-pdf-server/*.nupkg
retention-days: 14
+177
View File
@@ -0,0 +1,177 @@
name: Snap Publish
on:
release:
types: [released]
workflow_dispatch:
inputs:
channel:
description: "Snap Store channel to publish to"
required: true
default: "candidate"
type: choice
options:
- edge
- candidate
- stable
permissions:
contents: read
jobs:
# ── Build & publish the desktop snap ──────────────────────────────────────
snap-desktop:
name: Build desktop snap
runs-on: ubuntu-22.04
environment: snap-store
steps:
- name: Harden Runner
uses: step-security/harden-runner@v2
with:
egress-policy: audit
- uses: actions/checkout@v4
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
java-version: "21"
distribution: "temurin"
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v4
with:
gradle-version: 9.3.1
- name: Install Node.js
uses: actions/setup-node@v4
with:
node-version: "20"
cache: "npm"
cache-dependency-path: frontend/package-lock.json
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
targets: x86_64-unknown-linux-gnu
- name: Install Linux build deps
run: |
sudo apt-get update
sudo apt-get install -y \
libwebkit2gtk-4.1-dev \
libgtk-3-dev \
libayatana-appindicator3-dev \
librsvg2-dev \
patchelf \
dpkg
- name: Build Spring Boot JAR
run: ./gradlew :app:core:bootJar --no-daemon
env:
MAVEN_USER: ${{ secrets.MAVEN_USER }}
MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }}
MAVEN_PUBLIC_URL: ${{ secrets.MAVEN_PUBLIC_URL }}
- name: Install frontend deps
working-directory: frontend
run: npm ci
- name: Build Tauri .deb
working-directory: frontend
run: npm run tauri build -- --target x86_64-unknown-linux-gnu
env:
TAURI_PRIVATE_KEY: ""
TAURI_KEY_PASSWORD: ""
- name: Stage artifacts for snapcraft
run: |
mkdir -p manifests/snap/dist
cp frontend/src-tauri/target/release/bundle/deb/*.deb \
manifests/snap/dist/
- name: Build snap (desktop)
uses: snapcore/action-build@v1
id: snap-desktop
with:
path: manifests/snap
snapcraft-args: --verbosity=verbose
- name: Publish snap to Snap Store
if: github.event_name == 'release' || github.event_name == 'workflow_dispatch'
uses: snapcore/action-publish@v1
env:
SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAPCRAFT_STORE_CREDENTIALS }}
with:
snap: ${{ steps.snap-desktop.outputs.snap }}
release: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.channel || 'stable' }}
- name: Upload snap artifact
uses: actions/upload-artifact@v4
with:
name: stirling-pdf-desktop-snap
path: ${{ steps.snap-desktop.outputs.snap }}
retention-days: 14
# ── Build & publish the server snap ───────────────────────────────────────
snap-server:
name: Build server snap
runs-on: ubuntu-22.04
environment: snap-store
steps:
- name: Harden Runner
uses: step-security/harden-runner@v2
with:
egress-policy: audit
- uses: actions/checkout@v4
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
java-version: "21"
distribution: "temurin"
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v4
with:
gradle-version: 9.3.1
- name: Build Spring Boot JAR
run: ./gradlew :app:core:bootJar --no-daemon
env:
MAVEN_USER: ${{ secrets.MAVEN_USER }}
MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }}
MAVEN_PUBLIC_URL: ${{ secrets.MAVEN_PUBLIC_URL }}
- name: Stage JAR for snapcraft
run: |
mkdir -p manifests/snap/dist
cp app/core/build/libs/Stirling-PDF*.jar \
manifests/snap/dist/
- name: Build snap (server)
uses: snapcore/action-build@v1
id: snap-server
with:
path: manifests/snap
snapcraft-channel: stable
snapcraft-args: --verbosity=verbose --file snapcraft-server.yaml
- name: Publish server snap to Snap Store
if: github.event_name == 'release' || github.event_name == 'workflow_dispatch'
uses: snapcore/action-publish@v1
env:
SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAPCRAFT_STORE_CREDENTIALS }}
with:
snap: ${{ steps.snap-server.outputs.snap }}
release: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.channel || 'stable' }}
- name: Upload snap artifact
uses: actions/upload-artifact@v4
with:
name: stirling-pdf-server-snap
path: ${{ steps.snap-server.outputs.snap }}
retention-days: 14
+191
View File
@@ -0,0 +1,191 @@
# Stirling PDF — Chocolatey Distribution
Stirling PDF is distributed via Chocolatey as two packages:
| Package ID | Description |
|---|---|
| `stirling-pdf` | Desktop application (installs the MSI) |
| `stirling-pdf-server` | Headless server — runs as a Windows service on port 8080 |
---
## Installing via Chocolatey
```powershell
# Desktop application
choco install stirling-pdf
# Headless server (installs and starts a Windows service)
choco install stirling-pdf-server
```
### Upgrading
```powershell
choco upgrade stirling-pdf
choco upgrade stirling-pdf-server
```
### Uninstalling
```powershell
choco uninstall stirling-pdf
choco uninstall stirling-pdf-server
```
---
## Desktop package (`stirling-pdf`)
The desktop package downloads and runs the official MSI installer, which
installs the Tauri + Spring Boot application with a bundled JRE.
After installation:
- Launch from the **Start Menu** or **desktop shortcut**
- The embedded backend starts automatically when the app is opened
- No separate Java installation is needed
### MSI silent install flags
The installer uses `/quiet /norestart ALLUSERS=1` by default.
---
## Server package (`stirling-pdf-server`)
The server package:
1. Downloads the Spring Boot JAR to `C:\ProgramData\StirlingPDF\`
2. Downloads and unpacks a Temurin JRE 21 to
`C:\ProgramData\StirlingPDF\jre\`
3. Registers a Windows service named **`StirlingPDFServer`** via
[NSSM](https://nssm.cc/) and starts it automatically
The web UI is available at **http://localhost:8080** after installation.
### Managing the service
```powershell
# Check status
Get-Service StirlingPDFServer
# Start / stop / restart
Start-Service StirlingPDFServer
Stop-Service StirlingPDFServer
Restart-Service StirlingPDFServer
# Or via NSSM
nssm status StirlingPDFServer
nssm start StirlingPDFServer
nssm stop StirlingPDFServer
```
### File locations
| Path | Contents |
|---|---|
| `C:\ProgramData\StirlingPDF\Stirling-PDF-*.jar` | Application JAR |
| `C:\ProgramData\StirlingPDF\jre\` | Bundled Temurin JRE 21 |
| `C:\ProgramData\StirlingPDF\data\` | User data and settings |
| `C:\ProgramData\StirlingPDF\logs\` | Log files |
### Changing the port
Edit the service parameters via NSSM GUI:
```powershell
nssm edit StirlingPDFServer
```
Or update the `AppParameters` key directly and restart the service.
---
## Building the packages locally
### Prerequisites
```powershell
# Install Chocolatey (if not already installed)
Set-ExecutionPolicy Bypass -Scope Process -Force
iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))
```
### Desktop package
```powershell
# 1. Build the MSI via the Tauri workflow (or download from GitHub Releases)
# 2. Update version and checksum in the nuspec and install script
$version = "2.7.3"
$msiHash = (Get-FileHash "Stirling-PDF_${version}_x64_en-US.msi" -Algorithm SHA256).Hash.ToLower()
# 3. Pack
cd manifests/chocolatey/stirling-pdf
choco pack stirling-pdf.nuspec
# 4. Test install locally
choco install stirling-pdf --source . --pre -y
```
### Server package
```powershell
# 1. Build the JAR
./gradlew :app:core:bootJar
# 2. Update version and checksum in the nuspec and install script
$version = "2.7.3"
$jarHash = (Get-FileHash "Stirling-PDF-${version}.jar" -Algorithm SHA256).Hash.ToLower()
# 3. Pack
cd manifests/chocolatey/stirling-pdf-server
choco pack stirling-pdf-server.nuspec
# 4. Test install locally (requires nssm to be installed)
choco install stirling-pdf-server --source . --pre -y
```
---
## Publishing to the Chocolatey Community Repository
### One-time setup
1. Create an account at <https://community.chocolatey.org>
2. Generate an API key from your account page
3. Add the key as a GitHub Actions secret named `CHOCOLATEY_API_KEY`
### Automated publishing (CI)
The workflow at `.github/workflows/chocolatey-publish.yml` runs automatically
on every GitHub release. It:
1. Extracts the version from Gradle
2. Downloads the release artifacts and computes SHA256 checksums
3. Patches the version and checksum placeholders in the install scripts
4. Runs `choco pack` and `choco push`
Manual workflow dispatch lets you push just the `desktop`, just the `server`,
or `both` packages.
### Manual push
```powershell
choco push stirling-pdf.2.7.3.nupkg --source https://push.chocolatey.org/ --api-key YOUR_API_KEY
choco push stirling-pdf-server.2.7.3.nupkg --source https://push.chocolatey.org/ --api-key YOUR_API_KEY
```
> **Note:** New package submissions to the Chocolatey community repository
> undergo a moderation review before being publicly available. Allow 13 days
> for initial approval. Updates to approved packages are typically
> auto-approved within minutes.
---
## Useful resources
- Chocolatey package creation guide: <https://docs.chocolatey.org/en-us/create/create-packages>
- Chocolatey nuspec reference: <https://docs.chocolatey.org/en-us/create/create-packages#nuspec>
- NSSM (service manager): <https://nssm.cc/usage>
- Flathub submission (for Linux): see `docs/distribution/FLATPAK.md`
- Snap Store (for Linux): see `docs/distribution/SNAP.md`
+223
View File
@@ -0,0 +1,223 @@
# Stirling PDF — Flatpak / Flathub Distribution
This document covers building and distributing Stirling PDF as a Flatpak
application, including the process for submitting it to Flathub.
---
## Installing from Flathub
> **Note:** The Stirling PDF Flatpak has not yet been submitted to Flathub.
> Once approved it will be installable with:
```bash
flatpak install flathub org.stirlingtools.StirlingPDF
flatpak run org.stirlingtools.StirlingPDF
```
---
## Building the Flatpak locally
### Prerequisites
```bash
# Flatpak builder and Freedesktop SDK
sudo apt install flatpak flatpak-builder
flatpak remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo
flatpak install flathub org.freedesktop.Platform//23.08 org.freedesktop.Sdk//23.08
flatpak install flathub org.freedesktop.Sdk.Extension.rust-stable//23.08
flatpak install flathub org.freedesktop.Sdk.Extension.node20//23.08
```
### Build steps
```bash
# 1. Build the Tauri .deb (requires Rust, Node, JDK 21)
./gradlew :app:core:bootJar
cd frontend && npm ci && npm run tauri build -- --target x86_64-unknown-linux-gnu && cd ..
# 2. Stage the .deb next to the manifest
mkdir -p manifests/flatpak/dist
cp frontend/src-tauri/target/release/bundle/deb/*.deb \
manifests/flatpak/dist/Stirling-PDF_amd64.deb
# 3. Update the sha256 checksum in the manifest for the .deb source
sha256sum manifests/flatpak/dist/Stirling-PDF_amd64.deb
# 4. Build the Flatpak bundle
flatpak-builder --force-clean build-dir \
manifests/flatpak/org.stirlingtools.StirlingPDF.yaml
# 5. Create an installable .flatpak file
flatpak-builder --export-only --repo=repo build-dir \
manifests/flatpak/org.stirlingtools.StirlingPDF.yaml
flatpak build-bundle repo stirling-pdf.flatpak org.stirlingtools.StirlingPDF
# 6. Install and test locally
flatpak install --user stirling-pdf.flatpak
flatpak run org.stirlingtools.StirlingPDF
```
---
## Local testing
### Prerequisites
Install Flatpak tools and the Freedesktop runtime (one-time setup):
```bash
sudo apt install flatpak flatpak-builder
# Add Flathub remote
flatpak remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo
# Install the runtime and SDK matching the manifest's runtime-version (23.08)
flatpak install flathub \
org.freedesktop.Platform//23.08 \
org.freedesktop.Sdk//23.08 \
org.freedesktop.Sdk.Extension.rust-stable//23.08 \
org.freedesktop.Sdk.Extension.node20//23.08
```
### Build, install, and run
```bash
# Build the Flatpak and install it into your user session in one step.
# --force-clean wipes any previous build-dir so you start fresh.
flatpak-builder \
--user \
--install \
--force-clean \
build-dir \
manifests/flatpak/org.stirlingtools.StirlingPDF.yaml
# Launch the app
flatpak run org.stirlingtools.StirlingPDF
```
### Checking logs and errors
```bash
# Capture stdout/stderr from the app in a log file
flatpak run org.stirlingtools.StirlingPDF 2>&1 | tee /tmp/stirling-pdf-test.log
# View systemd journal for the Flatpak session unit
journalctl --user -e | grep -i StirlingPDF
# Enable verbose Flatpak sandbox logging (shows permission denials)
FLATPAK_BWRAP_DEBUG=1 flatpak run org.stirlingtools.StirlingPDF
```
### Linting before submission
Flathub runs `flatpak-builder-lint` on every PR. Run it locally first:
```bash
pip install flatpak-builder-lint
# Check the manifest
flatpak-builder-lint manifest manifests/flatpak/org.stirlingtools.StirlingPDF.yaml
# Check the AppStream metainfo
flatpak-builder-lint appstream manifests/flatpak/org.stirlingtools.StirlingPDF.metainfo.xml
```
Resolve all errors before opening the Flathub submission PR. Warnings are
advisory but should be addressed where possible.
### Cleanup
```bash
# Uninstall the locally built app
flatpak uninstall --user org.stirlingtools.StirlingPDF
# Remove build artefacts
rm -rf build-dir repo stirling-pdf.flatpak
```
### Common gotchas
| Problem | Cause | Fix |
|---|---|---|
| `runtime/sdk not found` | Freedesktop runtime not installed | Run the prerequisite install commands above |
| `sha256 mismatch` | `.deb` rebuilt since last checksum | Re-run `sha256sum` and update the manifest source entry |
| Blank/white window | WebKitGTK not available in sandbox | Ensure `org.webkit.webkitgtk` extension is listed in the manifest; check sandbox logs |
| `flatpak-builder: command not found` | Package missing | `sudo apt install flatpak-builder` |
| File open/save dialog fails | Filesystem portal not running | Start `xdg-desktop-portal` and the backend for your desktop environment |
| Sandbox blocks network | Incorrect finish-args | Confirm `--share=network` is present in the manifest's `finish-args` |
---
## Submitting to Flathub
### Requirements
- A GitHub account
- The app must be open source (MIT ✓)
- The Flatpak manifest must pass Flathub linting
### Process
1. **Fork the Flathub repository**
<https://github.com/flathub/flathub>
2. **Open a new app submission issue**
<https://github.com/flathub/flathub/issues/new?template=new_application.yml>
Fill in the app ID (`org.stirlingtools.StirlingPDF`), project URL, and a
link to the manifest.
3. **Create a dedicated app repository**
Flathub requires each app to have its own repository named after the app ID:
`https://github.com/flathub/org.stirlingtools.StirlingPDF`
This is created by the Flathub team after your issue is reviewed.
4. **Submit a pull request** to the app repository with:
- `org.stirlingtools.StirlingPDF.yaml` — the Flatpak manifest
- `org.stirlingtools.StirlingPDF.metainfo.xml` — AppStream metadata
5. **Flathub review** — the Flathub team will review the manifest for policy
compliance and may request changes.
6. **CI validation** — once merged, Flathub's build system will automatically
build and publish the app.
### Useful resources
- Flathub submission guidelines: <https://docs.flathub.org/docs/for-app-authors/submission>
- Flatpak manifest reference: <https://docs.flatpak.org/en/latest/manifests.html>
- AppStream metadata spec: <https://www.freedesktop.org/software/appstream/docs/>
- Flathub linter: <https://github.com/flathub-infra/flatpak-builder-lint>
---
## Sandbox limitations
Flatpak applications run inside a sandbox. This affects Stirling PDF in the
following ways:
| Feature | Status | Notes |
|---|---|---|
| Core PDF operations | ✅ Fully supported | Built into the JAR |
| Image conversion | ✅ Fully supported | Built into the JAR |
| Office → PDF (LibreOffice) | ❌ Not available | Cannot reach host LibreOffice |
| OCR (Tesseract) | ❌ Not available | Cannot reach host Tesseract |
| Ghostscript compression | ❌ Not available | Cannot reach host Ghostscript |
| File access | ✅ Home directory | Via `--filesystem=home` |
| Network | ✅ Enabled | For remote URL operations |
For full functionality including LibreOffice and Tesseract support, use the
Docker image or the native `.deb`/`.rpm` package.
---
## Updating the Flatpak manifest
When a new Stirling PDF version is released:
1. Update the `version` field in `tauri.conf.json`
2. Rebuild the Tauri `.deb` and compute its new SHA256
3. Update the `sha256` value for the `.deb` source in the manifest
4. Update the `<release>` entry in `org.stirlingtools.StirlingPDF.metainfo.xml`
5. Submit a pull request to the Flathub app repository
+248
View File
@@ -0,0 +1,248 @@
# Stirling PDF — Snap Distribution
Stirling PDF is distributed as two separate snaps:
| Snap name | Type | Description |
|---|---|---|
| `stirling-pdf` | Desktop app | Tauri GUI + embedded backend |
| `stirling-pdf-server` | Daemon | Headless web server on port 8080 |
---
## Installing from the Snap Store
```bash
# Desktop application
sudo snap install stirling-pdf --classic
# Headless server daemon
sudo snap install stirling-pdf-server
```
> **`--classic` confinement** is required for the desktop snap so that
> optional external tools installed on the host (LibreOffice, Tesseract OCR,
> etc.) can be discovered and called by Stirling PDF at runtime.
> The server snap uses strict confinement because it only needs network access.
---
## Running the desktop app
After installation, launch from the application menu or run:
```bash
stirling-pdf
```
The embedded Spring Boot backend starts automatically and the Tauri window
opens pointing at `http://localhost:8080`.
### Configuration
| Environment variable | Default | Description |
|---|---|---|
| `STIRLING_PDF_PORT` | `8080` | Port the backend listens on |
Set variables in the snap environment:
```bash
sudo snap set stirling-pdf stirling-pdf-port=9090
```
User data is stored in `$SNAP_USER_DATA` (typically
`~/snap/stirling-pdf/current/`).
---
## Running the server daemon
```bash
# Check service status
sudo snap services stirling-pdf-server
# Start / stop / restart
sudo snap start stirling-pdf-server.stirling-pdf-server
sudo snap stop stirling-pdf-server.stirling-pdf-server
sudo snap restart stirling-pdf-server.stirling-pdf-server
# View logs
sudo snap logs stirling-pdf-server -f
```
The web UI is available at **http://localhost:8080** once the service is
running.
### Configuration
```bash
# Change the listening port
sudo snap set stirling-pdf-server stirling-pdf-port=9090
sudo snap restart stirling-pdf-server.stirling-pdf-server
```
Data and logs are stored under `/var/snap/stirling-pdf-server/current/`.
---
## Building the snaps locally
### Prerequisites
```bash
sudo snap install snapcraft --classic
sudo snap install lxd
sudo lxd init --minimal
```
### Desktop snap
```bash
# 1. Build the Tauri .deb (requires Rust, Node, JDK 21)
./gradlew :app:core:bootJar
cd frontend && npm ci && npm run tauri build && cd ..
# 2. Stage the artifact
mkdir -p manifests/snap/dist
cp frontend/src-tauri/target/release/bundle/deb/*.deb manifests/snap/dist/
# 3. Build the snap
cd manifests/snap
snapcraft --use-lxd
# 4. (Optional) Install and test locally
sudo snap install stirling-pdf_*.snap --dangerous --classic
```
### Server snap
```bash
# 1. Build the JAR
./gradlew :app:core:bootJar
# 2. Stage the artifact
mkdir -p manifests/snap/dist
cp app/core/build/libs/Stirling-PDF*.jar manifests/snap/dist/
# 3. Build the snap
cd manifests/snap
snapcraft --use-lxd --file snapcraft-server.yaml
# 4. (Optional) Install and test locally
sudo snap install stirling-pdf-server_*.snap --dangerous
```
---
## Local testing
### LXD setup (required for `--use-lxd`)
```bash
sudo snap install lxd
sudo lxd init --minimal
# Add your user to the lxd group, then log out and back in
sudo usermod -aG lxd $USER
newgrp lxd # apply without logging out (current shell only)
```
### Testing the desktop snap
```bash
cd manifests/snap
snapcraft --use-lxd
# Install the locally built snap (--dangerous bypasses signature check)
sudo snap install --dangerous --classic stirling-pdf_*.snap
# Launch and verify the UI opens
snap run stirling-pdf
# Check logs if the app fails to start
snap logs stirling-pdf -n 100
journalctl -u snap.stirling-pdf.stirling-pdf --no-pager | tail -50
# Cleanup
sudo snap remove stirling-pdf
rm -f stirling-pdf_*.snap
```
### Testing the server snap
```bash
cd manifests/snap
snapcraft --use-lxd --file snapcraft-server.yaml
sudo snap install --dangerous stirling-pdf-server_*.snap
# Verify the daemon started
sudo snap services stirling-pdf-server
curl -sf http://localhost:8080/api/v1/info | python3 -m json.tool
# Follow live logs
sudo snap logs stirling-pdf-server -f
# Cleanup
sudo snap remove stirling-pdf-server
rm -f stirling-pdf-server_*.snap
```
### Common gotchas
| Problem | Cause | Fix |
|---|---|---|
| `lxd: permission denied` | User not in `lxd` group | `sudo usermod -aG lxd $USER` then log out/in |
| `classic confinement not available` | LXD container blocks classic | Build on host directly: `snapcraft` (without `--use-lxd`) |
| `cannot find snap` after install | Shell not refreshed | Open a new terminal or run `hash -r` |
| Port 8080 already in use | Conflicting local service | `sudo lsof -i :8080` — identify and stop the process |
| App starts but UI is blank | Missing display server integration | Ensure `DISPLAY` or `WAYLAND_DISPLAY` is set; test with `echo $DISPLAY` |
| `snap logs` returns nothing | systemd journal rotated | Try `journalctl -u snap.stirling-pdf.* -e` |
---
## Publishing to the Snap Store
### One-time setup
1. Create a developer account at <https://snapcraft.io>
2. Register the snap names:
```bash
snapcraft register stirling-pdf
snapcraft register stirling-pdf-server
```
3. Generate store credentials and add them as a GitHub Actions secret named
`SNAPCRAFT_STORE_CREDENTIALS`:
```bash
snapcraft export-login --snaps stirling-pdf,stirling-pdf-server \
--channels stable,candidate,beta,edge - | base64
```
### Automated publishing (CI)
The workflow at `.github/workflows/snap-publish.yml` runs automatically on
every GitHub release and publishes both snaps to the `stable` channel.
Manual workflow dispatch allows publishing to `edge` or `candidate`.
### Manual push
```bash
snapcraft upload stirling-pdf_*.snap --release=stable
snapcraft upload stirling-pdf-server_*.snap --release=stable
```
---
## External tool support
Because the desktop snap uses **classic confinement**, it can call external
tools installed on the host:
| Tool | Install | Purpose |
|---|---|---|
| LibreOffice | `sudo apt install libreoffice` | Office ↔ PDF conversion |
| Tesseract | `sudo apt install tesseract-ocr` | OCR processing |
| Ghostscript | `sudo apt install ghostscript` | PDF compression/repair |
The server snap (strict confinement) cannot reach host binaries. Use the
Docker image or native `.deb` package when you need full tool integration
in a server context.
@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Chocolatey package manifest for Stirling PDF Server (headless JAR) -->
<package xmlns="http://schemas.microsoft.com/packaging/2015/06/nuspec.xsd">
<metadata>
<id>stirling-pdf-server</id>
<version>2.8.0</version>
<packageSourceUrl>https://github.com/Stirling-Tools/Stirling-PDF</packageSourceUrl>
<owners>Stirling PDF Inc</owners>
<title>Stirling PDF Server</title>
<authors>Stirling PDF Inc</authors>
<projectUrl>https://www.stirling.com</projectUrl>
<!-- Contact: contact@stirlingpdf.com -->
<!-- License: MIT AND LicenseRef-Stirling-PDF-Proprietary (open-core) -->
<iconUrl>https://raw.githubusercontent.com/Stirling-Tools/Stirling-PDF/main/docs/stirling.png</iconUrl>
<licenseUrl>https://github.com/Stirling-Tools/Stirling-PDF/blob/main/LICENSE</licenseUrl>
<copyright>Copyright (c) 2025 Stirling PDF Inc</copyright>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<projectSourceUrl>https://github.com/Stirling-Tools/Stirling-PDF</projectSourceUrl>
<bugTrackerUrl>https://github.com/Stirling-Tools/Stirling-PDF/issues</bugTrackerUrl>
<tags>pdf server headless java spring-boot document convert merge split</tags>
<summary>Stirling PDF headless server — runs as a Windows service on port 8080</summary>
<description>
Stirling PDF Server runs the Stirling PDF Spring Boot backend as a Windows
service, exposing the full web UI and REST API on http://localhost:8080.
All processing happens locally on your machine — no data is sent to any server.
**What is installed:**
- The Stirling-PDF Spring Boot JAR to `C:\ProgramData\StirlingPDF\`
- A Windows service (`StirlingPDFServer`) managed via NSSM
- A bundled Temurin JRE 25 (no separate Java installation required)
- Log output to `C:\ProgramData\StirlingPDF\logs\`
For the full desktop GUI application use the `stirling-pdf` package instead.
</description>
<releaseNotes>https://github.com/Stirling-Tools/Stirling-PDF/releases/tag/v2.8.0</releaseNotes>
<dependencies>
<dependency id="nssm" version="2.24.101.20180116" />
</dependencies>
</metadata>
<files>
<file src="tools\**" target="tools" />
</files>
</package>
@@ -0,0 +1,109 @@
# Stirling PDF Server — Chocolatey install script
# Installs the Spring Boot JAR and registers a Windows service via NSSM.
# The $version and $checksum variables are updated automatically by the
# chocolatey-publish.yml CI workflow on each release.
$ErrorActionPreference = 'Stop'
$packageName = 'stirling-pdf-server'
$version = '2.8.0'
# ── Download URLs ─────────────────────────────────────────────────────────────
$jarUrl = "https://github.com/Stirling-Tools/Stirling-PDF/releases/download/v${version}/Stirling-PDF-server.jar"
$jarChecksum = 'PLACEHOLDER_SHA256_UPDATED_BY_CI'
# TODO: bump Adoptium URL + sha256 to latest 25.0.X point release before release.
$jreUrl = "https://github.com/adoptium/temurin25-binaries/releases/download/jdk-25.0.1%2B9/OpenJDK25U-jre_x64_windows_hotspot_25.0.1_9.zip"
$jreChecksum = 'PLACEHOLDER_JRE_SHA256'
# ── Install paths ─────────────────────────────────────────────────────────────
$installDir = Join-Path $env:ProgramData 'StirlingPDF'
$jreDir = Join-Path $installDir 'jre'
$jarDest = Join-Path $installDir "Stirling-PDF-${version}.jar"
$logDir = Join-Path $installDir 'logs'
$dataDir = Join-Path $installDir 'data'
$serviceName = 'StirlingPDFServer'
# ── Create directories ────────────────────────────────────────────────────────
foreach ($dir in @($installDir, $logDir, $dataDir)) {
if (-not (Test-Path $dir)) {
New-Item -ItemType Directory -Path $dir -Force | Out-Null
}
}
# ── Download JAR ──────────────────────────────────────────────────────────────
Write-Host "Downloading Stirling PDF JAR v${version}..."
Get-ChocolateyWebFile -PackageName $packageName `
-FileFullPath $jarDest `
-Url $jarUrl `
-Checksum $jarChecksum `
-ChecksumType 'sha256'
# ── Download and unpack JRE ───────────────────────────────────────────────────
$jreZip = Join-Path $env:TEMP 'temurin25-jre.zip'
Write-Host "Downloading Temurin JRE 25..."
Get-ChocolateyWebFile -PackageName $packageName `
-FileFullPath $jreZip `
-Url $jreUrl `
-Checksum $jreChecksum `
-ChecksumType 'sha256'
if (Test-Path $jreDir) {
Remove-Item $jreDir -Recurse -Force
}
Get-ChocolateyUnzip -FileFullPath $jreZip -Destination $installDir
# Temurin zip extracts to a versioned sub-directory; rename it to 'jre'
$extracted = Get-ChildItem $installDir -Directory | Where-Object { $_.Name -like 'jdk-*' } | Select-Object -First 1
if ($extracted) {
Rename-Item $extracted.FullName $jreDir
}
Remove-Item $jreZip -Force -ErrorAction SilentlyContinue
$javaExe = Join-Path $jreDir 'bin\java.exe'
if (-not (Test-Path $javaExe)) {
throw "JRE installation failed: java.exe not found at $javaExe"
}
# ── Register Windows service via NSSM ────────────────────────────────────────
$nssmCmd = Get-Command nssm -ErrorAction SilentlyContinue
$nssmExe = if ($nssmCmd) { $nssmCmd.Source } else { $null }
if (-not $nssmExe) {
throw "NSSM not found. Ensure the 'nssm' Chocolatey dependency is installed."
}
# Remove existing service if upgrading
$existingService = Get-Service -Name $serviceName -ErrorAction SilentlyContinue
if ($existingService) {
Write-Host "Stopping and removing existing service..."
& $nssmExe stop $serviceName confirm 2>$null
& $nssmExe remove $serviceName confirm
}
Write-Host "Registering Windows service '$serviceName'..."
& $nssmExe install $serviceName $javaExe
& $nssmExe set $serviceName AppParameters `
"-server -XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0 -Dserver.port=8080 -DHOME_DIRECTORY=`"$dataDir`" -Dlogging.file.path=`"$logDir`" -jar `"$jarDest`""
& $nssmExe set $serviceName AppDirectory $installDir
& $nssmExe set $serviceName DisplayName "Stirling PDF Server"
& $nssmExe set $serviceName Description "Stirling PDF headless web server (port 8080)"
& $nssmExe set $serviceName Start SERVICE_AUTO_START
& $nssmExe set $serviceName AppStdout (Join-Path $logDir 'service-stdout.log')
& $nssmExe set $serviceName AppStderr (Join-Path $logDir 'service-stderr.log')
& $nssmExe set $serviceName AppRotateFiles 1
& $nssmExe set $serviceName AppRotateSeconds 86400
# Start the service
& $nssmExe start $serviceName
Write-Host ""
Write-Host "Stirling PDF Server installed and started."
Write-Host "Web UI available at: http://localhost:8080"
Write-Host "Logs: $logDir"
Write-Host ""
@@ -0,0 +1,37 @@
# Stirling PDF Server — Chocolatey uninstall script
$ErrorActionPreference = 'Stop'
$serviceName = 'StirlingPDFServer'
$installDir = Join-Path $env:ProgramData 'StirlingPDF'
# ── Stop and remove the Windows service ──────────────────────────────────────
$nssmCmd = Get-Command nssm -ErrorAction SilentlyContinue
$nssmExe = if ($nssmCmd) { $nssmCmd.Source } else { $null }
$existingService = Get-Service -Name $serviceName -ErrorAction SilentlyContinue
if ($existingService) {
Write-Host "Stopping service '$serviceName'..."
if ($nssmExe) {
& $nssmExe stop $serviceName confirm 2>$null
& $nssmExe remove $serviceName confirm
} else {
Stop-Service -Name $serviceName -Force -ErrorAction SilentlyContinue
& sc.exe delete $serviceName
}
Write-Host "Service removed."
} else {
Write-Warning "Service '$serviceName' not found; skipping service removal."
}
# ── Remove installation directory ────────────────────────────────────────────
if (Test-Path $installDir) {
Write-Host "Removing installation directory: $installDir"
Remove-Item $installDir -Recurse -Force
} else {
Write-Warning "Installation directory '$installDir' not found; skipping."
}
Write-Host "Stirling PDF Server has been uninstalled."
@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Chocolatey package manifest for Stirling PDF (Desktop) -->
<package xmlns="http://schemas.microsoft.com/packaging/2015/06/nuspec.xsd">
<metadata>
<id>stirling-pdf</id>
<version>2.8.0</version>
<packageSourceUrl>https://github.com/Stirling-Tools/Stirling-PDF</packageSourceUrl>
<owners>Stirling PDF Inc</owners>
<title>Stirling PDF</title>
<authors>Stirling PDF Inc</authors>
<projectUrl>https://www.stirling.com</projectUrl>
<!-- Contact: contact@stirlingpdf.com -->
<iconUrl>https://raw.githubusercontent.com/Stirling-Tools/Stirling-PDF/main/docs/stirling.png</iconUrl>
<!-- License: MIT AND LicenseRef-Stirling-PDF-Proprietary (open-core) — see LICENSE file for full terms -->
<licenseUrl>https://github.com/Stirling-Tools/Stirling-PDF/blob/main/LICENSE</licenseUrl>
<copyright>Copyright (c) 2025 Stirling PDF Inc</copyright>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<projectSourceUrl>https://github.com/Stirling-Tools/Stirling-PDF</projectSourceUrl>
<bugTrackerUrl>https://github.com/Stirling-Tools/Stirling-PDF/issues</bugTrackerUrl>
<tags>pdf document convert merge split compress watermark ocr sign encrypt</tags>
<summary>Powerful, locally hosted PDF manipulation tool (desktop app)</summary>
<description>
Stirling PDF is a robust, locally hosted web-based PDF manipulation tool that
allows you to perform a wide range of operations on PDF files.
All processing happens locally on your machine — no data is sent to any server.
**Features:**
- Merge, split, reorder, and rotate PDF pages
- Convert PDF to/from images, Word, Excel, PowerPoint, HTML, and Markdown
- Compress and repair PDFs
- Add watermarks, stamps, and page numbers
- Password-protect and unlock PDFs
- Redact sensitive content
- OCR support (requires Tesseract)
- Office conversion (requires LibreOffice)
- Sign and verify digital signatures
This package installs the **desktop application** (Tauri + Spring Boot). For the
headless server variant use the `stirling-pdf-server` package instead.
</description>
<releaseNotes>https://github.com/Stirling-Tools/Stirling-PDF/releases/tag/v2.8.0</releaseNotes>
<dependencies>
<!-- Java runtime is bundled; no external JRE dependency needed -->
</dependencies>
</metadata>
<files>
<file src="tools\**" target="tools" />
</files>
</package>
@@ -0,0 +1,33 @@
# Stirling PDF — Chocolatey install script (desktop MSI)
# The $version and $checksum variables are updated automatically by the
# chocolatey-publish.yml CI workflow on each release.
$ErrorActionPreference = 'Stop'
$packageName = 'stirling-pdf'
$version = '2.8.0'
$installerType = 'msi'
$url64 = "https://github.com/Stirling-Tools/Stirling-PDF/releases/download/v${version}/Stirling-PDF-windows-x86_64.msi"
$checksum64 = 'PLACEHOLDER_SHA256_UPDATED_BY_CI'
$checksumType64 = 'sha256'
$silentArgs = '/quiet /norestart ALLUSERS=1'
$packageArgs = @{
packageName = $packageName
fileType = $installerType
url64bit = $url64
softwareName = 'Stirling-PDF*'
checksum64 = $checksum64
checksumType64 = $checksumType64
silentArgs = $silentArgs
validExitCodes = @(0, 3010, 1641)
}
Install-ChocolateyPackage @packageArgs
Write-Host ""
Write-Host "Stirling PDF has been installed."
Write-Host "Launch it from the Start Menu or desktop shortcut."
Write-Host ""
@@ -0,0 +1,29 @@
# Stirling PDF — Chocolatey uninstall script (desktop MSI)
$ErrorActionPreference = 'Stop'
$packageName = 'stirling-pdf'
$softwareName = 'Stirling-PDF*'
$installerType = 'msi'
$silentArgs = '/quiet /norestart'
$validExitCodes = @(0, 3010, 1605, 1614, 1641)
[array]$key = Get-UninstallRegistryKey -SoftwareName $softwareName
if ($key.Count -eq 1) {
$key | ForEach-Object {
$packageArgs = @{
packageName = $packageName
fileType = $installerType
silentArgs = "/x $($_.PSChildName) $silentArgs"
validExitCodes = $validExitCodes
}
Uninstall-ChocolateyPackage @packageArgs
}
} elseif ($key.Count -eq 0) {
Write-Warning "$packageName has already been uninstalled by other means."
} elseif ($key.Count -gt 1) {
Write-Warning "$($key.Count) matches found for '$softwareName'."
Write-Warning "To prevent accidental removal of the wrong program, no uninstallation will occur."
Write-Warning "Please uninstall manually via 'Add or Remove Programs'."
}
@@ -0,0 +1,106 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- AppStream / Flathub metainfo for Stirling PDF -->
<!-- https://www.freedesktop.org/software/appstream/docs/ -->
<component type="desktop-application">
<id>org.stirlingtools.StirlingPDF</id>
<name>Stirling PDF</name>
<summary>Powerful, locally hosted PDF manipulation tool</summary>
<!-- metadata_license covers this metainfo file only, which must be freely licensed for Flathub. -->
<metadata_license>MIT</metadata_license>
<!-- The desktop application itself is proprietary. Flathub accepts proprietary apps
in the "non-free" tier — see https://docs.flathub.org/docs/for-app-authors/submission/#proprietary-applications -->
<project_license>MIT AND LicenseRef-Stirling-PDF-Proprietary</project_license>
<copyright>Copyright (c) 2025 Stirling PDF Inc</copyright>
<description>
<p>
Stirling PDF is a robust, locally hosted web-based PDF manipulation tool
that allows you to perform a wide range of operations on PDF files. All
processing happens locally on your machine — no data is sent to any server.
</p>
<p>Features include:</p>
<ul>
<li>Merge, split, and reorder PDF pages</li>
<li>Convert between PDF and images, Office formats, HTML, Markdown, and more</li>
<li>Compress, repair, and sanitise PDF files</li>
<li>Add watermarks, stamps, and page numbers</li>
<li>Password-protect and unlock PDFs</li>
<li>Redact sensitive text and images</li>
<li>OCR support via Tesseract (when installed on host)</li>
<li>Office conversion via LibreOffice (when installed on host)</li>
<li>Sign and verify digital signatures</li>
</ul>
<p>
Note: Due to Flatpak sandboxing, optional external tools such as
LibreOffice and Tesseract OCR are not available inside the sandbox.
Use the native package or Docker image for full functionality.
</p>
</description>
<launchable type="desktop-id">org.stirlingtools.StirlingPDF.desktop</launchable>
<url type="homepage">https://www.stirling.com</url>
<url type="bugtracker">https://github.com/Stirling-Tools/Stirling-PDF/issues</url>
<url type="donation">https://github.com/sponsors/Frooodle</url>
<url type="vcs-browser">https://github.com/Stirling-Tools/Stirling-PDF</url>
<url type="contact">mailto:contact@stirlingpdf.com</url>
<developer id="com.stirlingpdf">
<name>Stirling PDF Inc</name>
</developer>
<branding>
<color type="primary" scheme_preference="light">#4b5563</color>
<color type="primary" scheme_preference="dark">#1f2937</color>
</branding>
<categories>
<category>Office</category>
<category>Graphics</category>
<category>Utility</category>
</categories>
<keywords>
<keyword>PDF</keyword>
<keyword>document</keyword>
<keyword>convert</keyword>
<keyword>merge</keyword>
<keyword>split</keyword>
<keyword>compress</keyword>
<keyword>OCR</keyword>
<keyword>watermark</keyword>
<keyword>sign</keyword>
</keywords>
<mimetypes>
<mimetype>application/pdf</mimetype>
</mimetypes>
<screenshots>
<screenshot type="default">
<caption>Stirling PDF home screen showing available PDF operations</caption>
<image>https://raw.githubusercontent.com/Stirling-Tools/Stirling-PDF/main/docs/stirling.png</image>
</screenshot>
</screenshots>
<releases>
<release version="2.7.3" date="2025-01-01">
<description>
<p>Latest stable release of Stirling PDF.</p>
</description>
</release>
</releases>
<content_rating type="oars-1.1" />
<supports>
<control>pointing</control>
<control>keyboard</control>
</supports>
<requires>
<display_length compare="ge">768</display_length>
<internet>offline-only</internet>
</requires>
</component>
@@ -0,0 +1,114 @@
app-id: org.stirlingtools.StirlingPDF
runtime: org.freedesktop.Platform
runtime-version: "23.08"
sdk: org.freedesktop.Sdk
sdk-extensions:
- org.freedesktop.Sdk.Extension.rust-stable
- org.freedesktop.Sdk.Extension.node20
command: stirling-pdf-launcher
finish-args:
# Wayland & X11 fallback
- --socket=wayland
- --socket=fallback-x11
- --share=ipc
# GPU acceleration
- --device=dri
# Network access for the embedded web server and optional remote URLs
- --share=network
# Read/write home directory (PDF files live here)
- --filesystem=home
# D-Bus for desktop notifications and portal access
- --socket=session-bus
- --talk-name=org.freedesktop.portal.Desktop
- --talk-name=org.freedesktop.portal.FileChooser
# Audio (not required; included for completeness)
- --socket=pulseaudio
modules:
# ── Temurin JRE 25 (pre-built tarball) ────────────────────────────────────
# TODO: verify Adoptium URL + sha256 before submission — bump the point release
# as needed (e.g. 25.0.2, 25.0.3 etc).
- name: temurin-jre
buildsystem: simple
build-commands:
- mkdir -p /app/jre
- tar -xzf OpenJDK25U-jre_x64_linux_hotspot.tar.gz -C /app/jre --strip-components=1
sources:
- type: file
url: https://github.com/adoptium/temurin25-binaries/releases/download/jdk-25.0.1%2B9/OpenJDK25U-jre_x64_linux_hotspot_25.0.1_9.tar.gz
sha256: "placeholder-update-with-real-sha256-before-submission"
dest-filename: OpenJDK25U-jre_x64_linux_hotspot.tar.gz
# ── WebKitGTK (required by Tauri) ─────────────────────────────────────────
- name: webkitgtk
buildsystem: cmake-ninja
config-opts:
- -DPORT=GTK
- -DCMAKE_BUILD_TYPE=Release
- -DENABLE_DOCUMENTATION=OFF
- -DENABLE_MINIBROWSER=OFF
sources:
- type: archive
url: https://webkitgtk.org/releases/webkitgtk-2.44.3.tar.xz
sha256: "placeholder-update-with-real-sha256-before-submission"
build-options:
env:
CFLAGS: "-O2"
CXXFLAGS: "-O2"
# ── Stirling-PDF Tauri desktop bundle ─────────────────────────────────────
# The CI workflow must have built the app and placed the AppImage (or .deb)
# in the repository root before running `flatpak-builder`.
- name: stirling-pdf
buildsystem: simple
build-commands:
# Extract the Tauri .deb bundle produced by the CI pipeline
- dpkg-deb -x Stirling-PDF_amd64.deb unpacked
# Install the Tauri binary
- install -Dm755 unpacked/usr/bin/stirling-pdf /app/bin/stirling-pdf-tauri
# Install bundled libs (JRE and Spring Boot JAR embedded by Tauri)
- cp -r unpacked/usr/lib/stirling-pdf /app/lib/stirling-pdf
# Desktop file
- install -Dm644 org.stirlingtools.StirlingPDF.desktop
/app/share/applications/org.stirlingtools.StirlingPDF.desktop
# Icons
- install -Dm644 unpacked/usr/share/icons/hicolor/256x256/apps/stirling-pdf.png
/app/share/icons/hicolor/256x256/apps/org.stirlingtools.StirlingPDF.png
# AppStream metadata
- install -Dm644 org.stirlingtools.StirlingPDF.metainfo.xml
/app/share/metainfo/org.stirlingtools.StirlingPDF.metainfo.xml
# Launcher wrapper
- install -Dm755 stirling-pdf-launcher /app/bin/stirling-pdf-launcher
sources:
# The .deb is expected to be placed in the same directory as this manifest
# by the build/CI system (see docs/distribution/FLATPAK.md).
- type: file
path: ../../dist/Stirling-PDF_amd64.deb
- type: inline
dest-filename: org.stirlingtools.StirlingPDF.desktop
contents: |
[Desktop Entry]
Name=Stirling PDF
Comment=Powerful, locally hosted PDF manipulation tool
Exec=stirling-pdf-launcher %F
Icon=org.stirlingtools.StirlingPDF
Type=Application
Categories=Office;Graphics;Utility;
MimeType=application/pdf;
StartupNotify=true
Keywords=PDF;document;convert;merge;split;compress;
- type: inline
dest-filename: stirling-pdf-launcher
contents: |
#!/bin/bash
export JAVA_HOME=/app/jre
export PATH=/app/jre/bin:/app/bin:$PATH
export STIRLING_PDF_DESKTOP_UI=true
export STIRLING_PDF_SYSTEM_ROOTURI="http://localhost:${STIRLING_PDF_PORT:-8080}"
exec /app/bin/stirling-pdf-tauri "$@"
- type: file
path: org.stirlingtools.StirlingPDF.metainfo.xml
@@ -0,0 +1,27 @@
#!/bin/bash
# Launcher for the Stirling-PDF server snap daemon.
set -euo pipefail
export JAVA_HOME="${SNAP}/jre"
export PATH="${JAVA_HOME}/bin:${PATH}"
PORT="${STIRLING_PDF_PORT:-8080}"
DATA_DIR="${STIRLING_PDF_DATA_DIR:-${SNAP_DATA}}"
JAR="${SNAP}/app/stirling-pdf.jar"
if [ ! -f "$JAR" ]; then
echo "ERROR: ${JAR} not found." >&2
exit 1
fi
mkdir -p "${DATA_DIR}/logs" "${DATA_DIR}/customFiles"
exec java \
-server \
-XX:+UseContainerSupport \
-XX:MaxRAMPercentage=75.0 \
-Dserver.port="${PORT}" \
-DHOME_DIRECTORY="${DATA_DIR}" \
-Dlogging.file.path="${DATA_DIR}/logs" \
-jar "${JAR}"
@@ -0,0 +1,47 @@
#!/bin/bash
# Launcher for the Stirling-PDF desktop snap.
# Starts the embedded Spring Boot backend and then opens the Tauri shell.
set -euo pipefail
export JAVA_HOME="${SNAP}/jre"
export PATH="${JAVA_HOME}/bin:${SNAP}/bin:${PATH}"
PORT="${STIRLING_PDF_PORT:-8080}"
JAR=$(ls "${SNAP}"/usr/lib/stirling-pdf/Stirling-PDF*.jar 2>/dev/null | head -1)
if [ -z "$JAR" ]; then
echo "ERROR: Stirling-PDF JAR not found inside snap." >&2
exit 1
fi
# Start backend in background, writing PID for cleanup
java \
-Dserver.port="${PORT}" \
-DHOME_DIRECTORY="${SNAP_USER_DATA}" \
-jar "${JAR}" &
BACKEND_PID=$!
cleanup() {
kill "${BACKEND_PID}" 2>/dev/null || true
}
trap cleanup EXIT INT TERM
# Wait until the backend is accepting connections (up to 60 s)
echo "Waiting for Stirling-PDF backend on port ${PORT}…"
for i in $(seq 1 60); do
if curl -sf "http://localhost:${PORT}/api/v1/info/status" >/dev/null 2>&1; then
break
fi
sleep 1
done
# Launch Tauri shell
TAURI_BIN=$(ls "${SNAP}"/usr/bin/stirling-pdf 2>/dev/null | head -1)
if [ -n "$TAURI_BIN" ] && [ -x "$TAURI_BIN" ]; then
exec "${TAURI_BIN}" "$@"
else
# Fallback: open in default browser
xdg-open "http://localhost:${PORT}" &
wait "${BACKEND_PID}"
fi
+98
View File
@@ -0,0 +1,98 @@
name: stirling-pdf-server
title: Stirling PDF Server
version: git
summary: Headless Stirling PDF server daemon (port 8080)
description: |
Stirling PDF is a robust, locally hosted web-based PDF manipulation tool.
This snap runs the Spring Boot backend as a system daemon listening on
port 8080. A bundled Temurin JRE 25 means no separate Java installation
is needed.
Access the web UI at http://localhost:8080 once the snap is installed and
the service is running.
Optional host tools (LibreOffice, Tesseract, etc.) are accessed via the
classic interface install them with your system package manager and they
will be detected automatically.
grade: stable
confinement: strict
base: core22
license: MIT AND LicenseRef-Stirling-PDF-Proprietary
# Copyright (c) 2025 Stirling PDF Inc — https://github.com/Stirling-Tools/Stirling-PDF/blob/main/LICENSE
# Open-core: MIT core with proprietary carve-outs for specific directories (see LICENSE).
compression: lzo
architectures:
- build-on: amd64
build-for: amd64
apps:
stirling-pdf-server:
command: bin/server-launcher
daemon: simple
restart-condition: on-failure
restart-delay: 10s
stop-timeout: 30s
install-mode: enable
environment:
JAVA_HOME: $SNAP/jre
PATH: $SNAP/jre/bin:$SNAP/bin:$PATH
HOME: $SNAP_DATA
STIRLING_PDF_RUNNING_AS_SNAP: "true"
STIRLING_PDF_DATA_DIR: $SNAP_DATA
plugs:
- network
- network-bind
# Manual CLI control (start / stop / restart)
cli:
command: bin/server-launcher
environment:
JAVA_HOME: $SNAP/jre
PATH: $SNAP/jre/bin:$SNAP/bin:$PATH
HOME: $SNAP_DATA
plugs:
- network
- network-bind
parts:
# ── Spring Boot JAR ───────────────────────────────────────────────────────
jar:
plugin: nil
source: .
override-build: |
# The CI workflow stages the built JAR next to this file before calling
# snapcraft. Adjust the glob pattern to match your release artifact name.
JAR=$(ls "${SNAPCRAFT_PROJECT_DIR}"/dist/Stirling-PDF*.jar 2>/dev/null | head -1)
if [ -z "$JAR" ]; then
echo "ERROR: Stirling-PDF JAR not found in dist/. Build the project first."
exit 1
fi
mkdir -p "${SNAPCRAFT_PART_INSTALL}/app"
cp "$JAR" "${SNAPCRAFT_PART_INSTALL}/app/stirling-pdf.jar"
# ── Temurin JRE 25 ───────────────────────────────────────────────────────
# TODO: bump Adoptium URL to latest 25.0.X point release before release.
jre:
plugin: nil
source: .
override-build: |
JRE_URL="https://github.com/adoptium/temurin25-binaries/releases/download/jdk-25.0.1%2B9/OpenJDK25U-jre_x64_linux_hotspot_25.0.1_9.tar.gz"
curl -fsSL "$JRE_URL" -o /tmp/jre.tar.gz
mkdir -p "${SNAPCRAFT_PART_INSTALL}/jre"
tar -xzf /tmp/jre.tar.gz -C "${SNAPCRAFT_PART_INSTALL}/jre" --strip-components=1
build-packages:
- curl
# ── Launcher script ───────────────────────────────────────────────────────
launcher:
plugin: dump
source: snap-server/local
organize:
server-launcher: bin/server-launcher
parts-ordering:
- jre
- jar
- launcher
+128
View File
@@ -0,0 +1,128 @@
name: stirling-pdf
title: Stirling PDF
version: git
summary: Powerful, locally hosted web-based PDF manipulation tool
description: |
Stirling PDF is a robust, locally hosted web-based PDF manipulation tool that
lets you perform a wide range of operations on PDF files. It supports merging,
splitting, compressing, converting, rotating, watermarking, and much more.
This desktop snap bundles the Tauri frontend together with the Spring Boot
backend JAR and a full JRE so no internet connection or external Java
installation is required.
Note: classic confinement is required so that optional external tools such as
LibreOffice (for Office ↔ PDF conversion) and Tesseract OCR (for OCR
processing) can be invoked when they are installed on the host system.
grade: stable
confinement: classic
base: core22
license: MIT AND LicenseRef-Stirling-PDF-Proprietary
# Copyright (c) 2025 Stirling PDF Inc — https://github.com/Stirling-Tools/Stirling-PDF/blob/main/LICENSE
# Open-core: MIT core with proprietary carve-outs for specific directories (see LICENSE).
compression: lzo
architectures:
- build-on: amd64
build-for: amd64
apps:
stirling-pdf:
command: bin/stirling-pdf-launcher
desktop: share/applications/stirling-pdf.desktop
environment:
JAVA_HOME: $SNAP/jre
PATH: $SNAP/jre/bin:$SNAP/bin:$PATH
STIRLING_PDF_DESKTOP_UI: "true"
STIRLING_PDF_SYSTEM_ROOTURI: "http://localhost:${STIRLING_PDF_PORT:-8080}"
HOME: $SNAP_USER_DATA
XDG_CONFIG_HOME: $SNAP_USER_DATA/.config
XDG_DATA_HOME: $SNAP_USER_DATA/.local/share
XDG_CACHE_HOME: $SNAP_USER_COMMON/.cache
plugs:
- home
- network
- network-bind
- opengl
- audio-playback
- desktop
- desktop-legacy
- wayland
- x11
- unity7
- browser-support
- cups
- removable-media
parts:
# ── Tauri desktop bundle (.deb) ───────────────────────────────────────────
tauri-deb:
plugin: nil
source: .
override-build: |
# The .deb produced by the Tauri build is expected to be staged next to
# this snapcraft.yaml by the CI workflow before calling snapcraft.
DEB=$(ls "${SNAPCRAFT_PROJECT_DIR}"/dist/stirling-pdf_*_amd64.deb 2>/dev/null | head -1)
if [ -z "$DEB" ]; then
echo "ERROR: No Stirling-PDF .deb found in dist/. Build the Tauri app first."
exit 1
fi
dpkg-deb -x "$DEB" "${SNAPCRAFT_PART_INSTALL}"
build-packages:
- dpkg
stage-packages:
- libwebkit2gtk-4.1-0
- libgtk-3-0
- libglib2.0-0
- libgdk-pixbuf-2.0-0
- libpango-1.0-0
- libcairo2
- libatk1.0-0
- libasound2
# ── Temurin JRE 25 ───────────────────────────────────────────────────────
# TODO: bump Adoptium URL + sha256 to latest 25.0.X point release before release.
jre:
plugin: nil
source: .
override-build: |
JRE_URL="https://github.com/adoptium/temurin25-binaries/releases/download/jdk-25.0.1%2B9/OpenJDK25U-jre_x64_linux_hotspot_25.0.1_9.tar.gz"
JRE_SHA256="placeholder-update-with-real-sha256-before-release"
curl -fsSL "$JRE_URL" -o /tmp/jre.tar.gz
mkdir -p "${SNAPCRAFT_PART_INSTALL}/jre"
tar -xzf /tmp/jre.tar.gz -C "${SNAPCRAFT_PART_INSTALL}/jre" --strip-components=1
build-packages:
- curl
# ── Launcher script ───────────────────────────────────────────────────────
launcher:
plugin: dump
source: snap/local
organize:
stirling-pdf-launcher: bin/stirling-pdf-launcher
# ── Desktop integration ───────────────────────────────────────────────────
desktop-file:
plugin: nil
source: .
override-build: |
mkdir -p "${SNAPCRAFT_PART_INSTALL}/share/applications"
mkdir -p "${SNAPCRAFT_PART_INSTALL}/share/icons/hicolor/256x256/apps"
cat > "${SNAPCRAFT_PART_INSTALL}/share/applications/stirling-pdf.desktop" <<'EOF'
[Desktop Entry]
Name=Stirling PDF
Comment=Powerful PDF manipulation tool
Exec=stirling-pdf %F
Icon=stirling-pdf
Type=Application
Categories=Office;Graphics;
MimeType=application/pdf;
StartupNotify=true
Keywords=PDF;document;convert;merge;split;
EOF
# Copy icon from Tauri bundle if present
ICON_SRC="${SNAPCRAFT_PROJECT_DIR}/frontend/src-tauri/icons/128x128.png"
if [ -f "$ICON_SRC" ]; then
cp "$ICON_SRC" "${SNAPCRAFT_PART_INSTALL}/share/icons/hicolor/256x256/apps/stirling-pdf.png"
fi