The bundle pool is ~884 MB and now travels through Git LFS, so a plain clone materialises all of it. Measured on this repository: 2.7 GB working tree, against 20 MB with smudge disabled -- the same 135x that decides whether one device or seven hundred can be provisioned from a git remote. bf-bootstrap exports GIT_LFS_SKIP_SMUDGE=1 for every git operation it performs (clone and fetch), so provisioning a device no longer implies downloading the package payload. The trade is explicit and documented rather than hidden: with smudge off the pool files on disk are 131-byte pointer texts, and the installer must not mistake one for a package. So the installer gained a guard. A pointer text satisfies every existence check, so without it the run died later inside `sha256sum -c` and reported a checksum mismatch -- a misdiagnosis that sends an operator looking for corruption when the payload was simply never fetched. It now recognises the pointer by content and names the remedy instead. Getting the payload is a deliberate second step, and both documented routes are real: a local mirror (the offline-correct path, and the one the fleet uses) or `git lfs pull --include='provisioning/offline-repo/built/pool/*'`, which fetches only the delivery pool and leaves the intake copy under packages/ unfetched -- verified: 1.8 GB and a real .deb in built/pool, 131-byte stub still in packages/. Tests: test-field-os-lifecycle.sh gains a scenario that lays down a pointer text where a .deb belongs and asserts three things -- the run refuses, the message names the cause, and it does not blame a checksum. Also asserts apt-get is never invoked. 16 scenarios, all passing. docs/27 is corrected where it had gone stale: it claimed a clone carries the packages and the installer downloads nothing, which stopped being true the moment the payload moved to LFS.
18 KiB
27 — Offline Provisioning
Kısa özet: Paketler git deposunun içindedir (
provisioning/offline-repo/built/pool/, 1321.deb, ~884 MB, Git LFS ile takip edilir). Saha kurulumu internet gerektirmez:sudo bf→ Kurulum sekmesi → "Bu cihazı kur" → 8 haneli bayi no → onay. Paket yükü klonla birlikte gelmez (bilerek; bkz. §4), yerel aynadan taşınır ve kurucu depoyu kendi bulur. Bu yol yalnızPROVISIONED_OFFLINEdurumuna getirir; cihaz, tek kullanımlık enrollment token ve merkezi kanallar doğrulanmadanENROLLEDveyaREADYolmaz.
- Dosya:
docs/27-OFFLINE-PROVISIONING.mdUygulama sözleşmesi: Kurucu, paket setini kendi kendine bulur ve varsayılan olarak yerel depodan kurar;
--offlinebayrağı artık gerekmez (geriye uyumluluk için kabul edilir, yalnız yerel depoyu zorlar). Arama sırası: (1)BF_OFFLINE_REPOortam değişkeni, (2)<depo>/provisioning/offline-repo/built, (3)/opt/blueforce/offline-repo; ilk eksiksiz aday kazanır. Yerelfile:APT kaynağı dışında hiçbir kaynak kullanılmaz: uzak APT source, curl, wget, anahtar indirme veyaapt downloadçağrılmaz. İnternet kurulum için gerekmez. İki farklı başarısızlık vardır: depo hiç yoksa kurulum Türkçe bir hata, aranan yollar veÇIKIŞ NEDENİ: yerel paket deposu bulunamadı.ile durur; depo bulunup da doğrulanamazsa (eksikPackages,Packages.gz,packages.lock.tsv,SHA256SUMS; checksum uyuşmazlığı; boş/bozuk kilit; eksik pin)OFFLINE BLOCKED: <sebep>ile durur. Her iki durumda da paket modüllerinden önce durulur, kurulum başlamaz ve sistemde hiçbir değişiklik yapılmaz. Paketler bu git deposunda taşınır ve repo sorumlusu tarafındanadd-packages.sh+build-index.shile bu depoya konur; kuran kişi hiçbir şey indirmez. Yalnız geliştirme/test için--onlinevardır ve üretim cihazlarında kullanılmaz. Grafik arayüzpython3-tkpaketine bağlıdır; bu paket offline depoda bilinçli olarak pinlidir (manifests/base-packages.txt).
- İlgili kararlar:
24-DECISION-LOG.md#K-16,#K-09,#K-11,#K-12- İlgili dokümanlar:
05-ONE-CLICK-INSTALLER.md(kurucu),33-OPERATOR-CONSOLE.md(arayüz),provisioning/offline-repo/README.md(paket hazırlama)- Durum: [ ] Taslak
1. Amaç
Saha interneti kesik veya güvenilmezken tekrarlanabilir, denetlenebilir ve secretsiz ilk kurulumu tanımlamak. Kuran kişi paket aramaz, indirmez, bayrak ezberlemez: paket seti depoda sürümlenir ve yerel aynadan taşınır.
2. Kapsam
- Kapsam içi: git checkout (paketler dahil) veya kurulmuş
/opt/blueforce/offline-repo, offline APT bundle (built/), kurucunun yerel depoyu otomatik bulması, iki hata durumu, grafik arayüz üzerinden kurulum,python3-tkpini, durum damgası ve sonradan enrollment. - Kapsam dışı: merkezi peer atama ve token doğrulama (29), release imzalama (30), paket setinin nasıl üretildiği (repo sorumlusunun işi,
provisioning/offline-repo/README.md).
3. Kararlar
KARAR: Paket seti git deposunda taşınır ve cihaz grafik arayüzden (`sudo bf` → Kurulum → "Bu cihazı kur") internetsiz kurulur; paket deposu kurucu tarafından otomatik bulunur ve sonuç durumu yalnızca PROVISIONED_OFFLINE'dır.
GEREKÇE: Paket indirme veya merkezi API'ye erişim yokken cihaz standarda getirilebilir; fakat merkezde doğrulanmamış kimlik ve kanallar READY iddiası yapamaz. Kuran kişinin indirme yapmaması ve bayrak hatırlamaması saha hatasını ortadan kaldırır: yerel depo varsayılan ve tek kaynaktır.
ALTERNATİF: İnternet gelene kadar kurulum yapmama — saha ziyareti ve bekleme maliyeti nedeniyle elendi. Kurulumu `--offline` bayrağına bağlamak — operatör bayrağı unuttuğunda kurulum durur; otomatik keşif seçildi, bayrak geriye uyumluluk için korundu.
RİSK: Eski veya karışık paket snapshot'ı; manifest, checksum ve release kimliği ile azaltılır. Yanlış/eski depo bulunması; arama sırası ve her adayda eksiksizlik denetimi ile azaltılır. Grafik arayüzün `python3-tk` paketine bağımlılığı; paketin offline depoda pinlenmesi ve eksikliğinde `sudo bf --tui` yedeği ile azaltılır.
MALİYET: Ücretsiz (depo boyutu git tarafında ~888 MB).
LİSANS: APT — https://manpages.ubuntu.com/manpages/noble/en/man8/apt.8.html ; dpkg — https://manpages.ubuntu.com/manpages/noble/en/man1/dpkg.1.html ; Ubuntu offline kurulum ayrıntısı 26.04 için LAB doğrulamalıdır.
4. Neden Bu Karar?
Paketler ayrı bir medyada değil, bu git deposunda taşınır: provisioning/offline-repo/built/pool/ altında 1321 .deb (~884 MB) durur ve .gitattributes ile Git LFS üzerinden takip edilir (*.deb filter=lfs ...). Bu yüzden sahada "hangi paket nereden geldi?" sorusu ne internete ne de dış medyaya bağlıdır; aynı soru packages.lock.tsv ve repo-manifest.yaml ile yanıtlanır.
Kuran kişi paket aramaz, ama paket yükünü kendiliğinden de indirmez — bu bilinçli bir ayrımdır. LFS yükü ~884 MB olduğu ve 700 cihazın her biri onu çekerse aylık bant kotası ilk günde tükeneceği için klon hafif tutulur; yük yerel aynadan (USB ya da repo sorumlusunun bıraktığı kopya) gelir, sahada internet gerekmez. Yalnız internet varken ve tek seferlik bir çekme uygunsa git lfs pull --include='provisioning/offline-repo/built/pool/*' kullanılır.
Durum makinesi, "kuruldu" ile "merkezce güvenildi" arasındaki farkı görünür yapar: offline kurulum yalnız PROVISIONED_OFFLINE üretir.
5. Alternatifler
| Alternatif | Artı | Eksi | Sonuç |
|---|---|---|---|
| Sürümlü offline APT bundle + repoda taşınan paketler | Tekrarlanabilir, indirme yok, medya lojistiği yok | Git deposu ~888 MB büyür (LFS) | Seçildi |
| Ayrı fiziksel seed USB medyası | Depo küçük kalır | Medya zimmeti/sürüm takibi, kaybolma riski | Yedek/geri dönüş yolu |
Rastgele .deb dosyaları |
İlk anda kolay | Bağımlılık/sürüm belirsiz | Elendi |
| İnternet bekleme | Basit | Saha blokajı | Elendi |
Yerel depoyu operatörün --offline bayrağıyla göstermesi |
Basit | Bayrak unutulunca kurulum durur, saha hatası üretir | Elendi (bayrak geriye uyumluluk için korundu) |
6. Avantajlar
- Bağlantısız sahada standarda yakın kurulum; kuran kişi hiçbir indirme yapmaz ve bayrak ezberlemez.
- Paket manifesti ve kilit dosyası ile hangi sürümün yüklendiği kanıtlanır.
- Nesil farkı yoktur: repo sorumlusu paketleri bir kez commit eder, 700 cihaz aynı setten kurulur.
- Kurulum akışı grafik arayüzde tek düğmedir; terminal bilgisi gerekmez.
7. Dezavantajlar
- Git deposu paket setiyle birlikte büyür (LFS; içerik-hash ile tekilleşir, ~884 MB). Klon hafiftir ama paket yükü ayrıca taşınmalıdır: 700 cihazın her biri LFS'ten çekerse bant kotası tükenir, bu yüzden yük yerel aynadan dağıtılır.
- Offline cihaz merkezi izleme ve erişim kanalları doğrulanana kadar operasyonel olarak hazır değildir.
- Paket snapshot'ı yenilenmediği sürece güvenlik güncellemeleri geride kalır (onaysız update zaten yasak, K-11).
8. Riskler
| Risk | Olasılık | Etki | Azaltma |
|---|---|---|---|
| Eski güvenlik paketi | Orta | Orta | Süre sonu olan release medyası/repo sürümü, hızlı enrollment kuyruğu |
| Secret repoda kalır | Düşük | Yüksek | Secret taraması (test), token yalnız bir kez ve cihazda girilir |
| Yarım paket işlemi | Orta | Orta | dpkg --configure -a, idempotent kurucu |
| Kurucu yanlış/eski depoyu bulur | Düşük | Orta | Arama sırası sabittir; aday eksiksiz değilse kullanılmaz, BF_OFFLINE_REPO ile açıkça yönlendirilebilir |
Paketler var ama indeks (built/) yok |
Orta | Yüksek | Kurucu fail-closed durur ("yerel paket deposu yok"); repo sorumlusu build-index.sh koşup built/ dizinini commit eder |
| Grafik arayüz açılamıyor | Orta | Düşük | python3-tk offline depoda pinli; ekransız ortamda sudo bf --tui |
9. Uygulama Planı
- Medya/repo manifesti: Field OS release, ISO checksum, offline APT snapshot kimliği, kurucu commit'i.
- Paket setini repo sorumlusu hazırlar:
.debdosyalarınıadd-packages.shileprovisioning/offline-repo/packages/altına koyar (Git LFS), pinlerimanifests/*.txtiçindepackage=versionolarak doldurur,build-index.shileprovisioning/offline-repo/built/indeksini (Packages,Packages.gz,packages.lock.tsv,SHA256SUMS,pool/) üretir. Kuran kişi yalnız git tarafını çeker. - Kurulumda yalnız genel paketler kullanılır; kurucu yerel depoyu otomatik bulur ve
--offlinegerekmez. - Kurucu yerel durum dosyasına
PROVISIONED_OFFLINEyazar;READYyazması yasaktır. - İnternet geldiğinde 29'daki tek-kullanımlık token ile enrollment başlatılır; sonra merkezi kanallar test edilir.
Kuran kişinin akışı (grafik arayüz — ana yol)
- Depoyu getir:
git clone <repo>— paketler bilerek gelmez. Bootstrap (ve her git işlemi)GIT_LFS_SKIP_SMUDGE=1ile çalışır, çünkü paket yükü ~884 MB'tır ve tam klon sahada 2.7 GB'lık bir çalışma kopyası üretir (ölçüldü; smudge kapalıyken 20 MB). Paket yükünü almanın iki yolu var:-
Yerel ayna (önerilen, sahada internet yok): repo sorumlusunun hazırladığı
/opt/blueforce/offline-repokopyasını taşıyın; ya da -
Hedefli LFS çekme (yalnız internet varken): depo kökünde
git lfs pull --include='provisioning/offline-repo/built/pool/*'Bu yalnız teslim havuzunu indirir (
packages/altındaki kaynak kopyayı çekmez, aynı baytları ikinci kez indirmez). Paketler gelmediyse kurucu bunu tek cümleyle söyler (Paketler henüz indirilmemiş: … Git LFS işaretçisi), çünkü havuzdaki dosyalar.debdeğil 131 baytlık işaretçi metnidir.
-
sudo bf— pencere açılır: Blueforce Field OS — Yönetim.- Üst çubuk Hedef > Bayi no (8 hane) alanına numarayı yaz (örn.
12010193). - Kurulum sekmesi →
Bu cihazı kur(hiçbir şey yazmayan ön kontrol için:Kurulum ön kontrolü (--check)). - Komut ekranda gösterilir, onay istenir; onaylandıktan sonra kurulum çalışır.
--offlineişaretlemek zorunlu değildir (varsayılan kaynak zaten yerel depodur). - Sonuç:
PROVISIONED_OFFLINE. Arayüzdeki Kurulum modül durumu vebf-statusile doğrulanır.
# Ana yol (grafik arayüz)
sudo bf
# → Hedef: Bayi no (8 hane) → Kurulum sekmesi → "Bu cihazı kur"
# Yedek yol (grafik ekran yoksa veya python3-tk yoksa): aynı uygulamanın terminal arayüzü
sudo bf --tui
# Doğrudan kurucu ile (otomasyon / teşhis)
sudo ./scripts/install/blueforce-install.sh --dealer-id 12010193
# Bilinçli olarak başka bir depo dizinini göstermek (nadir, repo sorumlusu isterse)
BF_OFFLINE_REPO=/mnt/blueforce-repo/built \
sudo ./scripts/install/blueforce-install.sh --dealer-id 12010193
Depo keşfi ve iki hata durumu
Sıra (ilk eksiksiz aday kazanır): BF_OFFLINE_REPO → <repo>/provisioning/offline-repo/built → /opt/blueforce/offline-repo. Bir aday "eksiksiz" sayılmak için Packages, Packages.gz, packages.lock.tsv ve SHA256SUMS dosyalarının hepsini içermelidir; yalnız packages/ (ham .deb havuzu) yeterli değildir — indeksin build-index.sh ile üretilmiş olması gerekir.
Depo bulunduğunda ekranda şu duyuru çıkar:
Yerel paket deposu bulundu: <N> paket, <boyut>
Depo : <dizin>
Kaynak : <bulunduğu yer>
Kip : yerel kurulum. İnternet, paket indirme ve ek anahtar gerekmez.
Depo hiçbir yerde yoksa kurulum başlamadan durur:
HATA: Yerel paket deposu yok. Repo sorumlusuna başvurun: provisioning/offline-repo/README.md
Aranan yerler:
- depodaki hazır paket seti — yok: <repo>/provisioning/offline-repo/built
- cihazdaki kurulu paket deposu — yok: /opt/blueforce/offline-repo
Ne yapmalı:
1) Paket setini git ile tam olarak getirin ... ya da /opt/blueforce/offline-repo altına koyun.
2) Kurulumu yeniden çalıştırın.
Kuruluma hiç başlanmadı; sistemde hiçbir değişiklik yapılmadı.
ÇIKIŞ NEDENİ: yerel paket deposu bulunamadı.
Depo bulundu ama doğrulanamadıysa (bozuk/eksik içerik) kurulum yine başlamaz:
OFFLINE BLOCKED: <sebep>
Depo : <dizin>
Ne yapmalı : paket setini yeniden üretip git ile getirin (provisioning/offline-repo/README.md)
ÇIKIŞ NEDENİ: yerel paket deposu doğrulanamadı; kurulum başlamadı ve
sistemde hiçbir değişiklik yapılmadı.
--online yalnız geliştirme/test makinesi içindir; paketleri internetten çeker ve üretim cihazlarında kullanılmaz.
python3-tk neden offline depoda pinli?
Grafik operatör uygulaması Tkinter ile yazılmıştır ve tkinter Ubuntu'da ayrı bir pakettir (python3-tk); minimal Ubuntu Server kurulumunda Python vardır ama tkinter yoktur. İnternetsiz sahada apt install python3-tk çalışmaz, bu yüzden paket ve bağımlılık kümesi (python3-tk, python3.14-tk, libtk8.6) provisioning/offline-repo/manifests/base-packages.txt içinde pinlidir ve depodan gelir. Kurulum sonu kapısı scripts/install/installer/modules/18-final-check.sh tkinter'ı denetler; eksikse WARN yazar ve kurulumu düşürmez (cihaz yine kurulur, operatör terminal konsoluna sudo bf --tui ile devam eder).
10. Test Planı
| Test | Beklenen sonuç | Ortam |
|---|---|---|
| İnternetsiz kurulum | Paketler manifestten kurulur, dış indirme yok | LAB(2) air-gapped |
| Depo yolu verilmeden kurulum | Kurucu depoyu otomatik bulur (repo/built), duyuru satırını yazar |
LAB(2) |
| Grafik arayüzden kurulum | sudo bf → Kurulum → "Bu cihazı kur" ile PROVISIONED_OFFLINE |
LAB(2) masaüstü oturumu |
BF_OFFLINE_REPO ile başka dizin |
Verilen dizin kullanılır; geçersizse durur | LAB(2) |
| Depo hiç yok | Türkçe hata + aranan yollar + ÇIKIŞ NEDENİ: yerel paket deposu bulunamadı., exit 1, sistem değişmez |
LAB(2) |
| Depo var ama bozuk (checksum/pin) | OFFLINE BLOCKED: <sebep> + Türkçe çıkış nedeni, exit 1, sistem değişmez |
LAB(2) |
Yalnız packages/ var, built/ yok |
Depo "yok" sayılır, kurulum başlamaz (fail-closed) | LAB(2) |
python3-tk eksik imaj |
sudo bf Türkçe hata + ipucu, exit 3; 18-final-check WARN yazar, kurulum düşmez |
LAB(2) |
| DNS/WAN kesik | Kurucu dış indirme istemez; 01-precheck ağı yalnız bilgi olarak yazar, 05-network DNS zorunlu tutmaz |
LAB(2) |
--online üretimde denenmez |
Yalnız geliştirme/test; kurucu uyarı yazar | LAB(2) |
bf-status |
PROVISIONED_OFFLINE; READY değil |
LAB(2) |
| Bağlantı sonrası enrollment | ENROLLED → READY kapıları çalışır | LAB(2) |
11. Rollback
- Paket işlemi bozuksa aynı onaylı snapshot ile
dpkg --configure -ave kurucu yeniden çalıştırılır. - Yanlış repo sürümü geri çekilir; önceki onaylı manifestle yeniden kurulur.
- Yerel depo bozuksa sahada onarılmaz: repo sorumlusu depoyu yeniden üretip commit eder (
add-packages.sh+build-index.sh), kurulum yapan kişi güncel git tarafını çekip komutu tekrarlar. - Kimlik/token hatasında cihaz resetlenmez; 29'daki token iptal/yenileme prosedürü uygulanır.
- Arayüz sorunuysa (ekran/tkinter) rollback gerekmez:
sudo bf --tuiile aynı akış yürütülür.
12. Kontrol Listesi
- Paket kaynağı repoda:
provisioning/offline-repo/packages/(1321.deb, Git LFS ile takip ediliyor; teslim kopyasıbuilt/pool/içindedir). - Bundle indeksi repoda:
provisioning/offline-repo/built/(Packages,Packages.gz,packages.lock.tsv,SHA256SUMS,pool/). - Paket yükü sahaya taşındı: yerel ayna (USB ya da
/opt/blueforce/offline-repo) — klon LFS yükünü bilerek getirmez, bu adım atlanırsa kurucuPaketler henüz indirilmemiş: … Git LFS işaretçisiile durur. repo-manifest.yamlgüncel; pin listesi ile paket havuzu uyuşuyor.- Depoda/repoda cihaz kimliği, private key veya kalıcı token yok.
python3-tkve bağımlılıklarımanifests/base-packages.txtiçinde pinli;18-final-checktkinter'ı denetliyor.- Kuran kişinin komutu
--offlinebayrağı istemiyor; depo otomatik bulunuyor. - Grafik arayüz akışı (bayi no → Kurulum → "Bu cihazı kur") yazılı ve ekransız ortam için
sudo bf --tuibelgeli. - İnternet kapalıyken kurulum tamamlanıyor; dış indirme çağrısı yok.
PROVISIONED_OFFLINEgörünür ve READY kapısı kapalı.- Sonradan enrollment sahibi/kuyruğu kayıtlı.
13. Açık Sorular
- Offline paket seti yenileme sıklığı ve Git LFS bant genişliği/kotaysa sahaya taşıma yöntemi — sahibi: release yöneticisi.
- Paketlerin sahaya taşınmasında git clone mu, hazır
/opt/blueforce/offline-repokopyası mı birincil — sahibi: saha operasyonu + 05 yazarı. --onlinegeliştirme yolunun hangi ortamlarda serbest olduğu — sahibi: yönetim + 26/33 yazarları.
Ek: Keşif ve durum akışı
flowchart LR
M["git clone (hafif: LFS smudge kapalı)<br/>+ paket yükü yerel aynadan"] --> G["sudo bf → Kurulum → 'Bu cihazı kur'"]
G --> D{"Kurucu yerel depoyu arar<br/>BF_OFFLINE_REPO → repo/built → /opt/blueforce/offline-repo"}
D -->|"hiçbiri yok / eksik"| X["HATA: Yerel paket deposu yok<br/>aranan yollar + ÇIKIŞ NEDENİ · exit 1<br/>sistem değişmez"]
D -->|"eksiksiz aday bulundu"| V{"Doğrulama katmanı:<br/>dosya listesi, SHA256SUMS, kilit, pin ↔ pool"}
V -->|"başarısız"| B["OFFLINE BLOCKED: sebep<br/>ÇIKIŞ NEDENİ: doğrulanamadı · exit 1"]
V -->|"geçti"| P["PROVISIONED_OFFLINE"]
P --> T["Tek kullanımlık token"]
T --> E["ENROLLED"]
E --> C["WG + erişim + izleme doğrulama"]
C --> R["READY"]