36 KiB
Container Reference Guide
Documentation of all deployed containers in the tower-of-joy infrastructure
Last Updated: 2025-11-16
Infrastructure Layer
Portainer
Portainer provides the web-based container management interface for the entire stack, offering visual control over Docker containers, stacks, images, volumes, and networks. It serves as the primary management tool for deploying and monitoring all other services, with GPU device management enabled for allocation to ML and transcoding workloads. The interface replaces the need for manual Docker CLI operations and provides real-time container logs, stats, and control.
| Property | Value |
|---|---|
| Image | portainer/portainer-ce:latest |
| Container Name | portainer |
| Access URL | http://192.168.86.149:8001 |
| External Access | LAN only (behind firewall) |
| Port Mapping | 8001:9000 (HTTP), 8443:9443 (HTTPS) |
| Network Mode | Host |
| Restart Policy | always |
| Volume Mounts | portainer_data:/data, /var/run/docker.sock |
| Resource Limits | None |
| GPU Required | No |
| Dependencies | None (base service) |
PostgreSQL Shared
PostgreSQL Shared is a centralized PostgreSQL 17 database server providing isolated database instances for multiple applications across the infrastructure, including Authentik (SSO), Gitea (Git hosting), and future services requiring relational database storage. It implements a shared infrastructure pattern where each application gets its own database and user credentials while sharing the same PostgreSQL instance for resource efficiency. The service stores all database data on the HDD with automated backups scheduled to the backups directory, providing persistent storage with volume-based data retention across container updates.
| Property | Value |
|---|---|
| Image | postgres:17 |
| Container Name | postgres-shared |
| Access URL | N/A (internal database server) |
| External Access | No (docker-dataplane network only) |
| Port Mapping | 5432:5432 (PostgreSQL) |
| Network Mode | Bridge (docker-dataplane) |
| Restart Policy | unless-stopped |
| Volume Mounts | /home/jpmschweitzer/docker-data/postgres-shared/data:/var/lib/postgresql/data, /home/jpmschweitzer/docker-data/postgres-shared/backups:/backups |
| Environment | POSTGRES_PASSWORD=<secure-password>, POSTGRES_DB=postgres, TZ=Europe/Amsterdam, PGDATA=/var/lib/postgresql/data/pgdata |
| Resource Limits | None |
| GPU Required | No |
| Dependencies | docker-dataplane network |
| Databases | authentik (Authentik SSO), gitea (Git hosting), postgres (default/admin) |
| Database Users | authentik_user, gitea_user, postgres (superuser) |
| Health Check | pg_isready -U postgres (30s interval) |
| Backup Strategy | /backups volume for pg_dump exports |
Initialization: Databases and users are created manually after first deployment:
docker exec -i postgres-shared psql -U postgres <<'EOF'
CREATE DATABASE authentik;
CREATE USER authentik_user WITH PASSWORD '<password>';
GRANT ALL PRIVILEGES ON DATABASE authentik TO authentik_user;
EOF
Redis Shared
Redis Shared is a centralized Redis 7 key-value store providing cache, session storage, and message queue capabilities for multiple applications, with logical database isolation (DB 0-15) allowing each service to maintain separate keyspaces within the same Redis instance. It implements a shared infrastructure pattern where applications like Authentik use DB 0 for sessions/cache while future services can use DB 1-15, eliminating the need for separate Redis containers per application. The service stores data on the HDD for persistence across restarts, with AOF (Append-Only File) enabled for durability and optional RDB snapshots for backup points.
| Property | Value |
|---|---|
| Image | redis:7-alpine |
| Container Name | redis-shared |
| Access URL | N/A (internal cache server) |
| External Access | No (docker-dataplane network only) |
| Port Mapping | 6379:6379 (Redis) |
| Network Mode | Bridge (docker-dataplane) |
| Restart Policy | unless-stopped |
| Volume Mounts | /home/jpmschweitzer/docker-data/redis-shared/data:/data |
| Command | redis-server --appendonly yes --dir /data |
| Resource Limits | None |
| GPU Required | No |
| Dependencies | docker-dataplane network |
| Database Allocation | DB 0: Authentik, DB 1-15: Available for future services |
| Persistence | AOF (Append-Only File) enabled for durability |
| Health Check | redis-cli ping returns PONG (30s interval) |
| Connection String | redis://redis-shared:6379/0 (DB 0), redis://redis-shared:6379/1 (DB 1), etc. |
Nginx Proxy Manager
Nginx Proxy Manager serves as the unified reverse proxy and SSL certificate manager, providing a web-based interface for routing HTTP/HTTPS traffic to backend services with automatic Let's Encrypt certificate provisioning. It consolidates access to all web services through a single entry point with path-based or subdomain routing, eliminating the need to remember individual service ports. The service handles SSL termination, proxy host configuration, and access list management through an intuitive dashboard.
| Property | Value |
|---|---|
| Image | jc21/nginx-proxy-manager:latest |
| Container Name | nginx-proxy-manager |
| Access URL | http://192.168.86.149:81 |
| External Access | LAN + Internet (ports 80/443 forwarded) |
| Port Mapping | 81:81 (Admin), 80:80 (HTTP), 443:443 (HTTPS) |
| Network Mode | Host |
| Restart Policy | unless-stopped |
| Volume Mounts | ~/docker-data/nginx-proxy-manager/data:/data, ~/docker-data/nginx-proxy-manager/letsencrypt:/etc/letsencrypt |
| Resource Limits | None |
| GPU Required | No |
| Dependencies | None (reverse proxy for other services) |
Ollama
Ollama is a GPU-accelerated large language model server that provides a REST API for running local LLM inference with models up to 13B parameters, leveraging the RTX 2080 Ti's 11GB VRAM for fast on-device AI capabilities. It manages model downloads, quantization, and serving through a simple API compatible with OpenAI's format, supporting use cases like code generation, chat applications, and text processing without cloud dependencies. The service stores models on the SSD for quick loading times and maintains persistent model storage across container restarts.
| Property | Value |
|---|---|
| Image | ollama/ollama:latest |
| Container Name | ollama |
| Access URL | http://192.168.86.149:11434 |
| External Access | LAN only (API endpoint) |
| Port Mapping | 11434:11434 (API) |
| Network Mode | Bridge (custom network) |
| Restart Policy | unless-stopped |
| Volume Mounts | ~/docker-data/ollama/models:/root/.ollama |
| Resource Limits | Memory: 8GB, GPU: 11GB VRAM |
| GPU Required | Yes (NVIDIA RTX 2080 Ti) |
| GPU Configuration | NVIDIA_VISIBLE_DEVICES=all, NVIDIA_DRIVER_CAPABILITIES=compute,utility |
| Dependencies | NVIDIA Container Toolkit |
| Typical Models | llama3.2:3b (~2GB), mistral:7b (~4GB), codellama:7b (~4GB) |
Code-Server
Code-Server provides a browser-based Visual Studio Code IDE running directly on the host system, offering a persistent development environment with full access to host-level configurations, filesystems, and systemd services without the limitations of containerization. It replaces traditional SSH access by providing a rich IDE experience that survives network disconnections through session persistence, with integrated terminal access, file explorer, git integration, and extension support. The service runs as a systemd service on the host, listening on localhost and exposed externally through Nginx Proxy Manager with SSL encryption and multi-layer authentication for secure remote development access.
| Property | Value |
|---|---|
| Deployment Type | Host-based systemd service (NOT containerized) |
| Binary Location | /usr/bin/code-server |
| Service Name | code-server.service |
| Access URL (LAN) | http://127.0.0.1:8084 (localhost only) |
| Access URL (Public) | https://code.schweitz.net |
| External Access | Yes (via NPM reverse proxy with SSL) |
| Port Binding | 127.0.0.1:8084 (not exposed to network) |
| User/Group | jpmschweitzer:jpmschweitzer |
| Restart Policy | always (systemd) |
| Config Location | ~/.config/code-server/config.yaml |
| Data Storage (SSD) | ~/docker-data/code-server/user-data/ (settings, workspace), ~/docker-data/code-server/extensions/ (extensions) |
| Resource Limits | None (native host process) |
| GPU Required | No |
| Dependencies | NPM (reverse proxy), systemd |
| Authentication | Triple-layer: NPM access list, code-server password, SSL certificate |
| WebSocket Support | Required (enabled via NPM proxy) |
| Typical Memory | ~200-500MB (depends on workspace size) |
| Setup Guide | docs/code-server-setup.md |
Networking Layer
Headscale
Headscale is a self-hosted control server for Tailscale's mesh VPN protocol, creating a private software-defined network across all connected devices with end-to-end encryption and zero-configuration NAT traversal. It enables secure remote access to all homelab services from anywhere without exposing ports to the internet, using a custom 10.99.0.0/16 IP range for the mesh network. The service manages device registration, authentication, and mesh routing while maintaining full data sovereignty compared to the hosted Tailscale control plane.
| Property | Value |
|---|---|
| Image | headscale/headscale:latest |
| Container Name | headscale |
| Access URL | http://192.168.86.149:8085 |
| External Access | LAN only (control server) |
| Port Mapping | 8085:8080 (Web/API), 9090:9090 (Metrics) |
| Network Mode | Bridge (custom network) |
| Restart Policy | unless-stopped |
| Volume Mounts | ~/docker-data/headscale/config:/etc/headscale, ~/docker-data/headscale/data:/var/lib/headscale |
| Resource Limits | None |
| GPU Required | No |
| Dependencies | None |
| Network Range | 10.99.0.0/16 (mesh IPs) |
| Pre-Auth Keys | 24-hour expiration |
Monitoring Layer
Uptime Kuma
Uptime Kuma monitors the availability and response times of all infrastructure and application services, providing real-time status dashboards with historical uptime tracking, incident detection, and notification capabilities. It performs HTTP, TCP, and ICMP checks at configurable intervals against each service endpoint, alerting on downtime events through multiple notification channels including email, Discord, and Slack. The service maintains a SQLite database of uptime history and response time metrics accessible through a clean web interface.
| Property | Value |
|---|---|
| Image | louislam/uptime-kuma:latest |
| Container Name | uptime-kuma |
| Access URL | http://192.168.86.149:3001 |
| External Access | LAN only (monitoring dashboard) |
| Port Mapping | 3001:3001 (Web UI) |
| Network Mode | Bridge |
| Restart Policy | unless-stopped |
| Volume Mounts | ~/docker-data/uptime-kuma:/app/data |
| Resource Limits | None |
| GPU Required | No |
| Dependencies | None (monitors other services) |
| Database | SQLite (persistent in volume) |
| Check Intervals | 60 seconds (configurable) |
Netdata
Netdata provides comprehensive real-time system performance monitoring with per-second metric collection for CPU, RAM, disk I/O, network traffic, and Docker container resource usage, displaying everything through interactive web dashboards with zero configuration required. It collects thousands of metrics automatically with minimal overhead, offering drill-down capabilities from system-wide views to per-container and per-process analysis. The service maintains short-term metric history in RAM and can stream data to long-term storage backends for historical analysis.
| Property | Value |
|---|---|
| Image | netdata/netdata:latest |
| Container Name | netdata |
| Access URL | http://192.168.86.149:19999 |
| External Access | LAN only (metrics dashboard) |
| Port Mapping | 19999:19999 (Web UI) |
| Network Mode | Host (for full system visibility) |
| Restart Policy | unless-stopped |
| Volume Mounts | /proc:/host/proc:ro, /sys:/host/sys:ro, /var/run/docker.sock:/var/run/docker.sock:ro |
| Capabilities | SYS_PTRACE, apparmor:unconfined |
| Resource Limits | None (monitoring overhead ~1-3% CPU) |
| GPU Required | No |
| Dependencies | Docker socket (read-only) |
| Metric Retention | ~1 hour (RAM-based) |
Organizr
Organizr serves as a comprehensive unified dashboard that consolidates all homelab services into a single tabbed interface with integrated homepage widgets showing real-time statistics from Jellyfin streams, Netdata metrics, Uptime Kuma status checks, and download client activity. It provides customizable authentication per-tab with support for SSO integration, user management with group-based access control, and a mobile-responsive interface for managing the entire infrastructure from anywhere. The service acts as a central hub replacing the need for multiple bookmarks or remembering service ports, offering both quick-access tabs and homepage cards with live data feeds from connected services.
| Property | Value |
|---|---|
| Image | organizr/organizr:latest |
| Container Name | organizr |
| Access URL (LAN) | http://192.168.86.149:9999 |
| Access URL (Public) | https://home.schweitz.net |
| External Access | Yes (via NPM reverse proxy with SSL) |
| Port Mapping | 9999:80 (HTTP), 443:443 (HTTPS) |
| Network Mode | Bridge |
| Restart Policy | unless-stopped |
| Volume Mounts | ~/docker-data/organizr:/config |
| Environment | Built-in (no custom env vars) |
| Resource Limits | None |
| GPU Required | No |
| Dependencies | None (integrates with other services via API) |
| Database | SQLite at /config/db/organizrDashboardDb.db |
| Database Size | ~5-10MB (typical) |
| Integrated Services | Jellyfin, Netdata, Uptime Kuma |
| Authentication | Internal (supports SSO, Plex OAuth, LDAP) |
Optimization Layer
Watchtower
Watchtower automatically monitors all running containers for updated images and performs rolling updates on a configurable schedule, ensuring the infrastructure stays current with security patches and feature releases without manual intervention. It checks Docker Hub and configured registries daily at 4 AM, pulls new images when available, gracefully stops containers, deploys updated versions, and cleans up old images to prevent disk bloat. The service logs all update activities and can send notifications through various channels when updates occur.
| Property | Value |
|---|---|
| Image | containrrr/watchtower:latest |
| Container Name | watchtower |
| Access URL | N/A (background service) |
| External Access | N/A |
| Port Mapping | None (no exposed ports) |
| Network Mode | Bridge |
| Restart Policy | unless-stopped |
| Volume Mounts | /var/run/docker.sock:/var/run/docker.sock |
| Environment | WATCHTOWER_CLEANUP=true, WATCHTOWER_SCHEDULE=0 0 4 * * * |
| Resource Limits | None |
| GPU Required | No |
| Dependencies | Docker socket (read-write for updates) |
| Schedule | Daily at 4:00 AM |
| Cleanup | Automatic (removes old images) |
Maintenance Container
The maintenance container runs scheduled automation tasks including nightly Docker configuration backups with 30-day retention, disk space monitoring, log cleanup, and future expansion for health checks and system maintenance scripts. It executes cron-based jobs at 3 AM daily to archive all Docker Compose configurations, container settings, and persistent data to the backup directory on the HDD with timestamped snapshots. The container provides a centralized location for all homelab automation without cluttering the host system with multiple cron entries.
| Property | Value |
|---|---|
| Image | alpine:latest |
| Container Name | maintenance |
| Access URL | N/A (background service) |
| External Access | N/A |
| Port Mapping | None (no exposed ports) |
| Network Mode | Bridge |
| Restart Policy | unless-stopped |
| Volume Mounts | ~/docker-data:/source:ro, /mnt/media/backups:/backups |
| Command | Runs crond with custom crontab |
| Resource Limits | None |
| GPU Required | No |
| Dependencies | None |
| Schedule | Daily at 3:00 AM (backups) |
| Backup Retention | 30 days |
| Backup Size | ~94MB per snapshot |
Application Layer
Open WebUI
Open WebUI is a feature-rich, self-hosted web interface for interacting with large language models via Ollama, providing a ChatGPT-like experience with support for multiple models, conversation history, RAG (Retrieval-Augmented Generation), web search integration, and user authentication. It offers a modern chat interface with streaming responses, markdown rendering, code syntax highlighting, and conversation management, enabling seamless switching between different LLM models and maintaining persistent chat histories in a local database. The service integrates directly with the local Ollama instance for GPU-accelerated inference without cloud dependencies, supporting features like web search via DuckDuckGo, document upload for context, and multi-user access with authentication. It is documented at: https://docs.openwebui.com/
| Property | Value |
|---|---|
| Image | ghcr.io/open-webui/open-webui:main |
| Container Name | open-webui |
| Access URL | http://192.168.86.149:82 |
| External Access | LAN only (not yet proxied) |
| Port Mapping | 82:8080 (HTTP) |
| Network Mode | Bridge (custom network: ai-network) |
| Restart Policy | unless-stopped |
| Volume Mounts | ~/docker-data/open-webui:/app/backend/data |
| Environment | OLLAMA_BASE_URL=http://192.168.86.149:11434, DEFAULT_MODELS=llama3.2:3b, ENABLE_RAG_WEB_SEARCH=true, ENABLE_OLLAMA_API=true, WEBUI_AUTH=true, RAG_WEB_SEARCH_ENGINE=duckduckgo, AUDIO_STT_ENGINE=openai, AUDIO_TTS_ENGINE=openai |
| Resource Limits | None |
| GPU Required | No (uses Ollama for GPU inference) |
| Dependencies | Ollama (ML inference backend) |
| Database | SQLite (persistent in volume) |
| Authentication | Built-in user management |
| Integrated Services | Ollama, DuckDuckGo (web search) |
Core API
Core API provides OpenAI-compatible HTTP functions for Open WebUI, extending LLM capabilities with AI orchestration, web scraping, and content processing services in a hot-reload development environment. The service implements Phase 1 of the AI Orchestrator plan, providing /v1/chat/completions and /v1/models endpoints with full OpenAI API compatibility, model aliasing (gpt-3.5-turbo → gemma:7b), and streaming support via Server-Sent Events. It uses Trafilatura for intelligent content extraction with BeautifulSoup fallback, offering configurable content length limits and optional link extraction optimized for feeding webpage content to language models. The service runs on Python 3.12 with mounted source code for instant updates, maintaining a persistent venv in docker-data for fast container restarts and development agility.
| Property | Value |
|---|---|
| Image | python:3.12 |
| Container Name | core-api |
| Access URL | http://192.168.86.149:8083 |
| API Documentation | http://192.168.86.149:8083/docs (Swagger UI) |
| External Access | LAN only (internal API) |
| Port Mapping | 8083:8083 (HTTP) |
| Network Mode | Bridge (custom network: ai-dataplane) |
| Restart Policy | unless-stopped |
| Volume Mounts | /home/jpmschweitzer/Projects/portainer-core/services/core-api:/app (source code), ~/docker-data/core-api/venv:/venv (dependencies), ~/docker-data/core-api/logs:/app/logs (logs) |
| Environment | APP_NAME=Core API, APP_VERSION=1.0.0-phase1, DEBUG=true, PORT=8083, LOG_LEVEL=INFO, PYTHONPATH=/app, Model aliases: ALIAS_GPT35=gemma:7b, ALIAS_GPT4=mistral:7b |
| Command | Hot-reload with uvicorn: --reload --reload-dir /app/src |
| Resource Limits | None |
| GPU Required | No (proxies requests to Ollama which uses GPU) |
| Dependencies | Ollama (model inference), Open WebUI (consumes this API), ai-dataplane network |
| Framework | FastAPI 0.115.0, Uvicorn 0.32.0, Pydantic 2.10.4, httpx 0.28.1 |
| Key Features | OpenAI-compatible API (/v1/chat/completions, /v1/models), Model aliasing (OpenAI → local models), Streaming & non-streaming responses, Web scraping (Trafilatura, BeautifulSoup), Hot-reload development, OpenAPI spec, Infrastructure management (Portainer, Uptime Kuma) |
| AI Orchestrator | Phase 1 Complete - OpenAI API wrapper with model routing. Phase 2+ will add memory systems, multi-agent workflows, and tool integration. |
| Health Check | GET /health (30s interval) - checks API status and Ollama connectivity |
| Monitoring API | Full CRUD for Uptime Kuma monitors via Socket.IO: GET /infrastructure/monitors, POST /infrastructure/monitors, GET /infrastructure/monitors/{id}, PUT /infrastructure/monitors/{id}, DELETE /infrastructure/monitors/{id} |
Creating Monitors via API:
# Create a TCP port monitor for Redis
curl -X POST http://192.168.86.149:8083/infrastructure/monitors \
-H "Content-Type: application/json" \
-d '{
"type": "port",
"name": "Redis Shared - Port Check",
"hostname": "redis-shared",
"port": 6379,
"interval": 60,
"retryInterval": 60,
"maxretries": 3,
"notificationIDList": [],
"accepted_statuscodes": ["200-299"]
}'
# Create a PostgreSQL database monitor (note URL-encoded password)
curl -X POST http://192.168.86.149:8083/infrastructure/monitors \
-H "Content-Type: application/json" \
-d '{
"type": "postgres",
"name": "PostgreSQL Shared",
"interval": 60,
"retryInterval": 60,
"maxretries": 3,
"notificationIDList": [],
"accepted_statuscodes": ["200-299"],
"databaseConnectionString": "postgres://user:password@postgres-shared:5432/postgres"
}'
Important: When creating database monitors with passwords containing special characters (/, =, +, etc.), URL-encode them in the connection string (e.g., / → %2F, = → %3D).
Jellyfin
Jellyfin is a GPU-accelerated media server that organizes, streams, and transcodes video, music, and photo libraries with hardware encoding via NVIDIA NVENC, enabling smooth 4K playback across multiple simultaneous clients without taxing the CPU. It provides a Netflix-like interface accessible through web browsers, mobile apps, and smart TV clients, with automatic metadata fetching, subtitle support, and user management for family sharing. The service stores configuration and cache on the SSD for responsive browsing while accessing massive media libraries on the 3.7TB HDD, supporting direct play when possible and GPU-accelerated transcoding when format conversion is needed.
| Property | Value |
|---|---|
| Image | jellyfin/jellyfin:latest |
| Container Name | jellyfin |
| Access URL | http://192.168.86.149:8096, https://media.schweitz.net |
| External Access | LAN + Internet (via NPM reverse proxy) |
| Port Mapping | 8096:8096 (HTTP), 8920:8920 (HTTPS), 7359:7359/udp (Discovery), 1900:1900/udp (DLNA) |
| Network Mode | Bridge |
| Restart Policy | unless-stopped |
| Volume Mounts | ~/docker-data/jellyfin/config:/config, ~/docker-data/jellyfin/cache:/cache, /mnt/media/jellyfin:/media:ro |
| Environment | NVIDIA_VISIBLE_DEVICES=all, NVIDIA_DRIVER_CAPABILITIES=all |
| User | 1000:1000 (UID:GID) |
| Resource Limits | Memory: 4GB, GPU: 11GB VRAM (shared) |
| GPU Required | Yes (NVIDIA RTX 2080 Ti) |
| GPU Configuration | NVENC hardware encoding, NVDEC hardware decoding |
| Dependencies | NVIDIA Container Toolkit, NPM (for external access) |
| Media Storage | /mnt/media/jellyfin (HDD) |
| Transcoding | Hardware-accelerated (H.264/H.265) |
Nextcloud
Nextcloud is a self-hosted cloud storage and collaboration platform providing file sync, sharing, calendar, contacts, and collaborative document editing with a web interface and mobile apps, replacing cloud services like Dropbox or Google Drive while maintaining full data sovereignty. It runs as a multi-container stack with a MariaDB database for metadata, Redis for caching and file locking, and the main PHP application container, with the application configuration stored on SSD for responsiveness while user data resides on the HDD for capacity. The service integrates behind Nginx Proxy Manager with SSL at https://cloud.schweitz.net, offering external access for file synchronization from anywhere while maintaining automated background job execution through the maintenance container's cron system.
| Property | Value |
|---|---|
| Image | nextcloud:stable |
| Container Name | nextcloud |
| Access URL (LAN) | http://192.168.86.149:8082 |
| Access URL (Public) | https://cloud.schweitz.net |
| External Access | Yes (via NPM reverse proxy with SSL) |
| Port Mapping | 8082:80 (HTTP) |
| Network Mode | Bridge (custom network: nextcloud_nextcloud-network) |
| Restart Policy | unless-stopped |
| Volume Mounts | ~/docker-data/nextcloud/config:/var/www/html (SSD), /mnt/media/nextcloud/data:/var/www/html/data (HDD) |
| Environment | MYSQL_HOST=nextcloud-db, MYSQL_DATABASE=nextcloud, MYSQL_USER=nextcloud, REDIS_HOST=nextcloud-redis, TZ=Europe/Amsterdam |
| Resource Limits | None |
| GPU Required | No |
| Dependencies | MariaDB 10.11 (nextcloud-db), Redis Alpine (nextcloud-redis), NPM (reverse proxy), Maintenance container (cron jobs) |
| Database | MariaDB on SSD (~100MB) |
| Cron Jobs | Background tasks every 5 minutes (via maintenance container) |
| Storage Split | Config/apps on SSD, user data on HDD |
| Features | File sync, calendar, contacts, document editing, photo gallery, mobile apps |
Samba
Samba provides SMB/CIFS network file sharing for seamless access to homelab storage from Windows, macOS, Linux, and mobile devices, exposing curated shares for media libraries, downloads, and backups with configurable read-only and read-write permissions. It runs as a single container on the samba_default network, serving three shares: Media (read-write access to Jellyfin content), Downloads (read-write for torrent clients), and Backups (read-only for safe data recovery). The service uses password authentication for the user jpmschweitzer and stores its minimal configuration on the SSD while directly mounting HDD paths for zero-copy file access with native performance.
| Property | Value |
|---|---|
| Image | dperson/samba |
| Container Name | samba |
| Access URL | \\192.168.86.149 or \\tower-of-joy |
| External Access | LAN only (ports firewalled) |
| Port Mapping | 139:139 (NetBIOS), 445:445 (SMB) |
| Network Mode | Bridge (custom network: samba_default) |
| Restart Policy | unless-stopped |
| Volume Mounts | ~/docker-data/samba:/share/config (SSD config), /mnt/media/jellyfin:/share/media (Media share), /mnt/media/downloads:/share/downloads (Downloads share), /mnt/media/backups:/share/backups:ro (Backups read-only) |
| Environment | TZ=Europe/Amsterdam, USERID=1000, GROUPID=1000 |
| Command | Share configs: Media (browseable, guest access), Downloads (no guest), Backups (read-only, browseable) |
| Resource Limits | None |
| GPU Required | No |
| Dependencies | UFW firewall rules (ports 139, 445), Host Samba service disabled |
| Shares | 3 total: Media (R/W), Downloads (R/W), Backups (R/O) |
| Authentication | Username/password (jpmschweitzer) |
| Client Compatibility | Windows, macOS, Linux, iOS, Android |
Gitea
Gitea is a lightweight, self-hosted Git service providing repository hosting, issue tracking, pull requests, code review, and CI/CD integration through a clean web interface accessible via both HTTPS and SSH. It runs as a multi-container stack with a PostgreSQL database for metadata storage, offering GitHub-like functionality including organizations, teams, wikis, webhooks, and automated Actions workflows while maintaining complete data sovereignty and minimal resource overhead. The service stores all Git repositories and configuration on the SSD for fast access, integrates behind Nginx Proxy Manager with SSL at https://git.schweitz.net for web access, and exposes SSH on port 2222 for standard Git operations without conflicting with the host's SSH service.
| Property | Value |
|---|---|
| Image | gitea/gitea:latest |
| Container Name | gitea |
| Access URL (LAN) | http://192.168.86.149:3002 |
| Access URL (Public) | https://git.schweitz.net |
| External Access | Yes (via NPM reverse proxy with SSL) |
| Port Mapping | 3002:3000 (HTTP), 2222:22 (SSH) |
| Network Mode | Bridge (custom network: gitea_gitea-network) |
| Restart Policy | unless-stopped |
| Volume Mounts | ~/docker-data/gitea/data:/data (SSD - repos, config) |
| Environment | USER_UID=1000, USER_GID=1000, GITEA__database__* (PostgreSQL connection), TZ=Europe/Amsterdam |
| Resource Limits | None |
| GPU Required | No |
| Dependencies | PostgreSQL 14 (gitea-db), NPM (reverse proxy) |
| Database | PostgreSQL on SSD (~50MB) |
| SSH Access | Port 2222 - git clone ssh://git@git.schweitz.net:2222/user/repo.git |
| Features | Git hosting, Organizations/teams, Issues/PRs, Code review, Wikis, Webhooks, Gitea Actions (CI/CD), GitHub/GitLab migration |
| SSH Config Tip | Add to ~/.ssh/config: Host git.schweitz.net / Port 2222 / User git for seamless cloning |
Quick Reference Tables
Service Access Matrix
| Service | LAN URL | Internet Access | Primary Function |
|---|---|---|---|
| Portainer | http://192.168.86.149:8001 | No | Container management |
| PostgreSQL Shared | postgres-shared:5432 | No (internal) | Shared database server |
| Redis Shared | redis-shared:6379 | No (internal) | Shared cache/session store |
| NPM | http://192.168.86.149:81 | Yes (admin) | Reverse proxy admin |
| Code-Server | https://code.schweitz.net | Yes | Browser-based IDE |
| Ollama | http://192.168.86.149:11434 | No | ML model API |
| Headscale | http://192.168.86.149:8085 | No | VPN control server |
| Uptime Kuma | http://192.168.86.149:3001 | No | Uptime monitoring |
| Netdata | http://192.168.86.149:19999 | No | System metrics |
| Heimdall | http://192.168.86.149:8888 | No | Service dashboard |
| Organizr | https://home.schweitz.net | Yes | Unified dashboard |
| Open WebUI | http://192.168.86.149:82 | No | LLM chat interface |
| Core API | http://192.168.86.149:8083 | No | API functions & infrastructure mgmt |
| Jellyfin | https://media.schweitz.net | Yes | Media streaming |
| Nextcloud | https://cloud.schweitz.net | Yes | Cloud storage & sync |
| Gitea | https://git.schweitz.net | Yes | Git repository hosting |
| Samba | \\192.168.86.149 | No | Network file shares |
| Watchtower | N/A (background) | N/A | Auto-updates |
| Maintenance | N/A (background) | N/A | Automated tasks |
GPU-Enabled Services
| Service | GPU Usage | VRAM Requirements | Purpose |
|---|---|---|---|
| Ollama | Compute, Utility | 2-10GB (model dependent) | LLM inference |
| Jellyfin | Video Encode/Decode | ~1-2GB (during transcode) | Media transcoding |
Total VRAM Available: 11GB (RTX 2080 Ti)
Storage Distribution
| Service | Config Location (SSD) | Data Location (HDD) | Typical Size |
|---|---|---|---|
| Portainer | Docker volume: portainer_data |
N/A | ~100MB |
| PostgreSQL Shared | N/A | ~/docker-data/postgres-shared/data/ |
Data: 100MB-5GB (depends on databases), Backups: variable |
| Redis Shared | N/A | ~/docker-data/redis-shared/data/ |
~10-100MB (AOF + RDB snapshots) |
| NPM | ~/docker-data/nginx-proxy-manager/ |
N/A | ~50MB |
| Code-Server | ~/.config/code-server/, ~/docker-data/code-server/ |
N/A | Config: ~5MB, Extensions: ~50-200MB, User data: ~50MB |
| Ollama | ~/docker-data/ollama/models/ |
Alt: /mnt/media/ollama/ |
2-15GB per model |
| Headscale | ~/docker-data/headscale/ |
N/A | ~10MB |
| Uptime Kuma | ~/docker-data/uptime-kuma/ |
N/A | ~50MB |
| Netdata | RAM-based (ephemeral) | N/A | ~200MB RAM |
| Heimdall | ~/docker-data/heimdall/ |
N/A | ~20MB |
| Organizr | ~/docker-data/organizr/ |
N/A | ~50MB |
| Open WebUI | ~/docker-data/open-webui/ |
N/A | ~100MB |
| Core API | ~/docker-data/core-api/, /home/jpmschweitzer/Projects/portainer-core/services/core-api/ (source) |
N/A | Venv: ~200MB, Logs: ~10MB |
| Jellyfin | ~/docker-data/jellyfin/ |
/mnt/media/jellyfin/ |
Config: ~500MB, Media: ~2TB |
| Nextcloud | ~/docker-data/nextcloud/ |
/mnt/media/nextcloud/data/ |
Config: ~200MB, DB: ~100MB, User data: variable |
| Gitea | ~/docker-data/gitea/ |
N/A | Data: ~100MB, DB: ~50MB, Repos: variable |
| Samba | ~/docker-data/samba/ |
Mounts: /mnt/media/ (shares) |
Config: ~5MB |
| Maintenance | N/A | /mnt/media/backups/ |
~94MB per backup |
SSD Usage (docker-data): ~6-11GB (configs, caches, databases) HDD Usage (/mnt/media): ~2.1TB / 3.6TB (58% used)
Network Architecture
As of 2025-11-15, all services have been consolidated to the docker-dataplane bridge network for simplified service discovery and inter-container communication. This consolidation replaced 12+ legacy networks with a single unified network, enabling all services to communicate using container names as DNS hostnames.
| Network Name | Containers | Purpose |
|---|---|---|
| docker-dataplane | Ollama, Open WebUI, Core API, Qdrant, Uptime Kuma, PostgreSQL Shared, Redis Shared, Headscale, Nextcloud, Gitea, Samba, Watchtower, Maintenance, Organizr, Netdata | Unified service mesh for all containerized applications |
| host | Portainer, NPM | Direct host port access for infrastructure management |
Benefits of Consolidation:
- Service Discovery: All services reachable via
http://container-name:port(e.g.,http://postgres-shared:5432) - Simplified Monitoring: Uptime Kuma can monitor all services on docker-dataplane
- Shared Infrastructure: postgres-shared and redis-shared accessible to all applications
- Network Cleanup: Removed 7 obsolete networks (stacks_default, ai-dataplane, various stack-specific networks)
Container Name Resolution Examples:
# From any container on docker-dataplane
curl http://uptime-kuma:3001 # Uptime Kuma API
curl http://ollama:11434 # Ollama LLM API
psql -h postgres-shared -U postgres # PostgreSQL connection
redis-cli -h redis-shared # Redis connection
Restart Policies
| Policy | Containers | Behavior |
|---|---|---|
| always | Portainer | Restart on failure, on Docker daemon restart |
| unless-stopped | All others | Restart on failure, but not after manual stop |
Maintenance Schedule
| Service | Task | Frequency | Time |
|---|---|---|---|
| Watchtower | Container updates | Daily | 4:00 AM |
| Maintenance | Config backups | Daily | 3:00 AM |
| Maintenance | Nextcloud background jobs | Every 5 minutes | Continuous |
| Maintenance | Log cleanup | Weekly | Sunday 3:30 AM |
| Docker | Image pruning | Monthly | 1st of month |
Last Updated: 2025-11-16 System: tower-of-joy (tower-of-joy v0.5.0-optimization)