This commit is contained in:
@@ -78,6 +78,8 @@ EOF
|
||||
RUN rm -rf /tmp/*
|
||||
|
||||
COPY samba.sh /usr/bin/
|
||||
COPY recycle-cleanup.sh /usr/local/bin/
|
||||
RUN chmod +x /usr/local/bin/recycle-cleanup.sh
|
||||
|
||||
EXPOSE 137/udp 138/udp 139 445
|
||||
|
||||
|
||||
58
README.md
58
README.md
@@ -141,6 +141,9 @@ docker run -it --rm upagge/samba -h
|
||||
| `USERID` | UID for smbuser |
|
||||
| `GROUPID` | GID for smb group |
|
||||
| `INCLUDE` | Path to additional config file |
|
||||
| `RECYCLE_AGE` | Auto-cleanup files older than N days from recycle bin |
|
||||
| `RECYCLE_CRON_HOUR` | Hour for cleanup job (0-23, default: 3) |
|
||||
| `RECYCLE_CRON_MINUTE` | Minute for cleanup job (0-59, default: 0) |
|
||||
|
||||
## Examples
|
||||
|
||||
@@ -332,6 +335,61 @@ This enables:
|
||||
|
||||
**Note**: Some older clients may not support these features. Only enable if all clients are compatible.
|
||||
|
||||
## Recycle Bin
|
||||
|
||||
By default, the image includes a recycle bin feature. When files are deleted, they are moved to a `.deleted` folder in each share instead of being permanently removed.
|
||||
|
||||
### Default Configuration
|
||||
|
||||
```ini
|
||||
vfs objects = catia recycle
|
||||
recycle:keeptree = yes # Preserve directory structure
|
||||
recycle:maxsize = 0 # No file size limit (0 = unlimited)
|
||||
recycle:repository = .deleted # Folder for deleted files
|
||||
recycle:versions = yes # Keep versions when deleting same filename
|
||||
```
|
||||
|
||||
### How It Works
|
||||
|
||||
1. When a file is deleted, it moves to `.deleted` in the share root
|
||||
2. Directory structure is preserved: `/share/docs/file.txt` → `/share/.deleted/docs/file.txt`
|
||||
3. Deleting a file with the same name creates versions: `file.txt`, `Copy #1 of file.txt`, etc.
|
||||
|
||||
### Automatic Cleanup
|
||||
|
||||
**Important**: Without cleanup, deleted files accumulate indefinitely and consume disk space.
|
||||
|
||||
Enable automatic cleanup with the `RECYCLE_AGE` environment variable:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
samba:
|
||||
image: upagge/samba
|
||||
environment:
|
||||
RECYCLE_AGE: "30" # Delete files older than 30 days
|
||||
RECYCLE_CRON_HOUR: "4" # Run at 4:00 AM (optional, default: 3)
|
||||
RECYCLE_CRON_MINUTE: "30" # Run at XX:30 (optional, default: 0)
|
||||
# ... other configuration
|
||||
```
|
||||
|
||||
The cleanup job:
|
||||
- Runs daily at the specified time (default: 3:00 AM)
|
||||
- Only activates if recycle bin is enabled (no `-r` flag)
|
||||
- Logs to `/var/log/recycle-cleanup.log`
|
||||
|
||||
### Disabling Recycle Bin
|
||||
|
||||
Use the `-r` flag or `RECYCLE=true` to disable the recycle bin entirely:
|
||||
|
||||
```bash
|
||||
docker run -d upagge/samba -r -p -s "share;/data"
|
||||
```
|
||||
|
||||
Recommended when:
|
||||
- Storing large media files (videos, music)
|
||||
- Limited disk space
|
||||
- Temporary or cache directories
|
||||
|
||||
## Feedback
|
||||
|
||||
If you have any problems or questions, please create an [issue on GitHub](https://github.com/upagge/samba/issues).
|
||||
|
||||
39
recycle-cleanup.sh
Normal file
39
recycle-cleanup.sh
Normal file
@@ -0,0 +1,39 @@
|
||||
#!/bin/sh
|
||||
#===============================================================================
|
||||
# FILE: recycle-cleanup.sh
|
||||
#
|
||||
# USAGE: ./recycle-cleanup.sh
|
||||
#
|
||||
# DESCRIPTION: Cleanup old files from Samba recycle bins
|
||||
#
|
||||
# OPTIONS: ---
|
||||
# NOTES: Runs via cron when RECYCLE_AGE is set
|
||||
# AUTHOR: Struchkov Mark (mark@struchkov.dev)
|
||||
# CREATED: 2025-01-08
|
||||
#===============================================================================
|
||||
|
||||
set -e
|
||||
|
||||
SMB_CONF="/etc/samba/smb.conf"
|
||||
DAYS="${RECYCLE_AGE:-30}"
|
||||
|
||||
# Get recycle repository name from config (default: .deleted)
|
||||
RECYCLE_DIR=$(awk -F' = ' '/recycle:repository/ {print $2}' "$SMB_CONF" | tr -d ' ')
|
||||
RECYCLE_DIR="${RECYCLE_DIR:-.deleted}"
|
||||
|
||||
# Get all share paths from smb.conf
|
||||
for share_path in $(awk -F' = ' '/^[[:space:]]*path = / {print $2}' "$SMB_CONF"); do
|
||||
recycle_path="$share_path/$RECYCLE_DIR"
|
||||
|
||||
if [ -d "$recycle_path" ]; then
|
||||
echo "$(date '+%Y-%m-%d %H:%M:%S') Cleaning $recycle_path (files older than $DAYS days)"
|
||||
|
||||
# Delete old files
|
||||
find "$recycle_path" -type f -mtime +"$DAYS" -delete 2>/dev/null || true
|
||||
|
||||
# Delete empty directories
|
||||
find "$recycle_path" -type d -empty -delete 2>/dev/null || true
|
||||
fi
|
||||
done
|
||||
|
||||
echo "$(date '+%Y-%m-%d %H:%M:%S') Recycle cleanup completed"
|
||||
55
samba.sh
55
samba.sh
@@ -287,6 +287,53 @@ secure() {
|
||||
smb encrypt = desired' "$SMB_CONF"
|
||||
}
|
||||
|
||||
### setup_recycle_cron: configure cron job for recycle bin cleanup
|
||||
# Arguments:
|
||||
# none)
|
||||
# Return: cron job configured if recycle is active
|
||||
setup_recycle_cron() {
|
||||
# Check if recycle bin is enabled (not disabled by -r flag)
|
||||
if ! grep -q 'vfs objects.*recycle' "$SMB_CONF"; then
|
||||
echo "INFO: Recycle bin is disabled, skipping cron setup" >&2
|
||||
return 0
|
||||
fi
|
||||
|
||||
local age="${RECYCLE_AGE}"
|
||||
local hour="${RECYCLE_CRON_HOUR:-3}"
|
||||
local minute="${RECYCLE_CRON_MINUTE:-0}"
|
||||
|
||||
# Validate RECYCLE_AGE is a positive integer
|
||||
if ! [[ "$age" =~ ^[0-9]+$ ]] || [ "$age" -lt 1 ]; then
|
||||
echo "ERROR: RECYCLE_AGE must be a positive integer (got: $age)" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Validate hour (0-23)
|
||||
if ! [[ "$hour" =~ ^[0-9]+$ ]] || [ "$hour" -lt 0 ] || [ "$hour" -gt 23 ]; then
|
||||
echo "ERROR: RECYCLE_CRON_HOUR must be 0-23 (got: $hour)" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Validate minute (0-59)
|
||||
if ! [[ "$minute" =~ ^[0-9]+$ ]] || [ "$minute" -lt 0 ] || [ "$minute" -gt 59 ]; then
|
||||
echo "ERROR: RECYCLE_CRON_MINUTE must be 0-59 (got: $minute)" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo "INFO: Setting up recycle cleanup cron (age: ${age} days, schedule: ${hour}:${minute})" >&2
|
||||
|
||||
# Create crontab with environment variable
|
||||
cat > /etc/crontabs/root <<EOF
|
||||
# Recycle bin cleanup - delete files older than ${age} days
|
||||
RECYCLE_AGE=${age}
|
||||
${minute} ${hour} * * * /usr/local/bin/recycle-cleanup.sh >> /var/log/recycle-cleanup.log 2>&1
|
||||
EOF
|
||||
|
||||
# Start crond in background
|
||||
crond -b -l 8
|
||||
echo "INFO: Crond started for recycle bin cleanup" >&2
|
||||
}
|
||||
|
||||
### usage: Help
|
||||
# Arguments:
|
||||
# none)
|
||||
@@ -340,6 +387,13 @@ Options (fields in '[]' are optional, '<>' are required):
|
||||
-E Enable enhanced security (signing and encryption)
|
||||
Enables: server signing, client signing, SMB encryption
|
||||
|
||||
Environment only options:
|
||||
RECYCLE_AGE=<days> Enable automatic recycle bin cleanup
|
||||
Files older than <days> will be deleted daily
|
||||
Requires recycle bin to be active (no -r flag)
|
||||
RECYCLE_CRON_HOUR=<0-23> Hour for cleanup job (default: 3)
|
||||
RECYCLE_CRON_MINUTE=<0-59> Minute for cleanup job (default: 0)
|
||||
|
||||
The 'command' (if provided and valid) will be run instead of samba
|
||||
" >&2
|
||||
exit $RC
|
||||
@@ -395,6 +449,7 @@ done < <(env | awk '/^USER[0-9=_]/ {sub (/^[^=]*=/, "", $0); print}')
|
||||
[[ "${SECURE:-""}" ]] && secure
|
||||
[[ "${INCLUDE:-""}" ]] && include "$INCLUDE"
|
||||
[[ "${PERMISSIONS:-""}" ]] && perms &
|
||||
[[ "${RECYCLE_AGE:-""}" ]] && setup_recycle_cron
|
||||
|
||||
if [[ $# -ge 1 ]]; then
|
||||
# Validate command exists and is executable
|
||||
|
||||
Reference in New Issue
Block a user