-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2 from shikharish/backup
- Loading branch information
Showing
10 changed files
with
246 additions
and
24 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
.env | ||
.env | ||
.pgpass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
FROM postgres:latest | ||
FROM postgres:16 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
FROM postgres:16 | ||
|
||
RUN apt-get update && apt-get install -y curl python3 python3-pip gzip | ||
|
||
ENV TZ=Asia/Kolkata | ||
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone | ||
|
||
# install supercronic as cron replacement : https://github.com/aptible/supercronic?tab=readme-ov-file#why-supercronic | ||
ENV SUPERCRONIC_URL=https://github.com/aptible/supercronic/releases/download/v0.2.30/supercronic-linux-amd64 \ | ||
SUPERCRONIC=supercronic-linux-amd64 \ | ||
SUPERCRONIC_SHA1SUM=9f27ad28c5c57cd133325b2a66bba69ba2235799 | ||
|
||
RUN curl -fsSLO "$SUPERCRONIC_URL" \ | ||
&& echo "${SUPERCRONIC_SHA1SUM} ${SUPERCRONIC}" | sha1sum -c - \ | ||
&& chmod +x "$SUPERCRONIC" \ | ||
&& mv "$SUPERCRONIC" "/usr/local/bin/${SUPERCRONIC}" \ | ||
&& ln -s "/usr/local/bin/${SUPERCRONIC}" /usr/local/bin/supercronic | ||
|
||
WORKDIR /root | ||
|
||
ARG DBPASSFILE | ||
|
||
COPY ./ ./backup | ||
COPY ${DBPASSFILE} ./.pgpass | ||
|
||
RUN pip3 install -qr ./backup/requirements.txt --break-system-packages | ||
|
||
CMD ["supercronic", "/root/backup/crontab"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
#!/usr/bin/env python3 | ||
|
||
import dropbox | ||
import traceback | ||
import sys | ||
import os | ||
|
||
file_name = sys.argv[1] | ||
|
||
app_key = os.environ["DROPBOX_APP_KEY"] | ||
app_secret = os.environ["DROPBOX_APP_SECRET"] | ||
access_token = os.environ["DROPBOX_ACCESS_TOKEN"] | ||
refresh_token = os.environ["DROPBOX_REFRESH_TOKEN"] | ||
client = dropbox.Dropbox( | ||
app_key=app_key, | ||
app_secret=app_secret, | ||
oauth2_access_token=access_token, | ||
oauth2_refresh_token=refresh_token, | ||
) | ||
|
||
with open(file_name, "rb") as f: | ||
chunksize = 32 * 1024 * 1024 | ||
|
||
try: | ||
if os.path.getsize(file_name) < chunksize: | ||
result = client.files_upload(f.read(), "/" + file_name) | ||
print(result) | ||
|
||
else: | ||
next_chunk = f.read(chunksize) | ||
|
||
session = client.files_upload_session_start(next_chunk) | ||
uploaded = len(next_chunk) | ||
|
||
next_chunk = f.read(chunksize) | ||
cursor = dropbox.files.UploadSessionCursor(session.session_id, uploaded) | ||
|
||
print("Uploaded: ", float(uploaded) / (1024 * 1024), "MB") | ||
while next_chunk: | ||
client.files_upload_session_append_v2(next_chunk, cursor) | ||
uploaded += len(next_chunk) | ||
cursor = dropbox.files.UploadSessionCursor(session.session_id, uploaded) | ||
print("Uploaded: ", float(uploaded) / (1024 * 1024), "MB") | ||
|
||
next_chunk = f.read(chunksize) | ||
|
||
commit_info = dropbox.files.CommitInfo(path="/" + file_name) | ||
result = client.files_upload_session_finish(f.read(), cursor, commit_info) | ||
print(result) | ||
except Exception as e: | ||
sys.exit(traceback.format_exc()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
20 4 * * * /root/backup/run_backup.sh >> /var/log/backups.log 2>&1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
dropbox |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
#!/usr/bin/env python3 | ||
|
||
import dropbox | ||
import os | ||
import traceback | ||
import sys | ||
import datetime | ||
|
||
app_key = os.environ["DROPBOX_APP_KEY"] | ||
app_secret = os.environ["DROPBOX_APP_SECRET"] | ||
access_token = os.environ["DROPBOX_ACCESS_TOKEN"] | ||
refresh_token = os.environ["DROPBOX_REFRESH_TOKEN"] | ||
client = dropbox.Dropbox( | ||
app_key=app_key, | ||
app_secret=app_secret, | ||
oauth2_access_token=access_token, | ||
oauth2_refresh_token=refresh_token, | ||
) | ||
|
||
BACKUP_FOLDER_PATH = "" | ||
has_more_files = True | ||
cursor = None | ||
result = None | ||
files = [] | ||
now = datetime.datetime.now() | ||
counter = 0 | ||
|
||
try: | ||
print("Fetching files from Dropbox...") | ||
while has_more_files: | ||
if cursor is None: | ||
result = client.files_list_folder(BACKUP_FOLDER_PATH) | ||
else: | ||
result = client.files_list_folder_continue(cursor=cursor) | ||
cursor = result.cursor | ||
has_more_files = result.has_more | ||
files.extend(result.entries) | ||
|
||
for file in files: | ||
if file.name.find("dob_dump") == -1: | ||
files.remove(file) | ||
|
||
number_of_files = len(files) | ||
print(f"{number_of_files} backup files found.") | ||
|
||
print("Starting rotation") | ||
for file in files: | ||
file_timestamp = file.client_modified | ||
days_old = (now - file_timestamp).days | ||
if days_old > 30 and (number_of_files - counter) > 30: | ||
client.files_delete(file.path_display) | ||
counter += 1 | ||
|
||
print(f"{counter} backup file(s) successfully deleted.") | ||
except Exception as e: | ||
sys.exit(traceback.format_exc()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
#!/usr/bin/env bash | ||
|
||
echo -e "\n-- Database of Babel Backup and Rotation START --\n" | ||
|
||
timestamp=$(date +%Y_%m_%d_%H_%M_%S) | ||
backup_to_dropbox="python3 /root/backup/backup_to_dropbox.py" | ||
rotate_backup="python3 /root/backup/rotate_backups.py" | ||
backups_dir="/root/backup/backups" | ||
dump_file="dob_dump_$timestamp.sql" | ||
backup_file="$dump_file.gz" | ||
|
||
mkdir -p "${backups_dir}" | ||
cd "$backups_dir" | ||
|
||
if ! pg_dumpall -U $POSTGRES_USER --no-password >$dump_file; then | ||
echo "pgdump failure!" | ||
exit 1 | ||
fi | ||
|
||
gzip $dump_file | ||
|
||
# Dropbox backup rotation | ||
if ! $rotate_backup; then | ||
echo "failed to rotate backups!" | ||
# Notify Slack | ||
if [[ -n "$SLACK_INCIDENTS_WH_URL" ]]; then | ||
curl -s -H 'content-type: application/json' \ | ||
-d "{ \"text\": \"🔴DoB Dropbox backup rotation failure on ${timestamp}\" }" \ | ||
"$SLACK_INCIDENTS_WH_URL" | ||
fi | ||
exit 1 | ||
fi | ||
|
||
# Delete local backups older than one week | ||
for file in ./*.gz; do | ||
if [ $(($(date +%s) - $(date -r $file +%s))) -gt 604800 ]; then | ||
rm "$file" | ||
fi | ||
done | ||
|
||
# Backup to Dropbox | ||
if ! $backup_to_dropbox $backup_file; then | ||
echo "Dropbox backup failure!" | ||
# Notify Slack | ||
if [[ -n "$SLACK_INCIDENTS_WH_URL" ]]; then | ||
curl -s -H 'content-type: application/json' \ | ||
-d "{ \"text\": \"🔴DoB Dropbox backup failure\nCould not upload \`${backup_file}\`.\" }" \ | ||
"$SLACK_INCIDENTS_WH_URL" | ||
fi | ||
exit 1 | ||
fi | ||
|
||
echo -e "\n-- Database of Babel Backup and Rotation END --\n" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,26 +1,48 @@ | ||
services: | ||
database: | ||
image: metakgporg/dob | ||
container_name: dob | ||
build: . | ||
networks: | ||
metaploy-private-network: | ||
aliases: | ||
- postgres-of-babel | ||
environment: | ||
- POSTGRES_USER=${DATABASE_USERNAME} | ||
- POSTGRES_PASSWORD=${DATABASE_PASSWORD} | ||
- POSTGRES_DB=${DATABASE_NAME} | ||
- PGPORT=${DATABASE_PORT} | ||
- PGHOST=${DATABASE_HOST} | ||
volumes: | ||
- db-volume:/var/lib/postgresql/data | ||
restart: always | ||
database: | ||
image: metakgporg/dob | ||
container_name: dob | ||
build: . | ||
networks: | ||
metaploy-private-network: | ||
aliases: | ||
- postgres-of-babel | ||
environment: | ||
- POSTGRES_USER=${DATABASE_USERNAME} | ||
- POSTGRES_PASSWORD=${DATABASE_PASSWORD} | ||
- POSTGRES_DB=${DATABASE_NAME} | ||
- PGPORT=${DATABASE_PORT} | ||
- PGHOST=${DATABASE_HOST} | ||
volumes: | ||
- db-volume:/var/lib/postgresql/data | ||
restart: always | ||
|
||
backup: | ||
build: | ||
context: ./backup | ||
args: | ||
- DBPASSFILE=${DBPASSFILE} | ||
restart: always | ||
networks: | ||
metaploy-private-network: | ||
depends_on: | ||
- database | ||
environment: | ||
- PGHOST=database | ||
- POSTGRES_USER=${DATABASE_USERNAME} | ||
- PGPASSFILE=/root/.pgpass | ||
- DROPBOX_APP_KEY=${DROPBOX_APP_KEY} | ||
- DROPBOX_APP_SECRET=${DROPBOX_APP_SECRET} | ||
- DROPBOX_ACCESS_TOKEN=${DROPBOX_ACCESS_TOKEN} | ||
- DROPBOX_REFRESH_TOKEN=${DROPBOX_REFRESH_TOKEN} | ||
- SLACK_INCIDENTS_WH_URL=${SLACK_INCIDENTS_WH_URL} | ||
volumes: | ||
- db-volume:/var/lib/postgresql/data | ||
|
||
networks: | ||
metaploy-private-network: | ||
external: true | ||
name: metaploy-private-network | ||
metaploy-private-network: | ||
external: true | ||
name: metaployprivate- -network | ||
|
||
volumes: | ||
db-volume: | ||
db-volume: |