Skip to main content

How to Make Zenko CloudServer Buckets Public (The Host CLI Method)

If you are self-hosting Zenko CloudServer (S3-compatible storage) using Docker, you will likely encounter an AccessDenied XML error when trying to view your files in a browser. This is because S3 buckets are private by default.

While you can try to configure this inside the container, I have learnt that the most efficient method is to run the AWS CLI directly from your VPS host, pointing it at the container's exposed port.

The Problem

You upload a file (e.g., via S3Drive or a script), but when you visit the URL, you see this error:

<Error>
<Code>AccessDenied</Code>
<Message>Access Denied</Message>
...
</Error>

The Solution: Host-Based AWS CLI

Instead of installing tools inside the Docker container (which is temporary and messy), we will use the AWS CLI installed on the host server to push a "Public Read" policy to the specific bucket.

Prerequisites

  • Root access to your VPS.
  • Zenko CloudServer running in Docker.
  • aws-cli installed on the host system (apt install awscli or apk add aws-cli).

Step 1: Find Your Container's Port

First, identify which port your Zenko container is currently listening on. It might be a static port (like 8000) or a random dynamic port if you didn't pin it.

Run this command:

docker ps | grep zenko

Look for the port mapping: 0.0.0.0:59573->8000/tcp. In this example, the host port is 59573. We will use this to talk to the container.

Step 2: Disable "Block Public Access"

Before applying a policy, we must ensure Zenko isn't globally blocking public ACLs. Replace YOUR-BUCKET-NAME and the port 59573 with your actual values.

aws s3api put-public-access-block \
    --bucket YOUR-BUCKET-NAME \
    --public-access-block-configuration "BlockPublicAcls=false,IgnorePublicAcls=false,BlockPublicPolicy=false,RestrictPublicBuckets=false" \
    --endpoint-url http://localhost:59573

Step 3: Create the Public Policy

Create a temporary file named public.json on your server. This policy allows s3:GetObject (download/read) for anyone (*).

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "PublicRead",
      "Effect": "Allow",
      "Principal": "*",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::YOUR-BUCKET-NAME/*"
    }
  ]
}

Note: Ensure Resource matches your bucket name exactly, ending with /*.

Step 4: Apply the Policy

Push the policy file to your Zenko instance.

aws s3api put-bucket-policy \
    --bucket YOUR-BUCKET-NAME \
    --policy file://public.json \
    --endpoint-url http://localhost:59573

Verification

Your files should now be public! Test it by accessing a file URL in your browser. If you use a reverse proxy (like Nginx), the URL will look like: http://s3.yourdomain.com/YOUR-BUCKET-NAME/image.png


Important Note: The "Random Port" Trap

If you saw a random high number port (like 59573) in Step 1, be aware that this might change if you restart the container.

To prevent your configuration scripts (or reverse proxy) from breaking in the future, it is highly recommended to "pin" the port in your docker-compose.yml or docker run command:

ports:
  - "8000:8000"

This ensures the service always listens on port 8000, making maintenance much easier.