← Blog

· 15 min čitanja #rust#mqtt#iot#unikernel#open source

urMQTT: gradimo MQTT broker koji je ujedno i operacijski sustav

Razvojne bilješke o urMQTT-u, unikernelu napisanom u Rustu koji je sam po sebi MQTT broker: jedan ELF s vlastitim TCP/IP-om, TLS-om 1.3, brokerom i SQLite-om, pokrenut s jednog ISO-a.

Uređaji u vozilima, na parkiralištima i u ormarima s elektronikom imaju jednu zajedničku osobinu: šalju male poruke, rijetko, ali ih je puno i stalno su spojeni. Godinama ih spajamo na MQTT brokere, i godinama nas muči isto pitanje. Zašto za nešto tako jednostavno trebamo cijeli Linux, OpenSSL, runtime nekog jezika, SSH, upravitelj paketa i tek onda broker? Svaki od tih slojeva donosi vlastite ranjivosti, troši vlastitu memoriju i dodaje još nešto što se može pokvariti, a flota uređaja od poslužitelja treba samo troje: da drži puno gotovo neaktivnih veza, da svaki uređaj pouzdano autentificira i da poruke prenese bez gubitka.

Tako je nastao urMQTT: unikernel koji jest MQTT broker. Jezgra, TCP/IP, TLS 1.3, MQTT i ugrađena baza podataka u jednom Rust binarnom programu koji se pokreće s jednog ISO-a. Nema procesa, nema sustavskih poziva, nema ljuske. Prva platforma na kojoj se gradi i testira je aarch64, a isti kod ide prema x86_64, po UEFI-ju i klasičnom BIOS-u, i prema pravom hardveru: cilj je jedan ISO koji se podiže na svemu tome. Projekt je otvorenog koda pod licencom MIT ili Apache 2.0, i u ovom tekstu želimo zapisati gdje smo stigli, kako je iznutra složen i što smo usput naučili.

Što točno znači "unikernel"

Uobičajeni broker je program koji radi na operacijskom sustavu. urMQTT nema operacijski sustav ispod sebe: sam se podiže kroz UEFI firmware i Limine bootloader, postavlja vlastite tablice stranica, programira kontroler prekida i tajmer, pronalazi virtio uređaje preko PCIe-a, dobiva adresu DHCP-om i sluša na jednom portu. Sve što bi inače radila jezgra, upravljački programi, mrežni stog i aplikacija, ovdje je jedan ELF koji radi na razini EL1.

Usporedba s tipičnom instalacijom govori sama za sebe:

Tipičan broker na Linuxu urMQTT
Izloženi servisi SSH, broker, često i port za metrike ili administraciju samo TCP 8883 (MQTT preko TLS-a 1.3 s mTLS-om)
Kod u slici jezgra, userland, libc, OpenSSL, runtime jedan Rust ELF (plus vendorirani SQLite)
Udaljeno upravljanje ljuska, konfiguracijske datoteke, ažuriranja paketa ništa. Nova verzija je novi ISO
Memorija po neaktivnoj vezi kilobajti (međuspremnici socketa, TLS objekti, heap) cilj ≤ 512 B
Višejezgreni model niti i brave ili jedna petlja događaja nit po jezgri, bez dijeljenog stanja, obrada do kraja
Integritet koda moguća su preslikavanja koja su i zapisiva i izvršna W^X, zaključane tablice stranica, PAC/BTI

Prioriteti su, tim redom: sigurnost, skalabilnost, višejezgrene performanse, mali otisak i nepromjenjiva instalacija. Kad god su dva cilja u sukobu, pobjeđuje onaj koji je viši na toj listi.

Gdje smo sada

