HOME LAB / NOTATKI TECHNICZNE

Od pomysłu do wdrożenia

Moje notatki z wdrożenia: przykładowe konfiguracje, decyzje integracyjne i wnioski z budowy domowej infrastruktury oraz lokalnego agenta AI.

Stan wdrożenia: 11 września 2026. Przykłady korzystają z danych poglądowych.

01 — Fundament sieciowy

Zacząłem od diagnostyki routera, eksportu konfiguracji, dzierżaw DHCP i rekordów statycznego DNS. Po aktualizacji RouterOS i RouterBOARD zweryfikowałem łączność i wdrożyłem WireGuard. Osobno skonfigurowałem zestawianie VPN, dostęp do DNS, przekazywanie ruchu do LAN oraz NAT do Internetu.

/system resource print
/system routerboard print
/ip dhcp-server lease print
/ip dns static print
/interface wireguard peers print
/ip firewall filter print stats
/ip firewall nat print stats

Tymi odczytowymi komendami oddzielam zestawienie tunelu od dostępności usług. Poprawny handshake WireGuard sam w sobie nie potwierdza działania DNS i reguł forward.

02 — Trwałe usługi na Synology

Przygotowałem niewielkie wdrożenia Compose, trwałe katalogi danych, polityki restartu i wspólny punkt wejścia w Homepage. Monitoring działa niezależnie od komputera AI. Poniżej fragment poglądowy — tagi obrazów i adresy należy dobrać do docelowego środowiska.

services:
  uptime-kuma:
    image: louislam/uptime-kuma:2
    restart: unless-stopped
    ports:
      - "${NAS_LAN_IP}:3001:3001"
    volumes:
      - ./uptime-kuma:/app/data
    mem_limit: 384m
    security_opt:
      - no-new-privileges:true

Pliki muzyczne są w osobnym udziale, montowanym przez Navidrome tylko do odczytu. Baza ma oddzielny mount z zapisem. Caddy kończy połączenie HTTPS i łączy się z Navidrome wewnątrz Dockera, więc kontener muzyki nie potrzebuje wystawionego portu hosta.

services:
  navidrome:
    image: deluan/navidrome:${NAVIDROME_VERSION}
    restart: unless-stopped
    volumes:
      - ./data:/data
      - ${MUSIC_DIRECTORY}:/music:ro
    environment:
      ND_SCANNER_SCHEDULE: "@every 15m"
      ND_ENABLEINSIGHTSCOLLECTOR: "false"
    # No published ports; reverse proxy uses the Docker network.

03 — Główne AI przeniosłem na PC

Mały model CPU na NAS był przydatnym eksperymentem, ale działał zbyt wolno do wygodnej rozmowy. Przeniosłem główną instancję Open WebUI na komputer z GPU i połączyłem ją z Ollamą działającą w Windows.

services:
  open-webui:
    image: ghcr.io/open-webui/open-webui:${WEBUI_VERSION}
    restart: unless-stopped
    environment:
      ENABLE_OLLAMA_API: "True"
      OLLAMA_BASE_URLS: "http://host.docker.internal:11434"
      WEBUI_AUTH: "True"
      ENABLE_VALVE_ENCRYPTION: "True"
      WEBUI_SECRET_KEY: "${WEBUI_SECRET_KEY}"
    volumes:
      - ./data:/app/backend/data
      - ${CONTEXT_DIRECTORY}:/home-ai/context:ro
      - ${DRAFT_DIRECTORY}:/home-ai/drafts:rw

Model widoczny na liście nie oznaczał jeszcze działającego wnioskowania. Sprawdzałem wykrywanie modeli z wnętrza kontenera WebUI, odróżniałem natywne API Ollamy od interfejsu zgodnego z OpenAI i testowałem rzeczywistą odpowiedź.

04 — Od czatu do agenta

Zaimplementowałem osobne narzędzia w Pythonie, zarejestrowałem specyfikacje ich funkcji w Open WebUI i przypisałem identyfikatory do modelu. Natywne wywoływanie funkcji i polska instrukcja systemowa udostępniają je podczas rozmowy. Konfiguracja jest trwała i nie opiera się wyłącznie na jednorazowej wiadomości w czacie.

Model profile:
  function_calling: native
  tools:
    - internet_search
    - pc_observer
    - ssh_operator
    - file_workspace
    - google_workspace
    - image_workflow

