From 74d1a7b45187fa717459516538ef6c3a7e406f1e Mon Sep 17 00:00:00 2001 From: Matthew Hoover Date: Tue, 2 Apr 2024 22:27:16 -0400 Subject: [PATCH 1/4] Enabled Docker multiplatform build so image will work on Raspberry Pi --- .github/workflows/docker-publish.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index 4c083db..c69249a 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -27,9 +27,13 @@ jobs: with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + - name: Build and push uses: docker/build-push-action@v5 with: push: true + platforms: linux/amd64,linux/arm64 tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} From 80b98cde6311fbb6876dcbe5ca93e1b1b11a506a Mon Sep 17 00:00:00 2001 From: Matthew Hoover Date: Fri, 19 Apr 2024 14:41:08 -0400 Subject: [PATCH 2/4] Updated service env var handling to allow for pulling secrets from the filesystem --- api/src/env.ts | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/api/src/env.ts b/api/src/env.ts index d4be04a..2059b64 100644 --- a/api/src/env.ts +++ b/api/src/env.ts @@ -1,22 +1,27 @@ import process from "node:process"; +import fs from "node:fs"; class Env { public static string(variableName: string): string; public static string(variableName: string, defaultValue: string): string; - public static string(variableName: string, canBeUndefined: true): string | undefined; - public static string(variableName: string, arg2: string | boolean = false): string | undefined { - const val = process.env[variableName]; + public static string(variableName: string, arg2?: string): string | undefined { + let val = process.env[variableName]; + + // If no value is present for the env var, check if its saved as a file? + if (val == null) { + const filename = process.env[variableName + "#file"]; + if (filename && fs.existsSync(filename)) { + val = fs.readFileSync(filename, { encoding: "utf-8" }) + } + } + if (val != null) return val; if (typeof arg2 === "string") return arg2; - if (arg2) return undefined; throw new Error(`Missing environment variable '${variableName}'`); } public static number(variableName: string): number { - const val1 = process.env[variableName]; - if (!val1) { - throw new Error(`Missing environment variable '${variableName}'`); - } + const val1 = Env.string(variableName); const val2 = Number(val1); if (isNaN(val2)) { throw new Error(`Invalid environment variable '${variableName}=${val1}'`); @@ -29,7 +34,7 @@ export const env = { serverPort: Env.number("SERVER_PORT"), logging: { level: Env.string("LOGGING.LEVEL", "off"), - logfile: Env.string("LOGGING.LOGFILE", true), + logfile: Env.string("LOGGING.LOGFILE", "logfile.log"), }, database: Env.string("DATABASE", ".temp.sqlite"), google: { From 744e52141125e0427107983f9975f77c927dc132 Mon Sep 17 00:00:00 2001 From: Matthew Hoover Date: Fri, 15 Mar 2024 15:10:31 -0400 Subject: [PATCH 3/4] Added Docker Stack compose file --- Dockerfile | 34 +++++++++++++++++++++++++--------- access-controller.stack.yml | 26 ++++++++++++++++++++++++++ api/package.json | 3 +++ 3 files changed, 54 insertions(+), 9 deletions(-) create mode 100644 access-controller.stack.yml diff --git a/Dockerfile b/Dockerfile index abc369f..79ff6ff 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,19 +1,35 @@ -FROM node:18-alpine +FROM node:18-alpine as base LABEL org.opencontainers.image.source = "https://github.com/familab/accessController" + +FROM base as build_api +# Build API + RUN npm install --global pnpm -WORKDIR /home +WORKDIR /build +COPY package.json \ + tsconfig.json \ + pnpm-workspace.yaml \ + ./ -COPY tsconfig.json ./ +WORKDIR /build/api COPY api/package.json \ api/tsconfig.json \ api/tsconfig.build.json \ - api/ -COPY api/src api/src + ./ +COPY api/src src/ + +RUN pnpm install +RUN pnpm run build +RUN pnpm \ + --filter=@familab/access-controller.api \ + --prod \ + deploy deployment + + +FROM base -RUN cd api && \ - pnpm install && \ - pnpm run build +COPY --from=build_api /build/api/deployment ./ -ENTRYPOINT node ./api/build/server.js +ENTRYPOINT node ./build/server.js diff --git a/access-controller.stack.yml b/access-controller.stack.yml new file mode 100644 index 0000000..7f403f9 --- /dev/null +++ b/access-controller.stack.yml @@ -0,0 +1,26 @@ +# Docker Swarm Stack +version: "3.9" + +services: + auth_service: + image: ghcr.io/familab/accesscontroller:release-v4 + build: + context: ./ + ports: + - "8080:8080/tcp" + secrets: + - google_credentials_client_email + - google_credentials_private_key + environment: + SERVER_PORT: 8080 + LOGGING.LEVEL: info + GOOGLE.SPREADSHEET_ID: 1Mq3VC8-aO_3UA5PiUksvpzVHU1C49I5I1nvsnFs80Zo + GOOGLE.SPREADSHEET_RANGE: Sheet1 + GOOGLE.CREDENTIALS.CLIENT_EMAIL#file: /run/secrets/google_credentials_client_email + GOOGLE.CREDENTIALS.PRIVATE_KEY#file: /run/secrets/google_credentials_private_key + +secrets: + google_credentials_client_email: + external: true + google_credentials_private_key: + external: true diff --git a/api/package.json b/api/package.json index 30a3ee8..449cc6b 100644 --- a/api/package.json +++ b/api/package.json @@ -2,6 +2,9 @@ "name": "@familab/access-controller.api", "description": "Modern API Rewrite of Familab's access control system.", "type": "module", + "files": [ + "build" + ], "scripts": { "build": "tsc --project tsconfig.build.json", "lint": "eslint --ext .ts src", From 81cd54c5cb689e4c82599a532765c64b83c81a51 Mon Sep 17 00:00:00 2001 From: Matthew Hoover Date: Fri, 19 Apr 2024 14:43:46 -0400 Subject: [PATCH 4/4] Added deployment instructions --- README.md | 50 +++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 43 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 5276827..cafb4b7 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,3 @@ - - FamiLAB Access Controller ========================= @@ -28,6 +21,8 @@ See [nfc/README.md](./nfc/README.md) See [api/README.md](./api/README.md) +-------------------------------- + ## Development Setup 1. Install Node 18+ @@ -41,6 +36,47 @@ See [api/README.md](./api/README.md) ``` 4. Follow Development Setup instructions for the sub-project you wish to work on. +-------------------------------- + +## Deployment Process + +The Docker image is built via GitHub Actions whenever a new commit is merged into the `release/v4` branch. The image is +therefore tagged `ghcr.io/familab/accesscontroller:release-v4`. + +The server application is composed of multiple docker containers defined by the `./access-controller.stack.yml` Docker +Stack. To deploy this file to the server, you must have a Docker Context set up locally, and then update the Stack using +the stack file. + +### Setup Docker Context + +On your local machine, create a new [Docker Context](https://docs.docker.com/engine/context/working-with-contexts/) for +the access controller server. + +```bash +docker context create familab.accesscontroller --docker "host=ssh://familab@accesscontroller.familab.lan.local" +docker context use familab.accesscontroller +``` + +Once you run these commands all `docker *` commands you use will target the remote server. + +You can always switch back to targeting your local machine by running: + +```bash +docker context use default +``` + +### Update Stack + +Once you have a Docker Context set up for the remote server, run the following command to push the Stack. + +```bash +docker stack deploy -c "./access-controller.stack.yml" access-controller +``` + +Make sure to check the logs of the containers to ensure the deployment worked. + +-------------------------------- + ## Project Status Currently implementing Phase 0.