Projekt je u pred-alfa fazi, ali je zatvoreno sedamnaest razvojnih prekretnica, od M0 do M17. Danas urMQTT poslužuje MQTT 3.1.1 preko TLS-a 1.3 s obaveznim klijentskim certifikatima, a stanje čuva u SQLite-u na sirovom disku. Ukratko, što već radi:

  • Jezgra: vlastiti vektori iznimaka s dekodiranim izvještajima, vlastite tablice stranica s provedenim W^X-om, zaštitne stranice, PAC i BTI gdje ih procesor ima, GICv3 i GICv2, generički tajmer, SMP do 64 jezgre.
  • Otkrivanje hardvera iz DTB-a ili ACPI-ja u jedan opis platforme, s identičnim rezultatom iz oba izvora.
  • Upravljački programi: PCIe ECAM, MSI-X, virtio-net, virtio-blk, virtio-scsi i virtio-rng, te CSPRNG zasijan hardverskom entropijom.
  • Mreža: vlastiti DHCPv4, ARP, ICMP i strogi IPv4, pa vlastiti TCP samo za poslužiteljsku stranu: SYN kolačići, hijerarhijski kotač tajmera, NewReno, spajanje ACK-ova, bez TIME_WAIT stanja.
  • TLS: samo TLS 1.3, obavezni mTLS, identitet uređaja iz CN-a ili SAN URI-ja; rukovanje radi rustls, a nakon njega vlastiti sloj zapisa s AES-128-GCM-om i ChaCha20-Poly1305. Nastavak sjednice PSK ulaznicama, lista opoziva, kontrola prijema već kod rukovanja.
  • MQTT: kodek bez kopiranja, fuzziran i testiran s pravim mosquitto klijentima; QoS 0 i 1, džokeri, zadržane poruke, oporuka (LWT), trajne sjednice, ACL s ograničenjem na devices/{id}/#, ograničenja brzine po uređaju.
  • Pohrana: SQLite unutar jezgre preko VFS-a nad sirovim diskom, u WAL načinu, s provjerom integriteta pri podizanju; registar uređaja, opozivi, zadržane poruke, trajne sjednice s redovima poruka za uređaje koji su offline; po jezgri zaseban telemetrijski dnevnik s CRC-om po zapisu i oporavkom nakon pada.
  • Pogon i nadzor: nadzorni tajmer za obrađivače, zdravstvena provjera, ograničeno logiranje, syslog i statsd preko UDP-a, prijem koji preživljava oluje ponovnih spajanja.
  • Isporuka: bitovno identične ponovne izgradnje provjerene u CI-ju, ISO i sirova GPT slika diska, minisign potpisi, upute za KVM, Proxmox i Hetzner.

Svaki je korak označen prekretnicom koja ga je donijela, a datoteka docs/PROGRESS.md u repozitoriju jedini je izvor istine o tome što stvarno radi.

Arhitektura u tri slike

Cijeli dizajn opisan je u docs/ARCHITECTURE.md, a razlozi za svaku važniju odluku zapisani su kao ADR-ovi u docs/DECISIONS.md. Ovdje je pregled.

Slojevi

Slojevi urMQTT-a: od brokera preko MQTT kodeka, TLS-a, TCP-a i mreže do virtio upravljačkih programa i arhitekturnog sloja, sve u jednom ELF-u na razini EL1.
Slojevi urMQTT-a: od brokera preko MQTT kodeka, TLS-a, TCP-a i mreže do virtio upravljačkih programa i arhitekturnog sloja, sve u jednom ELF-u na razini EL1.

Od vrha prema dnu: broker (sjednice, stablo tema, QoS, zadržane poruke, oporuke, ACL, ograničenja), MQTT kodek, TLS, TCP, mrežni sloj, pa upravljački programi. Pokraj tog glavnog puta stoji pohrana (SQLite i telemetrijski dnevnik), a ispod svega upravljanje memorijom, otkrivanje platforme i konfiguracija koja je u vrijeme izgradnje prevedena u konstante, zajedno s ugrađenim CA certifikatom, poslužiteljskim certifikatom i ključem. Hipervizor s virtio uređajima jedino je što je izvan slike.

