Update Strategies¶
This document describes the update strategies available in the minecraft-operator for managing Paper server versions and plugin versions.
Overview¶
The minecraft-operator provides flexible update strategies that allow you to control how your PaperMC servers and plugins are updated. Both PaperMCServer and Plugin resources support update strategies, giving you fine-grained control over version management.
Key principles:
- Never uses
:latestDocker tags - The operator always resolves to concrete version-build combinations (e.g.,1.21.1-91) - Unified approach - Similar concepts across both server and plugin resources
- Compatibility-first - The constraint solver ensures all components work together
- Scheduled updates - Updates only happen during configured maintenance windows
Version and Build Concepts¶
Understanding the difference between versions and builds is essential:
Paper Versioning¶
Paper uses a two-part versioning scheme:
- Version: The Minecraft version (e.g.,
1.21.1,1.20.4) - Build: The Paper build number for that version (e.g.,
91,115) - Docker tag: Combines both as
{version}-{build}(e.g.,1.21.1-91)
Example timeline for Paper 1.21.1:
1.21.1-86(initial release)1.21.1-87(bug fixes)1.21.1-91(latest build)
Build updates are typically bug fixes and performance improvements without gameplay changes. Version updates introduce new Minecraft features and may break plugin compatibility.
Plugin Versioning¶
Plugins typically use semantic versioning:
- Standard semver:
2.5.0,1.18.2,3.0.1 - Some plugins include builds:
2.5.0-build.123
The operator fetches version metadata from plugin repositories (Hangar, Modrinth, etc.) to determine compatibility.
PaperMCServer Update Strategies¶
The PaperMCServer resource supports four update strategies via the updateStrategy field.
Strategy: latest¶
Purpose: Always run the newest available Paper version from Docker Hub.
Behavior:
- Automatically updates to the latest Paper version (both version and build)
- Ignores plugin compatibility constraints
- Best for bleeding-edge testing or vanilla servers without plugins
Version resolution:
- Queries Docker Hub for the latest available Paper image tag
- Resolves to the highest version-build combination (e.g.,
1.21.1-91)
Update behavior:
- Updates happen during maintenance windows
- Both version upgrades (1.21.1 → 1.21.2) and build upgrades (91 → 92) are automatic
Use cases:
- Test/development environments
- Vanilla servers (no plugins)
- Bleeding-edge experimental servers
- When you want the absolute latest features
Example:
apiVersion: mc.k8s.lex.la/v1alpha1
kind: PaperMCServer
metadata:
name: test-server
spec:
updateStrategy: "latest"
updateSchedule:
checkCron: "0 3 * * *"
maintenanceWindow:
enabled: true
cron: "0 4 * * 0"
Important notes:
- May break plugin compatibility
- Suitable for servers without plugins or with very flexible plugins
- Always resolves to concrete tag (never uses
:latestDocker tag)
Strategy: auto¶
Purpose: Automatically pick the best Paper version compatible with all matched plugins.
Behavior:
- Uses the constraint solver to find the maximum Paper version where ALL plugins have compatible versions
- Balances staying up-to-date with maintaining plugin compatibility
- The solver considers both Paper versions and plugin version compatibility
Version resolution:
- Fetch all available Paper versions
- For each Paper version (newest first), check if ALL matched plugins have at least one compatible version
- Return the highest Paper version that satisfies all plugin constraints
- Respects
updateDelayif configured
Update behavior:
- Automatic version updates when solver finds a better solution
- Updates happen during maintenance windows
- Both version and build updates are automatic
- Blocks updates if no compatible solution exists
Use cases:
- Production servers with multiple plugins
- When you want automatic updates but need plugin compatibility
- Servers where you trust the solver to make good decisions
- Balanced approach between stability and staying current
Example:
apiVersion: mc.k8s.lex.la/v1alpha1
kind: PaperMCServer
metadata:
name: production-server
labels:
environment: production
type: modded
spec:
updateStrategy: "auto"
updateDelay: 168h # Wait 7 days before applying updates
updateSchedule:
checkCron: "0 3 * * *"
maintenanceWindow:
enabled: true
cron: "0 4 * * 0"
How it works on initial deployment:
On first deployment, the solver analyzes all matched plugins and selects the best Paper version. The operator then sets the StatefulSet image to the resolved version-build tag (e.g., lexfrei/papermc:1.21.1-91).
Status tracking:
The operator maintains detailed status information:
status:
currentPaperVersion: "1.21.1"
currentPaperBuild: 91
desiredPaperVersion: "1.21.1"
desiredPaperBuild: 91
availableUpdate:
paperVersion: "1.21.2"
paperBuild: 115
releasedAt: "2024-01-15T10:00:00Z"
foundAt: "2024-01-22T03:00:00Z"
Strategy: pin¶
Purpose: Pin to a specific Paper version but automatically update to the latest build.
Behavior:
- Stays on the specified Paper version (e.g.,
1.21.1) - Automatically updates to newer builds of that version (e.g.,
91 → 92 → 95) - Build updates are typically safe (bug fixes, performance improvements)
Version resolution:
- Uses the Paper version specified in
paperVersionfield - Finds the latest build available for that version
- Validates compatibility with matched plugins (for the pinned version)
Update behavior:
- No version updates (stays on pinned version)
- Automatic build updates during maintenance windows
- If you want to change versions, update the
paperVersionfield manually
Use cases:
- Production servers that need stability on a specific Minecraft version
- When plugins only support a specific version range
- Gradual migration to new versions (manually update
paperVersionwhen ready) - When you want bug fixes but not feature changes
Example:
apiVersion: mc.k8s.lex.la/v1alpha1
kind: PaperMCServer
metadata:
name: stable-server
spec:
updateStrategy: "pin"
paperVersion: "1.21.1" # Required for pin strategy
updateSchedule:
checkCron: "0 3 * * *"
maintenanceWindow:
enabled: true
cron: "0 4 * * 0"
Version changes:
To upgrade to a new version, edit the spec:
The operator will then resolve the latest build for 1.21.2 during the next maintenance window.
Strategy: build-pin¶
Purpose: Pin to both a specific Paper version AND build - no automatic updates.
Behavior:
- Completely static configuration
- No automatic updates whatsoever
- Full manual control over both version and build
Version resolution:
- Uses exact
paperVersionandpaperBuildspecified in spec - Validates the version-build combination exists
- Checks plugin compatibility for information purposes
Update behavior:
- No automatic updates
- To update, manually change
paperVersionand/orpaperBuildfields - Useful for maximum stability and predictability
Use cases:
- Extremely sensitive production environments
- Certification/compliance requirements
- When you need exact reproducibility
- Regression testing against specific builds
- When any change requires approval/testing
Example:
apiVersion: mc.k8s.lex.la/v1alpha1
kind: PaperMCServer
metadata:
name: certified-server
spec:
updateStrategy: "build-pin"
paperVersion: "1.21.1" # Required
paperBuild: 91 # Required
updateSchedule:
checkCron: "0 3 * * *"
maintenanceWindow:
enabled: true
cron: "0 4 * * 0"
Manual updates:
# Update to a new build
kubectl patch papermcserver certified-server --type=merge \
-p '{"spec":{"paperBuild":95}}'
# Update to a new version and build
kubectl patch papermcserver certified-server --type=merge \
-p '{"spec":{"paperVersion":"1.21.2","paperBuild":115}}'
Plugin Update Strategies¶
The Plugin resource uses the same updateStrategy field as PaperMCServer, providing a unified approach to version management.
Strategy: latest¶
Purpose: Automatically use the latest plugin version compatible with matched servers.
Behavior:
- Solver finds the maximum plugin version compatible with ALL matched servers
- Considers Paper versions of all servers this plugin applies to
- Respects
updateDelayfor stability
Version resolution:
- Fetch all available plugin versions from the repository (Hangar, Modrinth, etc.)
- Filter versions by
updateDelay(exclude too-new versions) - For each version (newest first), check compatibility with ALL matched servers' Paper versions
- Return the highest compatible version
Update behavior:
- Automatic updates when new compatible versions are available
- Updates respect server maintenance windows
- If multiple servers match, uses the most conservative compatible version
Use cases:
- Plugins you want to keep current automatically
- Well-maintained plugins with good backward compatibility
- Non-critical plugins where updates are low-risk
Example:
apiVersion: mc.k8s.lex.la/v1alpha1
kind: Plugin
metadata:
name: bluemap
spec:
source:
type: hangar
project: "BlueMap"
updateStrategy: latest
updateDelay: 168h # Wait 7 days before applying new versions
instanceSelector:
matchLabels:
type: vanilla
Strategy: auto¶
Purpose: Let the solver pick the best plugin version compatible with all matched servers.
Behavior:
- Solver finds optimal plugin version that works with all matched servers' Paper versions
- Automatically adapts as servers update their Paper versions
- Balances compatibility with staying current
Version resolution:
- Fetch all available plugin versions from repository
- Filter versions by
updateDelay - For each matched server, find plugin versions compatible with that server's Paper version
- Return the highest plugin version compatible with ALL servers
- If multiple servers run different Paper versions, picks most conservative compatible version
Update behavior:
- Automatic updates when new compatible versions are available
- Updates respect server maintenance windows
- Adapts to server Paper version changes
Use cases:
- Plugins that should stay compatible with server versions
- Multi-server environments with different Paper versions
- When you want automatic updates but need cross-server compatibility
- Plugins with good semantic versioning and compatibility metadata
Example:
apiVersion: mc.k8s.lex.la/v1alpha1
kind: Plugin
metadata:
name: worldedit
spec:
source:
type: hangar
project: "WorldEdit"
updateStrategy: auto
updateDelay: 168h
instanceSelector:
matchExpressions:
- key: type
operator: In
values: ["creative", "modded"]
How it works:
- Server A: Paper 1.21.1
- Server B: Paper 1.20.4
- Both match this plugin
- Plugin versions: 7.3.0 (1.21+), 7.2.0 (1.20-1.21), 7.1.0 (1.20)
- Solver picks 7.2.0 (compatible with both servers)
Strategy: pin¶
Purpose: Pin to a specific plugin version, with automatic build updates.
Behavior:
- Uses the exact version specified in
versionfield - Automatically updates to newer builds of the same version (if available)
- Manual control over major/minor version, automatic patch/build updates
Version resolution:
- Returns the
versionvalue directly - Validates the version exists in the repository
- Automatically updates to latest build of that version
- Checks compatibility with matched servers (warning if incompatible)
Update behavior:
- Build updates are automatic (e.g., 2.5.0-build.100 → 2.5.0-build.101)
- Version updates require manual change of the
versionfield
Use cases:
- Critical plugins where stability is paramount
- Plugins known to have breaking changes between versions
- When you need to test plugin updates in staging first
- Regulatory/compliance requirements
Example:
apiVersion: mc.k8s.lex.la/v1alpha1
kind: Plugin
metadata:
name: essentialsx
spec:
source:
type: hangar
project: "Essentials"
updateStrategy: pin
version: "2.20.1" # Required for pin strategy
instanceSelector:
matchLabels:
environment: production
Manual updates:
Strategy: build-pin¶
Purpose: Pin to exact plugin version and build - no automatic updates.
Behavior:
- Completely static configuration
- No automatic updates whatsoever
- Full manual control over both version and build
- Maximum stability and reproducibility
Version resolution:
- Uses exact
versionandbuildspecified in spec - Validates the version-build combination exists in repository
- Checks compatibility for information purposes only
Update behavior:
- No automatic updates
- To update, manually change
versionand/orbuildfields - Useful for maximum stability and predictability
Use cases:
- Extremely critical plugins (permissions, economy, core mechanics)
- Certification/compliance requirements
- Exact reproducibility needed
- Regression testing against specific builds
- When any change requires approval/testing
Example:
apiVersion: mc.k8s.lex.la/v1alpha1
kind: Plugin
metadata:
name: luckperms
spec:
source:
type: hangar
project: "LuckPerms"
updateStrategy: build-pin
version: "5.4.102" # Required
build: 1543 # Required
instanceSelector:
matchLabels:
environment: production
criticality: high
Manual updates:
# Update to a new build
kubectl patch plugin luckperms --type=merge \
-p '{"spec":{"build":1550}}'
# Update to a new version and build
kubectl patch plugin luckperms --type=merge \
-p '{"spec":{"version":"5.4.110","build":1555}}'
Strategy Comparison¶
PaperMCServer Strategies¶
| Strategy | Automatic Version Updates | Automatic Build Updates | Version Selection | Use Case |
|---|---|---|---|---|
latest | Yes | Yes | Highest available from Hub | Testing, vanilla servers |
auto | Yes | Yes | Solver (plugin-compatible) | Production with plugins |
pin | No (manual) | Yes | Pinned version, latest build | Stable version, get bug fixes |
build-pin | No (manual) | No (manual) | Fully pinned | Maximum stability, compliance |
Plugin Strategies¶
| Strategy | Automatic Version Updates | Automatic Build Updates | Version Selection | Use Case |
|---|---|---|---|---|
latest | Yes | Yes | Highest server-compatible | Keep plugins current |
auto | Yes | Yes | Solver (cross-server compatible) | Multi-server compatibility |
pin | No (manual) | Yes | Pinned version, latest build | Stable version, get bug fixes |
build-pin | No (manual) | No (manual) | Fully pinned | Maximum stability, compliance |
Common Configuration Scenarios¶
Scenario 1: Production Server with Automatic Plugin Updates¶
Goal: Run a production server that stays on a stable Paper version but gets the latest compatible plugins.
apiVersion: mc.k8s.lex.la/v1alpha1
kind: PaperMCServer
metadata:
name: prod-server
labels:
environment: production
spec:
updateStrategy: "pin"
paperVersion: "1.21.1"
updateDelay: 168h
---
apiVersion: mc.k8s.lex.la/v1alpha1
kind: Plugin
metadata:
name: plugin-a
spec:
updateStrategy: latest
updateDelay: 336h # 14 days - more conservative for production
instanceSelector:
matchLabels:
environment: production
Result: Server stays on Paper 1.21.1 (with build updates), plugins update to latest compatible versions after 14-day delay.
Scenario 2: Fully Automatic Server¶
Goal: Development server that always runs the latest compatible versions of everything.
apiVersion: mc.k8s.lex.la/v1alpha1
kind: PaperMCServer
metadata:
name: dev-server
labels:
environment: dev
spec:
updateStrategy: "auto"
updateDelay: 24h # Short delay for dev
---
apiVersion: mc.k8s.lex.la/v1alpha1
kind: Plugin
metadata:
name: plugin-b
spec:
updateStrategy: latest
updateDelay: 24h
instanceSelector:
matchLabels:
environment: dev
Result: Both Paper and plugins update automatically to latest compatible versions after 24 hours.
Scenario 3: Maximum Stability¶
Goal: Production server with zero automatic updates - full manual control.
apiVersion: mc.k8s.lex.la/v1alpha1
kind: PaperMCServer
metadata:
name: critical-server
labels:
environment: production
criticality: high
spec:
updateStrategy: "build-pin"
paperVersion: "1.21.1"
paperBuild: 91
---
apiVersion: mc.k8s.lex.la/v1alpha1
kind: Plugin
metadata:
name: plugin-c
spec:
updateStrategy: build-pin
version: "2.5.0"
build: 123
instanceSelector:
matchLabels:
criticality: high
Result: Nothing updates automatically. All changes require manual spec updates.
Scenario 4: Mixed Strategy - Stable Server, Experimental Plugins¶
Goal: Keep server version stable but allow some plugins to update automatically.
apiVersion: mc.k8s.lex.la/v1alpha1
kind: PaperMCServer
metadata:
name: mixed-server
labels:
type: mixed
spec:
updateStrategy: "pin"
paperVersion: "1.21.1"
---
# Critical plugin - pinned
apiVersion: mc.k8s.lex.la/v1alpha1
kind: Plugin
metadata:
name: essential-plugin
spec:
updateStrategy: pin
version: "3.0.1"
instanceSelector:
matchLabels:
type: mixed
---
# Non-critical plugin - latest
apiVersion: mc.k8s.lex.la/v1alpha1
kind: Plugin
metadata:
name: cosmetic-plugin
spec:
updateStrategy: latest
updateDelay: 168h
instanceSelector:
matchLabels:
type: mixed
Result: Server gets build updates for 1.21.1. Essential plugin stays pinned. Cosmetic plugin updates automatically.
How the Solver Works¶
The constraint solver ensures compatibility between Paper versions and plugin versions.
For Plugin Version Resolution (updateStrategy: latest)¶
- Fetch all available plugin versions from repository
- Filter out versions newer than
now - updateDelay - Sort versions in descending order (newest first)
- For each version:
- Check if compatible with ALL matched servers' Paper versions
- If yes, return this version
- If no, try next version
- If no compatible version found, report error
Example:
- Plugin has versions: 3.0.0 (requires 1.21.x), 2.9.0 (requires 1.20-1.21), 2.8.0 (requires 1.20.x)
- Server A runs Paper 1.21.1
- Server B runs Paper 1.20.4
- Both servers match this plugin's selector
- Solver picks version 2.9.0 (compatible with both servers)
For Paper Version Resolution (updateStrategy: auto)¶
- Fetch all available Paper versions
- Filter out versions newer than
now - updateDelay - Sort versions in descending order (newest first)
- For each Paper version:
- For each matched plugin, check if at least one plugin version is compatible
- If ALL plugins have compatible versions, return this Paper version
- If not, try next Paper version
- If no compatible Paper version found, block updates
Example:
- Paper versions available: 1.21.2, 1.21.1, 1.21.0
- Plugin A: compatible with 1.21.1, 1.21.0 (not yet updated for 1.21.2)
- Plugin B: compatible with 1.21.2, 1.21.1, 1.21.0
- Solver picks Paper 1.21.1 (highest version compatible with both plugins)
- Status shows
availableUpdatewith Paper 1.21.2 but blocked due to Plugin A
Update Delay Behavior¶
The updateDelay field provides a grace period before applying new versions, allowing the community to discover issues.
Field specification:
- Type: Duration (e.g.,
168h,7d,336h) - Optional: Yes (defaults to 0 = no delay)
- Applies to: Both
PaperMCServerandPluginresources - Behavior: When not specified or set to
0, updates apply immediately (subject to maintenance windows)
How it works:
- When a new version is released, the operator records the release time
- The solver excludes versions where
releaseTime + updateDelay > now - After the delay expires, the version becomes eligible for updates
- Updates only apply during maintenance windows
Example timeline:
Day 0: Plugin 3.0.0 released
Day 1: Operator detects new version, records in availableVersions
Day 7: updateDelay expires (if set to 168h)
Day 7+: Next maintenance window applies the update
Best practices:
- Development:
24h- Quick updates for testing - Staging:
168h(7 days) - Standard delay - Production:
336h(14 days) - Conservative delay - Critical production: Use
pinned/build-pinwith manual updates
Initial Deployment Behavior¶
For auto Strategy¶
On initial deployment (no existing server):
- Operator analyzes all matched plugins
- Solver finds the best Paper version compatible with all plugins
- Operator creates StatefulSet with resolved image (e.g.,
lexfrei/papermc:1.21.1-91) - Status is populated with current/desired versions
Important: The :latest Docker tag is NEVER used. Even on first deployment, the operator resolves to a concrete version-build tag.
For latest Strategy¶
- Query Docker Hub for latest available Paper image
- Extract version and build from tag
- Create StatefulSet with that specific tag
- Continue monitoring for newer versions
For pin Strategy¶
- Validate
paperVersionis specified - Find latest build for that version
- Create StatefulSet with
paperVersion-latestBuild - Monitor for new builds of the pinned version
For build-pin Strategy¶
- Validate both
paperVersionandpaperBuildare specified - Verify the version-build combination exists
- Create StatefulSet with exact tag
paperVersion-paperBuild - No further version changes without spec updates
Important Notes¶
Docker Tag Resolution¶
The operator NEVER uses the :latest Docker tag. All strategies resolve to concrete version-build combinations:
lateststrategy →lexfrei/papermc:1.21.1-91(highest available)autostrategy →lexfrei/papermc:1.21.1-91(solver result)pinstrategy →lexfrei/papermc:1.21.1-95(pinned version, latest build)build-pinstrategy →lexfrei/papermc:1.21.1-91(exact specification)
This ensures reproducibility and prevents unexpected changes.
Compatibility Validation¶
The operator validates compatibility using metadata from plugin repositories:
- Plugin versions declare supported Minecraft versions (e.g., "1.20.x", "1.21.x")
- Operator matches Paper version against these ranges
- If metadata is unavailable,
compatibilityOverridecan provide manual constraints
Update Blocking¶
When the solver cannot find a compatible solution:
- Updates are blocked
status.updateBlockedindicates the reason- Status shows which plugin is blocking and why
- Operator waits until constraints can be satisfied
Example blocked status:
status:
updateBlocked:
blocked: true
reason: "No compatible Paper version found for all plugins"
blockedBy:
plugin: "essentialsx"
version: "2.20.1"
supportedPaperVersions: ["1.20.4", "1.21.1"]
Maintenance Windows¶
Updates only occur during configured maintenance windows:
updateSchedule:
checkCron: "0 3 * * *" # Check daily at 3 AM
maintenanceWindow:
enabled: true
cron: "0 4 * * 0" # Apply Sundays at 4 AM
checkCron: When to run the solver and discover new versionsmaintenanceWindow.cron: When to actually apply updates- Allows discovery without immediate application
Graceful Shutdown¶
All updates use graceful shutdown via RCON:
- Operator sends RCON
save-allcommand - Operator sends RCON
stopcommand - Paper saves world, unloads plugins, shuts down cleanly
- Pod terminates
- StatefulSet recreates pod with new image
- Paper starts with updated version/plugins
This prevents world corruption and data loss.
Troubleshooting¶
Update Not Happening¶
Check:
- Is maintenance window enabled? (
maintenanceWindow.enabled: true) - Has the maintenance window cron triggered? (Check current time vs cron schedule)
- Is
updateDelayblocking? (Checkstatus.availableUpdate.foundAt+ delay) - Are updates blocked? (Check
status.updateBlocked)
Incompatible Plugin Version¶
Solution:
- Check
status.pluginsfor compatibility status - Use
compatibilityOverrideif metadata is incorrect - Consider pinning the plugin to a compatible version
- Report missing metadata to plugin maintainer
Unexpected Version¶
Check:
- Verify
updateStrategyis what you expect - Check
status.desiredPaperVersionvsstatus.currentPaperVersion - Review solver logic in
status.availableUpdate - Ensure
updateDelayis configured correctly
Rollback Needed¶
The operator does not perform downgrades by default. To rollback:
# Change to build-pin strategy with old version
kubectl patch papermcserver my-server --type=merge \
-p '{"spec":{"updateStrategy":"build-pin","paperVersion":"1.21.1","paperBuild":91}}'
Rollbacks require manual intervention for safety.
Further Reading¶
- Architecture - Detailed architectural design
- Constraint Solver - How version compatibility is resolved
- PaperMCServer Reference - Full PaperMCServer CRD specification
- Plugin Reference - Full Plugin CRD specification