├── Dockerfile ├── README.md └── backup.sh /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:3.7 2 | RUN apk --update add postgresql-client python py-pip 3 | RUN rm -rf /var/cache/apk/* 4 | RUN pip install --upgrade awscli 5 | 6 | WORKDIR /src 7 | COPY backup.sh /src 8 | RUN chmod +x /src/backup.sh 9 | 10 | CMD /src/backup.sh -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # rds-s3-database-backup 2 | 3 | This script allows uploading gzipped rds postgres backups to amazon s3. 4 | Database credentials are retrieved from aws parameter store. 5 | 6 | 7 | ## environment variables 8 | 9 | `ENVIRONMENT` allows tagging different environments, we use `prod` and 10 | `dev` as possible values. 11 | 12 | `IDENTIFIER` is a database identifier, e.g. `db`. The identifier is 13 | used for querying configuration options and for naming the result in s3. 14 | 15 | `REGION` is the aws region to operate in. 16 | 17 | ## parameter store keys 18 | 19 | - `/$ENVIRONMENT/cron/backup/$IDENTIFIER/host`: database host name 20 | - `/$ENVIRONMENT/cron/backup/$IDENTIFIER/name`: database name 21 | - `/$ENVIRONMENT/cron/backup/$IDENTIFIER/user`: database user name 22 | - `/$ENVIRONMENT/cron/backup/$IDENTIFIER/password`: database password 23 | - `/$ENVIRONMENT/cron/backup/$IDENTIFIER/bucket`: target s3 bucket 24 | 25 | ## output 26 | 27 | After completion, the script creates a gzipped backup in the target s3 28 | bucket named `$IDENTIFIER-YYYY-MM-DD.sql.gz`. All backups are stored in 29 | `STANDARD_IA` storage class. 30 | -------------------------------------------------------------------------------- /backup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | 4 | ENVIRONMENT=${ENVIRONMENT:-dev} 5 | REGION=${AWS_REGION:-us-east-1} 6 | 7 | if [[ -z "${IDENTIFIER}" ]]; then 8 | echo "Missing environment variable IDENTIFIER" 9 | exit 1 10 | fi 11 | 12 | echo env: ${ENVIRONMENT} 13 | echo identifier: ${IDENTIFIER} 14 | 15 | DATABASE_HOST=${DATABASE_HOST:-`aws ssm get-parameter --region $REGION --name "/$ENVIRONMENT/cron/backup/$IDENTIFIER/host" --with-decrypt --query "Parameter.Value" --output text`} 16 | 17 | if [[ -z "${DATABASE_HOST}" ]]; then 18 | echo "Missing environment variable DATABASE_HOST" 19 | exit 1 20 | fi 21 | 22 | DATABASE_NAME=${DATABASE_NAME:-`aws ssm get-parameter --region $REGION --name "/$ENVIRONMENT/cron/backup/$IDENTIFIER/name" --with-decrypt --query "Parameter.Value" --output text`} 23 | 24 | if [[ -z "${DATABASE_NAME}" ]]; then 25 | echo "Missing environment variable DATABASE_NAME" 26 | exit 1 27 | fi 28 | 29 | DATABASE_USER=${DATABASE_USER:-`aws ssm get-parameter --region $REGION --name "/$ENVIRONMENT/cron/backup/$IDENTIFIER/user" --with-decrypt --query "Parameter.Value" --output text`} 30 | 31 | if [[ -z "${DATABASE_USER}" ]]; then 32 | echo "Missing environment variable DATABASE_USER" 33 | exit 1 34 | fi 35 | 36 | DATABASE_PASSWORD=${DATABASE_PASSWORD:-`aws ssm get-parameter --region $REGION --name "/$ENVIRONMENT/cron/backup/$IDENTIFIER/password" --with-decrypt --query "Parameter.Value" --output text`} 37 | 38 | if [[ -z "${DATABASE_PASSWORD}" ]]; then 39 | echo "Missing environment variable DATABASE_PASSWORD" 40 | exit 1 41 | fi 42 | 43 | S3_BUCKET=${S3_BUCKET:-`aws ssm get-parameter --region $REGION --name "/$ENVIRONMENT/cron/backup/$IDENTIFIER/bucket" --with-decrypt --query "Parameter.Value" --output text`} 44 | 45 | if [[ -z "${S3_BUCKET}" ]]; then 46 | echo "Missing environment variable S3_BUCKET" 47 | exit 1 48 | fi 49 | 50 | DATE=$(date -I) 51 | TARGET=s3://${S3_BUCKET}/${IDENTIFIER}-${DATE}.sql.gz 52 | 53 | echo Backing up ${DATABASE_HOST}/${DATABASE_NAME} to ${TARGET} 54 | 55 | export PGPASSWORD=${DATABASE_PASSWORD} 56 | pg_dump -Z 9 -v -h ${DATABASE_HOST} -U ${DATABASE_USER} -d ${DATABASE_NAME} | aws s3 cp --storage-class STANDARD_IA --sse aws:kms - ${TARGET} 57 | rc=$? 58 | export PGPASSWORD= 59 | 60 | if [[ $rc != 0 ]]; then exit $rc; fi 61 | 62 | echo Done --------------------------------------------------------------------------------