Nit po jezgri, bez dijeljenog stanja

Model izvođenja: svaka podatkovna jezgra ima svoju petlju i svoj dio brokera, a najviša jezgra pokreće samo SQLite. Jezgre komuniciraju isključivo SPSC prstenovima.
Model izvođenja: svaka podatkovna jezgra ima svoju petlju i svoj dio brokera, a najviša jezgra pokreće samo SQLite. Jezgre komuniciraju isključivo SPSC prstenovima.

Svaka podatkovna jezgra vrti vlastitu petlju s vlastitim TCP stogom, TLS stanjima, dijelom brokera (sjednice i stablo tema), predmemorijom heapa i particijom telemetrije. Jezgre ne dijele nikakvo promjenjivo stanje, samo ograničene prstenove bez brava, po jedan za svaki uređeni par jezgri. Najviša jezgra pokreće SQLite i ništa drugo.

Mrežna kartica danas ima jedan par redova koji drži jezgra 0. Ona svaki MQTT tok prema Toeplitz hashu njegove četvorke usmjerava na jednu od radnih jezgri i šalje ono što radne jezgre vrate. Sjednica živi na svojoj domaćoj jezgri, određenoj hashom identifikatora klijenta, pa preuzimanje, oporuke i trajnost nikad ne prelaze jezgre. Veza koja sleti na drugu jezgru zadržava tamo svoj TCP i TLS, a običan MQTT prosljeđuje domaćoj jezgri uz kontrolu toka temeljenu na kreditima. Svaka usmjerena poruka razdjeljuje se i na ostale dijelove brokera, od kojih svaki drži repliku zadržanih poruka.

Tri pravila drže taj model na okupu. Obrada do kraja: primljeni paket obrađuje se u cijelosti na jednoj jezgri, od TCP-a preko dešifriranja TLS-a na mjestu, parsiranja MQTT-a i usmjeravanja do šifriranog odgovora, bez redova zadataka i bez kopiranja u aplikacijske međuspremnike. Prilagodljivo ispitivanje: pod opterećenjem se redovi za primanje aktivno ispituju, a u mirovanju se jezgra vraća na prekide i WFI; obrađivači prekida samo potvrde prekid i označe posao. Nadzorni tajmer: otkucaj od 10 ms po jezgri hvata obrađivače koji premaše svoj proračun.

Život jednog PUBLISH-a

Put jedne poruke PUBLISH s QoS 1: od TLS zapisa na mrežnoj kartici preko dešifriranja, provjere ACL-a i usmjeravanja do PUBACK-a spojenog s TCP ACK-om u jednom segmentu.
Put jedne poruke PUBLISH s QoS 1: od TLS zapisa na mrežnoj kartici preko dešifriranja, provjere ACL-a i usmjeravanja do PUBACK-a spojenog s TCP ACK-om u jednom segmentu.

Uređaj pošalje TLS zapis. Mrežna kartica ga preda petlji jezgre deskriptorom, bez kopiranja. Petlja provjeri TCP, dešifrira TLS na mjestu i parsira MQTT iz posuđenog međuspremnika, zatim u memoriji provjeri ACL, ograničenje brzine i put kroz stablo tema. Ako drugu jezgru zanima ta tema, dobije poruku za usmjeravanje s referencom na sadržaj i identifikatorom teme; baza dobije telemetrijski zapis ili ažuriranje zadržane poruke, u paketu. Odgovor PUBACK šifrira se izravno u odlazni međuspremnik i spoji s TCP ACK-om, pa uređaju odlazi jedan segment. Drugu jezgru poruka košta jedno šifriranje po pretplatniku u trenutku slanja.

Koliko košta jedna veza

