Files
homelab/services
Jordan Ramos e08951de21 feat(openclaw): deploy OpenClaw AI chatbot gateway on VM 120
- Add Docker Compose configs with security hardening (cap_drop ALL, non-root, read-only FS)
- Add Prometheus node_exporter scrape target for 192.168.2.120:9100
- Update services/README.md, INDEX.md, and CLAUDE_STATUS.md with VM 120
- Image pinned to v2026.2.1 (patches CVE-2026-25253)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 18:14:58 -07:00
..

Docker Compose Services

This directory contains Docker Compose configurations for various services deployed in the homelab environment.

Migration Information

Migration Date: 2025-12-02 Source: GitLab instance at https://vulcan.apophisnetworking.net/jramos/homelab Target: Gitea instance at http://192.168.2.102:3060/jramos/homelab Migration Tool: Claude Code automated migration

All service configurations have been migrated from the legacy GitLab instance to this repository as part of the infrastructure consolidation effort.

Services Overview

ByteStash

Directory: bytestash/ Port: 5000 Description: Code snippet and text snippet management system with JWT-based authentication Image: ghcr.io/jordan-dalby/bytestash:latest Key Features:

  • Snippet storage and organization
  • User account management
  • OIDC/SSO support (configurable)
  • Debug mode available

Deployment:

cd bytestash
docker compose up -d

FileBrowser

Directory: filebrowser/ Port: 8095 Description: Web-based file browser providing file management through a web interface Image: filebrowser/filebrowser:latest Key Features:

  • Full filesystem access (mounted at root /)
  • User and group ID configuration
  • SQLite database for settings
  • Customizable via settings.json

Deployment:

cd filebrowser
docker compose up -d

Note: Review volume mounts before deployment - currently configured to mount entire filesystem.

GitLab Utilities

Directory: gitlab/ Description: Quality of Life (QoL) scripts and systemd configurations for GitLab management Contents:

  • QoL Scripts/sync-npm-certs.sh: Script to sync Nginx Proxy Manager certificates
  • QoL Config Files/sync-npm-certs.service: Systemd service unit
  • QoL Config Files/sync-npm-certs.timer: Systemd timer for automated certificate sync

Purpose: Automates certificate synchronization between Nginx Proxy Manager and GitLab instance.

Paperless-ngx

Directory: paperless-ngx/ Port: 8000 URL: https://atlas.apophisnetworking.net Description: Document management system with OCR, full-text search, and automated organization Images:

  • ghcr.io/paperless-ngx/paperless-ngx:latest (webserver)
  • postgres:17 (database)
  • redis:8 (message broker)
  • gotenberg:8.20 (document conversion)
  • apache/tika:latest (text extraction)

Key Features:

  • OCR for scanned documents
  • Automated document processing
  • Tag and organization system
  • PostgreSQL backend
  • Redis task queue
  • Tika integration for file parsing
  • Gotenberg for document conversion

Deployment:

cd paperless-ngx
docker compose up -d

Environment Configuration: Check .env file or Portainer environment variables for production deployment.

Portainer

Directory: portainer/ Ports:

  • 8000 (Edge agent)
  • 9443 (Web UI - HTTPS)

Description: Docker container management platform with web UI Image: portainer/portainer-ce:latest Key Features:

  • Docker container management
  • Stack deployment
  • Image registry management
  • User access control
  • Remote agent support

Deployment:

cd portainer
docker compose up -d

Note: Uses external volume portainer_data - ensure volume exists before deployment.

Speedtest Tracker

Directory: speedtest-tracker/ Ports:

  • 8180 (HTTP)
  • 8143 (HTTPS)

Description: Automated internet speed test tracker with historical data and public dashboard Image: lscr.io/linuxserver/speedtest-tracker:latest Key Features:

  • Scheduled speed tests (cron: daily at midnight)
  • SQLite database
  • Public dashboard view
  • Historical speed test data
  • LinuxServer.io image with PUID/PGID support

Deployment:

cd speedtest-tracker
docker compose up -d

Monitoring Stack (VM-based)

Deployment: VM 101 (monitoring-docker) at 192.168.2.114 Technology: Docker Compose Components: Grafana, Prometheus, PVE Exporter

Overview

Comprehensive monitoring and observability stack for the Proxmox homelab environment providing real-time metrics, visualization, and alerting capabilities.

Components

