BACK
// HackerOS Project — Container Runtime

HackerOS Containers

Zaawansowane środowisko uruchomieniowe dla kontenerów napisane w języku Rust. Obsługuje przestrzenie nazw Linux, OverlayFS, cgroups v2, seccomp, CNI, REST API z TLS i autoryzacją, SQLite jako backend stanu, metryki Prometheus z realnym pomiarem CPU oraz OpenTelemetry tracing.

Rust 2021 Linux Namespaces OverlayFS cgroups v2 Seccomp REST API CNI Prometheus SQLite TLS/rustls OpenTelemetry Systemd

01 Przegląd

hco (HackerOS Containers) to lekki, niskopoziomowy runtime kontenerów napisany w Rust. Nie zależy od Dockera ani containerd — zarządza cyklem życia kontenerów bezpośrednio przez syscalle Linuksa.

Główne możliwości:

  • Izolacja przez przestrzenie nazw (UTS, PID, MNT, NET, IPC, USER)
  • OverlayFS — wielowarstwowy system plików jak w Dockerze
  • Ograniczenia zasobów przez cgroups v2 (pamięć, CPU)
  • Pobieranie obrazów OCI z rejestrów (Docker Hub, własne)
  • Przekierowanie portów przez iptables/DNAT (TCP i UDP)
  • Seccomp — filtrowanie syscalli z profili JSON
  • Tryb rootless (user namespaces)
  • Pods — grupy kontenerów ze wspólną siecią/PID/IPC
  • REST API (axum) z opcjonalnym TLS (rustls) i Bearer token auth
  • Eksport metryk w formacie Prometheus z realnym pomiarem CPU (delta)
  • Structured logging (tracing) + OpenTelemetry OTLP exporter
  • SQLite WAL jako backend stanu (zamiast JSON w /var/run)
  • IPAM — pula IP z gwarancją braku kolizji
  • Automatyczne restartowanie (auto_restart)
  • PTY shell — wejście do działającego kontenera
  • Systemd unit + socket activation
⚠ WYMAGANIA Uruchomienie hco wymaga uprawnień root lub odpowiednio skonfigurowanych user namespaces. Większość funkcji sieciowych wymaga roota.

02 Instalacja

HackerOS Linux — instalacja
hacker unpack hackeros-containers

Powyższa komenda pobierze i zainstaluje najnowszą wersję hco wraz ze wszystkimi zależnościami. Po zakończeniu procesu hco będzie dostępne w systemie.

ℹ Uwaga Jeśli używasz innej dystrybucji, skompiluj ze źródeł lub pobierz binaria z repozytorium GitHub.

03 Architektura

Kontener jest tworzony przez wywołanie nix::sched::clone() z odpowiednimi flagami przestrzeni nazw. Proces potomny wywołuje child_entrypoint(), który konfiguruje sieć, montuje OverlayFS, wykonuje pivot_root i uruchamia docelowy program przez execve.

Stan kontenerów i podów jest przechowywany w bazie SQLite w trybie WAL (/var/lib/hackeros/state.db). Adresy IP są zarządzane przez wbudowany moduł IPAM — każdy kontener dostaje unikalny sufiks z puli 2–254.

hco run
  │
  ├─ ImageManager::resolve_image_layers()   ← pobierz/cache OCI
  ├─ setup_overlayfs()                      ← zmontuj rootfs
  ├─ setup_bridge() / setup_cni()           ← skonfiguruj sieć
  ├─ setup_cgroups()                        ← ogranicz zasoby
  ├─ db::ipam_allocate()                    ← przydziel unikalny IP
  ├─ clone(CLONE_NEWUTS|PID|NS|NET|IPC)     ← nowe namespaces
  │     └─ child_entrypoint()
  │           ├─ setup_namespaces()         ← user ns (rootless)
  │           ├─ seccomp_setup()            ← załaduj profil
  │           ├─ sethostname()
  │           ├─ bind mounts (walidowane)
  │           ├─ pivot_root → /
  │           └─ execve(cmd)
  ├─ create_veth_pair()                     ← sieć host↔kontener
  ├─ setup_port_forwarding()                ← iptables DNAT (TCP+UDP)
  ├─ db::insert_container()                 ← zapisz stan + pełny HkConfig
  └─ ContainerLogger::start_capture()      ← capture stdout (100MB limit)