Cilj je najviše 512 bajtova po neaktivnoj TLS vezi, s težnjom prema 256. Dok veza miruje, ništa se za nju ne drži u međuspremniku: primljeni podaci obrađuju se izravno iz mrežnog okvira, a međuspremnici za slanje, zapise i MQTT postoje samo dok je nešto nedovršeno ili nepotvrđeno. Jezgra to i sama mjeri: točni brojači heapa u traženim bajtovima i u blokovima koje zauzimaju, zapisani svakih deset sekundi kao heap iznad osnovne razine po otvorenoj vezi.

Dio Veličina Kako
TCP kontrolni blok 96 B zapakirane zastavice, 16-bitni RTT/RTO, utor u kotaču tajmera, bez međuspremnika u mirovanju
Utor u TCP tablici 4–8 B samo indeks veze, tablica najviše napola puna
Veza i stanje TLS 1.3 zapisa 152 B tajna i sekvenca po smjeru (40 B); ključ i IV izvode se po zapisu
MQTT veza 48 B identitet i oporuka na heapu samo dok postoje
MQTT sjednica, vrući oblik 64 B jedna pretplata u retku, internirani identifikatori čvorova
Pretplata devices/<id>/cmd/# 0 čvorova stabla pohranjena relativno prema identifikatoru sjednice, zajednička svim uređajima

Izmjereno pod HVF-om s četiri virtualne jezgre, od toga tri radne, pri čemu svaki uređaj drži mTLS vezu i jednu pretplatu s QoS 1, uključujući zaokruživanje alokatora:

Veze Bajtova po vezi
960 531 B
9 922 494 B
10 197 474 B

Bazen mrežnih okvira fiksnih je oko 2 MiB, što je otprilike 200 B po vezi pri deset tisuća veza i oko 2 B pri milijun. Više od toga nismo mogli izmjeriti: QEMU-ovo korisničko umrežavanje na macOS-u prestalo je prihvaćati veze na 10 197, otprilike na granici od 10 240 deskriptora QEMU procesa. Brojka pada kako se fiksni dijelovi raspodjeljuju na više veza, pa ne raste s njihovim brojem.

Sigurnosni model

Sigurnost je prvi prioritet i dobiva sve sukobe s ostalim ciljevima. Model ima nekoliko slojeva:

  • Jedan port. TCP 8883, samo TLS 1.3, obavezni klijentski certifikati potpisani CA-om ugrađenim u sliku. Identifikator MQTT klijenta mora biti jednak identifikatoru uređaja iz certifikata.
  • Nema ulaza. Nema ljuske, konzolnog unosa, SSH-a, administracijskog API-ja, dinamičkog koda, SQL-a dostupnog mrežom ni datotečnog sustava.
  • Memorijska sigurnost. Rust, s forbid(unsafe_code) u protokolnim paketima; svaki unsafe blok ima komentar // SAFETY: koji provjerava lint, a na vanjski unos nema panike: clippy u paketima na podatkovnom putu zabranjuje unwrap, expect, indeksiranje i panic!.
  • Ublažavanje iskorištavanja. W^X provodi se kodiranjem deskriptora i bitom SCTLR_EL1.WXN i revidira pri svakom podizanju. Tablice stranica nakon podizanja su samo za čitanje, bez zapisivog aliasa. Donja polovica adresnog prostora je isključena. Svaki stog ima zaštitne stranice, a iznimke rade na zasebnom stogu. PAC i BTI uključuju se kad ih procesor podržava, i to provjeravaju dimni testovi.
  • Otpornost na zloporabu. SYN kolačići; prijem odbija nove veze, prije ikakve kriptografije, kad je heap nizak, kad baza zaostaje, kad je previše rukovanja u tijeku po jezgri ili po izvornoj adresi ili kad je brzina rukovanja previsoka. Ograničenja brzine po uređaju, ograničeni redovi, TCP prozor vezan uz protutlak brokera, ograničeno logiranje, nadzorni tajmer i zdravstvena provjera.
  • Nepromjenjivost. Konfiguracija, CA i poslužiteljski ključ ugrađeni su u sliku. Promjena bilo čega znači novu sliku.