Do diagnostyki PC wykorzystałem ograniczony interfejs HTTP w PowerShellu z uwierzytelnianiem tokenem. Poprawiłem obsługę nagłówka i odczyt listy aplikacji z rejestru. Dla SSH przygotowałem osobną usługę z konfiguracją urządzeń, kluczami i dziennikiem operacji. To różne modele uprawnień: odczyt PC nie oznacza odczytowego SSH.

Mój praktyczny test: zapytać o rzeczywiście zainstalowane aplikacje, wykonać wyszukiwanie ze źródłami i odczytać tożsamość urządzenia przez SSH. Sama deklaracja modelu, że coś potrafi, nie jest udanym testem.

05 — Gmail, kalendarz i daty źródłowe

Włączyłem Gmail i Calendar API oraz połączyłem lokalny moduł OAuth. Callback nasłuchuje na loopback komputera. Publiczna informacja o aplikacji i polityka prywatności to statyczne strony na NAS — nie udostępniają modułu Google.

Przełączyłem aplikację OAuth z trybu Testing. Pozwala to uniknąć siedmiodniowej reguły tokenów odświeżania związanej z takim trybem testowym, ale nie znaczy, że tokeny nigdy nie wygasną lub nie zostaną cofnięte. Nie oznacza też ukończenia weryfikacji aplikacji przez Google.

Testy ujawniły dwa istotne błędy: zapytanie o ostatnie maile mogło zwracać mniej wiadomości niż zamówiono, a model mylił datę otrzymania z datą wydarzenia. Dodałem jawne liczby odczytanych wiadomości i odczyt propozycji wydarzenia z ICS. Odpowiedzi na mail przechodzą przez szkic i zatwierdzenie.

06 — ComfyUI i zarządzanie zasobami

Dodałem ComfyUI jako kontener CUDA we wspólnej sieci Dockera. Kontener korzysta z katalogów modeli przez mounty tylko do odczytu, a wyniki zapisuje osobno. Agent tłumaczy opis na prompt obrazu, wysyła workflow przez API i sprawdza historię zadania.

Przetestowałem różne workflowy obrazów, po czym wybrałem Qwen-Image jako główną ścieżkę. Wyniki nadal wymagają przeglądu: udany render może zawierać dodatkowe obiekty lub błędną anatomię. Stałe postacie w wielu scenach pozostają kierunkiem rozwoju.

OLLAMA_KEEP_ALIVE=5m
OLLAMA_MAX_LOADED_MODELS=1
OLLAMA_NUM_PARALLEL=1

# The image tool requests model unloading before/after GPU work.
# ComfyUI runtime: --cache-none --disable-smart-memory

Docker Desktop wprowadza dodatkowy limit pamięci przez WSL. Uwzględniam go oddzielnie od 64 GB RAM komputera. Nie traktuję pozostania pliku modelu w cache jako gwarantowanej funkcji rezydowania modelu w RAM.

07 — Publikacja na własnym NAS

Wizytówka jest statyczna: nie potrzebuje logowania, obsługi formularzy, bazy danych ani kodu wykonywanego w przeglądarce. Caddy serwuje publiczny katalog przez HTTPS i automatycznie odnawia certyfikaty, gdy DNS i dostępność walidacji pozostają poprawne.

www.example.com {
    root * /portfolio/current
    encode gzip
    header {
        X-Content-Type-Options nosniff
        Referrer-Policy strict-origin-when-cross-origin
        Content-Security-Policy "default-src 'none'; style-src 'self'; img-src 'self'; base-uri 'none'; frame-ancestors 'none'; form-action 'none'"
        -Server
    }
    file_server
}

Pliki strony oddzielam od skryptów wdrożeniowych, kluczy certyfikatów i sekretów aplikacji. Przed zmianą proxy zachowuję poprzednią konfigurację do wycofania wdrożenia. Publiczny opis pokazuje architekturę bez publikowania mapy dostępu do urządzeń.

Co chcę rozwijać dalej

  • RAG na wybranych dokumentach, z informacją o źródle i wersji.
  • Rozmowy głosowe po polsku, dostęp rodzinny i wygodniejsza obsługa mobilna.
  • Wybudzanie PC na żądanie, lepsze kolejkowanie GPU i powtarzalne workflowy mediów.
  • Zatwierdzanie operacji wymuszane po stronie usług, niezależne kopie zapasowe i testy odtwarzania.

Najważniejszy wniosek z wdrożenia: sprawdzam każde ogniwo. Zielony kontener, model na liście i dostępne API są potrzebne, ale kryterium odbioru stanowi poprawnie wykonane zadanie.