Moduły

src/container.rs
Cykl życia kontenerów, clone(), cleanup, PTY, stats
src/db.rs
SQLite WAL — containers, pods, IPAM. Singleton z parking_lot::Mutex
src/api.rs
REST API (axum 0.7), auth middleware, rate limit, TLS loop
src/tls.rs
rustls ServerConfig z PEM cert/key, PKCS8 i RSA PKCS1
src/metrics.rs
Prometheus gauges + background CPU delta collector (1 s tick)
src/image.rs
OCI pull, cache warstw, digest verify, GC, import tar
src/sandbox.rs
overlayfs, cgroups v2, child entrypoint, pivot_root
src/network.rs
Bridge, veth pair, iptables DNAT/MASQUERADE, CNI, UDP
src/pod.rs
Pods, pause process, shared netns, restart_pod()
src/validation.rs
Walidacja inputów API/CLI — path traversal, nazwy, porty, env
src/logging.rs
ContainerLogger z limitem 100 MB i rotacją 3 plików
src/seccomp.rs
Ładowanie profili JSON seccomp przez libseccomp
ℹ OVERLAYFS Warstwy obrazu są montowane jako lowerdir (read-only). Zmiany trafiają do katalogu upper/ konkretnego kontenera. Po zatrzymaniu kontenera katalog upper/ jest usuwany.

04 CLI — Komendy

run
Uruchom nowy kontener z obrazu OCI
stop
Zatrzymaj działający kontener (SIGTERM → SIGKILL po 10 s)
list / ps
Wyświetl wszystkie kontenery z obrazem i IP
enter
Wejdź do kontenera przez PTY shell
stats
Zasoby kontenera. Dodaj -w dla live loop
pod
Zarządzaj grupami kontenerów (pods)
image
Zarządzaj obrazami OCI (gc, import)
api
Uruchom serwer REST API z opcjonalnym TLS i tokenem

hco run

składnia
hco run <name> -i <image> [opcje]
FlagaOpisPrzykład
-i / --imageObraz OCI do uruchomieniaalpine:latest
-d / --detachedUruchom w tle (daemon)
-p / --publishPrzekierowanie portu host:kontener[/proto]8080:80/tcp
-v / --volumeMontowanie katalogu host:kontener/data:/mnt/data
-e / --envZmienna środowiskowa KEY=VALUE (powtarzalna)-e FOO=bar
--memoryLimit pamięci RAM512MB
--cpuLimit CPU w % (1–100)50
--auto-restartRestart kontenera po zakończeniu
--rootlessUruchom w trybie user namespaces
przykłady
# Uruchom nginx w tle z przekierowaniem portu
hco run my-nginx -i nginx:alpine -p 8080:80 -d

# Uruchom z limitem pamięci i CPU
hco run db -i postgres:15 -e POSTGRES_PASSWORD=secret \
    --memory 512MB --cpu 50 -d

# Uruchom Alpine z wolumenem i auto-restartem
hco run dev-box -i alpine:latest -v /home/user/code:/app \
    --auto-restart -d

# Uruchom w trybie interaktywnym (foreground)
hco run test -i alpine:latest

hco stop

składnia
hco stop <name_lub_id_prefix>

Wysyła SIGTERM, czeka 10 sekund (sprawdzając co 100 ms), następnie wysyła SIGKILL. Czyści iptables (DNAT + FORWARD), veth, OverlayFS, cgroups i wpis z bazy SQLite.

hco list / hco ps

składnia
hco list
hco ps

Wyświetla tabelę z kolumnami: ID (skrócony), NAME, IMAGE, STATUS, IP, POD. Dane pobierane z SQLite.

hco enter

składnia
hco enter <name_lub_id>

Otwiera interaktywną sesję PTY w przestrzeniach nazw działającego kontenera. Wymaga roota.

hco stats

składnia
hco stats <name_lub_id> [-w]

Wyświetla statystyki pamięci i CPU z cgroups v2. Flaga -w / --watch włącza live refresh co 1 sekundę (bez czyszczenia całego ekranu — tylko kursor na górę).

hco image

składnia
# Usuń nieużywane warstwy obrazów (garbage collect)
hco image gc

# Importuj obraz z archiwum Docker save
hco image import my-image:local -f /tmp/myimage.tar