Grafana (Port 3000):

  • Visualization and dashboards
  • Pre-configured Proxmox VE dashboards
  • User authentication and RBAC
  • Alerting capabilities
  • Access: http://192.168.2.114:3000

Prometheus (Port 9090):

  • Metrics collection and time-series database
  • PromQL query language
  • 15-day retention (configurable)
  • Service discovery
  • Access: http://192.168.2.114:9090

PVE Exporter (Port 9221):

  • Proxmox VE metrics exporter
  • Connects to Proxmox API
  • Exports node, VM, CT, and storage metrics
  • Access: http://192.168.2.114:9221

Key Features

  • Real-time Proxmox infrastructure monitoring
  • VM and container resource utilization tracking
  • Storage pool capacity planning
  • Network traffic analysis
  • Backup job status monitoring
  • Custom alerting rules

Deployment

# Navigate to monitoring directory
cd /home/jramos/homelab/monitoring

# Deploy PVE Exporter
cd pve-exporter
docker compose up -d

# Deploy Prometheus
cd ../prometheus
docker compose up -d

# Deploy Grafana
cd ../grafana
docker compose up -d

# Verify all services
docker ps | grep -E 'grafana|prometheus|pve-exporter'

Configuration

PVE Exporter:

  • Environment file: monitoring/pve-exporter/.env
  • Configuration: monitoring/pve-exporter/pve.yml
  • Requires Proxmox API user with PVEAuditor role

Prometheus:

  • Configuration: monitoring/prometheus/prometheus.yml
  • Scrapes PVE Exporter every 30 seconds
  • Targets: localhost:9090, pve-exporter:9221

Grafana:

  • Default credentials: admin/admin (change on first login)
  • Data source: Prometheus at http://prometheus:9090
  • Recommended dashboard: Grafana ID 10347 (Proxmox VE)

Maintenance

# Update images
cd /home/jramos/homelab/monitoring/<component>
docker compose pull
docker compose up -d

# View logs
docker compose logs -f

# Restart services
docker compose restart

Troubleshooting

PVE Exporter connection issues:

  1. Verify Proxmox API is accessible: curl -k https://192.168.2.200:8006
  2. Check credentials in .env file
  3. Verify user has PVEAuditor role: pveum user list (on Proxmox)

Grafana shows no data:

  1. Verify Prometheus data source configuration
  2. Check Prometheus targets: http://192.168.2.114:9090/targets
  3. Test queries in Prometheus UI before using in Grafana

High memory usage:

  1. Reduce Prometheus retention period
  2. Limit Grafana concurrent queries
  3. Increase VM 101 memory allocation

Complete Documentation: See /home/jramos/homelab/monitoring/README.md


Twingate Connector

Deployment: CT 112 (twingate-connector) Technology: LXC Container Purpose: Zero-trust network access

Overview

Lightweight connector providing secure remote access to homelab resources without traditional VPN complexity. Part of Twingate's zero-trust network access (ZTNA) solution.

Features

  • Zero-Trust Architecture: Grant access to specific resources, not entire networks
  • No VPN Required: Simplified connection without VPN client configuration
  • Identity-Based Access: User and device authentication
  • Automatic Updates: Connector auto-updates for security patches
  • Low Resource Overhead: Minimal CPU and memory footprint

Architecture

External User → Twingate Cloud → Twingate Connector (CT 112) → Homelab Resources

Deployment Considerations

LXC vs Docker:

  • LXC chosen for lightweight, always-on service
  • Minimal resource consumption
  • System-level integration
  • Quick restart and recovery

Network Placement:

  • Deployed on homelab management network (192.168.2.0/24)
  • Access to all internal resources
  • No inbound port forwarding required

Configuration

The Twingate connector is configured via the Twingate Admin Console:

  1. Create Connector in Twingate Admin Console
  2. Generate Token for connector authentication
  3. Deploy Container with provided token
  4. Configure Resources to route through connector
  5. Assign Users to resources

Maintenance

Health Monitoring:

  • Check connector status in Twingate Admin Console
  • Monitor CPU/memory usage on CT 112
  • Review connection logs

Updates:

  • Connector auto-updates by default
  • Manual updates: Restart container or redeploy

Troubleshooting:

  • Verify network connectivity to Twingate cloud
  • Check connector token validity
  • Review resource routing configuration
  • Ensure firewall allows outbound HTTPS

