GCS S3-compatible destination
Five steps to configure a Google Cloud Storage bucket and HMAC key that walwarden writes backups to via the S3-compatible endpoint.
Walwarden supports Google Cloud Storage (GCS) as a backup destination via the S3-compatible endpoint at https://storage.googleapis.com. This page covers creating and configuring the bucket, enabling Bucket Lock, and creating the HMAC key walwarden uses to authenticate.
Walwarden supports the following parameters for this provider:
| Parameter | Description |
|---|---|
endpointUrl | Always https://storage.googleapis.com for GCS S3-compat. |
bucketName | The name of the GCS bucket (for example, my-company-walwarden-backups). |
region | The GCS region (for example, us-east1). Use GCS region names, not AWS region names. |
accessKeyId | The HMAC access key ID (from the GCS HMAC keys page in the Cloud Console). |
secretAccessKey | The corresponding HMAC secret. |
retentionFloorDays | Minimum number of days each backup is retained under Bucket Lock. Must be between 1 and 365. |
Trust boundary note. Walwarden stores the HMAC key for this destination. Unlike the AWS BYO S3 path (which uses short-lived AssumeRole session credentials), HMAC keys are long-lived. Use a minimum-scope service account (see step 4 below) and rotate the HMAC key periodically. Revoke the key immediately if walwarden is ever compromised.
Preflight status. GCS S3-compatible destinations start in unverified state. Run preflight after registration so walwarden can verify the HMAC key, bucket access, object write/read/head behavior, and public-access posture it can observe through the S3-compatible API.
Bucket Lock vs. Object Lock — important semantic difference
GCS Bucket Lock is bucket-wide retention. When you enable Bucket Lock with a 30-day retention period, every object in the bucket is retained for at least 30 days from when it was written — regardless of what walwarden sets at the object level. You cannot set a shorter retention on individual objects.
AWS S3 Object Lock (and MinIO's Object Lock equivalent) is per-object retention. Each object carries its own retention timestamp. Walwarden stamps each backup artifact with its own retention hold.
Both mechanisms prevent deletion before the retention period expires. The practical difference: GCS Bucket Lock applies uniformly to all objects in the bucket; AWS Object Lock can vary per object if needed. For walwarden's use case both are equivalent — walwarden sets the same retention floor on every backup artifact.
Step 1: Create the GCS bucket
- In the GCS Cloud Console, go to Cloud Storage > Buckets and click Create.
- Enter a bucket name. A pattern like
my-company-walwarden-backupsworks. - Choose the region closest to your database. Use a single-region bucket rather than multi-region for predictable latency and cost.
- Under Choose how to control access to objects, select Uniform (not Fine-grained). Bucket Lock requires uniform access control.
- Click Create.
Do not choose a multi-regional or dual-regional bucket unless you have a specific redundancy requirement — the extra replication increases cost without benefit for walwarden's access pattern.
Step 2: Enable Bucket Lock
Bucket Lock must be enabled on the bucket before any objects are written. If you enable it after writing objects, the retention applies only to objects written after the lock is set.
gcloud storage buckets update gs://my-company-walwarden-backups \
--retention-period=30d \
--lock-retention-policyThe --lock-retention-policy flag locks the policy so it cannot be removed and can only have its period extended, never decreased. This is the correct configuration for walwarden.
Verify the lock is in place:
gcloud storage buckets describe gs://my-company-walwarden-backups \
--format="value(retentionPolicy)"The output should show isLocked: true and a retentionPeriod matching your setting.
Step 3: Create a service account with minimum scope
Create a dedicated GCS service account for walwarden. Minimum required GCS roles: storage.objectCreator and storage.objectViewer on the specific bucket.
gcloud iam service-accounts create walwarden-backup-sa \
--display-name="Walwarden backup service account"
gcloud storage buckets add-iam-policy-binding gs://my-company-walwarden-backups \
--member="serviceAccount:walwarden-backup-sa@PROJECT.iam.gserviceaccount.com" \
--role="roles/storage.objectCreator"
gcloud storage buckets add-iam-policy-binding gs://my-company-walwarden-backups \
--member="serviceAccount:walwarden-backup-sa@PROJECT.iam.gserviceaccount.com" \
--role="roles/storage.objectViewer"Do not grant roles/storage.admin, roles/storage.objectAdmin, or any bucket-delete permission. Walwarden does not need those and they amplify blast radius.
Step 4: Create an HMAC key
HMAC keys (not service account JSON keys) are required for GCS S3-compatible access. Create an HMAC key for the service account:
gcloud storage hmac create walwarden-backup-sa@PROJECT.iam.gserviceaccount.comThe command outputs an accessId and a secret. Record both — the secret is shown only once.
Alternatively, in the Cloud Console go to Cloud Storage > Settings > Interoperability and create an HMAC key for your service account.
Step 5: Register the destination in walwarden
- In the walwarden dashboard, go to Destinations > Add destination.
- Select Google Cloud Storage (S3-compatible endpoint) as the provider.
- Fill in:
- Endpoint URL —
https://storage.googleapis.com(exact, no trailing slash). - Bucket name — the bucket name from step 1.
- Region — the GCS region (for example,
us-east1). - Access key ID — the HMAC
accessIdfrom step 4. - Secret access key — the HMAC secret from step 4.
- Endpoint URL —
- Click Save.
The destination will appear in state unverified. Run preflight from the destination detail page before attaching it to scheduled backups.
What walwarden can and cannot verify on GCS S3-compat
What walwarden can verify:
- The HMAC key authenticates successfully.
- Walwarden can write, read, and head an object in the bucket.
- The bucket is not publicly accessible.
What walwarden cannot verify via the S3-compat path:
- Bucket Lock is active. The S3-compat path does not expose GCS Bucket Lock settings. Walwarden cannot assert the retention policy is in place the way it can check S3 Object Lock via
GetObjectLockConfiguration. You must verify Bucket Lock independently (see step 2 above). - Cloud KMS customer-managed encryption keys. GCS's S3-compat API uses GCS-managed encryption regardless of any KMS configuration you have on the bucket. The S3-compat path does not accept AWS-style SSE-KMS headers for Cloud KMS.
Walwarden's audit log will record the endpointUrl and bucketName for every backup event, but the lock-active assertion relies on your bucket configuration rather than a walwarden-run check.
Common footguns
Using a service account JSON key instead of an HMAC key
GCS S3-compat authentication requires HMAC keys, not service account JSON keys. If you paste the access key ID from a JSON key file, authentication will fail.
Bucket Lock not locked
If you set a retention period without --lock-retention-policy, the retention period can be shortened or removed later. Walwarden requires a locked retention policy. Re-run the update command with --lock-retention-policy.
Fine-grained access control instead of uniform
GCS Bucket Lock requires uniform bucket-level access control (IAM, not ACLs). If you created the bucket with Fine-grained access control, you must recreate it — you cannot switch modes on an existing GCS bucket.
Wrong region format
GCS regions use a different naming convention than AWS. Use GCS region names (us-east1, europe-west1) not AWS names (us-east-1, eu-west-1). An incorrect region string will not cause authentication failures but will appear on the destination detail page and in the audit log.
HMAC key for a user account, not a service account
User account HMAC keys are bound to a personal Google account and expire when the person leaves the project. Always create HMAC keys for a dedicated service account.