mirror of
https://github.com/Portabase/portabase.git
synced 2026-07-14 11:16:13 +02:00
fix: new storage architecture
This commit is contained in:
@@ -0,0 +1,124 @@
|
|||||||
|
import {NextResponse} from "next/server";
|
||||||
|
import fs from "fs";
|
||||||
|
import path from "path";
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// export async function POST(request: Request) {
|
||||||
|
// try {
|
||||||
|
// const body = await request.json();
|
||||||
|
// console.log("tusd hook payload:", body);
|
||||||
|
//
|
||||||
|
// return NextResponse.json({
|
||||||
|
// "Upload-Defer-Length": true,
|
||||||
|
// "Upload-Metadata": "name somefilename",
|
||||||
|
// });
|
||||||
|
// } catch (error) {
|
||||||
|
// console.error("Error in POST handler:", error);
|
||||||
|
// return NextResponse.json(
|
||||||
|
// { error: "Internal server error" },
|
||||||
|
// { status: 500 }
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// export async function POST(request: Request) {
|
||||||
|
// try {
|
||||||
|
// const body = await request.json();
|
||||||
|
// console.log("TUSD hook payload:", body);
|
||||||
|
//
|
||||||
|
// // Pre-create hook: must return Upload-Defer-Length or Upload-Length
|
||||||
|
// if (body.event === "pre-create") {
|
||||||
|
// return NextResponse.json({
|
||||||
|
// "Upload-Defer-Length": true, // defer the upload length
|
||||||
|
// "Upload-Metadata": "name somefilename" // optional metadata
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // Post-receive hook: handle finished uploads
|
||||||
|
// if (body.event === "post-receive") {
|
||||||
|
// console.log(`Upload finished: ${body.id}, size: ${body.upload_length}`);
|
||||||
|
// // process the file, AES encryption, move, etc.
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return NextResponse.json({ ok: true }); // safe fallback for other events
|
||||||
|
// } catch (error) {
|
||||||
|
// console.error("Hook error:", error);
|
||||||
|
// return NextResponse.json({ error: "Internal server error" }, { status: 500 });
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
export async function POST(request: Request) {
|
||||||
|
try {
|
||||||
|
const body = await request.json();
|
||||||
|
console.log("TUSD hook payload:", body);
|
||||||
|
const event = body.Event
|
||||||
|
const headers = event.HTTPRequest.Header
|
||||||
|
|
||||||
|
// if (body.event === "pre-create") {
|
||||||
|
// return NextResponse.json({
|
||||||
|
// "Upload-Defer-Length": true
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
console.log("TUSD hook payload:", body.Type);
|
||||||
|
console.log("TUSD hook payload:", headers);
|
||||||
|
|
||||||
|
if (
|
||||||
|
body.Type === "post-receive" &&
|
||||||
|
event.Upload.SizeIsDeferred === false &&
|
||||||
|
event.Upload.Offset === event.Upload.Size
|
||||||
|
) {
|
||||||
|
const id = event.Upload.ID;
|
||||||
|
// const extensionFile = headers["X-Extension"]?.[0] ?? ".bin";
|
||||||
|
const extensionFile = ".enc";
|
||||||
|
const filePath = path.join(process.cwd(), "/private/uploads/backups/");
|
||||||
|
|
||||||
|
fs.renameSync(
|
||||||
|
`${filePath}${id}`,
|
||||||
|
`${filePath}${id}${extensionFile}`
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// if (body.Type === "post-receive"){
|
||||||
|
// // const id = event.Upload.ID
|
||||||
|
// // const extensionFile = headers["X-Extension"]?.[0] ?? ".bin";
|
||||||
|
// // const extensionFile = ".enc";
|
||||||
|
// // const filePath = path.join(process.cwd(), "/private/uploads/backups/");
|
||||||
|
// //
|
||||||
|
// // fs.renameSync(
|
||||||
|
// // `${filePath}${id}`,
|
||||||
|
// // `${filePath}${id}${extensionFile}`
|
||||||
|
// // );
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Post-receive hook: handle finished uploads
|
||||||
|
if (body.event === "post-receive") {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
console.log(`Upload finished: ${body.id}, size: ${body.upload_length}`);
|
||||||
|
// process the file, AES encryption, move, etc.
|
||||||
|
|
||||||
|
const id = body.id;
|
||||||
|
const ext = body.upload.metaData?.extension ?? ".bin";
|
||||||
|
console.log(body)
|
||||||
|
console.log("Upload finished: ", id);
|
||||||
|
console.log("Ext: ", ext);
|
||||||
|
|
||||||
|
// fs.renameSync(
|
||||||
|
// `/data/uploads/backups/${id}`,
|
||||||
|
// `/data/uploads/backups/${id}${ext}`
|
||||||
|
// );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return NextResponse.json({}); // no Upload-Defer-Length
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Hook error:", error);
|
||||||
|
return NextResponse.json({error: "Internal server error"}, {status: 500});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -17,5 +17,22 @@ services:
|
|||||||
timeout: 5s
|
timeout: 5s
|
||||||
retries: 5
|
retries: 5
|
||||||
|
|
||||||
|
tusd:
|
||||||
|
image: tusproject/tusd:v2.8.0
|
||||||
|
ports:
|
||||||
|
- "1080:8080"
|
||||||
|
command: >
|
||||||
|
-upload-dir /data/uploads/backups
|
||||||
|
-hooks-http http://localhost:8887/api/tus/hooks
|
||||||
|
-max-size 21474836480
|
||||||
|
|
||||||
|
# -max-size 54975581388
|
||||||
|
# -max-size 54975581388
|
||||||
|
|
||||||
|
extra_hosts:
|
||||||
|
- "localhost:host-gateway"
|
||||||
|
volumes:
|
||||||
|
- ./private/uploads/backups:/data/uploads/backups
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
postgres-data:
|
postgres-data:
|
||||||
|
|||||||
+162
-58
@@ -1,53 +1,177 @@
|
|||||||
FROM node:22-alpine AS base
|
#FROM node:22-alpine AS base
|
||||||
|
#
|
||||||
|
#RUN apk add --update --no-cache \
|
||||||
|
# libc6-compat \
|
||||||
|
# openssl \
|
||||||
|
# tzdata
|
||||||
|
#
|
||||||
|
#FROM base AS tusd-base
|
||||||
|
#
|
||||||
|
#RUN apk add --no-cache curl ca-certificates bash \
|
||||||
|
# && TUSD_VERSION=1.28.0 \
|
||||||
|
# && curl -L -o /usr/local/bin/tusd https://github.com/tus/tusd/releases/download/v${TUSD_VERSION}/tusd-${TUSD_VERSION}-linux-amd64 \
|
||||||
|
# && chmod +x /usr/local/bin/tusd
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#FROM base AS build-env
|
||||||
|
#
|
||||||
|
#RUN apk add --update --no-cache \
|
||||||
|
# build-base \
|
||||||
|
# g++ \
|
||||||
|
# make \
|
||||||
|
# libtool \
|
||||||
|
# autoconf \
|
||||||
|
# automake
|
||||||
|
#
|
||||||
|
#RUN corepack enable && corepack prepare pnpm@latest --activate
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#FROM build-env AS deps
|
||||||
|
#
|
||||||
|
#WORKDIR /app
|
||||||
|
#
|
||||||
|
#COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./
|
||||||
|
#
|
||||||
|
#RUN pnpm i --frozen-lockfile
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#FROM build-env AS dev
|
||||||
|
#
|
||||||
|
#COPY --from=tusd-base /usr/local/bin/tusd /usr/local/bin/tusd
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#WORKDIR /app
|
||||||
|
#
|
||||||
|
#COPY --from=deps /app/node_modules ./node_modules
|
||||||
|
#COPY . .
|
||||||
|
#
|
||||||
|
#USER root
|
||||||
|
#
|
||||||
|
#RUN chmod +x /app/docker/entrypoints/app-dev-entrypoint.sh
|
||||||
|
#ENTRYPOINT ["sh","/app/docker/entrypoints/app-dev-entrypoint.sh"]
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#FROM build-env AS builder
|
||||||
|
#
|
||||||
|
#WORKDIR /app
|
||||||
|
#COPY --from=deps /app/node_modules ./node_modules
|
||||||
|
#COPY . .
|
||||||
|
#
|
||||||
|
#ENV NEXT_TELEMETRY_DISABLED=1
|
||||||
|
#
|
||||||
|
#RUN pnpm run build
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#FROM base AS prod
|
||||||
|
#
|
||||||
|
#COPY --from=tusd-base /usr/local/bin/tusd /usr/local/bin/tusd
|
||||||
|
#
|
||||||
|
#WORKDIR /app
|
||||||
|
#
|
||||||
|
#ENV NODE_ENV=production
|
||||||
|
#ENV NEXT_TELEMETRY_DISABLED=1
|
||||||
|
#
|
||||||
|
#RUN addgroup --system --gid 1001 nodejs
|
||||||
|
#RUN adduser --system --uid 1001 nextjs
|
||||||
|
#
|
||||||
|
#COPY --from=builder /app/public ./public
|
||||||
|
#
|
||||||
|
#RUN mkdir .next
|
||||||
|
#RUN chown nextjs:nodejs .next
|
||||||
|
#RUN mkdir -p /app/private/uploads
|
||||||
|
#RUN chown -R nextjs:nodejs /app/private
|
||||||
|
#RUN chown -R nextjs:nodejs /app/public
|
||||||
|
#
|
||||||
|
#COPY --from=builder /app/next.config.ts ./
|
||||||
|
#
|
||||||
|
#COPY --from=builder /app/portabase.config.ts ./
|
||||||
|
#COPY --from=builder /app/drizzle.config.ts ./
|
||||||
|
#COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
|
||||||
|
#COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
|
||||||
|
#COPY --chown=nextjs:nodejs src/db ./src/db
|
||||||
|
#
|
||||||
|
#USER root
|
||||||
|
#
|
||||||
|
#COPY ./docker/entrypoints/app-prod-entrypoint.sh /app/app-prod-entrypoint.sh
|
||||||
|
#RUN chmod +x /app/app-prod-entrypoint.sh
|
||||||
|
#
|
||||||
|
#EXPOSE 80
|
||||||
|
#
|
||||||
|
#ENV PORT=80
|
||||||
|
#
|
||||||
|
#ENV HOSTNAME="0.0.0.0"
|
||||||
|
#
|
||||||
|
#USER nextjs
|
||||||
|
#
|
||||||
|
#ENTRYPOINT ["sh","/app/app-prod-entrypoint.sh"]
|
||||||
|
|
||||||
RUN apk add --update --no-cache \
|
|
||||||
libc6-compat \
|
|
||||||
openssl \
|
FROM node:22-bullseye AS base
|
||||||
tzdata
|
|
||||||
|
RUN apt-get update && apt-get install -y \
|
||||||
|
curl \
|
||||||
|
ca-certificates \
|
||||||
|
bash \
|
||||||
|
tzdata \
|
||||||
|
libc6 \
|
||||||
|
build-essential \
|
||||||
|
g++ \
|
||||||
|
make \
|
||||||
|
autoconf \
|
||||||
|
automake \
|
||||||
|
libtool \
|
||||||
|
git \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
FROM base AS tusd-base
|
||||||
|
|
||||||
|
ENV TUSD_VERSION=2.8.0
|
||||||
|
|
||||||
|
RUN apt-get update && apt-get install -y \
|
||||||
|
curl \
|
||||||
|
ca-certificates \
|
||||||
|
bash \
|
||||||
|
tar \
|
||||||
|
gzip \
|
||||||
|
libssl-dev \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Download and extract tusd
|
||||||
|
RUN curl -L -o /tmp/tusd.tar.gz \
|
||||||
|
https://github.com/tus/tusd/releases/download/v${TUSD_VERSION}/tusd_linux_amd64.tar.gz \
|
||||||
|
&& mkdir -p /usr/local/bin \
|
||||||
|
&& tar -xzf /tmp/tusd.tar.gz -C /tmp \
|
||||||
|
# Move the actual binary, whatever its name/folder inside tar
|
||||||
|
&& mv /tmp/*/tusd /usr/local/bin/tusd \
|
||||||
|
&& chmod +x /usr/local/bin/tusd \
|
||||||
|
&& /usr/local/bin/tusd --version
|
||||||
|
|
||||||
FROM base AS build-env
|
FROM base AS build-env
|
||||||
|
|
||||||
RUN apk add --update --no-cache \
|
|
||||||
build-base \
|
|
||||||
g++ \
|
|
||||||
make \
|
|
||||||
libtool \
|
|
||||||
autoconf \
|
|
||||||
automake
|
|
||||||
|
|
||||||
RUN corepack enable && corepack prepare pnpm@latest --activate
|
RUN corepack enable && corepack prepare pnpm@latest --activate
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
FROM build-env AS deps
|
FROM build-env AS deps
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./
|
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./
|
||||||
|
|
||||||
RUN pnpm i --frozen-lockfile
|
RUN pnpm i --frozen-lockfile
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
FROM build-env AS dev
|
FROM build-env AS dev
|
||||||
|
|
||||||
WORKDIR /app
|
|
||||||
|
|
||||||
COPY --from=deps /app/node_modules ./node_modules
|
COPY --from=deps /app/node_modules ./node_modules
|
||||||
|
COPY --from=tusd-base /usr/local/bin/tusd /usr/local/bin/tusd
|
||||||
|
WORKDIR /app
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
USER root
|
USER root
|
||||||
|
|
||||||
RUN chmod +x /app/docker/entrypoints/app-dev-entrypoint.sh
|
RUN chmod +x /app/docker/entrypoints/app-dev-entrypoint.sh
|
||||||
|
|
||||||
ENTRYPOINT ["sh","/app/docker/entrypoints/app-dev-entrypoint.sh"]
|
ENTRYPOINT ["sh","/app/docker/entrypoints/app-dev-entrypoint.sh"]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
FROM build-env AS builder
|
FROM build-env AS builder
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
@@ -55,57 +179,37 @@ COPY --from=deps /app/node_modules ./node_modules
|
|||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
ENV NEXT_TELEMETRY_DISABLED=1
|
ENV NEXT_TELEMETRY_DISABLED=1
|
||||||
|
|
||||||
RUN pnpm run build
|
RUN pnpm run build
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
FROM base AS prod
|
FROM base AS prod
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
ENV NODE_ENV=production
|
ENV NODE_ENV=production
|
||||||
ENV NEXT_TELEMETRY_DISABLED=1
|
ENV NEXT_TELEMETRY_DISABLED=1
|
||||||
|
ENV PORT=80
|
||||||
RUN corepack enable && corepack prepare pnpm@latest --activate
|
ENV HOSTNAME="0.0.0.0"
|
||||||
|
|
||||||
|
|
||||||
RUN addgroup --system --gid 1001 nodejs
|
RUN addgroup --system --gid 1001 nodejs
|
||||||
RUN adduser --system --uid 1001 nextjs
|
RUN adduser --system --uid 1001 nextjs
|
||||||
|
|
||||||
COPY --from=builder /app/public ./public
|
COPY --from=builder /app/public ./public
|
||||||
|
|
||||||
RUN mkdir .next
|
|
||||||
RUN chown nextjs:nodejs .next
|
|
||||||
RUN mkdir -p /app/private/uploads
|
|
||||||
RUN chown -R nextjs:nodejs /app/private
|
|
||||||
RUN chown -R nextjs:nodejs /app/public
|
|
||||||
|
|
||||||
COPY --from=builder /app/next.config.ts ./
|
COPY --from=builder /app/next.config.ts ./
|
||||||
COPY --from=builder /app/server ./server
|
|
||||||
COPY --from=builder /app/src ./src
|
|
||||||
|
|
||||||
COPY --from=builder /app/portabase.config.ts ./
|
COPY --from=builder /app/portabase.config.ts ./
|
||||||
COPY --from=builder /app/drizzle.config.ts ./
|
COPY --from=builder /app/drizzle.config.ts ./
|
||||||
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
|
COPY --from=builder --chown=1001:1001 /app/.next/standalone ./
|
||||||
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
|
COPY --from=builder --chown=1001:1001 /app/.next/static ./.next/static
|
||||||
COPY --chown=nextjs:nodejs src/db ./src/db
|
COPY --chown=1001:1001 src/db ./src/db
|
||||||
|
|
||||||
COPY --from=deps /app/node_modules ./node_modules
|
COPY --from=deps /app/node_modules ./node_modules
|
||||||
|
|
||||||
USER root
|
COPY --from=tusd-base /usr/local/bin/tusd /usr/local/bin/tusd
|
||||||
|
|
||||||
|
RUN mkdir -p .next /app/private/uploads \
|
||||||
|
&& chown -R nextjs:nodejs .next /app/private /app/public
|
||||||
|
|
||||||
|
USER root
|
||||||
COPY ./docker/entrypoints/app-prod-entrypoint.sh /app/app-prod-entrypoint.sh
|
COPY ./docker/entrypoints/app-prod-entrypoint.sh /app/app-prod-entrypoint.sh
|
||||||
RUN chmod +x /app/app-prod-entrypoint.sh
|
RUN chmod +x /app/app-prod-entrypoint.sh
|
||||||
|
|
||||||
EXPOSE 80
|
EXPOSE 80
|
||||||
|
|
||||||
ENV PORT=80
|
|
||||||
|
|
||||||
ENV HOSTNAME="0.0.0.0"
|
|
||||||
|
|
||||||
USER nextjs
|
USER nextjs
|
||||||
|
|
||||||
ENTRYPOINT ["sh","/app/app-prod-entrypoint.sh"]
|
ENTRYPOINT ["sh","/app/app-prod-entrypoint.sh"]
|
||||||
|
|||||||
@@ -7,8 +7,12 @@ else
|
|||||||
echo "[WARN] No TZ provided, using default container timezone"
|
echo "[WARN] No TZ provided, using default container timezone"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
pnpm run start
|
# Start tusd as background process
|
||||||
#node server.js
|
mkdir -p /app/private/uploads
|
||||||
|
echo "▶ Starting tusd server..."
|
||||||
|
tusd --dir /app/private/uploads --hooks-http http://localhost:80/api/tus/hooks --port 1080 &
|
||||||
|
|
||||||
|
node server.js
|
||||||
|
|
||||||
exec "$@"
|
exec "$@"
|
||||||
|
|
||||||
|
|||||||
@@ -47,6 +47,20 @@ const nextConfig: NextConfig = {
|
|||||||
},
|
},
|
||||||
proxyClientMaxBodySize: '10gb',
|
proxyClientMaxBodySize: '10gb',
|
||||||
},
|
},
|
||||||
|
async rewrites() {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
source: '/tus/metrics',
|
||||||
|
destination: 'http://localhost:1080/metrics',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
source: '/tus/files',
|
||||||
|
destination: 'http://localhost:1080/files',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
async headers() {
|
async headers() {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
|
|||||||
+3
-2
@@ -3,9 +3,10 @@
|
|||||||
"version": "1.2.5-rc.8",
|
"version": "1.2.5-rc.8",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "NODE_ENV=development tsx watch server/server.ts",
|
"dev": "next dev --turbopack -p 8887",
|
||||||
"build": "next build --experimental-build-mode compile",
|
"build": "next build --experimental-build-mode compile",
|
||||||
"start": "NODE_ENV=production tsx server/server.ts",
|
"start": "next start",
|
||||||
|
|
||||||
|
|
||||||
"lint": "next lint",
|
"lint": "next lint",
|
||||||
"email": "email dev --dir ./src/components/emails",
|
"email": "email dev --dir ./src/components/emails",
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ function checkRouteExists(pathname: string) {
|
|||||||
/^\/api\/agent\/[^/]+\/restore\/?$/,
|
/^\/api\/agent\/[^/]+\/restore\/?$/,
|
||||||
/^\/api\/files\/images\/[^/]+\/?$/,
|
/^\/api\/files\/images\/[^/]+\/?$/,
|
||||||
/^\/api\/files\/backups\/?$/,
|
/^\/api\/files\/backups\/?$/,
|
||||||
|
/^\/api\/tus\/hooks\/?$/,
|
||||||
/^\/api\/events\/?$/,
|
/^\/api\/events\/?$/,
|
||||||
/^\/api\/init\/?$/,
|
/^\/api\/init\/?$/,
|
||||||
/^\/api\/config\/?$/,
|
/^\/api\/config\/?$/,
|
||||||
|
|||||||
@@ -77,6 +77,7 @@ export default async function uploadTempFileToProviders(
|
|||||||
? await dispatchStorage(input, policy.id)
|
? await dispatchStorage(input, policy.id)
|
||||||
: await dispatchStorage(input, undefined, policy.storageChannelId);
|
: await dispatchStorage(input, undefined, policy.storageChannelId);
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
|
console.error(err);
|
||||||
result = {success: false, provider: null, error: err.message};
|
result = {success: false, provider: null, error: err.message};
|
||||||
}
|
}
|
||||||
await db.update(drizzleDb.schemas.backupStorage)
|
await db.update(drizzleDb.schemas.backupStorage)
|
||||||
|
|||||||
Reference in New Issue
Block a user