Security Best Practices

  1. Least Privilege: Grant access only to required resources
  2. MFA Enforcement: Require multi-factor authentication for users
  3. Device Trust: Enable device posture checks
  4. Audit Logs: Regularly review access logs in Twingate Console
  5. Connector Isolation: Consider dedicated network segment for connector

Integration with Homelab

Protected Resources:

  • Proxmox Web UI (192.168.2.200:8006)
  • Grafana Monitoring (192.168.2.114:3000)
  • Nginx Proxy Manager (192.168.2.101:81)
  • n8n Workflows (192.168.2.113:5678)
  • Development VMs and services

Access Policies:

  • Admin users: Full access to all resources
  • Monitoring users: Read-only Grafana access
  • Developers: Access to dev VMs and services

OpenClaw - AI Chatbot Gateway

Directory: openclaw/ Deployment: VM 120 (openclaw) at 192.168.2.120 Ports:

  • 18789 (Gateway WebSocket + UI)
  • 18790 (Bridge)
  • 1455 (OAuth)

Description: Multi-platform AI chatbot gateway bridging messaging platforms (Discord, Telegram, Slack, WhatsApp) with LLM providers (Anthropic, OpenAI, Ollama) Image: ghcr.io/openclaw/openclaw:2026.2.1

Key Features:

  • Multi-provider LLM support (Anthropic, OpenAI, Ollama)
  • Multi-platform messaging integration
  • WebSocket gateway with web UI
  • Pairing-based DM security policy
  • Hardened container (cap_drop ALL, non-root, read-only filesystem)

Security Note: Version must be >= 2026.2.1 (CVE-2026-25253 patch). All ports bound to localhost only; access via Nginx Proxy Manager reverse proxy at openclaw.apophisnetworking.net.

Deployment:

cd openclaw
cp .env.example .env
# Edit .env: add GATEWAY_TOKEN (openssl rand -hex 32) and at least one LLM API key
docker compose up -d

Complete Documentation: See services/openclaw/README.md


General Deployment Instructions

Prerequisites

  • Docker Engine 20.10+
  • Docker Compose v2.0+
  • Sufficient disk space for volumes
  • Network ports available (check port conflicts)

Standard Deployment Workflow

  1. Review Configuration

    cd services/<service-name>
    cat docker-compose.yaml
    
  2. Configure Environment Variables (if applicable)

    # Copy example env file if available
    cp .env.example .env
    # Edit with actual values
    nano .env
    
  3. Create Required Directories

    # Ensure volume mount points exist
    # Example for bytestash:
    mkdir -p /home/jramos/docker/bytestash/data
    
  4. Deploy Stack

    docker compose up -d
    
  5. Verify Deployment

    docker compose ps
    docker compose logs -f
    
  6. Configure Reverse Proxy (if using NPM)

    • Access Nginx Proxy Manager at http://192.168.2.101:81
    • Create proxy host pointing to service IP:PORT
    • Configure SSL certificate via Let's Encrypt
    • Set appropriate forwarding scheme (http/https)

Maintenance Commands

View Logs:

cd services/<service-name>
docker compose logs -f

Restart Service:

docker compose restart

Update Service:

docker compose pull
docker compose up -d

Stop Service:

docker compose down

Remove Service and Volumes (DESTRUCTIVE):

docker compose down -v

Directory Structure

services/
├── README.md                    # This file
├── openclaw/
│   ├── docker-compose.yml       # OpenClaw main configuration
│   ├── docker-compose.override.yml  # Security hardening overlay
│   └── .env.example             # Environment variable template
├── bytestash/
│   ├── docker-compose.yaml
│   └── .gitkeep
├── filebrowser/
│   ├── docker-compose.yaml
│   └── .gitkeep
├── gitlab/
│   ├── QoL Config Files/
│   │   ├── sync-npm-certs.service
│   │   └── sync-npm-certs.timer
│   └── QoL Scripts/
│       └── sync-npm-certs.sh
├── paperless-ngx/
│   ├── docker-compose.yaml
│   └── .env
├── portainer/
│   ├── docker-compose.yaml
│   └── .gitkeep
└── speedtest-tracker/
    ├── docker-compose.yaml
    └── .gitkeep

Volume Mounts and Data Locations

Services use the following host paths for persistent data:

