Skip to content

Commit 85cbd99

Browse files
authored
release(v2.13.1): harden Docker startup perms + explicit inline MIME mapping (see #79)
1 parent 95f911b commit 85cbd99

5 files changed

Lines changed: 110 additions & 31 deletions

File tree

CHANGELOG.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,24 @@
11
# Changelog
22

3+
## Changes 1/2/2025 (v2.13.1)
4+
5+
`release(v2.13.1): harden Docker startup perms + explicit inline MIME mapping (see #79)`
6+
7+
**Fixes**
8+
9+
- Prevent Docker container startup from exiting when `chown/chmod` are unsupported (exFAT/NTFS/CIFS/NFS root_squash, non-root runs). Startup now logs warnings and continues.
10+
- Add non-fatal permission writeability hints for `/var/www/{uploads,users,metadata,sessions}` to help diagnose mount/UID issues.
11+
12+
**Improvements**
13+
14+
- Serve inline-safe images/audio/video with explicit MIME mapping to avoid `nosniff` + `application/octet-stream` preview issues (more reliable inline previews).
15+
16+
**Docs**
17+
18+
- Add AI disclosure section to README.
19+
20+
---
21+
322
## Changes 12/30/2025 (v2.13.0)
423

524
`release(v2.13.0): inline rename + video preview limits + folder tree perf (see #79)`

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,12 @@ If FileRise saves you time or becomes your daily driver, a ⭐ on GitHub or spon
339339

340340
---
341341

342+
## AI Disclosure
343+
344+
FileRise is my project. I use AI like a tool for some tasks (e.g., translations/snippets), but the architecture, core code, and ongoing maintenance are mine.
345+
346+
---
347+
342348
## License & third-party code
343349

344350
FileRise Core is released under the **MIT License** – see `LICENSE`.

scripts/manual-sync.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# === Update FileRise to v2.3.2 (safe rsync, no composer on demo) ===
33
set -Eeuo pipefail
44

5-
VER="v2.7.1"
5+
VER="v2.13.0"
66
ASSET="FileRise-${VER}.zip" # matches GitHub release asset name
77

88
WEBROOT="/var/www"

src/controllers/FileController.php

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1326,10 +1326,34 @@ public function downloadFile()
13261326
$ext = strtolower(pathinfo($realFilePath, PATHINFO_EXTENSION));
13271327
$isSvg = ($ext === 'svg' || $ext === 'svgz');
13281328

1329-
// Images we are OK to render inline
1330-
$inlineImageTypes = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'ico'];
1331-
$inlineVideoTypes = ['mp4', 'mkv', 'webm', 'mov', 'ogv'];
1332-
$inlineAudioTypes = ['mp3', 'wav', 'm4a', 'ogg', 'flac', 'aac', 'wma', 'opus'];
1329+
// Inline-safe types with explicit MIME mapping (avoid nosniff + octet-stream issues)
1330+
$inlineImageMime = [
1331+
'jpg' => 'image/jpeg',
1332+
'jpeg' => 'image/jpeg',
1333+
'png' => 'image/png',
1334+
'gif' => 'image/gif',
1335+
'bmp' => 'image/bmp',
1336+
'webp' => 'image/webp',
1337+
'ico' => 'image/x-icon',
1338+
];
1339+
$inlineVideoMime = [
1340+
'mp4' => 'video/mp4',
1341+
'm4v' => 'video/mp4',
1342+
'mkv' => 'video/x-matroska',
1343+
'webm' => 'video/webm',
1344+
'mov' => 'video/quicktime',
1345+
'ogv' => 'video/ogg',
1346+
];
1347+
$inlineAudioMime = [
1348+
'mp3' => 'audio/mpeg',
1349+
'wav' => 'audio/wav',
1350+
'm4a' => 'audio/mp4',
1351+
'ogg' => 'audio/ogg',
1352+
'flac' => 'audio/flac',
1353+
'aac' => 'audio/aac',
1354+
'wma' => 'audio/x-ms-wma',
1355+
'opus' => 'audio/opus',
1356+
];
13331357

