04/Documentation
Dağıtım varyantları B–E
Varsayılan dışındaki giriş kapıları: kimlik algılayıcı proxy, Tailscale içermeyen bir ters proxy, sunucu dışı bir ingress, tek bir sunucuda birden fazla Collie (kullanıcı başına bir tane veya tek bir kullanıcı için birden fazla örnek) ve bir crew'un yedek kapısı
Köprü 127.0.0.1 adresine bağlanır. Dağıtımlar, giriş ve kimlik doğrulama yöntemlerine göre farklılık gösterir. Varyant A (yalın tailscale serve) README içindedir. docs/security.md içindeki güvenlik gereksinimleri tüm biçimler için geçerlidir.
Münferit cihazlar, eşleme üzerinden bir proxy olmadan da yetkilendirilebilir.
---
Varyant B: kimlik algılayıcı proxy + cihaz başına yetkilendirme
Collie, COLLIE_DEVICE_HEADER başlığından opak bir cihaz kimliği okur ve COLLIE_DEVICE_ALLOWLIST değerini kontrol eder. İzin verilen kimlikler yazma erişimi alır; eksik veya listede bulunmayan kimlikler salt okunur erişim alır (okumalar, anlık görüntüler, oturum listeleri açık kalır; terminal girdisi, yüklemeler ve bölme eylemleri engellenir).
Collie yapılandırması (.env):
COLLIE_HOST=127.0.0.1 # keep loopback (default)
COLLIE_DEVICE_HEADER=X-Device-Id # the header your proxy injects
# ids allowed to drive agents; others → read-only
COLLIE_DEVICE_ALLOWLIST=my-phone,my-laptop
# only if the proxy does NOT forward the public Host
# COLLIE_ALLOWED_ORIGINS=https://collie.example.com
# REQUIRED unless the proxy forwards a Host Collie already knows: loopback, a
# discovered Tailscale host, or an allowed origin's host
# COLLIE_PUBLIC_HOSTS=collie.example.com
# opt out of Host validation entirely (re-opens DNS rebinding)
# COLLIE_ALLOW_ANY_HOST=1
# COLLIE_TRUSTED_USER still composes on top if your ingress also injects
# Tailscale-User-Login
# accept a request carrying no Tailscale-User-Login at all
# COLLIE_TRUSTED_USER_OPTIONAL=1Proxy gereksinimleri:
- Cihazı doğrulayın (mTLS, SSO, forward-auth).
- İstemci sahteciliğini önlemek için yukarı akışa giden her istekte Cihaz başlığını geçersiz kılın.
- Loopback'e proxy yapın (
127.0.0.1:$COLLIE_PORT). - Genel
Hostdeğerini değiştirmeden iletin veya aynı kaynak denetimini geçmek için genel kaynağıCOLLIE_ALLOWED_ORIGINSiçinde listeleyin.
Örnek Nginx yapılandırması:
location / {
proxy_set_header X-Device-Id $device_id;
proxy_set_header Host $host;
proxy_pass http://127.0.0.1:8787;
}Harici bir cihazdan başlık ekleme ve geçersiz kılma işlemlerini doğrulayın:
$ curl -s https://collie.example.com/api/snapshot | jq -c .device
{"enforced":true,"device":"my-laptop","authorized":true}
$ curl -s -H 'X-Device-Id: my-phone' https://collie.example.com/api/snapshot | jq -c .device
{"enforced":true,"device":"my-laptop","authorized":true}İkinci denetim "device":"my-phone" döndürürse, proxy geçersiz kılmak yerine sonuna ekleme yapıyordur.
Operasyonel notlar:
- Doğrudan loopback erişimi (
http://127.0.0.1:$COLLIE_PORT) başlık göndermez ve salt okunurdur. - curl aracılığıyla yerel olarak komut yürütmek için başlığı loopback'e açıkça iletin:
curl -H 'X-Device-Id: my-laptop' http://127.0.0.1:$COLLIE_PORT/api/... - Kimliği
COLLIE_DEVICE_ALLOWLISTdosyasından kaldırarak ve yeniden başlatarak erişimi iptal edin (Standalone:bin/collie restart; Herdr:herdr plugin action invoke restart --plugin herdr.collie). - Yalın
tailscale serveüzerindeCOLLIE_DEVICE_HEADERseçeneğini etkinleştirmeyin; başlıkları geçersiz kılmaz.
---
Varyant C: tek ön kapı olarak ters proxy (Tailscale yok)
Tailscale dışında veya özel bir TLS/SSO proxy'si arkasında çalışırken bunu kullanın. COLLIE_SKIP_SERVE=1, Collie'nin tailscale serve yönetimini engeller.
B Varyantı altındaki dört proxy gereksinimi geçerlidir.
Örnek Caddy yapılandırması:
collie.example.com {
reverse_proxy 127.0.0.1:8787 {
header_up X-Device-Id {your_device_id}
header_up Host {host}
}
}Collie yapılandırması (.env):
# proxy is ingress; never run tailscale serve
COLLIE_SKIP_SERVE=1
# REQUIRED — Host validation fails closed, and `collie start` discovers no
# tailnet name here
COLLIE_PUBLIC_HOSTS=collie.example.com
# opt out of Host validation (re-opens DNS rebinding)
# COLLIE_ALLOW_ANY_HOST=1
# exact public origin for the same-origin gate
COLLIE_ALLOWED_ORIGINS=https://collie.example.com
COLLIE_DEVICE_HEADER=X-Device-Id # the header your proxy injects…
# …and the ids allowed to drive; others → read-only
COLLIE_DEVICE_ALLOWLIST=my-phone,my-laptop
# optional — status banner, `collie qr`, and the address a lead hands
# joining machines (crew)
# COLLIE_PUBLIC_URL=https://collie.example.comCOLLIE_TRUSTED_USER ayarının Tailscale olmadan hiçbir etkisi yoktur. Cihaz başına başlıklar veya proxy'nin kendi kimlik doğrulaması erişim kapısı görevi görür.
/auth/ yönlendirme ve önbelleğe alma
/sw.jsveindex.htmlistekleriniCache-Controlkaynağı ile iletin (no-cache). Kimliği doğrulanmamış istemcilere statik varlıkları engellemeyin, aksi takdirde service worker'lar güncellenemez.- Kimlik doğrulama akışlarını
/auth/*(veya Cloudflare Access için/cdn-cgi/access/) altına yönlendirin. Service worker'lar/auth/*için önbelleğe almayı atlar. - API isteklerindeki forward-auth yönlendirmeleri, giriş arayüzünü göstermek için 401 olarak değerlendirilir. Authentik kurulumları
/auth/adresini/outpost.goauthentik.io/startadresine yönlendirmelidir.
collie.example.com {
handle /auth/* {
reverse_proxy 127.0.0.1:9091
}
handle {
forward_auth 127.0.0.1:9091 { ... }
reverse_proxy 127.0.0.1:8787 { ... }
}
}Uç noktayı ve önbelleğe alma kurallarını doğrulayın:
$ curl -s https://collie.example.com/api/snapshot | jq -c .device
{"enforced":true,"device":"my-phone","authorized":true}
$ curl -sI https://collie.example.com/sw.js | grep -i '^cache-control'
cache-control: no-cache---
Varyant D: tailnet üzerinden sunucu dışı kimlik proxy'si
Trafiği merkezi bir Tailscale giriş düğümü üzerinden yönlendirirken bunu kullanın.
Proxy'nin geri döngü yerine ana bilgisayarın Tailscale HTTP uç noktasını hedeflemesi dışında, B Varyantı içindeki gereksinimler geçerlidir.
Tailscale ACL'leri (Zorunlu)
tailscale serve istemci başlıklarını değiştirmeden ilettiğinden, Tailscale ACL'leri doğrudan bağlantı noktası erişimini yalnızca giriş düğümüyle sınırlandırmalıdır.
Tailscale / Headscale ≥ 0.29:
"grants": [
{ "src": ["tag:ingress"], "dst": ["tag:agent-host"], "ip": ["tcp:8787"] },
]Headscale ≤ 0.28:
acls:
- action: accept
src: ["ingress-node"]
dst: ["agent-host:8787"]
- action: accept
src: ["my-phone", "my-laptop"]
dst: ["agent-host:1-8786", "agent-host:8788-65535"]Collie yapılandırması (.env):
# proxy terminates TLS; this hop is tailnet-internal
COLLIE_SERVE_MODE=http
COLLIE_HOST=127.0.0.1 # keep loopback (default)
# header your forward-auth injects — REQUIRED here
COLLIE_DEVICE_HEADER=X-Tailnet-Device
# ids allowed to drive; others + header-less → read-only
COLLIE_DEVICE_ALLOWLIST=my-phone,my-laptop
# REQUIRED — the Host the proxy forwards. COLLIE_TAILSCALE_HOSTS carries the bare
# tailnet name `collie start` found; a rewritten Host is yours to list.
# COLLIE_ALLOW_ANY_HOST=1 opts out.
COLLIE_PUBLIC_HOSTS=host:8787,host.your-tailnet.ts.net:8787
# the public origin the browser actually uses
COLLIE_ALLOWED_ORIGINS=https://collie.example.comCOLLIE_TRUSTED_USER, arkasındaki son kullanıcıyı değil, giriş düğümünün kimliğini eşler.
Doğrulama:
Giriş olmayan bir tailnet eşinden:
$ curl -s https://collie.example.com/api/snapshot | jq -c .device
{"enforced":true,"device":"my-phone","authorized":true}
$ curl -s --max-time 10 -H 'X-Tailnet-Device: my-phone' http://host.your-tailnet.ts.net:8787/api/snapshot
curl: (28) Connection timed outAjan ana bilgisayarında:
$ curl -s http://127.0.0.1:8787/api/snapshot | jq -c .device
{"enforced":true,"device":null,"authorized":false}---
Varyant E: diğer herhangi bir mesh veya tünel (NetBird, ZeroTier, Cloudflare Tunnel)
Tüneli/proxy'yi 127.0.0.1:$COLLIE_PORT adresine yönlendirin.
Collie yapılandırması (.env):
COLLIE_SKIP_SERVE=1 # never run tailscale serve
# REQUIRED — exact public host; Host validation fails closed and finds no
# tailnet name here
COLLIE_PUBLIC_HOSTS=collie.example.com
# exact public origin for the same-origin gate
COLLIE_ALLOWED_ORIGINS=https://collie.example.comKurallar:
- B Varyantı proxy kurallarını uygulayın.
COLLIE_TRUSTED_USER, Tailscale olmadan devre dışıdır.COLLIE_DEVICE_HEADERveya tünelin kimlik doğrulamasını kullanın.- PWA önbelleğe almanın ve
COLLIE_PUBLIC_HOSTSayarının geçerli kalması için statik bir ana bilgisayar adı kullanın.
---
Tek bir ana makinede birden fazla Collie
Paylaşılan bir sistemde kullanıcı başına bağımsız örnekler barındırmak için (ADR 0001):
# ~/.config/herdr/plugins/config/herdr.collie/.env — one per Unix user
# this user's loopback bridge port — unique per user
COLLIE_PORT=8801
# this user's tailnet https listener — unique per user
COLLIE_SERVE_PORT=8443
COLLIE_TRUSTED_USER=dev-a@example.com # only this tailnet login may drive these agentsBağımsız ikili URL kontrolü: bin/collie url. Herdr eklentisi URL kontrolü: herdr plugin action invoke url --plugin herdr.collie.
Gereksinimler:
- Farklı Unix kullanıcıları ve ayrı
herdr/Collie örnekleri çalıştırın. - Bağlantı noktası başına erişimi kısıtlamak için her zaman
COLLIE_TRUSTED_USERayarlayın. - İlk Tailscale bağlamaları operatör kurulumu gerektirir:
bin/collie serve(veya Herdr eşdeğeri) komutunu operatör ayrıcalıklarıyla çalıştırın.
COLLIE_SERVE_PORT, bir örneğin giriş bağlantı noktasını ayarlar. COLLIE_INSTANCE, aynı ana bilgisayarda kendi servis birimi ve yapılandırması olan yalıtılmış bir örnek oluşturur (Tek bir konakta birden fazla Collie örneği).
---
Tek bir konakta birden fazla Collie örneği
Aynı makinede ikinci ve farklı bir Collie çalıştırmak için bu kurulumu kullanın. Kararlı bir sürümü çalışan bir kopyanın yanında çalıştırmak veya Herdr tarafından yönetilen varsayılanın yanında ikinci bir çoklayıcı (tmux/zellij) çalıştırmak buna örnektir. Her örnek özel bir bağlantı noktası, yapılandırma, durum dizini ve servis birimi alır. Bu, Unix kullanıcısı başına bir örnek ayıran Tek bir ana makinede birden fazla Collie yönteminden farklıdır. Burada tek bir kullanıcı birden fazla örnek çalıştırır.
İkinci örneği oluşturun
Örneği adlandırmak için COLLIE_INSTANCE=<name> ayarlayın. Ad [a-z0-9-]{1,16} ile eşleşmelidir. Adlandırılmış bir örnek ayrıca açık bir COLLIE_PORT gerektirir. Bu bağlantı noktası eksikse CLI bir hatayla çıkar; hiçbir varsayılan değer çıkarımı yapmaz.
~/.config/herdr/plugins/config/herdr.collie-<name>/.env oluşturun:
COLLIE_INSTANCE=<name> # required — [a-z0-9-], max 16 chars
COLLIE_PORT=8788 # required for a named instance — no default is inferred
# Unset, this defaults to ~/.local/state/collie, with no instance suffix
COLLIE_STATE_DIR=/home/you/.local/state/collie-<name>COLLIE_INSTANCE, COLLIE_PORT ve COLLIE_STATE_DIR değerlerinin tümü bu .env dosyasında bulunabilir. Birleştirilen ortam örneği çözer. HERDR_PLUGIN_CONFIG_DIR, CLI'nın yapılandırmayı aradığı dizini geçersiz kılar.
Örnek başına bir servis birimi çalıştırın
collie start, ortam örneği belirlediğinde birimi yazar. Operatör bunu elle yazmaz. macOS üzerinde bunun yerine ~/Library/LaunchAgents/ altına bir launchd plist yazar. Birim COLLIE_PORT, COLLIE_INSTANCE, COLLIE_PLUGIN_ROOT, HERDR_PLUGIN_CONFIG_DIR ve EnvironmentFile=-<config dir>/.env değerlerini ayarlar. ExecStart üzerindeki --instance <name>, yalnızca tek bir ikili dosyayı paylaşan iki örneğin kendi köprülerini ayırt edebilmesi için mevcuttur (cli/unit.ts systemdUnit()):
ExecStart=<root>/bin/collie _exec-bridge --instance <name>
Environment=COLLIE_PORT=8788
Environment=COLLIE_INSTANCE=<name>
Environment=COLLIE_PLUGIN_ROOT=<root>
Environment=HERDR_PLUGIN_CONFIG_DIR=<config dir>
EnvironmentFile=-<config dir>/.envCLI, örnek başına bir tailscale serve işleyici dosyası tutar; bu sayede bir örnek üzerinde unserve çalıştırmak başka bir örneğin eşlemesini silmez.
CLI'dan adlandırılmış bir örneği hedefleyin
Her CLI fiili (pair, devices, url, qr, crew …, logs, push-test, …) hedef örneğini süreç ortamından çözer. Fiili çağırmadan önce COLLIE_INSTANCE değerini ayarlayın:
COLLIE_INSTANCE=next bin/collie pair
COLLIE_INSTANCE=next bin/collie devices listCOLLIE_INSTANCE olmadan CLI, Herdr'ı sorgular. Herdr yalnızca soneksiz eklentiyi izler, bu nedenle komut ilk örneğe karşı yürütülür. Yanlış örneği değiştirmeyi önlemek için tek bir ana bilgisayarda birden fazla örnek çalıştırırken COLLIE_INSTANCE değerini her zaman açıkça ayarlayın.
Reddetme kuralı
COLLIE_INSTANCE ayarlanmışsa ancak herdr.collie-<name>/.env eksikse CLI bir hata vererek çıkar. Başka bir örneğin yapılandırmasına geri dönmez.
Eşleştirme örnek başınadır
collie pair, eşleştirme kodunu söz konusu örneğin durum dizinine yazar. Yazdırdığı QR, o örneğin kendi URL'sini kodlar; çünkü her örneğin kendi durum dizini ve COLLIE_PUBLIC_URL veya kendi bağlantı noktası aracılığıyla kendi ön kapısı vardır. Telefonda söz konusu örneğin özel URL'sini açın ve kodu Ayarlar → Eşlenen cihazlar altına girin. Bir örnek için üretilen kod, bir cihazı başka bir örnekle eşleştiremez (Bir cihazı eşleyin).
---
Yedek kapı: bir ekibin yük devretme yolu
crew dağıtımları içindir. Lider erişilemez hale gelirse görevi devralması için önceden yetkilendirilmiş bir deputy yapılandırır (ADR 0027, ADR 0028, CREW_PROTOCOL.md §18).
Deputy ve lider ayarları:
| Anahtar | Varsayılan | İşlevi |
|---|---|---|
COLLIE_STANDBY_PORT | (ayarlanmamış) | Bekleme dinleyicisinin bağlantı noktası. Ayarlanmaması bekleme kapısını devre dışı bırakır. Lider ve deputy üzerinde eşleşmelidir. |
COLLIE_STANDBY_HOST | 127.0.0.1 | Bağlanma adresi (yerel vekiller için 127.0.0.1, uzak için örtü ağı IP'si). |
COLLIE_STANDBY_ARM_MS | max(30000, 2.5 × COLLIE_POLL_IDLE_MS) | Devreye girmeden önce gereken lider sessizlik süresi. |
Hem lider hem de deputy üzerinde COLLIE_STANDBY_PORT değerini aynı ve kullanılmayan bir bağlantı noktasına ayarlayın.
Ön koşul: bir ana bilgisayar adı, iki arka uç
PWA kaydını ve cihaz kimlik bilgilerini paylaşmak için lider ve deputy aynı kaynaktan sunulmalıdır. Birleşik giriş noktası olmayan bağımsız bir ekip bin/collie promote aracılığıyla kurtarılır (veya Herdr: herdr plugin action invoke promote --plugin herdr.collie; CREW_PROTOCOL §14.4).
Örnek Traefik yapılandırması:
http:
routers:
collie:
rule: "Host(`collie.example.com`)"
service: collie-crew
tls: {}
services:
collie-crew:
failover:
service: collie-lead
fallback: collie-deputy
collie-lead:
loadBalancer:
servers:
- url: "http://lead.internal:8787"
healthCheck:
path: /standby/health
interval: 5s
timeout: 2s
collie-deputy:
loadBalancer:
servers:
- url: "http://deputy.internal:8788" # COLLIE_STANDBY_PORT
healthCheck:
path: /standby/health
interval: 5s
timeout: 2sSistem durumu denetimi yanıtları: lider 200 döndürür (görevden alındığında 200 harici); deputy devreye girene kadar 503, ardından 200 döndürür.
Her şey sağlıklıyken bir kez kurun
Lider üzerinde bağımsız kurulum:
bin/collie pair
bin/collie crew deputy nas
bin/collie crew statusLider üzerinde Herdr kurulumu:
herdr plugin action invoke pair --plugin herdr.collie
herdr plugin action invoke crew --plugin herdr.collie deputy nas
herdr plugin action invoke crew --plugin herdr.collie statusDeputy üzerinde COLLIE_STANDBY_PORT=8788 yapılandırın ve yeniden başlatın. Deputy warrant dosyasını yüklemek için tüm eşlerin yeniden başlatıldığından emin olun. https://collie.example.com/standby adresinde doğrulayın.
⚠️ deputy denetlenmelidir
Devralma sırasında deputy durumu yazar ve süreç yeniden başlatmasını (bridge/index.ts) tetiklemek için 75 (EX_TEMPFAIL) durum koduyla çıkar.
Denetleyicinin sıfır dışı çıkış kodlarında yeniden başladığından emin olun (systemd: Restart=always veya Restart=on-failure).
Kötü gün: Çalışma kitabı
https://collie.example.comadresini açın.- lead sağlıksız olduğunda proxy
/standbyadresine yönlendirir. - deputy bekleme durumunu inceleyin.
- Devral seçeneğini belirleyin.
- deputy eş konsensüsünü doğrular, warrant uygular ve
75koduyla çıkar. - Denetleyici süreci yeniden başlatır; PWA yeni lead olarak yeniden yüklenir.
Kurtarma sonrası:
- Görevden alınan düğümün eş adresini güncelleyin: Bağımsız
bin/collie crew set-address <member> <host:port>veya Herdrherdr plugin action invoke crew --plugin herdr.collie set-address <member> <host:port>. - Yeni bir deputy atayın: Bağımsız
bin/collie crew deputy <member>veya Herdrherdr plugin action invoke crew --plugin herdr.collie deputy <member>. - Tüm üyeler yeniden bağlanana kadar
crew rotateçalıştırmayın.
Bu sayfayı GitHub üzerinde düzenleyin