Service Host Path Purpose
ByteStash /home/jramos/docker/bytestash/data Snippet storage
FileBrowser /home/docker/filebrowser/ Database and settings
Paperless-ngx /home/jramos/paperless-ngx/consume Document intake directory
Speedtest Tracker /home/jramos/docker/speedtest-tracker/config Configuration and database
Portainer portainer_data (Docker volume) Application data

Important: Ensure these directories exist with appropriate permissions before deploying services.

Network Configuration

All services are configured to use host networking or specific port mappings. If deploying behind Nginx Proxy Manager (CT 102 at 192.168.2.101):

  1. Services should be accessible via internal IPs and ports
  2. NPM handles external HTTPS access and SSL termination
  3. Use http scheme in NPM when forwarding to backend services
  4. Enable "Force SSL" in NPM for external HTTPS access

Security Considerations

Environment Files

  • .env files are excluded from git via .gitignore
  • Never commit credentials or API keys
  • Use strong, unique passwords for database services
  • Rotate JWT secrets and app keys regularly

Secrets in Docker Compose Files

Several services have embedded secrets in their docker-compose.yaml files:

  • ByteStash: JWT_SECRET: your-secret (CHANGE THIS)
  • Paperless-ngx: Database password paperless (CHANGE THIS)
  • Speedtest Tracker: APP_KEY (already generated, but sensitive)

Action Required: Create .env files and move secrets out of docker-compose.yaml files.

Network Exposure

  • Review port mappings before deployment
  • Consider using Docker networks instead of host port binding
  • Use NPM for external access with SSL
  • Implement authentication on all services

Troubleshooting

Service Won't Start

  1. Check logs: docker compose logs -f
  2. Verify port availability: netstat -tulpn | grep <port>
  3. Check volume permissions: ls -la /path/to/volume
  4. Validate docker-compose.yaml syntax: docker compose config

Cannot Access Service Externally

  1. Verify service is running: docker compose ps
  2. Test local access: curl http://localhost:<port>
  3. Check NPM proxy host configuration
  4. Verify DNS resolution
  5. Check firewall rules: iptables -L -n -v

Database Connection Errors (Paperless-ngx)

  1. Verify PostgreSQL container is running
  2. Check database credentials in environment variables
  3. Ensure database initialization completed: docker compose logs db
  4. Verify network connectivity between containers

Permission Denied Errors

  1. Check PUID/PGID settings in docker-compose.yaml
  2. Verify host directory ownership: chown -R <user>:<group> /path/to/volume
  3. Check SELinux context (if applicable): ls -Z /path/to/volume

Monitoring Stack Issues

Metrics Not Appearing:

  1. Verify PVE Exporter can reach Proxmox API
  2. Check Prometheus scrape targets status
  3. Ensure Grafana data source is configured correctly
  4. Review retention policies (data may be expired)

Authentication Failures (PVE Exporter):

  1. Verify Proxmox user credentials in .env file
  2. Check user has PVEAuditor role
  3. Test API access: curl -k https://192.168.2.200:8006/api2/json/version

High Resource Usage:

  1. Adjust Prometheus retention: --storage.tsdb.retention.time=7d
  2. Reduce scrape frequency in prometheus.yml
  3. Limit Grafana query concurrency
  4. Increase VM 101 resources if needed

Twingate Connector Issues

Connector Offline:

  1. Check CT 112 is running: pct status 112
  2. Verify network connectivity from container
  3. Check connector token validity in Twingate Console
  4. Review container logs for error messages

Cannot Access Resources:

  1. Verify resource is configured in Twingate Console
  2. Check user has permission to access resource
  3. Ensure connector is online and healthy
  4. Verify network routes on CT 112

Migration Notes

Post-Migration Tasks

  • Review all .env files and update with production values
  • Change default passwords and secrets in docker-compose files
  • Verify volume mount paths exist on target system
  • Test each service deployment individually
  • Configure NPM proxy hosts for external access
  • Update DNS records if service URLs changed
  • Backup existing service data before redeployment
  • Document any service-specific configuration changes

Known Issues

  • FileBrowser: Mounts entire filesystem root - review and restrict as needed
  • Paperless-ngx: Contains .env file with secrets - ensure it's excluded from git
  • GitLab Utilities: May require path adjustments depending on GitLab installation location

Contributing

