Skip to content

cproxy

Castis cproxy is a caching reverse proxy that sits in front of Streamer nodes. It handles origin routing, memory/file caching, and TTL rules per file extension.

Compose

cproxy_bkk_1:
  image: registry.mashup.castis.io/castis-images/image-storage/cproxy:v1
  platform: linux/amd64
  container_name: cproxy_bkk_1
  networks:
    - internal
  ports:
    - "28080:8080"   # proxy
    - "28081:8081"   # api
  volumes:
    - ./cdn/cproxy-bkk-1/cproxy.yml:/usr/local/castis/origin_cproxy/cproxy-new.yml
    - ./cdn/cproxy-bkk-1/logs:/data/log/cproxy
    - ./cdn/cproxy-bkk-1/filecache:/data/cproxy/filecache
  command: bash -c "cd /usr/local/castis/origin_cproxy && cp cproxy-new.yml cproxy.yml && ./cproxy"

Config mount workaround

The cproxy image entrypoint runs envsubst which overwrites the mounted config. The command override copies cproxy-new.ymlcproxy.yml before starting, bypassing the entrypoint issue.

Volume Reference

Host path Container path Purpose
cproxy.yml cproxy-new.yml (copied to cproxy.yml at startup) Config
logs/ /data/log/cproxy/ Log output
filecache/ /data/cproxy/filecache/ File cache persistence

Key Config

origins:
  - key: streamer-bkk
    url-pattern: ^/bkk/.*$
    url-rewriters:
      - match-pattern: ^/bkk/(.*)$
        replace: /$1
    origin-urls:
      - url: http://streamer_bkk:18080
    memcache-config-id: mem-cache
    ttl: 1s
    ttl-rules:
      - extensions: [.ts, .m4s, .mp4, .m4a, .aac]
        ttl: 30s
      - extensions: [.m3u8, .mpd]
        ttl: 500ms
    health-check:
      period: 5s
      timeout: 1s
    failover-responses: [404, 5xx]
    retry-count: 3
    balancing-policy: first-active

  - key: streamer-ntb
    url-pattern: ^/ntb/.*$
    url-rewriters:
      - match-pattern: ^/ntb/(.*)$
        replace: /$1
    origin-urls:
      - url: http://streamer_ntb:18080
    memcache-config-id: mem-cache
    ttl: 1s
    ttl-rules:
      - extensions: [.ts, .m4s, .mp4, .m4a, .aac]
        ttl: 30s
      - extensions: [.m3u8, .mpd]
        ttl: 500ms
    health-check:
      period: 5s
      timeout: 1s
    failover-responses: [404, 5xx]
    retry-count: 3
    balancing-policy: first-active

memcaches:
  - id: mem-cache
    size: 1G

filecaches:
  - id: file-cache
    cache-dir: /data/cproxy/filecache
    size: 10G

Warning

memcaches and filecaches must be defined in cproxy.yml at startup. Origins referencing a memcache-config-id that doesn't exist will cause cproxy to crash-loop with memcache-config-id not exists.

Origin Routing

urlPattern matches the first path segment. urlRewriters strips the prefix before forwarding to the streamer — the streamer never sees /bkk/ or /ntb/:

client  →  /bkk/ads/jet.mp4/fmp4.noll_manifest.mpd
cproxy  →  http://streamer_bkk:18080/ads/jet.mp4/fmp4.noll_manifest.mpd

Origin order matters — cproxy matches the first pattern that fits.

Runtime Origin Switching (v1.1.5+)

PUT /api/config/origins replaces the entire origins array at runtime and persists to disk. No restart needed.

Always GET first — fields omitted in the PUT body are dropped:

# 1. read current state
curl -s http://localhost:28081/api/config | jq .origins

# 2. push new origins array
curl -X PUT http://localhost:28081/api/config/origins \
  -H "Content-Type: application/json" \
  -d '[
    {
      "key": "streamer-bkk",
      "urlPattern": "^/bkk/.*$",
      "urlRewriters": [{"matchPattern": "^/bkk/(.*)$", "replace": "/$1"}],
      "originUrls": [{"url": "http://streamer_bkk:18080"}],
      "memCacheConfigId": "mem-cache",
      "ttl": "1s",
      "ttlRules": [
        {"extensions": [".ts", ".m4s", ".mp4", ".m4a", ".aac"], "ttl": "30s"},
        {"extensions": [".m3u8", ".mpd"], "ttl": "500ms"}
      ],
      "healthCheck": {"period": "5s", "timeout": "1s"},
      "failoverResponses": ["404", "5xx"],
      "retryCount": 3,
      "balancingPolicy": "first-active"
    },
    {
      "key": "streamer-ntb",
      "urlPattern": "^/ntb/.*$",
      "urlRewriters": [{"matchPattern": "^/ntb/(.*)$", "replace": "/$1"}],
      "originUrls": [{"url": "http://streamer_ntb:18080"}],
      "memCacheConfigId": "mem-cache",
      "ttl": "1s",
      "ttlRules": [
        {"extensions": [".ts", ".m4s", ".mp4", ".m4a", ".aac"], "ttl": "30s"},
        {"extensions": [".m3u8", ".mpd"], "ttl": "500ms"}
      ],
      "healthCheck": {"period": "5s", "timeout": "1s"},
      "failoverResponses": ["404", "5xx"],
      "retryCount": 3,
      "balancingPolicy": "first-active"
    }
  ]'

# 3. verify
curl -s http://localhost:28081/api/config | jq '.origins[] | {key, urlPattern}'

What can be changed at runtime via PUT: originUrls, urlPattern, urlRewriters, ttl, ttlRules, memCacheConfigId

Startup-only (set in yml, cannot change at runtime): balancingPolicy, healthCheck, retryCount, failoverResponses, memcaches, filecaches

API

# current config
curl http://localhost:28081/api/config | jq .

# traffic stats
curl http://localhost:28081/api/traffic | jq .

# purge cache for an origin key
curl -X DELETE http://localhost:28081/api/caches/streamer-bkk/*

# reload config from disk
curl -X PUT http://localhost:28081/api/config

Version Requirement

PUT /api/config/origins requires cproxy v1.1.5.rc1 or later. Earlier versions return 404 for this endpoint.