#
Nenjim
Documentation
> **Dokumentstatus:** Journal-format version 1, den immutable Java-model, den interne tekstparser, det read-only
> `JournalService` med en Hub-styret procesimplementation, den passive eksplicit refresh-baserede
> `JournalServiceManager`, den Hub-styrede `JavaFxRuntimeService`, første version af det centrale component Registry
> og den obligatoriske format 1 Hub-konfiguration er implementeret. Contexts, resolution, discovery, runtime loading
> og removal er fortsat fremtidig funktionalitet.
**Indholdsfortegnelse:**
* [1. Introduktion til Nenjim](#1-introduktion-til-nenjim)
* [2. Versionering og Afhængigheder](#2-versionering-og-afhængigheder)
* [3. Opdateringer og Sikkerhed](#3-opdateringer-og-sikkerhed)
* [4. Betalingssystem og Integration med AssetAZ](#4-betalingssystem-og-integration-med-assetaz)
* [5. Backing Store og Fleksibilitet](#5-backing-store-og-fleksibilitet)
* [6. Standardiseret og Automatiseret Pakkehåndtering](#6-standardiseret-og-automatiseret-pakkehåndtering)
* [7. Betydningen af Semantisk Versionering](#7-betydningen-af-semantisk-versionering)
* [8. Componenter og det centrale Registry](#8-componenter-og-det-centrale-registry)
* [9. Integration med AssetAZ og økonomisk aktivitet](#9-integration-med-assetaz-og-økonomisk-aktivitet)
## 1. Introduktion til Nenjim
Nenjim skal på sigt kunne håndtere forskellige versioner af softwareartifakter samtidigt. Det nu implementerede
fundament er Journal-laget: et strengt tekstformat og en immutable model, som kan fastholde, hvad der var kendt om
en artifakt på et bestemt tidspunkt. Det første Registry kan desuden katalogisere de konstruerede componenter, og
Hub-konfigurationen vælger den manuelt ordnede procesmængde. Dependency-resolution, Contexts, downloading og
classloading kommer senere.
## 2. Versionering og Afhængigheder
Nenjim beskriver moduler, artifakter, releases, relationer og versionspolitik i Journaler. Almindelig Java-kode skal
ikke indbygge Nenjim- eller versionsspecifikke navne for at bruge et API. Et Context beskriver de ønskede valg, og
Nenjim resolver senere disse valg og Journalernes metadata til en eksakt artifakt- og dependency-graf.
### 2.1 Én Journal per artifakt
En Journal beskriver præcis én artifakt. API, tests og referenceimplementation har derfor hver sin Journal; roller
som `API`, `IMPLEMENTATION` og `TEST` gemmes ikke som et `TYPE`-felt. Journalens identitet udledes af metadata:
```text
--
```
Eksempelkoordinater er `com_r35157_nenjim-hubd-api`, `com_r35157_nenjim-hubd-tests` og
`com_r35157_nenjim-hubd-impl_ref`. En komplet release-reference tilføjer en eksakt Semantic Version:
```text
com_r35157_nenjim-hubd-api:1.0.3
```
Der findes intet separat `JOURNAL_ID`.
### 2.2 Metadata og release-indhold
`[METADATA]` indeholder coordinate-delene og en obligatorisk single-quoted `DESCRIPTION`. Den valgfrie
`INFORMATION_URI` er også single-quoted, skal være en syntaktisk gyldig absolut `URI`, og kan bruge enhver scheme,
for eksempel `https:`, `ftp:` eller `ipfs:`. Nenjim åbner eller fortolker ikke URI'en automatisk.
Hver `[RELEASE major.minor.patch]` indeholder sin egen single-quoted `LICENSE`, `PUBLISHED_AT`, `CONTENT_SIZE` og
mindst én `CONTENT_DIGEST`. Format 1 accepterer valideret `sha256` og CIDv1 (`cid1`). Licensen er fri tekst, gemmes
uden normalisering og kan være forskellig mellem releases; fremtidig licensfiltrering er ikke implementeret.
### 2.3 Komplette snapshots og Journal-kæden
Hver Journal-fil er et komplet immutable snapshot af al aktuel viden om artifakten og dens kendte releases. En
revision er aldrig en delta og arver intet implicit. En nyere revision kan ændre metadata, policy, dependencies og
selv korrigere eller fjerne tidligere kendt release-information. Et no-op snapshot er også gyldigt.
`JOURNAL_VERSION` er et strengt stigende UTC-timestamp med millisekundpræcision:
```text
uuuuMMddHHmmssSSS'Z'
```
Genesis-revisionen udelader `PREVIOUS_JOURNAL_DIGEST`. Hver efterfølger refererer til SHA-256 over forgængerens
komplette UTF-8-tekst præcis som leveret, inklusive whitespace og linjeskift. Manglende forgængere, forks, flere
genesis-revisioner, fremmede artifaktkæder og ikke-stigende versioner afvises.
`PUBLISHED_AT` er release-tid og er uafhængig af Journalens publiceringstid. Historiske queries vælger et helt
snapshot ud fra Journal-kæden; de filtrerer ikke det nyeste snapshot efter `PUBLISHED_AT`.
### 2.4 Version expressions
En `SemanticVersion` (`1.0.3`) er én eksakt release. En `VersionExpression` beskriver et sæt acceptable releases:
* `1.0.3` og `[1.0.3]` er samme eksakte selector.
* `[1.0]` betyder hele den stabile `1.0.x`-serie, ikke eksakt `1.0.0`.
* `[1.0.3-->1.0.7]` inkluderer begge grænser; `)` ekskluderer øvre grænse.
* `[1.0-->1.2]` inkluderer hele `1.2.x`; `[1.0-->1.2)` gør ikke.
* `[1.0-->` stopper før `2.0.0`; `(1.0-->` starter ved `1.1.0`.
* Komma adskiller en union af expressions.
Endpoints skal mindst indeholde major og minor. Matematiske operatorer som `>=`, prereleases, build-metadata,
tomme elementer, omvendte ranges og implicitte cross-major open ranges afvises.
### 2.5 Dependencies
Dependencies hører til en bestemt artifaktrelease og bruger altid en explicit scheme. Format 1 implementerer kun:
```text
DEPENDS_ON=nenjim:com_r35157_nenjim-hubd-api=[1.0-->
EXCLUDES=nenjim:com_r35157_nenjim-hubd-api=1.0.5:'Known incompatibility'
PREFERRED=nenjim:com_r35157_nenjim-hubd-api=1.0.3:'Built together'
```
`DEPENDS_ON` er basissættet. `EXCLUDES` er en hård relationel begrænsning. `PREFERRED` er kun et hint og skal være
en delmængde af `DEPENDS_ON - EXCLUDES`. Flere exclusion/preference-linjer for samme target kombineres som union,
men deres individuelle beskrivelser bevares. Ukendte schemes, herunder `maven:`, afvises i format 1.
### 2.6 Artifact policy
Den valgfrie `[POLICY]` bevarer individuelle regler og beskrivelser:
* `BLACKLIST` er en hård global regel: matchende releases må ikke vælges.
* `DISCOURAGED` er et negativt hint: releasen kan stadig vælges.
* `RECOMMENDED` er et positivt hint til én eksakt release, som findes i samme snapshot.
Overlap er tilladt, og hårde regler vinder over hints. En fremtidig resolver bør søge en gyldig graf med flest muligt
kompatible anbefalinger; højeste versionsnummer er fallback, ikke en ubetinget regel. Det kan senere føre til
konvergens fra en højere lokal release til en lavere anbefalet release, men den adfærd er ikke implementeret nu.
### 2.7 Parser og immutable model
Parseren kræver `FORMAT_VERSION=1` som første faktiske entry, men tillader blanke linjer og `#`-kommentarer.
`#` inde i single quotes er tekst. Quoted værdier understøtter `\'` og `\\`. Ukendte, malformed, duplikerede eller
forkert placerede felter/sektioner afvises med source, linjenummer og årsag. Hele dokumentet valideres før servicens
state ændres. Alle publicerede modeller og collections er immutable og defensivt kopieret.
### 2.8 JournalService, JournalServiceManager og disk-layout
En `Service` er det domæne-API, som applikationer og andre services bruger i daglig drift. `JournalService` er en
registrerbar Nenjim component, men API'et er fortsat filesystem-uafhængigt og read-only: det kan vise coordinates,
kronologiske revisionslister, latest, exact og newest-at-or-before snapshots samt en eksakt release fra et valgt
snapshot. Det eksponerer ikke lifecycle, filesystem paths, refresh, parser eller mutation. Queries er først
tilgængelige, når Journal-processens initiale loading er lykkedes.
En `ServiceManager` er et separat administrationshandle, som en composition/lifecycle owner kan beholde uden at
give almindelige service-consumers administrative rettigheder. `JournalServiceManager` er passiv og eksponerer kun
den normaliserede Journal-root og explicit refresh; den har ingen `start()`, `stop()` eller service-accessor og er
hverken component eller process. Hub'en konstruerer ét Journal-objekt, som både er `JournalService` og
`NenjimProcess`, samt en separat manager bundet til objektets package-private admin-view.
Når Hub'en starter Journal-processen, læser referenceimplementationen komplette UTF-8-filer kronologisk og
validerer placement/navne. Hele den initiale worldview publiceres først, når alle runtime-filer er accepteret; en
fejl efterlader servicen utilgængelig uden partial state og samme instans kan ikke startes igen. Refresh efter
vellykket startup er fortsat explicit, idempotent og per-ingestion atomisk; der er ingen watcher eller background
polling.
`JournalServiceImpl` vedligeholder internt kæderne og udfører atomisk ingestion med exact-text SHA-256. Identisk tekst
er idempotent; anderledes tekst med samme coordinate og Journal-version er en conflict. Parser, ingestion og mutable
chain state er implementation details og findes ikke i public signatures. Public API-pakkerne er opdelt således:
```text
com.r35157.nenjim.service.journal JournalService, JournalServiceManager
com.r35157.nenjim.service.journal.model sammensatte immutable domænemodeller
com.r35157.nenjim.service.journal.valuetypes små værdidefinerede typer
com.r35157.nenjim.service.journal.exception Journal-specifikke exceptions
com.r35157.nenjim.service.journal.impl.ref referenceimplementation og interne helpers
```
```text
data/nenjim/journals/
└── /
├── .journal
└── .journal.example
```
Kun `.journal` er runtime-input. `.journal.example` dokumenterer formatet og indlæses ikke. Roden skal allerede
eksistere og være læsbar; Journal-processen og dens manager opretter, overskriver eller sletter ikke Journal-filer.
## 3. Opdateringer og Sikkerhed
Det implementerede Journal-lag kan repræsentere nye sikkerhedsoplysninger som en nyere immutable revision, for
eksempel via `BLACKLIST` eller en ændret `RECOMMENDED`. Automatisk synchronization, selection, reconciliation og
upgrade/downgrade er fremtidigt arbejde.
## 4. Betalingssystem og Integration med AssetAZ
Betaling og AssetAZ-integration er langsigtet vision og er ikke en del af Journal-formatet eller denne implementation.
## 5. Backing Store og Fleksibilitet
Den nuværende Journal-proces læser kun det dokumenterede lokale disk-layout gennem en intern filesystem-loader.
Artifact downloading, IPFS retrieval, remote Journals og andre backing stores er ikke implementeret. En
`ipfs:`-værdi i `INFORMATION_URI` er metadata, ikke en retrieval-instruks.
## 6. Standardiseret og Automatiseret Pakkehåndtering
Journalen modellerer dependency-krav og indholdsidentiteter, men downloader ikke bytes og verificerer ikke downloadet
indhold. Dependency-graph resolution, automatisk release-selection og Maven-resolution er fremtidigt arbejde.
## 7. Betydningen af Semantisk Versionering
Format 1 accepterer kun stabile eksakte releases med alle tre numeriske komponenter. Det forudsætter ikke, at en
resolver altid vælger den numerisk højeste version: hard constraints afgrænser de gyldige valg, og policy/dependency
hints kan på sigt foretrække en lavere kompatibel release.
## 8. Componenter og det centrale Registry
En Nenjim component er en færdigkonstrueret byggeklods, som er klar til brug. Rollen som service, applikation,
algoritme eller adapter og klassifikationen som aktiv proces er uafhængige dimensioner. En service eksponerer et
domain API, mens en applikation beskriver en user-facing eller orchestration-rolle. Registry-API'et bruger det
fælles ord `component` og ikke `plugin`, og `NenjimComponent` er en ren marker interface. En component, som Hub'en
kan starte og tracke, implementerer desuden den canonical `com.r35157.nenjim.process.NenjimProcess`, som kun lover
`start()` og ikke en fælles stop-, restart- eller health-operation. En service- eller applikationsimplementation kan
derfor også være en process; passive componenter er det ikke.
Ticker følger denne opdeling: almindelige consumers modtager `TickerService` med kun latest-price query, mens det
samme `TickerServiceImpl`-objekt separat er en `NenjimProcess`, som Hub'en starter. Tickerens source-lifecycle er
implementation-owned; `PriceSource`-instanser startes internt, og en fejlet Ticker-start stopper de sources, som nåede
at starte. Der findes ingen almindelig Ticker-serviceoperation til start eller stop.
Evelyn IOU Burner følger samme opdeling, selv om dens nuværende domain-service-view er tomt:
`EvelynIOUBurnerService` giver typed Registry- og dependency-identitet uden eksterne håndtag, mens det samme
`EvelynIOUBurnerServiceImpl`-objekt separat er en Hub-styret `NenjimProcess`. Kun process-view'et eksponerer startup;
hverken service-interfacet eller implementationen eksponerer almindelig stop eller restart.
En `NenjimComponentId` er registration metadata i ét Registry og er ikke en egenskab ved objektet. ID-formatet er
lower-case ASCII med dot-separated segments og valgfrie interne bindestreger, f.eks. `nenjim.registry.service` og
`assetaz.price-source.raydium-pool.eve-usdt`. Det samme objekt må registreres under flere forskellige ID'er, og én
registration bliver automatisk synlig gennem alle component interfaces, som objektet implementerer. Registry-
service- og process-view af Registry-objektet har derfor samme ID og samme object identity.
`NenjimRegistryService` er det read-only katalog, som almindelige consumers modtager gennem constructor injection.
Det kan returnere et immutable registration-order snapshot af ID'er for et component interface eller slå ét ID op
gennem et forventet interface. Et manglende ID giver `null`; et eksisterende ID med forkert interface er en caller
programming error. Public API'et kan ikke registrere eller fjerne componenter.
`NenjimHubImpl` repræsenterer én kørende Nenjim runtime. Hub'en læser deployment-konfigurationen, ejer dependency
wiring og lifecycle, konstruerer hele den nuværende passive component graph og konstruerer kun de processer, som er
valgt til autorun. Et implementation-only Registry assembly udleverer read-only service-view, process-view af det
samme Registry-objekt og en separat `NenjimRegistryServiceManager`. Manageren er kun Hub'ens passive
registrationshandle: den er hverken component eller process, har ingen `start()` eller service-accessor, registreres
ikke og starter aldrig en component.
Et tilsvarende implementation-only Journal assembly udleverer read-only service-view, process-view af det samme
Journal-objekt og en separat passiv `JournalServiceManager`. Journal-manageren registreres ikke og giver kun adgang
til root og refresh gennem et package-private admin-view; almindelige `JournalService`-consumers kan ikke udlede
administrationsadgangen.
Alle moderne JavaFX-applikationer deler ét JVM-wide JavaFX toolkit. Det repræsenteres af
`JavaFxRuntimeService`, mens samme `JavaFxRuntimeServiceImpl`-objekt også implementerer `NenjimProcess` for Hub'ens
lifecycle. Når den er valgt, konstruerer og registrerer Hub'en objektet som `nenjim.javafx-runtime.service`; den skal
stå før valgte JavaFX-applikationer i autorun-listen, så dens service-view kan injiceres efter vellykket startup. Kun
processens `start()` må kalde `Platform.startup(...)`; `runLater(...)` starter aldrig toolkit'et implicit og afviser
arbejde, indtil startup er lykkedes. Startup venter på JavaFX Application Thread og sætter
`Platform.setImplicitExit(false)`. Udelades alle JavaFX-processer, konstruerer Hub'en ikke runtime-objektet og
initialiserer ikke toolkittet.
Den package-private `NenjimRegistryServiceAdmin` er managerens interne mutationsadgang. Den må ikke gøres public,
fordi almindelige consumers ellers kunne caste deres Registry-service til mutationsinterfacet og bryde det
read-only service contract. Registration starter ikke et objekt, og Registry'et forbliver internt åbent for senere
registration efter startup.
### 8.1 Obligatorisk `NenjimHub.conf` format 1
Hub'en læser kun `conf/NenjimHub.conf`. Filen skal eksistere som en læsbar regular file; en manglende eller ugyldig
fil stopper startup, før Registry startes. `conf/NenjimHub.conf.example` er kun en versioneret copy-template: Hub'en
læser, kopierer og genererer den aldrig og falder hverken tilbage til den eller til en hardcoded procesliste.
Den første faktiske entry skal være `FORMAT_VERSION=1`; før den må der kun stå blanke linjer og full-line
`#`-kommentarer. Den næste faktiske entry skal være den ene eksakte `[AUTO_START]`-header. Hver aktiv linje i
sektionen er ét `NenjimComponentId`, og rækkefølgen bevares præcist. Leading/trailing whitespace ignoreres, en trimmet
linje som begynder med `#` er en kommentar, og `#` efter faktisk indhold starter en trailing kommentar. Inde i
sektionen fortsætter en comment-only line listen, mens den første whitespace-only line afslutter sektionen; EOF kan
også afslutte den. Efter afslutningen tillades kun blanke linjer og kommentarer. Formatet har ingen quoting eller
escaping for `#`.
Hele listen valideres før første proces-start. Ugyldige, duplikerede, ukendte og passive component-ID'er afvises.
Registry skal stå præcis én gang først og Journal præcis én gang som nummer to. De kendte valgbare processer er:
```text
nenjim.registry.service
nenjim.journal.service
assetaz.ticker.default
jupiter-perps-alarm.default
evelyn.status.prod
evelyn.status.test
evelyn.iou-burner.prod
nenjim.javafx-runtime.service
evelyn.mission-control.default
nenjim.process-manager.default
```
Ved opgradering erstattes `evelyn.service.prod` med `evelyn.status.prod` og
`evelyn.service.test` med `evelyn.status.test` i deploymentets private `conf/NenjimHub.conf`, hvor de forekommer.
Bevar rækkefølge og aktive/udkommenterede valg. De gamle ID'er accepteres ikke længere. Hub'en konstruerer samme
navngivne `Production`- og `Test`-instanser gennem `EvelynStatusServiceImpl` og injicerer deres
`EvelynStatusService`-views i Mission Control. Process Manager viser de nye ID'er fra Hub'ens startup-snapshot.
Historik ligger fortsat i `data/evelyn//status.log` med formatversion 1 og kræver ingen migration.
Efter validering konstruerer og starter Hub'en Registry, registrerer det som `nenjim.registry.service` og registrerer
startup-milepælen. Derefter konstrueres og registreres hele den nuværende passive graph uden at starte workers eller
processer. Først herefter behandles resten af `[AUTO_START]` i den angivne rækkefølge, begyndende med Journal. Hver
valgt proces konstrueres først, når dens linje nås, registreres før `start()` og tilføjes kun til Hub'ens immutable
ordered snapshot, når `start()` returnerer. Journal er derfor stadig den anden succesfulde proces, selv om den passive
graph konstrueres mellem Registry- og Journal-start.
`[AUTO_START]` er foreløbig deploymentets komplette, manuelt ordnede proces-dependency closure. Hub'en finder,
indsætter eller omordner ikke dependencies. En krævet proces skal stå før sin consumer; eksempelvis skal
`nenjim.javafx-runtime.service` stå før Mission Control og Process Manager. Mangler forgængeren, stopper konstruktion
eller startup fail-fast uden implicit reparation. En udeladt proces bliver hverken konstrueret, registreret, startet
eller vist af Process Manager. Den versionerede template vælger kun de obligatoriske Registry- og Journal-processer;
alle øvrige processer skal tilføjes eksplicit til deploymentets private konfiguration.
Et minimalt headless eksempel, svarende til den versionerede template, er:
```text
FORMAT_VERSION=1
[AUTO_START]
nenjim.registry.service
nenjim.journal.service
```
Tickerens egen component-konfiguration vælger fortsat eksplicit
`assetaz.price-source.raydium-pool.eve-usdt` gennem Registry'et; den hardcodede price source er registreret, men
inaktiv. Fejl under passiv konstruktion, valgt proceskonstruktion, registration eller startup stopper straks og
forhindrer alle senere processer. Tidligere succeser forbliver synlige, den fejlende proces registreres ikke som
startet, og der udføres ingen generic rollback. Online point og det afsluttende blocking wait nås kun efter alle
konfigurerede processer er startet. Process Manager viser fortsat Hub'ens faktiske succesfulde snapshots og ikke den
ønskede konfigurationsliste.
`com.r35157.nenjim.hubd.Main` er kun det yderste Java-bootstrap. `Main.main(...)` konstruerer `NenjimHubImpl` gennem
det globale `NenjimHub`-interface og kalder `start()` præcis én gang. Hub'en ejer også det eksisterende online point
og den afsluttende blocking wait. Hub'en er hverken component eller process og registreres ikke i sit eget Registry.
Det implementerede Registry er ét katalog og er ikke et authorization-system. Contexts, artifact-version semantics,
resolution, classloading, automatic discovery, public runtime loading/registration, removal, persistence, events,
automatic dependency construction/start-all, usage tracking og permissions er fremtidigt arbejde. Den nuværende
autorun-fil er ikke Context resolution eller process discovery. Journal publishing, remote synchronization og
signature validation er ligeledes ikke implementeret.
## 9. Integration med AssetAZ og økonomisk aktivitet
Økonomi, publicering og distribution er fremtidig vision. Format 1 beskriver alene artifaktviden; det indeholder
ingen betalings-, salgs- eller transaktionsadfærd.
## 10. Installation af en NenjimHub
For at NenjimHub'en kan køre godt, skal den leve i et samspil med nogle andre komponenter. Dette kan sættes op på
forskellige måder. Efterfølgende er et eksempel på en opsætning i en Virtuel Maskine, eller en lille fysisk host.
Bemærk at ECC ram er kritisk for stabiliteten, specielt hvis NenjimHub'en skal arbejde med finansielle aktiviteter.
Efterfølgende er en beskrivelse af hvordan man laver en opsætning som virker. Du kan lave specielle rettelser, hvis
du forstår hvad du laver. Det vil dog være en god idé at følge en standard opsætning, så alt bliver lidt nemmere
at styre.
## 10.1 Reference opsætning af Fysisk eller Virtuel Maskine (VM) til NenjimHub
Her beskrives hvordan man laver en standard opsætning af en NenjimHub. Denne opsætning vil også blive refereret til
som reference opsætningen, sådan at man har et fælles udgangspunkt at tale ud fra.
## 10.1.2 Minimale system krav
Det er klart at jo mere NenjimHub'en skal lave, jo større er hardware kravene, men med en 'NenjimHub Reference
Configuration', får du en opsætning der kan starte op og som du kan bygge videre fra.
Derfor er kravene til opsætningen meget moderate.
* CPU: 64bit x86
* RAM: 2GB (Helst ECC)
* Storage: 2x16GB (for RAID)
* Networking: Public IPv4 access
## 10.1.3 Basis Operativ System installation
Hvis du installerer som en VM (Proxmox), så brug følgende:
* Aktiver Qemu Agent
* Virtual Machine type: q35
* BIOS: OVMF (UEFI - med EFI disk + Pre-Enrolled keys)
* Storage: 2 x 16GB (SSD emulation + Discard)
* CPU: 2 CPU cores (type: x86-64-v2-AES)
* Memory: 2GB (Minimum 1GB + Ballooning)
* Network: Adgang til et netværk med DHCP service (Fravælg Proxmox firewall)
Installer basis Operativ System:
- Boot installations medie for Debian-13
- Vælg defaults med mindre andet angivet nedenfor
- User setup:
- Full name: System Operator
- Username: sysop
- Partition disks:
- Manual
- Lav nye tomme partitions tabeller
- Disk 1:
- Partition 1
- Size: 512MB
- Name: EFI1
- Use as: EFI System Partition
- Bootable: on
- Partition 2
- Size: 8GB
- Name: ROOT1
- Use as: Ext4
- Label: ROOT
- Partition 3
- Size: 8.7GB (Resten af disken)
- Name: ZFS1
- Use as: do not use
- Disk 2:
- Partition 1
- Size: 512MB
- Name: EFI2
- Use as: do not use
- Partition 2
- Size: 8GB
- Name: ROOT2
- Use as: do not use
- Partition 3
- Size: 8.7GB (Resten af disken)
- Name: ZFS2
- Use as: do not use
- Acceptér ikke at opsætte swap endnu.
- Software selection:
- SSH server
- standard system utilities
- Reboot after installation
Install additional tools:
```
$ su -
# apt-get update; apt-get install -y htop zram-tools sudo tmux
# usermod -aG sudo sysop
(Log ud og ind igen)
# sudo bash
# vi /etc/default/zramswap
(Ret PRIORITY=1)
# sed -ri'.bak' '/^deb/ { /contrib/! s/$/ contrib/ }' /etc/apt/sources.list
# apt-get update
# mokutil --sb-state || sudo apt -y install mokutil && mokutil --sb-state
# apt install -y dkms sbsigntool shim-signed mokutil
# mokutil --import /var/lib/dkms/mok.pub
(Indtast en midlertidig adgangskode)
# apt-get install -y linux-headers-amd64 zfsutils-linux zfs-dkms zfs-zed
# reboot
(Når den blå skærm kommer, vælg 'Enroll MOK' og brug nu det password du valgte ovenover)
```
Opret ZFS pool:
```
$ sudo bash
# zpool create zfspool -O xattr=sa -o ashift=12 -O compression=lz4 -O checksum=sha512 -O dedup=on -O atime=off mirror /dev/sda3 /dev/sdb3
```
Opret swap:
```
$ sudo bash
# zfs create -V 4G -o compression=zle \
-o logbias=throughput -o sync=always \
-o primarycache=metadata -o secondarycache=none \
-o com.sun:auto-snapshot=false zfspool/swap
# mkswap -f /dev/zvol/zfspool/swap
# echo /dev/zvol/zfspool/swap none swap sw,pri=0 0 0 >> /etc/fstab
# swapon -av
```
Installér docker (using official repository instead of Debian repository):
```
$ sudo bash
# apt install -y apt-transport-https ca-certificates curl gpg
# curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker.gpg
# echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker.gpg] https://download.docker.com/linux/debian trixie stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# apt update
# apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
# usermod -aG docker sysop
(Log out and in again)
```
Flyt docker storage til ZFS:
```
$ sudo bash
# systemctl stop docker
# zfs create -V 3G zfspool/var_lib_docker
# mkfs.ext4 /dev/zvol/zfspool/var_lib_docker
# rm -rf /var/lib/docker
# mkdir /var/lib/docker
# echo "/dev/zvol/zfspool/var_lib_docker /var/lib/docker ext4 defaults 0 2" >> /etc/fstab
# systemctl daemon-reload
# mount /var/lib/docker
# chmod 710 /var/lib/docker
# systemctl enable docker ; systemctl start docker
```
Installer ZeroTier:
```
$ sudo bash
# curl -fsSL 'https://raw.githubusercontent.com/zerotier/ZeroTierOne/main/doc/contact%40zerotier.com.gpg' | gpg --import
(Importer ZeroTier's signeringsnøgle)
# gpg --fingerprint contact@zerotier.com
(Check nøglen)
#if z=$(curl -fsSL 'https://install.zerotier.com/' | gpg --decrypt); then
echo "$z" | sudo bash
else
echo "Signaturtjek mislykkedes – kører ikke scriptet." >&2
exit 1
fi
(Henter og dekryperer (verificerer) install-scriptet og kører det kun hvis signaturen er OK)
```
Konfigurer ZeroTier net:
- Login på 'https://my.zerotier.com'
- Opret et nye netværk 'Create A Network'
(Som skal forbinde terminaler og AssetAZHub)
- Klik på det nye netværk
- Basic/Name: 'assetaz-<ditid>'
(f.eks 'assetaz-mortengh')
- Vælg et IP range, f.eks 192.168.192.*
- Forbind AssetAZHub til netværket (netværks id'et kan ses på websiden):
- # zerotier-cli join a8bea75acfa45477
- Autoriser den nye maskine på nettet. Dette gøres ved at trykke på 'Edit' ved maskinen på websiden, som nu
burde kunne se den. Autoriser den, giv den et navn og evt. en beskrivelse.
- Tryk 'Add IP' og giv den en IP adresse inden for det range du har valgt oven over (f.eks 192.168.192.1). Tryk 'Save'
- Se at AssetAZHub' nu kan pinge sig selv:
# ping 192.168.192.1
Forbind terminal (f.eks en Android telefon)
- Installer ZeroTier-One
- Forbind til det samme net som hub'en.
- Autoriser terminalen inde på ZeroTiers web side og set terminalen ip adresse til noget kendt f.eks 192.168.192.2.
(Så kører hub'en på *.1 og terminalen på *.2)
Opsæt locale
Opret Docker baby swarm cluster
```
```