Skip to content
Crow CI

Reverse Proxy

Configure a reverse proxy to expose Crow CI with TLS termination.

PortServiceRequired
8000Web UI and APIYes
9000GRPC (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/