|  | 
| 3 | 3 | [](https://travis-ci.org/jameshy/pgdump-aws-lambda) | 
| 4 | 4 | [](https://coveralls.io/github/jameshy/pgdump-aws-lambda?branch=master) | 
| 5 | 5 | 
 | 
| 6 |  | -# Overview | 
| 7 |  | - | 
| 8 | 6 | An AWS Lambda function that runs pg_dump and streams the output to s3. | 
| 9 | 7 | 
 | 
| 10 | 8 | It can be configured to run periodically using CloudWatch events. | 
| 11 | 9 | 
 | 
| 12 | 10 | ## Quick start | 
| 13 | 11 | 
 | 
| 14 | 12 | 1. Create an AWS lambda function: | 
| 15 |  | -    - Runtime: Node.js 6.10 | 
| 16 |  | -    - Code entry type: Upload a .ZIP file | 
| 17 |  | -    ([pgdump-aws-lambda.zip](https://github.com/jameshy/pgdump-aws-lambda/releases/download/v1.1.5/pgdump-aws-lambda.zip)) | 
| 18 |  | -    - Configuration -> Advanced Settings | 
| 19 |  | -        - Timeout = 5 minutes | 
| 20 |  | -        - Select a VPC and security group (must be suitable for connecting to the target database server) | 
| 21 |  | -2. Create a CloudWatch rule: | 
| 22 |  | -    - Event Source: Fixed rate of 1 hour | 
| 23 |  | -    - Targets: Lambda Function (the one created in step #1) | 
| 24 |  | -    - Configure input -> Constant (JSON text) and paste your config, e.g.: | 
|  | 13 | +    - Author from scratch | 
|  | 14 | +    - Runtime: Node.js 12.x | 
|  | 15 | +2. Configuration -> Function code: | 
|  | 16 | +    - Code Entry Type: Upload a .zip file | 
|  | 17 | +        - Upload ([pgdump-aws-lambda.zip](https://github.com/jameshy/pgdump-aws-lambda/releases/latest)) | 
|  | 18 | +    - Basic Settings -> Timeout: 15 minutes | 
|  | 19 | +    - Save | 
|  | 20 | +3. Configuration -> Execution role | 
|  | 21 | +    - Edit the role and attach the policy "AmazonS3FullAccess" | 
|  | 22 | +4. Test | 
|  | 23 | +    - Create new test event, e.g.: | 
| 25 | 24 |     ```json | 
| 26 | 25 |     { | 
| 27 |  | -        "PGDATABASE": "oxandcart", | 
| 28 |  | -        "PGUSER": "staging", | 
| 29 |  | -        "PGPASSWORD": "uBXKFecSKu7hyNu4", | 
| 30 |  | -        "PGHOST": "database.com", | 
| 31 |  | -        "S3_BUCKET" : "my-db-backups", | 
|  | 26 | +        "PGDATABASE": "dbname", | 
|  | 27 | +        "PGUSER": "postgres", | 
|  | 28 | +        "PGPASSWORD": "password", | 
|  | 29 | +        "PGHOST": "host", | 
|  | 30 | +        "S3_BUCKET" : "db-backups", | 
| 32 | 31 |         "ROOT": "hourly-backups" | 
| 33 | 32 |     } | 
| 34 | 33 |     ``` | 
|  | 34 | +    - *Test* and check the output | 
| 35 | 35 | 
 | 
| 36 |  | -Note: you can test the lambda function using the "Test" button and providing config like above. | 
|  | 36 | +5. Create a CloudWatch rule: | 
|  | 37 | +    - Event Source: Schedule -> Fixed rate of 1 hour | 
|  | 38 | +    - Targets: Lambda Function (the one created in step #1) | 
|  | 39 | +    - Configure input -> Constant (JSON text) and paste your config (as per step #3) | 
| 37 | 40 | 
 | 
| 38 |  | -**AWS lambda has a 5 minute maximum execution time for lambda functions, so your backup must take less time that that.** | 
| 39 | 41 | 
 | 
| 40 |  | -## File Naming | 
|  | 42 | +#### File Naming | 
| 41 | 43 | 
 | 
| 42 | 44 | This function will store your backup with the following s3 key: | 
| 43 | 45 | 
 | 
| 44 | 46 | s3://${S3_BUCKET}${ROOT}/YYYY-MM-DD/YYYY-MM-DD@HH-mm-ss.backup | 
| 45 | 47 | 
 | 
| 46 |  | -## PostgreSQL version compatibility | 
|  | 48 | +#### AWS Firewall | 
| 47 | 49 | 
 | 
| 48 |  | -This script uses the pg_dump utility from PostgreSQL 9.6.2. | 
|  | 50 | +- If you run the Lambda function outside a VPC, you must enable public access to your database instance, a non VPC Lambda function executes on the public internet. | 
|  | 51 | +- If you run the Lambda function inside a VPC (not tested), you must allow access from the Lambda Security Group to your database instance. Also you must add a NAT gateway to your VPC so the Lambda can connect to S3. | 
| 49 | 52 | 
 | 
| 50 |  | -It should be able to dump older versions of PostgreSQL. I will try to keep the included  binaries in sync with the latest from postgresql.org, but PR or message me if there is a newer PostgreSQL binary available. | 
|  | 53 | +#### Encryption | 
| 51 | 54 | 
 | 
| 52 |  | -## Encryption | 
|  | 55 | +You can add an encryption key to your event, e.g. | 
| 53 | 56 | 
 | 
| 54 |  | -You can pass the config option 'ENCRYPTION_PASSWORD' and the backup will be encrypted using aes-256-ctr algorithm. | 
| 55 |  | - | 
| 56 |  | -Example config: | 
| 57 | 57 | ```json | 
| 58 | 58 | { | 
| 59 | 59 |     "PGDATABASE": "dbname", | 
| 60 | 60 |     "PGUSER": "postgres", | 
| 61 | 61 |     "PGPASSWORD": "password", | 
| 62 |  | -    "PGHOST": "localhost", | 
| 63 |  | -    "S3_BUCKET" : "my-db-backups", | 
| 64 |  | -    "ENCRYPTION_PASSWORD": "my-secret-password" | 
|  | 62 | +    "PGHOST": "host", | 
|  | 63 | +    "S3_BUCKET" : "db-backups", | 
|  | 64 | +    "ROOT": "hourly-backups", | 
|  | 65 | +    "ENCRYPT_KEY": "c0d71d7ae094bdde1ef60db8503079ce615e71644133dc22e9686dc7216de8d0" | 
| 65 | 66 | } | 
| 66 | 67 | ``` | 
| 67 | 68 | 
 | 
| 68 |  | -To decrypt these dumps, use the command: | 
| 69 |  | -`openssl aes-256-ctr -d -in ./encrypted-db.backup  -nosalt -out unencrypted.backup` | 
|  | 69 | +The key should be exactly 64 hex characters (32 hex bytes). | 
|  | 70 | + | 
|  | 71 | +When this key is present the function will do streaming encryption directly from pg_dump -> S3. | 
|  | 72 | + | 
|  | 73 | +It uses the aes-256-cbc encryption algorithm with a random IV for each backup file. | 
|  | 74 | +The IV is stored alongside the backup in a separate file with the .iv extension. | 
|  | 75 | + | 
|  | 76 | +You can decrypt such a backup with the following bash command: | 
|  | 77 | + | 
|  | 78 | +```bash | 
|  | 79 | +openssl enc -aes-256-cbc -d \ | 
|  | 80 | +-in postgres-27-12-2019@13-19-13.backup \ | 
|  | 81 | +-out postgres-27-12-2019@13-19-13.unencrypted.backup \ | 
|  | 82 | +-K c0d71d7ae094bdde1ef60db8503079ce615e71644133dc22e9686dc7216de8d0 \ | 
|  | 83 | +-iv $(< postgres-27-12-2019@13-19-13.backup.iv) | 
|  | 84 | +``` | 
|  | 85 | + | 
|  | 86 | + | 
|  | 87 | +## Developer | 
| 70 | 88 | 
 | 
| 71 |  | -## Loading your own `pg_dump` binary | 
| 72 |  | -1. Spin up an Amazon AMI image on EC2 (since the lambda function will run | 
| 73 |  | -   on Amazon AMI image, based off of CentOS, using it would have the | 
| 74 |  | -best chance of being compatible) | 
| 75 |  | -2. Install PostgreSQL using yum.  You can install the latest version from the [official repository](https://yum.postgresql.org/repopackages.php#pg96). | 
| 76 |  | -3. Add a new directory for your pg_dump binaries: `mkdir bin/postgres-9.5.2` | 
|  | 89 | +#### Bundling a new `pg_dump` binary | 
|  | 90 | +1. Launch an EC2 instance with the Amazon Linux 2 AMI | 
|  | 91 | +2. Connect via SSH and (Install PostgreSQL using yum)[https://stackoverflow.com/questions/55798856/deploy-postgres11-to-elastic-beanstalk-requires-etc-redhat-release]. | 
|  | 92 | +3. Locally, create a new directory for your pg_dump binaries: `mkdir bin/postgres-11.6` | 
| 77 | 93 | 3. Copy the binaries | 
| 78 |  | - - `scp -i YOUR-ID.pem ec2-user@AWS_IP:/usr/bin/pg_dump ./bin/postgres-9.5.2/pg_dump` | 
| 79 |  | - - `scp -i YOUR-ID.pem ec2-user@AWS_UP:/usr/lib64/libpq.so.5.8 ./bin/postgres-9.5.2/libpq.so.5` | 
| 80 |  | -4. When calling the handler, pass the env variable PGDUMP_PATH=postgres-9.5.2 to use the binaries in the bin/postgres-9.5.2 directory. | 
|  | 94 | + - `scp -i <aws PEM> ec2-user@<EC2 Instance IP>:/usr/bin/pg_dump ./bin/postgres-11.6/pg_dump` | 
|  | 95 | + - `scp -i <aws PEM> ec2-user@<EC2 Instance IP>:/usr/lib64/{libcrypt.so.1,libnss3.so,libsmime3.so,libssl3.so,libsasl2.so.3,liblber-2.4.so.2,libldap_r-2.4.so.2} ./bin/postgres-11.6/` | 
|  | 96 | + - `scp -i <aws PEM> ec2-user@<EC2 Instance IP>:/usr/pgsql-11/lib/libpq.so.5 ./bin/postgres-11.6/libpq.so.5` | 
|  | 97 | +4. When calling the handler, pass the environment variable `PGDUMP_PATH=postgres-11.6` to use the binaries in the bin/postgres-11.6 directory. | 
|  | 98 | + | 
|  | 99 | +#### Creating a new function zip | 
| 81 | 100 | 
 | 
| 82 |  | -NOTE: `libpq.so.5.8` is found out by running `ll /usr/lib64/libpq.so.5` | 
| 83 |  | -and looking at where the symlink goes to. | 
|  | 101 | +`npm run deploy` | 
| 84 | 102 | 
 | 
| 85 |  | -## Contributing | 
|  | 103 | +#### Contributing | 
| 86 | 104 | 
 | 
| 87 | 105 | Please submit issues and PRs. | 
0 commit comments