This content originally appeared on DEV Community and was authored by Edgaras
If you’re running a Laravel app and want an easy way to back it up to Azure Blob Storage without Docker images or third-party SaaS tools, here’s a self-contained Bash script that does exactly that.
It backs up:
- Your Laravel project files (with exclusions like
vendor/
andlogs
) - Your MySQL database (via
mysqldump
) - Packages everything into a
.tar.gz
- Uploads to Azure Blob Storage using
az CLI
- Cleans up local backups older than X days
Requirements
-
bash
,tar
,gzip
,find
-
mysqldump
(MySQL/MariaDB client) - Azure CLI
The Script
#!/usr/bin/env bash
set -Eeuo pipefail
# ---- Paths ----
LARAVEL_DIR="/path/to/laravel/project" # Path to your Laravel project root
BACKUP_DIR="/path/to/local/backup/directory" # Local backup directory
# ---- Azure Storage (account + key) ----
AZURE_STORAGE_ACCOUNT="<ACCOUNT_NAME>"
AZURE_STORAGE_KEY="<ACCOUNT-KEY>"
AZURE_CONTAINER="<CONTAINER-NAME>"
# ---- Retention (local only) ----
RETAIN_LOCAL_DAYS=7
# ---- Backup content exclusion ----
EXCLUDES=(
"vendor"
"node_modules"
"storage/framework/cache"
"storage/logs"
".git"
)
#############################################
timestamp_utc() { date -u +"%Y%m%dT%H%M%SZ"; }
require_cmd() {
command -v "$1" >/dev/null 2>&1 || { echo "ERROR: Missing required command: $1" >&2; exit 1; }
}
read_env_var() {
local key="$1"
local val=""
if [[ -f "$LARAVEL_DIR/.env" ]]; then
val="$(grep -E "^${key}=" "$LARAVEL_DIR/.env" 2>/dev/null | tail -n1 | sed -E "s/^${key}=(.*)$/\1/" | tr -d '\r' || true)"
fi
if [[ -n "$val" && "${val:0:1}" == '"' && "${val: -1}" == '"' ]]; then
val="${val:1:-1}"
elif [[ -n "$val" && "${val:0:1}" == "'" && "${val: -1}" == "'" ]]; then
val="${val:1:-1}"
fi
echo "$val"
}
dump_mysql() {
local db_host db_port db_name db_user db_pass db_socket dump_path
db_host="$(read_env_var "DB_HOST")"
db_port="$(read_env_var "DB_PORT")"
db_name="$(read_env_var "DB_DATABASE")"
db_user="$(read_env_var "DB_USERNAME")"
db_pass="$(read_env_var "DB_PASSWORD")"
db_socket="$(read_env_var "DB_SOCKET")"
dump_path="$1"
require_cmd mysqldump
db_host="${db_host:-127.0.0.1}"
db_port="${db_port:-3306}"
local args=( --user="$db_user" --single-transaction --quick --routines --events --triggers )
if [[ -n "$db_socket" ]]; then
args+=( --socket="$db_socket" )
else
args+=( --host="$db_host" --port="$db_port" )
fi
umask 077
MYSQL_PWD="$db_pass" mysqldump "${args[@]}" "$db_name" > "$dump_path"
}
make_archive() {
local src_dir="$1"
local db_sql="$2"
local out_tar_gz="$3"
local stage
stage="$(mktemp -d)"
trap 'rm -rf "$stage"' RETURN
mkdir -p "$stage/site" "$stage/db"
pushd "$src_dir" >/dev/null
local tar_excludes=()
for e in "${EXCLUDES[@]}"; do
tar_excludes+=( "--exclude=$e" )
done
tar -cf - "${tar_excludes[@]}" . | tar -C "$stage/site" -xf -
popd >/dev/null
cp "$db_sql" "$stage/db/database.sql"
tar -C "$stage" -czf "$out_tar_gz" site db
}
upload_with_azcli() {
local file="$1"
AZURE_STORAGE_ACCOUNT="$AZURE_STORAGE_ACCOUNT" AZURE_STORAGE_KEY="$AZURE_STORAGE_KEY" \
az storage blob upload \
--container-name "$AZURE_CONTAINER" \
--file "$file" \
--name "$(basename "$file")" \
--overwrite true >/dev/null
}
main() {
[[ -d "$LARAVEL_DIR" ]] || { echo "ERROR: LARAVEL_DIR not found: $LARAVEL_DIR" >&2; exit 1; }
mkdir -p "$BACKUP_DIR"
local ts app_name base_name db_dump archive
ts="$(timestamp_utc)"
app_name="$(basename "$LARAVEL_DIR")"
base_name="${app_name}-${ts}"
db_dump="${BACKUP_DIR}/${base_name}.sql"
archive="${BACKUP_DIR}/${base_name}.tar.gz"
echo "[1/4] Dumping MySQL → $db_dump"
dump_mysql "$db_dump"
echo "[2/4] Creating archive → $archive"
make_archive "$LARAVEL_DIR" "$db_dump" "$archive"
echo "[3/4] Uploading to Azure via az CLI"
upload_with_azcli "$archive"
echo "Upload complete: $(basename "$archive")"
echo "[4/4] Pruning local backups older than ${RETAIN_LOCAL_DAYS}d"
find "$BACKUP_DIR" -type f -name "${app_name}-*.tar.gz" -mtime +"$RETAIN_LOCAL_DAYS" -print -delete || true
find "$BACKUP_DIR" -type f -name "${app_name}-*.sql" -mtime +"$RETAIN_LOCAL_DAYS" -print -delete || true
echo "Done."
}
main "$@"
How It Works
-
Database Dump
- Reads
DB_HOST
,DB_DATABASE
,DB_USERNAME
,DB_PASSWORD
from.env
- Runs
mysqldump
- Reads
-
File Packaging
- Copies project files while excluding unnecessary directories
- Adds
database.sql
- Compresses into
tar.gz
-
Azure Upload
- Uses
az storage blob upload
withAZURE_STORAGE_ACCOUNT
+AZURE_STORAGE_KEY
- Uses
-
Retention Cleanup
- Deletes
.sql
and.tar.gz
files older thanRETAIN_LOCAL_DAYS
- Deletes
Usage
Save the script:
nano laravel-backup.sh
chmod +x laravel-backup.sh
Configure variables:
LARAVEL_DIR
BACKUP_DIR
AZURE_STORAGE_ACCOUNT
AZURE_STORAGE_KEY
AZURE_CONTAINER
Run manually:
./laravel-backup.sh
Or schedule with cron:
crontab -e
0 3 * * * /path/to/laravel-backup.sh >> /var/log/laravel-backup.log 2>&1
This content originally appeared on DEV Community and was authored by Edgaras

Edgaras | Sciencx (2025-08-25T22:13:48+00:00) Laravel Project Backup to Azure Blob with Bash Script. Retrieved from https://www.scien.cx/2025/08/25/laravel-project-backup-to-azure-blob-with-bash-script/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.