cmc-sales/scripts/VAULT_PERMISSIONS_FIX.md
2025-12-23 15:54:26 +11:00

7.3 KiB

Vault Permissions Fix - Attachment Directory Issue

Problem

The PHP container (cmc-prod-php) could not read attachments written by the Go vault because they were being written to different directories.

Root Cause Analysis

Go Vault Container (cmc-prod-go):

  • Was writing attachments to: /var/www/emails/ (default --emaildir flag)
  • Host directory: /home/cmc/files/emails
  • Running as: root user (UID 0)

PHP Application Container (cmc-prod-php):

  • Reads attachments from: /var/www/cmc-sales/app/webroot/attachments_files/
  • Host directory: /home/cmc/files/attachments_files
  • Running as: www-data user (UID 33 or 82)

Two Issues Identified

  1. Different Directory Paths (Primary Issue)

    • Go wrote to /var/www/emails → Host: /home/cmc/files/emails
    • PHP read from /var/www/cmc-sales/app/webroot/attachments_files → Host: /home/cmc/files/attachments_files
    • These are completely separate directories on the host!
  2. File Permissions (Secondary) ⚠️

    • Files: 0644 (-rw-r--r--) - World readable
    • Directories: 0755 (drwxr-xr-x) - World readable/executable
    • Owner: root:root (from Go container)
    • Reader: www-data (from PHP container)
    • Verdict: Permissions were actually OK (world-readable), but wrong directory!

Solution Implemented

Changes Made

1. Updated Docker Compose (docker-compose.prod.yml)

Added the attachments_files mount to the Go container:

cmc-prod-go:
  volumes:
    - /home/cmc/files/attachments_files:/var/www/attachments_files  # ← ADDED
    - /home/cmc/files/emails:/var/www/emails
    - /home/cmc/files/vault:/var/www/vault
    - /home/cmc/files/vaultmsgs:/var/www/vaultmsgs

2. Updated Vault Cron Script (scripts/vault-cron-prod.sh)

Changed the --emaildir flag to point to the correct directory:

docker exec -t "$CONTAINER_NAME" ./vault --mode=local \
  --vaultdir=/var/www/vaultmsgs/new \
  --processeddir=/var/www/vaultmsgs/cur \
  --emaildir=/var/www/attachments_files \  # ← CHANGED from /var/www/emails
  --dbhost=cmc-prod-db \
  --dbuser=cmc \
  --dbpass="xVRQI&cA?7AU=hqJ!%au" \
  --dbname=cmc

3. Updated Documentation

Verification Steps

After deploying the fix, verify it works:

Step 1: Rebuild and Restart Containers

cd ~/src/cmc-sales
docker compose -f docker-compose.prod.yml up -d cmc-prod-go

Step 2: Verify Mount Points

# Check Go container can see the directory
docker exec -it cmc-prod-go ls -la /var/www/attachments_files

# Check PHP container can see the directory
docker exec -it cmc-prod-php ls -la /var/www/cmc-sales/app/webroot/attachments_files

Both should show the same files (same inode on host).

Step 3: Test Vault Processing

# Run vault manually
~/scripts/vault-cron-prod.sh

# Check if files were written
ls -la /home/cmc/files/attachments_files/$(date +%m-%Y)/

# Check file permissions
ls -l /home/cmc/files/attachments_files/$(date +%m-%Y)/ | head -5

Expected output:

-rw-r--r-- 1 root root  1234 Nov 23 10:00 abc123-texthtml
-rw-r--r-- 1 root root  5678 Nov 23 10:00 abc123-document.pdf

Step 4: Verify PHP Can Read Files

# Enter PHP container as www-data user
docker exec -it -u www-data cmc-prod-php sh

# Try to read an attachment file
cd /var/www/cmc-sales/app/webroot/attachments_files/$(date +%m-%Y)
ls -la
cat abc123-texthtml  # Should display content
exit

Step 5: Check Database

# Verify attachments are in database with correct paths
docker exec -it cmc-prod-db mariadb -u cmc -p cmc -e "
SELECT id, email_id, filename, name, size
FROM email_attachments
ORDER BY created DESC
LIMIT 5;
"

The name column should contain paths like: 11-2025/abc123-filename.pdf

File Permissions Breakdown

The current permissions (0644 for files, 0755 for dirs) are correct:

File Permissions: 0644

-rw-r--r--
│││││││││
│││└─┴─┴─── Other (everyone): read (r--)
││└─┬─┴───── Group: read (r--)
│└─┬┴─────── Owner: read + write (rw-)
└─────────── Regular file (-)

Result: All users (including www-data) can read the files

Directory Permissions: 0755

drwxr-xr-x
││││││││││
│││└─┴─┴─── Other: read + execute (r-x) - can list & access
││└─┬─┴───── Group: read + execute (r-x)
│└─┬┴─────── Owner: read + write + execute (rwx)
└─────────── Directory (d)

Result: All users can navigate into and list the directories

Why This Works

  1. Files are world-readable (r-- in other bits)
  2. Directories are world-executable (x in other bits)
  3. Even though owner is root:root, the "other" permissions allow www-data to read

When You'd Need to Change Permissions

You would only need different permissions if:

Scenario Change To Reason
Only owner should read 0600 / 0700 Security/privacy
Group needs write access 0664 / 0775 Collaborative editing
Everyone needs write 0666 / 0777 ⚠️ NOT recommended - security risk

For your use case: Keep 0644 / 0755

Database Path Storage

The vault stores relative paths in the database:

-- email_attachments table
name: "11-2025/abc123-filename.pdf"

The PHP application prepends the base path:

$fullPath = "/var/www/cmc-sales/app/webroot/attachments_files/" . $attachment['name'];
// Results in: /var/www/cmc-sales/app/webroot/attachments_files/11-2025/abc123-filename.pdf

This is why the directory mount must be correct!

Alternative Solutions (Not Implemented)

Could create a symlink from /var/www/emails/var/www/attachments_files, but this adds complexity.

Alternative 2: Change User ID (Overkill)

Could run Go container as www-data user, but:

  • Requires rebuilding the Dockerfile
  • Adds unnecessary complexity
  • Current permissions already work

Alternative 3: Set Group Permissions (Unnecessary)

Could use 0664 / 0775 and shared group, but:

  • World-readable permissions already work
  • No need for write access
  • Simpler is better

Summary

What was fixed:

  • Go vault now writes to /var/www/attachments_files (same as PHP reads from)
  • Added volume mount for attachments_files directory
  • Updated all scripts and documentation

What didn't need fixing:

  • File permissions (0644) are already world-readable
  • Directory permissions (0755) are already world-accessible
  • No user/group changes needed

Root cause:

  • Wrong directory path, NOT permissions issue

Deployment Checklist

  • Pull latest code with fixes
  • Restart Go container (docker compose up -d cmc-prod-go)
  • Verify mount points in both containers
  • Run vault manually to test
  • Check files appear in /home/cmc/files/attachments_files/
  • Verify PHP can read the files
  • Check database paths are correct
  • Enable cron job
  • Monitor logs for 24 hours