Infrastructure Reference

itsolutionseu — request & data flow

A 3-node k3s cluster running on Multipass VMs on a Mac, serving real public traffic through Cloudflare. This map traces every hop a request takes, every port each service listens on, and how secrets get from Infisical into running pods.

Cluster k3s v1.36.2, 3× Multipass VM, 4 vCPU / 6GiB / 30GB each Public hosts 5 Namespaces 7

Legend

Edge / routing path Internal service call Secrets sync TLS-encrypted hop ( ) data store

Request path

Browser → Cloudflare → home network → k3s cluster
%%{init: {'theme':'dark', 'themeVariables': { 'primaryColor':'#242832', 'primaryTextColor':'#ebe9e4', 'primaryBorderColor':'#e0924a', 'lineColor':'#7fa1c2', 'secondaryColor':'#1c1f28', 'tertiaryColor':'#14161a', 'fontFamily':'ui-monospace, SF Mono, Menlo, monospace', 'fontSize':'13px' }}}%%
flowchart LR
    Browser(["Browser"])

    subgraph CF["Cloudflare — proxied, SSL: Full (strict)"]
        CFEdge["edge :443\nstamps Cf-Connecting-Ip"]
    end

    subgraph HOME["Home network"]
        Router["router\n:443 → 192.168.4.56"]
        Socat["Mac — socat\n0.0.0.0:443 → 192.168.252.4:443"]
    end

    subgraph K3S["k3s cluster — 192.168.252.0/24"]
        Traefik["Traefik\nweb :80 · websecure :443\nroutes on Host header"]

        subgraph NSAPP["ns/itsolutionseu"]
            Core["core :3000"]
            Stream["stream :3000"]
            InfraApp["infra-app :80"]
            Directus["directus :8055"]
            PG[("postgres :5432\ndirectus · streamdb · infisical")]
        end

        subgraph NSSEC["ns/infisical"]
            Infisical["infisical :8080"]
            Redis[("infisical-redis :6379")]
        end

        subgraph NSLOG["ns/logging"]
            Kibana["kibana :5601"]
            ES[("elasticsearch :9200\nTLS + auth")]
            FluentBit["fluent-bit\n(DaemonSet, 3 nodes)"]
        end

        subgraph NSMON["ns/monitoring"]
            Grafana["grafana :80\npersistent (2Gi PVC)"]
            Prometheus[("prometheus :9090\n7d retention, 10Gi PVC")]
        end

        subgraph NSARGO["ns/argocd"]
            ArgoCD["argocd-server :80\nauto-sync + self-heal"]
        end
    end

    Browser -->|https 443| CFEdge
    CFEdge -->|https 443| Router
    Router -->|https 443| Socat
    Socat -->|tcp passthrough 443| Traefik

    Traefik -->|core.itsolutionseu.com| Core
    Traefik -->|stream.itsolutionseu.com| Stream
    Traefik -->|infra.itsolutionseu.com| InfraApp
    Traefik -->|cms.★.local| Directus
    Traefik -->|kibana.★.com / .local| Kibana
    Traefik -->|secrets.★.local| Infisical
    Traefik -->|grafana.★.com / .local| Grafana
    Traefik -->|argocd.★.local| ArgoCD

    Core -.->|http :8055| Directus
    Directus -->|:5432| PG
    Stream -->|:5432, pg client| PG
    Infisical -->|:5432| PG
    Infisical -->|:6379| Redis

    FluentBit -->|https :9200, fluent_writer| ES
    Kibana -->|https :9200, kibana_system| ES
    Grafana -->|PromQL query| Prometheus
    ArgoCD -.->|apply k8s/itsolutionseu/| Core

    classDef edge fill:#2a2317,stroke:#e0924a,color:#ebe9e4
    classDef app fill:#1a2430,stroke:#7fa1c2,color:#ebe9e4
    classDef data fill:#20242c,stroke:#565c66,color:#ebe9e4
    class Browser,CFEdge,Router,Socat,Traefik edge
    class Core,Stream,InfraApp,Directus,Infisical,Kibana,FluentBit,Grafana,ArgoCD app
    class PG,Redis,ES,Prometheus data
      

