BYO AWS S3 destination
Six steps to create and configure the S3 bucket and IAM role that walwarden writes backups to.
Walwarden writes backups to an S3 bucket you own. This page covers creating and configuring that bucket and the IAM role walwarden uses to access it.
Walwarden's AWS account ID is 194343789105. The IAM role trust policy you create in step 4 must list this account as the trusted principal.
Step 1: Create the S3 bucket
- In the AWS console, go to S3 and click Create bucket.
- Choose a name. The name must be globally unique. A pattern like
my-company-walwarden-backupsworks. - Choose the region closest to your database. Keep a note of the region — you will enter it in walwarden later.
- Leave all defaults in place. Do not enable public access. Do not enable static website hosting.
- Click Create bucket.
Step 2: Configure the bucket
These settings must all be applied after creation.
Enable Object Lock (GOVERNANCE mode)
Object Lock prevents walwarden from deleting your backups, even if walwarden's account is compromised. Use GOVERNANCE mode, not COMPLIANCE. COMPLIANCE prevents even the root account from deleting objects before the retention period, which creates an operational risk if you need to recover storage. GOVERNANCE mode is enforced unless a user with specific IAM permissions overrides it.
- On the bucket detail page, click Properties.
- Scroll to Object Lock and click Edit.
- Enable Object Lock.
- Set the default retention mode to Governance.
- Set the default retention period. A 30-day minimum is recommended.
Object Lock requires versioning. AWS enables versioning automatically when you enable Object Lock.
Block all public access
On the Permissions tab:
- Click Block public access (bucket settings).
- Enable all four checkboxes.
- Click Save.
Enforce TLS-only access (bucket policy)
Attach the following bucket policy to reject any unencrypted requests. Replace BUCKET-NAME with your bucket name.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyNonTLS",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::BUCKET-NAME",
"arn:aws:s3:::BUCKET-NAME/*"
],
"Condition": {
"Bool": {
"aws:SecureTransport": "false"
}
}
}
]
}
Default encryption
- On the Properties tab, scroll to Default encryption.
- Select SSE-S3 (AES-256, AWS-managed keys). This is the minimum.
- If your compliance requirements require customer-managed keys, select SSE-KMS and specify your KMS key ARN.
Step 3: Create the IAM policy
Create an IAM policy that grants walwarden the permissions it needs to write and read backup artifacts. This policy will be attached to the IAM role in step 4.
In the AWS console, go to IAM > Policies > Create policy. Use the JSON editor and paste the policy below. Replace BUCKET-NAME with your bucket name.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "WalwardenBackupRW",
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:HeadObject",
"s3:DeleteObject",
"s3:ListBucket",
"s3:GetBucketLocation",
"s3:GetBucketVersioning",
"s3:PutObjectRetention",
"s3:PutObjectLegalHold",
"s3:GetObjectRetention",
"s3:GetObjectLegalHold",
"s3:GetObjectVersion",
"s3:ListBucketVersions"
],
"Resource": [
"arn:aws:s3:::BUCKET-NAME",
"arn:aws:s3:::BUCKET-NAME/*"
]
}
]
}
The PutObjectRetention and PutObjectLegalHold actions are required for Object Lock. Omitting them is the most common cause of preflight failure after the initial setup.
Name the policy something identifiable, for example walwarden-backup-policy.
Step 4: Create the IAM role and trust policy
- In IAM > Roles, click Create role.
- Select Another AWS account as the trusted entity type.
- Enter
194343789105as the Account ID. - Check Require external ID and paste the external ID that walwarden generated for your destination. You can find this on the destination setup page in the walwarden dashboard. Do not use a placeholder. Using a placeholder external ID is a security misconfiguration and will be rejected by preflight.
- Attach the policy you created in step 3.
- Name the role, for example
walwarden-backup-role. - Click Create role and copy the Role ARN (format:
arn:aws:iam::ACCOUNT-ID:role/walwarden-backup-role).
The trust policy walwarden requires looks like this (AWS populates this automatically when you use the console flow above):
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::194343789105:root"
},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"sts:ExternalId": "YOUR-WALWARDEN-EXTERNAL-ID"
}
}
}
]
}
Replace YOUR-WALWARDEN-EXTERNAL-ID with the exact value from the walwarden dashboard destination page. The value is case-sensitive.
Step 5: Register the destination in walwarden
- In the walwarden dashboard, go to Destinations > Add destination.
- Fill in:
- Bucket name — the bucket name (not the ARN)
- Region — the AWS region (for example,
us-east-1) - Role ARN — the ARN of the role you created in step 4
- External ID — the same external ID you used in the trust policy
- Click Save.
Step 6: Wait for preflight verification
Walwarden runs preflight immediately after you save the destination. Preflight attempts every required operation against the bucket: write a test object, read it back, verify metadata, verify Object Lock is active. All checks must pass before backups can run.
Preflight typically completes within 30 seconds. If it fails, see Preflight verification for per-check guidance.
Common footguns
Forgot PutObjectRetention in the IAM policy
Preflight fails with: User is not authorized to perform: s3:PutObjectRetention. Re-attach the policy from step 3 and confirm the action is listed.
Used the placeholder external ID
If you pasted a placeholder value (such as your-external-id-here) into the IAM trust policy instead of the walwarden-issued value, preflight fails with an Access denied error on sts:AssumeRole. Delete the role and re-create it with the correct external ID from the walwarden dashboard.
Object Lock set to COMPLIANCE instead of GOVERNANCE
COMPLIANCE mode locks objects even against root-account deletion. This is not required by walwarden and creates operational risk. If you created the bucket with COMPLIANCE mode, you cannot change it; create a new bucket with GOVERNANCE mode.
Public access not fully blocked
Preflight checks that the bucket has all four public-access-block settings enabled. Partial blocking is rejected.