# 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](../docker-compose.prod.yml))** Added the `attachments_files` mount to the Go container: ```yaml 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](vault-cron-prod.sh))** Changed the `--emaildir` flag to point to the correct directory: ```bash 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** - [VAULT_QUICKSTART.md](VAULT_QUICKSTART.md) - Updated all examples - [VAULT_DEPLOYMENT.md](VAULT_DEPLOYMENT.md) - Updated deployment instructions ## Verification Steps After deploying the fix, verify it works: ### Step 1: Rebuild and Restart Containers ```bash cd ~/src/cmc-sales docker compose -f docker-compose.prod.yml up -d cmc-prod-go ``` ### Step 2: Verify Mount Points ```bash # 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 ```bash # 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 ```bash # 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 ```bash # 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: ```sql -- email_attachments table name: "11-2025/abc123-filename.pdf" ``` The PHP application prepends the base path: ```php $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) ### Alternative 1: Symlink (Not Needed) 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