Compare commits

..

9 Commits

Author SHA1 Message Date
copilot-swe-agent[bot]
0fcbd33ee1 Add CLAMD_STARTUP_TIMEOUT to docker-compose.yml environment
Co-authored-by: DerLinkman <62480600+DerLinkman@users.noreply.github.com>
2025-12-11 13:19:07 +00:00
copilot-swe-agent[bot]
c8acacb5b1 Use wall clock time for accurate elapsed time reporting
Co-authored-by: DerLinkman <62480600+DerLinkman@users.noreply.github.com>
2025-12-11 12:44:20 +00:00
copilot-swe-agent[bot]
322841cbeb Use localhost for consistency and fix timing to report 0 seconds when ready immediately
Co-authored-by: DerLinkman <62480600+DerLinkman@users.noreply.github.com>
2025-12-11 12:43:03 +00:00
copilot-swe-agent[bot]
de3d617840 Fix timing accuracy and simplify final status reporting
Co-authored-by: DerLinkman <62480600+DerLinkman@users.noreply.github.com>
2025-12-11 12:41:19 +00:00
copilot-swe-agent[bot]
a98a5b298d Refactor clamd readiness check with helper function and improve timing logic
Co-authored-by: DerLinkman <62480600+DerLinkman@users.noreply.github.com>
2025-12-11 12:39:49 +00:00
copilot-swe-agent[bot]
4d55d037c0 Fix timing accuracy and improve status messaging in clamd startup
Co-authored-by: DerLinkman <62480600+DerLinkman@users.noreply.github.com>
2025-12-11 12:38:14 +00:00
copilot-swe-agent[bot]
bdc02ce882 Make clamd startup timeout configurable and add readiness check
Co-authored-by: DerLinkman <62480600+DerLinkman@users.noreply.github.com>
2025-12-11 12:36:52 +00:00
copilot-swe-agent[bot]
d73223cd93 Add 10-minute startup grace period for clamd to fix memory limiting issue
Co-authored-by: DerLinkman <62480600+DerLinkman@users.noreply.github.com>
2025-12-11 12:35:21 +00:00
copilot-swe-agent[bot]
376ba57f35 Initial plan 2025-12-11 12:32:29 +00:00
5 changed files with 48 additions and 66 deletions

View File

@@ -95,6 +95,51 @@ echo "$(clamd -V) is starting... please wait a moment."
nice -n10 clamd &
BACKGROUND_TASKS+=($!)
# Give clamd time to start up, especially with limited resources
# This grace period allows clamd to initialize fully before health checks begin
# Can be configured via CLAMD_STARTUP_TIMEOUT environment variable
STARTUP_GRACE_PERIOD=${CLAMD_STARTUP_TIMEOUT:-600} # Default: 10 minutes in seconds
echo "Waiting up to ${STARTUP_GRACE_PERIOD} seconds for clamd to start up..."
# Helper function to check if clamd is ready
clamd_is_ready() {
[ "$(echo "PING" | nc -w 1 localhost 3310 2>/dev/null)" = "PONG" ]
}
# Wait for clamd to be ready or until timeout
START_TIME=$(date +%s)
POLL_INTERVAL=10
CLAMD_READY=0
while true; do
CURRENT_TIME=$(date +%s)
ELAPSED=$((CURRENT_TIME - START_TIME))
# Check if clamd is responsive by attempting to connect on localhost
# clamd listens on 0.0.0.0:3310 (configured in Dockerfile)
if clamd_is_ready; then
echo "clamd is ready after ${ELAPSED} seconds"
CLAMD_READY=1
break
fi
# Check if we've exceeded the timeout
if [ ${ELAPSED} -ge ${STARTUP_GRACE_PERIOD} ]; then
break
fi
sleep ${POLL_INTERVAL}
done
# Report final status only if not already reported as ready
if [ ${CLAMD_READY} -eq 0 ]; then
if clamd_is_ready; then
echo "clamd is now ready (started during final check)"
else
echo "Warning: clamd did not respond to PING within ${STARTUP_GRACE_PERIOD} seconds - it may still be starting up"
fi
fi
while true; do
for bg_task in ${BACKGROUND_TASKS[*]}; do
if ! kill -0 ${bg_task} 1>&2; then

View File

