diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000..faaba34
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,21 @@
+# Source control
+.git
+.gitignore
+.github
+.github/**
+Dockerfile*
+resources/
+
+# Node dependencies
+node_modules/
+
+# Logs and temp files
+*.log
+tmp/
+
+# Local env settings
+.env
+
+# IDE/project files
+.vscode/
+.DS_Store
\ No newline at end of file
diff --git a/.gitattributes b/.gitattributes
index d50ee95..d666fad 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,2 +1,4 @@
public/api.html linguist-documentation
-public/openapi.json linguist-documentation
\ No newline at end of file
+public/openapi.json linguist-documentation
+resources/ export-ignore
+.github/ export-ignore
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 275f72f..4e07c80 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -22,6 +22,14 @@
- Updated `AdminModel` & `AdminController` to persist and validate new settings
- Enhanced `shareFolder()` view to pull from admin config and format the max‑upload‑size label
- Restored the MIT license copyright line that was inadvertently removed.
+- Move .htaccess to public folder this was mistake since API refactor.
+- gitattributes to ignore resources/ & .github/ on export
+- Hardened `Dockerfile` permissions: all code files owned by `root:www-data` (dirs `755`, files `644`), only `uploads/`, `users/` and `metadata/` are writable by `www-data` (`775`)
+- `.dockerignore` entry to exclude the `.github` directory from build context
+- `start.sh`:
+ - Creates and secures `metadata/log` for Apache logs
+ - Dynamically creates and sets permissions on `uploads`, `users`, and `metadata` directories at startup
+- Apache VirtualHost updated to redirect `ErrorLog` and `CustomLog` into `/var/www/metadata/log`
---
diff --git a/Dockerfile b/Dockerfile
index edfabef..35f79a8 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -6,12 +6,9 @@
FROM ubuntu:24.04 AS appsource
RUN apt-get update && \
apt-get install -y --no-install-recommends ca-certificates && \
- rm -rf /var/lib/apt/lists/*
+ rm -rf /var/lib/apt/lists/* # clean up apt cache
-# prepare the folder and remove Apache’s default index
RUN mkdir -p /var/www && rm -f /var/www/html/index.html
-
-# **Copy the FileRise source** (where your composer.json lives)
COPY . /var/www
#############################
@@ -19,76 +16,53 @@ COPY . /var/www
#############################
FROM composer:2 AS composer
WORKDIR /app
-
-# **Copy composer files from the source** and install
COPY --from=appsource /var/www/composer.json /var/www/composer.lock ./
-RUN composer install --no-dev --optimize-autoloader
+RUN composer install --no-dev --optimize-autoloader # production-ready autoloader
#############################
# Final Stage – runtime image
#############################
FROM ubuntu:24.04
-
LABEL by=error311
-# Set basic environment variables (these can be overridden via the Unraid template)
ENV DEBIAN_FRONTEND=noninteractive \
HOME=/root \
- LC_ALL=C.UTF-8 \
- LANG=en_US.UTF-8 \
- LANGUAGE=en_US.UTF-8 \
- TERM=xterm \
- UPLOAD_MAX_FILESIZE=5G \
- POST_MAX_SIZE=5G \
- TOTAL_UPLOAD_SIZE=5G \
+ LC_ALL=C.UTF-8 LANG=en_US.UTF-8 LANGUAGE=en_US.UTF-8 TERM=xterm \
+ UPLOAD_MAX_FILESIZE=5G POST_MAX_SIZE=5G TOTAL_UPLOAD_SIZE=5G \
PERSISTENT_TOKENS_KEY=default_please_change_this_key \
- PUID=99 \
- PGID=100
+ PUID=99 PGID=100
# Install Apache, PHP, and required extensions
RUN apt-get update && \
apt-get upgrade -y && \
apt-get install -y --no-install-recommends \
- apache2 \
- php \
- php-json \
- php-curl \
- php-zip \
- php-mbstring \
- php-gd \
- php-xml \
- ca-certificates \
- curl \
- git \
- openssl && \
- apt-get clean && \
- rm -rf /var/lib/apt/lists/*
+ apache2 php php-json php-curl php-zip php-mbstring php-gd php-xml \
+ ca-certificates curl git openssl && \
+ apt-get clean && rm -rf /var/lib/apt/lists/* # slim down image
-# Remap www-data to the PUID/PGID provided
+# Remap www-data to the PUID/PGID provided for safe bind mounts
RUN set -eux; \
- # only change the UID if it’s not already correct
- if [ "$(id -u www-data)" != "${PUID}" ]; then \
- usermod -u "${PUID}" www-data; \
- fi; \
- # attempt to change the GID, but ignore “already exists” errors
- if [ "$(id -g www-data)" != "${PGID}" ]; then \
- groupmod -g "${PGID}" www-data 2>/dev/null || true; \
- fi; \
- # finally set www-data’s primary group to PGID (will succeed if the group exists)
+ if [ "$(id -u www-data)" != "${PUID}" ]; then usermod -u "${PUID}" www-data; fi; \
+ if [ "$(id -g www-data)" != "${PGID}" ]; then groupmod -g "${PGID}" www-data 2>/dev/null || true; fi; \
usermod -g "${PGID}" www-data
-# Copy application tuning and code
+# Copy config, code, and vendor
COPY custom-php.ini /etc/php/8.3/apache2/conf.d/99-app-tuning.ini
COPY --from=appsource /var/www /var/www
-COPY --from=composer /app/vendor /var/www/vendor
+COPY --from=composer /app/vendor /var/www/vendor
-# Ensure the webroot is owned by the remapped www-data user
-RUN chown -R www-data:www-data /var/www && chmod -R 775 /var/www
+# Secure permissions: code read-only, only data dirs writable
+RUN chown -R root:www-data /var/www && \
+ find /var/www -type d -exec chmod 755 {} \; && \
+ find /var/www -type f -exec chmod 644 {} \; && \
+ mkdir -p /var/www/public/uploads /var/www/users /var/www/metadata && \
+ chown -R www-data:www-data /var/www/public/uploads /var/www/users /var/www/metadata && \
+ chmod -R 775 /var/www/public/uploads /var/www/users /var/www/metadata # writable upload areas
-# Create a symlink for uploads folder in public directory.
+# Preserve your uploads symlink
RUN cd /var/www/public && ln -s ../uploads uploads
-# Configure Apache
+# Apache site configuration
RUN cat <<'EOF' > /etc/apache2/sites-available/000-default.conf
ServerAdmin webmaster@localhost
@@ -96,17 +70,16 @@ RUN cat <<'EOF' > /etc/apache2/sites-available/000-default.conf
AllowOverride All
Require all granted
- DirectoryIndex index.php index.html
+ DirectoryIndex index.html
- ErrorLog /var/log/apache2/error.log
- CustomLog /var/log/apache2/access.log combined
+ ErrorLog /var/www/metadata/log/error.log
+ CustomLog /var/www/metadata/log/access.log combined
EOF
-# Enable the rewrite and headers modules
+# Enable required modules
RUN a2enmod rewrite headers
-# Expose ports and set up the startup script
EXPOSE 80 443
COPY start.sh /usr/local/bin/start.sh
RUN chmod +x /usr/local/bin/start.sh
diff --git a/.htaccess b/public/.htaccess
similarity index 100%
rename from .htaccess
rename to public/.htaccess
diff --git a/start.sh b/start.sh
index 12b6b51..b2fe67f 100644
--- a/start.sh
+++ b/start.sh
@@ -1,162 +1,108 @@
#!/bin/bash
-
+set -euo pipefail
echo "🚀 Running start.sh..."
-# Warn if default persistent tokens key is in use
-if [ "$PERSISTENT_TOKENS_KEY" = "default_please_change_this_key" ]; then
- echo "⚠️ WARNING: Using default persistent tokens key. Please override PERSISTENT_TOKENS_KEY for production."
+# 1) Token‐key warning
+if [ "${PERSISTENT_TOKENS_KEY}" = "default_please_change_this_key" ]; then
+ echo "⚠️ WARNING: Using default persistent tokens key—override for production."
fi
-# Update config.php based on environment variables
+# 2) Update config.php based on environment variables
CONFIG_FILE="/var/www/config/config.php"
-if [ -f "$CONFIG_FILE" ]; then
- echo "🔄 Updating config.php based on environment variables..."
- if [ -n "$TIMEZONE" ]; then
- echo " Setting TIMEZONE to $TIMEZONE"
- sed -i "s|define('TIMEZONE',[[:space:]]*'[^']*');|define('TIMEZONE', '$TIMEZONE');|" "$CONFIG_FILE"
- fi
- if [ -n "$DATE_TIME_FORMAT" ]; then
- echo "🔄 Setting DATE_TIME_FORMAT to $DATE_TIME_FORMAT"
- sed -i "s|define('DATE_TIME_FORMAT',[[:space:]]*'[^']*');|define('DATE_TIME_FORMAT', '$DATE_TIME_FORMAT');|" "$CONFIG_FILE"
- fi
- if [ -n "$TOTAL_UPLOAD_SIZE" ]; then
- echo "🔄 Setting TOTAL_UPLOAD_SIZE to $TOTAL_UPLOAD_SIZE"
- sed -i "s|define('TOTAL_UPLOAD_SIZE',[[:space:]]*'[^']*');|define('TOTAL_UPLOAD_SIZE', '$TOTAL_UPLOAD_SIZE');|" "$CONFIG_FILE"
- fi
- if [ -n "$SECURE" ]; then
- echo "🔄 Setting SECURE to $SECURE"
- sed -i "s|\$envSecure = getenv('SECURE');|\$envSecure = '$SECURE';|" "$CONFIG_FILE"
- fi
- if [ -n "$SHARE_URL" ]; then
- echo "🔄 Setting SHARE_URL to $SHARE_URL"
- sed -i "s|define('SHARE_URL',[[:space:]]*'[^']*');|define('SHARE_URL', '$SHARE_URL');|" "$CONFIG_FILE"
+if [ -f "${CONFIG_FILE}" ]; then
+ echo "🔄 Updating config.php from env vars..."
+ [ -n "${TIMEZONE:-}" ] && sed -i "s|define('TIMEZONE',[[:space:]]*'[^']*');|define('TIMEZONE', '${TIMEZONE}');|" "${CONFIG_FILE}"
+ [ -n "${DATE_TIME_FORMAT:-}" ] && sed -i "s|define('DATE_TIME_FORMAT',[[:space:]]*'[^']*');|define('DATE_TIME_FORMAT', '${DATE_TIME_FORMAT}');|" "${CONFIG_FILE}"
+ if [ -n "${TOTAL_UPLOAD_SIZE:-}" ]; then
+ sed -i "s|define('TOTAL_UPLOAD_SIZE',[[:space:]]*'[^']*');|define('TOTAL_UPLOAD_SIZE', '${TOTAL_UPLOAD_SIZE}');|" "${CONFIG_FILE}"
fi
+ [ -n "${SECURE:-}" ] && sed -i "s|\$envSecure = getenv('SECURE');|\$envSecure = '${SECURE}';|" "${CONFIG_FILE}"
+ [ -n "${SHARE_URL:-}" ] && sed -i "s|define('SHARE_URL',[[:space:]]*'[^']*');|define('SHARE_URL', '${SHARE_URL}');|" "${CONFIG_FILE}"
fi
-# Ensure the PHP configuration directory exists
+# 2.1) Prepare metadata/log for Apache logs
+mkdir -p /var/www/metadata/log
+chown www-data:www-data /var/www/metadata/log
+chmod 775 /var/www/metadata/log
+
+# 2.2) Prepare other dynamic dirs
+for d in uploads users metadata; do
+ tgt="/var/www/${d}"
+ mkdir -p "${tgt}"
+ chown www-data:www-data "${tgt}"
+ chmod 775 "${tgt}"
+done
+
+# 3) Ensure PHP config dir & set upload limits
mkdir -p /etc/php/8.3/apache2/conf.d
-
-# Update PHP upload limits at runtime if TOTAL_UPLOAD_SIZE is set.
-if [ -n "$TOTAL_UPLOAD_SIZE" ]; then
- echo "🔄 Updating PHP upload limits with TOTAL_UPLOAD_SIZE=$TOTAL_UPLOAD_SIZE"
- echo "upload_max_filesize = $TOTAL_UPLOAD_SIZE" > /etc/php/8.3/apache2/conf.d/99-custom.ini
- echo "post_max_size = $TOTAL_UPLOAD_SIZE" >> /etc/php/8.3/apache2/conf.d/99-custom.ini
+if [ -n "${TOTAL_UPLOAD_SIZE:-}" ]; then
+ echo "🔄 Setting PHP upload limits to ${TOTAL_UPLOAD_SIZE}"
+ cat > /etc/php/8.3/apache2/conf.d/99-custom.ini < /etc/apache2/conf-enabled/limit_request_body.conf
+ LIMIT_REQUEST_BODY=$(( num * factor ))
+ echo "🔄 Setting Apache LimitRequestBody to ${LIMIT_REQUEST_BODY} bytes"
+ cat > /etc/apache2/conf-enabled/limit_request_body.conf <
- LimitRequestBody $LIMIT_REQUEST_BODY
+ LimitRequestBody ${LIMIT_REQUEST_BODY}
EOF
fi
-# Set Apache Timeout (default is 300 seconds)
-echo "🔄 Setting Apache Timeout to 600 seconds"
-cat < /etc/apache2/conf-enabled/timeout.conf
+# 5) Configure Apache timeout (600s)
+cat > /etc/apache2/conf-enabled/timeout.conf <//" /etc/apache2/sites-available/000-default.conf
+# 6) Override ports if provided
+if [ -n "${HTTP_PORT:-}" ]; then
+ sed -i "s/^Listen 80$/Listen ${HTTP_PORT}/" /etc/apache2/ports.conf
+ sed -i "s///" /etc/apache2/sites-available/000-default.conf
+fi
+if [ -n "${HTTPS_PORT:-}" ]; then
+ sed -i "s/^Listen 443$/Listen ${HTTPS_PORT}/" /etc/apache2/ports.conf
fi
-if [ -n "$HTTPS_PORT" ]; then
- echo "🔄 Setting Apache HTTPS port to $HTTPS_PORT"
- sed -i "s/^Listen 443$/Listen $HTTPS_PORT/" /etc/apache2/ports.conf
-fi
-
-# Update Apache ServerName if environment variable is provided
-if [ -n "$SERVER_NAME" ]; then
- echo "🔄 Setting Apache ServerName to $SERVER_NAME"
- echo "ServerName $SERVER_NAME" >> /etc/apache2/apache2.conf
+# 7) Set ServerName
+if [ -n "${SERVER_NAME:-}" ]; then
+ echo "ServerName ${SERVER_NAME}" >> /etc/apache2/apache2.conf
else
- echo "🔄 Setting Apache ServerName to default: FileRise"
echo "ServerName FileRise" >> /etc/apache2/apache2.conf
fi
-echo "Final /etc/apache2/ports.conf content:"
-cat /etc/apache2/ports.conf
+# 8) Prepare dynamic data directories with least privilege
+for d in uploads users metadata; do
+ tgt="/var/www/${d}"
+ mkdir -p "${tgt}"
+ chown www-data:www-data "${tgt}"
+ chmod 775 "${tgt}"
+done
-echo "📁 Web app is served from /var/www/public."
-
-# Ensure the uploads folder exists in /var/www
-mkdir -p /var/www/uploads
-echo "🔑 Fixing permissions for /var/www/uploads..."
-chown -R ${PUID:-99}:${PGID:-100} /var/www/uploads
-chmod -R 775 /var/www/uploads
-
-# Ensure the users folder exists in /var/www
-mkdir -p /var/www/users
-echo "🔑 Fixing permissions for /var/www/users..."
-chown -R ${PUID:-99}:${PGID:-100} /var/www/users
-chmod -R 775 /var/www/users
-
-# Ensure the metadata folder exists in /var/www
-mkdir -p /var/www/metadata
-echo "🔑 Fixing permissions for /var/www/metadata..."
-chown -R ${PUID:-99}:${PGID:-100} /var/www/metadata
-chmod -R 775 /var/www/metadata
-
-# Create users.txt only if it doesn't already exist (preserving persistent data)
+# 9) Initialize persistent files if absent
if [ ! -f /var/www/users/users.txt ]; then
- echo "ℹ️ users.txt not found in persistent storage; creating new file..."
echo "" > /var/www/users/users.txt
- chown ${PUID:-99}:${PGID:-100} /var/www/users/users.txt
+ chown www-data:www-data /var/www/users/users.txt
chmod 664 /var/www/users/users.txt
-else
- echo "ℹ️ users.txt already exists; preserving persistent data."
fi
-# Create createdTags.json only if it doesn't already exist (preserving persistent data)
if [ ! -f /var/www/metadata/createdTags.json ]; then
- echo "ℹ️ createdTags.json not found in persistent storage; creating new file..."
echo "[]" > /var/www/metadata/createdTags.json
- chown ${PUID:-99}:${PGID:-100} /var/www/metadata/createdTags.json
+ chown www-data:www-data /var/www/metadata/createdTags.json
chmod 664 /var/www/metadata/createdTags.json
-else
- echo "ℹ️ createdTags.json already exists; preserving persistent data."
fi
-# Optionally, fix permissions for the rest of /var/www
-echo "🔑 Fixing permissions for /var/www..."
-find /var/www -type f -exec chmod 664 {} \;
-find /var/www -type d -exec chmod 775 {} \;
-chown -R ${PUID:-99}:${PGID:-100} /var/www
-
-echo "🔥 Final PHP configuration (99-custom.ini):"
-cat /etc/php/8.3/apache2/conf.d/99-custom.ini
-
-echo "🔥 Final Apache configuration (limit_request_body.conf):"
-cat /etc/apache2/conf-enabled/limit_request_body.conf
-
echo "🔥 Starting Apache..."
-exec apachectl -D FOREGROUND
+exec apachectl -D FOREGROUND
\ No newline at end of file