Skip to main content

Stirling-PDF on Google Cloud Run

Stirling-PDF on Google Cloud Run

Stirling-PDF is an open-source (MIT-licensed core), locally-hosted web PDF toolkit — merge, split, convert, OCR, compress, watermark, sign, redact, and 50+ other PDF operations, all processed on your own infrastructure so documents never touch a third-party service. This module deploys Stirling-PDF on Cloud Run v2 on top of the App_CloudRun foundation, which provisions and manages the shared Google Cloud infrastructure.

This guide focuses on the cloud services Stirling-PDF uses and how to explore and operate them from the Google Cloud Console and the command line. For the mechanics common to every Cloud Run application — service identity, ingress and load balancing, scaling and concurrency, CI/CD, Cloud Armor, IAP, Binary Authorization, VPC Service Controls, and the deployment lifecycle — refer to the App_CloudRun foundation guide rather than repeating them here.


1. Overview

Stirling-PDF runs as a Java / Spring Boot container (with a bundled LibreOffice for document conversions) on Cloud Run v2. The deployment wires together a deliberately small set of Google Cloud services — Stirling-PDF is stateless, so there is no database, no persistent storage, and no secrets to manage:

CapabilityGoogle Cloud serviceNotes
ComputeCloud Run v2Java service, 1 vCPU / 2 GiB by default, serverless autoscaling; scale-to-zero enabled
Container imageArtifact RegistryOfficial stirlingtools/stirling-pdf image, mirrored in by default
IngressCloud Run URL / Cloud Load BalancingDefault run.app URL; optional external HTTPS load balancer + custom domain
Rate limiting (optional)RedisOff by default; enable only to throttle abuse on a public instance
ObservabilityCloud Logging / Cloud MonitoringContainer logs, metrics, optional uptime check and alerts

Sensible defaults worth knowing up front:

  • Stateless — no database, no storage, no secrets. database_type = "NONE", no GCS buckets, no NFS, and an empty secret map. Every PDF operation runs in a per-request ephemeral working directory that is discarded on completion.
  • Prebuilt image. container_image_source = "prebuilt" deploys the official stirlingtools/stirling-pdf image directly; enable_image_mirroring = true mirrors it into Artifact Registry to avoid Docker Hub rate limits.
  • Login is disabled by default. enable_login = false (SECURITY_ENABLELOGIN=false) ships an open instance. Enable it and front the service with IAP or Cloud Armor for a private deployment.
  • Request-based billing + scale-to-zero. cpu_always_allocated = false and min_instance_count = 0 — CPU is billed only while serving a request, and the service scales to zero when idle. A cold start adds a few seconds of JVM warm-up.
  • 2 GiB memory floor. The JVM plus LibreOffice needs at least 2Gi; raise memory_limit for heavy OCR / conversion workloads.
  • Public ingress by default. ingress_settings = "all" so the toolkit is reachable at its run.app URL. Combine with IAP for identity-gated access.
  • Health probes hit /api/v1/info/status — a public, unauthenticated endpoint that returns 200 once the JVM and LibreOffice have initialised (~70s first-boot window).

2. Google Cloud Services & How to Explore Them

All commands assume PROJECT and REGION are set. Service and resource names are reported in the deployment Outputs.

A. Cloud Run — the Stirling-PDF service

Stirling-PDF runs as a Cloud Run v2 service that autoscales by request load between the minimum (0) and maximum instance counts. Each deployment creates an immutable revision; traffic can be split across revisions for safe rollouts.

  • Console: Cloud Run → select the service for revisions, traffic, logs, and metrics.
  • CLI:
    gcloud run services list --project "$PROJECT" --region "$REGION"
    gcloud run services describe <service-name> --project "$PROJECT" --region "$REGION"
    gcloud run revisions list --service <service-name> --project "$PROJECT" --region "$REGION"

See App_CloudRun for scaling, concurrency, execution environment, and traffic splitting.

B. Artifact Registry — the container image

The official stirlingtools/stirling-pdf image is mirrored into Artifact Registry (enable_image_mirroring = true) and Cloud Run pulls it from there. No Cloud Build step runs — the image is prebuilt upstream.

  • Console: Artifact Registry → Repositories.
  • CLI:
    gcloud artifacts repositories list --project "$PROJECT" --location "$REGION"
    gcloud artifacts docker images list <repo-path> --project "$PROJECT"

