Configuration reference
Set these variables in the ShipLean service environment. Values marked Not set have no documented default. Leave them out unless you need that option. Keep passwords, tokens, and keys in your deployment’s secret store. The examples use placeholders, not working credentials.
Database
Section titled “Database”SHIPLEAN_DB_CONNECTION
Section titled “SHIPLEAN_DB_CONNECTION”Connection string for the required PostgreSQL database.
- Default: None; required.
- Example:
Host=db;Database=shiplean;Username=shiplean;Password=<database-password> - Set it when: Always. Point it at the database that this ShipLean instance uses.
SHIPLEAN_DB_MIGRATE
Section titled “SHIPLEAN_DB_MIGRATE”Controls whether ShipLean applies its database schema and migrations at startup.
- Default:
true. - Example:
false - Set it when: Set it to
falseonly when you manage schema changes separately.
First admin
Section titled “First admin”SHIPLEAN_ADMIN_EMAIL
Section titled “SHIPLEAN_ADMIN_EMAIL”Email address of the first instance admin. With password sign-in, set it together with SHIPLEAN_ADMIN_PASSWORD. With an identity proxy, the email address alone is enough.
- Default: Not set.
- Example:
admin@example.com - Set it when: You are creating the first instance admin. If you followed the quick start, remove it after you sign in.
SHIPLEAN_ADMIN_PASSWORD
Section titled “SHIPLEAN_ADMIN_PASSWORD”Password used to create or find the first instance admin when you sign in with a password. In proxy mode, ShipLean ignores it and logs a warning.
- Default: Not set.
- Example:
<initial-admin-password> - Set it when: You are creating the first instance admin with email and password sign-in. Remove it from the environment after setup.
Attachments and blob storage
Section titled “Attachments and blob storage”SHIPLEAN_BLOB_ROOT
Section titled “SHIPLEAN_BLOB_ROOT”Folder used for attachments and profile photos when neither blob connection is set.
- Default:
data/blobsin the app folder. The Compose setup uses/data/blobson a named volume. - Example:
/data/blobs - Set it when: You use folder storage and need to choose its persistent path. For multiple instances, use PostgreSQL or S3 instead.
SHIPLEAN_BLOB_DB_CONNECTION
Section titled “SHIPLEAN_BLOB_DB_CONNECTION”PostgreSQL connection string for storing attachments and profile photos in a database table. It can point to the same database as SHIPLEAN_DB_CONNECTION or to a separate one. ShipLean creates the table at startup when SHIPLEAN_DB_MIGRATE is enabled.
- Default: Not set.
- Example:
Host=db;Database=shiplean;Username=shiplean;Password=<database-password> - Set it when: You want database-backed storage for attachments and photos, especially when several instances run or the app has no persistent disk.
SHIPLEAN_BLOB_S3_CONNECTION
Section titled “SHIPLEAN_BLOB_S3_CONNECTION”Connection settings for an S3 bucket. Separate the name=value settings with semicolons. bucket is required. Set region or serviceUrl. Set both accessKey and secretKey, or leave both out to use the AWS default credentials chain. forcePathStyle and prefix are optional. The bucket must already exist.
- Default: Not set.
- Example:
bucket=shiplean;region=ap-southeast-1;prefix=prod/ - Set it when: You want attachments and photos in AWS S3 or an S3-compatible service such as R2 or RustFS, especially for multiple instances or when the app disk is not persistent.
ShipLean chooses the first configured store in this order: SHIPLEAN_BLOB_S3_CONNECTION, then SHIPLEAN_BLOB_DB_CONNECTION, then the folder at SHIPLEAN_BLOB_ROOT. Startup logs the selected store and the reason, and it omits passwords and secret keys. It logs a warning when both connection settings are present. Changing stores does not move existing files. They stay in the old store.
SHIPLEAN_ATTACHMENT_MAX_BYTES
Section titled “SHIPLEAN_ATTACHMENT_MAX_BYTES”Maximum size of one attachment accepted through uploads and imports, in bytes.
- Default:
26214400, which is 25 MiB. - Example:
52428800, which is 50 MiB. - Set it when: You need a different per-file maximum.
SHIPLEAN_ATTACHMENT_MAX_ITEM_BYTES
Section titled “SHIPLEAN_ATTACHMENT_MAX_ITEM_BYTES”Maximum total size of the attachments on one work item. Only live files count toward it. Replaced files stop counting, but each file must still meet SHIPLEAN_ATTACHMENT_MAX_BYTES.
- Default:
262144000, which is 250 MiB. - Example:
524288000, which is 500 MiB. - Set it when: You need a different total allowance for each work item.
Reverse proxy
Section titled “Reverse proxy”SHIPLEAN_TRUSTED_PROXIES
Section titled “SHIPLEAN_TRUSTED_PROXIES”Comma-separated addresses or CIDR ranges of the reverse proxies that ShipLean trusts for forwarded client addresses and schemes. The published app trusts loopback peers by default. It does not trust a container network unless you list it here.
- Default: Loopback peers are trusted. A proxy network is not trusted by default.
- Example:
10.0.0.12 - Set it when: Your reverse proxy connects from an address outside loopback. Use the address that ShipLean sees as the proxy peer. The supplied Caddy Compose example sets
172.31.251.2/32for its Caddy container. For your own proxy, use the address or CIDR range that applies to it.
SHIPLEAN_FORWARDED_FOR_HEADER
Section titled “SHIPLEAN_FORWARDED_FOR_HEADER”Name of the header that holds the original client address when your proxy uses its own forwarded-address header.
- Default:
X-Forwarded-For. - Example:
CF-Connecting-IP - Set it when: Your proxy uses a different header, such as Cloudflare’s
CF-Connecting-IP.
Sign-in through an identity proxy
Section titled “Sign-in through an identity proxy”SHIPLEAN_AUTH_PROXY_TOKEN_HEADER
Section titled “SHIPLEAN_AUTH_PROXY_TOKEN_HEADER”Enables the recommended identity-proxy sign-in mode. It names the request header that carries the proxy’s signed JWT. ShipLean verifies the token on every request. Also set SHIPLEAN_AUTH_PROXY_TOKEN_ISSUER.
- Default: Not set. Email and password sign-in stays active.
- Example:
Cf-Access-Jwt-Assertion - Set it when: Your proxy forwards a signed identity token. Common header names are
X-Forwarded-Access-Tokenfor oauth2-proxy,Cf-Access-Jwt-Assertionfor Cloudflare Access, andX-Pomerium-Jwt-Assertionfor Pomerium. UseAuthorizationto read a Bearer token.
SHIPLEAN_AUTH_PROXY_TOKEN_ISSUER
Section titled “SHIPLEAN_AUTH_PROXY_TOKEN_ISSUER”Expected iss value of the identity token. ShipLean gets the signing keys from the issuer’s /.well-known/openid-configuration discovery document, unless you set a JWKS URL.
- Default: Not set. Required with
SHIPLEAN_AUTH_PROXY_TOKEN_HEADER. - Example:
https://login.example.com/ - Set it when: You enable token-based proxy sign-in. Use an absolute HTTPS URL. HTTP is allowed only for loopback addresses.
SHIPLEAN_AUTH_PROXY_TOKEN_JWKS_URL
Section titled “SHIPLEAN_AUTH_PROXY_TOKEN_JWKS_URL”Sets an explicit key-set URL in place of discovery, for an issuer that has no discovery document.
- Default: Not set. Discovery is used.
- Example:
https://team.example.cloudflareaccess.com/cdn-cgi/access/certs - Set it when: Your identity provider requires a direct JWKS URL, such as Cloudflare Access. It follows the same URL rule as the issuer.
SHIPLEAN_AUTH_PROXY_TOKEN_AUDIENCE
Section titled “SHIPLEAN_AUTH_PROXY_TOKEN_AUDIENCE”Expected audience claim in the signed identity token.
- Default: Not set. No audience value is checked.
- Example:
shiplean.example.com - Set it when: You want ShipLean to require a specific value in the token’s
audclaim.
SHIPLEAN_AUTH_PROXY_EMAIL_CLAIM
Section titled “SHIPLEAN_AUTH_PROXY_EMAIL_CLAIM”Name of the claim that holds the signed-in person’s email address.
- Default:
email. - Example:
preferred_username - Set it when: Your identity provider stores the email address under a different claim name.
SHIPLEAN_AUTH_PROXY_NAME_CLAIM
Section titled “SHIPLEAN_AUTH_PROXY_NAME_CLAIM”Name of the claim that holds the person’s display name. If the claim is missing, a new user’s name is the part of their email address before @.
- Default:
name. - Example:
display_name - Set it when: Your identity provider uses a different claim for a person’s name.
SHIPLEAN_AUTH_PROXY_EMAIL_HEADER
Section titled “SHIPLEAN_AUTH_PROXY_EMAIL_HEADER”Enables proxy sign-in with an email header when the proxy sends no signed token. ShipLean trusts this header only from loopback addresses and from addresses in SHIPLEAN_TRUSTED_PROXIES. Do not set it together with SHIPLEAN_AUTH_PROXY_TOKEN_HEADER.
- Default: Not set. Plain-header proxy sign-in is off.
- Example:
Remote-Email - Set it when: Your proxy provides a trusted email header, such as Authelia’s
Remote-Email, and only the proxy can reach ShipLean. A direct client that can set this header can sign in as any email address.
SHIPLEAN_AUTH_PROXY_NAME_HEADER
Section titled “SHIPLEAN_AUTH_PROXY_NAME_HEADER”Optional header that holds a display name in plain-header proxy mode.
- Default: Not set.
- Example:
Remote-Name - Set it when: You use
SHIPLEAN_AUTH_PROXY_EMAIL_HEADERand your proxy also supplies a name.
SHIPLEAN_AUTH_PROXY_SIGN_OUT_URL
Section titled “SHIPLEAN_AUTH_PROXY_SIGN_OUT_URL”Destination for the ShipLean sign-out action while proxy sign-in is active.
- Default: Not set. The sign-out action is hidden.
- Example:
/oauth2/sign_out - Set it when: You want sign-out to send the person to the proxy’s sign-out route, or to another HTTP or HTTPS destination.
MCP gateway
Section titled “MCP gateway”SHIPLEAN_MCP_GATEWAY_EMAIL_HEADER
Section titled “SHIPLEAN_MCP_GATEWAY_EMAIL_HEADER”Enables trusted-gateway identity for /mcp. It names the request header that carries the caller’s email. A non-blank email value in this header takes precedence over any bearer token, including a valid ShipLean agent token. If the header is absent, blank, repeated, or not a usable email, ShipLean checks the bearer token as usual. Without a valid bearer token, the request is refused.
- Default: Not set.
/mcpaccepts ShipLean agent bearer tokens and ignores this header. - Example:
x-user-email - Set it when: A sidecar, policy proxy, or ingress writes this header and removes any copy that a client supplies, and clients cannot reach
/mcpdirectly. A client that can set this header can act as any email address. Project membership still limits board access.
GitHub/GitLab integration
Section titled “GitHub/GitLab integration”Environment integration settings are defaults. Settings saved in the Integrations section of Instance settings override SHIPLEAN_GITHUB_TOKEN, SHIPLEAN_GITLAB_URL, and SHIPLEAN_GITLAB_TOKEN. Only the environment sets the GitHub API URL. A saved GitLab URL uses its saved token and never combines with the environment token. Clearing the saved GitLab URL restores the environment pair. Tokens are sent only to HTTPS API addresses.
SHIPLEAN_GITHUB_TOKEN
Section titled “SHIPLEAN_GITHUB_TOKEN”GitHub token that lets Feature pull request and issue links show live titles and states, including for private repositories. Without it, ShipLean reads only public repositories.
- Default: Not set.
- Example:
<github-read-token> - Set it when: You want live link cards for private GitHub repositories. Provide a token that can read pull requests and issues.
SHIPLEAN_GITHUB_API_URL
Section titled “SHIPLEAN_GITHUB_API_URL”GitHub API base address. Only the environment sets this value. Instance settings cannot override it.
- Default:
https://api.github.com. - Example:
https://github.example.com/api/v3 - Set it when: You use GitHub Enterprise Server.
SHIPLEAN_GITLAB_URL
Section titled “SHIPLEAN_GITLAB_URL”GitLab host whose merge request and issue links ShipLean reads. Links to other GitLab hosts remain ordinary page links. When this setting is unset, ShipLean does not read GitLab links.
- Default: Not set.
- Example:
https://gitlab.example.com - Set it when: You want live link cards for a self-hosted or selected GitLab host.
SHIPLEAN_GITLAB_TOKEN
Section titled “SHIPLEAN_GITLAB_TOKEN”GitLab token that can read merge requests and issues. ShipLean uses it only with SHIPLEAN_GITLAB_URL, and sends it only when that URL is HTTPS.
- Default: Not set.
- Example:
<gitlab-read-token> - Set it when: You need live link cards from a private GitLab project. A GitLab URL saved in Instance settings uses its own saved token instead.
Webhooks
Section titled “Webhooks”SHIPLEAN_GITHUB_WEBHOOK_SECRET
Section titled “SHIPLEAN_GITHUB_WEBHOOK_SECRET”Secret that ShipLean expects on GitHub webhook requests. Setting it enables POST /api/webhooks/github. Without it, that endpoint returns 404.
- Default: Not set. The endpoint is off.
- Example:
<github-webhook-secret> - Set it when: You configure the GitHub webhook so that pull requests can link to work items, show their state, and close linked items on merge.
SHIPLEAN_GITLAB_WEBHOOK_SECRET
Section titled “SHIPLEAN_GITLAB_WEBHOOK_SECRET”Secret that ShipLean expects on GitLab webhook requests. Setting it enables POST /api/webhooks/gitlab. Without it, that endpoint returns 404.
- Default: Not set. The endpoint is off.
- Example:
<gitlab-webhook-secret> - Set it when: You configure the GitLab webhook so that merge requests can link to work items, show their state, and close linked items on merge.
Multiple instances with Redis
Section titled “Multiple instances with Redis”SHIPLEAN_REDIS_CONNECTION
Section titled “SHIPLEAN_REDIS_CONNECTION”StackExchange.Redis connection string. With multiple ShipLean instances, Redis carries the SignalR backplane, along with shared presence and member-removal messages. The load balancer still needs sticky sessions, so that SignalR negotiate and WebSocket requests reach the same instance. Redis must be reachable when ShipLean starts.
- Default: Not set. Real-time state stays in each process.
- Example:
redis:6379,password=<redis-password>,channelPrefix=shiplean-prod - Set it when: You run more than one instance. If deployments share a Redis server, set a different
channelPrefixfor each. The default prefix isshiplean.
Logging with Seq
Section titled “Logging with Seq”SHIPLEAN_SEQ_URL
Section titled “SHIPLEAN_SEQ_URL”Address of the Seq server that receives application logs, in addition to the console.
- Default: Not set. Seq logging is off.
- Example:
http://seq:5341 - Set it when: You want ShipLean logs sent to your Seq server.
SHIPLEAN_SEQ_API_KEY
Section titled “SHIPLEAN_SEQ_API_KEY”API key that ShipLean uses to authenticate its connection to Seq.
- Default: Not set.
- Example:
<seq-api-key> - Set it when: Your Seq server requires an API key. Keep it in a secret store.
OpenTelemetry
Section titled “OpenTelemetry”ShipLean can export traces, metrics, and logs over OTLP to a collector or backend. Set OTEL_EXPORTER_OTLP_ENDPOINT to enable all three signals. Without an endpoint, OpenTelemetry export is off. Console logs and the optional Seq sink keep working as before.
OTEL_EXPORTER_OTLP_ENDPOINT
Section titled “OTEL_EXPORTER_OTLP_ENDPOINT”OTLP collector address. Setting this variable enables traces, metrics, and logs.
- Default: Not set. OTLP export is off.
- Example:
https://otel-collector.example.com - Set it when: You want ShipLean telemetry sent to an OTLP collector, Grafana Alloy, or another compatible backend.
OTEL_EXPORTER_OTLP_PROTOCOL
Section titled “OTEL_EXPORTER_OTLP_PROTOCOL”OTLP transport protocol. ShipLean supports grpc and http/protobuf. With http/protobuf, the exporter appends signal paths to the endpoint. For example, logs use /v1/logs.
- Default: Depends on the SDK. Usually
grpcorhttp/protobuf. - Example:
http/protobuf - Set it when: Your collector requires a particular transport. Choose one that it accepts.
OTEL_EXPORTER_OTLP_HEADERS
Section titled “OTEL_EXPORTER_OTLP_HEADERS”Comma-separated key=value headers sent with telemetry exports. Use it for collector credentials, such as an API key.
- Default: No additional headers.
- Example:
api-key=<collector-api-key> - Set it when: Your collector requires an API key or another request header. Keep credentials in a secret store.
OTEL_SERVICE_NAME
Section titled “OTEL_SERVICE_NAME”Value of the telemetry resource’s service.name attribute.
- Default:
shiplean. - Example:
shiplean-production - Set it when: You want this instance to use a different service name in your telemetry backend.
OTEL_RESOURCE_ATTRIBUTES
Section titled “OTEL_RESOURCE_ATTRIBUTES”Additional comma-separated key=value resource attributes added to telemetry.
- Default: No additional attributes.
- Example:
deployment.environment=production - Set it when: You want to label telemetry with deployment or environment details.
Jira import
Section titled “Jira import”SHIPLEAN_JIRA_ALLOW_LOCAL_ENDPOINTS
Section titled “SHIPLEAN_JIRA_ALLOW_LOCAL_ENDPOINTS”Allows local Jira import addresses, and permits plain HTTP to any host. Over HTTP, the token is sent without encryption.
- Default: Off, which is
false. - Example:
true - Set it when: Jira runs on your own network and you need to import from a local endpoint. Leave it off otherwise.
Search
Section titled “Search”SHIPLEAN_EMBEDDINGS
Section titled “SHIPLEAN_EMBEDDINGS”Controls semantic search. When a model is loaded, on ranks results by meaning as well as by words. off keeps search lexical, which means it matches words only.
- Default:
on. - Example:
off - Set it when: You want lexical-only search, for example when semantic embeddings are unavailable.
SHIPLEAN_EMBEDDINGS_MODEL_PATH
Section titled “SHIPLEAN_EMBEDDINGS_MODEL_PATH”Folder that contains the embedding model files. The published image sets this to /app/models/multilingual-e5-small.
- Default:
/app/models/multilingual-e5-smallin the published image. - Example:
/app/models/multilingual-e5-small - Set it when: You run the published image with a model mounted at a different path. An unreadable or missing model leaves search lexical, and
/healthreports the reason.
SHIPLEAN_SEARCH_CHUNK_CHARS
Section titled “SHIPLEAN_SEARCH_CHUNK_CHARS”Length in characters of each text chunk created for indexing.
- Default:
1200. - Example:
1200 - Set it when: You need to adjust the amount of text indexed as one chunk.
SHIPLEAN_SEARCH_CHUNK_OVERLAP
Section titled “SHIPLEAN_SEARCH_CHUNK_OVERLAP”Number of characters that consecutive indexed chunks repeat.
- Default:
150. - Example:
150 - Set it when: You need to adjust how much context adjacent chunks share.
SHIPLEAN_SEARCH_CUTOFF
Section titled “SHIPLEAN_SEARCH_CUTOFF”Lowest semantic similarity score, from 0 to 1, that counts as a meaning match.
- Default:
0.84for the published embedding model. - Example:
0.84 - Set it when: You need to tune the semantic match threshold.
SHIPLEAN_SEARCH_TOP_PER_LIST
Section titled “SHIPLEAN_SEARCH_TOP_PER_LIST”Maximum number of results kept from each ranked search list before merging.
- Default:
100. - Example:
100 - Set it when: You need to change how many candidates each list contributes.
SHIPLEAN_SEARCH_RRF_K
Section titled “SHIPLEAN_SEARCH_RRF_K”Reciprocal rank fusion constant that merges ranked result lists.
- Default:
60. - Example:
60 - Set it when: You need to tune how separate ranked lists are combined.
SHIPLEAN_SEARCH_BATCH
Section titled “SHIPLEAN_SEARCH_BATCH”Number of texts embedded in each model call.
- Default:
32. - Example:
32 - Set it when: You need to change how many texts are sent per embedding call.
SHIPLEAN_SEARCH_THREADS
Section titled “SHIPLEAN_SEARCH_THREADS”Number of ONNX Runtime intra-op threads used for embedding.
- Default:
1. - Example:
1 - Set it when: You need to change how many threads embedding uses on your host.
SHIPLEAN_SEARCH_FIRST_PASS_SECONDS
Section titled “SHIPLEAN_SEARCH_FIRST_PASS_SECONDS”Delay in seconds before the background indexer’s first pass after startup.
- Default:
20. - Example:
20 - Set it when: You need to change when the first indexing pass starts.
SHIPLEAN_SEARCH_INTERVAL_SECONDS
Section titled “SHIPLEAN_SEARCH_INTERVAL_SECONDS”Number of seconds between background indexer passes.
- Default:
60. - Example:
60 - Set it when: You need to change the interval between indexing passes.
Compose-only
Section titled “Compose-only”SHIPLEAN_PORT
Section titled “SHIPLEAN_PORT”Host port published for the ShipLean web app by the Compose setup.
- Default:
8080in the product Compose file. - Example:
8081 - Set it when: Host port 8080 is already in use, or you want a different local port.
SHIPLEAN_PG_PORT
Section titled “SHIPLEAN_PG_PORT”Host port published for PostgreSQL by the Compose setup.
- Default:
5432in the product Compose file. - Example:
5433 - Set it when: Host port 5432 is already in use, or you want a different local port.
The Compose table also has POSTGRES_PASSWORD, which sets PostgreSQL’s password. It is not a SHIPLEAN_* variable.