- Add SECURITY.md policy with credential management, Docker security, SSL/TLS guidance - Add security audit report (2025-12-20) with 31 findings across 4 severity levels - Add pre-deployment security checklist template - Update CLAUDE_STATUS.md with security audit initiative - Expand services/README.md with comprehensive security sections - Add script validation report and container name fix guide Audit identified 6 CRITICAL, 3 HIGH, 2 MEDIUM findings 4-phase remediation roadmap created (estimated 6-13 min downtime) All security scripts validated and ready for execution Related: Security Audit Q4 2025, CRITICAL-001 through CRITICAL-006 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
15 KiB
Container Name Standardization
Issue: MED-010 from Security Audit 2025-12-20 Severity: Medium (Low priority, continuous improvement) Impact: Inconsistent container naming makes monitoring and automation difficult
Current State
Docker Compose automatically generates container names using the format:
<directory>-<service>-<instance>
This results in inconsistent and unclear names:
| Current Name | Service | Issue |
|---|---|---|
paperless-ngx-webserver-1 |
Paperless webserver | Redundant "ngx" and unclear purpose |
paperless-ngx-db-1 |
PostgreSQL | Unclear it's Paperless database |
speedtest-tracker-app-1 |
Speedtest main service | Generic "app" name |
tinyauth-tinyauth-1 |
TinyAuth | Duplicate service name |
monitoring-grafana-1 |
Grafana | Directory name included |
monitoring-prometheus-1 |
Prometheus | Directory name included |
Desired State
Use explicit container_name directive for clarity:
| Desired Name | Service | Benefit |
|---|---|---|
paperless-webserver |
Paperless webserver | Clear, no instance suffix |
paperless-db |
Paperless PostgreSQL | Obviously Paperless database |
paperless-redis |
Paperless Redis | Clear purpose |
speedtest-tracker |
Speedtest service | Concise, descriptive |
tinyauth |
TinyAuth | Simple, no duplication |
grafana |
Grafana | Short, clear |
prometheus |
Prometheus | Short, clear |
Naming Convention Standard
Format
<service>[-<component>]
Examples
Single-container services:
services:
tinyauth:
container_name: tinyauth
# ...
Multi-container services:
services:
webserver:
container_name: paperless-webserver
# ...
db:
container_name: paperless-db
# ...
redis:
container_name: paperless-redis
# ...
Rules
- Use lowercase - All container names lowercase
- Use hyphens - Separate words with hyphens (not underscores)
- Be descriptive - Name should indicate purpose
- Be concise - Avoid redundancy (no "paperless-ngx-paperless-1")
- No instance numbers - Use
container_nameto remove-1,-2suffixes - Service prefix for multi-container - e.g.,
paperless-db,paperless-redis - No directory names - Avoid
monitoring-grafana, just usegrafana
Implementation
Step 1: Update docker-compose.yaml Files
For each service, add container_name directive.
ByteStash
File: /home/jramos/homelab/services/bytestash/docker-compose.yaml
services:
bytestash:
container_name: bytestash # Add this line
image: ghcr.io/jordan-dalby/bytestash:latest
# ... rest of configuration
FileBrowser
File: /home/jramos/homelab/services/filebrowser/docker-compose.yaml
services:
filebrowser:
container_name: filebrowser # Add this line
image: filebrowser/filebrowser:latest
# ... rest of configuration
Paperless-ngx
File: /home/jramos/homelab/services/paperless-ngx/docker-compose.yaml
services:
broker:
container_name: paperless-redis # Add this line
image: redis:8
# ...
db:
container_name: paperless-db # Add this line
image: postgres:17
# ...
webserver:
container_name: paperless-webserver # Add this line
image: ghcr.io/paperless-ngx/paperless-ngx:latest
# ...
gotenberg:
container_name: paperless-gotenberg # Add this line
image: gotenberg:8.20
# ...
tika:
container_name: paperless-tika # Add this line
image: apache/tika:latest
# ...
Portainer
File: /home/jramos/homelab/services/portainer/docker-compose.yaml
services:
portainer:
container_name: portainer # Add this line
image: portainer/portainer-ce:latest
# ... rest of configuration
Speedtest Tracker
File: /home/jramos/homelab/services/speedtest-tracker/docker-compose.yaml
services:
app:
container_name: speedtest-tracker # Add this line
image: lscr.io/linuxserver/speedtest-tracker:latest
# ... rest of configuration
TinyAuth
File: /home/jramos/homelab/services/tinyauth/docker-compose.yml
services:
tinyauth:
container_name: tinyauth # Add this line
image: ghcr.io/steveiliop56/tinyauth:v4
# ... rest of configuration
Monitoring Stack
Grafana - /home/jramos/homelab/monitoring/grafana/docker-compose.yml:
services:
grafana:
container_name: grafana # Add this line
image: grafana/grafana:latest
# ...
Prometheus - /home/jramos/homelab/monitoring/prometheus/docker-compose.yml:
services:
prometheus:
container_name: prometheus # Add this line
image: prom/prometheus:latest
# ...
PVE Exporter - /home/jramos/homelab/monitoring/pve-exporter/docker-compose.yml:
services:
pve-exporter:
container_name: pve-exporter # Add this line
image: prompve/prometheus-pve-exporter:latest
# ...
Loki - /home/jramos/homelab/monitoring/loki/docker-compose.yml:
services:
loki:
container_name: loki # Add this line
image: grafana/loki:latest
# ...
Promtail - /home/jramos/homelab/monitoring/promtail/docker-compose.yml:
services:
promtail:
container_name: promtail # Add this line
image: grafana/promtail:latest
# ...
n8n
File: /home/jramos/homelab/services/n8n/docker-compose.yml
services:
n8n:
container_name: n8n # Add this line
image: n8nio/n8n:latest
# ...
postgres:
container_name: n8n-db # Add this line
image: postgres:15
# ...
Docker Socket Proxy
File: /home/jramos/homelab/services/docker-socket-proxy/docker-compose.yml
services:
socket-proxy:
container_name: socket-proxy # Add this line
image: tecnativa/docker-socket-proxy:latest
# ...
Step 2: Apply Changes
For each service, recreate containers with new names:
cd /home/jramos/homelab/services/<service-name>
# Stop existing containers
docker compose down
# Start with new container names
docker compose up -d
# Verify new container names
docker compose ps
Important: This will recreate containers but preserve data in volumes.
Step 3: Update Monitoring
After renaming containers, update Prometheus scrape configs if using container discovery:
File: /home/jramos/homelab/monitoring/prometheus/prometheus.yml
scrape_configs:
- job_name: 'grafana'
static_configs:
- targets: ['grafana:3000'] # Use new container name
- job_name: 'prometheus'
static_configs:
- targets: ['prometheus:9090'] # Use new container name
Step 4: Update Documentation
Update references to container names in:
/home/jramos/homelab/services/README.md/home/jramos/homelab/monitoring/README.md- Any troubleshooting guides
- Any automation scripts
Automated Fix Script
To automate the container name standardization:
File: /home/jramos/homelab/scripts/security/fix-container-names.sh
#!/bin/bash
# Standardize container names across all Docker Compose services
# Addresses MED-010: Container Name Inconsistency
set -euo pipefail
SERVICES_DIR="/home/jramos/homelab/services"
MONITORING_DIR="/home/jramos/homelab/monitoring"
TIMESTAMP=$(date +%Y%m%d-%H%M%S)
DRY_RUN=false
if [[ "${1:-}" == "--dry-run" ]]; then
DRY_RUN=true
echo "DRY RUN MODE - No changes will be made"
fi
# Container name mappings
declare -A CONTAINER_NAMES=(
# Services
["bytestash"]="bytestash"
["filebrowser"]="filebrowser"
["paperless-ngx/broker"]="paperless-redis"
["paperless-ngx/db"]="paperless-db"
["paperless-ngx/webserver"]="paperless-webserver"
["paperless-ngx/gotenberg"]="paperless-gotenberg"
["paperless-ngx/tika"]="paperless-tika"
["portainer"]="portainer"
["speedtest-tracker/app"]="speedtest-tracker"
["tinyauth"]="tinyauth"
["n8n/n8n"]="n8n"
["n8n/postgres"]="n8n-db"
["docker-socket-proxy/socket-proxy"]="socket-proxy"
# Monitoring
["monitoring/grafana"]="grafana"
["monitoring/prometheus"]="prometheus"
["monitoring/pve-exporter"]="pve-exporter"
["monitoring/loki"]="loki"
["monitoring/promtail"]="promtail"
)
add_container_name() {
local COMPOSE_FILE=$1
local SERVICE=$2
local CONTAINER_NAME=$3
echo "Processing $COMPOSE_FILE (service: $SERVICE)"
if [[ ! -f "$COMPOSE_FILE" ]]; then
echo " ⚠️ File not found: $COMPOSE_FILE"
return 1
fi
# Backup original file
if [[ "$DRY_RUN" == false ]]; then
cp "$COMPOSE_FILE" "$COMPOSE_FILE.backup-$TIMESTAMP"
echo " ✓ Backup created"
fi
# Check if container_name already exists for this service
if grep -A 5 "^[[:space:]]*$SERVICE:" "$COMPOSE_FILE" | grep -q "container_name:"; then
echo " ℹ️ container_name already set"
return 0
fi
# Add container_name directive
if [[ "$DRY_RUN" == false ]]; then
# Find the service block and add container_name after service name
awk -v service="$SERVICE" -v name="$CONTAINER_NAME" '
/^[[:space:]]*'"$SERVICE"':/ {
print
print " container_name: " name
next
}
{print}
' "$COMPOSE_FILE" > "$COMPOSE_FILE.tmp"
mv "$COMPOSE_FILE.tmp" "$COMPOSE_FILE"
echo " ✓ Added container_name: $CONTAINER_NAME"
else
echo " [DRY RUN] Would add container_name: $CONTAINER_NAME"
fi
# Validate compose file syntax
if [[ "$DRY_RUN" == false ]]; then
if docker compose -f "$COMPOSE_FILE" config > /dev/null 2>&1; then
echo " ✓ Compose file syntax valid"
else
echo " ✗ ERROR: Compose file syntax invalid"
echo " Restoring backup..."
mv "$COMPOSE_FILE.backup-$TIMESTAMP" "$COMPOSE_FILE"
return 1
fi
fi
}
main() {
echo "=== Container Name Standardization ==="
echo ""
# Process all container name mappings
for KEY in "${!CONTAINER_NAMES[@]}"; do
# Parse key: "service" or "service/container"
if [[ "$KEY" == *"/"* ]]; then
# Multi-container service
DIR=$(echo "$KEY" | cut -d'/' -f1)
SERVICE=$(echo "$KEY" | cut -d'/' -f2)
if [[ "$DIR" == "monitoring" ]]; then
COMPOSE_FILE="$MONITORING_DIR/$SERVICE/docker-compose.yml"
else
COMPOSE_FILE="$SERVICES_DIR/$DIR/docker-compose.yaml"
fi
else
# Single-container service
DIR="$KEY"
SERVICE="$KEY"
COMPOSE_FILE="$SERVICES_DIR/$DIR/docker-compose.yaml"
fi
CONTAINER_NAME="${CONTAINER_NAMES[$KEY]}"
add_container_name "$COMPOSE_FILE" "$SERVICE" "$CONTAINER_NAME"
echo ""
done
echo "=== Summary ==="
echo "Services processed: ${#CONTAINER_NAMES[@]}"
if [[ "$DRY_RUN" == true ]]; then
echo "Mode: DRY RUN (no changes made)"
echo "Run without --dry-run to apply changes"
else
echo "Mode: LIVE (changes applied)"
echo ""
echo "⚠️ IMPORTANT: Restart services to use new container names"
echo "Example:"
echo " cd $SERVICES_DIR/paperless-ngx"
echo " docker compose down"
echo " docker compose up -d"
fi
}
main "$@"
Usage:
# Test in dry-run mode
./fix-container-names.sh --dry-run
# Apply changes
./fix-container-names.sh
# Restart all services (optional script)
cd /home/jramos/homelab
find services monitoring -name "docker-compose.y*ml" -execdir bash -c 'docker compose down && docker compose up -d' \;
Verification
After applying changes, verify new container names:
# List all containers with new names
docker ps --format "table {{.Names}}\t{{.Image}}\t{{.Status}}"
# Expected output:
# NAMES IMAGE STATUS
# bytestash ghcr.io/jordan-dalby/bytestash:latest Up 5 minutes
# filebrowser filebrowser/filebrowser:latest Up 5 minutes
# paperless-webserver ghcr.io/paperless-ngx/paperless-ngx Up 5 minutes
# paperless-db postgres:17 Up 5 minutes
# paperless-redis redis:8 Up 5 minutes
# grafana grafana/grafana:latest Up 5 minutes
# prometheus prom/prometheus:latest Up 5 minutes
# tinyauth ghcr.io/steveiliop56/tinyauth:v4 Up 5 minutes
Monitoring Dashboard Update
If using Grafana dashboards that reference container names, update queries:
Before:
rate(container_cpu_usage_seconds_total{name="paperless-ngx-webserver-1"}[5m])
After:
rate(container_cpu_usage_seconds_total{name="paperless-webserver"}[5m])
Log Aggregation Update
If using Loki/Promtail with container name labels, update label matchers:
Before:
{container_name="paperless-ngx-webserver-1"}
After:
{container_name="paperless-webserver"}
Benefits
After standardization:
- Clarity: Container names clearly indicate purpose
- Consistency: All containers follow same naming pattern
- Automation: Easier to write scripts targeting specific containers
- Monitoring: Cleaner metrics and log labels
- Documentation: Less confusion in guides and troubleshooting docs
- Maintainability: Easier for new team members to understand infrastructure
Rollback
If issues occur after renaming:
# Restore original docker-compose.yaml
cd /home/jramos/homelab/services/<service>
mv docker-compose.yaml.backup-<timestamp> docker-compose.yaml
# Recreate containers with original names
docker compose down
docker compose up -d
Future Considerations
Docker Compose Project Names
Consider also standardizing Docker Compose project names using:
name: paperless # Add to top of docker-compose.yaml
services:
# ...
This controls the prefix used in network and volume names.
Container Labels
Add labels for better organization:
services:
paperless-webserver:
container_name: paperless-webserver
labels:
- "com.homelab.service=paperless"
- "com.homelab.component=webserver"
- "com.homelab.tier=application"
- "com.homelab.environment=production"
Labels enable advanced filtering and automation.
Completion Checklist
- Review current container names
- Update all docker-compose.yaml files with
container_name - Validate compose file syntax
- Stop and restart all services
- Verify new container names
- Update Prometheus configs (if using container discovery)
- Update Grafana dashboards
- Update Loki/Promtail configs
- Update documentation
- Update automation scripts
- Test monitoring and logging
- Commit changes to git
Issue: MED-010 Priority: Low (Continuous Improvement) Estimated Effort: 2-3 hours Status: Documentation Complete - Ready for Implementation
Document Version: 1.0 Last Updated: 2025-12-20 Author: Claude Code (Scribe Agent)