13341358
// Default mime if not provided
13351359
if (empty($mimeType)) {
@@ -1344,17 +1368,15 @@ public function downloadFile()
13441368
} else {
13451369
$inline = false;
13461370
if ($inlineParam) {
1347-
$mimeLower = strtolower((string)$mimeType);
1348-
$isVideoMime = (strpos($mimeLower, 'video/') === 0);
1349-
$isAudioMime = (strpos($mimeLower, 'audio/') === 0) || ($mimeLower === 'application/ogg');
1350-
$isOctet = ($mimeLower === 'application/octet-stream');
1351-
1352-
if (in_array($ext, $inlineImageTypes, true)) {
1371+
if (isset($inlineImageMime[$ext])) {
13531372
$inline = true;
1354-
} elseif (in_array($ext, $inlineVideoTypes, true) && ($isVideoMime || $isOctet)) {
1373+
$mimeType = $inlineImageMime[$ext];
1374+
} elseif (isset($inlineVideoMime[$ext])) {
13551375
$inline = true;
1356-
} elseif (in_array($ext, $inlineAudioTypes, true) && ($isAudioMime || $isOctet)) {
1376+
$mimeType = $inlineVideoMime[$ext];
1377+
} elseif (isset($inlineAudioMime[$ext])) {
13571378
$inline = true;
1379+
$mimeType = $inlineAudioMime[$ext];
13581380
}
13591381
}
13601382
}

start.sh

Lines changed: 50 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,29 @@ set -euo pipefail
33
umask 002
44
echo "🚀 Running start.sh..."
55

6+
# ──────────────────────────────────────────────────────────────
7+
# Helpers: NEVER crash the container just because chown/chmod isn't supported
8+
# (exFAT/NTFS/CIFS/NFS root_squash, or running as non-root, etc.)
9+
IS_ROOT=false
10+
if [ "$(id -u)" -eq 0 ]; then IS_ROOT=true; fi
11+
12+
safe_chown() {
13+
if [ "${IS_ROOT}" = "true" ]; then
14+
chown "$@" 2>&1 || echo "[startup] chown failed (continuing): chown $*"
15+
fi
16+
}
17+
18+
safe_chmod() {
19+
if [ "${IS_ROOT}" = "true" ]; then
20+
chmod "$@" 2>&1 || echo "[startup] chmod failed (continuing): chmod $*"
21+
fi
22+
}
23+
24+
safe_truncate() {
25+
# Truncate/create a file without killing the container if the FS is read-only, etc.
26+
: > "$1" 2>&1 || echo "[startup] could not write: $1"
27+
}
28+
629
# ──────────────────────────────────────────────────────────────
730
# 0) If NOT root, we can't remap/chown. Log a hint and skip those parts.
831
# If root, remap www-data to PUID/PGID and (optionally) chown data dirs.
@@ -28,8 +51,8 @@ else
2851
# Optional: normalize ownership on data dirs (good for first run on existing shares)
2952
if [ "${CHOWN_ON_START:-true}" = "true" ]; then
3053
echo "[startup] Normalizing ownership on uploads/metadata..."
31-
chown -R www-data:www-data /var/www/metadata /var/www/uploads || echo "[startup] chown failed (continuing)"
32-
chmod -R u+rwX /var/www/metadata /var/www/uploads || echo "[startup] chmod failed (continuing)"
54+
safe_chown -R www-data:www-data /var/www/metadata /var/www/uploads
55+
safe_chmod -R u+rwX /var/www/metadata /var/www/uploads
3356
fi
3457
fi
3558

@@ -62,24 +85,33 @@ fi
6285

6386
# 2.1) Prepare metadata/log & sessions
6487
mkdir -p /var/www/metadata/log
65-
chown www-data:www-data /var/www/metadata/log
66-
chmod 775 /var/www/metadata/log
67-
: > /var/www/metadata/log/error.log
68-
: > /var/www/metadata/log/access.log
69-
chown www-data:www-data /var/www/metadata/log/*.log
88+
safe_chown www-data:www-data /var/www/metadata/log
89+
safe_chmod 775 /var/www/metadata/log
90+
safe_truncate /var/www/metadata/log/error.log
91+
safe_truncate /var/www/metadata/log/access.log
92+
safe_chown www-data:www-data /var/www/metadata/log/*.log
7093

7194
mkdir -p /var/www/sessions
72-
chown www-data:www-data /var/www/sessions
73-
chmod 700 /var/www/sessions
95+
safe_chown www-data:www-data /var/www/sessions
96+
safe_chmod 700 /var/www/sessions
7497

7598
# 2.2) Prepare dynamic dirs (uploads/users/metadata)
7699
for d in uploads users metadata; do
77100
tgt="/var/www/${d}"
78101
mkdir -p "${tgt}"
79-
chown www-data:www-data "${tgt}"
80-
chmod 775 "${tgt}"
102+
safe_chown www-data:www-data "${tgt}"
103+
safe_chmod 775 "${tgt}"
81104
done
82105

106+
# 2.3) Optional: log quick permission hints (non-fatal)
107+
if [ "$(id -u)" -eq 0 ]; then
108+
if command -v runuser >/dev/null 2>&1; then
109+
for p in /var/www/uploads /var/www/users /var/www/metadata /var/www/sessions; do
110+
runuser -u www-data -- test -w "$p" 2>/dev/null || echo "[startup] WARNING: www-data may not be able to write to $p"
111+
done
112+
fi
113+
fi
114+
83115
# 3) Ensure PHP conf dir & set upload limits
84116
mkdir -p /etc/php/8.3/apache2/conf.d
85117
if [ -n "${TOTAL_UPLOAD_SIZE:-}" ]; then
@@ -97,7 +129,7 @@ if [ "${CLAMAV_AUTO_UPDATE:-true}" = "true" ]; then
97129
echo "[startup] Updating ClamAV signatures via freshclam..."
98130
# Suppress noisy "NotifyClamd" warnings – we don't run clamd in this container.
99131
freshclam >/dev/null 2>&1 \
100-
|| echo "[startup] freshclam failed; continuing with existing signatures (if any)."
132+
|| echo "[startup] freshclam failed; continuing with existing signatures (if any)."
101133
else
102134
echo "[startup] Not running as root; skipping freshclam (requires root)."
103135
fi
@@ -151,20 +183,20 @@ fi
151183
# 8) Initialize persistent files if absent
152184
if [ ! -f /var/www/users/users.txt ]; then
153185
echo "" > /var/www/users/users.txt
154-
chown www-data:www-data /var/www/users/users.txt
155-
chmod 664 /var/www/users/users.txt
186+
safe_chown www-data:www-data /var/www/users/users.txt
187+
safe_chmod 664 /var/www/users/users.txt
156188
fi
157189

158190
if [ ! -f /var/www/metadata/createdTags.json ]; then
159191
echo "[]" > /var/www/metadata/createdTags.json
160-
chown www-data:www-data /var/www/metadata/createdTags.json
161-
chmod 664 /var/www/metadata/createdTags.json
192+
safe_chown www-data:www-data /var/www/metadata/createdTags.json
193+
safe_chmod 664 /var/www/metadata/createdTags.json
162194
fi
163195

164196
# 8.5) Harden scan script perms (only if root)
165197
if [ -f /var/www/scripts/scan_uploads.php ] && [ "$(id -u)" -eq 0 ]; then
166-
chown root:root /var/www/scripts/scan_uploads.php
167-
chmod 0644 /var/www/scripts/scan_uploads.php
198+
chown root:root /var/www/scripts/scan_uploads.php || true
199+
chmod 0644 /var/www/scripts/scan_uploads.php || true
168200
fi
169201

170202
# 9) One-shot scan when the container starts (opt-in via SCAN_ON_START)

0 commit comments

Comments
 (0)