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
20 changes: 17 additions & 3 deletions portals/developer-portal/.dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,28 @@ configs/
sample.config.toml
.env
.env.*
api-platform.env
api-platform.env.*

# ── setup.sh output: bind-mounted TLS cert ────────────────────────
# Must never be baked into the image — a stale copy here can silently
# resurface a removed/rotated secret on `docker compose up` without `--build`.
resources/certificates/

# ── Docker / distribution files ───────────────────────────────────
docker-compose.yml
distribution/
docker-compose*.yaml

# ── Database init / seed scripts (volume-mounted into postgres) ───
artifacts/

# ── Sample APIs/MCPs (deployed via ./scripts/seed-samples.sh against the
# REST API, not read from disk by the running app) ─────────────────
samples/

# ── Host-side operational scripts (setup.sh, seed-samples.sh) — run against
# a running container from the host, never executed inside it ──────
scripts/

# ── Build tooling ─────────────────────────────────────────────────
Makefile
VERSION
Expand All @@ -29,7 +43,7 @@ README.md
LICENSE
docs/*.md
bin/
scripts/
tools/

# ── Git / editor metadata ─────────────────────────────────────────
.git
Expand Down
4 changes: 4 additions & 0 deletions portals/developer-portal/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,11 @@ resources/default-layout
resources/mock

.env
api-platform.env
configs/config-platform-api.toml

# ./setup.sh output: bind-mounted TLS cert
resources/certificates/

# Test reports
it/reports/*
8 changes: 5 additions & 3 deletions portals/developer-portal/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,11 @@ EXPOSE 8080
# Create a non-root user with UID 10001 to satisfy Checkov CKV_CHOREO_1
RUN groupadd -g 10001 appgroup && useradd -u 10001 -g appgroup -s /bin/bash -M appuser

# Pre-create the certs and logs directories owned by the non-root user so the
# entrypoint script can write self-signed certs, and the app can write log files.
RUN mkdir -p /app/certs /app/logs /app/data && chown -R 10001:10001 /app/certs /app/logs /app/data
# Pre-create the logs and data directories owned by the non-root user so the
# app can write log files and its database. The TLS certificate is bind-mounted
# read-only at /etc/devportal/tls (generated host-side by setup.sh) — never
# written to by the container.
RUN mkdir -p /app/logs /app/data && chown -R 10001:10001 /app/logs /app/data

RUN chmod +x /app/docker-entrypoint.sh

Expand Down
27 changes: 19 additions & 8 deletions portals/developer-portal/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -140,11 +140,22 @@ DIST_ZIP := target/$(DIST_NAME).zip
dist: clean-dist ## Build standalone developer portal distribution zip
@echo "Building distribution $(DIST_NAME)..."
@mkdir -p $(DIST_DIR)/configs
@cp -R database $(DIST_DIR)
@mkdir -p $(DIST_DIR)/resources/developer-portal/db-scripts
@cp -R database/* $(DIST_DIR)/resources/developer-portal/db-scripts
@mkdir -p $(DIST_DIR)/resources/samples
@cp -R samples/apis $(DIST_DIR)/resources/samples/
@cp -R samples/mcps $(DIST_DIR)/resources/samples/
@cp configs/config.toml $(DIST_DIR)/configs/config.toml
@cp configs/config-template.toml $(DIST_DIR)/configs/config-template.toml
@cp configs/config-platform-api.toml.example $(DIST_DIR)/configs/config-platform-api.toml
@cp distribution/docker-compose.yaml $(DIST_DIR)/docker-compose.yaml
@cp configs/config-platform-api-template.toml $(DIST_DIR)/configs/config-platform-api.toml
@cp configs/config-platform-api-template.toml $(DIST_DIR)/configs/config-platform-api-template.toml
@cp docker-compose.yaml $(DIST_DIR)/docker-compose.yaml
@cp distribution/README.md $(DIST_DIR)/README.md
@mkdir -p $(DIST_DIR)/scripts
@cp scripts/setup.sh $(DIST_DIR)/scripts/setup.sh
@chmod +x $(DIST_DIR)/scripts/setup.sh
@cp scripts/seed-samples.sh $(DIST_DIR)/scripts/seed-samples.sh
@chmod +x $(DIST_DIR)/scripts/seed-samples.sh
@sed -i.bak \
-e 's|image: .*/developer-portal:[^[:space:]]*|image: $(DEVPORTAL_IMAGE):$(DIST_VERSION)|g' \
$(DIST_DIR)/docker-compose.yaml
Expand All @@ -168,11 +179,11 @@ clean: clean-dist ## Clean all build artifacts
.PHONY: generate-ddl
generate-ddl: ## Generate DDL schema files from Sequelize models for all supported dialects
@echo "Generating DDL files (postgres, mysql, mariadb, mssql, sqlite)..."
@node scripts/generate-ddl.js postgres
@node scripts/generate-ddl.js mysql
@node scripts/generate-ddl.js mariadb
@node scripts/generate-ddl.js mssql
@node scripts/generate-ddl.js sqlite
@node tools/generate-ddl.js postgres
@node tools/generate-ddl.js mysql
@node tools/generate-ddl.js mariadb
@node tools/generate-ddl.js mssql
@node tools/generate-ddl.js sqlite
@echo "Done. Files written to database/"

