Skip to content

Install Shield360 Enterprise from the image

Shield360 Enterprise customers who run Shield360 inside their own network install it from a private image registry. Shield360 gives you two things:

  • Registry access: either an AWS access key pair that can only pull Shield360’s images, or pull access for your own AWS account.
  • A licence: a single line starting S360L1. that sets your seats, end date and modules. See Self-hosted licence.

The licence is checked offline. Shield360 never calls home, so both images also work with no internet access once they are pulled.

Every release has two images, built from the same platform build:

ImageRunsBest for
shield360-selfhosted:<version>-allinoneShield360, PostgreSQL and ClickHouse in one containerPilots, evaluations and small teams on one host
shield360-selfhosted:<version>The Shield360 platform only. PostgreSQL and ClickHouse run separately: as containers from the bundled compose file, or your own serversProduction, larger teams, and teams that run their own databases

The registry is 959429674945.dkr.ecr.us-east-2.amazonaws.com.

Tags:

  • 2.1.0 and 2.1.0-allinone never change.
  • 2.1 and 2.1-allinone follow the newest patch release of that line.
  • stable and stable-allinone follow the newest release.

Pin an exact version in production.

Architectures: every tag is a multi-arch image for linux/amd64 (x86-64) and linux/arm64 (for example AWS Graviton, Ampere, or Apple silicon running Docker). docker pull picks the one that matches the host. Each architecture is built natively from the same commit, so both behave the same. To pull a specific one, for example to save it for another host, add --platform linux/arm64 or --platform linux/amd64.

What the host needs: Docker Engine 24 or later, 4 CPU cores, 8 GB of memory and 40 GB of free disk.

Terminal window
export AWS_ACCESS_KEY_ID=… # from Shield360
export AWS_SECRET_ACCESS_KEY=…
aws ecr get-login-password --region us-east-2 \
| docker login --username AWS --password-stdin 959429674945.dkr.ecr.us-east-2.amazonaws.com

A Docker login to ECR lasts 12 hours. Sign in again before each pull.

Terminal window
docker run -d --name shield360 --restart unless-stopped \
-p 3000:3000 \
-v shield360-data:/data \
-e SHIELD360_LICENSE='S360L1.…' \
-e SHIELD360_ADMIN_EMAIL=admin@example.com \
-e SHIELD360_ADMIN_PASSWORD='a long password' \
959429674945.dkr.ecr.us-east-2.amazonaws.com/shield360-selfhosted:2.1.0-allinone

Open http://<host>:3000 and sign in as the administrator. The first start takes one to three minutes; docker ps shows the container as healthy when it is ready.

What the all-in-one container does:

  • Everything is kept in the /data volume: the PostgreSQL and ClickHouse data, the platform’s own data, and the secrets it generates on first start (database passwords, session and vault keys) in /data/secrets. Back the volume up. Restarts and upgrades reuse the same secrets. To supply your own, set POSTGRES_PASSWORD, SHIELD360_DB_PASSWORD, SHIELD360_VAULT_ENCRYPTION_KEY, NEXTAUTH_SECRET and CRON_JOB_SECRET.
  • PostgreSQL and ClickHouse listen only inside the container.
  • If any of the three processes stops, the container stops the others cleanly and exits. --restart unless-stopped brings it back.

To upgrade, pull the new tag, then docker rm -f shield360 and run the same command with the new tag. The volume keeps your data, and migrations run on start.

Separate services: platform, PostgreSQL and ClickHouse

Section titled “Separate services: platform, PostgreSQL and ClickHouse”

The platform image carries a matching compose bundle at /app/selfhost. The bundle runs PostgreSQL and ClickHouse as their own containers.

Terminal window
IMAGE=959429674945.dkr.ecr.us-east-2.amazonaws.com/shield360-selfhosted:2.1.0
docker pull "$IMAGE"
docker create --name shield360-bundle "$IMAGE"
docker cp shield360-bundle:/app/selfhost ./shield360
docker rm shield360-bundle
cd shield360
cp .env.example .env && chmod 600 .env
# Replace every CHANGE_ME (openssl rand -hex 32), set SHIELD360_VERSION=2.1.0,
# SHIELD360_PUBLIC_URL to the address people use, and paste your licence into
# SHIELD360_LICENSE.
docker compose up -d

To use your own PostgreSQL or ClickHouse instead, remove that service from the compose file and point the platform at yours. Use DATABASE_URL for PostgreSQL, and INIT_DB_HOST, INIT_DB_PORT, INIT_DB_USERNAME, INIT_DB_PASSWORD and INIT_DB_DATABASE for ClickHouse. See Connect existing databases.

To upgrade, set SHIELD360_VERSION to the new release, then run docker compose pull shield360 && docker compose up -d. Copy the bundle out of the new image and compare it with yours, in case the compose file changed.

On a machine that can reach the registry, pull the images and save them to a file:

  • All-in-one: save just the one image.
  • Separate services: save the platform image together with postgres:17-alpine and clickhouse/clickhouse-server:24.4.1.

If the server’s architecture differs from the machine you pull on, add --platform linux/amd64 or --platform linux/arm64 to each docker pull first, so the saved file holds the server’s architecture.

Copy the file to the server and docker load it there. To use an internal registry instead, push the images to it and set SHIELD360_IMAGE to your copy.

Each release image is signed by Shield360’s release workflow. To check one with cosign:

Terminal window
cosign verify \
--certificate-identity-regexp '^https://github.com/ThinkfleetAI/Shield360/\.github/workflows/release-selfhosted-image\.yml@' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
959429674945.dkr.ecr.us-east-2.amazonaws.com/shield360-selfhosted:2.1.0

The multi-arch image and each architecture’s image are signed, so the check also passes for a digest pinned to one architecture.