When adding new services to this directory:

  1. Create a new subdirectory with service name (lowercase, hyphenated)
  2. Include docker-compose.yaml (or docker-compose.yml)
  3. Add .env.example if service requires environment variables
  4. Document service in this README under "Services Overview"
  5. Update directory structure diagram
  6. Test deployment from scratch before committing
  7. Ensure .gitignore excludes sensitive files

Additional Resources

Support

For homelab-specific questions or issues:

  • Check existing documentation in /home/jramos/homelab/
  • Review CLAUDE_STATUS.md for current infrastructure state
  • Consult service-specific documentation linked in each service section

Docker Socket Security

Overview

Direct Docker socket access (/var/run/docker.sock) provides complete control over the Docker daemon, equivalent to root access on the host system. This represents a significant security risk that must be carefully managed.

Current Exposures

The following containers currently have direct Docker socket access:

Service Socket Mount Risk Level Purpose
Portainer /var/run/docker.sock:/var/run/docker.sock CRITICAL Container management UI
Nginx Proxy Manager /var/run/docker.sock:/var/run/docker.sock CRITICAL Auto-discovery of containers
Speedtest Tracker /var/run/docker.sock:/var/run/docker.sock CRITICAL Container self-management

Risk Assessment: Any compromise of these containers grants an attacker root access to the host system via Docker API.

Implement a read-only socket proxy to restrict Docker API access:

Architecture:

Container → Docker Socket Proxy (read-only API) → Docker Daemon
         (filtered access)              (full access)

Implementation:

# docker-socket-proxy/docker-compose.yml
version: '3.8'
services:
  docker-socket-proxy:
    image: tecnativa/docker-socket-proxy:latest
    container_name: docker-socket-proxy
    restart: unless-stopped
    environment:
      CONTAINERS: 1     # Allow container listing
      NETWORKS: 1       # Allow network listing
      SERVICES: 0       # Deny service operations
      TASKS: 0          # Deny task operations
      POST: 0           # Deny POST (create/start/stop)
      DELETE: 0         # Deny DELETE operations
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
    ports:
      - 127.0.0.1:2375:2375

Migration Steps:

  1. Deploy socket proxy: cd docker-socket-proxy && docker compose up -d
  2. Update Portainer to use tcp://docker-socket-proxy:2375
  3. Update NPM to use HTTP API instead of socket
  4. Remove socket mounts from all containers
  5. Verify functionality and remove socket proxy if not needed

Reference: /home/jramos/homelab/scripts/security/docker-socket-proxy/


SSL/TLS Configuration

Overview

Transport Layer Security (TLS/SSL) encrypts traffic between clients and servers, preventing eavesdropping and man-in-the-middle attacks. All externally accessible services MUST use HTTPS.

Nginx Proxy Manager SSL Setup

Recommended Approach: Use Let's Encrypt for automatic certificate issuance and renewal.

Configuration Steps:

  1. Add Proxy Host:

    • Navigate to NPM UI: http://192.168.2.101:81
    • Proxy Hosts → Add Proxy Host
    • Domain: service.apophisnetworking.net
    • Scheme: http (internal communication)
    • Forward Hostname/IP: 192.168.2.xxx
    • Forward Port: 8080 (service port)
  2. Configure SSL:

    • SSL Tab → Request New Certificate
    • Certificate Type: Let's Encrypt
    • Email: your-email@domain.com
    • Toggle "Force SSL" (redirects HTTP → HTTPS)
    • Toggle "HTTP/2 Support"
    • Agree to Let's Encrypt ToS
  3. Advanced Options (Optional):

    # Custom headers for security
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-XSS-Protection "1; mode=block" always;
    

Certificate Management

Automatic Renewal:

  • Let's Encrypt certificates renew automatically 30 days before expiration
  • NPM handles renewal process transparently
  • Monitor renewal logs in NPM UI

Manual Certificate Upload: For internal certificates or custom CAs:

  1. SSL Certificates → Add SSL Certificate
  2. Certificate Type: Custom
  3. Paste certificate, private key, and intermediate certificates
  4. Save and apply to proxy hosts

Internal Service SSL

When to Use:

  • Communication between NPM and backend services can use HTTP (internal network)
  • Use HTTPS only if service contains highly sensitive data or requires end-to-end encryption

Self-Signed Certificate Generation:

# Generate self-signed certificate for internal service
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes \
  -subj "/C=US/ST=State/L=City/O=Homelab/CN=service.local"

