https://github.com/mc256/honkai-rule-server
Self-hosted Mihomo/Clash subscription aggregator: merges multiple upstream sources, applies custom routing rules, and serves a unified config to clients.
https://github.com/mc256/honkai-rule-server
clash go kubernetes mihomo subscription-aggregator
Last synced: 26 days ago
JSON representation
Self-hosted Mihomo/Clash subscription aggregator: merges multiple upstream sources, applies custom routing rules, and serves a unified config to clients.
- Host: GitHub
- URL: https://github.com/mc256/honkai-rule-server
- Owner: mc256
- License: mit
- Created: 2026-05-08T01:28:27.000Z (about 1 month ago)
- Default Branch: master
- Last Pushed: 2026-05-08T05:19:30.000Z (about 1 month ago)
- Last Synced: 2026-05-08T06:31:18.476Z (about 1 month ago)
- Topics: clash, go, kubernetes, mihomo, subscription-aggregator
- Language: Go
- Size: 816 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 5
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# honkai-rule-server
A small Go service that aggregates multiple Mihomo / Clash subscription URLs into a single token-authenticated subscription endpoint. Adds operator-declared own-proxies, exposes aggregated traffic quota in the standard `Subscription-Userinfo` header, and reports a per-source-weighted daily allowance via `/health`.
## Documentation
- **Spec**: [`specs/001-subscription-aggregator/spec.md`](specs/001-subscription-aggregator/spec.md) — what this service does and why
- **Plan**: [`specs/001-subscription-aggregator/plan.md`](specs/001-subscription-aggregator/plan.md) — tech stack, project layout, test plan
- **Quickstart**: [`specs/001-subscription-aggregator/quickstart.md`](specs/001-subscription-aggregator/quickstart.md) — go from zero to a running merged subscription
- **Tasks**: [`specs/001-subscription-aggregator/tasks.md`](specs/001-subscription-aggregator/tasks.md) — implementation task list
- **Constitution**: [`.specify/memory/constitution.md`](.specify/memory/constitution.md) — non-negotiable engineering principles for this repo
## Layout
```
cmd/server/ entry point
internal/
clock/ Clock interface (RealClock + FakeClock for deterministic tests)
config/ subscriptions CSV / own-proxies YAML / tokens JSON / server env loaders
fetcher/ per-source background fetch + cache + bootstrap state machine
merge/ pure-functional transformation core (proxies, proxy-groups, rules, traffic)
output/ subscription-mode adapter (renders the served Clash YAML)
observability/ log/slog + token sanitization
server/ net/http app + auth middleware + routes
integration/ cross-package integration + snapshot tests
templates/ served-config template (Clash globals)
config/ operator config (gitignored — see config/README.md)
deploy/k8s/ Kubernetes manifests
example/ sandbox / sample inputs (NOT imported by the server)
```
## Build & test
```bash
make build # → bin/server
make test # all tests
make test-race # all tests + race detector
make snapshot-update # accept new committed snapshot baselines (requires PR review)
make check # CI gate: vet + lint + test + verify clean working tree
```
See the [quickstart](specs/001-subscription-aggregator/quickstart.md) for end-to-end run instructions.
## Run locally
```bash
# Copy fixtures as a starting point
cp internal/integration/testdata/fixtures/subscriptions.csv config/
cp internal/integration/testdata/fixtures/own-proxies.yaml config/
cp internal/integration/testdata/fixtures/tokens.json config/
# Edit config/subscriptions.csv to point at your real upstream URLs.
make build
SUBSCRIPTIONS_CSV_PATH=./config/subscriptions.csv \
OWN_PROXIES_YAML_PATH=./config/own-proxies.yaml \
TOKENS_PATH=./config/tokens.json \
SERVED_CONFIG_TEMPLATE_PATH=./templates/served-config.template.yaml \
CACHE_DIR=./.cache PORT=8080 LOG_LEVEL=info \
./bin/server
```
Then `curl 'http://localhost:8080/?token='` returns the merged Clash YAML.
See the [quickstart](specs/001-subscription-aggregator/quickstart.md) for the full operator workflow including K8s deployment.
## Deployment (Kubernetes)
Manifests under [`deploy/k8s/`](deploy/k8s/):
```bash
# 1. Stuff the three secret-bearing files into a Secret
kubectl create secret generic honkai-rule-server-config \
--from-file=subscriptions.csv=./config/subscriptions.csv \
--from-file=own-proxies.yaml=./config/own-proxies.yaml \
--from-file=tokens.json=./config/tokens.json
# 2. Apply manifests
kubectl apply -f deploy/k8s/configmap-served-template.yaml
kubectl apply -f deploy/k8s/deployment.yaml
kubectl apply -f deploy/k8s/service.yaml
kubectl apply -f deploy/k8s/ingress.yaml # edit hostname first
```
The Ingress handles TLS termination per FR-019c. **Only `/` is exposed** to the public internet; `/health` is intentionally omitted (it leaks per-upstream state). Hit `/health` from the cluster-internal Service.
## Constitution + spec coverage
- All 5 Constitution principles (Unified Transformation Core, Deterministic Transformation, CSV strict-schema/loud-failure, Test-First/Real-Input Integration, Observable Routing & Source-Merge Decisions) — gates pass; see plan.md Constitution Check.
- All 27 functional requirements (FR-001..FR-019c) and 15 success criteria (SC-001..SC-015) implemented and tested. See [`specs/001-subscription-aggregator/spec.md`](specs/001-subscription-aggregator/spec.md).
- Three deterministic snapshots committed under `internal/integration/testdata/snapshots/` pin the served-config body, the `Subscription-Userinfo` wire format, and the `/health` JSON response shape (Constitution Principle II).
## Module path
The committed `go.mod` uses a placeholder owner (`github.com/junlinchen/honkai-rule-server`). After creating the actual GitHub repo, run:
```bash
go mod edit -module github.com//honkai-rule-server
go mod tidy
goimports -w . # update import paths in any code that referenced the old path
```