Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,9 @@ jobs:
chown -R "$(id -u):$(id -g)" /ws 2>/dev/null || true
find "$GITHUB_WORKSPACE" -mindepth 1 -delete 2>/dev/null || true
exit 0

customer-bundle:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: bash deploy/scripts/test-customer-bundle.sh
34 changes: 34 additions & 0 deletions .github/workflows/release-please.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ jobs:
permissions:
contents: read
packages: write
outputs:
image_digest: ${{ steps.publish.outputs.digest }}
steps:
- name: Reset workspace ownership
run: |
Expand Down Expand Up @@ -80,3 +82,35 @@ jobs:
docker buildx prune -f --filter "until=1h" 2>/dev/null || true
docker system prune -f --filter "until=1h" 2>/dev/null || true
exit 0

customer-bundle:
needs:
- release
- publish-image
if: needs.release.outputs.release_created == 'true'
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Check out repository
uses: actions/checkout@v4

- name: Package customer install bundle
run: |
set -euo pipefail
TAG_NAME="${{ needs.release.outputs.tag_name }}"
VERSION="${TAG_NAME#ct-cve-}"
IMAGE_REF="${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ needs.publish-image.outputs.image_digest }}"
bash deploy/scripts/package-customer-bundle.sh dist "$VERSION" "$IMAGE_REF"

- name: Upload customer install bundle
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAG_NAME: ${{ needs.release.outputs.tag_name }}
run: |
gh release upload "$TAG_NAME" \
dist/ct-cve-single-*.zip \
dist/ct-cve-single-*.zip.sha256 \
dist/ct-cve-single.zip \
dist/ct-cve-single.zip.sha256 \
--clobber
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,32 @@ Use a versioned tag for deployments that need reproducible rollouts. The
`latest` tag is provided for local evaluation and follows the most recent
published release.

## Customer Install Bundle

Each GitHub release also publishes a downloadable `ct-cve-single.zip` bundle
for single-host customer installs. Unzip it on a host with Docker and run:

```sh
unzip ct-cve-single.zip
cd ct-cve
./start.sh
```

The bundle includes `docker-compose.yml`, `.env.example`, `start.sh`, and
`upgrade.sh`. On first run, `start.sh` creates `.env`, generates a local
PostgreSQL password, starts the database and CT-CVE containers, and waits for
the service health check. CT-CVE applies embedded database migrations during
startup before the health check succeeds.

To upgrade an existing install, run:

```sh
./upgrade.sh
```

The upgrade helper backs up local install files, preserves `.env`, replaces the
bundle-managed files, and restarts CT-CVE unless `--no-start` is passed.

## Configuration

| Variable | Required | Default | Description |
Expand Down
24 changes: 24 additions & 0 deletions deploy/customer-bundle/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# CT-CVE customer install configuration.
# start.sh copies this file to .env and fills blank required values on first run.

CT_CVE_IMAGE=ghcr.io/carrtech-dev/ct-cve:latest
CT_CVE_HTTP_PORT=8080

# Leave blank on first run to let start.sh generate a strong local password.
POSTGRES_PASSWORD=
CT_CVE_DATABASE_URL=

CT_CVE_FEED_SYNC_INTERVAL=6h
CT_CVE_FEED_SYNC_ON_STARTUP=true
CT_CVE_FEED_HTTP_TIMEOUT=30s

CT_CVE_NVD_ENABLED=true
CT_CVE_NVD_BASE_URL=https://services.nvd.nist.gov/rest/json/cves/2.0
CT_CVE_NVD_API_KEY=
CT_CVE_NVD_REQUEST_DELAY=

CT_CVE_CISA_KEV_ENABLED=true
CT_CVE_CISA_KEV_BASE_URL=https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json

# JSON array of CT Ops connector definitions. Configure this after pairing CT-CVE with CT Ops.
CT_CVE_CT_OPS_CONNECTIONS=[]
35 changes: 35 additions & 0 deletions deploy/customer-bundle/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# CT-CVE Customer Bundle

This bundle runs CT-CVE on a single host with Docker Compose.

## Requirements

- Docker Engine 24 or newer with the Compose plugin
- `openssl`
- `curl` and `unzip` for online upgrades

## First Start

```sh
unzip ct-cve-single.zip
cd ct-cve
./start.sh
```

On first run, `start.sh` creates `.env`, generates a database password, starts
PostgreSQL, starts CT-CVE, and waits for `/healthz`. CT-CVE applies embedded
database migrations automatically before the health check succeeds.

Open `http://localhost:8080/status` after startup. Change `CT_CVE_HTTP_PORT` in
`.env` if port 8080 is already in use.

## Upgrade

```sh
./upgrade.sh
```

The upgrade helper backs up local install files, downloads the latest bundle,
preserves `.env`, stops containers without deleting named volumes, installs the
new files, and starts CT-CVE. Use `./upgrade.sh --from-zip <path>` for a bundle
that was downloaded separately.
45 changes: 45 additions & 0 deletions deploy/customer-bundle/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
services:
ct-cve:
image: ${CT_CVE_IMAGE:-ghcr.io/carrtech-dev/ct-cve:latest}
restart: unless-stopped
environment:
CT_CVE_HTTP_ADDR: ":8080"
CT_CVE_DATABASE_URL: "${CT_CVE_DATABASE_URL:?CT_CVE_DATABASE_URL must be set by start.sh}"
CT_CVE_FEED_SYNC_INTERVAL: "${CT_CVE_FEED_SYNC_INTERVAL:-6h}"
CT_CVE_FEED_SYNC_ON_STARTUP: "${CT_CVE_FEED_SYNC_ON_STARTUP:-true}"
CT_CVE_FEED_HTTP_TIMEOUT: "${CT_CVE_FEED_HTTP_TIMEOUT:-30s}"
CT_CVE_NVD_ENABLED: "${CT_CVE_NVD_ENABLED:-true}"
CT_CVE_NVD_BASE_URL: "${CT_CVE_NVD_BASE_URL:-https://services.nvd.nist.gov/rest/json/cves/2.0}"
CT_CVE_NVD_API_KEY: "${CT_CVE_NVD_API_KEY:-}"
CT_CVE_NVD_REQUEST_DELAY: "${CT_CVE_NVD_REQUEST_DELAY:-}"
CT_CVE_CISA_KEV_ENABLED: "${CT_CVE_CISA_KEV_ENABLED:-true}"
CT_CVE_CISA_KEV_BASE_URL: "${CT_CVE_CISA_KEV_BASE_URL:-https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json}"
CT_CVE_CT_OPS_CONNECTIONS: "${CT_CVE_CT_OPS_CONNECTIONS:-[]}"
ports:
- "${CT_CVE_HTTP_PORT:-8080}:8080"
depends_on:
ct-cve-db:
condition: service_healthy
healthcheck:
test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:8080/healthz >/dev/null 2>&1"]
interval: 10s
timeout: 3s
retries: 12

ct-cve-db:
image: postgres:16-alpine
restart: unless-stopped
environment:
POSTGRES_DB: ct_cve
POSTGRES_USER: ct_cve
POSTGRES_PASSWORD: "${POSTGRES_PASSWORD:?POSTGRES_PASSWORD must be set by start.sh}"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ct_cve -d ct_cve"]
interval: 5s
timeout: 3s
retries: 12
volumes:
- ct-cve-db-data:/var/lib/postgresql/data

volumes:
ct-cve-db-data:
Loading
Loading