Model prijetnji zapisan je u docs/SECURITY.md.

Pohrana bez datotečnog sustava

Podaci žive na zasebnom disku, virtio-blk ili virtio-scsi, na kojem nema datotečnog sustava. Raspored je minimalan i vlastiti:

LBA 0      [ superblok: magija · verzija rasporeda · uuid · tablica regija · CRC-32C ]
LBA 8, 16  [ tablica veličina datoteka, utori A/B (najnoviji valjani pobjeđuje) ]
LBA 64     [ SQLite glavna baza ½ ][ SQLite WAL ⅛ ][ dnevnik 1 MiB ][ telemetrijski dnevnik: 8 particija … ]
zadnja 4 KiB [ prostor za samoprovjeru blok-uređaja pri podizanju ]

SQLite (vendorirani 3.54.1, s provjerom sažetka pri izgradnji) preveden je u jezgru clangom, bez standardne biblioteke, i koristi fiksni memsys5 heap. Njegov VFS preslikava tri fiksne datoteke na regije diska. Radi u WAL načinu s locking_mode=EXCLUSIVE, pa mu ne treba indeks u dijeljenoj memoriji, i sa synchronous=FULL; ako quick_check pri podizanju nađe grešku, sustav se sigurno zaustavlja. U bazi su registar uređaja, opozivi, zadržane poruke i trajne sjednice s redovima QoS 1 poruka za uređaje koji nisu spojeni.

Jezgra za bazu, ona s najvišim brojem, pokreće SQLite i ništa drugo. Podatkovna ravnina šalje joj promjene stanja preko SPSC prstena bez brava; ona ih skuplja u jednu transakciju svakih 5 ms ili svakih 512 operacija i potvrde vraća drugim prstenom. Prazan disk formatira se pri prvom podizanju; sve drugo se nikad ne formatira preko.

Telemetrija ide drugim putem. Svaki prihvaćeni PUBLISH na temama iz storage.telemetry_topics odlazi u particiju telemetrijskog dnevnika svoje jezgre: prsten segmenata s CRC-om po zapisu, posoljenim sekvencom segmenta, tako da se stari prolazi prstena nikad ne pojave ponovno. Jezgre predaju zapise bazi vlastitim prstenom, bez kopiranja, a ona ih ispisuje svakih 5 ms ili svakih 256 KiB. Pri podizanju oporavak zadržava svaki ispisani zapis, odsiječe nedovršeni rep i nastavlja u novom segmentu. Zadržavanje je po veličini, kroz prsten, i po starosti, kroz retention_days. Provjerili smo to s milijun zapisa i s kill -9 usred pisanja.

Brojke

Alat za opterećenje u tools/loadgen radi tri stvari: oluju TLS 1.3 rukovanja s mTLS-om i CONNECT-om, dugotrajne veze s PINGREQ-om koje svake sekunde objavljuju telemetriju, i oluje ponovnog spajanja. make bench na Apple M4 Pro pod HVF-om daje:

Radne jezgre rukovanja/s u gostu skaliranje kroz QEMU korisničku mrežu (veza/s)
1 862 1,00× 789
2 1 724 2,00× 636
4 3 438 3,99× 536

Brojka u gostu, gdje su klijent i poslužitelj unutar istog virtualnog stroja i svaka radna jezgra radi sama za sebe, pokazuje da podatkovna ravnina skalira linearno. Mrežna brojka ograničena je jednonitnim korisničkim umrežavanjem QEMU-a, ne gostom; i to je zapisano kao ADR-032.

Oluje ponovnog spajanja testiramo tako da se svi uređaji spoje odjednom, ponavljaju odbijene pokušaje s odgodom i onda svi padnu bez DISCONNECT-a. Parametar heap_limit_mb= u razvojnom načinu natjera prijem da heap smatra manjim nego što jest, pa se oluja veća od heapa može isprobati s malo socketa. U jednom takvom krugu od 3 000 uređaja spojilo se 1 368 u 36 sekundi, a 5 619 pokušaja bilo je uredno odbijeno, uz ograničenje od 8 MiB; memorija se nakon oluje vratila.

