Skip to content
Closed

1 #23

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions deployment/caddy/Caddyfile
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,32 @@ beta.fromchat.ru {
}
}

git.fromchat.ru {
reverse_proxy 172.18.0.1:3000 host.docker.internal:3000 172.17.0.1:3000 {
lb_policy first
header_up X-Real-IP {remote_host}
}

# Security headers
header {
X-XSS-Protection "1; mode=block" # Prevent XSS attacks
X-Content-Type-Options "nosniff" # Prevent MIME type sniffing
X-Frame-Options "DENY" # Prevent clickjacking
Referrer-Policy "strict-origin-when-cross-origin"
Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
Permissions-Policy "geolocation=(), microphone=(), camera=()"
}

rate_limit {
zone global {
key {remote_ip}
window 1m
burst 20
events 500
}
}
}

api.getgadgets.toolbox-io.ru {
reverse_proxy 95.165.0.162:8400
}
Expand Down
82 changes: 78 additions & 4 deletions scripts/deploy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -407,15 +407,89 @@ if ! docker pussh --help > /dev/null 2>&1; then
echo " Install: npm run install:pussh"
fi

# Detect images
IMAGES=($(docker images --format "{{.Repository}}:{{.Tag}}" | grep "^${PROJECT_NAME}-" || true))
# Detect images based on docker-compose.yml (prefer explicit `image:` entries; fall back to built tags)
cd "$DEPLOYMENT_DIR"
COMPOSE_SERVICES=$(docker compose -f docker-compose.yml config --services 2>/dev/null || true)
IMAGES=()

for S in $COMPOSE_SERVICES; do
# Try to read explicit image: field from the compose config for this service
IMAGE_FROM_COMPOSE=$(docker compose -f docker-compose.yml config 2>/dev/null | \
grep -A5 "^[[:space:]]*${S}:" | \
grep -m1 "image:" || true)

IMAGE_FROM_COMPOSE=$(echo "$IMAGE_FROM_COMPOSE" | sed 's/.*image:[[:space:]]*//' | tr -d '"' | tr -d "'" | xargs || true)

if [ -n "$IMAGE_FROM_COMPOSE" ]; then
IMAGES+=("$IMAGE_FROM_COMPOSE")
else
# If service has a build section (we built it above), use the tag pattern used during build
TAG="${PROJECT_NAME}-${S}:latest"
# Only include the tag if the image exists locally (avoid pushing unrelated images)
if docker images --format "{{.Repository}}:{{.Tag}}" | grep -q "^${TAG}$"; then
IMAGES+=("$TAG")
fi
fi
done

# Deduplicate while preserving order
if [ ${#IMAGES[@]} -gt 0 ]; then
IMAGES=($(printf "%s\n" "${IMAGES[@]}" | awk '!seen[$0]++'))
fi

# Verify that all built images are among the detected images to be pushed.
# This prevents accidentally pushing unrelated images.
BUILT_COUNT=${#BUILT_IMAGES[@]}
MATCHING_BUILT=0
MISSING_FROM_DETECTED=()
for BI in "${BUILT_IMAGES[@]}"; do
found=false
for DI in "${IMAGES[@]}"; do
if [ "$BI" = "$DI" ]; then
found=true
break
fi
done
if [ "$found" = true ]; then
MATCHING_BUILT=$((MATCHING_BUILT + 1))
else
MISSING_FROM_DETECTED+=("$BI")
fi
done

# Also list detected images that weren't built locally (these are likely external images)
NOT_BUILT_DETECTED=()
for DI in "${IMAGES[@]}"; do
built=false
for BI in "${BUILT_IMAGES[@]}"; do
if [ "$DI" = "$BI" ]; then
built=true
break
fi
done
if [ "$built" = false ]; then
NOT_BUILT_DETECTED+=("$DI")
fi
done

if [ "$BUILT_COUNT" -ne "$MATCHING_BUILT" ]; then
error "Mismatch between built images (${BUILT_COUNT}) and detected built images (${MATCHING_BUILT})."
if [ ${#MISSING_FROM_DETECTED[@]} -gt 0 ]; then
echo " Built but not detected: ${MISSING_FROM_DETECTED[*]}"
fi
if [ ${#NOT_BUILT_DETECTED[@]} -gt 0 ]; then
echo " Detected but not built (external images): ${NOT_BUILT_DETECTED[*]}"
fi
echo "Aborting to avoid pushing incorrect images."
exit 1
fi

if [ ${#IMAGES[@]} -eq 0 ]; then
error "No ${PROJECT_NAME} images found"
error "No images found in docker-compose.yml or built locally for project ${PROJECT_NAME}"
fi

# Pre-pull unregistry image if needed
UNREGISTRY_IMAGE="ghcr.io/psviderski/unregistry:0.3.1"
UNREGISTRY_IMAGE="ghcr.io/psviderski/unregistry"
if ! ssh "$SERVER" "docker images --format '{{.Repository}}:{{.Tag}}' | grep -q '^${UNREGISTRY_IMAGE}$'" 2>/dev/null; then
substep "Pulling unregistry image (one-time setup)..."
ssh "$SERVER" "docker pull ${UNREGISTRY_IMAGE}" > /dev/null 2>&1 || true
Expand Down