hco api

składnia
hco api [opcje]
FlagaOpisDomyślnie
--api-addrAdres i port nasłuchu127.0.0.1:8080
--api-tokenBearer token dla autoryzacjibrak (dev mode)
--tls-certŚcieżka do pliku PEM z certyfikatembrak (HTTP)
--tls-keyŚcieżka do pliku PEM z kluczem prywatnymbrak (HTTP)
--json-logsLogi w formacie JSON (structured)wyłączone
--otlpEndpoint OTLP gRPC (OpenTelemetry)brak
--dbŚcieżka do pliku bazy SQLite/var/lib/hackeros/state.db
przykład — produkcyjne uruchomienie API
hco api \
  --api-addr 0.0.0.0:8443 \
  --api-token "$(cat /etc/hco/token)" \
  --tls-cert /etc/hco/tls.crt \
  --tls-key  /etc/hco/tls.key \
  --json-logs \
  --otlp http://otel-collector:4317

05 Pliki konfiguracyjne (.hk)

Kontenery można opisywać plikami .hk — własnym formatem konfiguracyjnym HackerOS. Pliki te są ładowane przez HkConfig::from_file().

przykład — myapp.hk
[Metadata]
-> name = "my-app"
-> version = "1.0"
-> authors = "devops@example.com"
-> license = "MIT"

[Specs]
-> base_image = "alpine:latest"
-> memory_limit = "256MB"
-> cpu_percent = 50
-> mounts = "/data:/mnt/data"
-> port_mappings = "8080:80"
-> env = "APP_ENV=production,LOG_LEVEL=info"
-> cmd = "/usr/bin/myapp,--config,/etc/app.conf"

[Runtime]
-> auto_restart = true
-> network_mode = "bridge"

[Security]
-> rootless = false
-> readonly_root = false
-> drop_caps = "CAP_SYS_ADMIN"
-> seccomp_profile = "/etc/hco/profiles/default.json"

[Network]
-> bridge_name = "hkbr0"
-> subnet = "10.10.0.0/24"
-> gateway = "10.10.0.1"
ℹ PERSIST CONFIG Pełna konfiguracja (HkConfig) jest serializowana jako JSON i zapisywana w kolumnie config_json w bazie SQLite. Dzięki temu restart_container() może odtworzyć dokładnie te same parametry bez żadnych dodatkowych plików.

Sekcje konfiguracji

SekcjaPoleTypOpis
[Metadata]namestringNazwa kontenera
versionstringWersja obrazu/konfiguracji
authorsstringAutorzy
licensestringLicencja
[Specs]base_imagestringObraz OCI (np. alpine:latest)
memory_limitstringLimit pamięci: 256MB, 1GB
cpu_percentnumberLimit CPU w procentach (1–100)
mountsstringMontowania oddzielone przecinkami
port_mappingsstringPrzekierowania portów host:kontenera[/proto]
envstringZmienne środowiskowe KEY=val
cmdstringKomenda do uruchomienia
[Runtime]auto_restartboolAutomatyczny restart po zakończeniu
network_modestringbridge | cni | none
cni_networkstringNazwa sieci CNI (opcjonalne)
[Security]rootlessboolTryb bez roota (user namespaces)
readonly_rootboolRead-only rootfs
drop_capsstringCapabilities do usunięcia
allow_raw_socketsboolZezwól na gniazda raw
seccomp_profilestringŚcieżka do profilu JSON seccomp

06 Pods

Pod to grupa kontenerów współdzielących przestrzenie nazw sieci, PID i/lub IPC. Wzorowane na Kubernetes Pods — kontenery w jednym podzie widzą się nawzajem przez localhost.

Każdy pod uruchamia proces pause (/usr/libexec/hco/pause), który trzyma współdzielone przestrzenie nazw przez cały czas życia poda. Jeśli binarium pause nie istnieje, używany jest fallback sleep infinity.

Plik specyfikacji poda (YAML)

my-pod.yaml
name: web-pod
shared_network: true
shared_pid: false
shared_ipc: true
containers:
  - metadata:
      name: web
      version: "1.0"
      authors: ""
      license: ""
    specs:
      base_image: nginx:alpine
      port_mappings: ["80:80"]
      mounts: []
      env: []
      cmd: []
    runtime:
      auto_restart: false
      network_mode: none
    security:
      rootless: false
      readonly_root: false
      allow_raw_sockets: true
      drop_caps: []
  - metadata:
      name: sidecar
    specs:
      base_image: alpine:latest
      cmd: ["/bin/sh", "-c", "while true; do sleep 5; done"]