Kako radimo

Projekt vodi pisana specifikacija, PROMPT.md, s planom prekretnica, i svaka prekretnica završava istim ritualom: make check i make smoke zeleni, jedan commit s oznakom M<n>, zapis u docs/PROGRESS.md i ADR za svaku odluku koja nije očita. Pravila su kratka i ne pregovaramo o njima: nema panike na vanjski unos, unsafe samo u hardverskim i FFI paketima i uvijek s komentarom, nema alokacija na vrućem putu, komentar uz svaki redoslijed atomskih operacija, svako ograničenje dolazi iz konfiguracije, a namjerni privremeni dijelovi padaju glasno.

CI radi više nego što bismo ručno stigli: fmt, clippy za host i za aarch64-unknown-none, typos, actionlint i shellcheck; testove na Linuxu i macOS-u na arm64; izgradnju jezgre za razvojnu i produkcijsku konfiguraciju s veličinom ELF-a u sažetku; podizanje pod QEMU-om sa svim scenarijima dimnog testa i spremanje serijskih zapisa; cargo-deny za savjete, licence i izvore; minutu fuzzinga po svakoj od jedanaest meta, a noću deset minuta po meti s predmemoriranim korpusom. Uz to CodeQL, OpenSSF Scorecard, Dependabot i objava s SLSA porijeklom. Svaka tuđa akcija zakvačena je na puni commit SHA.

Reproducibilnost shvaćamo doslovno: make repro izgradi HEAD dvaput u svježim radnim stablima i usporedi ELF, ISO i sirovu sliku bajt po bajt. Objave su potpisane minisignom, a artefakti se mogu provjeriti s gh attestation verify. Produkcijska slika sadrži privatni ključ poslužitelja, pa je sam ISO tajna; slike uz objave na GitHubu razvojne su, s privremenim ključevima, i služe samo za isprobavanje.

Što smo naučili

Nekoliko lekcija koje su promijenile plan:

  • Vlastiti TCP ipak se isplatio. Prototip je radio na smoltcp-u i dobro nam je poslužio do M13. Ali poslužitelj koji drži stotine tisuća veza ne treba klijentski TCP, treba SYN kolačiće, kotač tajmera i stanje od 96 bajtova. U M14 smo smoltcp zamijenili vlastitim stogom samo za poslužiteljsku stranu, s testovima simuliranog gubitka i fuzzingom segmenata.
  • Mjerite memoriju iznutra. Procjene po vezi bile su beskorisne dok jezgra nije sama počela brojati heap u blokovima alokatora, a ne u traženim bajtovima. Tek tada smo vidjeli gdje 512 bajtova stvarno odlazi i spustili se na 494.
  • Alat za testiranje je dio proizvoda. Najveće ograničenje nije bila jezgra, nego QEMU-ovo korisničko umrežavanje i broj efemernih portova na razvojnom računalu. Za sto tisuća i više veza treba vmnet-shared na macOS-u ili Linux s KVM-om, tap sučeljem i više klijentskih adresa.
  • SQLite bez operacijskog sustava je moguć, ali samo uz stroge uvjete: fiksni heap, ekskluzivno zaključavanje bez dijeljene memorije, VFS koji ne zna za datoteke, i prijem koji baze ne pušta da zaostane.
  • Oluje ponovnog spajanja su normalno stanje, ne iznimka. Kad padne mobilna mreža i vrati se, tisuće uređaja kucaju istodobno. Zato prijem odbija vezu prije ikakve kriptografije, a svaka odbijena veza košta gotovo ništa.

Što slijedi

