feat: migrate from PostgreSQL to SQLite

- Updated Docker Compose and Dockerfile to remove PostgreSQL dependencies and configure SQLite as the database provider.
- Adjusted environment variables and healthcheck commands to reflect the new database setup.
- Simplified server startup script by removing PostgreSQL wait logic and replacing migration commands with schema push.
- Updated Prisma schema to use SQLite and removed related migration files.
This commit is contained in:
Daniel Luiz Alves
2025-05-30 22:50:40 -03:00
parent 602780e8dd
commit c39d41b76c
8 changed files with 21 additions and 248 deletions

View File

@@ -1,8 +1,7 @@
FROM node:18-alpine AS base
# Install system dependencies
# Install system dependencies (removed netcat-openbsd since we no longer need to wait for PostgreSQL)
RUN apk add --no-cache \
netcat-openbsd \
gcompat \
supervisor \
curl
@@ -77,9 +76,10 @@ RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 palmr
# Create application directories and set permissions
# Include storage directories for filesystem mode
# Include storage directories for filesystem mode and SQLite database directory
RUN mkdir -p /app/server /app/web /home/palmr/.npm /home/palmr/.cache \
/app/server/uploads /app/server/temp-chunks /app/server/uploads/logo
/app/server/uploads /app/server/temp-chunks /app/server/uploads/logo \
/app/server/prisma
RUN chown -R palmr:nodejs /app /home/palmr
# === Copy Server Files ===
@@ -92,7 +92,7 @@ COPY --from=server-builder --chown=palmr:nodejs /app/server/prisma ./prisma
COPY --from=server-builder --chown=palmr:nodejs /app/server/package.json ./
# Ensure storage directories have correct permissions
RUN chown -R palmr:nodejs /app/server/uploads /app/server/temp-chunks
RUN chown -R palmr:nodejs /app/server/uploads /app/server/temp-chunks /app/server/prisma
# === Copy Web Files ===
WORKDIR /app/web
@@ -113,7 +113,7 @@ COPY infra/server-start.sh /app/server-start.sh
RUN chmod +x /app/server-start.sh
RUN chown palmr:nodejs /app/server-start.sh
# Copy supervisor configuration
# Copy supervisor configuration (simplified without PostgreSQL dependency)
COPY <<EOF /etc/supervisor/conf.d/supervisord.conf
[supervisord]
nodaemon=true
@@ -151,10 +151,11 @@ COPY <<EOF /app/start.sh
echo "Starting Palmr Application..."
echo "Storage Mode: \${ENABLE_S3:-false}"
echo "Database: SQLite"
# Ensure storage directories exist with correct permissions
mkdir -p /app/server/uploads /app/server/temp-chunks /app/server/uploads/logo
chown -R palmr:nodejs /app/server/uploads /app/server/temp-chunks
mkdir -p /app/server/uploads /app/server/temp-chunks /app/server/uploads/logo /app/server/prisma
chown -R palmr:nodejs /app/server/uploads /app/server/temp-chunks /app/server/prisma
# Start supervisor
exec /usr/bin/supervisord -c /etc/supervisor/conf.d/supervisord.conf
@@ -162,8 +163,8 @@ EOF
RUN chmod +x /app/start.sh
# Create volume mount points for persistent storage (filesystem mode)
VOLUME ["/app/server/uploads", "/app/server/temp-chunks"]
# Create volume mount points for persistent storage (filesystem mode and SQLite database)
VOLUME ["/app/server/uploads", "/app/server/temp-chunks", "/app/server/prisma"]
# Expose ports
EXPOSE 3333 5487

View File

@@ -1,4 +1,4 @@
DATABASE_URL="postgresql://palmr:palmr123@localhost:5432/palmr?schema=public"
# DATABASE_URL="postgresql://palmr:palmr123@localhost:5432/palmr?schema=public"
FRONTEND_URL="http://localhost:3000"
MAX_FILESIZE="1073741824"

View File