Komendy pod

bash
# Utwórz i uruchom poda ze specyfikacji YAML
hco pod create my-pod -f my-pod.yaml

# Wyświetl działające pods
hco pod list

# Zrestartuj zatrzymane kontenery w podzie
hco pod start my-pod

# Zatrzymaj poda (i wszystkie jego kontenery)
hco pod stop my-pod
ℹ SHARED NETWORK Gdy shared_network: true, tworzony jest dedykowany network namespace dla całego poda przez ip netns add pod-<name>. Wszystkie kontenery w podzie używają network_mode: none i wchodzą do wspólnego netns.
ℹ RESTART POD hco pod start <name> sprawdza każdy kontener w podzie przez SQLite. Jeśli kontener nie działa, odczytuje jego config_json i restartuje z dokładnie tymi samymi parametrami.

07 REST API

Po uruchomieniu hco api dostępny jest serwer HTTP/HTTPS (axum 0.7) z endpointami do zarządzania kontenerami i podami. Serwer obsługuje paginację, timeouty żądań (60 s), limit rozmiaru body (10 MB) oraz opcjonalną autoryzację Bearer tokenem.

uruchomienie (dev — plain HTTP)
hco api --api-addr 0.0.0.0:8080
uruchomienie (produkcja — TLS + auth)
hco api \
  --api-addr 0.0.0.0:8443 \
  --api-token my-secret-token \
  --tls-cert /etc/hco/tls.crt \
  --tls-key  /etc/hco/tls.key

Endpointy — Kontenery

MetodaŚcieżkaOpis
GET/containersLista kontenerów (paginacja: ?page=1&per_page=50)
POST/containersUtwórz i uruchom nowy kontener (timeout 300 s)
DELETE/containers/:idZatrzymaj i usuń kontener
POST/containers/:id/startZrestartuj kontener (odczytuje config z SQLite) NOWE
POST/containers/:id/stopZatrzymaj kontener
GET/containers/:id/logsPobierz logi stdout kontenera

Endpointy — Pods

MetodaŚcieżkaOpis
GET/podsLista podów (paginacja: ?page=1&per_page=50)
POST/podsUtwórz i uruchom nowego poda (timeout 600 s)
DELETE/pods/:nameZatrzymaj i usuń poda
POST/pods/:name/startZrestartuj zatrzymane kontenery w podzie NOWE
POST/pods/:name/stopZatrzymaj poda

Endpointy — System ZAKTUALIZOWANE

MetodaŚcieżkaAuthOpis
GET/healthpublicznyHealth check — status, wersja, liczba działających kontenerów
GET/metricspublicznyMetryki Prometheus text (Content-Type: text/plain; version=0.0.4)
ℹ /health i /metrics są publiczne Endpointy /health i /metrics nie wymagają tokenu auth — są dostępne publicznie, co umożliwia scraping przez Prometheus i health check przez load balancer bez przekazywania tokenu.

Paginacja

Listy kontenerów i podów obsługują paginację przez query string:

GET /containers?page=2&per_page=25
GET /pods?page=1&per_page=10
odpowiedź
{
  "containers": [...],
  "total": 142,
  "page": 2,
  "per_page": 25
}

Przykład — tworzenie kontenera (curl)

bash
curl -X POST https://localhost:8443/containers \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer my-secret-token" \
  -d '{
    "name": "my-nginx",
    "image": "nginx:alpine",
    "ports": ["8080:80/tcp"],
    "env": ["NGINX_ENTRYPOINT_QUIET_LOGS=1"],
    "memory_limit": "128MB",
    "cpu_percent": 25,
    "auto_restart": true
  }'
odpowiedź — 201 Created
{ "id": "a3f7c2d1-8b4e-4f2a-b1c3-d5e6f7a8b9c0" }

Health check

bash
curl https://localhost:8443/health
odpowiedź — 200 OK
{
  "status": "ok",
  "version": "0.3.0",
  "containers_running": 5
}

Schemat błędów