See App_CloudRun for the mirroring mechanism and image retention.

C. Networking & ingress

The service is reachable at its run.app URL by default (ingress_settings = "all"). An external HTTPS load balancer with a custom domain, Cloud CDN, and Cloud Armor can be layered on; ingress settings and VPC egress control connectivity.

  • Console: Cloud Run (service URL); Network services → Load balancing.
  • CLI:
    gcloud run services describe <service-name> --region "$REGION" --format='value(status.url)'
    gcloud compute addresses list --project "$PROJECT"

See App_CloudRun.

D. Redis (optional rate limiting)

Redis is disabled by default. Stirling-PDF uses it only for rate limiting and bot detection on public-facing instances (enable_redis = true). When redis_host is left empty and enable_nfs is true, the NFS server VM's IP is used as the Redis endpoint.

  • Console: Memorystore → Redis (if using a managed instance).
  • CLI:
    redis-cli -h <redis-host> ping
    # Confirm the env injected into the running revision:
    gcloud run services describe <service-name> --region "$REGION" \
    --format='value(spec.template.spec.containers[0].env)'

E. Identity-Aware Proxy (optional)

Because Stirling-PDF processes potentially sensitive documents, a private deployment should gate access with IAP. Enabling enable_iap requires an authenticated, authorized Google identity before any request reaches the service — no VPN or Stirling-PDF login configuration needed.

  • Console: Security → Identity-Aware Proxy.
  • CLI:
    gcloud iap web get-iam-policy --resource-type=backend-services --project "$PROJECT"

See App_CloudRun for the IAP wiring.

F. Cloud Logging & Monitoring

Container logs flow to Cloud Logging; Cloud Run metrics flow to Cloud Monitoring, with optional uptime checks and alert policies.

  • Console: Logging → Logs Explorer; Monitoring → Dashboards / Alerting.
  • CLI:
    gcloud run services logs read <service-name> --project "$PROJECT" --region "$REGION" --limit 50

3. Stirling-PDF Application Behaviour

  • Nothing is persisted. Uploads are written to a per-request ephemeral working directory and deleted when the response is returned. There is no database and no bucket — a redeploy or scale event loses nothing because there is nothing to lose.
  • Slow first boot. Spring Boot plus LibreOffice initialisation takes tens of seconds. The startup probe targets /api/v1/info/status and allows up to ~70 seconds (10s initial delay + 6 × 10s) before the revision is marked unhealthy.
  • Login is optional and off by default. enable_login = false ships an open instance. Set enable_login = true to require Stirling-PDF's built-in authentication; combine with IAP for defence in depth.
  • Version upgrades are image-tag bumps. Because the image is unmodified upstream and there is no schema, changing application_version rolls out a new revision with no migration step.
  • Large files and long conversions. Raise memory_limit and timeout_seconds for large documents or heavy OCR; set SYSTEM_MAXFILESIZE via environment_variables to cap upload size.
  • Confirm the running configuration:
    gcloud run services describe <service-name> --region "$REGION" --project "$PROJECT" \
    --format='value(spec.template.spec.containers[0].env)'

4. Configuration Variables

Variables are grouped exactly as they appear on the deployment platform. Only settings specific to or notable for Stirling-PDF are listed; every other input is inherited from App_CloudRun with its standard behaviour.

Group 1 — Project & Identity

VariableDefaultDescription
project_id(required)Target Google Cloud project.
regionus-central1Region for the service and regional resources.

Group 2 — Deployment Environment

VariableDefaultDescription
tenant_deployment_iddemoShort suffix that makes resource names unique per environment.
support_users[]Emails granted project access and monitoring alerts.
resource_labels{}Labels applied to all resources.

Group 3 — Application Identity

VariableDefaultDescription
application_namestirlingpdfBase name for resources. Do not change after first deploy.
display_nameStirling-PDFHuman-readable name shown in the Console.
application_versionlatestStirling-PDF image tag; pin to a specific release in production.
enable_loginfalseEnable Stirling-PDF's built-in auth (SECURITY_ENABLELOGIN).
default_localeen-USDefault UI locale (SYSTEM_DEFAULTLOCALE).