SSL Verification Warnings

Issue: Some services (PVE Exporter, NetBox) use self-signed certificates causing verification errors.

Workarounds:

  • Option 1: Disable SSL verification (NOT recommended for production)
    environment:
      - VERIFY_SSL=false
    
  • Option 2: Add self-signed CA to trusted store
    # Copy CA certificate to trusted store
    cp /path/to/ca.crt /usr/local/share/ca-certificates/homelab-ca.crt
    update-ca-certificates
    
  • Option 3: Use Let's Encrypt for all services (recommended)

Credential Rotation Schedule

Regular credential rotation reduces the impact of credential compromise and is a security best practice.

Rotation Frequencies

Credential Type Rotation Frequency Automation Status Script
Proxmox API Tokens Quarterly (90 days) Manual rotate-pve-credentials.sh
Database Passwords Semi-Annual (180 days) Manual rotate-paperless-password.sh
JWT Secrets Annual (365 days) Manual rotate-bytestash-jwt.sh
Service Credentials Annual (365 days) Manual rotate-logward-credentials.sh
SSH Keys Biennial (730 days) Manual TBD
TLS Certificates Automatic (Let's Encrypt) Automatic NPM built-in

Rotation Workflow Example

Paperless-ngx Database Password Rotation:

# 1. Backup current configuration
cd /home/jramos/homelab/scripts/security
./backup-before-remediation.sh

# 2. Generate new password
NEW_PASSWORD=$(openssl rand -base64 32)

# 3. Run rotation script
./rotate-paperless-password.sh

# 4. Verify service health
docker compose -f /home/jramos/homelab/services/paperless-ngx/docker-compose.yml ps
docker compose -f /home/jramos/homelab/services/paperless-ngx/docker-compose.yml logs --tail=50

# 5. Test application login
curl -I https://atlas.apophisnetworking.net

# 6. Document rotation in logbook
echo "$(date): Rotated Paperless-ngx DB password" >> /home/jramos/homelab/security-logbook.txt

Credential Storage Best Practices

  1. Never commit credentials to git:

    • Use .env files (gitignored)
    • Use Docker secrets for production
    • Use HashiCorp Vault for enterprise
  2. Separate credentials from code:

    # BAD: Hardcoded credentials
    environment:
      DB_PASSWORD: "hardcoded_password"
    
    # GOOD: Environment variable
    environment:
      DB_PASSWORD: ${DB_PASSWORD}
    
    # BEST: Docker secret
    secrets:
      - db_password
    
  3. Use strong, unique passwords:

    # Generate cryptographically secure password
    openssl rand -base64 32
    
    # Generate passphrase-style password
    shuf -n 6 /usr/share/dict/words | tr '\n' '-' | sed 's/-$//'
    

Secrets Migration Strategy

Current State: Secrets in Docker Compose Files

Several services have embedded credentials in docker-compose.yml files tracked by git:

Service Secret Type Location Risk Level
ByteStash JWT_SECRET docker-compose.yml HIGH
Paperless-ngx DB_PASSWORD docker-compose.yml CRITICAL
Speedtest Tracker APP_KEY docker-compose.yml MEDIUM
Logward OIDC_CLIENT_SECRET docker-compose.yml HIGH

Current Risk: Credentials visible in git history, repository access = credential access.

Migration Path

Phase 1: Move to .env Files (Immediate - Low Risk)

# For each service:
cd /home/jramos/homelab/services/<service-name>

# 1. Create .env file
cat > .env << 'EOF'
# Database credentials
DB_PASSWORD=<strong-password-here>
DB_USER=paperless

# Application secrets
SECRET_KEY=<generated-secret-key>
EOF

# 2. Update docker-compose.yml
# Replace:
#   environment:
#     - DB_PASSWORD=hardcoded_password
# With:
#   env_file:
#     - .env

# 3. Verify .env is gitignored
git check-ignore .env  # Should show ".env" if properly ignored

# 4. Test deployment
docker compose config  # Validates .env interpolation
docker compose up -d

# 5. Remove credentials from docker-compose.yml
git add docker-compose.yml
git commit -m "fix(security): move credentials to .env file"

Phase 2: Docker Secrets (Future - Production Grade)

For services requiring enhanced security:

# docker-compose.yml with secrets
version: '3.8'
services:
  paperless:
    image: ghcr.io/paperless-ngx/paperless-ngx:latest
    secrets:
      - db_password
      - secret_key
    environment:
      PAPERLESS_DBPASS_FILE: /run/secrets/db_password
      PAPERLESS_SECRET_KEY_FILE: /run/secrets/secret_key

secrets:
  db_password:
    file: ./secrets/db_password.txt
  secret_key:
    file: ./secrets/secret_key.txt

Phase 3: External Secret Management (Future - Enterprise)

For homelab expansion or multi-node deployments:

  • HashiCorp Vault integration
  • Kubernetes Secrets (if migrating to K8s)
  • AWS Secrets Manager / Azure Key Vault (hybrid cloud)

Migration Priority

  1. Immediate (Week 1):

    • ByteStash JWT_SECRET → .env
    • Paperless-ngx DB_PASSWORD → .env
    • Speedtest Tracker APP_KEY → .env
  2. Short-term (Month 1):

    • All remaining services migrated to .env
    • Git history scrubbing (BFG Repo-Cleaner)
  3. Long-term (Quarter 1):

    • Evaluate Docker Secrets for production services
    • Implement Vault for Proxmox credentials

Security Audit References

Latest Audit: 2025-12-20

Comprehensive Security Assessment Results:

Severity Count Examples
CRITICAL 6 Docker socket exposure, hardcoded credentials, database passwords
HIGH 3 Missing SSL/TLS, weak passwords, containers as root
MEDIUM 2 SSL verification disabled, missing auth
LOW 20 Documentation gaps, monitoring needs, backup encryption

Total Findings: 31 security issues identified

Detailed Report: /home/jramos/homelab/troubleshooting/SECURITY_AUDIT_2025-12-20.md

Critical Findings Summary

CRITICAL-001: Docker Socket Exposure (CVSS 9.8)

  • Affected: Portainer, Nginx Proxy Manager, Speedtest Tracker
  • Impact: Container escape to host root access
  • Remediation: Implement docker-socket-proxy with read-only permissions
  • Timeline: Week 1

CRITICAL-002: Proxmox Credentials in Plaintext (CVSS 9.1)

  • Affected: PVE Exporter configuration files
  • Impact: Full Proxmox infrastructure compromise
  • Remediation: Use Proxmox API tokens, move to environment variables
  • Timeline: Week 1

CRITICAL-003: Database Passwords in Git (CVSS 8.5)

  • Affected: Paperless-ngx, ByteStash, Speedtest Tracker
  • Impact: Credential exposure via repository access
  • Remediation: Migrate to .env files, scrub git history
  • Timeline: Week 1

Remediation Progress

Track remediation status in /home/jramos/homelab/CLAUDE_STATUS.md under "Security Audit Initiative"

Phase 1 - Immediate (Week 1):

  • Backup all service configurations
  • Deploy docker-socket-proxy
  • Migrate Portainer to socket proxy
  • Move database passwords to .env files

Phase 2 - Low-Risk Changes (Weeks 2-3):

  • Rotate Proxmox API credentials
  • Implement SSL/TLS for internal services
  • Enable container user namespacing
  • Deploy fail2ban

Phase 3 - High-Risk Changes (Month 2):

  • Migrate NPM to socket proxy
  • Remove socket mounts from all containers
  • Implement network segmentation
  • Enable backup encryption

Phase 4 - Infrastructure (Quarter 1):

  • Container vulnerability scanning pipeline
  • Automated credential rotation
  • Security monitoring dashboards

Security Checklist

Pre-Deployment Security Checklist: /home/jramos/homelab/templates/SECURITY_CHECKLIST.md

Use this checklist before deploying ANY new service to ensure security best practices.

Validation Scripts

Security Script Validation Report: /home/jramos/homelab/scripts/security/VALIDATION_REPORT.md

All security scripts have been validated by the lab-operator agent:

  • Ready for Execution: 5/8 scripts (verify-service-status.sh, rotate-pve-credentials.sh, rotate-bytestash-jwt.sh, backup-before-remediation.sh)
  • Needs Container Name Fixes: 3/8 scripts (see CONTAINER_NAME_FIXES.md)

Last Updated: 2025-12-21 Maintainer: jramos Repository: http://192.168.2.102:3060/jramos/homelab Infrastructure: 8 VMs, 2 Templates, 4 LXC Containers