Prevent Disk Space Woes with Automated Laravel Envoyer Release Cleanup
Laravel Envoyer is an incredibly powerful tool for zero-downtime deployments. However, if a deployment fails partway through, Envoyer can sometimes leave behind incomplete release directories. Over time, these orphaned directories, combined with the standard accumulation of old releases, can silently eat up disk space, potentially leading to your server running out of room and causing critical system failures.
We've experienced this headache ourselves and developed a robust solution: a pre-deployment hook that automatically cleans up old and orphaned releases, ensuring your server's disk space remains healthy.
The Problem: Accumulating Releases
Envoyer's deployment strategy involves creating new release directories and then symlinking the current
directory to the latest successful release. This is great for rollbacks, but it also means that every deployment, successful or not, can leave a new directory in your releases
folder. If deployments frequently fail or if you deploy very often, these directories can pile up, consuming valuable disk space.
The Solution: A Smart Cleanup Script
Our solution is a simple yet effective bash script that runs as a "Before Deploy" hook in Envoyer. This script intelligently identifies and removes old releases, while crucially protecting the most recent successful deployments and the currently active release.
Here's how it works:
- Identifies the Current Release: It first determines which release your
current
symlink points to, ensuring that your live application's files are never touched. - Keeps Recent Releases: It then identifies and preserves the four most recent release directories. This provides a safety net for quick rollbacks if needed.
- Deletes the Rest: Any other release directories (those older than the four most recent and not the current active one) are then safely removed.
- Force Mode for Automation: The script includes a "force" mode (
-f
) which bypasses the interactive confirmation, making it perfect for automated deployment environments like Envoyer.
Implementing the Cleanup Hook in Envoyer
To implement this solution, you'll add a "Before Deploy" hook in your Envoyer project settings. This ensures the cleanup runs before a new deployment starts, preventing further disk space consumption during a potentially failed deployment.
Here's the full script you'll use:
1cd /var/www/html/envoyer; # Adjust this path to your Envoyer project root 2 3cat > cleanup_releases.sh << 'EOF' 4#!/bin/bash 5 6# Envoyer Release Cleanup Script 7# Keeps the newest 4 releases + the currently active release 8# Usage: ./cleanup_releases.sh [--force|-f] 9 10# !!! IMPORTANT: Adjust these paths to match your Envoyer setup !!! 11RELEASES_DIR="/var/www/html/envoyer/releases" # Path to your 'releases' directory 12CURRENT_LINK="/var/www/html/envoyer/current" # Path to your 'current' symlink 13 14# Check for force flag 15FORCE_MODE=false 16if [[ "$1" == "--force" ]] || [[ "$1" == "-f" ]]; then 17 FORCE_MODE=true 18 echo "Running in force mode (no confirmation prompt)" 19fi 20 21# Check if directories exist 22if [ ! -d "$RELEASES_DIR" ]; then 23 echo "Error: Releases directory not found: $RELEASES_DIR" 24 exit 1 25fi 26 27if [ ! -L "$CURRENT_LINK" ]; then 28 echo "Error: Current symlink not found: $CURRENT_LINK" 29 exit 1 30fi 31 32# Get the currently active release (what current symlink points to) 33CURRENT_RELEASE=$(readlink "$CURRENT_LINK" | xargs basename) 34echo "Currently active release: $CURRENT_RELEASE" 35 36# Get all releases sorted by name (which corresponds to timestamps) 37cd "$RELEASES_DIR" 38RELEASES=($(ls -1 | grep -E '^[0-9]{14}$' | sort -r)) # Filters for timestamp-named directories 39 40echo "Found ${#RELEASES[@]} total releases" 41 42# Keep track of releases to preserve 43KEEP_RELEASES=() 44 45# Always keep the current release 46if [[ " ${RELEASES[@]} " =~ " ${CURRENT_RELEASE} " ]]; then 47 KEEP_RELEASES+=("$CURRENT_RELEASE") 48 echo "Preserving current release: $CURRENT_RELEASE" 49fi 50 51# Keep the newest 4 releases 52NEWEST_COUNT=0 53for release in "${RELEASES[@]}"; do 54 if [[ $NEWEST_COUNT -lt 4 ]]; then 55 # Only add if not already in the keep list 56 if [[ ! " ${KEEP_RELEASES[@]} " =~ " ${release} " ]]; then 57 KEEP_RELEASES+=("$release") 58 echo "Preserving newest release #$((NEWEST_COUNT + 1)): $release" 59 fi 60 NEWEST_COUNT=$((NEWEST_COUNT + 1)) 61 fi 62done 63 64echo "" 65echo "Releases to keep:" 66for keep in "${KEEP_RELEASES[@]}"; do 67 echo " - $keep" 68done 69 70echo "" 71echo "Releases to delete:" 72DELETE_COUNT=0 73for release in "${RELEASES[@]}"; do 74 if [[ ! " ${KEEP_RELEASES[@]} " =~ " ${release} " ]]; then 75 echo " - $release" 76 DELETE_COUNT=$((DELETE_COUNT + 1)) 77 fi 78done 79 80if [ $DELETE_COUNT -eq 0 ]; then 81 echo "No releases to delete." 82 exit 0 83fi 84 85# Ask for confirmation (unless in force mode) 86if [ "$FORCE_MODE" = false ]; then 87 echo "" 88 read -p "Delete $DELETE_COUNT release(s)? (y/N): " -n 1 -r 89 echo 90 if [[ ! $REPLY =~ ^[Yy]$ ]]; then 91 echo "Aborted." 92 exit 0 93 fi 94else 95 echo "" 96 echo "Force mode: Proceeding with deletion without confirmation..." 97fi 98 99# Delete the releases100echo "Deleting releases..."101for release in "${RELEASES[@]}"; do102 if [[ ! " ${KEEP_RELEASES[@]} " =~ " ${release} " ]]; then103 echo "Deleting: $release"104 rm -rf "$RELEASES_DIR/$release"105 fi106done107 108echo "Cleanup completed!"109echo "Kept ${#KEEP_RELEASES[@]} releases."110EOF111 112# Make it executable and run in force mode113chmod +x cleanup_releases.sh;114./cleanup_releases.sh -f;
Important Considerations:
- Adjust Paths: The script includes placeholders for
RELEASES_DIR
andCURRENT_LINK
. You must adjust these paths to match your specific Envoyer project setup on your server. Typically, these will be within your/home/envoyer/{project-name}/
directory. - Safety First: While this script is designed to be safe, it's always recommended to test it in a staging or development environment first before deploying it to production.
- Number of Releases: We chose to keep 4 recent releases. You can modify the
NEWEST_COUNT
variable in the script if you wish to retain more or fewer old releases.
Conclusion
By implementing this simple pre-deployment hook, you can proactively manage your server's disk space, prevent unexpected outages due to full disks, and ensure your Laravel Envoyer deployments run smoothly and efficiently. This small addition can save you from big headaches down the line.
We hope this helps someone else facing similar challenges!