This commit is contained in:
@@ -78,6 +78,8 @@ EOF
|
|||||||
RUN rm -rf /tmp/*
|
RUN rm -rf /tmp/*
|
||||||
|
|
||||||
COPY samba.sh /usr/bin/
|
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
|
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 |
|
| `USERID` | UID for smbuser |
|
||||||
| `GROUPID` | GID for smb group |
|
| `GROUPID` | GID for smb group |
|
||||||
| `INCLUDE` | Path to additional config file |
|
| `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
|
## Examples
|
||||||
|
|
||||||
@@ -332,6 +335,61 @@ This enables:
|
|||||||
|
|
||||||
**Note**: Some older clients may not support these features. Only enable if all clients are compatible.
|
**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
|
## Feedback
|
||||||
|
|
||||||
If you have any problems or questions, please create an [issue on GitHub](https://github.com/upagge/samba/issues).
|
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"
|
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
|
### usage: Help
|
||||||
# Arguments:
|
# Arguments:
|
||||||
# none)
|
# none)
|
||||||
@@ -340,6 +387,13 @@ Options (fields in '[]' are optional, '<>' are required):
|
|||||||
-E Enable enhanced security (signing and encryption)
|
-E Enable enhanced security (signing and encryption)
|
||||||
Enables: server signing, client signing, SMB 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
|
The 'command' (if provided and valid) will be run instead of samba
|
||||||
" >&2
|
" >&2
|
||||||
exit $RC
|
exit $RC
|
||||||
@@ -395,6 +449,7 @@ done < <(env | awk '/^USER[0-9=_]/ {sub (/^[^=]*=/, "", $0); print}')
|
|||||||
[[ "${SECURE:-""}" ]] && secure
|
[[ "${SECURE:-""}" ]] && secure
|
||||||
[[ "${INCLUDE:-""}" ]] && include "$INCLUDE"
|
[[ "${INCLUDE:-""}" ]] && include "$INCLUDE"
|
||||||
[[ "${PERMISSIONS:-""}" ]] && perms &
|
[[ "${PERMISSIONS:-""}" ]] && perms &
|
||||||
|
[[ "${RECYCLE_AGE:-""}" ]] && setup_recycle_cron
|
||||||
|
|
||||||
if [[ $# -ge 1 ]]; then
|
if [[ $# -ge 1 ]]; then
|
||||||
# Validate command exists and is executable
|
# Validate command exists and is executable
|
||||||
|
|||||||
Reference in New Issue
Block a user