Skip to content

Commit f031336

Browse files
committed
feat: Support environment variables config. Add remote pruning.
1 parent 4cee065 commit f031336

File tree

5 files changed

+107
-69
lines changed

5 files changed

+107
-69
lines changed

.dockerignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
.DS_Store
2+
.env

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
.DS_Store
2+
.env

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM debian:sid-slim
1+
FROM debian:bookworm-slim
22

33
LABEL org.opencontainers.image.source = "https://github.com/dataforgoodfr/d4g-s3-backup"
44
LABEL org.opencontainers.image.authors = "Data For Good"

README.md

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,31 +19,30 @@ USAGE docker run -it --rm -v /var/data:/data -v /opt/backups:/backups ghcr.io/da
1919
[--service-name="service"] \
2020
[--retention-days=30] \
2121
[--bucket-region="fr-par"] \
22-
[--prom-metrics] \
2322
[--debug] \
2423
[--help]
2524
2625
Create backups for a specific dir easily and sync them to an s3 compatible bucket.
2726
This script also supports publishing prometheu-compatible metrics through the Textfile Collector.
2827
29-
Data from <data_dir> will be backed up to <backups-dir>/<service-name>/<service-name>-2023-12-20.tar.gz
28+
Data from <data_dir> will be backed up to <backups-dir>/<service-name>/<service-name>-2024-06-19.tar.gz
3029
Files will be keps around for <retention-days> days.
3130
Files will be synced to s3 under s3://<bucket-name>/<service-name> using supplied credentials and configuration.
3231
3332
Supported parameters :
3433
-h, --help : display this message
35-
--debug : Print configuration before running (Optional)
36-
--access-key : AWS access key (Required)
37-
--secret-key : AWS secret key (Required)
38-
--bucket-name : name of the bucket to sync backups to (Optional, Default backups)
39-
--data-dir : directory to backup (Optional, Default ./data)
40-
--service-name : name of the service to backup (Optional, Default service)
41-
--backups-dir : backups root directory where will be stored (Optional, Default /opt/backups/)
42-
--host-bucket : Bucket host base (Optional, Default ${BUCKET_NAME}s.s3.fr-par.scw.cloud)
43-
--host-base : S3 host base (Optional, Default %(bucket)s.s3.fr-par.scw.cloud)
44-
--bucket-region : S3 bucket region (Optional, Default fr-par)
45-
--retention-days : number of days to keep backups (Default 30)
46-
--prom-metrics : enable prometheus metrics (Default false)
34+
--debug : Print configuration before running (Optional, also set by environment variable DEBUG)
35+
--access-key : AWS access key (Required, also set by environment variable ACCESS_KEY)
36+
--secret-key : AWS secret key (Required, also set by environment variable SECRET_KEY)
37+
--bucket-name : name of the bucket to sync backups to (Optional, Default backups, also set by environment variable BUCKET_NAME)
38+
--data-dir : directory to backup (Optional, Default ./data, also set by environment variable DATA_DIR)
39+
--service-name : name of the service to backup (Optional, Default service, also set by environment variable SERVICE_NAME)
40+
--backups-dir : backups root directory where will be stored (Optional, Default /opt/backups/, also set by environment variable BACKUPS_DIR)
41+
--host-bucket : Bucket host base (Optional, Default ${BUCKET_NAME}s.s3.fr-par.scw.cloud, also set by environment variable HOST_BUCKET)
42+
--host-base : S3 host base (Optional, Default %(bucket)s.s3.fr-par.scw.cloud, also set by environment variable HOST_BASE)
43+
--bucket-region : S3 bucket region (Optional, Default fr-par, also set by environment variable BUCKET_REGION)
44+
--retention-days : number of days to keep backups (Default 30, also set by environment variable RETENTION_DAYS)
45+
--prune : prune backups older than retention-days on remote s3 bucket (Optional, Default false, also set by environment variable PRUNE)
4746
```
4847

4948
### Example

entrypoint.sh

Lines changed: 91 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -8,38 +8,37 @@ usage() {
88
USAGE docker run -it --rm -v /var/data:/data -v /opt/backups:/backups ghcr.io/dataforgoodfr/d4g-s3-backup \\
99
[--access-key="<access_key>"] \\
1010
[--secret-key="<secret_key>"] \\
11-
[--bucket-name="backups"] \\
12-
[--host-base="%(bucket)s.s3.fr-par.scw.cloud"] \\
13-
[--data-dir="/data"] \\
1411
[--backups-dir="/backups"] \\
15-
[--service-name="service"] \\
16-
[--retention-days=30] \\
12+
[--bucket-name="backups"] \\
1713
[--bucket-region="fr-par"] \\
14+
[--data-dir="/data"] \\
15+
[--host-base="%(bucket)s.s3.fr-par.scw.cloud"] \\
1816
[--prom-metrics] \\
17+
[--retention-days=30] \\
18+
[--service-name="service"] \\
1919
[--debug] \\
2020
[--help]
2121
2222
Create backups for a specific dir easily and sync them to an s3 compatible bucket.
23-
This script also supports publishing prometheu-compatible metrics through the Textfile Collector.
2423
2524
Data from <data_dir> will be backed up to <backups-dir>/<service-name>/<service-name>-$(date +%Y-%m-%d).tar.gz
2625
Files will be keps around for <retention-days> days.
2726
Files will be synced to s3 under s3://<bucket-name>/<service-name> using supplied credentials and configuration.
2827
2928
Supported parameters :
3029
-h, --help : display this message
31-
--debug : Print configuration before running (Optional)
32-
--access-key : AWS access key (Required)
33-
--secret-key : AWS secret key (Required)
34-
--bucket-name : name of the bucket to sync backups to (Optional, Default backups)
35-
--data-dir : directory to backup (Optional, Default ./data)
36-
--service-name : name of the service to backup (Optional, Default service)
37-
--backups-dir : backups root directory where will be stored (Optional, Default /opt/backups/)
38-
--host-bucket : Bucket host base (Optional, Default \${BUCKET_NAME}s.s3.fr-par.scw.cloud)
39-
--host-base : S3 host base (Optional, Default %(bucket)s.s3.fr-par.scw.cloud)
40-
--bucket-region : S3 bucket region (Optional, Default fr-par)
41-
--retention-days : number of days to keep backups (Default 30)
42-
--prom-metrics : enable prometheus metrics (Default false)
30+
--access-key : AWS-format access key (Required, also set by environment variable ACCESS_KEY)
31+
--secret-key : AWS-format secret key (Required, also set by environment variable SECRET_KEY)
32+
--backups-dir : backups root directory where will be stored (Optional, Default /opt/backups/, also set by environment variable BACKUPS_DIR)
33+
--bucket-name : name of the bucket to sync backups to (Optional, Default backups, also set by environment variable BUCKET_NAME)
34+
--bucket-region : S3 bucket region (Optional, Default fr-par, also set by environment variable BUCKET_REGION)
35+
--data-dir : directory to backup (Optional, Default ./data, also set by environment variable DATA_DIR)
36+
--host-base : S3 host base (Optional, Default %(bucket)s.s3.fr-par.scw.cloud, also set by environment variable HOST_BASE)
37+
--host-bucket : Bucket host base (Optional, Default \${BUCKET_NAME}s.s3.fr-par.scw.cloud, also set by environment variable HOST_BUCKET)
38+
--prom-metrics : enable prometheus metrics (Optional, Default false, also set by environment variable PROM_METRICS)
39+
--prune : prune backups older than retention-days on remote s3 bucket (Optional, Default false, also set by environment variable PRUNE)
40+
--retention-days : number of days to keep backups (Default 30, also set by environment variable RETENTION_DAYS)
41+
--service-name : name of the service to backup (Optional, Default service, also set by environment variable SERVICE_NAME)
4342
EOF
4443
exit 1
4544
}
@@ -52,7 +51,29 @@ cleanup() {
5251
if [ "$FAILURE" != 0 ]; then
5352
error "Backup for $SERVICE_NAME $(date +%Y-%m-%d) failed."
5453
fi
55-
exit 0
54+
}
55+
56+
setup_colors() {
57+
if [[ -t 2 ]] && [[ -z "${NO_COLOR-}" ]] && [[ "${TERM-}" != "dumb" ]]; then
58+
# shellcheck disable=SC2034
59+
NOCOLOR='\033[0m' RED='\033[0;31m' GREEN='\033[0;32m' ORANGE='\033[0;33m' BLUE='\033[0;34m' PURPLE='\033[0;35m' CYAN='\033[0;36m' YELLOW='\033[1;33m'
60+
else
61+
NOCOLOR='' RED='' GREEN='' ORANGE='' BLUE='' PURPLE='' CYAN='' YELLOW=''
62+
fi
63+
}
64+
65+
info() {
66+
echo -e "${GREEN}$*${NOCOLOR}"
67+
}
68+
69+
error() {
70+
echo -e "${RED}$*${NOCOLOR}"
71+
}
72+
73+
debug() {
74+
if [ "$DEBUG" != "false" ]; then
75+
echo -e "$1"
76+
fi
5677
}
5778

5879
function write_metrics() {
@@ -66,7 +87,7 @@ function write_metrics() {
6687
cat << EOF > "$TEXTFILE_COLLECTOR_DIR/${SERVICE_NAME}_backup.prom.$$"
6788
# HELP ${SERVICE_NAME}_backup_duration Duration of the planned ${SERVICE_NAME} backup
6889
# TYPE ${SERVICE_NAME}_backup_duration counter
69-
${SERVICE_NAME}_backup_duration $((END - START))
90+
${SERVICE_NAME}_backup_duration $((END START))
7091
# HELP ${SERVICE_NAME}_backup_failure Result of the planned ${SERVICE_NAME} backup
7192
# TYPE ${SERVICE_NAME}_backup_failure gauge
7293
${SERVICE_NAME}_backup_failure $FAILURE
@@ -81,27 +102,19 @@ EOF
81102
"$TEXTFILE_COLLECTOR_DIR/${SERVICE_NAME}_backup.prom"
82103
}
83104

84-
setup_colors() {
85-
if [[ -t 2 ]] && [[ -z "${NO_COLOR-}" ]] && [[ "${TERM-}" != "dumb" ]]; then
86-
# shellcheck disable=SC2034
87-
NOCOLOR='\033[0m' RED='\033[0;31m' GREEN='\033[0;32m' ORANGE='\033[0;33m' BLUE='\033[0;34m' PURPLE='\033[0;35m' CYAN='\033[0;36m' YELLOW='\033[1;33m'
88-
else
89-
NOCOLOR='' RED='' GREEN='' ORANGE='' BLUE='' PURPLE='' CYAN='' YELLOW=''
90-
fi
91-
}
92-
93-
info() {
94-
echo -e "${GREEN}$*${NOCOLOR}"
95-
}
96-
97-
error() {
98-
echo -e "${RED}$*${NOCOLOR}"
99-
}
100-
101-
debug() {
102-
if [ "$DEBUG" == 'true' ]; then
103-
echo -e "$1"
104-
fi
105+
function prune_s3_files () {
106+
debug "Pruning backups older than $RETENTION_DAYS in ${BUCKET_PATH}"
107+
/usr/bin/s3cmd --config=/.s3cfg ls "${BUCKET_PATH}" | while read FILE; do
108+
FILE_DATE=$(echo "$FILE" | awk '{print $1}')
109+
FILE_NAME=$(echo "$FILE" | awk '{print $4}')
110+
FILE_DATE=$(date -d "$FILE_DATE" +%s)
111+
RETENTION_DATE="$(date -d "-$RETENTION_DAYS days" +%s)"
112+
if [ "$FILE_DATE" -lt "$RETENTION_DATE" ]; then
113+
debug "Removing $FILE_NAME. Date: $FILE_DATE. Retention date: $RETENTION_DATE"
114+
/usr/bin/s3cmd --config=/.s3cfg del "$FILE_NAME"
115+
fi
116+
done
117+
debug "Bucket pruning complete."
105118
}
106119

107120
parse_params() {
@@ -115,18 +128,19 @@ parse_params() {
115128
START="$(date +%s)"
116129

117130
# Sane defaults
118-
DEBUG="false"
119-
DATA_DIR="/data"
120-
SERVICE_NAME="app"
121-
BACKUPS_DIR="/backups"
122-
BUCKET_NAME="backups"
123-
HOST_BASE="s3.fr-par.scw.cloud"
124-
HOST_BUCKET="%(bucket)s.s3.fr-par.scw.cloud"
125-
BUCKET_REGION="fr-par"
126-
RETENTION_DAYS="30"
127-
PROM_METRICS="false"
128-
ACCESS_KEY=""
129-
SECRET_KEY=""
131+
DEBUG="${DEBUG:-false}"
132+
DATA_DIR="${DATA_DIR:-/data}"
133+
SERVICE_NAME="${SERVICE_NAME:-app}"
134+
BACKUPS_DIR="${BACKUPS_DIR:-/backups}"
135+
BUCKET_NAME="${BUCKET_NAME:-backups}"
136+
HOST_BASE="${HOST_BASE:-s3.fr-par.scw.cloud}"
137+
HOST_BUCKET="${HOST_BUCKET:-%(bucket)s.s3.fr-par.scw.cloud}"
138+
BUCKET_REGION="${BUCKET_REGION:-fr-par}"
139+
RETENTION_DAYS="${RETENTION_DAYS:-30}"
140+
ACCESS_KEY="${ACCESS_KEY:-}"
141+
SECRET_KEY="${SECRET_KEY:-}"
142+
PROM_METRICS="${PROM_METRICS:-false}"
143+
PRUNE="${PRUNE:-false}"
130144

131145
while :; do
132146
case "${1-}" in
@@ -169,6 +183,9 @@ parse_params() {
169183
--prom-metrics*)
170184
PROM_METRICS="true"
171185
;;
186+
--prune*)
187+
PRUNE="true"
188+
;;
172189
-?*)
173190
echo "Unknown option: $1"
174191
usage
@@ -195,6 +212,21 @@ parse_params() {
195212
BACKUP_FILE="${BACKUP_DIR}${SERVICE_NAME}-$(date +%Y-%m-%d).tar.gz"
196213
BUCKET_PATH="s3://${BUCKET_NAME}/${SERVICE_NAME}/"
197214

215+
debug "Configuration"
216+
debug "ACCESS_KEY: $ACCESS_KEY"
217+
debug "SECRET_KEY: $SECRET_KEY"
218+
debug "BACKUPS_DIR: $BACKUPS_DIR"
219+
debug "BUCKET_NAME: $BUCKET_NAME"
220+
debug "BUCKET_REGION: $BUCKET_REGION"
221+
debug "DATA_DIR: $DATA_DIR"
222+
debug "DEBUG: $DEBUG"
223+
debug "HOST_BASE: $HOST_BASE"
224+
debug "HOST_BUCKET: $HOST_BUCKET"
225+
debug "PROM_METRICS: $PROM_METRICS"
226+
debug "PRUNE: $PRUNE"
227+
debug "RETENTION_DAYS: $RETENTION_DAYS"
228+
debug "SERVICE_NAME: $SERVICE_NAME"
229+
198230
return 0
199231
}
200232

@@ -223,14 +255,19 @@ debug "Creating backups directory : ${BACKUP_DIR}"
223255
mkdir -p "${BACKUP_DIR}"
224256

225257
# Cleanup backups that are older than RETENTION_DAYS days
226-
debug "Finding backups older than $RETENTION_DAYS in ${BACKUP_DIR}"
258+
debug "Removing local backups older than $RETENTION_DAYS in ${BACKUP_DIR}"
227259
find "${BACKUP_DIR}" -type f -name "${SERVICE_NAME}-*.tar.gz" -mtime +"$RETENTION_DAYS" -exec rm -f {} \;
228260

229261
debug "Compressing files to ${BACKUP_FILE}"
230262
tar -czf "${BACKUP_FILE}" ./
231263

232264
debug "Uploading ${BACKUP_DIR} to ${BUCKET_PATH}"
233265
/usr/bin/s3cmd --config=/.s3cfg sync "${BACKUP_DIR}" "${BUCKET_PATH}"
266+
267+
# Now pruning old backups
268+
if [ "$PRUNE" != "false" ]; then
269+
prune_s3_files
270+
fi
234271
FAILURE=0
235272

236273
info "Backup for $SERVICE_NAME $(date +%Y-%m-%d) completed successfully."

0 commit comments

Comments
 (0)