Blueforce-Linux/docs/27-OFFLINE-PROVISIONING.md
emirhanmamak-blueforce e28783e563 feat(offline-repo): build the APT index so installs work without network
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.
2026-09-16 21:42:27 +03:00

16 KiB
Raw Blame History

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ız PROVISIONED_OFFLINE durumuna getirir; cihaz, tek kullanımlık enrollment token ve merkezi kanallar doğrulanmadan ENROLLED veya READY olmaz.

  • Dosya: docs/27-OFFLINE-PROVISIONING.md

Uygulama sözleşmesi: Kurucu, paket setini kendi kendine bulur ve varsayılan olarak yerel depodan kurar; --offline bayrağı artık gerekmez (geriye uyumluluk için kabul edilir, yalnız yerel depoyu zorlar). Arama sırası: (1) BF_OFFLINE_REPO ortam değişkeni, (2) <depo>/provisioning/offline-repo/built, (3) /opt/blueforce/offline-repo; ilk eksiksiz aday kazanır. Yerel file: APT kaynağı dışında hiçbir kaynak kullanılmaz: uzak APT source, curl, wget, anahtar indirme veya apt 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 (eksik Packages, 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ından add-packages.sh + build-index.sh ile bu depoya konur; kuran kişi hiçbir şey indirmez. Yalnız geliştirme/test için --online vardır ve üretim cihazlarında kullanılmaz. Grafik arayüz python3-tk paketine 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-tk pini, 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ı

  1. Medya/repo manifesti: Field OS release, ISO checksum, offline APT snapshot kimliği, kurucu commit'i.
  2. Paket setini repo sorumlusu hazırlar: .deb dosyalarını add-packages.sh ile provisioning/offline-repo/packages/ altına koyar (Git LFS), pinleri manifests/*.txt içinde package=version olarak doldurur, build-index.sh ile provisioning/offline-repo/built/ indeksini (Packages, Packages.gz, packages.lock.tsv, SHA256SUMS, pool/) üretir. Kuran kişi yalnız git tarafını çeker.
  3. Kurulumda yalnız genel paketler kullanılır; kurucu yerel depoyu otomatik bulur ve --offline gerekmez.
  4. Kurucu yerel durum dosyasına PROVISIONED_OFFLINE yazar; READY yazması yasaktır.
  5. İ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)

  1. Depoyu getir: git clone <repo> (paketler Git LFS ile gelir) — veya repo sorumlusunun bıraktığı kopyada /opt/blueforce/offline-repo hazırdır.
  2. sudo bf — pencere açılır: Blueforce Field OS — Yönetim.
  3. Üst çubuk Hedef > Bayi no (8 hane) alanına numarayı yaz (örn. 12010193).
  4. Kurulum sekmesi → Bu cihazı kur (hiçbir şey yazmayan ön kontrol için: Kurulum ön kontrolü (--check)).
  5. Komut ekranda gösterilir, onay istenir; onaylandıktan sonra kurulum çalışır. --offline işaretlemek zorunlu değildir (varsayılan kaynak zaten yerel depodur).
  6. Sonuç: PROVISIONED_OFFLINE. Arayüzdeki Kurulum modül durumu ve bf-status ile 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

  1. Paket işlemi bozuksa aynı onaylı snapshot ile dpkg --configure -a ve kurucu yeniden çalıştırılır.
  2. Yanlış repo sürümü geri çekilir; önceki onaylı manifestle yeniden kurulur.
  3. 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.
  4. Kimlik/token hatasında cihaz resetlenmez; 29'daki token iptal/yenileme prosedürü uygulanır.
  5. Arayüz sorunuysa (ekran/tkinter) rollback gerekmez: sudo bf --tui ile 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.yaml güncel; pin listesi ile paket havuzu uyuşuyor.
  • Depoda/repoda cihaz kimliği, private key veya kalıcı token yok.
  • python3-tk ve bağımlılıkları manifests/base-packages.txt içinde pinli; 18-final-check tkinter'ı denetliyor.
  • Kuran kişinin komutu --offline bayrağı istemiyor; depo otomatik bulunuyor.
  • Grafik arayüz akışı (bayi no → Kurulum → "Bu cihazı kur") yazılı ve ekransız ortam için sudo bf --tui belgeli.
  • İnternet kapalıyken kurulum tamamlanıyor; dış indirme çağrısı yok.
  • PROVISIONED_OFFLINE gö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-repo kopyası mı birincil — sahibi: saha operasyonu + 05 yazarı.
  • --online geliş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"]