docker: consolidate config & security improvements

This commit is contained in:
Ryan
2025-04-22 21:34:21 -04:00
committed by GitHub
parent 6ccfc88acb
commit 2792c05c1c
6 changed files with 126 additions and 176 deletions

21
.dockerignore Normal file
View File

@@ -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

4
.gitattributes vendored
View File

@@ -1,2 +1,4 @@
public/api.html linguist-documentation public/api.html linguist-documentation
public/openapi.json linguist-documentation public/openapi.json linguist-documentation
resources/ export-ignore
.github/ export-ignore

View File

@@ -22,6 +22,14 @@
- Updated `AdminModel` & `AdminController` to persist and validate new settings - Updated `AdminModel` & `AdminController` to persist and validate new settings
- Enhanced `shareFolder()` view to pull from admin config and format the maxuploadsize label - Enhanced `shareFolder()` view to pull from admin config and format the maxuploadsize label
- Restored the MIT license copyright line that was inadvertently removed. - 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`
--- ---

View File

@@ -6,12 +6,9 @@
FROM ubuntu:24.04 AS appsource FROM ubuntu:24.04 AS appsource
RUN apt-get update && \ RUN apt-get update && \
apt-get install -y --no-install-recommends ca-certificates && \ 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 Apaches default index
RUN mkdir -p /var/www && rm -f /var/www/html/index.html RUN mkdir -p /var/www && rm -f /var/www/html/index.html
# **Copy the FileRise source** (where your composer.json lives)
COPY . /var/www COPY . /var/www
############################# #############################
@@ -19,76 +16,53 @@ COPY . /var/www
############################# #############################
FROM composer:2 AS composer FROM composer:2 AS composer
WORKDIR /app WORKDIR /app
# **Copy composer files from the source** and install
COPY --from=appsource /var/www/composer.json /var/www/composer.lock ./ 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 # Final Stage runtime image
############################# #############################
FROM ubuntu:24.04 FROM ubuntu:24.04
LABEL by=error311 LABEL by=error311
# Set basic environment variables (these can be overridden via the Unraid template)
ENV DEBIAN_FRONTEND=noninteractive \ ENV DEBIAN_FRONTEND=noninteractive \
HOME=/root \ HOME=/root \
LC_ALL=C.UTF-8 \ LC_ALL=C.UTF-8 LANG=en_US.UTF-8 LANGUAGE=en_US.UTF-8 TERM=xterm \
LANG=en_US.UTF-8 \ UPLOAD_MAX_FILESIZE=5G POST_MAX_SIZE=5G TOTAL_UPLOAD_SIZE=5G \
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 \ PERSISTENT_TOKENS_KEY=default_please_change_this_key \
PUID=99 \ PUID=99 PGID=100
PGID=100
# Install Apache, PHP, and required extensions # Install Apache, PHP, and required extensions
RUN apt-get update && \ RUN apt-get update && \
apt-get upgrade -y && \ apt-get upgrade -y && \
apt-get install -y --no-install-recommends \ apt-get install -y --no-install-recommends \
apache2 \ apache2 php php-json php-curl php-zip php-mbstring php-gd php-xml \
php \ ca-certificates curl git openssl && \
php-json \ apt-get clean && rm -rf /var/lib/apt/lists/* # slim down image
php-curl \
php-zip \
php-mbstring \
php-gd \
php-xml \
ca-certificates \
curl \
git \
openssl && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
# Remap www-data to the PUID/PGID provided # Remap www-data to the PUID/PGID provided for safe bind mounts
RUN set -eux; \ RUN set -eux; \
# only change the UID if its not already correct if [ "$(id -u www-data)" != "${PUID}" ]; then usermod -u "${PUID}" www-data; fi; \
if [ "$(id -u www-data)" != "${PUID}" ]; then \ if [ "$(id -g www-data)" != "${PGID}" ]; then groupmod -g "${PGID}" www-data 2>/dev/null || true; fi; \
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-datas primary group to PGID (will succeed if the group exists)
usermod -g "${PGID}" www-data 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 custom-php.ini /etc/php/8.3/apache2/conf.d/99-app-tuning.ini
COPY --from=appsource /var/www /var/www 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 # Secure permissions: code read-only, only data dirs writable
RUN chown -R www-data:www-data /var/www && chmod -R 775 /var/www 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 RUN cd /var/www/public && ln -s ../uploads uploads
# Configure Apache # Apache site configuration
RUN cat <<'EOF' > /etc/apache2/sites-available/000-default.conf RUN cat <<'EOF' > /etc/apache2/sites-available/000-default.conf
<VirtualHost *:80> <VirtualHost *:80>
ServerAdmin webmaster@localhost ServerAdmin webmaster@localhost
@@ -96,17 +70,16 @@ RUN cat <<'EOF' > /etc/apache2/sites-available/000-default.conf
<Directory "/var/www/public"> <Directory "/var/www/public">
AllowOverride All AllowOverride All
Require all granted Require all granted
DirectoryIndex index.php index.html DirectoryIndex index.html
</Directory> </Directory>
ErrorLog /var/log/apache2/error.log ErrorLog /var/www/metadata/log/error.log
CustomLog /var/log/apache2/access.log combined CustomLog /var/www/metadata/log/access.log combined
</VirtualHost> </VirtualHost>
EOF EOF
# Enable the rewrite and headers modules # Enable required modules
RUN a2enmod rewrite headers RUN a2enmod rewrite headers
# Expose ports and set up the startup script
EXPOSE 80 443 EXPOSE 80 443
COPY start.sh /usr/local/bin/start.sh COPY start.sh /usr/local/bin/start.sh
RUN chmod +x /usr/local/bin/start.sh RUN chmod +x /usr/local/bin/start.sh

190
start.sh
View File

@@ -1,162 +1,108 @@
#!/bin/bash #!/bin/bash
set -euo pipefail
echo "🚀 Running start.sh..." echo "🚀 Running start.sh..."
# Warn if default persistent tokens key is in use # 1) Tokenkey warning
if [ "$PERSISTENT_TOKENS_KEY" = "default_please_change_this_key" ]; then if [ "${PERSISTENT_TOKENS_KEY}" = "default_please_change_this_key" ]; then
echo "⚠️ WARNING: Using default persistent tokens key. Please override PERSISTENT_TOKENS_KEY for production." echo "⚠️ WARNING: Using default persistent tokens key—override for production."
fi fi
# Update config.php based on environment variables # 2) Update config.php based on environment variables
CONFIG_FILE="/var/www/config/config.php" CONFIG_FILE="/var/www/config/config.php"
if [ -f "$CONFIG_FILE" ]; then if [ -f "${CONFIG_FILE}" ]; then
echo "🔄 Updating config.php based on environment variables..." echo "🔄 Updating config.php from env vars..."
if [ -n "$TIMEZONE" ]; then [ -n "${TIMEZONE:-}" ] && sed -i "s|define('TIMEZONE',[[:space:]]*'[^']*');|define('TIMEZONE', '${TIMEZONE}');|" "${CONFIG_FILE}"
echo " Setting TIMEZONE to $TIMEZONE" [ -n "${DATE_TIME_FORMAT:-}" ] && sed -i "s|define('DATE_TIME_FORMAT',[[:space:]]*'[^']*');|define('DATE_TIME_FORMAT', '${DATE_TIME_FORMAT}');|" "${CONFIG_FILE}"
sed -i "s|define('TIMEZONE',[[:space:]]*'[^']*');|define('TIMEZONE', '$TIMEZONE');|" "$CONFIG_FILE" if [ -n "${TOTAL_UPLOAD_SIZE:-}" ]; then
fi sed -i "s|define('TOTAL_UPLOAD_SIZE',[[:space:]]*'[^']*');|define('TOTAL_UPLOAD_SIZE', '${TOTAL_UPLOAD_SIZE}');|" "${CONFIG_FILE}"
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"
fi 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 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 mkdir -p /etc/php/8.3/apache2/conf.d
if [ -n "${TOTAL_UPLOAD_SIZE:-}" ]; then
# Update PHP upload limits at runtime if TOTAL_UPLOAD_SIZE is set. echo "🔄 Setting PHP upload limits to ${TOTAL_UPLOAD_SIZE}"
if [ -n "$TOTAL_UPLOAD_SIZE" ]; then cat > /etc/php/8.3/apache2/conf.d/99-custom.ini <<EOF
echo "🔄 Updating PHP upload limits with TOTAL_UPLOAD_SIZE=$TOTAL_UPLOAD_SIZE" upload_max_filesize = ${TOTAL_UPLOAD_SIZE}
echo "upload_max_filesize = $TOTAL_UPLOAD_SIZE" > /etc/php/8.3/apache2/conf.d/99-custom.ini post_max_size = ${TOTAL_UPLOAD_SIZE}
echo "post_max_size = $TOTAL_UPLOAD_SIZE" >> /etc/php/8.3/apache2/conf.d/99-custom.ini EOF
fi fi
# Update Apache LimitRequestBody based on TOTAL_UPLOAD_SIZE if set. # 4) Adjust Apache LimitRequestBody
if [ -n "$TOTAL_UPLOAD_SIZE" ]; then if [ -n "${TOTAL_UPLOAD_SIZE:-}" ]; then
size_str=$(echo "$TOTAL_UPLOAD_SIZE" | tr '[:upper:]' '[:lower:]') # convert to bytes
factor=1 size_str=$(echo "${TOTAL_UPLOAD_SIZE}" | tr '[:upper:]' '[:lower:]')
case "${size_str: -1}" in case "${size_str: -1}" in
g) g) factor=$((1024*1024*1024)); num=${size_str%g} ;;
factor=$((1024*1024*1024)) m) factor=$((1024*1024)); num=${size_str%m} ;;
size_num=${size_str%g} k) factor=1024; num=${size_str%k} ;;
;; *) factor=1; num=${size_str} ;;
m)
factor=$((1024*1024))
size_num=${size_str%m}
;;
k)
factor=1024
size_num=${size_str%k}
;;
*)
size_num=$size_str
;;
esac esac
LIMIT_REQUEST_BODY=$((size_num * factor)) LIMIT_REQUEST_BODY=$(( num * factor ))
echo "🔄 Setting Apache LimitRequestBody to $LIMIT_REQUEST_BODY bytes (from TOTAL_UPLOAD_SIZE=$TOTAL_UPLOAD_SIZE)" echo "🔄 Setting Apache LimitRequestBody to ${LIMIT_REQUEST_BODY} bytes"
cat <<EOF > /etc/apache2/conf-enabled/limit_request_body.conf cat > /etc/apache2/conf-enabled/limit_request_body.conf <<EOF
<Directory "/var/www/public"> <Directory "/var/www/public">
LimitRequestBody $LIMIT_REQUEST_BODY LimitRequestBody ${LIMIT_REQUEST_BODY}
</Directory> </Directory>
EOF EOF
fi fi
# Set Apache Timeout (default is 300 seconds) # 5) Configure Apache timeout (600s)
echo "🔄 Setting Apache Timeout to 600 seconds" cat > /etc/apache2/conf-enabled/timeout.conf <<EOF
cat <<EOF > /etc/apache2/conf-enabled/timeout.conf
Timeout 600 Timeout 600
EOF EOF
echo "🔥 Final Apache Timeout configuration:" # 6) Override ports if provided
cat /etc/apache2/conf-enabled/timeout.conf if [ -n "${HTTP_PORT:-}" ]; then
sed -i "s/^Listen 80$/Listen ${HTTP_PORT}/" /etc/apache2/ports.conf
# Update Apache ports if environment variables are provided sed -i "s/<VirtualHost \*:80>/<VirtualHost *:${HTTP_PORT}>/" /etc/apache2/sites-available/000-default.conf
if [ -n "$HTTP_PORT" ]; then fi
echo "🔄 Setting Apache HTTP port to $HTTP_PORT" if [ -n "${HTTPS_PORT:-}" ]; then
sed -i "s/^Listen 80$/Listen $HTTP_PORT/" /etc/apache2/ports.conf sed -i "s/^Listen 443$/Listen ${HTTPS_PORT}/" /etc/apache2/ports.conf
sed -i "s/<VirtualHost \*:80>/<VirtualHost *:$HTTP_PORT>/" /etc/apache2/sites-available/000-default.conf
fi fi
if [ -n "$HTTPS_PORT" ]; then # 7) Set ServerName
echo "🔄 Setting Apache HTTPS port to $HTTPS_PORT" if [ -n "${SERVER_NAME:-}" ]; then
sed -i "s/^Listen 443$/Listen $HTTPS_PORT/" /etc/apache2/ports.conf echo "ServerName ${SERVER_NAME}" >> /etc/apache2/apache2.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
else else
echo "🔄 Setting Apache ServerName to default: FileRise"
echo "ServerName FileRise" >> /etc/apache2/apache2.conf echo "ServerName FileRise" >> /etc/apache2/apache2.conf
fi fi
echo "Final /etc/apache2/ports.conf content:" # 8) Prepare dynamic data directories with least privilege
cat /etc/apache2/ports.conf 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." # 9) Initialize persistent files if absent
# 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)
if [ ! -f /var/www/users/users.txt ]; then 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 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 chmod 664 /var/www/users/users.txt
else
echo " users.txt already exists; preserving persistent data."
fi fi
# Create createdTags.json only if it doesn't already exist (preserving persistent data)
if [ ! -f /var/www/metadata/createdTags.json ]; then 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 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 chmod 664 /var/www/metadata/createdTags.json
else
echo " createdTags.json already exists; preserving persistent data."
fi 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..." echo "🔥 Starting Apache..."
exec apachectl -D FOREGROUND exec apachectl -D FOREGROUND