- Python 95.5%
- Shell 2.4%
- Dockerfile 2.1%
|
|
||
|---|---|---|
| .forgejo/workflows | ||
| .dockerignore | ||
| .env.example | ||
| .gitignore | ||
| docker-compose.yml | ||
| docker-entrypoint.sh | ||
| Dockerfile | ||
| export_bookstack_pdfs.py | ||
| README.md | ||
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, orpages. Defaults tobooks.BOOKSTACK_OUTPUT_DIR: output directory inside the container. Defaults to/exports.CRON_SCHEDULE: cron expression for scheduled exports. Defaults to0 3 * * *.RUN_ON_STARTUP: set totrueto run an export when the container starts, before cron.RUN_ONCE: set totrueto run once and exit.GOOGLE_DRIVE_ENABLED: set totrueto mirror successful exports to Google Drive. Defaults tofalse.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 toBookStack 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 to53682.GOOGLE_DRIVE_TRASH_REMOTE_EXTRAS: set totrueto trash Drive files/folders missing locally. Defaults totrue.GOOGLE_DRIVE_SYNC_ON_FAILED_EXPORT: set totrueto sync even when the BookStack export had failures. Defaults tofalse.
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
- Enable the Google Drive API in a Google Cloud project.
- Configure the OAuth consent screen.
- Create OAuth client credentials for a desktop app.
- 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_USERNAMEACCESS_TOKEN