Kavita on Cloud Run — Lab Guide
Overview
Estimated time: 45–90 minutes
Kavita is a fast, self-hosted digital library and reading server for comics, manga, and e-books — a web reading UI, OPDS feeds, collections, reading lists, and full-text search, built on .NET with an internal SQLite database. This lab takes you through the full operational lifecycle of the Kavita on Cloud Run module on Google Cloud: deploy it, access and verify it, run it day-to-day, observe it, diagnose common problems, and tear it down.
The lab focuses on operating the Cloud Run module and the Google Cloud platform, not on Kavita product features. For the complete list of provisioned services and every configuration input (organised by group), see the Configuration Guide — this lab deliberately does not duplicate that detail so it stays accurate over time.
Objectives
By the end of this lab you will be able to:
- Deploy the module from the RAD platform and locate the resources it provisions.
- Access and verify the running service, and complete the first-run setup wizard.
- Perform day-2 operations — inspect, scale (or rather, understand why not to), update, and manage storage/backups.
- Observe the service with Cloud Logging and Cloud Monitoring.
- Diagnose and resolve the most common deployment and runtime issues.
- Tear the deployment down cleanly.
Prerequisites
- Services_GCP deployed in the target project (provides the VPC, Artifact Registry, and shared service accounts this module depends on — Kavita itself needs no Cloud SQL).
- A Google Cloud project with billing enabled.
- gcloud CLI authenticated:
gcloud auth loginandgcloud auth application-default login. - Project Owner (or equivalent) IAM on the project.
- RAD platform access with permission to deploy modules into the project.
Set these shell variables once; every task below reuses them:
export PROJECT="<your-gcp-project-id>"
export REGION="us-central1" # the region you deploy into
Task 1 — Deploy the module [Automated]
-
In the RAD platform, open Kavita (Cloud Run), set
project_id, and review the inputs. Configure only what you need — the Configuration Guide documents every input by group, with defaults. Review the estimated cost (if credits are enabled) and click Deploy, which opens the deployment status page with real-time logs. -
The platform provisions the Cloud Run service and a Cloud Storage bucket (mounted at
/kavita/configvia GCS Fuse), builds the custom container image (a thin wrapper overjvmilazz0/kavita), and starts the service. There is no database to provision and no init job to wait on — Kavita manages its own internal SQLite database. First deploys typically finish in 5–10 minutes (dominated by the image build). -
When it completes, discover the resource with a name-agnostic filter (so the command keeps working regardless of the deployment suffix):
SERVICE=$(gcloud run services list --project="$PROJECT" --region="$REGION" \
--filter="metadata.name~kavita" --format="value(metadata.name)" --limit=1)
SERVICE_URL=$(gcloud run services describe "$SERVICE" \
--project="$PROJECT" --region="$REGION" --format="value(status.url)")
echo "Service: $SERVICE"
echo "URL: $SERVICE_URL"
Task 2 — Access & verify [Manual]
-
Confirm the service is healthy. Kavita exposes a public, unauthenticated health endpoint that returns
200once the server is serving:curl -s -o /dev/null -w "%{http_code}\n" "$SERVICE_URL/api/health" # expect 200 -
Open
$SERVICE_URLin a browser. On first visit Kavita's first-run setup wizard walks through creating the initial administrator account and adding your first library — there is no pre-seeded admin credential in Secret Manager. Complete this promptly: until the wizard runs, the service is reachable but unclaimed, and anyone who reaches the URL first can create the admin account. -
This module only persists Kavita's state directory (
/kavita/config— settings, the SQLite database, covers). It does not provision the actual library content. To read anything, add your owngcs_volumes(or an NFS mount) pointing at your comics/manga/e-book files and register that path as a library inside the Kavita UI.
Task 3 — Operate & keep it running (Day-2) [Manual]
-
Inspect the service and its revisions (each deploy creates an immutable revision; traffic shifts to the newest healthy one):
gcloud run services describe "$SERVICE" --project="$PROJECT" --region="$REGION"
gcloud run revisions list --service="$SERVICE" --project="$PROJECT" --region="$REGION" -
Do not scale beyond one instance.
min_instance_countdefaults to1(unlike most modules, which default to scale-to-zero — this avoids cold-start delays while gcsfuse re-mounts and Kavita reloads its library index) andmax_instance_countis pinned to1. Kavita has no clustering or shared-write coordination, so a second instance writing the same gcsfuse-mounted SQLite file risks corrupting the library index — leavemax_instance_countat1. -
Be aware of the storage layer. Cloud Run has no block Persistent Volume option, so
/kavita/config(the SQLite database and settings) is always mounted through GCS Fuse here — the one place in this module where the repository's usual "gcsfuse corrupts SQLite" caution is unavoidable rather than a misconfiguration. This module is best suited to light-to-medium libraries; for large libraries or heavy metadata scans, prefer Kavita_GKE, whose default block PVC is the safer, lower-latency option. -
Update the application version by changing the version input in the RAD platform and applying it via Update; a new image builds and a new revision rolls out. Note
application_version = "latest"resolves to a pinnedKAVITA_VERSION = 0.8.7build argument insideKavita_Common, not the generic tag the Foundation injects — bumping the version requires editing that pinned value and rebuilding, not just redeploying. -
Inspect and back up storage:
gcloud storage buckets list --project="$PROJECT" --filter="name~kavita"
gcloud storage ls gs://<config-bucket>/ # bucket name is in the OutputsBackups run on the module's
backup_schedule(default0 2 * * *UTC) and restore the whole/kavita/configdirectory — Kavita has no separate database dump, since its state is the config directory itself.
Task 4 — Observe: Logging & Monitoring [Manual]
-
Logs — from the CLI or the Logs Explorer:
gcloud run services logs read "$SERVICE" --project="$PROJECT" --region="$REGION" --limit=50Logs Explorer filter:
resource.type="cloud_run_revision" AND resource.labels.service_name="<service>". -
Monitoring — open the Cloud Run dashboard for the service and review request count, request latency, instance count, and CPU / memory utilisation. An optional uptime check against
/api/healthcan be enabled (uptime_check_config, disabled by default); if enabled, confirm it is green under Monitoring → Uptime checks and review Alerting → Policies.
Task 5 — Troubleshoot & debug [Manual]
Durable techniques for the failure modes you are most likely to hit. These are platform-level diagnostics and do not change with Kavita releases.
- Revision unhealthy / service won't serve: inspect the latest revision and
its logs for startup errors. The startup probe targets
/api/healthwith a generous failure budget (10 attempts) to tolerate first-boot library indexing before the liveness probe takes over.gcloud run revisions list --service="$SERVICE" --project="$PROJECT" --region="$REGION"
gcloud run services logs read "$SERVICE" --project="$PROJECT" --region="$REGION" --limit=100 - Service reachable but library/data missing after a redeploy: confirm the
storagebucket is still mounted at/kavita/configand that no one accidentally pointed the module at a different bucket — this directory is the entirety of Kavita's durable state. - Slow response times or occasional errors under load: this is the expected trade-off of GCS Fuse-backed SQLite on a light/medium library; if it persists, consider migrating to Kavita_GKE for its block-PVC-backed storage.
- OPDS or mobile reader app can't connect: confirm
enable_iap = false(the default) — Kavita's OPDS feed and mobile reader-app clients typically cannot complete Google IAP's auth flow — and thatingress_settings = "all". - Image build failed: review Cloud Build history for the failed build's
log; a common cause is an edited
KAVITA_VERSIONpointing at a tag that does not exist upstream. - 403 / permission errors: verify the runtime service account's IAM roles.
See the Configuration Guide's Configuration Pitfalls section for
setting-specific gotchas (including why max_instance_count must stay at 1
and why enable_redis/enable_cloudsql_volume are inert for this module).
Task 6 — Tear down [Automated]
On the Deployments page, open the deployment and click the Trash icon (Delete). Delete runs terraform destroy and is irreversible (the deployment record is retained for history). If a deployment is stuck and the RAD platform can no longer manage it (for example after manual changes that conflict with the Terraform state), use Purge instead — it removes the deployment from RAD's records without destroying the cloud resources (it makes RAD forget the project). This removes everything the module created — the Cloud Run service
and the Cloud Storage bucket holding Kavita's entire state (SQLite database,
settings, covers, backups). Resources owned by Services_GCP (the VPC,
Artifact Registry) are managed separately and are not removed here. Because
that bucket is the library index and reading progress, make sure you have a
backup or export you care about before deleting.
Summary
| Task | Type | Outcome |
|---|---|---|
| 1 — Deploy | Automated | Module provisions Cloud Run and the GCS Fuse-mounted config bucket; no database, no init job |
| 2 — Access & verify | Manual | Health check passes; complete the first-run setup wizard to create the admin account and first library |
| 3 — Operate | Manual | Inspect revisions, keep max_instance_count = 1, update version, manage storage/backups |
| 4 — Observe | Manual | Query Cloud Logging; review Cloud Monitoring metrics and optional uptime check |
| 5 — Troubleshoot | Manual | Diagnose revision, storage, OPDS/IAP, build, and IAM issues |
| 6 — Tear down | Automated | Delete (Trash) removes all module resources, including the bucket holding Kavita's entire state |