HTTPKiedy
400 Bad RequestNieprawidłowy input — błąd walidacji nazwy, obrazu, portu, montowania, timeout startu
401 UnauthorizedBrakujący lub nieprawidłowy Bearer token
404 Not FoundKontener lub pod nie istnieje
500 Internal Server ErrorBłąd runtime — szczegóły w polu error
JSON — błąd
{ "error": "Invalid port mapping '99999:80': port numbers must be > 0" }

08 Autoryzacja API NOWE

API obsługuje opcjonalną autoryzację przez Bearer token. Gdy --api-token jest podany, wszystkie chronione endpointy wymagają nagłówka Authorization: Bearer <token>. Brak tokenu lub nieprawidłowy token zwraca 401 Unauthorized.

⚠ DEV MODE Jeśli --api-token nie jest podany, API działa bez autoryzacji. W środowisku produkcyjnym zawsze ustaw token i włącz TLS.
przykład — curl z tokenem
# Ustaw token przy starcie
hco api --api-token "$(openssl rand -hex 32)"

# Użyj tokenu w żądaniach
curl -H "Authorization: Bearer <token>" \
     https://localhost:8443/containers

Endpointy GET /health i GET /metricspubliczne — nie wymagają tokenu, co umożliwia zewnętrzny scraping metryk i health check przez load balancer.

09 TLS / HTTPS NOWE

Serwer API obsługuje TLS przez bibliotekę rustls (bez OpenSSL). Certyfikat i klucz prywatny podajesz w formacie PEM. Obsługiwane formaty klucza: PKCS8 i RSA PKCS1.

Generowanie self-signed certyfikatu (dev)

bash
mkdir -p /etc/hco
openssl req -x509 -newkey rsa:4096 -keyout /etc/hco/tls.key \
  -out /etc/hco/tls.crt -days 365 -nodes \
  -subj "/CN=hco-api/O=HackerOS"

Uruchomienie z TLS

bash
hco api \
  --api-addr 0.0.0.0:8443 \
  --tls-cert /etc/hco/tls.crt \
  --tls-key  /etc/hco/tls.key \
  --api-token my-secret
ℹ FALLBACK Jeśli --tls-cert lub --tls-key są podane, ale pliki nie istnieją, serwer automatycznie wraca do trybu plain HTTP z ostrzeżeniem w logach.

Implementacja

TLS loop w src/api.rs akceptuje połączenia przez tokio::net::TcpListener, opakowuje je w tokio_rustls::TlsAcceptor i podaje do hyper 1.x przez adapter TowerToHyperService (bridge między tower::Service a hyper::service::Service).

10 Metryki Prometheus ZAKTUALIZOWANE

Serwer API eksportuje metryki pod GET /metrics w formacie Prometheus text. Metryki CPU są teraz realne — background task (spawn_metrics_collector) co 1 sekundę czyta cpu.stat z cgroup v2, oblicza deltę usage_usec i przelicza na procenty z uwzględnieniem liczby rdzeni CPU.

MetrykaTypOpis
hco_containers_totalGaugeŁączna liczba kiedykolwiek stworzonych kontenerów
hco_containers_runningGaugeAktualnie działające kontenery
hco_container_memory_bytesGaugeVecUżycie pamięci z memory.current (labels: id, name)
hco_container_cpu_usage_percentGaugeVecRzeczywiste użycie CPU % w oknie 1 s (labels: id, name)
hco_container_start_totalCounterŁączna liczba startów kontenerów
✓ REALNE METRYKI CPU W poprzedniej wersji metryki CPU były zawsze 0. Teraz background task co sekundę czyta usage_usec z cgroup v2, oblicza: cpu% = (Δusage_usec / Δwall_usec) * 100 / num_cpus.
przykładowe dane
# HELP hco_containers_running Number of currently running containers
# TYPE hco_containers_running gauge
hco_containers_running 3

# HELP hco_container_memory_bytes Memory usage in bytes
# TYPE hco_container_memory_bytes gauge
hco_container_memory_bytes{id="a3f7...",name="my-nginx"} 1.24e+07

# HELP hco_container_cpu_usage_percent CPU usage percent (1-second window)
# TYPE hco_container_cpu_usage_percent gauge
hco_container_cpu_usage_percent{id="a3f7...",name="my-nginx"} 2.3

