feat(docker): add encryption key generation for integration secrets (#1202)
* feat(docker): add encryption key generation for integration secrets * chore: address pull request feedback * fix: build failing * fix: docker build fails because of error when encryption key not defined
This commit is contained in:
@@ -46,6 +46,7 @@ COPY --from=builder /app/cli-out/full/ .
|
|||||||
# Copy static data as it is not part of the build
|
# Copy static data as it is not part of the build
|
||||||
COPY static-data ./static-data
|
COPY static-data ./static-data
|
||||||
ARG SKIP_ENV_VALIDATION='true'
|
ARG SKIP_ENV_VALIDATION='true'
|
||||||
|
ARG CI='true'
|
||||||
ARG DISABLE_REDIS_LOGS='true'
|
ARG DISABLE_REDIS_LOGS='true'
|
||||||
RUN corepack enable pnpm && pnpm build
|
RUN corepack enable pnpm && pnpm build
|
||||||
|
|
||||||
@@ -58,6 +59,8 @@ RUN mkdir /appdata
|
|||||||
RUN mkdir /appdata/db
|
RUN mkdir /appdata/db
|
||||||
RUN mkdir /appdata/redis
|
RUN mkdir /appdata/redis
|
||||||
VOLUME /appdata
|
VOLUME /appdata
|
||||||
|
RUN mkdir /secrets
|
||||||
|
VOLUME /secrets
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -71,6 +74,7 @@ RUN chmod +x /usr/bin/homarr
|
|||||||
|
|
||||||
# Don't run production as root
|
# Don't run production as root
|
||||||
RUN chown -R nextjs:nodejs /appdata
|
RUN chown -R nextjs:nodejs /appdata
|
||||||
|
RUN chown -R nextjs:nodejs /secrets
|
||||||
RUN mkdir -p /var/cache/nginx && chown -R nextjs:nodejs /var/cache/nginx && \
|
RUN mkdir -p /var/cache/nginx && chown -R nextjs:nodejs /var/cache/nginx && \
|
||||||
mkdir -p /var/log/nginx && chown -R nextjs:nodejs /var/log/nginx && \
|
mkdir -p /var/log/nginx && chown -R nextjs:nodejs /var/log/nginx && \
|
||||||
mkdir -p /var/lib/nginx && chown -R nextjs:nodejs /var/lib/nginx && \
|
mkdir -p /var/lib/nginx && chown -R nextjs:nodejs /var/lib/nginx && \
|
||||||
@@ -93,6 +97,7 @@ COPY --from=installer --chown=nextjs:nodejs /app/apps/nextjs/.next/standalone ./
|
|||||||
COPY --from=installer --chown=nextjs:nodejs /app/apps/nextjs/.next/static ./apps/nextjs/.next/static
|
COPY --from=installer --chown=nextjs:nodejs /app/apps/nextjs/.next/static ./apps/nextjs/.next/static
|
||||||
COPY --from=installer --chown=nextjs:nodejs /app/apps/nextjs/public ./apps/nextjs/public
|
COPY --from=installer --chown=nextjs:nodejs /app/apps/nextjs/public ./apps/nextjs/public
|
||||||
COPY --chown=nextjs:nodejs scripts/run.sh ./run.sh
|
COPY --chown=nextjs:nodejs scripts/run.sh ./run.sh
|
||||||
|
COPY --chown=nextjs:nodejs scripts/generateEncryptionKey.js ./generateEncryptionKey.js
|
||||||
COPY --chown=nextjs:nodejs packages/redis/redis.conf /app/redis.conf
|
COPY --chown=nextjs:nodejs packages/redis/redis.conf /app/redis.conf
|
||||||
COPY --chown=nextjs:nodejs nginx.conf /etc/nginx/templates/nginx.conf
|
COPY --chown=nextjs:nodejs nginx.conf /etc/nginx/templates/nginx.conf
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
},
|
},
|
||||||
"prettier": "@homarr/prettier-config",
|
"prettier": "@homarr/prettier-config",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@homarr/log": "workspace:^0.1.0",
|
||||||
"dayjs": "^1.11.13",
|
"dayjs": "^1.11.13",
|
||||||
"next": "^14.2.14",
|
"next": "^14.2.14",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
|
|||||||
@@ -1,7 +1,20 @@
|
|||||||
import crypto from "crypto";
|
import crypto from "crypto";
|
||||||
|
|
||||||
|
import { logger } from "@homarr/log";
|
||||||
|
|
||||||
const algorithm = "aes-256-cbc"; //Using AES encryption
|
const algorithm = "aes-256-cbc"; //Using AES encryption
|
||||||
const key = Buffer.from("1d71cceced68159ba59a277d056a66173613052cbeeccbfbd15ab1c909455a4d", "hex"); // TODO: generate with const data = crypto.randomBytes(32).toString('hex')
|
const fallbackKey = "0000000000000000000000000000000000000000000000000000000000000000";
|
||||||
|
const encryptionKey = process.env.ENCRYPTION_KEY ?? fallbackKey; // Fallback to a default key for local development
|
||||||
|
if (encryptionKey === fallbackKey) {
|
||||||
|
logger.warn("Using a fallback encryption key, stored secrets are not secure");
|
||||||
|
|
||||||
|
// We never want to use the fallback key in production
|
||||||
|
if (process.env.NODE_ENV === "production" && process.env.CI !== "true") {
|
||||||
|
throw new Error("Encryption key is not set");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const key = Buffer.from(encryptionKey, "hex");
|
||||||
|
|
||||||
export function encryptSecret(text: string): `${string}.${string}` {
|
export function encryptSecret(text: string): `${string}.${string}` {
|
||||||
const initializationVector = crypto.randomBytes(16);
|
const initializationVector = crypto.randomBytes(16);
|
||||||
|
|||||||
5
pnpm-lock.yaml
generated
5
pnpm-lock.yaml
generated
@@ -659,6 +659,9 @@ importers:
|
|||||||
|
|
||||||
packages/common:
|
packages/common:
|
||||||
dependencies:
|
dependencies:
|
||||||
|
'@homarr/log':
|
||||||
|
specifier: workspace:^0.1.0
|
||||||
|
version: link:../log
|
||||||
dayjs:
|
dayjs:
|
||||||
specifier: ^1.11.13
|
specifier: ^1.11.13
|
||||||
version: 1.11.13
|
version: 1.11.13
|
||||||
@@ -11294,7 +11297,7 @@ snapshots:
|
|||||||
|
|
||||||
estree-walker@3.0.3:
|
estree-walker@3.0.3:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/estree': 1.0.6
|
'@types/estree': 1.0.5
|
||||||
|
|
||||||
esutils@2.0.3: {}
|
esutils@2.0.3: {}
|
||||||
|
|
||||||
|
|||||||
7
scripts/generateEncryptionKey.js
Normal file
7
scripts/generateEncryptionKey.js
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
// This script generates a random encryption key
|
||||||
|
// This key is used to encrypt and decrypt the integration secrets
|
||||||
|
// In production it is generated in run.sh and stored in the environment variable ENCRYPTION_KEY
|
||||||
|
// during runtime, it's also stored in a file.
|
||||||
|
|
||||||
|
const crypto = require("crypto");
|
||||||
|
console.log(crypto.randomBytes(32).toString("hex"));
|
||||||
@@ -6,6 +6,19 @@ else
|
|||||||
node ./db/migrations/$DB_DIALECT/migrate.cjs ./db/migrations/$DB_DIALECT
|
node ./db/migrations/$DB_DIALECT/migrate.cjs ./db/migrations/$DB_DIALECT
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Generates an encryption key if it doesn't exist and saves it to /secrets/encryptionKey
|
||||||
|
# Also sets the ENCRYPTION_KEY environment variable
|
||||||
|
encryptionKey=""
|
||||||
|
if [ -r /secrets/encryptionKey ]; then
|
||||||
|
echo "Encryption key already exists"
|
||||||
|
encryptionKey=$(cat /secrets/encryptionKey)
|
||||||
|
else
|
||||||
|
echo "Generating encryption key"
|
||||||
|
encryptionKey=$(node ./generateEncryptionKey.js)
|
||||||
|
echo $encryptionKey > /secrets/encryptionKey
|
||||||
|
fi
|
||||||
|
export ENCRYPTION_KEY=$encryptionKey
|
||||||
|
|
||||||
# Start nginx proxy
|
# Start nginx proxy
|
||||||
# 1. Replace the HOSTNAME in the nginx template file
|
# 1. Replace the HOSTNAME in the nginx template file
|
||||||
# 2. Create the nginx configuration file from the template
|
# 2. Create the nginx configuration file from the template
|
||||||
|
|||||||
Reference in New Issue
Block a user