# Docs Targets
Expand Down
71 changes: 20 additions & 51 deletions portals/developer-portal/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,32 +22,24 @@ For end-user documentation, see [docs/](docs/).

## Quick Start (Docker Compose)

The fastest way to get the portal running — no local Node install required.

### Build

```bash
# Build the developer-portal Docker image from source
make build
```
The fastest way to get the portal running — no local Node install required. Requires `openssl` and Docker (used by `./scripts/setup.sh` to bcrypt-hash the admin password).

### Run

```bash
mkdir -p configs && cp configs/config.toml.example configs/config.toml
./scripts/setup.sh
docker compose up
```

Then open **https://localhost:3000/default/views/default**
`./scripts/setup.sh` is a one-time step: it generates devportal's and the Platform API's encryption/JWT secrets, a self-signed TLS certificate, and an admin user into `api-platform.env` (git-ignored) and `configs/config-platform-api.toml` (also git-ignored — copy `configs/config-platform-api-template.toml` instead for a static, no-dependencies starting point). It prompts for an admin username/password interactively, or generates a random password if you press Enter; set `ADMIN_USERNAME`/`ADMIN_PASSWORD` env vars to skip the prompts (e.g. in CI). Safe to re-run — it only fills in what's missing and never overwrites an existing value; to build devportal from source instead of using the published image, run `docker compose up --build`.

> **Browser warning:** A self-signed TLS certificate is generated automatically on first start. Click **Advanced → Proceed** (Chrome) or **Accept the Risk** (Firefox) to continue.
Then open **https://localhost:3000/default/views/default** and log in with the admin credentials `./scripts/setup.sh` printed.

Default credentials: `admin` / `admin` (defined in `configs/config-platform-api.toml`)
> **Browser warning:** the TLS certificate is self-signed. Click **Advanced → Proceed** (Chrome) or **Accept the Risk** (Firefox) to continue.

What happens automatically on first start:
- The DB schema is applied and the database is initialised automatically
- A default **default** org, view, labels, and subscription plans are seeded automatically on startup (controlled by `organization.default_name` in config)
- A self-signed TLS certificate is generated and stored in the `certs_data` Docker volume

### Test

Expand Down Expand Up @@ -143,26 +135,13 @@ See [it/README.md](it/README.md) for the full list of test commands and suite de

Use this for active development, custom IdP configuration, or when you prefer to run Node directly.

### 1. Create config file
### 1. Config file

```bash
mkdir -p configs && cp configs/config.toml.example configs/config.toml
```