Group 4 — Runtime & Scaling

VariableDefaultDescription
deploy_applicationtrueSet false to provision infrastructure only.
container_image_sourceprebuiltDeploy the official image (prebuilt) or build a custom one.
cpu_limit1000mCPU per instance.
memory_limit2GiMemory per instance; 2Gi floor for JVM + LibreOffice.
cpu_always_allocatedfalseRequest-based billing — Stirling-PDF has no background work.
min_instance_count0Fixed at 0 (scale-to-zero) — the module hardcodes this value; the variable is not forwarded to the Foundation and cannot be changed.
max_instance_count3Autoscaling upper bound (safe to raise — no shared state).
container_port8080Stirling-PDF listens on port 8080.
execution_environmentgen2Gen2 recommended.
timeout_seconds60Maximum request duration; raise for large conversions.
enable_cloudsql_volumefalseNot used — Stirling-PDF has no database.
enable_image_mirroringtrueMirror the image into Artifact Registry.
traffic_split[]Split traffic across revisions for staged rollouts.

Group 5 — Access & Ingress Control

VariableDefaultDescription
ingress_settingsallall for public access; internal-and-cloud-load-balancing behind an LB.
vpc_egress_settingPRIVATE_RANGES_ONLYRoute only RFC 1918 traffic via VPC.
enable_iapfalseRequire Google sign-in. Recommended for private/sensitive-document instances.
iap_authorized_users / iap_authorized_groups[]Who may access through IAP.

Group 6 — Environment Variables & Secrets

VariableDefaultDescription
environment_variables{}Extra Stirling-PDF settings (e.g. SYSTEM_MAXFILESIZE). Login and locale are set via enable_login / default_locale.
secret_environment_variables{}Secret Manager references. Stirling-PDF needs none by default.
secret_propagation_delay30Seconds to wait after secret creation before proceeding.
secret_rotation_period2592000sSecret Manager rotation notification frequency.

Group 7 — Backup & Restore

Stirling-PDF is stateless, so backup inputs (backup_schedule, backup_retention_days, enable_backup_import, backup_source, backup_uri, backup_format) have no application data to protect. Left at defaults.

Group 8 — CI/CD & Binary Authorization

Standard App_CloudRun Cloud Build / Cloud Deploy integration — see App_CloudRun. Key inputs: enable_cicd_trigger, github_repository_url, github_token, enable_cloud_deploy, enable_binary_authorization.

Group 10 — Load Balancer, CDN & Image Retention

VariableDefaultDescription
enable_cloud_armorfalseProvision Global HTTPS LB + Cloud Armor WAF. Recommended for public instances.
admin_ip_ranges[]CIDR ranges exempted from WAF rules.
application_domains[]Custom domain names for the HTTPS LB.
enable_cdnfalseEnable Cloud CDN on the HTTPS LB backend.
max_images_to_retain / delete_untagged_images / image_retention_days(set)Artifact Registry cleanup policy.

Group 11 — Storage & Filesystem

VariableDefaultDescription
create_cloud_storagefalseStirling-PDF is stateless — no bucket by default.
storage_buckets[]Optional additional GCS buckets.
enable_nfsfalseNFS off by default; enable only if co-locating Redis on the NFS server.
gcs_volumes[]GCS Fuse volume mounts (requires gen2).
manage_storage_kms_iam / enable_artifact_registry_cmekfalseCMEK options.

Group 12 — Database Backend

VariableDefaultDescription
database_typeNONEFixed — Stirling-PDF uses no database.
database_password_length32Not used.
enable_auto_password_rotation / rotation_propagation_delay_secoffNot applicable.

Group 14 — Observability & Health

VariableDefaultDescription
startup_probeHTTP /api/v1/info/status, 10s delay, 6 retriesStartup probe. ~70s first-boot window for JVM + LibreOffice.
liveness_probeHTTP /api/v1/info/status, 15s delayLiveness probe.
uptime_check_config{ enabled=false, path="/api/v1/info/status" }Cloud Monitoring uptime check.
alert_policies[]Metric alert policies.

