Configure a reverse proxy to expose Crow CI with TLS termination.
| Port | Service | Required |
|---|
| 8000 | Web UI and API | Yes |
| 9000 | GRPC (agent communication) | Only for remote agents |
Crow reads the client IP from the X-Forwarded-For and X-Real-IP headers.
It uses the IP to rate-limit failed LDAP sign-ins.
Without CROW_TRUSTED_PROXIES Crow trusts those headers from any client, so a client can fake its address and avoid the per-IP limit.
Set CROW_TRUSTED_PROXIES to the IP addresses or CIDR ranges of your reverse proxies:
CROW_TRUSTED_PROXIES=10.0.0.0/8,192.168.1.10
The server refuses to start when an entry is not a valid IP address or CIDR range.
It logs a warning at startup when LDAP is enabled and the variable is unset.
# Web UI
crow.example.com {
reverse_proxy crow-server:8000
}
# GRPC (optional - for remote agents)
grpc.crow.example.com {
reverse_proxy h2c://crow-server:9000
}
server {
listen 443 ssl;
server_name crow.example.com;
ssl_certificate /path/to/cert;
ssl_certificate_key /path/to/key;
location / {
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_pass http://127.0.0.1:8000;
proxy_redirect off;
proxy_http_version 1.1;
proxy_buffering off;
chunked_transfer_encoding off;
}
}
# GRPC (optional - for remote agents)
server {
listen 443 ssl;
server_name grpc.crow.example.com;
ssl_certificate /path/to/cert;
ssl_certificate_key /path/to/key;
location / {
grpc_pass grpc://127.0.0.1:9000;
}
}
Docker Compose with TLS termination and HTTP→HTTPS redirect:
services:
server:
image: codefloe.com/crowci/crow-server:v4
networks:
- traefik
volumes:
- crow-data:/var/lib/crow
deploy:
labels:
- traefik.enable=true
# Web UI
- traefik.http.services.crow.loadbalancer.server.port=8000
- traefik.http.routers.crow-secure.rule=Host(`crow.example.com`)
- traefik.http.routers.crow-secure.tls=true
- traefik.http.routers.crow-secure.tls.certresolver=letsencrypt
- traefik.http.routers.crow-secure.entrypoints=web-secure
- traefik.http.routers.crow-secure.service=crow
# HTTP redirect
- traefik.http.routers.crow.rule=Host(`crow.example.com`)
- traefik.http.routers.crow.entrypoints=web
- traefik.http.middlewares.crow-redirect.redirectscheme.scheme=https
- traefik.http.routers.crow.middlewares=crow-redirect@docker
# GRPC (optional - for remote agents)
- traefik.http.services.crow-grpc.loadbalancer.server.port=9000
- traefik.http.services.crow-grpc.loadbalancer.server.scheme=h2c
- traefik.http.routers.crow-grpc-secure.rule=Host(`grpc.crow.example.com`)
- traefik.http.routers.crow-grpc-secure.tls=true
- traefik.http.routers.crow-grpc-secure.tls.certresolver=letsencrypt
- traefik.http.routers.crow-grpc-secure.entrypoints=web-secure
- traefik.http.routers.crow-grpc-secure.service=crow-grpc
networks:
traefik:
external: true
Crow’s event and log streams stay open for as long as the web UI is open, so a gateway must not limit how long a response may take.
Envoy Gateway ends every HTTP request after 15 seconds by default.
The web UI then reconnects and refetches its data on that schedule, and it misses events between reconnects.
Disable the request timeout on the route that serves the web UI:
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: crow
spec:
parentRefs:
- name: my-gateway
hostnames:
- ci.example.com
rules:
- backendRefs:
- name: crow
port: 80
timeouts:
request: 0s
The Helm chart can create this route for you.
Remote agents connect over gRPC, and a GRPCRoute has no standard timeout field.
On Envoy Gateway, disable the timeout for the route with a BackendTrafficPolicy:
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: BackendTrafficPolicy
metadata:
name: crow-grpc
spec:
targetRefs:
- group: gateway.networking.k8s.io
kind: GRPCRoute
name: crow-grpc
timeout:
http:
requestTimeout: '0s'
frontend https_in
mode http
bind :::443 v4v6 ssl crt /path/to/cert
acl is_crow hdr(host) -i crow.example.com
acl is_crow_grpc hdr(host) -i grpc.crow.example.com
use_backend crow if is_crow
use_backend crow_grpc if is_crow_grpc
backend crow
mode http
balance roundrobin
http-request del-header X-Forwarded-For
http-request del-header X-Real-IP
option forwardfor
server crow 127.0.0.1:8000 maxconn 100000 check
backend crow_grpc
mode http
server crow_grpc 127.0.0.1:9000 maxconn 100000 no-check proto h2
Required modules: proxy, proxy_http
ProxyPreserveHost On
RequestHeader set X-Forwarded-Proto "https"
ProxyPass / http://127.0.0.1:8000/
ProxyPassReverse / http://127.0.0.1:8000/