diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5803fce..40c3697 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -33,6 +33,8 @@ This refactor improves maintainability, testability, and documentation clarity a
- Expanded checkAuth.php Response now returns all three flags—folderOnly, readOnly, and disableUpload so client can handle every permission.
- In auth.js’s updateAuthenticatedUI(), write all three flags into localStorage whenever you land on the app (OIDC, basic or form). That guarantees consistent behavior across page loads.
- Made sure the OIDC handler reads the live config via AdminModel::getConfig() and pushes you through the TOTP flow if needed, then back to /index.html.
+- Dockerfile, custom-php.ini & start.sh moved into main repo for easier onboarding.
+- filerise-docker changed to dedicated CI/CD pipeline
---
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..eca82a5
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,98 @@
+# syntax=docker/dockerfile:1.4
+
+#############################
+# Source Stage – copy your FileRise app
+#############################
+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/*
+
+# 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
+
+#############################
+# Composer Stage – install PHP dependencies
+#############################
+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
+
+#############################
+# Final Stage – runtime image
+#############################
+FROM ubuntu:24.04
+
+LABEL by=error311
+
+# Set basic environment variables
+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 \
+ PERSISTENT_TOKENS_KEY=default_please_change_this_key
+
+ARG PUID=99
+ARG 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 \
+ ca-certificates curl git openssl && \
+ apt-get clean && \
+ rm -rf /var/lib/apt/lists/*
+
+# Fix www-data UID/GID
+RUN set -eux; \
+ if [ "$(id -u www-data)" != "${PUID}" ]; then usermod -u ${PUID} www-data || true; fi; \
+ if [ "$(id -g www-data)" != "${PGID}" ]; then groupmod -g ${PGID} www-data || true; fi; \
+ usermod -g ${PGID} www-data
+
+# Copy application code and vendor directory
+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
+
+# Fix ownership & permissions
+RUN chown -R www-data:www-data /var/www && chmod -R 775 /var/www
+
+# Create a symlink for uploads folder in public directory.
+RUN cd /var/www/public && ln -s ../uploads uploads
+
+# Configure Apache
+RUN cat <<'EOF' > /etc/apache2/sites-available/000-default.conf
+
+ ServerAdmin webmaster@localhost
+ DocumentRoot /var/www/public
+
+ AllowOverride All
+ Require all granted
+ DirectoryIndex index.php index.html
+
+ ErrorLog /var/log/apache2/error.log
+ CustomLog /var/log/apache2/access.log combined
+
+EOF
+
+# Enable the rewrite and headers modules
+RUN a2enmod rewrite headers
+
+# Expose ports and set up start script
+EXPOSE 80 443
+COPY start.sh /usr/local/bin/start.sh
+RUN chmod +x /usr/local/bin/start.sh
+
+CMD ["/usr/local/bin/start.sh"]
\ No newline at end of file
diff --git a/custom-php.ini b/custom-php.ini
new file mode 100644
index 0000000..6e1d2ae
--- /dev/null
+++ b/custom-php.ini
@@ -0,0 +1,52 @@
+; custom-php.ini
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; OPcache Settings
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+opcache.enable=1
+opcache.enable_cli=0
+; Allocate 128MB of memory for opcode caching
+opcache.memory_consumption=128
+; Increase the maximum number of accelerated files (adjust if you have a large codebase)
+opcache.max_accelerated_files=4000
+; Refresh file timestamp every 60 seconds to avoid too many disk reads
+opcache.revalidate_freq=60
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; Memory and Execution Time Limits
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; Increase memory limit to 512M for large file processing or image processing operations
+memory_limit=512M
+; Set execution time limits to accommodate long-running uploads/processes
+max_execution_time=300
+max_input_time=300
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; Realpath Cache Settings
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+realpath_cache_size=4096k
+realpath_cache_ttl=600
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; File Upload Settings
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; Allow a maximum of 20 files per request
+max_file_uploads=20
+; Ensure the temporary directory is set (should exist and be writable)
+upload_tmp_dir=/tmp
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; Session Configuration (if applicable)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+session.gc_maxlifetime=1440
+session.gc_probability=1
+session.gc_divisor=100
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; Error Handling / Logging
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; Do not display errors publicly in production
+display_errors=Off
+; Log errors to a dedicated file
+log_errors=On
+error_log=/var/log/php8.3-error.log
\ No newline at end of file
diff --git a/public/js/authModals.js b/public/js/authModals.js
index 4677f12..8e2b774 100644
--- a/public/js/authModals.js
+++ b/public/js/authModals.js
@@ -3,7 +3,7 @@ import { sendRequest } from './networkUtils.js';
import { t, applyTranslations, setLocale } from './i18n.js';
import { loadAdminConfigFunc } from './auth.js';
-const version = "v1.1.3";
+const version = "v1.2.0";
// Use t() for the admin panel title. (Make sure t("admin_panel") returns "Admin Panel" in English.)
const adminTitle = `${t("admin_panel")} ${version}`;
diff --git a/start.sh b/start.sh
new file mode 100644
index 0000000..61cf610
--- /dev/null
+++ b/start.sh
@@ -0,0 +1,162 @@
+#!/bin/bash
+
+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."
+fi
+
+# 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"
+ fi
+fi
+
+# Ensure the PHP configuration directory exists
+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
+fi
+
+# Update Apache LimitRequestBody based on TOTAL_UPLOAD_SIZE if set.
+if [ -n "$TOTAL_UPLOAD_SIZE" ]; then
+ size_str=$(echo "$TOTAL_UPLOAD_SIZE" | tr '[:upper:]' '[:lower:]')
+ factor=1
+ case "${size_str: -1}" in
+ g)
+ factor=$((1024*1024*1024))
+ size_num=${size_str%g}
+ ;;
+ m)
+ factor=$((1024*1024))
+ size_num=${size_str%m}
+ ;;
+ k)
+ factor=1024
+ size_num=${size_str%k}
+ ;;
+ *)
+ size_num=$size_str
+ ;;
+ esac
+ LIMIT_REQUEST_BODY=$((size_num * factor))
+ echo "🔄 Setting Apache LimitRequestBody to $LIMIT_REQUEST_BODY bytes (from TOTAL_UPLOAD_SIZE=$TOTAL_UPLOAD_SIZE)"
+ cat < /etc/apache2/conf-enabled/limit_request_body.conf
+
+ 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
+Timeout 600
+EOF
+
+echo "🔥 Final Apache Timeout configuration:"
+cat /etc/apache2/conf-enabled/timeout.conf
+
+# Update Apache ports if environment variables are provided
+if [ -n "$HTTP_PORT" ]; then
+ echo "🔄 Setting Apache HTTP port to $HTTP_PORT"
+ 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
+ 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
+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
+
+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)
+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
+ 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
+ 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 (90-custom.ini):"
+cat /etc/php/8.3/apache2/conf.d/90-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