The 2026 ransomware playbook does not start with encrypting /home. It starts with stealing the JetBackup destination credentials out of /usr/local/jetapi/data/, deleting every offsite snapshot, and then encrypting the live data. By the time the operator notices, the backups are gone and the only restore source is whatever the attacker hasn't touched yet.
Object Lock is the answer. It tells the S3-compatible storage provider to physically refuse deletion or overwrite of an object until a retention timer expires — even from the root account, in Compliance mode. JetBackup 5 can write to a locked bucket, but the destination configuration and retention math are non-obvious. Get them wrong and the daily prune job fails forever; get them right and an attacker with full root on the cPanel box still cannot touch yesterday's backup.
How Object Lock interacts with JetBackup prune
JetBackup 5 manages its own retention. Every job run, after a successful upload, it lists the destination, identifies snapshots older than the retention window, and issues DeleteObject calls against them. That is the cycle that Object Lock blocks.
The conflict is fixable, not fundamental. Two rules:
- Lock period must exceed retention period plus slack. If JetBackup retains 30 days and locks for 30 days, the prune job races the lock expiry — half the time the object is still locked when JetBackup tries to delete it, the API returns
AccessDenied, and the job logs a failure even though the backup itself succeeded. - Storage cost is bounded by lock period, not retention. A locked object survives JetBackup's delete call and stays billable until the lock expires naturally. Plan storage capacity against the lock window, not the retention window.
The right pattern is retention < lock < retention + 7 days. JetBackup tries to delete on day 30, fails silently (or noisily, depending on settings), and the object self-deletes on day 37 when the lock expires. The S3 lifecycle isn't involved unless you add a lifecycle policy explicitly — see below.
Set up the bucket
The bucket-level config is the same shape across providers; the console paths differ.
AWS S3
In the S3 console, Create bucket. Object Lock must be enabled at creation time — there is no way to enable it on an existing bucket. Tick Enable Object Lock, acknowledge the warning, create.
Then Properties → Object Lock → Edit default retention:
- Default retention: Enabled
- Mode: Compliance
- Default retention period: 37 days (matches a 30-day JetBackup retention with 7-day slack)
Bucket versioning is enabled automatically with Object Lock — that is required, leave it on. Add a lifecycle rule under Management → Lifecycle rules to permanently delete noncurrent versions after 1 day, otherwise versioning will accumulate every overwrite forever. Object Lock applies to current versions, so the lifecycle rule only cleans up superseded delete-markers and is safe.
Wasabi
Wasabi exposes Object Lock under Compliance Settings when creating a bucket. Same constraints — must be enabled at creation, cannot be added later. Set the Minimum Retention Time to 37 days; pick Conditional Hold (Wasabi's equivalent of Compliance mode).
Note Wasabi's 90-day minimum storage billing applies on top of Object Lock. A 37-day lock period still bills for 90 days minimum per object. If you are using Wasabi for immutable backups, set the lock period to 97 days and retention to 90 — you are paying for 90 days anyway, get the protection too.
Backblaze B2
B2 calls this File Lock. Create a Bucket → File Lock: Enable. Then Lifecycle Settings → Configure and set Default retention mode to Compliance with a 37-day duration.
B2 has no minimum storage period, so the bucket cost matches retention exactly. This is the cheapest immutable option for typical cPanel backup volumes.
IAM policy for the JetBackup sub-user
The destination credentials JetBackup uses must be able to PutObject and GetObject but must not be able to disable Object Lock or change the bucket's lock configuration. If the attacker grabs the JetBackup credentials, you want them to find a key that cannot weaken the bucket.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:DeleteObject",
"s3:ListBucket",
"s3:GetBucketLocation"
],
"Resource": [
"arn:aws:s3:::acme-cpanel-immutable",
"arn:aws:s3:::acme-cpanel-immutable/*"
]
},
{
"Effect": "Deny",
"Action": [
"s3:PutObjectRetention",
"s3:PutObjectLegalHold",
"s3:BypassGovernanceRetention",
"s3:PutBucketObjectLockConfiguration"
],
"Resource": "*"
}
]
}
The DeleteObject allow is intentional — JetBackup needs it to attempt prune even though Compliance mode will block actual deletion. Without it the daily job logs an authorisation failure on every retention pass.
Configure the JetBackup destination
In WHM open JetBackup 5 → Destinations → Create Destination → Amazon S3 (compatible). The fields match a normal S3 destination — see Configure JetBackup 5 destinations on cPanel for endpoint and region detail per provider. Two settings matter specifically for Object Lock:
- Path-style addressing: enabled. Some providers' Object Lock endpoints reject virtual-hosted style.
- Multipart threshold: 100 MB or higher. Each part of a multipart upload is locked individually; with a 5 MB threshold a 2 GB backup creates 400 locked parts, which inflates the bucket's ListObjectVersions response and slows down JetBackup's own prune scan.
Click Test Connection. JetBackup writes a test object, reads it back, and tries to delete it. With Compliance mode active the delete will fail — and that is the point. JetBackup 5.3+ treats this as success for the connection test, but if you see a red error containing AccessDenied: object is locked, the test is functionally passing. The destination is usable.
Attach to a backup job and verify
Attach the destination under Backup Jobs → [your job] → Destinations. Set the job's retention to 30 days (or your chosen window), keeping it strictly less than the bucket's lock period.
After the first job run, verify immutability with the AWS CLI:
aws --endpoint-url https://s3.us-east-1.amazonaws.com s3api list-object-versions \
--bucket acme-cpanel-immutable --max-items 1
Pick an object key from the output and try to delete it as the root account:
aws s3api delete-object --bucket acme-cpanel-immutable --key <key>
# Expected: An error occurred (AccessDenied) when calling the DeleteObject operation:
# Object is locked due to compliance.
If that command succeeds, Object Lock is not active — recheck the bucket's default retention setting.
Can ransomware delete JetBackup backups protected by Object Lock?+
Why does JetBackup's daily prune job report errors after enabling Object Lock?+
Does Object Lock work with all S3-compatible providers?+
How much does immutable backup storage cost?+
Can I restore from a locked bucket?+
What happens if I need to delete a backup early for GDPR or legal reasons?+
Next steps
- Activate JetBackup with JetBackup licensing.
- Set up the underlying destination first — see Configure JetBackup 5 destinations on cPanel.
- For Wasabi-specific endpoint and retention math, read Add Wasabi as a JetBackup 5 destination.
- Compare backup approaches in R1Soft vs JetBackup before standardising your fleet.