CI/CD pipeline

git push → GHCR → Argo CD sync — no manual kubectl/docker for core, stream, or infra-app
%%{init: {'theme':'dark', 'themeVariables': { 'primaryColor':'#242832', 'primaryTextColor':'#ebe9e4', 'primaryBorderColor':'#e0924a', 'lineColor':'#7fa1c2', 'secondaryColor':'#1c1f28', 'tertiaryColor':'#14161a', 'fontFamily':'ui-monospace, SF Mono, Menlo, monospace', 'fontSize':'13px' }}}%%
flowchart LR
    Dev(["git push\napps/core, apps/stream,\napps/infra-app"])

    subgraph GH["GitHub"]
        Repo["itsolutionseu repo\nmain branch"]
        Actions["Actions\narm64 runner"]
    end

    GHCR[("GHCR\nghcr.io/tuffii91/itsolutionseu-*\npublic images")]

    subgraph K3S["k3s cluster"]
        ArgoCD["Argo CD\nns/argocd\nauto-sync + self-heal"]
        Pods["core / stream / infra-app pods\nns/itsolutionseu"]
    end

    Dev -->|push| Repo
    Repo -->|triggers| Actions
    Actions -->|docker build + push| GHCR
    Actions -->|commit image tag bump / regenerate ConfigMap| Repo
    ArgoCD -->|watches k8s/itsolutionseu/| Repo
    ArgoCD -->|apply manifests| Pods
    Pods -->|pull image| GHCR

    classDef edge fill:#2a2317,stroke:#e0924a,color:#ebe9e4
    classDef app fill:#1a2430,stroke:#7fa1c2,color:#ebe9e4
    classDef data fill:#20242c,stroke:#565c66,color:#ebe9e4
    class Dev,Repo,Actions edge
    class ArgoCD,Pods app
    class GHCR data
      

Secrets sync

Infisical operator → cluster secrets, every namespace independently
%%{init: {'theme':'dark', 'themeVariables': { 'primaryColor':'#242832', 'primaryTextColor':'#ebe9e4', 'primaryBorderColor':'#e0924a', 'lineColor':'#7fa1c2', 'secondaryColor':'#1c1f28', 'tertiaryColor':'#14161a', 'fontFamily':'ui-monospace, SF Mono, Menlo, monospace', 'fontSize':'13px' }}}%%
flowchart LR
    Infisical["infisical :8080\nns/infisical"]
    K8sAPI["k3s API :6443\nTokenReview"]
    Operator["Infisical Operator\nns/infisical-operator-system"]
    S1["Secret: postgres\nns/itsolutionseu"]
    S2["Secret: directus\nns/itsolutionseu"]
    S3["Secret: elasticsearch-credentials\nns/logging"]

    Operator -->|Kubernetes Auth: present SA token| K8sAPI
    K8sAPI -->|validated| Operator
    Operator -->|https :8080, pull secrets| Infisical
    Operator -->|create / refresh, 60s interval| S1
    Operator -->|create / refresh, 60s interval| S2
    Operator -->|create / refresh, 60s interval| S3

    classDef sec fill:#1a2430,stroke:#7fa1c2,color:#ebe9e4
    classDef out fill:#20242c,stroke:#565c66,color:#ebe9e4
    class Infisical,Operator,K8sAPI sec
    class S1,S2,S3 out
      

Metrics collection