@@ -814,32 +814,6 @@ function verify_hash($hash, $password) {
$hash = $components[4];
return hash_equals(hash_pbkdf2('sha1', $password, $salt, $rounds), $hash);
case "PBKDF2-SHA512":
// Handle FreeIPA-style hash: {PBKDF2-SHA512}10000$<base64_salt>$<base64_hash>
$components = explode('$', $hash);
if (count($components) !== 3) return false;
// 1st part: iteration count (integer)
$iterations = intval($components[0]);
if ($iterations <= 0) return false;
// 2nd part: salt (base64-encoded)
$salt = $components[1];
// 3rd part: hash (base64-encoded)
$stored_hash_b64 = $components[2];
// Decode salt and hash from base64
$salt_bin = base64_decode($salt, true);
$hash_bin = base64_decode($stored_hash_b64, true);
if ($salt_bin === false || $hash_bin === false) return false;
// Get length of hash in bytes
$hash_len = strlen($hash_bin);
if ($hash_len === 0) return false;
// Calculate PBKDF2-SHA512 hash for provided password
$test_hash = hash_pbkdf2('sha512', $password, $salt_bin, $iterations, $hash_len, true);
return hash_equals($hash_bin, $test_hash);
case "PLAIN-MD4":
return hash_equals(hash('md4', $password), $hash);

View File

@@ -144,7 +144,7 @@
<form action="/" method="post" id="logout"><input type="hidden" name="logout"></form>
{% if ui_texts.ui_announcement_text and ui_texts.ui_announcement_active and not is_root_uri and mailcow_cc_username %}
{% if ui_texts.ui_announcement_text and ui_texts.ui_announcement_active and not is_root_uri %}
<div class="container mt-4">
<div class="alert alert-{{ ui_texts.ui_announcement_type }}">{{ ui_texts.ui_announcement_text }}</div>
</div>

View File

@@ -75,6 +75,7 @@ services:
environment:
- TZ=${TZ}
- SKIP_CLAMD=${SKIP_CLAMD:-n}
- CLAMD_STARTUP_TIMEOUT=${CLAMD_STARTUP_TIMEOUT:-600}
volumes:
- ./data/conf/clamav/:/etc/clamav/:Z
- clamd-db-vol-1:/var/lib/clamav
@@ -321,7 +322,7 @@ services:
ofelia.job-exec.dovecot_clean_q_aged.command: "/bin/bash -c \"[[ $${MASTER} == y ]] && /usr/local/bin/gosu vmail /usr/local/bin/clean_q_aged.sh || exit 0\""
ofelia.job-exec.dovecot_maildir_gc.schedule: "0 */30 * * * *"
ofelia.job-exec.dovecot_maildir_gc.command: "/bin/bash -c \"source /source_env.sh ; /usr/local/bin/gosu vmail /usr/local/bin/maildir_gc.sh\""
ofelia.job-exec.dovecot_sarules.schedule: "@every 24h"
ofelia.job-exec.dovecot_sarules.schedule: "0 0 0 * * *"
ofelia.job-exec.dovecot_sarules.command: "/bin/bash -c \"/usr/local/bin/sa-rules.sh\""
ofelia.job-exec.dovecot_fts.schedule: "0 0 0 * * *"
ofelia.job-exec.dovecot_fts.command: "/bin/bash -c \"/usr/local/bin/gosu vmail /usr/local/bin/optimize-fts.sh\""

View File

@@ -91,44 +91,6 @@ if grep --help 2>&1 | head -n 1 | grep -q -i "busybox"; then
exit 1
fi
# Add image prefetch function
function prefetch_image() {
echo "Checking Docker image: ${DEBIAN_DOCKER_IMAGE}"
# Get local image digest if it exists
local local_digest=$(docker image inspect ${DEBIAN_DOCKER_IMAGE} --format='{{index .RepoDigests 0}}' 2>/dev/null | cut -d'@' -f2)
# Get remote image digest without pulling
local remote_digest=$(docker manifest inspect ${DEBIAN_DOCKER_IMAGE} 2>/dev/null | grep -oP '"digest":\s*"\K[^"]+' | head -1)
if [[ -z "${remote_digest}" ]]; then
echo "Warning: Unable to check remote image"
if [[ -n "${local_digest}" ]]; then
echo "Using cached version"
echo
return 0
else
echo "Error: Image ${DEBIAN_DOCKER_IMAGE} not found locally or remotely"
exit 1
fi
fi
if [[ "${local_digest}" != "${remote_digest}" ]]; then
echo "Image update available, pulling ${DEBIAN_DOCKER_IMAGE}"
if docker pull ${DEBIAN_DOCKER_IMAGE} 2>/dev/null; then
echo "Successfully pulled ${DEBIAN_DOCKER_IMAGE}"
else
echo "Error: Failed to pull ${DEBIAN_DOCKER_IMAGE}"
exit 1
fi
else
echo "Image is up to date (${remote_digest:0:12}...)"
fi
echo
}
# Prefetch the image early in the script
prefetch_image
function backup() {
DATE=$(date +"%Y-%m-%d-%H-%M-%S")