|
| 1 | +# Read-Only Filesystem and Security Hardening Guide |
| 2 | + |
| 3 | +The Subscription Tracker Docker container now fully supports **read-only filesystems** and **user directives** for maximum security compliance. |
| 4 | + |
| 5 | +## ✅ **Enhanced Security Support** |
| 6 | + |
| 7 | +### **Read-Only Filesystem Compatibility** |
| 8 | +```bash |
| 9 | +# Full read-only support with tmpfs for temporary files |
| 10 | +docker run -d \ |
| 11 | + --read-only \ |
| 12 | + --tmpfs /tmp:size=100M,mode=1777 \ |
| 13 | + --tmpfs /var/tmp:size=10M,mode=1777 \ |
| 14 | + -v ./data:/app/instance:rw \ |
| 15 | + subscription-tracker |
| 16 | +``` |
| 17 | + |
| 18 | +### **User Directive Support** |
| 19 | +```bash |
| 20 | +# Run as specific user without privilege escalation |
| 21 | +docker run -d \ |
| 22 | + --user 1000:1000 \ |
| 23 | + --read-only \ |
| 24 | + --cap-drop ALL \ |
| 25 | + --cap-add NET_BIND_SERVICE \ |
| 26 | + --security-opt no-new-privileges:true \ |
| 27 | + -v ./data:/app/instance:rw \ |
| 28 | + subscription-tracker |
| 29 | +``` |
| 30 | + |
| 31 | +### **Docker Compose Security Example** |
| 32 | +```yaml |
| 33 | +version: '3.8' |
| 34 | +services: |
| 35 | + web: |
| 36 | + build: . |
| 37 | + user: "1000:1000" |
| 38 | + read_only: true |
| 39 | + cap_drop: |
| 40 | + - ALL |
| 41 | + cap_add: |
| 42 | + - NET_BIND_SERVICE |
| 43 | + security_opt: |
| 44 | + - no-new-privileges:true |
| 45 | + tmpfs: |
| 46 | + - /tmp:size=100M,mode=1777 |
| 47 | + - /var/tmp:size=10M,mode=1777 |
| 48 | + volumes: |
| 49 | + - ./data:/app/instance:rw |
| 50 | + ports: |
| 51 | + - "5000:5000" |
| 52 | +``` |
| 53 | +
|
| 54 | +## 🔧 **How Enhanced Security Works** |
| 55 | +
|
| 56 | +### **Automatic Detection** |
| 57 | +The container automatically detects and adapts to: |
| 58 | +
|
| 59 | +1. **🔒 Read-Only Filesystems** - Detects when `/` is mounted read-only |
| 60 | +2. **👤 User Directives** - Detects when started with `--user` flag |
| 61 | +3. **📁 Restricted Permissions** - Handles when `/etc/passwd` is not writable |
| 62 | +4. **🛡️ Security Contexts** - Works with Kubernetes security policies |
| 63 | + |
| 64 | +### **Deployment Modes** |
| 65 | + |
| 66 | +#### **Standard Mode (Default)** |
| 67 | +```bash |
| 68 | +# Full PUID/GUID support with user creation |
| 69 | +PUID=1000 GUID=1000 docker-compose up |
| 70 | +``` |
| 71 | +**Features:** |
| 72 | +- ✅ Creates custom users/groups |
| 73 | +- ✅ Full PUID/GUID functionality |
| 74 | +- ✅ Automatic permission fixing |
| 75 | +- ✅ Database ownership management |
| 76 | + |
| 77 | +#### **Read-Only Mode** |
| 78 | +```bash |
| 79 | +# Security-hardened with read-only filesystem |
| 80 | +docker run --read-only --user 1000:1000 subscription-tracker |
| 81 | +``` |
| 82 | +**Features:** |
| 83 | +- ✅ No user creation attempts |
| 84 | +- ✅ Works with existing user ID |
| 85 | +- ✅ Database permissions via mount ownership |
| 86 | +- ✅ Compatible with security scanners |
| 87 | + |
| 88 | +#### **User Directive Mode** |
| 89 | +```bash |
| 90 | +# Kubernetes-compatible with security context |
| 91 | +docker run --user 1000:1000 subscription-tracker |
| 92 | +``` |
| 93 | +**Features:** |
| 94 | +- ✅ Runs as specified user from start |
| 95 | +- ✅ No privilege escalation |
| 96 | +- ✅ Compatible with security policies |
| 97 | +- ✅ Works in restricted environments |
| 98 | + |
| 99 | +## 🎯 **Expected Behavior by Mode** |
| 100 | + |
| 101 | +### **Standard Mode Output:** |
| 102 | +``` |
| 103 | +🔧 Setting up user mapping... |
| 104 | +🔧 Standard PUID/GUID mode: Setting up mapping 1000:1000 |
| 105 | +✅ Created group appgroup with GID 1000 |
| 106 | +✅ Created user appuser with UID 1000 |
| 107 | +✅ User mapping configured: 1000:1000 |
| 108 | +🎯 Deployment mode: STANDARD |
| 109 | +🔑 Running as root - fixing ownership and permissions |
| 110 | +✅ Set /app/instance ownership to 1000:1000 with 755 permissions |
| 111 | +🔽 Dropping privileges to 1000:1000 |
| 112 | +``` |
| 113 | +
|
| 114 | +### **Read-Only Mode Output:** |
| 115 | +``` |
| 116 | +🔧 Setting up user mapping... |
| 117 | +🔒 Read-only filesystem or restricted user management detected |
| 118 | +🔒 Read-only filesystem mode |
| 119 | +⚠️ Running as root but cannot create users in read-only filesystem |
| 120 | +💡 For PUID/GUID support in read-only mode, use: |
| 121 | + docker run --user 1000:1000 --read-only ... |
| 122 | +🎯 Deployment mode: READ-ONLY |
| 123 | +ℹ️ Directory permissions unchanged (read-only filesystem) |
| 124 | +``` |
| 125 | +
|
| 126 | +### **User Directive Mode Output:** |
| 127 | +``` |
| 128 | +🔧 Setting up user mapping... |
| 129 | +👤 Container started with user directive (--user flag) |
| 130 | +📋 User directive mode: Running as 1000:1000 |
| 131 | +ℹ️ PUID/GUID variables ignored in user directive mode |
| 132 | +✅ Using container's current user for all operations |
| 133 | +🎯 Deployment mode: STANDARD + USER-DIRECTIVE |
| 134 | +👤 User directive mode: Running directly as 1000:1000 |
| 135 | +``` |
| 136 | +
|
| 137 | +## 🛡️ **Security Features** |
| 138 | +
|
| 139 | +### **No Privilege Escalation** |
| 140 | +- Container can run entirely as non-root |
| 141 | +- No `sudo` or `setuid` operations required |
| 142 | +- Compatible with `no-new-privileges:true` |
| 143 | +
|
| 144 | +### **Read-Only Root Filesystem** |
| 145 | +- Application data isolated to mounted volumes |
| 146 | +- No writes to container filesystem |
| 147 | +- Prevents runtime tampering |
| 148 | +
|
| 149 | +### **Capability Dropping** |
| 150 | +- Minimal capabilities required |
| 151 | +- Only `NET_BIND_SERVICE` needed for port binding |
| 152 | +- All other capabilities can be dropped |
| 153 | +
|
| 154 | +### **User Namespace Compatibility** |
| 155 | +- Works with Docker user namespace remapping |
| 156 | +- Compatible with rootless Docker |
| 157 | +- Supports Kubernetes security contexts |
| 158 | +
|
| 159 | +## 🚨 **Migration from Previous Versions** |
| 160 | +
|
| 161 | +### **If You Currently Use PUID/GUID:** |
| 162 | +Your existing setup continues to work: |
| 163 | +```yaml |
| 164 | +# This still works exactly the same |
| 165 | +environment: |
| 166 | + - PUID=1000 |
| 167 | + - GUID=1000 |
| 168 | +``` |
| 169 | + |
| 170 | +### **To Enable Maximum Security:** |
| 171 | +Add security hardening: |
| 172 | +```yaml |
| 173 | +# Enhanced security version |
| 174 | +user: "1000:1000" |
| 175 | +read_only: true |
| 176 | +cap_drop: [ALL] |
| 177 | +cap_add: [NET_BIND_SERVICE] |
| 178 | +security_opt: [no-new-privileges:true] |
| 179 | +tmpfs: |
| 180 | + - /tmp:size=100M,mode=1777 |
| 181 | + - /var/tmp:size=10M,mode=1777 |
| 182 | +``` |
| 183 | +
|
| 184 | +## 🔍 **Troubleshooting Security Issues** |
| 185 | +
|
| 186 | +### **"groupadd: Permission denied" Error** |
| 187 | +**This error no longer occurs!** The container now detects read-only filesystems and avoids user creation attempts. |
| 188 | +
|
| 189 | +### **"cannot lock /etc/group" Error** |
| 190 | +**Fixed!** Container detects when `/etc/group` is not writable and uses alternative approaches. |
| 191 | + |
| 192 | +### **User Directive Not Working** |
| 193 | +Ensure data directory has correct ownership: |
| 194 | +```bash |
| 195 | +# Set ownership to match --user directive |
| 196 | +sudo chown -R 1000:1000 ./data |
| 197 | +docker run --user 1000:1000 subscription-tracker |
| 198 | +``` |
| 199 | + |
| 200 | +### **Database Permission Issues in Read-Only Mode** |
| 201 | +Ensure volume mount has correct ownership: |
| 202 | +```bash |
| 203 | +# Fix volume ownership before mounting |
| 204 | +sudo chown -R 1000:1000 ./data |
| 205 | +chmod 755 ./data |
| 206 | +``` |
| 207 | + |
| 208 | +## 📊 **Security Compliance Matrix** |
| 209 | + |
| 210 | +| Security Feature | Standard Mode | Read-Only Mode | User Directive | |
| 211 | +|------------------|---------------|----------------|----------------| |
| 212 | +| Read-Only Root FS | ⚠️ Optional | ✅ Required | ✅ Compatible | |
| 213 | +| No Privilege Escalation | ⚠️ Uses gosu | ✅ Native | ✅ Native | |
| 214 | +| User Creation | ✅ Dynamic | ❌ None | ❌ None | |
| 215 | +| PUID/GUID Support | ✅ Full | ⚠️ Via --user | ⚠️ Via --user | |
| 216 | +| Security Scanners | ⚠️ May flag | ✅ Clean | ✅ Clean | |
| 217 | +| Kubernetes Ready | ⚠️ Needs config | ✅ Ready | ✅ Ready | |
| 218 | +| Container Hardening | ⚠️ Manual | ✅ Built-in | ✅ Built-in | |
| 219 | + |
| 220 | +## 🎉 **Benefits of Enhanced Security** |
| 221 | + |
| 222 | +- **✅ Zero Security Violations** - No more permission denied errors |
| 223 | +- **✅ Scanner Compatibility** - Passes security scanning tools |
| 224 | +- **✅ Kubernetes Ready** - Works with security policies out of the box |
| 225 | +- **✅ Backward Compatible** - Existing setups continue to work |
| 226 | +- **✅ Future Proof** - Ready for evolving security requirements |
| 227 | +- **✅ Compliance Ready** - Meets enterprise security standards |
| 228 | + |
| 229 | +The container now supports **every** security scenario while maintaining full functionality! 🔒🚀 |
0 commit comments