Tencent Cloud CDN refresh and push tool with explicit site and job management.
Get command help:
cdnfix -v
cdnfix --help
cdnfix init --help
cdnfix refresh --help
cdnfix push --help
cdnfix batch --help
cdnfix query --helpFor a general system installation, use fixed config, state, and log directories instead of relying on the current working directory.
Recommended layout:
/etc/cdnfix/
sites.yaml
jobs.yaml
urls/
prod-a/
refresh.txt
push.txt
prod-b/
refresh.txt
/var/lib/cdnfix/
cache/
runs/
/var/log/cdnfix/
Default config files:
/etc/cdnfix/sites.yaml/etc/cdnfix/jobs.yaml
Runtime output:
- task cache:
/var/lib/cdnfix/cache - run metadata:
/var/lib/cdnfix/runs - logs:
/var/log/cdnfix
Runtime behavior notes:
queryno longer writes a dedicated file log by default. It now emits its runtime log/output tostderr, which fitssystemdandjournalddirectly.- run records are no longer stored as one JSON file per execution.
cdnfixnow appends records into monthly JSONL files underruns/, for example/var/lib/cdnfix/runs/2026-05.jsonl. - Recommended retention split:
- use
logrotatefor/var/log/cdnfix/*/*.log - use
systemd-tmpfilesfor/var/lib/cdnfix/runs/*.jsonl
- use
Typical commands:
cdnfix init
cdnfix batch
cdnfix batch --job prod-a-refresh
cdnfix --site prod-a -f /etc/cdnfix/urls/prod-a/refresh.txt refresh
cdnfix --site prod-a -u https://example.com/a.js push
printf '%s\n' https://example.com/a.js | cdnfix --site prod-a push
cdnfix query
cdnfix --site prod-a queryWhen running under systemd, keep stdout/stderr attached to the service manager unless you explicitly want file logs. That lets query output land in journald without any extra wrapper.
refresh and push support three URL input methods:
--urls/-u: comma-separated URLs--urlfile/-f: one URL per line from a filestdin: one URL per line from a shell pipeline
When stdin is piped in, cdnfix reads from stdin first.
Examples:
# Comma-separated URLs
cdnfix --site prod-a -u https://example.com/a.js,https://example.com/b.css push
# Read from file
cdnfix --site prod-a -f /etc/cdnfix/urls/prod-a/refresh.txt refresh
# Read from stdin
printf '%s\n' https://example.com/a.js https://example.com/b.css | cdnfix --site prod-a push
cat /etc/cdnfix/urls/prod-a/refresh.txt | cdnfix --site prod-a refreshInitialize a fresh layout:
cdnfix init
cdnfix --root /opt/cdnfix init
cdnfix --root /opt/cdnfix --site-name prod-a initPath resolution should follow this order:
- CLI flags
--config-dir--state-dir--log-dir--root
- Environment variables
CDNFIX_CONFIG_DIRCDNFIX_STATE_DIRCDNFIX_LOG_DIRCDNFIX_ROOT
- Portable root shortcut
--rootorCDNFIX_ROOTmaps to a self-contained layout under one directory
- System defaults
- config:
/etc/cdnfix - state:
/var/lib/cdnfix - logs:
/var/log/cdnfix
- config:
Use explicit CLI flags or environment variables when the installation does not follow the system defaults.
git clone https://github.com/zzerding/cdnfix.git- cd cdnfix
- go run main.go
- go install github.com/zzerding/cdnfix
- cdnfix
1.use -e args
docker run -rm -v $PWD:/app -e SECRET_ID=xxx -e SECRET_KEY=xxx zzerding/refresh-cnd
- save cache to local
docker run --rm --env-file=.env -v $(PWD)/.task_push.cache:/root/.task_push.cache -v $(PWD)/.task_refresh.cache:/root/.task_refresh.cache zzerding/cdnfix -u https://www.xxxx.com/join/ push
- query status
docker run --rm --env-file=.env -v $(PWD)/.task_push.cache:/root/.task_push.cache -v $(PWD)/.task_refresh.cache:/root/.task_refresh.cache zzerding/cdnfix query
System install example: /etc/cdnfix/sites.yaml
sites:
prod-a:
secret_id: your-secret-id
secret_key: your-secret-key
region: ap-guangzhou
prod-b:
secret_id: your-secret-id
secret_key: your-secret-key
region: ap-shanghaiSingle-site .env fallback is still supported when you only need one site.
System install example: /etc/cdnfix/jobs.yaml
jobs:
- name: prod-a-refresh
site: prod-a
action: refresh
file: ./urls/prod-a/refresh.txt
- name: prod-b-push
site: prod-b
action: push
file: ./urls/prod-b/push.txtfile paths are resolved relative to the manifest file, not relative to the shell working directory.
That means file: ./urls/prod-a/refresh.txt in /etc/cdnfix/jobs.yaml resolves to /etc/cdnfix/urls/prod-a/refresh.txt.
Portable deployment is still supported. In that mode, keep everything under one directory and pass --root explicitly.
Example layout:
/opt/cdnfix/
cdnfix
config/
sites.yaml
jobs.yaml
urls/
prod-a/
refresh.txt
var/
lib/
cache/
runs/
log/
Portable examples:
cdnfix --root /opt/cdnfix batch
cdnfix --root /opt/cdnfix --site prod-a -f /opt/cdnfix/config/urls/prod-a/refresh.txt refresh
cdnfix --root /opt/cdnfix queryWith --root /opt/cdnfix, the portable layout is:
- site config:
/opt/cdnfix/config/sites.yaml - jobs manifest:
/opt/cdnfix/config/jobs.yaml - task cache:
/opt/cdnfix/var/lib/cache - run metadata:
/opt/cdnfix/var/lib/runs - logs:
/opt/cdnfix/var/log
runs/ uses the same monthly JSONL append format in portable mode, for example /opt/cdnfix/var/lib/runs/2026-05.jsonl.
Recommended system installation:
- application log files under
/var/log/cdnfix/*/*.logare rotated bylogrotate - monthly run ledgers under
/var/lib/cdnfix/runs/*.jsonlare expired bysystemd-tmpfiles queryoutput is read fromstderr/journald, not from a dedicated query log file
Install the sample policies from this repository:
install -Dm0644 deploy/logrotate/cdnfix /etc/logrotate.d/cdnfix
install -Dm0644 deploy/tmpfiles/cdnfix.conf /etc/tmpfiles.d/cdnfix.conf
systemd-tmpfiles --create /etc/tmpfiles.d/cdnfix.confReview the retention window before enabling it in production. The shipped examples keep rotated log files for a limited period and remove old monthly runs/*.jsonl files after 90 days.
Common checks:
journalctl -u cdnfix.service -e
ls -lh /var/log/cdnfix/
ls -lh /var/lib/cdnfix/runs/
systemd-tmpfiles --clean /etc/tmpfiles.d/cdnfix.conf
logrotate -d /etc/logrotate.d/cdnfixRun tests:
go test ./...