Group 21 — Redis (optional rate limiting)

VariableDefaultDescription
enable_redisfalseEnable Redis-backed rate limiting / bot detection for public instances.
redis_host""Redis endpoint. Leave empty to use the NFS server IP (requires enable_nfs = true).
redis_port6379Redis port.
redis_auth""Optional Redis auth password (sensitive).

Group 22 — VPC Service Controls & Audit Logging

VariableDefaultDescription
enable_vpc_scfalseEnforce a VPC-SC perimeter (requires organization_id).
vpc_cidr_ranges / vpc_sc_dry_run(set)Access level CIDRs / dry-run mode.
enable_audit_loggingfalseDetailed Cloud Audit Logs.

5. Outputs

Returned on a successful deployment — the quickest way to locate and explore the running resources.

OutputDescription
service_nameCloud Run service name.
service_urlDefault run.app URL of the service.
service_locationRegion the service runs in.
stage_servicesStage-specific service URLs (Cloud Deploy).
load_balancer_ip / load_balancer_urlExternal HTTPS load balancer IP / URL (when enabled).
storage_bucketsCreated Cloud Storage buckets (empty — Stirling-PDF is stateless).
network_name / network_exists / regionsVPC network, presence, regions.
container_image / container_registryDeployed image and Artifact Registry repo.
monitoring_enabled / monitoring_notification_channels / uptime_check_namesMonitoring status, channels, uptime checks.
deployment_id / tenant_id / resource_prefixNaming identifiers.
project_id / project_numberProject identifiers.
cicd_enabled / github_repository_url / cicd_configurationCI/CD status and details.
artifact_registry_repository / cloudbuild_trigger_nameRegistry and build trigger.
vpc_sc_enabled / vpc_sc_perimeter_name / vpc_sc_dry_run_modeVPC-SC status.
audit_logging_enabled / artifact_registry_cmek_enabledAudit logging and CMEK status.

6. Configuration Pitfalls & Sensible Defaults

Risk: Critical (data loss / outage / security) — High (service degraded) — Medium (cost or partial degradation) — Low (minor).

Inherited plan-time validation. This module passes its configuration through the App_CloudRun foundation engine, which validates values and combinations at plan time — IAP with no authorized identities, a gen1 runtime with NFS/GCS mounts, an out-of-range redis_port/timeout_seconds, a memory below the gen2 floor. Invalid configuration fails the plan with a clear, named error before any resource is created, so most mistakes below are caught up front rather than at apply or runtime.

SettingSensible valueRiskConsequence if wrong
enable_login + ingressenable_login = true or IAP for private useHighDefault enable_login = false + public ingress leaves an open PDF toolkit anyone with the URL can use.
enable_iapEnable for sensitive-document instancesHighWithout IAP (and with login off) the service is unauthenticated; users can upload confidential documents to an open endpoint.
memory_limit2GiHighBelow ~2Gi the JVM + LibreOffice OOM-kills during conversions; gen2 also rejects < 512Mi at plan time.
timeout_seconds60, raise for big filesHighLarge OCR/conversion jobs exceeding the timeout return 504 mid-operation.
startup_probe windowKeep the ~70s defaultMediumShortening the initial delay / failure threshold marks the revision unhealthy before LibreOffice finishes warming up.
enable_cloud_armorEnable for public instancesMediumA public toolkit without a WAF is exposed to abuse and automated scanning.
enable_redisEnable on public instancesMediumWithout it there is no rate limiting / bot detection to throttle abusive traffic.
min_instance_count0 (fixed)LowScale-to-zero adds a few seconds of JVM warm-up on the first request after idle. The module hardcodes min_instance_count = 0 — the variable is not forwarded, so it cannot be raised to 1 to eliminate cold starts.
SYSTEM_MAXFILESIZE (via environment_variables)Set a sane capLowUnbounded uploads let a single large file consume the instance's memory.

For the foundation behaviour referenced throughout — service identity, scaling and concurrency, ingress and load balancing, CI/CD, Cloud Armor, IAP, Binary Authorization, VPC-SC, and image mirroring — see App_CloudRun. Stirling-PDF-specific application configuration shared with the GKE variant is described in StirlingPDF_Common.