No description
  • Python 95.5%
  • Shell 2.4%
  • Dockerfile 2.1%
Find a file
Jackson Barker 1200f6d04e
All checks were successful
Publish Latest Image / python check (push) Successful in 4s
Publish Latest Image / shell check (push) Successful in 4s
Publish Latest Image / image build (push) Successful in 6s
Publish Latest Image / publish (push) Successful in 19s
Merge pull request 'Add Google Drive backup support' (#7) from t3code/google-drive-backup-auth into main
Reviewed-on: #7
2026-05-20 17:02:57 -04:00
.forgejo/workflows Add Google Drive backup support 2026-05-20 17:01:09 -04:00
.dockerignore Add Dockerized BookStack export workflow 2026-05-20 14:32:27 -04:00
.env.example Add Google Drive backup support 2026-05-20 17:01:09 -04:00
.gitignore Add Google Drive backup support 2026-05-20 17:01:09 -04:00
docker-compose.yml Add Google Drive backup support 2026-05-20 17:01:09 -04:00
docker-entrypoint.sh Add Dockerized BookStack export workflow 2026-05-20 14:32:27 -04:00
Dockerfile Add Google Drive backup support 2026-05-20 17:01:09 -04:00
export_bookstack_pdfs.py Add Google Drive backup support 2026-05-20 17:01:09 -04:00
README.md Add Google Drive backup support 2026-05-20 17:01:09 -04:00

BookStack PDF Export

Exports BookStack shelves to PDF files.

Docker Compose

Copy .env.example to .env, fill in the BookStack URL and API token values, then run:

docker compose up -d --build

The container writes exports to ./exports by default. Google Drive OAuth tokens are stored in ./google-credentials when Drive backup is enabled.

Environment

  • BOOKSTACK_BASE_URL: BookStack base URL.
  • BOOKSTACK_TOKEN_ID: BookStack API token ID.
  • BOOKSTACK_TOKEN_SECRET: BookStack API token secret.
  • BOOKSTACK_MODE: books, chapters, or pages. Defaults to books.
  • BOOKSTACK_OUTPUT_DIR: output directory inside the container. Defaults to /exports.
  • CRON_SCHEDULE: cron expression for scheduled exports. Defaults to 0 3 * * *.
  • RUN_ON_STARTUP: set to true to run an export when the container starts, before cron.
  • RUN_ONCE: set to true to run once and exit.
  • GOOGLE_DRIVE_ENABLED: set to true to mirror successful exports to Google Drive. Defaults to false.
  • GOOGLE_DRIVE_CLIENT_ID: Google OAuth desktop client ID.
  • GOOGLE_DRIVE_CLIENT_SECRET: Google OAuth desktop client secret.
  • GOOGLE_DRIVE_TOKEN_FILE: token path inside the container. Defaults to /credentials/google-drive-token.json.
  • GOOGLE_DRIVE_ROOT_FOLDER_NAME: Drive folder name to create/use. Defaults to BookStack PDF Export.
  • GOOGLE_DRIVE_ROOT_FOLDER_ID: optional existing Drive folder ID to sync into.
  • GOOGLE_DRIVE_AUTH_PORT: localhost redirect port shown during guided auth. Defaults to 53682.
  • GOOGLE_DRIVE_TRASH_REMOTE_EXTRAS: set to true to trash Drive files/folders missing locally. Defaults to true.
  • GOOGLE_DRIVE_SYNC_ON_FAILED_EXPORT: set to true to sync even when the BookStack export had failures. Defaults to false.

Modes:

  • books: one PDF per book.
  • chapters: top-level book pages plus one PDF per chapter.
  • pages: every page, with chapter pages placed into per-chapter folders.

One-Shot Run

docker compose run --rm -e RUN_ONCE=true bookstack-export

Google Drive Backup

Drive backup mirrors the local export tree into one stable Drive folder after a successful BookStack export. PDFs, manifest.json, and failures.json are included. Temporary .part files and hidden files are ignored. Remote files or folders that no longer exist locally are moved to Drive trash when GOOGLE_DRIVE_TRASH_REMOTE_EXTRAS=true.

The backup uses the narrow https://www.googleapis.com/auth/drive.file scope. It can create and manage files created by this app, without requesting full Drive access.

Google Cloud Setup

  1. Enable the Google Drive API in a Google Cloud project.
  2. Configure the OAuth consent screen.
  3. Create OAuth client credentials for a desktop app.
  4. Put the client ID and client secret in .env:
GOOGLE_DRIVE_CLIENT_ID=replace-me
GOOGLE_DRIVE_CLIENT_SECRET=replace-me

Headless OAuth Setup

Run the guided auth command:

docker compose run --rm bookstack-export /app/export_bookstack_pdfs.py --google-drive-auth

The command prints a Google consent URL. Open it in a browser. After consent, the browser will try to load a localhost URL such as:

http://127.0.0.1:53682/?code=...&state=...

No listener is expected. Copy the full localhost URL from the browser address bar and paste it back into the terminal prompt. The command writes the token to ./google-credentials/google-drive-token.json.

Then enable Drive backup in .env:

GOOGLE_DRIVE_ENABLED=true

Run one export to verify:

docker compose run --rm -e RUN_ONCE=true bookstack-export

Drive-Only Sync

To sync the existing local ./exports tree without running a BookStack export:

docker compose run --rm bookstack-export /app/export_bookstack_pdfs.py --google-drive-sync

Reauth and Troubleshooting

If token refresh fails, rerun --google-drive-auth. If the OAuth screen reports a redirect mismatch, confirm the desktop OAuth client allows loopback redirects and that GOOGLE_DRIVE_AUTH_PORT matches the port in the pasted localhost URL.

If a BookStack export fails, Drive sync is skipped by default so a partial local export does not replace a good Drive backup. Set GOOGLE_DRIVE_SYNC_ON_FAILED_EXPORT=true only if that behavior is intentional.

Forgejo Image Publishing

The Forgejo workflows mirror the existing runner setup: .forgejo/workflows/ci.yml runs pull request checks, .forgejo/workflows/publish.yml publishes latest plus the short commit SHA tag on pushes to main, .forgejo/workflows/publish-review-image.yml manually publishes a SHA-tagged image for a selected ref, and .forgejo/workflows/publish-labeled-review-image.yml publishes and comments a SHA-tagged review image when a pull request gets the review-image label.

Required repository secrets:

  • REGISTRY_USERNAME
  • ACCESS_TOKEN