Konfiguracja Prometheus scrape

prometheus.yml
scrape_configs:
  - job_name: 'hco'
    static_configs:
      - targets: ['localhost:8080']
    metrics_path: /metrics
    scrape_interval: 5s

11 Observability / OpenTelemetry NOWE

hco używa biblioteki tracing do structured logging. Wspiera eksport tracingów przez protokół OTLP gRPC do OpenTelemetry Collector, Jaeger, Tempo lub innego backendu.

Structured logging

Domyślnie logi są wypisywane w formacie tekstowym. Flaga --json-logs włącza format JSON:

bash
hco api --json-logs 2>&1 | jq .
przykładowy log JSON
{
  "timestamp": "2025-05-18T12:34:56.789Z",
  "level": "INFO",
  "target": "hco::container",
  "fields": {
    "id": "a3f7c2d1",
    "name": "my-nginx",
    "pid": 12345,
    "ip": "10.10.0.5",
    "message": "Container started"
  }
}

OpenTelemetry OTLP

Flaga --otlp włącza eksport tracingów do OTLP endpoint (gRPC):

bash
hco api --otlp http://localhost:4317 --json-logs
ℹ JSON WYMAGANY Z OTLP Gdy OTel jest aktywny, logi są automatycznie formatowane jako JSON (wymóg JsonFields dla trait bound OpenTelemetryLayer).

Poziom logowania

Steruj poziomem przez zmienną środowiskową:

bash
# Pokaż tylko błędy i ostrzeżenia
RUST_LOG=warn hco api

# Debug dla modułu hco::container
RUST_LOG=warn,hco::container=debug hco api

12 Seccomp / Bezpieczeństwo

hco obsługuje filtrowanie syscalli przez seccomp przy użyciu biblioteki libseccomp. Profile są plikami JSON kompatybilnymi ze schematem Docker/Podman.

Walidacja inputów