Pull-based — Prometheus scrapes, nothing pushes to it
%%{init: {'theme':'dark', 'themeVariables': { 'primaryColor':'#242832', 'primaryTextColor':'#ebe9e4', 'primaryBorderColor':'#e0924a', 'lineColor':'#7fa1c2', 'secondaryColor':'#1c1f28', 'tertiaryColor':'#14161a', 'fontFamily':'ui-monospace, SF Mono, Menlo, monospace', 'fontSize':'13px' }}}%%
flowchart LR
    subgraph TARGETS["Scrape targets"]
        NodeExp["node-exporter\nDaemonSet, 3 nodes"]
        Kubelet["kubelet + cAdvisor\nbuilt into k3s"]
        KSM["kube-state-metrics"]
        TraefikM["traefik :9100\n/metrics"]
        Apiserver["apiserver"]
        CoreDNSm["coredns"]
    end
    Prometheus[("prometheus :9090\nns/monitoring")]
    Grafana["grafana :80\nns/monitoring"]
    NodeExp -->|ServiceMonitor| Prometheus
    Kubelet -->|ServiceMonitor| Prometheus
    KSM -->|ServiceMonitor| Prometheus
    TraefikM -->|ServiceMonitor| Prometheus
    Apiserver -->|ServiceMonitor| Prometheus
    CoreDNSm -->|ServiceMonitor| Prometheus
    Grafana -->|PromQL query, on demand| Prometheus
    classDef app fill:#1a2430,stroke:#7fa1c2,color:#ebe9e4
    classDef data fill:#20242c,stroke:#565c66,color:#ebe9e4
    class NodeExp,Kubelet,KSM,TraefikM,Apiserver,CoreDNSm,Grafana app
    class Prometheus data
      

Endpoint reference

Endpoint Port Zone Reached via Auth TLS
core.itsolutionseu.com 443 public Cloudflare → Traefik → core:3000 none Let's Encrypt
stream.itsolutionseu.com 443 public Cloudflare → Traefik → stream:3000 none Let's Encrypt
infra.itsolutionseu.com 443 public Cloudflare → Traefik → infra-app:80 none Let's Encrypt
kibana.itsolutionseu.com 443 public Cloudflare → Traefik → kibana:5601 elastic user login Let's Encrypt
grafana.itsolutionseu.com 443 public Cloudflare → Traefik → grafana:80 admin user login Let's Encrypt
cms.itsolutionseu.local 443 internal only /etc/hosts → Traefik → directus:8055 Directus login self-signed
secrets.itsolutionseu.local 443 internal only /etc/hosts → Traefik → infisical:8080 Infisical login self-signed
kibana.itsolutionseu.local 443 internal only /etc/hosts → Traefik → kibana:5601 elastic user login self-signed
grafana.itsolutionseu.local 443 internal only /etc/hosts → Traefik → grafana:80 admin user login self-signed
argocd.itsolutionseu.local 443 internal only /etc/hosts → Traefik → argocd-server:80 admin user login self-signed
postgres.itsolutionseu.svc 5432 cluster-internal directus, stream, infisical postgres user + password plaintext (in-cluster)
elasticsearch.logging.svc 9200 cluster-internal kibana, fluent-bit kibana_system / fluent_writer / elastic self-signed, xpack
infisical-redis.infisical.svc 6379 cluster-internal infisical backend none plaintext (in-cluster)
k3s API server 6443 cluster-internal kubectl, Infisical operator (TokenReview) kubeconfig / SA token cluster CA
Mac — socat proxy 443 home network router port-forward none — plain TCP passthrough passthrough only

Worth knowing

The real visitor IP isn't in ClientAddr. The Mac's socat proxy terminates and reopens the TCP connection, so Traefik's own ClientAddr field shows an internal cluster address. Cloudflare's Cf-Connecting-Ip header carries the true visitor IP regardless, and Traefik is configured to capture it specifically for this reason.
Elasticsearch is one node, not a cluster. Three 6GiB VMs don't have room for real multi-node Elasticsearch. Security (TLS + auth) is fully enabled regardless, since Kibana is public.
Postgres is one instance, three logical databases. directus, streamdb, and infisical all live on the same pod — kept as one deployment to fit the cluster's resource budget rather than three.
No plaintext secrets in git. Every credential above is minted once, stored in Infisical, and synced into the cluster by the Infisical operator using short-lived Kubernetes Auth tokens — nothing long-lived is stored in-cluster for the sync itself.
GitOps only covers ns/itsolutionseu so far. Argo CD auto-syncs that one namespace from k8s/itsolutionseu/ with prune: true, selfHeal: true — the other namespaces (logging, monitoring, infisical, platform) are still applied by hand with kubectl/helm.