PaperBackup is a lightweight Paper/Purpur plugin for creating ZIP backups of a Minecraft server and uploading them to Google Drive. It targets Paper/Purpur 1.21.1 and Java 21.
Backups run asynchronously, so the archive process is kept away from the main
server thread. When Google Drive storage is enabled, the ZIP is streamed directly
to Google Drive and no local backup-*.zip file is created on the server.
- Creates full server backups as
.ziparchives. - Runs backup work asynchronously.
- Automatically excludes the backup folder to avoid recursive backups.
- Supports configurable excluded files and folders.
- Supports Google Drive uploads through OAuth for normal personal Drive accounts.
- Supports service accounts for Google Workspace Shared Drives.
- Streams backup ZIPs directly to Google Drive without creating local ZIP files.
- Limits Google Drive upload chunk size to reduce temporary memory use.
- Logs JVM memory before and after backups for easier hosting diagnostics.
- Supports scheduled automatic backups.
- Persists the next scheduled backup time in
plugins/PaperBackup/state.yml, so server restarts do not reset the interval. - Supports manual backups through an admin command.
- Prunes old Google Drive backups by maximum count and maximum total folder size.
- Keeps a configurable minimum number of
backup-*.ziparchives as a safety floor during cleanup. - Can save loaded worlds before the ZIP task starts.
- Paper or Purpur 1.21.1
- Java 21
- Download the built
PaperBackupjar. - Put it into the server
pluginsfolder. - Restart the server.
- Edit
plugins/PaperBackup/google-drive-config.yml. - For a normal personal Google Drive account, use
google-drive.auth-mode: OAUTH. - Fill
google-drive.oauth.client-id,client-secret,refresh-token, andgoogle-drive.folder-id. - Set
google-drive.enabled: true. - Run
/backup reloadafter changing the config.
All commands require the backup.admin permission. Operators receive this
permission by default.
| Command | Description |
|---|---|
/backup |
Show command help. |
/backup run |
Start a manual backup. |
/backup status |
Show the current schedule, retention settings, and running state. |
/backup reload |
Reload google-drive-config.yml and reschedule automatic backups. |
The plugin creates plugins/PaperBackup/google-drive-config.yml on first startup.
If an older plugins/PaperBackup/config.yml exists, it is copied to
google-drive-config.yml automatically on first startup.
# Folder where backups are saved. Relative paths are resolved from the server root.
backup-folder: "backups"
# Maximum number of backup archives to keep.
# Set to -1 to disable this limit.
max-backups: 10
# Safety floor for automatic cleanup.
# PaperBackup never deletes below this many backup-*.zip files.
minimum-backups-to-keep: 1
# Maximum total size of all backup archives in megabytes.
# Set to -1 to disable this limit.
max-total-size-mb: 10240
# Automatic backup interval in minutes.
# Set to 0 or -1 to disable scheduled backups.
backup-interval-minutes: 60
# Delay before a missed scheduled backup starts after server boot, in seconds.
startup-delay-seconds: 60
# If true, one missed scheduled backup runs after startup-delay-seconds.
# If false, missed backups are skipped and the next future interval is used.
catch-up-missed-backup-on-start: true
# Save all loaded worlds before the async ZIP task starts.
save-worlds-before-backup: true
memory:
# Ask the JVM to clean unused backup/upload objects after a backup.
cleanup-after-backup: true
# A second memory log after cleanup. Set to 0 to disable.
delayed-log-seconds: 15
# Legacy alias. cleanup-after-backup is preferred.
request-gc-after-backup: false
# Google Drive storage.
# When enabled, PaperBackup streams the ZIP directly to Google Drive.
# No local backup-*.zip file is created on the server.
google-drive:
enabled: true
auth-mode: "OAUTH"
service-account-file: "plugins/PaperBackup/google-service-account.json"
oauth:
client-id: "PUT_OAUTH_CLIENT_ID_HERE"
client-secret: "PUT_OAUTH_CLIENT_SECRET_HERE"
refresh-token: "PUT_OAUTH_REFRESH_TOKEN_HERE"
folder-id: "PUT_GOOGLE_DRIVE_FOLDER_ID_HERE"
upload-chunk-size-kb: 256
pipe-buffer-size-kb: 256
keep-client-between-backups: false
max-backups: 10
minimum-backups-to-keep: 1
max-total-size-mb: 10240
# Files and folders excluded from backups.
# Paths are relative to the server root.
exclude-paths:
- "backups"
- "cache"
- "logs"
- "plugins/PaperBackup/backups"
- ".git"
- "crash-reports"
- "webdoc"
- "session.lock"
- "world/session.lock"
- "world_nether/session.lock"
- "world_the_end/session.lock"- With
google-drive.enabled: true, PaperBackup does not create local ZIP files. The ZIP is produced as a stream and uploaded directly to Google Drive. - PaperBackup does not keep the full ZIP in RAM. Files are read in small chunks,
the ZIP is streamed, and Google Drive upload chunks are controlled by
google-drive.upload-chunk-size-kb. - Older configs with
google-drive.upload-chunk-size-mbstill work, butupload-chunk-size-kb: 256gives the lowest memory upload mode. - Java may keep allocated heap after the backup until garbage collection. Use
the memory lines in console to check real JVM heap usage. PaperBackup requests
cleanup after backups when
memory.cleanup-after-backupis enabled. - The Google Drive retention cleanup only touches files named
backup-*.zipin the configured Google Drive folder. - The configured backup folder is always excluded automatically, even if it is
not listed in
exclude-paths. This still matters if you keep an old local backup folder or temporarily disable Google Drive storage. - The automatic schedule is based on the server machine clock, not on Minecraft
ticks. The next planned backup time is saved to
plugins/PaperBackup/state.yml. If the server is offline when a backup is due, the plugin runs one catch-up backup after startup whencatch-up-missed-backup-on-startis enabled. - When
save-worlds-before-backupis enabled, PaperBackup callsWorld#save()for loaded worlds on the main thread before the async ZIP task starts. - Files that are locked, deleted during the backup, or otherwise unreadable are skipped and logged instead of crashing the backup.
- If another backup is already running,
/backup runwill not start a second backup.
- Open Google Cloud Console.
- Create or select a project.
- Enable Google Drive API for the project.
- Go to APIs & Services -> Credentials.
- Create an OAuth client ID. For the simplest setup, use a Desktop app client.
- Use OAuth mode in
google-drive-config.yml. - Generate a refresh token for your own Google account with this scope:
https://www.googleapis.com/auth/drive. A quick way is Google OAuth 2.0 Playground:- Open OAuth 2.0 Playground.
- Open the settings gear.
- Enable Use your own OAuth credentials.
- Paste your OAuth client ID and client secret.
- Select the Drive API scope
https://www.googleapis.com/auth/drive. - Authorize APIs.
- Exchange the authorization code for tokens.
- Copy the refresh token.
- Open Google Drive in your browser and create a backup folder.
- Copy the folder ID from the folder URL:
https://drive.google.com/drive/folders/FOLDER_ID_IS_HERE
- Paste it into:
google-drive:
enabled: true
auth-mode: "OAUTH"
oauth:
client-id: "YOUR_OAUTH_CLIENT_ID"
client-secret: "YOUR_OAUTH_CLIENT_SECRET"
refresh-token: "YOUR_OAUTH_REFRESH_TOKEN"
folder-id: "FOLDER_ID_IS_HERE"- Run
/backup reload, then/backup run.
Service accounts do not have storage quota on normal personal Google Drive.
Use SERVICE_ACCOUNT only with Google Workspace Shared Drives or advanced
domain delegation. If you see Service Accounts do not have storage quota, use
OAUTH mode instead.
This project uses Gradle:
./gradlew clean buildThe compiled plugin jar is created in build/libs/PaperBackup-GoogleDrive-1.0.jar.
Tests only:
./gradlew test| Java | 21 |
| Minecraft | Paper / Purpur 1.21.1 |
| Build system | Gradle 8.10.2 + Shadow |
| Main package | com.kaerna.paperbackup |
PaperBackup — Plugin bootstrap: wires services, registers command, starts scheduler.
BackupService — Runs backups, owns the AtomicBoolean guard, calls storage.
ZipBackupWriter — Walks the server directory tree and writes the ZIP stream.
ExclusionMatcher — Decides which files and folders to skip during the walk.
BackupStorage — Interface implemented by local and Google Drive storage.
LocalBackupStorage — Writes backup-*.zip to the local backup folder.
GoogleDriveStorage — Streams the ZIP directly to Google Drive via resumable upload.
GoogleDriveClientFactory — Builds the authenticated Drive client (OAuth or service account).
BackupScheduler — Calculates next-run time, schedules the Bukkit task, handles catch-up.
ConfigService — Loads google-drive-config.yml, applies defaults, handles migration.
StateService — Reads and writes state.yml (next-backup-at-millis, last-scheduled-backup-at-millis).
RetentionPolicy — Data class: max-backups, max-total-size-mb, minimum-backups-to-keep.
LocalRetentionService — Prunes old backup-*.zip files from the local backup folder.
GoogleDriveRetentionService — Prunes old backup-*.zip files from the Google Drive folder.
BackupNotifier — Sends coloured status messages to the console and online admins.
MemoryReporter — Logs JVM heap and buffer pool usage before and after each backup.