Moduł src/validation.rs waliduje wszystkie dane wejściowe CLI i API:

  • Nazwy — tylko [a-zA-Z0-9_-], max 128 znaków
  • Obrazy — blokuje metaznaki shell ($ ; & | ` \ { })
  • Montowania — blokuje path traversal (../), wymaga ścieżek absolutnych, blokuje wrażliwe ścieżki (/proc, /sys, /etc/shadow itd.)
  • Porty — format host:container[/tcp|udp], zakres 1–65535
  • Env — klucz musi pasować do [A-Za-z_][A-Za-z0-9_]*
  • Memory limit — format \d+(B|KB|MB|GB)
  • CPU percent — zakres 1–100

Format profilu seccomp (JSON)

default-profile.json
{
  "default_action": "SCMP_ACT_ERRNO",
  "architectures": ["x86_64", "aarch64"],
  "syscalls": [
    {
      "names": ["read", "write", "open", "close", "stat",
                "fstat", "lstat", "poll", "lseek", "mmap",
                "mprotect", "munmap", "brk", "rt_sigaction",
                "rt_sigprocmask", "ioctl", "access", "pipe",
                "select", "nanosleep", "getpid", "fork",
                "execve", "exit", "exit_group", "getdents64"],
      "action": "SCMP_ACT_ALLOW"
    }
  ]
}

Dostępne akcje

AkcjaEfekt
SCMP_ACT_ALLOWPrzepuść syscall
SCMP_ACT_ERRNOZwróć EPERM (domyślny błąd)
SCMP_ACT_ERRNO(N)Zwróć errno o numerze N
SCMP_ACT_KILLZabij wątek
SCMP_ACT_KILL_PROCESSZabij cały proces
SCMP_ACT_TRAPWyślij SIGSYS
SCMP_ACT_LOGLoguj (przepuść)
🔒 BEZPIECZEŃSTWO Domyślnie, jeśli nie podano profilu seccomp, kontener nie ma żadnych ograniczeń na poziomie syscalli. Zawsze stosuj profil seccomp w środowiskach produkcyjnych.

13 Stan — SQLite NOWE

Stan kontenerów, podów i alokacji IP jest przechowywany w bazie danych SQLite w trybie WAL (Write-Ahead Logging). Zastępuje poprzednie podejście z plikami JSON w /var/run/hackeros/, eliminując race conditions przy równoległych operacjach.

Lokalizacja bazy

/var/lib/hackeros/state.db

Można zmienić przez flagę --db <path> przy starcie hco api.

Schemat bazy

TabelaZawartość
containersStan kontenera + pełny HkConfig jako JSON w kolumnie config_json. Umożliwia restart po zatrzymaniu.
podsStan poda + spec YAML jako JSON. Lista ID kontenerów w container_ids_json.
ipamPula adresów IP — sufiks (2–254), container_id, subnet_prefix, flaga released.
schema_versionWersja schematu (migracje automatyczne).
bash — podgląd stanu przez sqlite3
sqlite3 /var/lib/hackeros/state.db \
  "SELECT id, name, image, status, ip_address FROM containers;"

# Sprawdź alokacje IP
sqlite3 /var/lib/hackeros/state.db \
  "SELECT container_id, suffix, released FROM ipam;"
ℹ IPAM Każdy kontener dostaje unikalny sufiks IP z puli 2–254 przez funkcję db::ipam_allocate(). Po zatrzymaniu kontenera sufiks jest oznaczany jako released=1 i może być ponownie użyty. Eliminuje kolizje IP przy dużej liczbie kontenerów.

14 Systemd / Socket Activation NOWE

hco dostarcza plik unit systemd (hco-api.service) oraz opcjonalny plik socket (hco-api.socket) dla socket activation.

Instalacja

bash
sudo cp hco-api.service /etc/systemd/system/
sudo cp hco-api.socket  /etc/systemd/system/   # opcjonalnie

sudo systemctl daemon-reload
sudo systemctl enable --now hco-api.service

Konfiguracja przez EnvironmentFile

Utwórz plik /etc/hco/hco.env z nadpisaniami:

/etc/hco/hco.env
HCO_API_ADDR=0.0.0.0:8443
HCO_API_TOKEN=my-production-secret
HCO_TLS_CERT=/etc/hco/tls.crt
HCO_TLS_KEY=/etc/hco/tls.key
HCO_OTLP=http://otel-collector:4317
RUST_LOG=hco=info

Zarządzanie serwisem

bash
# Status serwisu
systemctl status hco-api

# Logi (journald)
journalctl -u hco-api -f

# Restart
systemctl restart hco-api

Socket Activation

Plik hco-api.socket umożliwia uruchomienie serwisu dopiero przy pierwszym połączeniu na port 8080. Oszczędza zasoby przy starcie systemu.

bash
sudo systemctl enable --now hco-api.socket
# hco-api.service uruchomi się automatycznie przy pierwszym połączeniu
⚠ UPRAWNIENIA Serwis uruchamiany jest jako root (wymagane dla namespaces i cgroups). CapabilityBoundingSet ogranicza do niezbędnego minimum: CAP_SYS_ADMIN, CAP_NET_ADMIN, CAP_MKNOD, CAP_SETUID, CAP_SETGID, CAP_CHOWN, CAP_DAC_OVERRIDE, CAP_SYS_CHROOT.

15 Sieć / CNI

Domyślny tryb sieciowy to bridge. Każdy kontener dostaje parę interfejsów veth: jeden po stronie hosta (podłączony do mostu hkbr0), drugi wewnątrz kontenera jako eth0. Adres IP jest przydzielany przez IPAM z gwarancją unikalności.

Tryby sieci

TrybOpis
bridgeDomyślny. Most hkbr0, veth, iptables NAT/DNAT (TCP i UDP)
cniZewnętrzne wtyczki CNI przez cnitool
noneBrak sieci (używane przez kontenery w podach ze shared_network)

Konfiguracja mostu

Most jest tworzony automatycznie przy pierwszym uruchomieniu:

Domyślna podsieć: 10.10.0.0/24
Gateway:         10.10.0.1  (przypisany do hkbr0)
IP kontenerów:   10.10.0.2 — 10.10.0.254  (zarządzane przez IPAM)
NAT:             iptables MASQUERADE na ruch wychodzący
FORWARD:         reguły ACCEPT dla każdego przekierowanego portu

Przekierowanie portów

Reguły iptables DNAT są dodawane dla każdego mapowania portów. Obsługiwane protokoły: tcp i udp. Nieużywany interfejs veth host-side jest usuwany przez ip link del po zatrzymaniu kontenera (nazwa zapisana w SQLite jako veth_host).

przykład — port UDP
hco run dns -i coredns:latest -p 5353:53/udp -d
ℹ IPAM Adresy IP są przydzielane z puli przez db::ipam_allocate(). Po zatrzymaniu kontenera adres jest zwalniany (released=1) i może być ponownie użyty. Eliminuje kolizje przy dużej liczbie kontenerów.

16 Obrazy OCI

hco pobiera obrazy bezpośrednio z rejestrów OCI (Docker Hub, prywatne) bez potrzeby instalowania Dockera. Warstwy są buforowane lokalnie.

Format referencji obrazu

FormatPrzykładRozwinięcie
namealpineregistry-1.docker.io/library/alpine:latest
name:tagnginx:alpineregistry-1.docker.io/library/nginx:alpine
user/repo:tagmyuser/myapp:v1registry-1.docker.io/myuser/myapp:v1
registry/repo:tagghcr.io/org/app:latestBezpośrednie użycie rejestru

Cache warstw i timeouty

Warstwy obrazów są zapisywane w /var/lib/hackeros/layers/. Przy ponownym użyciu tej samej warstwy (identyczny digest SHA256) pobieranie jest pomijane. Każda pobrana warstwa jest weryfikowana przez SHA256.

OperacjaTimeout
Pobieranie manifestu / auth token30 s
Pobieranie warstwy300 s
Start kontenera (API)300 s
Start poda (API)600 s

Garbage collect

bash
# Usuń warstwy nieużywane przez żaden obraz
hco image gc

Import z archiwum tar

bash
hco image import my-image:local -f /tmp/myimage.tar

17 Błędy i diagnostyka

hco używa biblioteki miette do czytelnych komunikatów błędów z kontekstem i wskazówkami. Logowanie odbywa się przez tracing z filtrem kontrolowanym przez RUST_LOG.

Logi kontenerów

Stdout kontenera jest przechwytywany do pliku z limitem 100 MB i rotacją 3 plików (np. .log.1, .log.2, .log.3):

/var/log/hackeros/<container-id>.log
bash — podgląd logów
tail -f /var/log/hackeros/a3f7c2d1-8b4e-4f2a-b1c3-d5e6f7a8b9c0.log

# Lub przez API:
curl -H "Authorization: Bearer <token>" \
     https://localhost:8443/containers/a3f7c/logs | jq .logs

Rollback przy błędzie startu

Jeśli start kontenera nie powiedzie się na dowolnym etapie (np. błąd sieci po zamontowaniu OverlayFS), struktura StartResources automatycznie cofa wszystkie operacje: odmontowuje overlayfs, usuwa veth, czyści reguły iptables, usuwa wpis z SQLite i zwalnia IP z IPAM.

Typowe błędy

BłądPrzyczynaRozwiązanie
Failed to clone container processBrak uprawnień root lub brak obsługi namespaceUruchom jako root lub włącz user namespaces w kernelu
Cannot bind addrPort zajęty lub brak uprawnieńSprawdź ss -tlnp, zmień port API
Failed to get manifestBrak dostępu do rejestru lub zły tag obrazuSprawdź połączenie i nazwę obrazu
Digest mismatchUszkodzona warstwa podczas pobieraniaUsuń cache: rm -rf /var/lib/hackeros/images/<img>
Container not foundPodany ID/nazwa nie istnieje w SQLiteSprawdź hco list
IPAM pool exhaustedBrak wolnych adresów IP (wszystkie 253 zajęte)Zatrzymaj nieużywane kontenery
Invalid mount specŚcieżka relatywna, traversal lub wrażliwa ścieżkaUżyj bezwzględnej ścieżki poza /proc, /sys
Cannot open TLS cert/keyPlik nie istnieje lub brak uprawnień odczytuSprawdź ścieżki i chmod 600 /etc/hco/tls.key
Failed to create seccomp filterKernel nie obsługuje seccomp lub brak libseccompSprawdź CONFIG_SECCOMP i zainstaluj libseccomp-dev
UnauthorizedBrakujący lub nieprawidłowy Bearer tokenDodaj nagłówek Authorization: Bearer <token>

18 Licencja

HackerOS Containers jest udostępniany na licencji MIT.

Copyright (c) HackerOS Team <hackeros068@gmail.com>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.