Self-Hosting Supabase on AWS Without Using ECR

Jerzy Kopaczewski 01 June 2026 11 min read
Contents
A common question when self-hosting Supabase on AWS: do I actually need Amazon ECR? The short answer is no. Supabase publishes all its container images publicly on Docker Hub, and there are legitimate reasons to skip ECR entirely.

This post covers how to run Supabase on AWS using public container registries, when ECR makes sense, and how to configure ECS Fargate or EC2 to pull from Docker Hub or GitHub Container Registry instead.

If you’re still evaluating whether to self-host at all, start with our guide on why teams choose to self-host Supabase on AWS instead of using Supabase Cloud.

 

Why skip ECR?

Amazon Elastic Container Registry is AWS’s native container image store. It integrates tightly with ECS, has IAM-based access control, and offers vulnerability scanning via Amazon Inspector. It’s the default recommendation in most AWS guides.

But there are valid reasons to avoid it:

  • Complexity for small teams. ECR requires IAM policies, lifecycle policies, and authentication setup. For a team that just wants Supabase running, this is overhead that doesn’t add value when using public images.
  • Cost. ECR charges for storage ($0.10/GB/month) and data transfer. For Supabase’s ~15 images that update frequently, this adds up. Public Docker Hub images cost nothing to pull.
  • You don’t build custom Supabase images. If you’re running the official Supabase images unmodified, there’s no reason to copy them into ECR. You’re adding a middleman between Docker Hub and your compute.
  • CI/CD simplification. Without ECR, your deployment pipeline doesn’t need docker push/pull credentials, ECR login steps, or image tag management. The docker-compose file just references public image tags.

Where Supabase images live

Supabase publishes all official images to Docker Hub under the supabase/ namespace. These are the same images used by supabase start (the CLI) and the official docker-compose.yml in the Supabase repository.

The key images you need for a self-hosted deployment:

ImageServiceDocker Hub
supabase/postgresPostgreSQL with extensions10M+ pulls
supabase/gotrueAuthentication (GoTrue)Public
supabase/realtimeRealtime subscriptionsPublic
supabase/storage-apiObject storage APIPublic
supabase/postgrestREST API (PostgREST)Public
supabase/studioDashboard UIPublic
supabase/edge-runtimeEdge Functions (Deno)Public
kongAPI GatewayPublic (official Kong image)

All of these can be pulled directly by ECS Fargate, EC2, or any Docker host without any registry authentication.

Option 1: Docker Compose on EC2 (simplest)

The most straightforward approach. Clone the official Supabase Docker setup and run it on an EC2 instance. No ECR needed at all.

# SSH into your EC2 instance
git clone --depth 1 https://github.com/supabase/supabase
cd supabase/docker
cp .env.example .env

# Edit .env with your secrets (JWT secret, anon key, service role key, etc.)
# NEVER use the example values in production

docker compose up -d

All images pull from Docker Hub automatically. No registry configuration needed.

Pros:

  • Zero registry setup
  • Matches local development experience exactly
  • Easy to update (docker compose pull && docker compose up -d)

Cons:

  • Single EC2 instance (no high availability without additional work)
  • You manage OS patching, Docker updates, and backups yourself
  • No built-in auto-scaling

When to use: Proof of concept, development environments, or small production workloads where simplicity outweighs resilience requirements.

Option 2: ECS Fargate with public Docker Hub images

ECS Fargate can pull directly from Docker Hub without any ECR involvement. You simply reference the public image in your task definition.

{
  "containerDefinitions": [
    {
      "name": "supabase-postgrest",
      "image": "supabase/postgrest:latest",
      "essential": true,
      "portMappings": [
        {
          "containerPort": 3000,
          "protocol": "tcp"
        }
      ],
      "environment": [
        {
          "name": "PGRST_DB_URI",
          "value": "postgres://authenticator:password@db:5432/postgres"
        },
        {
          "name": "PGRST_DB_SCHEMAS",
          "value": "public,storage,graphql_public"
        }
      ]
    }
  ]
}

The image field points directly to Docker Hub. ECS pulls it without authentication since it’s a public image.

Important considerations:

  • Pin your image tags. Don’t use :latest in production. Use specific version tags like supabase/postgrest:v12.2.3 so deployments are reproducible and you control when upgrades happen.
  • Docker Hub rate limits. Anonymous pulls from Docker Hub are limited to 100 pulls per 6 hours per IP. For ECS Fargate (which uses shared NAT IPs), you can hit this if you’re scaling many tasks. Solutions: use a Docker Hub authenticated pull (free tier gives 200 pulls/6h), or mirror to ECR if you hit limits at scale.
  • No vulnerability scanning. Without ECR, you don’t get Amazon Inspector scanning on your container images. You’d need to run a separate scanning tool in your CI pipeline.

Terraform example for ECS with Docker Hub images