Rad nakon M17 planiran je u tri smjera, a redoslijed među njima zapisan je u docs/PLAN.md. Ništa od ovoga još nije izgrađeno.

  • Jedan ISO za više platformi. Ista datoteka urmqtt-<env>-<verzija>.iso i jedna sirova GPT slika koje se podižu na aarch64 UEFI-ju, x86_64 UEFI-ju i x86_64 BIOS-u, u virtualnim strojevima i na pravom hardveru, počevši od jednog Intel PC-a. I dalje uređaj sa svime unutra, reproducibilan i potpisan.
  • Sirovi disk, bez datotečnog sustava. Specifikacija formata na razini bajta, host alat urmqtt-disk koji dijeli parsere s jezgrom, poravnanje regija na 1 MiB, rast diska s podacima, discard za tanko dodijeljene diskove, A/B snimke baze, provjera bitova i, po izboru, šifriranje AES-256-XTS s hardverskim AES-om.
  • Dokazivo sigurno. Opoziv i lista dopuštenih uređaja za vrijeme rada preko potpisanog kontrolnog kanala, bez nove slike; diferencijalno i konformacijsko testiranje vlastitog TLS-a i TCP-a; KASLR, zaštita stoga, kCFI, MTE i ojačani alokator; SQLite izoliran na razini EL0; Secure Boot; SBOM i cargo-vet; i na kraju paket za vanjsku reviziju.

Platforme koje nude samo ne-virtio uređaje, poput AWS ENA-e ili Azure MANA-e, zasad nisu podržane. Raspberry Pi 4 i 5 kao KVM domaćin, Hetzner CAX i Oracle Ampere A1 dokumentirani su i podržani kodom, ali još nisu isprobani na pravoj usluzi.

Isprobajte

Repozitorij je na github.com/zeljan-alduk/urMQTT. Uz Rust s prikvačenim nightly lancem alata i QEMU, make certs, make run i jedan mosquitto klijent dovoljni su za prvi PUBLISH preko mTLS-a na vlastitom računalu. Upozorenje s početka vrijedi i na kraju: ovo je pred-alfa, i sve što radi piše u docs/PROGRESS.md. Prijave grešaka, pitanja o dizajnu i sigurnosne prijave po uputama u SECURITY.md su dobrodošli. O svakoj sljedećoj prekretnici javit ćemo se ovdje.

Komentari

Pravila komentiranja

Pravila komentiranja

Komentari su tu za razmjenu iskustava i pitanja o temama bloga. Da bi rasprava bila korisna svima, vrijede ova pravila.

  1. Pristojnost Bez uvreda, prijetnji, uznemiravanja, govora mržnje i diskriminacije po bilo kojoj osnovi. Kritizirajte argument, ne osobu.
  2. Na temu Komentar se treba odnositi na objavu ili na raspravu ispod nje.
  3. Bez reklama i spama Bez oglašavanja, lančanih poruka i poveznica bez konteksta. Poveznice i slike su dobrodošle kad doprinose raspravi.
  4. Privatnost drugih Ne objavljujte tuđe osobne podatke: imena i prezimena privatnih osoba, adrese, telefone, e-poštu, fotografije bez pristanka.
  5. Autorska prava Objavljujte samo sadržaj koji smijete dijeliti. Kod citiranja navedite izvor.
  6. Jedan identitet Koristite jedan nadimak i ne predstavljajte se kao netko drugi.
  7. Potvrda e-poštom Komentar se objavljuje tek kad potvrdite poveznicu iz e-pošte. Adresa se ne prikazuje i ne koristi se ni za što drugo; nepotvrđeni komentari brišu se nakon 48 sati.
  8. Moderacija Komentare koji krše pravila sakrivamo ili brišemo bez najave, a raspravu možemo zaključati. Odluke moderatora su konačne.
  9. Odgovornost Za sadržaj komentara odgovara njegov autor. Komentari ne odražavaju stavove ALDO TECH-a.
  10. Prijava Neprimjeren sadržaj prijavite na info@aldo.tech.