`configs/config.toml` is your local config file (not committed to git). See [Configuration reference](#configuration-reference) below for all available settings.
`configs/config.toml` already ships with sensible defaults — edit it directly for custom settings. `configs/config-template.toml` is the full annotated reference of every available setting; see [Configuration reference](#configuration-reference) below.

### 2. Configure HTTP mode (optional)
### 2. Use `npm run start:local`, not `npm start`

Open `configs/config.toml` and confirm these are set (they are the defaults in `configs/config.toml.example`):

```toml
[tls]
enabled = false

[server]
base_url = "http://localhost:3000"
port = 3000
```
`configs/config.toml`'s own defaults are wired for the Docker Compose topology (TLS on, pointing at a cert only the containers have, `platform_api.base_url` pointing at the `platform-api` hostname that only resolves inside the compose network). Plain `npm start` inherits those as-is and will fail — there's no `/app` filesystem or bind-mounted cert here. `npm run start:local` (`package.json`) overrides all of it in one place: TLS off, `http://localhost:3000`, and `platform_api.base_url` pointed at `localhost` (see [Local auth](#local-auth) if you're running the Platform API sidecar).

### 3. Configure the Identity Provider (optional)

Expand Down Expand Up @@ -223,7 +202,7 @@ No manual step is required.

```bash
npm install
npm start
npm run start:local
```

Open **http://localhost:3000/default/views/default**
Expand All @@ -232,35 +211,25 @@ Open **http://localhost:3000/default/views/default**

## Seed Sample APIs (optional)

Seeds a set of sample APIs into the default organisation. Works with both the Docker Compose and `npm start` workflows.

Get a Bearer token first, then pass it via `DEVPORTAL_TOKEN`:
Deploys the sample APIs and MCP servers under `samples/` into the default organisation, entirely through the public REST API — devportal itself has no built-in seeding logic. Works with both the Docker Compose and `npm start` workflows.

**npm start (HTTP):**
```bash
TOKEN=$(curl -sk -X POST "https://localhost:9243/api/portal/v0.9/auth/login" \
-d "username=admin&password=admin" | jq -r .token)
DEVPORTAL_URL=http://localhost:3000 DEVPORTAL_TOKEN=$TOKEN ./seeders/seed-apis.sh
./scripts/seed-samples.sh
```

**Docker Compose (HTTPS):**
```bash
TOKEN=$(curl -sk -X POST "https://localhost:9243/api/portal/v0.9/auth/login" \
-d "username=admin&password=admin" | jq -r .token)
DEVPORTAL_URL=https://localhost:3000 DEVPORTAL_TOKEN=$TOKEN ./seeders/seed-apis.sh
```
Prompts for the admin username/password (or set `ADMIN_USERNAME`/`ADMIN_PASSWORD` to skip the prompt, e.g. in CI). Safe to re-run — entries that already exist are skipped. Set `DEVPORTAL_URL`/`PLATFORM_API_URL` to override the defaults (`https://localhost:3000` / `https://localhost:9243`) — e.g. `DEVPORTAL_URL=http://localhost:3000` when running against `npm run start:local`.

---

## Configuration Reference

All settings live in `configs/config.toml`. Every setting can also be overridden with an `APIP_DP_*` environment variable.

The full annotated list of settings is in [`configs/config.toml.example`](configs/config.toml.example).
The full annotated list of settings is in [`configs/config-template.toml`](configs/config-template.toml).

### Local auth

For quick exploration without an IdP, the portal delegates credential validation to a Platform API sidecar. Users, bcrypt-hashed passwords, and `dp:*` scopes are defined in `configs/config-platform-api.toml` (copy from `configs/config-platform-api.toml.example`):
For quick exploration without an IdP, the portal delegates credential validation to a Platform API sidecar. Users, bcrypt-hashed passwords, and `dp:*` scopes are defined in `configs/config-platform-api.toml` (copy from `configs/config-platform-api-template.toml`):

```toml
[[auth.file_based.users]]
Expand All @@ -269,13 +238,13 @@ password_hash = "$2y$10$..." # bcrypt hash — generate with: htpasswd -bnBC 1
scopes = "dp:org_manage dp:api_manage ..."
```

The portal config (or `APIP_DP_PLATFORMAPI_*` env vars) must point to the Platform API. Docker Compose sets these automatically:
The portal config (or `APIP_DP_PLATFORMAPI_*` env vars) must point to the Platform API. `config.toml`'s own defaults assume Docker Compose, where `platform-api` is a resolvable hostname on the compose network — `npm run start:local` already overrides `base_url` to `https://localhost:9243` (the sidecar's port published to the host) and `insecure = true` (self-signed cert), so no manual edit is needed for that flow:

```toml
[platform_api]
base_url = "https://platform-api:9243" # env: APIP_DP_PLATFORMAPI_BASEURL
base_url = "https://localhost:9243" # env: APIP_DP_PLATFORMAPI_BASEURL
jwt_secret = "" # same as the Platform API's APIP_CP_AUTH_JWT_SECRET_KEY — env: APIP_DP_PLATFORMAPI_JWTSECRET
insecure = false # set true when Platform API uses a self-signed cert
insecure = true # Platform API uses a self-signed cert
```

For production, configure an OIDC identity provider per organization instead of local auth.
Expand Down Expand Up @@ -433,7 +402,7 @@ paths:
```

```bash
# Get a Bearer token
# Get a Bearer token (substitute the credentials ./scripts/setup.sh printed)
TOKEN=$(curl -sk -X POST "https://localhost:9243/api/portal/v0.9/auth/login" \
-d "username=admin&password=admin" | jq -r .token)

Expand All @@ -457,5 +426,5 @@ Refresh the portal — the Ping API now appears in the catalog. Click it to view
| Organization | `default` |
| Default view | `default` |
| Portal URL | `https://localhost:3000/default/views/default` |
| Admin credentials | `admin` / `admin` (local auth) |
| Admin credentials | printed by `./scripts/setup.sh` (local auth) |
| Sample API | `Ping API` visible in the catalog |
Loading
Loading