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
2 changes: 1 addition & 1 deletion docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ The Docker Compose configuration is modular, allowing you to choose which data s
- [Container Image Access](./container-images.md)
- [Configuration Reference](./configuration.md)
- [Enable SAML SSO](./sso-saml.md)
- [Use AWS S3 for Artifact Storage](./object-storage.md)
- [Use AWS S3 for Object Storage](./object-storage.md)
- [Logging Configuration](./logging.md)
- [Backup and Restore](./backup-restore.md)
- [Upgrading Currents On-Prem](./upgrading.md)
Expand Down
31 changes: 29 additions & 2 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ These have defaults but you'll likely want to customize them.
| `FILE_STORAGE_ACCESS_KEY_ID` | string | `${RUSTFS_ACCESS_KEY}` | Object storage access key ID |
| `FILE_STORAGE_SECRET_ACCESS_KEY` | string | `${RUSTFS_SECRET_KEY}` | Object storage secret access key |
| `FILE_STORAGE_REGION` | string | _(commented)_ | S3 region (required for AWS S3) |
| `APP_CONTENT_STORAGE_ENDPOINT` | string | `${FILE_STORAGE_ENDPOINT}` | App content bucket endpoint (external access): context shares, organization logos and session files. Unset, context sharing and logo editing are off and session files cannot be uploaded ([details](./object-storage.md#app-content-bucket)) |
| `APP_CONTENT_STORAGE_BUCKET` | string | `currents-app-content` | App content bucket name |
| `APP_CONTENT_STORAGE_ACCESS_KEY_ID` | string | `${FILE_STORAGE_ACCESS_KEY_ID}` | App content bucket access key ID |
| `APP_CONTENT_STORAGE_SECRET_ACCESS_KEY` | string | `${FILE_STORAGE_SECRET_ACCESS_KEY}` | App content bucket secret access key |
| `APP_CONTENT_STORAGE_REGION` | string | _(commented)_ | S3 region (required for AWS S3) |
| `CLICKHOUSE_URL` | string | `http://clickhouse:8123` | ClickHouse HTTP endpoint |
| `CLICKHOUSE_USERNAME` | string | `currents` | ClickHouse username |
| `MONGODB_USERNAME` | string | `currents-user` | MongoDB username |
Expand All @@ -64,11 +69,28 @@ Less commonly changed settings with sensible defaults.
| `RUSTFS_ACCESS_KEY` | string | `rustfs-access-key` | RustFS/S3 access key |
| `FILE_STORAGE_INTERNAL_ENDPOINT` | string | `http://host.docker.internal:9000` | Object storage endpoint the services use from inside Docker. For AWS S3, set it to `FILE_STORAGE_ENDPOINT` ([details](./object-storage.md)) |
| `FILE_STORAGE_FORCE_PATH_STYLE` | bool | _(commented)_ | Use path-style S3 URLs (auto-set to `true` when using RustFS profile) |
| `APP_CONTENT_STORAGE_INTERNAL_ENDPOINT` | string | `${FILE_STORAGE_INTERNAL_ENDPOINT}` | App content bucket endpoint the services use from inside Docker |
| `APP_CONTENT_STORAGE_FORCE_PATH_STYLE` | bool | _(commented)_ | Path-style URLs for the app content bucket (auto-set to `true` when using RustFS profile) |
| `API_BASE_URL` | string | `${APP_BASE_URL}` | Public API origin, used in share links and as the OAuth token audience |
| `AUTOMATED_REPORTS_EMAIL_BCC` | string | _(empty)_ | BCC address for automated reports |
| `INVITE_EMAIL_BCC` | string | _(empty)_ | BCC address for invitation emails |
| `INVITE_EXPIRATION_DAYS` | int | `14` | Number of days before invitations expire |
| `EMAIL_LINKS_BASE_URL` | string | `${APP_BASE_URL}` | Base URL for links in emails (derived from APP_BASE_URL) |

### Remote MCP and OAuth

Remote MCP lets coding agents use Currents tools over HTTP at `<APP_BASE_URL>/mcp`. Clients authenticate with a Currents API key or personal access token, or, with the OAuth provider on, by signing in with a Currents account. Both endpoints are reachable by anyone who can reach the install; they refuse requests without a valid credential.

| Variable | Type | Default | Description |
|----------|------|---------|-------------|
| `MCP_ENABLED` | bool | `true` | Serve remote MCP at `/mcp`. Set `false` to turn it off; `/mcp` then answers 503 |
| `MCP_ORIGINS` | string | _(empty)_ | Other origins clients reach `/mcp` on, comma separated |
| `OAUTH_PROVIDER_ENABLED` | bool | `true` in `.env.example` | Serve OAuth authorization (`/api/auth/oauth2/*`, `/.well-known/oauth-*`). Issuer, token audience and JWKS URL are derived from `APP_BASE_URL`. Off when absent, so an upgraded `.env` keeps it off until added. Use an `https` `APP_BASE_URL` for any real setup. Over `http` it works only on `localhost`, or, for an evaluation, on a `.localhost` name in `OAUTH_HTTP_ALLOWED_HOSTS`. On any other `http` host the API refuses to start with it on, so set it to `false` there |
| `OAUTH_DYNAMIC_CLIENT_REGISTRATION_ENABLED` | bool | `true` in `.env.example` | Let clients register themselves, the way to add a client without internet access |
| `OAUTH_CIMD_ENABLED` | bool | `true` | Accept clients identified by a client ID metadata document: an https URL the server fetches. Hosts resolving to private, loopback or link-local addresses are refused |
| `OAUTH_HTTP_ALLOWED_HOSTS` | string | _(empty)_ | For an evaluation without TLS: a `.localhost` name (e.g. `currents.localhost`) the OAuth endpoints may serve over `http`. Browsers resolve `.localhost` names to this machine. Another `http` host starts, but OAuth clients are sent to an `https` issuer the install does not serve |
| `OAUTH_JWKS_URL` | string | `<APP_BASE_URL>/api/auth/jwks` | Where the API fetches its own signing keys to check access tokens. With a `.localhost` `APP_BASE_URL`, set `http://localhost:4000/api/auth/jwks`: the container cannot resolve `.localhost` names, so every token is rejected. Set the same when the container cannot reach or trust `APP_BASE_URL` (split DNS, an internal CA) |

### SAML SSO (Optional)

Enable SAML single sign-on by setting the two required variables and mounting your IdP metadata file into `./data/sso`. See [Enable SAML SSO](sso-saml.md) for the full walkthrough. SSO turns on automatically once both required variables are set — there is no separate enable flag.
Expand All @@ -80,8 +102,7 @@ Enable SAML single sign-on by setting the two required variables and mounting yo
| `SSO_SAML_PROVIDER_ID` | string | `onprem-saml` | Provider id; recommend your IdP name (e.g. `okta`). Becomes the last path segment of the ACS callback URL. |
| `SSO_SAML_DEFAULT_ROLE` | string | `member` | Role granted to auto-provisioned SSO users |
| `SSO_ALLOWED_DOMAINS` | string | _(empty)_ | Comma-separated email domains allowed to sign in via SSO |
| `SSO_SAML_AUTHN_REQUESTS_SIGNED` | bool | `false` | Sign outbound AuthnRequests (requires the SP key/cert below) |
| `SSO_SAML_SP_CERT_FILE` | string | _(empty)_ | Path to the mounted SP certificate PEM (only when signing requests) |
| `SSO_SAML_AUTHN_REQUESTS_SIGNED` | bool | `false` | Sign outbound AuthnRequests (requires the SP key below) |
| `SSO_SAML_SP_KEY_FILE` | string | _(empty)_ | Path to the mounted SP private key PEM (only when signing requests) |

### Docker Compose Configuration
Expand All @@ -100,6 +121,12 @@ These variables configure Docker Compose behavior only (not passed to containers
| `DC_RUSTFS_IMAGE` | string | `rustfs/rustfs:1.0.1` | RustFS image |
| `DC_AWS_CLI_IMAGE` | string | `amazon/aws-cli:latest` | AWS CLI image (for bucket init) |

#### Included RustFS

| Variable | Type | Default | Description |
|----------|------|---------|-------------|
| `DC_RUSTFS_DELETE_ARTIFACTS_AFTER_DAYS` | int | _(unset)_ | Delete artifacts (screenshots, videos, traces, stdout) older than this many days, through a lifecycle rule `rustfs-init` applies. Unset keeps them until deleted. Other storage: [Artifact expiry](./object-storage.md#artifact-expiry) |

#### Port Configuration

| Variable | Type | Default | Description |
Expand Down
2 changes: 1 addition & 1 deletion docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Docker Compose configuration for self-hosted Currents deployment.
- [Quickstart Guide](quickstart.md) — Get up and running with Docker Compose
- [Configuration Reference](configuration.md) — All environment variables and settings
- [Enable SAML SSO](sso-saml.md) — Delegate sign-in to your SAML identity provider
- [Use AWS S3 for Artifact Storage](object-storage.md) — IAM policy and CORS rules for your bucket
- [Use AWS S3 for Object Storage](object-storage.md) — IAM policy, CORS and lifecycle rules for your buckets
- [Logging Configuration](logging.md) — Configure container logging for production
- [Backup and Restore](backup-restore.md) — Backup and restore procedures
- [Upgrading Currents On-Prem](upgrading.md) — Upgrade workflows and version management
Expand Down
50 changes: 48 additions & 2 deletions docs/object-storage.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Use AWS S3 for Artifact Storage
# Use AWS S3 for Object Storage

Currents stores test artifacts (screenshots, videos, Playwright traces, stdout and attachments) in an S3-compatible bucket. This page covers the bucket permissions and CORS rules Currents needs when you use AWS S3 instead of the included RustFS service.
Currents stores test artifacts (screenshots, videos, Playwright traces, stdout and attachments) in an S3-compatible bucket, and context shares, organization logos and session files in a second one, the [app content bucket](#app-content-bucket). This page covers the bucket permissions, CORS and lifecycle rules Currents needs when you use AWS S3 instead of the included RustFS service.

## How Artifacts Reach the Bucket

Expand Down Expand Up @@ -92,6 +92,52 @@ aws s3api put-bucket-cors --bucket currents-artifacts --cors-configuration '{

Uploads come from the CI reporter and from Currents services rather than a browser, so they don't need a CORS rule.

## App Content Bucket

Context shares, organization logos and session files go to a separate bucket, configured with the `APP_CONTENT_STORAGE_*` variables. Without it, context sharing and logo editing are off and uploading session files answers `503`.

```bash
APP_CONTENT_STORAGE_ENDPOINT=https://s3.us-east-1.amazonaws.com
APP_CONTENT_STORAGE_INTERNAL_ENDPOINT=https://s3.us-east-1.amazonaws.com
APP_CONTENT_STORAGE_REGION=us-east-1
APP_CONTENT_STORAGE_BUCKET=currents-app-content
APP_CONTENT_STORAGE_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE
APP_CONTENT_STORAGE_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
```

The same rules as the artifact bucket apply, with these differences:

- **IAM policy:** the [policy above](#iam-policy) on the app content bucket, plus `s3:DeleteObject` on its objects. Deleting a session or organization removes its files.
- **CORS:** add `PUT` to `AllowedMethods`. Admins upload the organization logo from the browser. trace.playwright.dev is not needed.
- **Lifecycle rules:** shares expire, but nothing deletes their objects. Add these rules, and scope them to these prefixes only: the bucket also holds logos (`<orgId>/logo/`) and session files (`<orgId>/sessions/`), and a bucket-wide rule deletes them.

```bash
aws s3api put-bucket-lifecycle-configuration --bucket currents-app-content --lifecycle-configuration '{
"Rules": [
{ "ID": "ai-context-share", "Status": "Enabled", "Filter": { "Prefix": "ai-context-share/" }, "Expiration": { "Days": 2 } },
{ "ID": "share-3d", "Status": "Enabled", "Filter": { "Prefix": "share-3d/" }, "Expiration": { "Days": 4 } },
{ "ID": "share-7d", "Status": "Enabled", "Filter": { "Prefix": "share-7d/" }, "Expiration": { "Days": 8 } },
{ "ID": "trace-links", "Status": "Enabled", "Filter": { "Prefix": "trace-links/" }, "Expiration": { "Days": 8 } }
]
}'
```

Each rule outlives the longest share written under its prefix by a day. The included RustFS service gets these rules from `rustfs-init`.

## Artifact Expiry

Currents does not delete artifacts. To limit how long they are kept, add a lifecycle rule to the artifact bucket. Replace `30` with the number of days and `currents-artifacts` with your bucket name:

```bash
aws s3api put-bucket-lifecycle-configuration --bucket currents-artifacts --lifecycle-configuration '{
"Rules": [
{ "ID": "delete-artifacts-after-days", "Status": "Enabled", "Filter": { "Prefix": "" }, "Expiration": { "Days": 30 } }
]
}'
```

Runs older than that still show in the dashboard, without their screenshots, videos, traces and stdout. With the included RustFS service, set `DC_RUSTFS_DELETE_ARTIFACTS_AFTER_DAYS` instead.

## Troubleshooting 403 Errors

Open the failing request in the browser's developer tools (**Network** tab):
Expand Down
8 changes: 6 additions & 2 deletions docs/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ APP_BASE_URL=http://localhost:4000
CURRENTS_RECORD_API_URL=http://localhost:1234
```

The OAuth provider for remote MCP, on in `.env.example`, needs `https` or `localhost`. With an `http` `APP_BASE_URL` on any other host, set `OAUTH_PROVIDER_ENABLED=false`, or the API refuses to start. To evaluate OAuth without TLS on a name other than `localhost`, use a `.localhost` name such as `http://currents.localhost:4000`, and set `OAUTH_HTTP_ALLOWED_HOSTS=currents.localhost` and `OAUTH_JWKS_URL=http://localhost:4000/api/auth/jwks`.

### Root User Account

The `ON_PREM_EMAIL` is the email address used to create the initial root admin user:
Expand Down Expand Up @@ -108,9 +110,11 @@ FILE_STORAGE_REGION=us-east-1
# FILE_STORAGE_FORCE_PATH_STYLE=true
```

For AWS S3, also set `FILE_STORAGE_INTERNAL_ENDPOINT` to the same endpoint, and give the bucket the IAM policy and CORS rules in [Use AWS S3 for Artifact Storage](./object-storage.md).
For AWS S3, also set `FILE_STORAGE_INTERNAL_ENDPOINT` to the same endpoint, and give the bucket the IAM policy and CORS rules in [Use AWS S3 for Object Storage](./object-storage.md).

Context shares, organization logos and session files need a second bucket, set with the `APP_CONTENT_STORAGE_*` variables. `.env.example` reuses the artifact storage endpoint and credentials for it. Create the bucket and add the lifecycle rules in [App Content Bucket](./object-storage.md#app-content-bucket).

If using the included RustFS for testing, configure the `RUSTFS_*` variables instead. The RustFS profile automatically sets `FILE_STORAGE_FORCE_PATH_STYLE=true` for all services.
If using the included RustFS for testing, configure the `RUSTFS_*` variables instead. The RustFS profile automatically sets `FILE_STORAGE_FORCE_PATH_STYLE=true` and `APP_CONTENT_STORAGE_FORCE_PATH_STYLE=true` for all services, and creates both buckets.

> ⚠️ **Production Note:** RustFS is intended for local development and testing only—it is **not recommended for production deployments**. The included Docker Compose configuration is designed for local development; production environments should use external, production-grade object storage backends such as AWS S3, Google Cloud Storage, or a managed MinIO cluster.

Expand Down
7 changes: 3 additions & 4 deletions docs/sso-saml.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,12 +74,12 @@ Go to your dashboard and enter your email on the sign-in screen. If your email i
|----------|---------|
| `SSO_SAML_DEFAULT_ROLE` | Role for auto-provisioned SSO users. Default `member`. |
| `SSO_ALLOWED_DOMAINS` | Comma-separated allow-list of email domains, e.g. `acme.com,acme.io`. Defense-in-depth on top of your IdP. |
| `SSO_SAML_AUTHN_REQUESTS_SIGNED` | Set `true` to sign outbound AuthnRequests. Requires an SP key/cert (below). |
| `SSO_SAML_SP_CERT_FILE` / `SSO_SAML_SP_KEY_FILE` | Paths to your SP certificate/private key PEMs (place them in `./data/sso` too). Only needed for signed requests. |
| `SSO_SAML_AUTHN_REQUESTS_SIGNED` | Set `true` to sign outbound AuthnRequests. Requires an SP key (below). |
| `SSO_SAML_SP_KEY_FILE` | Path to your SP private key PEM (place it in `./data/sso` too). Only needed for signed requests. |

### Signing AuthnRequests (advanced)

If your IdP requires signed requests, generate a self-signed SP keypair, drop it in `./data/sso`, and point the vars at it:
If your IdP requires signed requests, generate a self-signed SP keypair in `./data/sso`, upload `sp-cert.pem` to your IdP so it can verify the signatures, and point Currents at the key:

```bash
openssl req -x509 -newkey rsa:2048 -nodes \
Expand All @@ -89,7 +89,6 @@ openssl req -x509 -newkey rsa:2048 -nodes \

```bash
SSO_SAML_AUTHN_REQUESTS_SIGNED=true
SSO_SAML_SP_CERT_FILE=/etc/currents/sso/sp-cert.pem
SSO_SAML_SP_KEY_FILE=/etc/currents/sso/sp-key.pem
```

Expand Down
Loading
Loading