Fix docker build error and SSL regeneration
This commit is contained in:
@@ -9,6 +9,7 @@ COPY package*.json ./
|
|||||||
ENV npm_config_target_platform=linux
|
ENV npm_config_target_platform=linux
|
||||||
ENV npm_config_target_arch=x64
|
ENV npm_config_target_arch=x64
|
||||||
ENV npm_config_target_libc=glibc
|
ENV npm_config_target_libc=glibc
|
||||||
|
ENV NODE_OPTIONS="--max-old-space-size=4096"
|
||||||
|
|
||||||
RUN npm ci --force --ignore-scripts && \
|
RUN npm ci --force --ignore-scripts && \
|
||||||
npm cache clean --force
|
npm cache clean --force
|
||||||
@@ -19,7 +20,11 @@ WORKDIR /app
|
|||||||
|
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
|
ENV NODE_OPTIONS="--max-old-space-size=4096"
|
||||||
|
ENV NODE_ENV=production
|
||||||
|
|
||||||
RUN npm run build
|
RUN npm run build
|
||||||
|
RUN npm run build:types
|
||||||
|
|
||||||
# Stage 3: Build backend TypeScript
|
# Stage 3: Build backend TypeScript
|
||||||
FROM deps AS backend-builder
|
FROM deps AS backend-builder
|
||||||
@@ -30,6 +35,8 @@ COPY . .
|
|||||||
ENV npm_config_target_platform=linux
|
ENV npm_config_target_platform=linux
|
||||||
ENV npm_config_target_arch=x64
|
ENV npm_config_target_arch=x64
|
||||||
ENV npm_config_target_libc=glibc
|
ENV npm_config_target_libc=glibc
|
||||||
|
ENV NODE_OPTIONS="--max-old-space-size=4096"
|
||||||
|
ENV NODE_ENV=production
|
||||||
|
|
||||||
RUN npm rebuild better-sqlite3 --force
|
RUN npm rebuild better-sqlite3 --force
|
||||||
|
|
||||||
@@ -46,6 +53,7 @@ COPY package*.json ./
|
|||||||
ENV npm_config_target_platform=linux
|
ENV npm_config_target_platform=linux
|
||||||
ENV npm_config_target_arch=x64
|
ENV npm_config_target_arch=x64
|
||||||
ENV npm_config_target_libc=glibc
|
ENV npm_config_target_libc=glibc
|
||||||
|
ENV NODE_OPTIONS="--max-old-space-size=4096"
|
||||||
|
|
||||||
RUN npm ci --only=production --ignore-scripts --force && \
|
RUN npm ci --only=production --ignore-scripts --force && \
|
||||||
npm rebuild better-sqlite3 bcryptjs --force && \
|
npm rebuild better-sqlite3 bcryptjs --force && \
|
||||||
|
|||||||
@@ -25,15 +25,33 @@ chown -R node:node /app/data
|
|||||||
chmod 755 /app/data
|
chmod 755 /app/data
|
||||||
|
|
||||||
if [ "$ENABLE_SSL" = "true" ]; then
|
if [ "$ENABLE_SSL" = "true" ]; then
|
||||||
echo "Generating SSL certificates..."
|
echo "Checking SSL certificate configuration..."
|
||||||
mkdir -p /app/data/ssl
|
mkdir -p /app/data/ssl
|
||||||
chown -R node:node /app/data/ssl
|
chown -R node:node /app/data/ssl
|
||||||
chmod 755 /app/data/ssl
|
chmod 755 /app/data/ssl
|
||||||
|
|
||||||
DOMAIN=${SSL_DOMAIN:-localhost}
|
DOMAIN=${SSL_DOMAIN:-localhost}
|
||||||
echo "Generating certificate for domain: $DOMAIN"
|
|
||||||
|
# Check if certificates already exist and are valid
|
||||||
|
if [ -f "/app/data/ssl/termix.crt" ] && [ -f "/app/data/ssl/termix.key" ]; then
|
||||||
|
echo "SSL certificates found, checking validity..."
|
||||||
|
|
||||||
|
# Check if certificate is still valid (not expired within 30 days)
|
||||||
|
if openssl x509 -in /app/data/ssl/termix.crt -checkend 2592000 -noout >/dev/null 2>&1; then
|
||||||
|
echo "SSL certificates are valid and will be reused for domain: $DOMAIN"
|
||||||
|
else
|
||||||
|
echo "SSL certificate is expired or expiring soon, regenerating..."
|
||||||
|
rm -f /app/data/ssl/termix.crt /app/data/ssl/termix.key
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "SSL certificates not found, will generate new ones..."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Generate certificates only if they don't exist or are invalid
|
||||||
|
if [ ! -f "/app/data/ssl/termix.crt" ] || [ ! -f "/app/data/ssl/termix.key" ]; then
|
||||||
|
echo "Generating SSL certificates for domain: $DOMAIN"
|
||||||
|
|
||||||
cat > /app/data/ssl/openssl.conf << EOF
|
cat > /app/data/ssl/openssl.conf << EOF
|
||||||
[req]
|
[req]
|
||||||
default_bits = 2048
|
default_bits = 2048
|
||||||
prompt = no
|
prompt = no
|
||||||
@@ -62,17 +80,18 @@ IP.1 = 127.0.0.1
|
|||||||
IP.2 = ::1
|
IP.2 = ::1
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
openssl genrsa -out /app/data/ssl/termix.key 2048
|
openssl genrsa -out /app/data/ssl/termix.key 2048
|
||||||
|
|
||||||
openssl req -new -x509 -key /app/data/ssl/termix.key -out /app/data/ssl/termix.crt -days 365 -config /app/data/ssl/openssl.conf -extensions v3_req
|
openssl req -new -x509 -key /app/data/ssl/termix.key -out /app/data/ssl/termix.crt -days 365 -config /app/data/ssl/openssl.conf -extensions v3_req
|
||||||
|
|
||||||
chmod 600 /app/data/ssl/termix.key
|
chmod 600 /app/data/ssl/termix.key
|
||||||
chmod 644 /app/data/ssl/termix.crt
|
chmod 644 /app/data/ssl/termix.crt
|
||||||
chown node:node /app/data/ssl/termix.key /app/data/ssl/termix.crt
|
chown node:node /app/data/ssl/termix.key /app/data/ssl/termix.crt
|
||||||
|
|
||||||
rm -f /app/data/ssl/openssl.conf
|
rm -f /app/data/ssl/openssl.conf
|
||||||
|
|
||||||
echo "SSL certificates generated successfully for domain: $DOMAIN"
|
echo "SSL certificates generated successfully for domain: $DOMAIN"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Starting nginx..."
|
echo "Starting nginx..."
|
||||||
|
|||||||
@@ -10,7 +10,9 @@
|
|||||||
"clean": "npx prettier . --write",
|
"clean": "npx prettier . --write",
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"dev:https": "cross-env VITE_HTTPS=true vite",
|
"dev:https": "cross-env VITE_HTTPS=true vite",
|
||||||
"build": "vite build && tsc -p tsconfig.node.json",
|
"build": "vite build",
|
||||||
|
"build:types": "tsc -p tsconfig.node.json",
|
||||||
|
"build:full": "npm run build && npm run build:types",
|
||||||
"build:backend": "tsc -p tsconfig.node.json",
|
"build:backend": "tsc -p tsconfig.node.json",
|
||||||
"dev:backend": "tsc -p tsconfig.node.json && node ./dist/backend/backend/starter.js",
|
"dev:backend": "tsc -p tsconfig.node.json && node ./dist/backend/backend/starter.js",
|
||||||
"start": "npm run build:backend && node ./dist/backend/backend/starter.js",
|
"start": "npm run build:backend && node ./dist/backend/backend/starter.js",
|
||||||
|
|||||||
@@ -30,12 +30,30 @@ export class AutoSSLSetup {
|
|||||||
try {
|
try {
|
||||||
if (await this.isSSLConfigured()) {
|
if (await this.isSSLConfigured()) {
|
||||||
await this.logCertificateInfo();
|
await this.logCertificateInfo();
|
||||||
|
await this.setupEnvironmentVariables();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.generateSSLCertificates();
|
// In Docker, certificates might be generated by entrypoint script
|
||||||
|
// Check if they exist but weren't detected by isSSLConfigured
|
||||||
await this.setupEnvironmentVariables();
|
try {
|
||||||
|
await fs.access(this.CERT_FILE);
|
||||||
|
await fs.access(this.KEY_FILE);
|
||||||
|
|
||||||
|
systemLogger.info("SSL certificates found from entrypoint script", {
|
||||||
|
operation: "ssl_cert_found_entrypoint",
|
||||||
|
cert_path: this.CERT_FILE,
|
||||||
|
key_path: this.KEY_FILE,
|
||||||
|
});
|
||||||
|
|
||||||
|
await this.logCertificateInfo();
|
||||||
|
await this.setupEnvironmentVariables();
|
||||||
|
return;
|
||||||
|
} catch {
|
||||||
|
// Certificates don't exist, generate them
|
||||||
|
await this.generateSSLCertificates();
|
||||||
|
await this.setupEnvironmentVariables();
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
systemLogger.error("Failed to initialize SSL configuration", error, {
|
systemLogger.error("Failed to initialize SSL configuration", error, {
|
||||||
operation: "ssl_auto_init_failed",
|
operation: "ssl_auto_init_failed",
|
||||||
|
|||||||
@@ -222,9 +222,8 @@ export function HomepageAuth({
|
|||||||
setTotpCode("");
|
setTotpCode("");
|
||||||
setTotpTempToken("");
|
setTotpTempToken("");
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
toast.error(
|
const errorMessage = err?.response?.data?.error || err?.message || t("errors.unknownError");
|
||||||
err?.response?.data?.error || err?.message || t("errors.unknownError"),
|
toast.error(errorMessage);
|
||||||
);
|
|
||||||
setInternalLoggedIn(false);
|
setInternalLoggedIn(false);
|
||||||
setLoggedIn(false);
|
setLoggedIn(false);
|
||||||
setIsAdmin(false);
|
setIsAdmin(false);
|
||||||
@@ -371,11 +370,8 @@ export function HomepageAuth({
|
|||||||
setTotpTempToken("");
|
setTotpTempToken("");
|
||||||
toast.success(t("messages.loginSuccess"));
|
toast.success(t("messages.loginSuccess"));
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
toast.error(
|
const errorMessage = err?.response?.data?.error || err?.message || t("errors.invalidTotpCode");
|
||||||
err?.response?.data?.error ||
|
toast.error(errorMessage);
|
||||||
err?.message ||
|
|
||||||
t("errors.invalidTotpCode"),
|
|
||||||
);
|
|
||||||
} finally {
|
} finally {
|
||||||
setTotpLoading(false);
|
setTotpLoading(false);
|
||||||
}
|
}
|
||||||
@@ -394,11 +390,8 @@ export function HomepageAuth({
|
|||||||
|
|
||||||
window.location.replace(authUrl);
|
window.location.replace(authUrl);
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
toast.error(
|
const errorMessage = err?.response?.data?.error || err?.message || t("errors.failedOidcLogin");
|
||||||
err?.response?.data?.error ||
|
toast.error(errorMessage);
|
||||||
err?.message ||
|
|
||||||
t("errors.failedOidcLogin"),
|
|
||||||
);
|
|
||||||
setOidcLoading(false);
|
setOidcLoading(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -204,9 +204,8 @@ export function HomepageAuth({
|
|||||||
setTotpCode("");
|
setTotpCode("");
|
||||||
setTotpTempToken("");
|
setTotpTempToken("");
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
toast.error(
|
const errorMessage = err?.response?.data?.error || err?.message || t("errors.unknownError");
|
||||||
err?.response?.data?.error || err?.message || t("errors.unknownError"),
|
toast.error(errorMessage);
|
||||||
);
|
|
||||||
setInternalLoggedIn(false);
|
setInternalLoggedIn(false);
|
||||||
setLoggedIn(false);
|
setLoggedIn(false);
|
||||||
setIsAdmin(false);
|
setIsAdmin(false);
|
||||||
@@ -347,11 +346,8 @@ export function HomepageAuth({
|
|||||||
setTotpTempToken("");
|
setTotpTempToken("");
|
||||||
toast.success(t("messages.loginSuccess"));
|
toast.success(t("messages.loginSuccess"));
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
toast.error(
|
const errorMessage = err?.response?.data?.error || err?.message || t("errors.invalidTotpCode");
|
||||||
err?.response?.data?.error ||
|
toast.error(errorMessage);
|
||||||
err?.message ||
|
|
||||||
t("errors.invalidTotpCode"),
|
|
||||||
);
|
|
||||||
} finally {
|
} finally {
|
||||||
setTotpLoading(false);
|
setTotpLoading(false);
|
||||||
}
|
}
|
||||||
@@ -370,11 +366,8 @@ export function HomepageAuth({
|
|||||||
|
|
||||||
window.location.replace(authUrl);
|
window.location.replace(authUrl);
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
toast.error(
|
const errorMessage = err?.response?.data?.error || err?.message || t("errors.failedOidcLogin");
|
||||||
err?.response?.data?.error ||
|
toast.error(errorMessage);
|
||||||
err?.message ||
|
|
||||||
t("errors.failedOidcLogin"),
|
|
||||||
);
|
|
||||||
setOidcLoading(false);
|
setOidcLoading(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -402,12 +395,12 @@ export function HomepageAuth({
|
|||||||
setLoggedIn(true);
|
setLoggedIn(true);
|
||||||
setIsAdmin(!!meRes.is_admin);
|
setIsAdmin(!!meRes.is_admin);
|
||||||
setUsername(meRes.username || null);
|
setUsername(meRes.username || null);
|
||||||
setUserId(meRes.id || null);
|
setUserId(meRes.userId || null);
|
||||||
setDbError(null);
|
setDbError(null);
|
||||||
onAuthSuccess({
|
onAuthSuccess({
|
||||||
isAdmin: !!meRes.is_admin,
|
isAdmin: !!meRes.is_admin,
|
||||||
username: meRes.username || null,
|
username: meRes.username || null,
|
||||||
userId: meRes.id || null,
|
userId: meRes.userId || null,
|
||||||
});
|
});
|
||||||
setInternalLoggedIn(true);
|
setInternalLoggedIn(true);
|
||||||
window.history.replaceState(
|
window.history.replaceState(
|
||||||
|
|||||||
Reference in New Issue
Block a user