@@ -1,178 +0,0 @@
-- CreateTable
CREATE TABLE "users" (
"id" TEXT NOT NULL,
"firstName" TEXT NOT NULL,
"lastName" TEXT NOT NULL,
"username" TEXT NOT NULL,
"email" TEXT NOT NULL,
"password" TEXT NOT NULL,
"image" TEXT,
"isAdmin" BOOLEAN NOT NULL DEFAULT false,
"isActive" BOOLEAN NOT NULL DEFAULT true,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "users_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "files" (
"id" TEXT NOT NULL,
"name" TEXT NOT NULL,
"description" TEXT,
"extension" TEXT NOT NULL,
"size" BIGINT NOT NULL,
"objectName" TEXT NOT NULL,
"userId" TEXT NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "files_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "shares" (
"id" TEXT NOT NULL,
"name" TEXT,
"views" INTEGER NOT NULL DEFAULT 0,
"expiration" TIMESTAMP(3),
"description" TEXT,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"creatorId" TEXT,
"securityId" TEXT NOT NULL,
CONSTRAINT "shares_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "share_security" (
"id" TEXT NOT NULL,
"password" TEXT,
"maxViews" INTEGER,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "share_security_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "share_recipients" (
"id" TEXT NOT NULL,
"email" TEXT NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"shareId" TEXT NOT NULL,
CONSTRAINT "share_recipients_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "app_configs" (
"id" TEXT NOT NULL,
"key" TEXT NOT NULL,
"value" TEXT NOT NULL,
"type" TEXT NOT NULL,
"group" TEXT NOT NULL,
"isSystem" BOOLEAN NOT NULL DEFAULT true,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "app_configs_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "login_attempts" (
"id" TEXT NOT NULL,
"userId" TEXT NOT NULL,
"attempts" INTEGER NOT NULL DEFAULT 1,
"lastAttempt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "login_attempts_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "password_resets" (
"id" TEXT NOT NULL,
"userId" TEXT NOT NULL,
"token" TEXT NOT NULL,
"expiresAt" TIMESTAMP(3) NOT NULL,
"used" BOOLEAN NOT NULL DEFAULT false,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "password_resets_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "share_aliases" (
"id" TEXT NOT NULL,
"alias" TEXT NOT NULL,
"shareId" TEXT NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "share_aliases_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "_ShareFiles" (
"A" TEXT NOT NULL,
"B" TEXT NOT NULL,
CONSTRAINT "_ShareFiles_AB_pkey" PRIMARY KEY ("A","B")
);
-- CreateIndex
CREATE UNIQUE INDEX "users_username_key" ON "users"("username");
-- CreateIndex
CREATE UNIQUE INDEX "users_email_key" ON "users"("email");
-- CreateIndex
CREATE UNIQUE INDEX "shares_securityId_key" ON "shares"("securityId");
-- CreateIndex
CREATE UNIQUE INDEX "app_configs_key_key" ON "app_configs"("key");
-- CreateIndex
CREATE UNIQUE INDEX "login_attempts_userId_key" ON "login_attempts"("userId");
-- CreateIndex
CREATE UNIQUE INDEX "password_resets_token_key" ON "password_resets"("token");
-- CreateIndex
CREATE UNIQUE INDEX "share_aliases_alias_key" ON "share_aliases"("alias");
-- CreateIndex
CREATE UNIQUE INDEX "share_aliases_shareId_key" ON "share_aliases"("shareId");
-- CreateIndex
CREATE INDEX "_ShareFiles_B_index" ON "_ShareFiles"("B");
-- AddForeignKey
ALTER TABLE "files" ADD CONSTRAINT "files_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "shares" ADD CONSTRAINT "shares_creatorId_fkey" FOREIGN KEY ("creatorId") REFERENCES "users"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "shares" ADD CONSTRAINT "shares_securityId_fkey" FOREIGN KEY ("securityId") REFERENCES "share_security"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "share_recipients" ADD CONSTRAINT "share_recipients_shareId_fkey" FOREIGN KEY ("shareId") REFERENCES "shares"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "login_attempts" ADD CONSTRAINT "login_attempts_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "password_resets" ADD CONSTRAINT "password_resets_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "share_aliases" ADD CONSTRAINT "share_aliases_shareId_fkey" FOREIGN KEY ("shareId") REFERENCES "shares"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "_ShareFiles" ADD CONSTRAINT "_ShareFiles_A_fkey" FOREIGN KEY ("A") REFERENCES "files"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "_ShareFiles" ADD CONSTRAINT "_ShareFiles_B_fkey" FOREIGN KEY ("B") REFERENCES "shares"("id") ON DELETE CASCADE ON UPDATE CASCADE;

View File

@@ -1,3 +0,0 @@
# Please do not edit this file manually
# It should be added in your version-control system (e.g., Git)
provider = "postgresql"

View File

@@ -3,8 +3,8 @@ generator client {
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
provider = "sqlite"
url = "file:./palmr.db"
}
model User {

View File

@@ -12,7 +12,6 @@ const envSchema = z.object({
S3_REGION: z.string().optional(),
S3_BUCKET_NAME: z.string().optional(),
S3_FORCE_PATH_STYLE: z.union([z.literal("true"), z.literal("false")]).default("false"),
DATABASE_URL: z.string().min(1),
MAX_FILESIZE: z.string().min(1),
});

View File

@@ -2,16 +2,12 @@ services:
palmr:
image: kyantech/palmr:latest # Make sure to use the correct version (latest) of the image
container_name: palmr-application
depends_on:
postgres:
condition: "service_healthy"
environment:
# Storage Configuration
- ENABLE_S3=false # Set to 'false' to use local filesystem storage instead of S3/MinIO or true to use S3/MinIO in this case we are using filesystem storage
- ENCRYPTION_KEY=${ENCRYPTION_KEY:-change-this-key-in-production-min-32-chars} # Required for filesystem encryption (min 32 chars)
# Server environment variables
- DATABASE_URL=postgresql://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:-postgresRootPassword}@postgres:${DB_EXTERNAL_PORT:-5432}/${POSTGRES_DB:-palmr_db}?schema=public # Database URL with configurable credentials through env vars
- FRONTEND_URL=http://palmr:${APP_EXTERNAL_PORT:-5487} # Frontend URL - Make sure to use the correct frontend URL, depends on where the frontend is running, its prepared for localhost, but you can change it to your frontend URL if needed
- API_BASE_URL=http://palmr:${API_EXTERNAL_PORT:-3333} # Using Docker service name for internal communication
- MAX_FILESIZE=${MAX_FILESIZE:-1073741824} # Max Filesize for upload - Declared in Bytes. Default is 1GB. can be changed by admin in the frontend.
@@ -21,54 +17,21 @@ services:
volumes:
- palmr_uploads:/app/server/uploads # Uploads folder for the application
- palmr_temp_chunks:/app/server/temp-chunks # Temp chunks folder for the application
networks:
- palmr-network # Network for the application to communicate with the database
- palmr_database:/app/server/prisma # SQLite database folder
restart: unless-stopped
healthcheck:
test: [
"CMD",
"sh",
"-c",
"wget --no-verbose --tries=1 --spider http://palmr:${API_EXTERNAL_PORT:-3333}/health && wget --no-verbose --tries=1 --spider http://palmr:5487",
"wget --no-verbose --tries=1 --spider http://palmr:${API_EXTERNAL_PORT:-3333}/health && wget --no-verbose --tries=1 --spider http://palmr:${APP_EXTERNAL_PORT:-5487}",
] # Healthcheck for the application
interval: 30s
timeout: 10s
retries: 5
start_period: 120s
postgres:
image: postgres:16-alpine # You can use any postgres version you prefer, but remember that some versions might not be compatible
container_name: palmr-database
environment:
- POSTGRES_USER=${POSTGRES_USER:-postgres} # PostgreSQL username (default: postgres) can be overridden by env var
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-postgresRootPassword} # PostgreSQL password (default: postgresRootPassword) can be overridden by env var
- POSTGRES_DB=${POSTGRES_DB:-palmr_db} # PostgreSQL database name (default: palmr_db) can be overridden by env var
volumes:
- postgres_data:/var/lib/postgresql/data # PostgreSQL data volume for the application
ports:
- "${DB_EXTERNAL_PORT:-5432}:5432" # PostgreSQL port (default: 5432) can be overridden by env var
networks:
- palmr-network # Network for the application to communicate with the database
restart: unless-stopped
healthcheck:
test: [
"CMD",
"pg_isready",
"-U",
"${POSTGRES_USER:-postgres}",
"-d",
"${POSTGRES_DB:-palmr_db}",
] # Healthcheck for the database
interval: 5s
timeout: 3s
retries: 6
start_period: 30s
start_period: 60s # Reduced start period since we don't need to wait for PostgreSQL
volumes:
postgres_data:
palmr_uploads:
palmr_temp_chunks:
networks:
palmr-network:
driver: bridge
palmr_database: # Volume for SQLite database persistence

View File

@@ -1,28 +1,19 @@
#!/bin/sh
echo "Starting Palmr Server..."
echo "Starting Palmr Server with SQLite..."
# Set proper environment
export HOME=/home/palmr
export NPM_CONFIG_CACHE=/home/palmr/.npm
export PNPM_HOME=/home/palmr/.pnpm
# Wait for PostgreSQL - use environment variable or default to postgres
DB_HOST=${DB_HOST:-postgres}
DB_PORT=${DB_PORT:-5432}
echo "Waiting for PostgreSQL at $DB_HOST:$DB_PORT..."
while ! nc -z $DB_HOST $DB_PORT; do
sleep 1
done
echo "PostgreSQL is up!"
cd /app/server
echo "Generating Prisma client..."
npx prisma generate --schema=./prisma/schema.prisma
echo "Running migrations..."
npx prisma migrate deploy
echo "Pushing database schema..."
npx prisma db push --accept-data-loss
echo "Running database seeds..."
node prisma/seed.js || echo "Seeds failed or already exist, continuing..."