One S3 bucket per webQsee team
The cleaner alternative for stricter isolation: each webQsee team owns its own S3 bucket, its own IAM policies and its own users. More buckets to manage, harder, simpler boundaries.
Estimated time: 30–45 min · Last reviewed: 2026-05 · Difficulty: Intermediate
Before you start
- webQsee installed in Chrome or Edge, get it here
- Each team has an active Professional or Team plan, see pricing
- At least two webQsee teams set up, if not, see Create and manage multiple webQsee teams
- AWS account with IAM and S3 administrator rights
- Familiarity with the multi-user S3 setup
Why per-team buckets?
- Bucket-level boundary, the strongest isolation S3 offers; impossible to accidentally read across teams via a typo in a path
- Per-team lifecycle / retention, one team can keep recordings 90 days, another forever
- Per-team billing using AWS cost allocation tags on the bucket
- Easy hand-off, transfer a single bucket to a team's own AWS account if they spin out
Trade-off: more S3 buckets and IAM resources to manage. If you only have two or three teams that's no problem. For ten or more teams consider prefix-based isolation in one bucket.
Naming convention
Pick a stable prefix you can extend per team:
- Buckets:
webqsee-team-a,webqsee-team-b, … - Policies:
webqsee-team-a-admin,webqsee-team-a-user, … - Groups:
webqsee-team-a-admin,webqsee-team-a-user, … - Users:
<person>-team-a(if a person is in multiple teams they get one IAM user per team)
The walkthrough below is for "team A"; repeat the whole pattern for each additional team.
1. Create the team-A bucket
Open S3 → Create bucket
Pick a region (
eu-central-1, etc.).Sanity check: You're on the Create bucket form with your chosen region in the top-right.Configure the bucket
Name:
webqsee-team-a. Block all public access: ON. Versioning: Disabled. Encryption: SSE-S3. ACLs: disabled. Optionally add an AWS cost-allocation tagwebqsee-team=team-afor per-team billing reports.Sanity check: Review summary confirms: public access blocked, versioning disabled, SSE-S3 encryption on, optional tag visible.Click Create bucket
Sanity check: Green toast "Successfully created bucket 'webqsee-team-a'". The bucket appears in the list with the right region.Apply CORS to this bucket
Bucket → Permissions → CORS → Edit:
[ { "AllowedOrigins": [ "https://view.webqsee.com", "https://app.webqsee.com", "chrome-extension://*" ], "AllowedMethods": ["GET", "PUT", "POST", "DELETE", "HEAD"], "AllowedHeaders": ["*"], "ExposeHeaders": ["ETag", "x-amz-request-id", "x-amz-version-id"], "MaxAgeSeconds": 3000 } ]Save changes.
Sanity check: Toast "Successfully edited CORS". CORS must be applied to every team bucket individually, unlike the shared-bucket pattern.
2. Create the team-A policies
Create policy
webqsee-team-a-adminIAM → Policies → Create policy → JSON. Paste:
{ "Version": "2012-10-17", "Statement": [ { "Sid": "AdminListBucket", "Effect": "Allow", "Action": [ "s3:ListBucket", "s3:GetBucketLocation", "s3:GetBucketCors" ], "Resource": "arn:aws:s3:::webqsee-team-a", "Condition": { "StringLike": { "s3:prefix": [ "shared/*", "shared/", "protected/*", "protected/", "private/*", "private/", "" ] } } }, { "Sid": "AdminFullObjects", "Effect": "Allow", "Action": [ "s3:GetObject", "s3:GetObjectTagging", "s3:PutObject", "s3:PutObjectTagging", "s3:DeleteObject", "s3:AbortMultipartUpload", "s3:ListMultipartUploadParts" ], "Resource": [ "arn:aws:s3:::webqsee-team-a/shared/*", "arn:aws:s3:::webqsee-team-a/protected/*", "arn:aws:s3:::webqsee-team-a/private/*" ] } ] }Save as
webqsee-team-a-admin.Sanity check: The policy is in the Customer managed list. Note the ARNs targetwebqsee-team-a, not a generic shared bucket.Create policy
webqsee-team-a-userThe per-user policy with the
aws:PrincipalTag/webqsee-user-idcondition. Paste:{ "Version": "2012-10-17", "Statement": [ { "Sid": "UserListBucketScoped", "Effect": "Allow", "Action": [ "s3:ListBucket", "s3:GetBucketLocation", "s3:GetBucketCors" ], "Resource": "arn:aws:s3:::webqsee-team-a", "Condition": { "StringLike": { "s3:prefix": [ "shared/*", "shared/", "protected/*", "protected/", "private/${aws:PrincipalTag/webqsee-user-id}/*", "private/${aws:PrincipalTag/webqsee-user-id}/", "" ] } } }, { "Sid": "UserSharedRW", "Effect": "Allow", "Action": [ "s3:GetObject", "s3:GetObjectTagging", "s3:PutObject", "s3:PutObjectTagging", "s3:DeleteObject", "s3:AbortMultipartUpload", "s3:ListMultipartUploadParts" ], "Resource": "arn:aws:s3:::webqsee-team-a/shared/*" }, { "Sid": "UserPrivateRW", "Effect": "Allow", "Action": [ "s3:GetObject", "s3:GetObjectTagging", "s3:PutObject", "s3:PutObjectTagging", "s3:DeleteObject", "s3:AbortMultipartUpload", "s3:ListMultipartUploadParts" ], "Resource": "arn:aws:s3:::webqsee-team-a/private/${aws:PrincipalTag/webqsee-user-id}/*" }, { "Sid": "UserProtectedReadOnly", "Effect": "Allow", "Action": ["s3:GetObject", "s3:GetObjectTagging"], "Resource": "arn:aws:s3:::webqsee-team-a/protected/*" } ] }Save as
webqsee-team-a-user.Sanity check: Both team-A policies are in the Customer managed list. Each ARN starts witharn:aws:s3:::webqsee-team-a, no other team's bucket name appears.
3. Create team-A groups and users
Create two groups
IAM → User groups → Create group, twice:
webqsee-team-a-admin, attach the admin policywebqsee-team-a-user, attach the user policy
Sanity check: Both groups appear in User groups with 1 attached policy each.Collect team-A webQsee user IDs
In webQsee, use the team-switcher to make team A the active team. Open Settings → Current User and Team. Note each member's User ID.
Sanity check: You have the full (name, webQsee user ID) list for team A.Create one IAM user per team-A member
IAM → Users → Create user. For each:
- Username:
<first-name>-team-a - Programmatic only (no console access)
- Group:
webqsee-team-a-user(or-admin) - Tag: key
webqsee-user-id, value = their webQsee user ID in team A (exact case) - Generate one access key, save the Access Key ID + Secret immediately
Important: If a person is also in team B, they need a separate IAM user
<first-name>-team-b. Don't reuse one IAM user across teams, the IAM tag can only have one value.Sanity check: IAM → Users shows one IAM user per team-A member, all Active, all in the right group, all carrying the matching tag. Access keys are in your password manager.- Username:
4. Configure webQsee team A
Switch to team A in webQsee
Use the team-switcher in the toolbar. The Cloud Gallery settings below apply only to the currently active team.
Sanity check: Top of the main window shows "Team: Team A".Team-wide settings
Gallery → Cloud Gallery → Edit Settings:
- Storage Type:
S3 compatible storage, KEY-Auth - Authentication mode:
Per-user credentials (multi-user) - Bucket name:
webqsee-team-a - Connection settings:
No{ "region": "eu-central-1" }prefixfield is needed because the bucket itself already isolates the team.
Save team settings.
Sanity check: Toast "Team cloud settings saved" appears.- Storage Type:
Each team-A member enters their personal credentials
Personal section: paste own Access Key ID and Secret. Save.
Sanity check: Every team-A member sees "Cloud Storage connected ✓" in their webQsee.
5. Repeat for team B (and so on)
Repeat steps 1–4 for each additional team
For team B: create bucket
webqsee-team-b, apply CORS, createwebqsee-team-b-admin/webqsee-team-b-userpolicies (ARNs targetingwebqsee-team-b), groups, per-member IAM users with theirwebqsee-user-idtag, distribute keys, configure webQsee. The settings are exactly the same shape; only the bucket name and policy/group names differ.Sanity check: S3 bucket list showswebqsee-team-a,webqsee-team-b, etc. IAM Policies list shows admin/user pairs for each team. Each team's members see "Cloud Storage connected ✓" when their team is active.
Final sanity check, hard isolation
Open the AWS CLI with a team-A IAM access key:
aws s3 ls s3://webqsee-team-a/ # should list shared/ protected/ private/ ...
aws s3 ls s3://webqsee-team-b/ # should return AccessDeniedIf team-A credentials can read team B, an IAM policy mistakenly references the wrong bucket name, re-check step 2. In webQsee itself: switching from team A to team B should switch the Cloud Gallery's entire content; you'll never see a team-A item while team B is active.
Troubleshooting
- "NoSuchBucket": the bucket name in webQsee's team-wide settings doesn't match an actual bucket. Make sure you've selected the right team in webQsee before editing settings.
- 403 on every operation: the policy ARNs are still pointing at a different bucket (e.g. you copy-pasted the team-A policy when creating team B and forgot to swap
webqsee-team-a→webqsee-team-b). Edit the customer-managed policy. - 403 on PUT to private/: the IAM user's
webqsee-user-idtag is missing or doesn't match. Re-check step 3 step 3. - CORS error after creating a new bucket: CORS is per-bucket. You must apply step 1 step 4 to every new team bucket.
- One human in two teams cannot upload to team B: they probably tried to reuse their team-A access key. Each team needs its own IAM user (separate access key) because the IAM tag is per-user. Generate a second key under
<name>-team-b. - "Bucket name already exists": S3 bucket names are globally unique across all AWS customers. Add a discriminator:
webqsee-team-a-acme.
Related tutorials
One bucket, many teams
The lighter alternative using prefix-based isolation in a single bucket.
Open tutorialCreate multiple webQsee teams
Spin up several teams under one organisation and administrate them centrally.
Open tutorialStop guessing. Start webQseeing.
Add webQsee to Chrome or Edge in one click. Most features are free, forever, no signup needed. Upgrade only if your team needs cloud sharing, S3 storage and Pro-grade tooling.
Works in Chrome 103+, Edge 103+ and most Chromium-based browsers. Install instructions.