resource "aws_ecs_task_definition" "supabase_postgrest" {
  family                   = "supabase-postgrest"
  requires_compatibilities = ["FARGATE"]
  network_mode             = "awsvpc"
  cpu                      = "256"
  memory                   = "512"

  container_definitions = jsonencode([
    {
      name      = "postgrest"
      image     = "supabase/postgrest:v12.2.3"
      essential = true
      portMappings = [
        {
          containerPort = 3000
          protocol      = "tcp"
        }
      ]
      environment = [
        {
          name  = "PGRST_DB_SCHEMAS"
          value = "public,storage,graphql_public"
        }
      ]
      secrets = [
        {
          name      = "PGRST_DB_URI"
          valueFrom = aws_secretsmanager_secret.db_uri.arn
        }
      ]
      logConfiguration = {
        logDriver = "awslogs"
        options = {
          "awslogs-group"         = "/ecs/supabase-postgrest"
          "awslogs-region"        = "eu-west-2"
          "awslogs-stream-prefix" = "ecs"
        }
      }
    }
  ])

  execution_role_arn = aws_iam_role.ecs_execution.arn
  task_role_arn      = aws_iam_role.ecs_task.arn
}

Note: secrets are pulled from AWS Secrets Manager (not environment variables), which is best practice regardless of which registry you use.

Option 3: GitHub Container Registry (GHCR)

If you fork or customise Supabase images, GitHub Container Registry (ghcr.io) is a good alternative to ECR. It integrates naturally with GitHub Actions, supports public and private images, and has no pull rate limits for public images.

# Your customised Supabase image
FROM supabase/postgrest:v12.2.3

# Add custom configuration
COPY custom-postgrest.conf /etc/postgrest.conf

Push to GHCR from your GitHub Actions workflow:

- name: Push to GHCR
  run: |
    echo "$" | docker login ghcr.io -u $ --password-stdin
    docker push ghcr.io/$/supabase-postgrest:$

Then reference ghcr.io/your-org/supabase-postgrest:sha in your ECS task definition. For public GHCR images, no authentication is needed on the ECS side.

When you actually need ECR

ECR makes sense when:

  • You build custom images that include proprietary code or configuration you don’t want public.
  • You need Inspector scanning for vulnerability detection as part of your compliance requirements (SOC 2, Cyber Essentials Plus, HIPAA).
  • You’re hitting Docker Hub rate limits at scale (dozens of ECS tasks pulling images frequently).
  • You want pull-through cache. ECR can act as a caching proxy for Docker Hub, giving you the speed of a local registry with the convenience of public images. You get the image locally without managing the push yourself.
  • Cross-region redundancy. ECR replication rules can mirror images across regions for disaster recovery.

If any of these apply, ECR is the right choice. But for a straightforward Supabase self-hosting deployment using official public images, it’s an unnecessary layer.

Comparison: ECR vs Docker Hub vs GHCR for Supabase

FactorDocker Hub (public)GHCRAWS ECR
CostFree for pullsFree for public images$0.10/GB storage + transfer
Auth required for ECSNo (public images)No (public images)No (same AWS account)
Rate limits100 pulls/6h (anon)Unlimited (public)Unlimited
Vulnerability scanningDocker Scout (paid)GitHub security alertsAmazon Inspector (included)
CI/CD integrationAny pipelineGitHub Actions nativeAWS CodePipeline / any with IAM
Best forUsing official images as-isCustom forks, GitHub-based teamsEnterprise, compliance, scale

Handling updates without ECR

When Supabase releases a new version, you need to update the image tags in your deployment:

Docker Compose (EC2):

cd supabase/docker
git pull  # Gets updated docker-compose.yml with new tags
docker compose pull
docker compose up -d

ECS Fargate (Terraform): Update the image tag in your Terraform variable and deploy:

variable "supabase_postgrest_version" {
  default = "v12.2.3"  # Bump this to upgrade
}

Then terraform apply triggers a new ECS deployment with the updated image.

Tip: Pin to specific version tags and treat updates as deliberate deployments. Don’t use :latest in production as it makes rollbacks impossible and can introduce breaking changes silently.

Security considerations without ECR

Without ECR’s built-in scanning, you need alternative approaches to container security:

  • Trivy (open-source, runs in CI): Scan images before deployment. Add a step in your GitHub Actions or CI pipeline that runs trivy image supabase/postgrest:v12.2.3 and fails the build on critical CVEs.
  • Docker Scout (Docker Hub native): Available for Docker Hub images, provides vulnerability insights directly in the registry.
  • Pin and audit: Since you’re using official Supabase images, the Supabase team handles patching. Your responsibility is to stay on recent versions and update promptly when security advisories are published.

For regulated environments (fintech, healthcare) where you need to demonstrate a vulnerability scanning process to auditors, ECR + Inspector is the path of least resistance. See our security and compliance services for how we handle this for clients in regulated sectors.

Summary

You don’t need ECR to self-host Supabase on AWS. The official images are public on Docker Hub and can be pulled directly by ECS Fargate or EC2 without any registry setup. This simplifies your deployment, removes an infrastructure component to manage, and saves cost.

Use ECR when you need vulnerability scanning for compliance, you’re building custom images, or you’re operating at a scale where Docker Hub rate limits become a problem.

For most teams getting started with self-hosted Supabase on AWS, Docker Hub direct pulls are the right starting point. You can always add ECR later when the need arises.

Related guides:

Need help setting up self-hosted Supabase on your AWS infrastructure? Our cloud migration services cover the full setup from IaC to CI/CD.

Supabase AWS Docker self-hosting ECR

Read also:

Previous post