Amazon S3 is one of the most popular ways to host static websites, single-page applications, and frontend assets. But updating your S3 bucket manually — whether through the AWS Console, the CLI, or a drag-and-drop client — gets old fast. You have to remember which files changed, upload them in the right order, and hope you don't miss anything.

With [DeployHQ](https://www.deployhq.com), you can connect your Git repository directly to an S3 bucket and deploy automatically every time you push. Changed files are detected and uploaded for you — no manual work, no missed files.

This guide covers the full setup for **GitHub, Bitbucket, and GitLab** repositories, plus S3-compatible storage like Cloudflare R2, Wasabi, and DigitalOcean Spaces.

## What you'll need

- A Git repository on [GitHub](https://www.deployhq.com/deploy-from-github), [Bitbucket](https://www.deployhq.com/deploy-from-bitbucket), or [GitLab](https://www.deployhq.com/deploy-from-gitlab)
- An Amazon S3 bucket (or S3-compatible storage)
- Your AWS Access Key ID and Secret Access Key
- A [DeployHQ](https://www.deployhq.com) account (free plan: 1 project, up to 10 deploys/day)

## Step 1: Create a new project in DeployHQ

After signing up, click the **New Project** button at the top of the screen.

![New project](https://blog.deployhq.com/attachment/7e7553d2-4d21-40bb-956e-af7dc19eba57/77qc-Ov-S.png)

Enter a name for your project and select your repository provider — GitHub, Bitbucket, or GitLab. [DeployHQ](https://www.deployhq.com) also supports manual repository configuration if you host code elsewhere.

## Step 2: Connect your repository

Click **Create Project** and you'll be prompted to log in to your repository provider and authorize [DeployHQ](https://www.deployhq.com). After that, you'll see a list of your repositories.

![Repository list](https://blog.deployhq.com/attachment/ed1df0f8-498c-45f6-9438-cacb6fe9a82a/2cv-DNAZ.png)

Select the repository you want to deploy from. [DeployHQ](https://www.deployhq.com) will automatically add an SSH key for access. Keep the **add a webhook** option checked — this enables [automatic deployments](https://www.deployhq.com/blog/automate-website-deployments-from-git-without-downtime-with-deployhq) later.

## Step 3: Configure your S3 bucket

After connecting your repository, you'll be taken to the **New Server** screen. Enter a name, then select **Amazon S3** as the protocol.

![S3 Bucket config](https://blog.deployhq.com/attachment/40ff5f2e-99e4-4d98-b0ee-298c5580784c/0qs-Hiz-M.png)

Fill in the following details:

- **Bucket name** : The name of your S3 bucket (e.g., `my-website-bucket`)
- **Access Key ID** : Your AWS access key
- **Secret Access Key** : Your AWS secret key
- **Region** : The AWS region where your bucket lives (e.g., `us-east-1`)
- **Path prefix** : The directory within the bucket to deploy to (e.g., `public/` or leave blank for the root)

Click **Create Server** to finish.

### IAM permissions for your AWS keys

Your AWS access key needs at minimum these S3 permissions on the target bucket:

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:GetObject",
                "s3:DeleteObject",
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::your-bucket-name",
                "arn:aws:s3:::your-bucket-name/*"
            ]
        }
    ]
}
```

We recommend creating a dedicated IAM user for [DeployHQ](https://www.deployhq.com) rather than using your root account credentials. This limits the blast radius if the keys are ever compromised. For more on protecting sensitive credentials in your deployment workflow, see our guide on [managing environment variables](https://www.deployhq.com/blog/how-to-deploy-php-applications-with-encrypted-environment-variables-using-dotenvx-and-deployhq).

## Step 4: Run your first deployment

Click **Deploy for the first time** in the top right of your project.

![First deployment](https://blog.deployhq.com/attachment/8134f3b3-c6f2-49a4-98c4-e275343e725c/Ty5Hwof.png)

Review the details — the server and branch are auto-selected, and the start revision shows **The very first commit** since nothing has been deployed yet. Click **Deploy** to transfer all files to your S3 bucket.

![First deployment complete](https://blog.deployhq.com/attachment/001bff82-ebf7-448a-8332-e71e534caeee/3kjaut-G.png)

Once complete, you can review the deployment log to see exactly which files were uploaded.

> Ready to skip the manual S3 sync? [Start a free](https://www.deployhq.com/signup)[DeployHQ](https://www.deployhq.com) project and connect your repository in under five minutes.

## Step 5: Enable automatic deployments

Go to the **Automatic Deployments** page in the left sidebar and enable it for your server:

![Auto deployment](https://blog.deployhq.com/attachment/ff7ce3e3-8391-4ffe-88c2-599695aa94c5/5cptv-EZ.png)

Now every `git push` will trigger a deployment automatically. Only changed files are uploaded — [DeployHQ](https://www.deployhq.com) compares the commits and uploads just the diff.

![New deployment](https://blog.deployhq.com/attachment/24b7b093-6408-40df-a67f-e7b0eb882c8a/2Ap0u61.png)

## Deploying from GitHub specifically

The flow above works the same for GitHub, Bitbucket, and GitLab — but GitHub is the most common starting point, so here's what the GitHub-specific path looks like end-to-end.

When you select **GitHub** as the repository host in Step 1, [DeployHQ](https://www.deployhq.com) prompts you to authorize the integration with your GitHub account. After authentication you'll see your repositories, including any organisations you're a member of:

![Selecting a GitHub repository](https://blog.deployhq.com/attachment/cb0ae530-9c2e-471e-934a-6a7784465fe3/UIi-EX0H.png)

Pick the repository you want to deploy. [DeployHQ](https://www.deployhq.com) adds an SSH key to GitHub on your behalf (you can revoke it from your GitHub account settings at any time) and registers a webhook so future pushes trigger deployments automatically.

If you're weighing GitHub against the alternatives for your team, our [GitHub vs GitLab comparison](https://www.deployhq.com/blog/gitlab-vs-github-2025-in-depth-comparison-platform-choice-guide) covers the practical tradeoffs for deployment workflows. From there, every push to your chosen branch triggers [automatic deployments from GitHub](https://www.deployhq.com/features/automatic-deployments) — no manual sync, no missed files.

## Hosting a static website on S3

S3 can serve static websites directly. To enable this:

1. Open your bucket in the AWS S3 console
2. Go to **Properties** → **Static website hosting** and enable it
3. Set the **Index document** (typically `index.html`) and optionally an **Error document** (e.g., `404.html`)
4. Under **Permissions** → **Bucket policy** , add a policy allowing public read access:

```
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": "*",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::my-website-bucket/*"
    }
  ]
}
```

Your site is then accessible at `http://my-website-bucket.s3-website-REGION.amazonaws.com`. For a custom domain with HTTPS, place a CloudFront distribution in front of the bucket.

For a deeper walk-through of building a fully static site with [DeployHQ](https://www.deployhq.com) — including framework-specific patterns — see our guide on [using](https://www.deployhq.com/blog/using-deployhq-to-build-your-static-site)[DeployHQ](https://www.deployhq.com) to build your static site.

## Using S3-compatible storage (Cloudflare R2, Wasabi, DigitalOcean Spaces)

[DeployHQ](https://www.deployhq.com) supports any S3-compatible storage, not just AWS. When configuring your server, select **Amazon S3** as the protocol but enter the custom endpoint for your provider:

| Provider | Endpoint format | Example |
| --- | --- | --- |
| [Cloudflare R2](https://www.deployhq.com/blog/aws-s3-vs-cloudflare-r2-a-deep-dive-for-deployhq-users) | `<account-id>.r2.cloudflarestorage.com` | `abc123.r2.cloudflarestorage.com` |
| Wasabi | `s3.<region>.wasabisys.com` | `s3.us-east-1.wasabisys.com` |
| DigitalOcean Spaces | `<region>.digitaloceanspaces.com` | `nyc3.digitaloceanspaces.com` |
| MinIO | Your MinIO server URL | `minio.example.com:9000` |

Enter the provider's access key and secret, and [DeployHQ](https://www.deployhq.com) handles the rest. The S3 protocol is the same — only the endpoint differs.

## Setting custom request headers

If you're using S3 to host a static website, you may want to set custom headers like `Cache-Control` or `Content-Type` for specific file types. You can configure these in your [DeployHQ](https://www.deployhq.com) server settings under **Custom Headers** — see our walkthrough on [custom Amazon S3 request headers](https://www.deployhq.com/blog/custom-amazon-s3-request-headers) for the full options list.

For example, setting a long cache lifetime for assets:

- `*.css, *.js` → `Cache-Control: public, max-age=31536000`
- `*.html` → `Cache-Control: public, max-age=3600`

## Building assets before deploying to S3

One limitation of S3 is that you can't run server-side commands. If your project uses Sass, TypeScript, or a bundler like Webpack or Vite, you need to compile assets before they're uploaded.

DeployHQ's [build pipelines](https://www.deployhq.com/blog/build-pipelines-in-deployhq-streamline-your-deployment-workflow) feature solves this. You can define build commands that run in an isolated environment before deployment:

![Build commands](https://blog.deployhq.com/attachment/b8bbf52b-d38c-4012-89ab-fbe21d8483e1/M9h-Jujt.png)

Common build commands:

```
npm install
npm run build
```

DeployHQ's build environment comes with Node, Ruby, PHP, and [many more languages](https://www.deployhq.com/support/build-pipelines) pre-installed. After the build completes, only the output files (e.g., the `dist/` directory) are uploaded to S3.

This means you never have to commit compiled assets to Git — your repository stays clean, and your S3 bucket always gets fresh builds.

## Deploying to multiple environments

For projects that need staging and production environments, you can add multiple S3 servers to a single [DeployHQ](https://www.deployhq.com) project — each pointing to a different bucket or path prefix. [Deploy](https://www.deployhq.com) different branches to different environments using DeployHQ's [multi-environment management](https://www.deployhq.com/blog/managing-multiple-environments-with-deployhq-dev-staging-and-production) features.

## Troubleshooting S3 deployments

**Access Denied errors** : Check that your IAM user has the correct permissions on the bucket. The `s3:ListBucket` permission is often forgotten but required for [DeployHQ](https://www.deployhq.com) to detect existing files.

**Wrong region** : If the bucket region doesn't match your configuration, uploads will fail. Double-check in the AWS Console under **Bucket Properties \> AWS Region**.

**Files deploying to the wrong path** : Check the **Path prefix** in your [DeployHQ](https://www.deployhq.com) server settings. Leave it blank to deploy to the bucket root.

For more server connection issues, see our [server troubleshooting guide](https://www.deployhq.com/blog/troubleshooting-server-issues-with-deploy).

* * *

Ready to automate your Git to S3 deployments? [See](https://www.deployhq.com/pricing)[DeployHQ](https://www.deployhq.com) pricing — the free plan covers 1 project and 10 deploys per day, and paid tiers start at $10/month.

If you have questions about deploying to S3 or any other aspect of [DeployHQ](https://www.deployhq.com), drop us an email at [support@deployhq.com](mailto:support@deployhq.com) or find us on [Twitter/X](https://x.com/deployhq).

