The package pool was committed but the installer still stopped at "no local package repository": it requires the compiled bundle (Packages, Packages.gz, packages.lock.tsv, SHA256SUMS), and building that had never run. The bundle - 1321 packages, 884 MiB, Ubuntu 26.04 amd64, built with apt-ftparchive on the fleet's own release so the closure matches the devices. - built/pool/ is gitignored: those .deb files are already tracked once under provisioning/offline-repo/packages/, and the same ~890 MB does not need a second path. What the installer reads from the bundle is the index. - The output directory is chmod 0755: mktemp -d created it 0700 and left it so, which made a valid bundle unreadable to the installer's probe. dpkg-deb output was parsed wrong in four places - `dpkg-deb -f <file> Package Version` prints "<Field>: <value>", and the callers kept the whole line, so the value carried its label. build-index.sh therefore accepted no package at all and reported an empty pool; add-packages.sh rejected every real .deb as an invalid name, missed version conflicts, and copied a duplicate; build-offline-repo.sh never matched a pin. - The test suite could not see any of this: its dpkg-deb stub emitted bare values. The stub now prints the labels exactly as the real tool does, which is what surfaced the remaining three sites. Tests - The secret scan covers the files we author, not apt-ftparchive's index over third-party packages: polkit's own description reads "...asked for their password:", which is prose in the packages, not a leak. Any secret reaching a manifest, README or tool is still caught. - The "test build must not touch the bundle" assertion now compares the directory before and after instead of demanding it be empty, so a maintainer's real build is not reported as test spill.
16 KiB
27 — Offline Provisioning
Kısa özet: Paketler git deposunun içindedir (
provisioning/offline-repo/packages/, 1321.deb, ~888 MB, Git LFS ile takip edilir). Saha kurulumu internet gerektirmez ve kuran kişi hiçbir şey indirmez:sudo bf→ Kurulum sekmesi → "Bu cihazı kur" → 8 haneli bayi no → onay. 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 depoyla birlikte gelir.
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 artık ayrı bir medyada değil, bu git deposunda taşınır: provisioning/offline-repo/packages/ altında 1321 .deb (~888 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 ve indirmez; klonladığı depo seti zaten taşı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 clone/pull maliyeti); derin clone sahada zaman alabilir.
- 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 Git LFS ile gelir) — veya repo sorumlusunun bıraktığı kopyada/opt/blueforce/offline-repohazırdır. 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 seti repoda:
provisioning/offline-repo/packages/(1321.deb, Git LFS ile takip ediliyor). - Bundle indeksi repoda:
provisioning/offline-repo/built/(Packages,Packages.gz,packages.lock.tsv,SHA256SUMS,pool/). 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 checkout (paketler LFS ile)<br/>veya /opt/blueforce/offline-repo"] --> 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"]