Server Introduction
Hardware specifications, storage layout, network topology, and the base Docker environment that underpins the entire Centerpoint stack.
Overview & Hardware
Overview & Hardware tags: [hardware, centerpoint, specs]
Overview
Centerpoint is the primary homelab server — a Mini PC form factor running a full self-hosted Docker stack. It acts as the central compute node for all containerised services, reverse proxying, media, AI inference, and automation in the homelab.
| Property | Value |
|---|---|
| Hostname | centerpoint |
| Role | Primary Docker host |
| Form Factor | Mini PC (NUC-style) |
| IP Address | 192.168.1.85 |
| Tailscale IP | 100.117.158.101 |
| OS | Ubuntu 24.04.4 LTS (Noble Numbat) |
| Kernel | 6.17.0-35-generic |
CPU
| Property | Value |
|---|---|
| Model | Intel Core Ultra 9 285H |
| Core Architecture | P-cores only (no hyperthreading) |
| Physical Cores | 16 |
| Sockets | 1 |
| Threads | 16 (1 per core) |
The 285H is an Intel Meteor Lake H-series mobile processor with a dedicated Neural Processing Unit (NPU). The absence of E-cores or hyperthreading means all 16 logical CPUs are full performance cores, which benefits parallel container workloads.
Memory
| Property | Value |
|---|---|
| Total RAM | 96 GB |
At time of writing, approximately 33 GB is actively in use with ~9 GB free and ~49 GB used as page cache — normal for a long-running Linux system running a large Docker stack.
Notes
- Uptime is typically measured in weeks; the system runs continuously.
- The NPU in the 285H is not currently leveraged by any container workload — it is available for future OpenVINO or AI inference optimisation.
Last Updated: 2026-06-16
Storage Layout
Overview
Centerpoint uses a three-tier storage strategy:
- Local NVMe — fast system and application data storage
- Ceph OSD block devices — two NVMe drives contributing to a distributed Ceph cluster for object/block storage across the homelab
- NFS mounts from UnRAID — bulk media and data storage from the NAS server at
192.168.1.119
Local NVMe Drives
System Drive — nvme1n1 (1.8 TB)
The primary system disk, GPT-partitioned with LVM.
| Partition | Size | Mount Point | Purpose |
|---|---|---|---|
nvme1n1p1 |
1 GB | /boot/efi |
EFI System Partition |
nvme1n1p2 |
2 GB | /boot |
Boot partition |
nvme1n1p3 (LVM PV) |
1.8 TB | — | LVM physical volume |
ubuntu-vg/ubuntu-lv |
1.8 TB | / |
Root filesystem |
Current usage: 520 GB used / 1.3 TB free
This drive holds the OS, all Docker image layers (/var/lib/docker), container
volumes, and the compose project files under /home/jeeves/docker/.
Ceph OSD — nvme0n1 (931.5 GB)
Configured as a Ceph OSD block device under LVM management.
Mounted at /media/jeeves/1TB_Vol2.
The volume appears nearly empty at the filesystem level because Ceph manages the block device directly — actual utilised capacity is tracked by the Ceph cluster, not the OS mount point.
Ceph OSD — nvme2n1 (931.5 GB)
Second Ceph OSD block device, LVM-managed.
Mounted at /media/jeeves/1TB_Vol1. Shows ~115 GB used at the OS level; the
remainder is managed by Ceph.
Both Ceph OSD drives contribute to a distributed storage pool shared across the homelab. Ceph provides replication and data protection at the cluster level rather than at the individual host level.
NFS Mounts — UnRAID (192.168.1.119)
UnRAID at 192.168.1.119 hosts a 38 TB storage pool (~32 TB in use) and exports
three NFS shares, auto-mounted on Centerpoint at boot.
| Mount Point | NFS Source | Consumer Services |
|---|---|---|
/mnt/Photos |
192.168.1.119:/mnt/user/Photos |
Immich |
/mnt/data |
192.168.1.119:/mnt/user/Data |
General / miscellaneous |
/mnt/Multimedia |
192.168.1.119:/mnt/user/Multimedia |
Plex, Jellyfin, Stash, Audiobookshelf |
These paths are bind-mounted into media containers — the media files themselves are never stored locally on Centerpoint.
Notes / Gotchas
- If UnRAID is offline or rebooting, NFS mounts will stall and any container with
a bind mount into
/mnt/*will hang or fail to start until the mount recovers. - Docker named volumes (databases, config state, etc.) all reside on the system
NVMe under
/var/lib/docker/volumes/— these are not automatically backed up to UnRAID. - The Ceph cluster should be monitored independently; degraded OSD status does not surface through Docker or the OS mounts in any obvious way.
Last Updated: 2026-06-16
Networking
Overview
Centerpoint is reachable via four distinct paths depending on the use case.
| Path | Address / Domain | Use Case |
|---|---|---|
| LAN (physical) | 192.168.1.85 |
Direct IP access, management |
| Tailscale VPN | 100.117.158.101 |
Secure remote access |
| Traefik (internal) | *.home.local |
Named HTTPS on LAN |
| Traefik (external) | *.jeeves5454.ddns.net / *.jeevesconsults.ca |
Internet-facing HTTPS |
Physical Network
| Property | Value |
|---|---|
| Interface | enp47s0 |
| IP Address | 192.168.1.85/24 |
| Default Gateway | 192.168.1.1 (Unifi router) |
| Subnet | 192.168.1.0/24 |
The IP is assigned via DHCP with a static lease on the Unifi gateway, making it functionally static.
Tailscale Mesh VPN
Centerpoint runs as a Tailscale node and exit node, allowing remote devices to route all traffic through the home network.
| Peer | Tailscale IP | Platform | Notes |
|---|---|---|---|
| centerpoint | 100.117.158.101 |
Linux | This host — exit node |
| corsec | 100.101.27.107 |
Linux | HA OS server — also exit node |
| halcyon | 100.81.166.2 |
Windows | Active peer (direct connection) |
| Mobile | varies | iOS | Occasional peers |
Docker Network Architecture
Docker maintains approximately 25 bridge networks on the host. Each application stack follows a consistent isolation pattern:
| Network | Purpose |
|---|---|
traefik-net |
Shared bridge — all Traefik-fronted containers attach here |
*-internal |
Per-stack isolated networks for app-to-database communication |
media-network |
Shared bridge for media stack containers |
bridge |
Docker default (not used for production workloads) |
Typical stack pattern:
- Application container → attached to both
traefik-netand<stack>-internal - Database / cache sidecar → attached to
<stack>-internalonly (never on Traefik)
DNS
Internal (*.home.local): Resolved by AdGuard Home on the LAN. A wildcard DNS
record points *.home.local → 192.168.1.85 so Traefik receives all requests and
routes by hostname.
External (*.jeeves5454.ddns.net): DDNS via No-IP, keeps the external hostname
updated with the home WAN IP.
External (*.jeevesconsults.ca): Managed via DNS provider with appropriate
A / CNAME records pointing to the home WAN.
Notes / Gotchas
- If AdGuard Home is down, all
*.home.localDNS resolution fails. Services remain accessible via direct IP but HTTPS by hostname will not work. - Tailscale must be running (
tailscaled) for the100.xaddress to be reachable. - The large number of
br-*interfaces visible onip addris normal — Docker creates one per network. - Traefik handles all TLS termination; individual containers do not need to manage certificates.
Last Updated: 2026-06-16
Docker Environment
Overview
All services on Centerpoint run as Docker containers, managed through Docker Compose project files and monitored via Portainer EE. Traefik v3 serves as the reverse proxy and TLS termination point for every service.
Docker Engine
| Property | Value |
|---|---|
| Docker Version | 29.5.3 |
| Docker Compose | v5.1.4 |
| Storage Driver | overlayfs |
| Docker Root | /var/lib/docker |
| Total Containers | 112 |
| Running | 97 |
| Stopped | 15 |
| Images | 108 |
Project Structure
All compose projects live under /home/jeeves/docker/, with one subdirectory per
logical stack:
/home/jeeves/docker/
├── adguard/
├── ai-stack/ ← Ollama, Open Web UI, Faster-Whisper, Kokoro
├── arr/ ← Sonarr, Radarr, Prowlarr, Bazarr, NZBGet, etc.
├── authentik/
├── bookstack/
├── crowdsec/
├── homepage/
├── immich/
├── paperless/
├── traefik/
└── ... (one directory per stack)
Each directory contains a docker-compose.yml and any local config files or
bind-mount targets specific to that stack.
Container Management — Portainer EE
Portainer Enterprise Edition provides the web UI for container lifecycle management, log viewing, stack deployment, and environment monitoring.
Portainer connects to the Docker daemon via a dockerproxy sidecar container
(Tecnativa Docker Socket Proxy) rather than mounting the Docker socket directly.
This limits the API surface exposed to Portainer and reduces the blast radius of
any container compromise.
Traefik v3 — Reverse Proxy
Traefik is the single ingress point for all named HTTP/HTTPS traffic. It runs
permanently on traefik-net and discovers routes automatically from Docker container
labels — no manual reload required when stacks are added or removed.
| Property | Value |
|---|---|
| HTTP port | 80 — auto-redirects all traffic to HTTPS |
| HTTPS port | 443 |
| Dashboard port | 8080 — internal only (traefik.home.local) |
| Static config | /home/jeeves/docker/traefik/traefik.yml |
| Dynamic config | /home/jeeves/docker/traefik/dynamic.yml (file-watched) |
| Access logs | /var/log/traefik/access.log (JSON, buffered) |
Certificate Resolvers
| Resolver | Scope | Method | Certificate Authority |
|---|---|---|---|
letsencrypt |
External domains | HTTP challenge | Let's Encrypt |
step-ca |
*.home.local |
ACME | Internal Step-CA (ca.home.local) |
Internal certificates have a 720-hour (30-day) duration and auto-renew via Traefik's built-in ACME client against the Step-CA instance.
Active Plugins
| Plugin | Version | Purpose |
|---|---|---|
PascalMinder/geoblock |
v0.3.6 | Country-level block on external-facing routes |
maxlerebourg/crowdsec-bouncer-traefik-plugin |
v1.3.0 | Blocks IPs flagged by the local CrowdSec LAPI |
Standard Routing Pattern
Each service defines Traefik labels in its own docker-compose.yml. The typical
pattern for a dual-route service (internal + external) is:
labels:
- "traefik.enable=true"
# External route — Let's Encrypt TLS + security middleware
- "traefik.http.routers.<name>-ext.rule=Host(`<svc>.jeeves5454.ddns.net`)"
- "traefik.http.routers.<name>-ext.entrypoints=websecure"
- "traefik.http.routers.<name>-ext.tls.certresolver=letsencrypt"
- "traefik.http.routers.<name>-ext.middlewares=authentik-auth@docker,plex-geoblock@file,crowdsec-bouncer@file"
# Internal route — Step-CA TLS, no extra middleware
- "traefik.http.routers.<name>-int.rule=Host(`<svc>.home.local`)"
- "traefik.http.routers.<name>-int.entrypoints=websecure"
- "traefik.http.routers.<name>-int.tls.certresolver=step-ca"
# Backend service port
- "traefik.http.services.<name>-svc.loadbalancer.server.port=<port>"
Services that are internal-only omit the -ext router entirely. Services that
require OAuth2 authentication on external routes add authentik@file middleware.
Notes / Gotchas
traefik-netis an externally created network and must exist before any Traefik-fronted stack is started:docker network create traefik-net- Never restart
dockerproxywhile Portainer is actively being used — it will lose its Docker connection until the proxy is back up. - Compose files use the stack subdirectory as their working directory — relative bind mount paths resolve from there.
overlayfscan accumulate orphaned image layers over time. Prune periodically:docker image prune docker volume prune # caution — only remove truly unused volumes
Last Updated: 2026-06-16