From 6eb240fe2cdea25fc25b8aa9944f5c0f8eb3c72e Mon Sep 17 00:00:00 2001 From: Francis Li Date: Fri, 3 Jan 2025 16:22:10 -0800 Subject: [PATCH] [Closes #160] Update CloudFormation template to use LaunchTemplate (#161) * Update Dockerfile postgres install * Fix env vars, create config to support LaunchTemplate * Generate prisma client as part of build * Generate 32 byte session secret --- Dockerfile | 26 +++++++++++++++----------- deploy/aws/create | 2 +- deploy/aws/create.cfn.json | 5 +++++ server/example.env | 9 +++++---- server/lib/mailer.js | 5 ++++- server/package.json | 1 + server/plugins/auth.js | 2 +- 7 files changed, 32 insertions(+), 18 deletions(-) diff --git a/Dockerfile b/Dockerfile index cd423a2..6db591b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,11 +7,14 @@ ARG TARGETARCH ENV APP_HOME=/opt/node/app # Install postgres dependencies -RUN wget -q https://www.postgresql.org/media/keys/ACCC4CF8.asc -O - | apt-key add - && \ - echo "deb http://apt.postgresql.org/pub/repos/apt/ bookworm-pgdg main" >> /etc/apt/sources.list.d/pgdg.list && \ - apt-get update -y && \ - apt-get install -y postgresql-client-17 && \ - apt-get clean +RUN apt update -y && \ + apt install -y curl ca-certificates && \ + install -d /usr/share/postgresql-common/pgdg && \ + curl -o /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc --fail https://www.postgresql.org/media/keys/ACCC4CF8.asc && \ + sh -c 'echo "deb [signed-by=/usr/share/postgresql-common/pgdg/apt.postgresql.org.asc] https://apt.postgresql.org/pub/repos/apt bookworm-pgdg main" > /etc/apt/sources.list.d/pgdg.list' && \ + apt update -y && \ + apt install -y postgresql-client-17 && \ + apt clean # Install docker dependencies RUN install -m 0755 -d /etc/apt/keyrings && \ @@ -21,12 +24,12 @@ RUN install -m 0755 -d /etc/apt/keyrings && \ "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian \ $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \ tee /etc/apt/sources.list.d/docker.list > /dev/null && \ - apt-get update -y && \ - apt-get install -y docker-ce-cli docker-buildx-plugin && \ - apt-get clean + apt update -y && \ + apt install -y docker-ce-cli docker-buildx-plugin && \ + apt clean # Install AWS cli dependencies -RUN apt-get install -y jq less zip && \ +RUN apt install -y jq less zip && \ if [ "$TARGETARCH" = "amd64" ]; then \ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"; \ elif [ "$TARGETARCH" = "arm64" ]; then \ @@ -47,9 +50,10 @@ RUN mkdir -p $APP_HOME ADD . $APP_HOME WORKDIR $APP_HOME -# Install dependencies, build client app +# Install dependencies, build client app, generate server prisma client RUN npm install && \ - npm run build -w client + npm run build -w client && \ + npm run prisma:generate -w server # Set up default command to run Node on port 3000 EXPOSE 3000 diff --git a/deploy/aws/create b/deploy/aws/create index 9748548..e59f4ba 100755 --- a/deploy/aws/create +++ b/deploy/aws/create @@ -13,7 +13,7 @@ read -p "Dry run (staging SSL certs)? [y/n]: " DRY_RUN [[ $DRY_RUN = "n" ]] && LETSENCRYPT_OPTS="" || LETSENCRYPT_OPTS="--test-cert" DB_PASSWORD=`echo $RANDOM | md5sum | head -c 20` -SESSION_SECRET=`echo $RANDOM | md5sum | head -c 32` +SESSION_SECRET=`echo $RANDOM | md5sum | head -c 32``echo $RANDOM | md5sum | head -c 32` SOLUTION_STACK_NAME=`aws elasticbeanstalk list-available-solution-stacks --output text | grep -m 1 -oP "SOLUTIONSTACKS\t\K64bit Amazon Linux 2023 v4\.[^ ]+ running ECS"` diff --git a/deploy/aws/create.cfn.json b/deploy/aws/create.cfn.json index 4210771..8c4358b 100644 --- a/deploy/aws/create.cfn.json +++ b/deploy/aws/create.cfn.json @@ -496,6 +496,11 @@ "OptionName": "RootVolumeSize", "Value": 16 }, + { + "Namespace": "aws:autoscaling:launchconfiguration", + "OptionName": "RootVolumeType", + "Value": "gp3" + }, { "Namespace": "aws:autoscaling:launchconfiguration", "OptionName": "SecurityGroups", diff --git a/server/example.env b/server/example.env index a4d8f7d..9da3e43 100644 --- a/server/example.env +++ b/server/example.env @@ -2,18 +2,19 @@ AWS_CLOUDFRONT_DOMAIN= AWS_CLOUDFRONT_KEYPAIR_ID= AWS_CLOUDFRONT_PRIVATE_KEY= AWS_S3_ACCESS_KEY_ID= -AWS_S3_SECRET_ACCESS_KEY= AWS_S3_BUCKET= AWS_S3_ENDPOINT= AWS_S3_REGION= +AWS_S3_SECRET_ACCESS_KEY= AWS_S3_SIGNER_ENDPOINT= -AWS_SES_REGION= AWS_SES_ACCESS_KEY_ID= +AWS_SES_REGION= AWS_SES_SECRET_ACCESS_KEY= BASE_URL=http://localhost:5000 DATABASE_URL= -MAILER_FROM=no-reply@example.com -SESSION_SECRET_KEY=f0d10894891af0dd21871df84e613ba648c2a21995266fd5cb663bff7de9147c +SESSION_SECRET=f0d10894891af0dd21871df84e613ba648c2a21995266fd5cb663bff7de9147c +SMTP_ENABLED=true +SMTP_FROM_EMAIL_ADDRESS=no-reply@example.com SMTP_HOST= SMTP_PORT= SMTP_USER= diff --git a/server/lib/mailer.js b/server/lib/mailer.js index 6b3e5e6..ceb6501 100644 --- a/server/lib/mailer.js +++ b/server/lib/mailer.js @@ -44,7 +44,7 @@ const transport = nodemailer.createTransport(options); const mailer = new Email({ message: { - from: process.env.MAILER_FROM, + from: process.env.SMTP_FROM_EMAIL_ADDRESS, }, send: true, transport, @@ -57,6 +57,9 @@ const mailer = new Email({ }); async function send (options) { + if (process.env.SMTP_ENABLED !== 'true') { + return; + } options.locals ||= {}; options.locals._layout = { BASE_URL: process.env.BASE_URL, diff --git a/server/package.json b/server/package.json index d14c5e4..82b322f 100644 --- a/server/package.json +++ b/server/package.json @@ -10,6 +10,7 @@ "dev": "fastify start -w -l info -P app.js", "lint": "eslint --fix", "pretest": "eslint", + "prisma:generate": "prisma generate", "prisma:studio": "prisma studio", "start": "fastify start -l info app.js", "test": "node --test $(find test -name '*.test.js')" diff --git a/server/plugins/auth.js b/server/plugins/auth.js index eb13987..9804c27 100644 --- a/server/plugins/auth.js +++ b/server/plugins/auth.js @@ -6,7 +6,7 @@ import User from '#models/user.js'; export default fp(async function (fastify) { // set up secure encrypted cookie-based sessions await fastify.register(import('@fastify/secure-session'), { - key: Buffer.from(process.env.SESSION_SECRET_KEY, 'hex'), + key: Buffer.from(process.env.SESSION_SECRET, 'hex'), cookie: { path: '/', httpOnly: true,