mirror of
				https://github.com/kyantech/Palmr.git
				synced 2025-11-04 05:53:23 +00:00 
			
		
		
		
	Compare commits
	
		
			7 Commits
		
	
	
		
			v2.0.0-bet
			...
			v2.0.0-bet
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					9984a21b76 | ||
| 
						 | 
					431086a614 | ||
| 
						 | 
					d40ef51695 | ||
| 
						 | 
					8f3ad71850 | ||
| 
						 | 
					a9191d6b54 | ||
| 
						 | 
					b8465df016 | ||
| 
						 | 
					5a44d79279 | 
							
								
								
									
										70
									
								
								.dockerignore
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								.dockerignore
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,70 @@
 | 
				
			|||||||
 | 
					# Git
 | 
				
			||||||
 | 
					.git
 | 
				
			||||||
 | 
					.gitignore
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Documentation
 | 
				
			||||||
 | 
					README.md
 | 
				
			||||||
 | 
					CONTRIBUTING.md
 | 
				
			||||||
 | 
					*.md
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Node modules
 | 
				
			||||||
 | 
					node_modules
 | 
				
			||||||
 | 
					*/node_modules
 | 
				
			||||||
 | 
					**/node_modules
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Build outputs
 | 
				
			||||||
 | 
					.next
 | 
				
			||||||
 | 
					dist
 | 
				
			||||||
 | 
					build
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Development files
 | 
				
			||||||
 | 
					.env*
 | 
				
			||||||
 | 
					.vscode
 | 
				
			||||||
 | 
					.idea
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Logs
 | 
				
			||||||
 | 
					*.log
 | 
				
			||||||
 | 
					logs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Runtime data
 | 
				
			||||||
 | 
					pids
 | 
				
			||||||
 | 
					*.pid
 | 
				
			||||||
 | 
					*.seed
 | 
				
			||||||
 | 
					*.pid.lock
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Coverage directory used by tools like istanbul
 | 
				
			||||||
 | 
					coverage
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# nyc test coverage
 | 
				
			||||||
 | 
					.nyc_output
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Dependency directories
 | 
				
			||||||
 | 
					jspm_packages/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Optional npm cache directory
 | 
				
			||||||
 | 
					.npm
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Optional REPL history
 | 
				
			||||||
 | 
					.node_repl_history
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Output of 'npm pack'
 | 
				
			||||||
 | 
					*.tgz
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Yarn Integrity file
 | 
				
			||||||
 | 
					.yarn-integrity
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# dotenv environment variables file
 | 
				
			||||||
 | 
					.env
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Docker files
 | 
				
			||||||
 | 
					Dockerfile*
 | 
				
			||||||
 | 
					docker-compose*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# OS generated files
 | 
				
			||||||
 | 
					.DS_Store
 | 
				
			||||||
 | 
					.DS_Store?
 | 
				
			||||||
 | 
					._*
 | 
				
			||||||
 | 
					.Spotlight-V100
 | 
				
			||||||
 | 
					.Trashes
 | 
				
			||||||
 | 
					ehthumbs.db
 | 
				
			||||||
 | 
					Thumbs.db 
 | 
				
			||||||
							
								
								
									
										160
									
								
								Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										160
									
								
								Dockerfile
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,160 @@
 | 
				
			|||||||
 | 
					FROM node:18-alpine AS base
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Install system dependencies
 | 
				
			||||||
 | 
					RUN apk add --no-cache \
 | 
				
			||||||
 | 
					  netcat-openbsd \
 | 
				
			||||||
 | 
					  gcompat \
 | 
				
			||||||
 | 
					  supervisor \
 | 
				
			||||||
 | 
					  curl
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Enable pnpm
 | 
				
			||||||
 | 
					RUN corepack enable pnpm
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Set working directory
 | 
				
			||||||
 | 
					WORKDIR /app
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# === SERVER BUILD STAGE ===
 | 
				
			||||||
 | 
					FROM base AS server-deps
 | 
				
			||||||
 | 
					WORKDIR /app/server
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Copy server package files
 | 
				
			||||||
 | 
					COPY apps/server/package*.json ./
 | 
				
			||||||
 | 
					COPY apps/server/pnpm-lock.yaml ./
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Install server dependencies
 | 
				
			||||||
 | 
					RUN pnpm install --frozen-lockfile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FROM base AS server-builder
 | 
				
			||||||
 | 
					WORKDIR /app/server
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Copy server dependencies
 | 
				
			||||||
 | 
					COPY --from=server-deps /app/server/node_modules ./node_modules
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Copy server source code
 | 
				
			||||||
 | 
					COPY apps/server/ ./
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Generate Prisma client
 | 
				
			||||||
 | 
					RUN npx prisma generate
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Build server
 | 
				
			||||||
 | 
					RUN pnpm build
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# === WEB BUILD STAGE ===
 | 
				
			||||||
 | 
					FROM base AS web-deps
 | 
				
			||||||
 | 
					WORKDIR /app/web
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Copy web package files
 | 
				
			||||||
 | 
					COPY apps/web/package.json apps/web/pnpm-lock.yaml ./
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Install web dependencies
 | 
				
			||||||
 | 
					RUN pnpm install --frozen-lockfile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FROM base AS web-builder
 | 
				
			||||||
 | 
					WORKDIR /app/web
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Copy web dependencies
 | 
				
			||||||
 | 
					COPY --from=web-deps /app/web/node_modules ./node_modules
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Copy web source code
 | 
				
			||||||
 | 
					COPY apps/web/ ./
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Set environment variables for build
 | 
				
			||||||
 | 
					ENV NEXT_TELEMETRY_DISABLED=1
 | 
				
			||||||
 | 
					ENV NODE_ENV=production
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Build web application
 | 
				
			||||||
 | 
					RUN pnpm run build
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# === PRODUCTION STAGE ===
 | 
				
			||||||
 | 
					FROM base AS runner
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Set production environment
 | 
				
			||||||
 | 
					ENV NODE_ENV=production
 | 
				
			||||||
 | 
					ENV NEXT_TELEMETRY_DISABLED=1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Create application user
 | 
				
			||||||
 | 
					RUN addgroup --system --gid 1001 nodejs
 | 
				
			||||||
 | 
					RUN adduser --system --uid 1001 palmr
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Create application directories and set permissions
 | 
				
			||||||
 | 
					RUN mkdir -p /app/server /app/web /home/palmr/.npm /home/palmr/.cache
 | 
				
			||||||
 | 
					RUN chown -R palmr:nodejs /app /home/palmr
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# === Copy Server Files ===
 | 
				
			||||||
 | 
					WORKDIR /app/server
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Copy server production files
 | 
				
			||||||
 | 
					COPY --from=server-builder --chown=palmr:nodejs /app/server/dist ./dist
 | 
				
			||||||
 | 
					COPY --from=server-builder --chown=palmr:nodejs /app/server/node_modules ./node_modules
 | 
				
			||||||
 | 
					COPY --from=server-builder --chown=palmr:nodejs /app/server/prisma ./prisma
 | 
				
			||||||
 | 
					COPY --from=server-builder --chown=palmr:nodejs /app/server/package.json ./
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# === Copy Web Files ===
 | 
				
			||||||
 | 
					WORKDIR /app/web
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Copy web production files
 | 
				
			||||||
 | 
					COPY --from=web-builder --chown=palmr:nodejs /app/web/public ./public
 | 
				
			||||||
 | 
					COPY --from=web-builder --chown=palmr:nodejs /app/web/.next/standalone ./
 | 
				
			||||||
 | 
					COPY --from=web-builder --chown=palmr:nodejs /app/web/.next/static ./.next/static
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# === Setup Supervisor ===
 | 
				
			||||||
 | 
					WORKDIR /app
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Create supervisor configuration
 | 
				
			||||||
 | 
					RUN mkdir -p /etc/supervisor/conf.d /var/log/supervisor
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Copy server start script
 | 
				
			||||||
 | 
					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 <<EOF /etc/supervisor/conf.d/supervisord.conf
 | 
				
			||||||
 | 
					[supervisord]
 | 
				
			||||||
 | 
					nodaemon=true
 | 
				
			||||||
 | 
					user=root
 | 
				
			||||||
 | 
					logfile=/var/log/supervisor/supervisord.log
 | 
				
			||||||
 | 
					pidfile=/var/run/supervisord.pid
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[program:server]
 | 
				
			||||||
 | 
					command=/app/server-start.sh
 | 
				
			||||||
 | 
					directory=/app/server
 | 
				
			||||||
 | 
					user=palmr
 | 
				
			||||||
 | 
					autostart=true
 | 
				
			||||||
 | 
					autorestart=true
 | 
				
			||||||
 | 
					stderr_logfile=/var/log/supervisor/server.err.log
 | 
				
			||||||
 | 
					stdout_logfile=/var/log/supervisor/server.out.log
 | 
				
			||||||
 | 
					environment=PORT=3333,HOME="/home/palmr"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[program:web]
 | 
				
			||||||
 | 
					command=node server.js
 | 
				
			||||||
 | 
					directory=/app/web
 | 
				
			||||||
 | 
					user=palmr
 | 
				
			||||||
 | 
					autostart=true
 | 
				
			||||||
 | 
					autorestart=true
 | 
				
			||||||
 | 
					stderr_logfile=/var/log/supervisor/web.err.log
 | 
				
			||||||
 | 
					stdout_logfile=/var/log/supervisor/web.out.log
 | 
				
			||||||
 | 
					environment=PORT=5487,HOSTNAME="0.0.0.0",HOME="/home/palmr"
 | 
				
			||||||
 | 
					EOF
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Create main startup script
 | 
				
			||||||
 | 
					COPY <<EOF /app/start.sh
 | 
				
			||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					echo "Starting Palmr Application..."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Start supervisor
 | 
				
			||||||
 | 
					exec /usr/bin/supervisord -c /etc/supervisor/conf.d/supervisord.conf
 | 
				
			||||||
 | 
					EOF
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RUN chmod +x /app/start.sh
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Expose ports
 | 
				
			||||||
 | 
					EXPOSE 3333 5487
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Health check
 | 
				
			||||||
 | 
					HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
 | 
				
			||||||
 | 
					  CMD curl -f http://localhost:5487 || exit 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Start application
 | 
				
			||||||
 | 
					CMD ["/app/start.sh"] 
 | 
				
			||||||
							
								
								
									
										47
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,47 @@
 | 
				
			|||||||
 | 
					.PHONY: help build start clean logs stop restart
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Default target
 | 
				
			||||||
 | 
					help:
 | 
				
			||||||
 | 
						@echo "🚀 Palmr - Available Commands:"
 | 
				
			||||||
 | 
						@echo ""
 | 
				
			||||||
 | 
						@echo "  make build     - Build Docker image with multi-platform support"
 | 
				
			||||||
 | 
						@echo "  make start     - Start the application using docker-compose"
 | 
				
			||||||
 | 
						@echo "  make stop      - Stop all running containers"
 | 
				
			||||||
 | 
						@echo "  make logs      - Show application logs"
 | 
				
			||||||
 | 
						@echo "  make clean     - Clean up containers and images"
 | 
				
			||||||
 | 
						@echo "  make shell     - Access the application container shell"
 | 
				
			||||||
 | 
						@echo ""
 | 
				
			||||||
 | 
						@echo "📁 Scripts location: ./infra/"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Build Docker image using the build script
 | 
				
			||||||
 | 
					build:
 | 
				
			||||||
 | 
						@echo "🏗️  Building Palmr Docker image..."
 | 
				
			||||||
 | 
						@chmod +x ./infra/build-docker.sh
 | 
				
			||||||
 | 
						@./infra/build-docker.sh
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Start the application
 | 
				
			||||||
 | 
					start:
 | 
				
			||||||
 | 
						@echo "🚀 Starting Palmr application..."
 | 
				
			||||||
 | 
						@docker-compose up -d
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Stop the application
 | 
				
			||||||
 | 
					stop:
 | 
				
			||||||
 | 
						@echo "🛑 Stopping Palmr application..."
 | 
				
			||||||
 | 
						@docker-compose down
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Show logs
 | 
				
			||||||
 | 
					logs:
 | 
				
			||||||
 | 
						@echo "📋 Showing Palmr logs..."
 | 
				
			||||||
 | 
						@docker-compose logs -f
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Clean up containers and images
 | 
				
			||||||
 | 
					clean:
 | 
				
			||||||
 | 
						@echo "🧹 Cleaning up Docker containers and images..."
 | 
				
			||||||
 | 
						@docker-compose down -v
 | 
				
			||||||
 | 
						@docker system prune -f
 | 
				
			||||||
 | 
						@echo "✅ Cleanup completed!"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Access container shell
 | 
				
			||||||
 | 
					shell:
 | 
				
			||||||
 | 
						@echo "🐚 Accessing Palmr container shell..."
 | 
				
			||||||
 | 
						@docker-compose exec palmr /bin/sh
 | 
				
			||||||
@@ -29,18 +29,19 @@ Below is the complete content of our `docker-compose.yaml` that can be copied di
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
```yaml
 | 
					```yaml
 | 
				
			||||||
services:
 | 
					services:
 | 
				
			||||||
  palmr-api:
 | 
					  palmr:
 | 
				
			||||||
    image: kyantech/palmr-api:latest # Make sure to use the correct version (latest) of the image
 | 
					    image: kyantech/palmr:latest # Make sure to use the correct version (latest) of the image
 | 
				
			||||||
    container_name: palmr-api
 | 
					    container_name: palmr
 | 
				
			||||||
    depends_on:
 | 
					    depends_on:
 | 
				
			||||||
      postgres:
 | 
					      postgres:
 | 
				
			||||||
        condition: "service_healthy"
 | 
					        condition: "service_healthy"
 | 
				
			||||||
      minio:
 | 
					      minio:
 | 
				
			||||||
        condition: "service_healthy"
 | 
					        condition: "service_healthy"
 | 
				
			||||||
    environment:
 | 
					    environment:
 | 
				
			||||||
 | 
					      # Server environment variables
 | 
				
			||||||
      - PORT=${API_INTERNAL_PORT:-3333} # Port for the backend service
 | 
					      - PORT=${API_INTERNAL_PORT:-3333} # Port for the backend service
 | 
				
			||||||
      - DATABASE_URL=postgresql://postgres:${POSTGRES_PASSWORD:-postgresRootPassword}@postgres:5432/palmr_db?schema=public # Database URL with configurable password through POSTGRES_PASSWORD env var
 | 
					      - DATABASE_URL=postgresql://postgres:${POSTGRESQL_PASSWORD:-postgresRootPassword}@postgres:5432/palmr_db?schema=public # Database URL with configurable password through POSTGRESQL_PASSWORD env var
 | 
				
			||||||
      - MINIO_ENDPOINT=minio # This can change if your MinIO is at a different address
 | 
					      - MINIO_ENDPOINT=${MINIO_ENDPOINT:-minio} # This can change if your MinIO is at a different address
 | 
				
			||||||
      - MINIO_PORT=${MINIO_INTERNAL_API_PORT:-6421} # Default MinIO port (Change if yours is not the default)
 | 
					      - MINIO_PORT=${MINIO_INTERNAL_API_PORT:-6421} # Default MinIO port (Change if yours is not the default)
 | 
				
			||||||
      - MINIO_USE_SSL=false # MinIO uses SSL by default, but you can change it to true if needed
 | 
					      - MINIO_USE_SSL=false # MinIO uses SSL by default, but you can change it to true if needed
 | 
				
			||||||
      - MINIO_ROOT_USER=${MINIO_ROOT_USER:-minio_root_user} # MinIO credentials can be configured through MINIO_ROOT_USER env vars
 | 
					      - MINIO_ROOT_USER=${MINIO_ROOT_USER:-minio_root_user} # MinIO credentials can be configured through MINIO_ROOT_USER env vars
 | 
				
			||||||
@@ -50,34 +51,21 @@ services:
 | 
				
			|||||||
      - FRONTEND_URL=${APP_URL:-http://${SERVER_IP:-localhost}:${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
 | 
					      - FRONTEND_URL=${APP_URL:-http://${SERVER_IP:-localhost}:${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
 | 
				
			||||||
      - SERVER_IP=${SERVER_IP:-localhost} # Server IP - Make sure to use the correct server IP if you running on a cloud provider or a virtual machine. This prepared for localhost, but you can change it to your server IP if needed
 | 
					      - SERVER_IP=${SERVER_IP:-localhost} # Server IP - Make sure to use the correct server IP if you running on a cloud provider or a virtual machine. This prepared for localhost, but you can change it to your server IP if needed
 | 
				
			||||||
      - MAX_FILESIZE=${MAX_FILESIZE:-1073741824} # Max Filesize for upload - Declared in Bytes. Default is 1GiB
 | 
					      - MAX_FILESIZE=${MAX_FILESIZE:-1073741824} # Max Filesize for upload - Declared in Bytes. Default is 1GiB
 | 
				
			||||||
    ports:
 | 
					      
 | 
				
			||||||
      - "${API_EXTERNAL_PORT:-3333}:${API_INTERNAL_PORT:-3333}" # Backend port mapping 
 | 
					      # Web environment variables
 | 
				
			||||||
    restart: unless-stopped
 | 
					 | 
				
			||||||
    healthcheck:
 | 
					 | 
				
			||||||
      test: ["CMD", "curl", "-f", "http://localhost:${API_INTERNAL_PORT:-3333}/health"]
 | 
					 | 
				
			||||||
      interval: 10s
 | 
					 | 
				
			||||||
      timeout: 5s
 | 
					 | 
				
			||||||
      retries: 5
 | 
					 | 
				
			||||||
      start_period: 30s
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  palmr-app:
 | 
					 | 
				
			||||||
    image: kyantech/palmr-app:latest # Make sure to use the correct version (latest) of the image
 | 
					 | 
				
			||||||
    container_name: palmr-web
 | 
					 | 
				
			||||||
    depends_on:
 | 
					 | 
				
			||||||
      palmr-api:
 | 
					 | 
				
			||||||
        condition: "service_healthy"
 | 
					 | 
				
			||||||
    ports:
 | 
					 | 
				
			||||||
      - "${APP_EXTERNAL_PORT:-5487}:5487" # Frontend port mapping
 | 
					 | 
				
			||||||
    environment:
 | 
					 | 
				
			||||||
      - NODE_ENV=production
 | 
					      - NODE_ENV=production
 | 
				
			||||||
      - NEXT_TELEMETRY_DISABLED=1
 | 
					      - NEXT_TELEMETRY_DISABLED=1
 | 
				
			||||||
      - API_BASE_URL=http://palmr-api:${API_INTERNAL_PORT:-3333} # Here we use docker's internal network to reference the backend service (can be changed if needed)
 | 
					      - API_BASE_URL=http://palmr:${API_INTERNAL_PORT:-3333} # Using Docker service name for internal communication
 | 
				
			||||||
 | 
					    ports:
 | 
				
			||||||
 | 
					      - "${API_EXTERNAL_PORT:-3333}:3333"  # Server port
 | 
				
			||||||
 | 
					      - "${APP_EXTERNAL_PORT:-5487}:5487"  # Web port
 | 
				
			||||||
    restart: unless-stopped
 | 
					    restart: unless-stopped
 | 
				
			||||||
    healthcheck:
 | 
					    healthcheck:
 | 
				
			||||||
      test: ["CMD", "curl", "-f", "http://localhost:5487"]
 | 
					      test: ["CMD", "wget", "--no-verbose", "http://palmr:${API_INTERNAL_PORT:-3333}/health", "&&", "wget", "--no-verbose", "http://palmr:${APP_INTERNAL_PORT:-5487}"]
 | 
				
			||||||
      interval: 30s
 | 
					      interval: 30s
 | 
				
			||||||
      timeout: 10s
 | 
					      timeout: 10s
 | 
				
			||||||
      retries: 3
 | 
					      retries: 3
 | 
				
			||||||
 | 
					      start_period: 60s
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  minio:
 | 
					  minio:
 | 
				
			||||||
    image: minio/minio:RELEASE.2025-03-12T18-04-18Z # Use only version RELEASE.2025-03-12T18-04-18Z to avoid compatibility issues with the backend
 | 
					    image: minio/minio:RELEASE.2025-03-12T18-04-18Z # Use only version RELEASE.2025-03-12T18-04-18Z to avoid compatibility issues with the backend
 | 
				
			||||||
@@ -121,10 +109,10 @@ services:
 | 
				
			|||||||
    container_name: palmr-postgres
 | 
					    container_name: palmr-postgres
 | 
				
			||||||
    environment:
 | 
					    environment:
 | 
				
			||||||
      # PostgreSQL credentials configurable through environment variables
 | 
					      # PostgreSQL credentials configurable through environment variables
 | 
				
			||||||
      # POSTGRES_USER, POSTGRES_PASSWORD, and POSTGRES_DB can be set to override defaults
 | 
					      # POSTGRESQL_USERNAME, POSTGRESQL_PASSWORD, and POSTGRES_DB can be set to override defaults
 | 
				
			||||||
      - POSTGRESQL_USERNAME=${POSTGRES_USER:-postgres}
 | 
					      - POSTGRESQL_USERNAME=${POSTGRESQL_USERNAME:-postgres}
 | 
				
			||||||
      - POSTGRESQL_PASSWORD=${POSTGRES_PASSWORD:-postgresRootPassword}
 | 
					      - POSTGRESQL_PASSWORD=${POSTGRESQL_PASSWORD:-postgresRootPassword}
 | 
				
			||||||
      - POSTGRESQL_DATABASE=${POSTGRES_DB:-palmr_db}
 | 
					      - POSTGRESQL_DATABASE=${POSTGRES_DATABASE:-palmr_db}
 | 
				
			||||||
    volumes:
 | 
					    volumes:
 | 
				
			||||||
      - postgres_data:/bitnami/postgresql
 | 
					      - postgres_data:/bitnami/postgresql
 | 
				
			||||||
    ports:
 | 
					    ports:
 | 
				
			||||||
@@ -138,7 +126,7 @@ services:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
volumes:
 | 
					volumes:
 | 
				
			||||||
  minio_data:
 | 
					  minio_data:
 | 
				
			||||||
  postgres_data:
 | 
					  postgres_data: 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -148,12 +136,11 @@ Notice that the `docker-compose.yaml` has several comments that help you configu
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
### ⚙️ Services Overview
 | 
					### ⚙️ Services Overview
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Palmr. consists of five main services, each with specific responsibilities. Below, we present a detailed view of each component:
 | 
					Palmr. consists of four main services, each with specific responsibilities. Below, we present a detailed view of each component:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| **Service** | **Image** | **Exposed Ports** | **Main Features** |
 | 
					| **Service** | **Image** | **Exposed Ports** | **Main Features** |
 | 
				
			||||||
| --- | --- | --- | --- |
 | 
					| --- | --- | --- | --- |
 | 
				
			||||||
| palmr-api (Backend) | [kyantech/palmr-api:latest](https://hub.docker.com/repository/docker/kyantech/palmr-api/tags/latest/sha256-84245d3d0012aa65c588caba56322363729c4b68c3722a08dcda912904de9d1d) | **3333** | • Main API service<br/>• Depends on services: postgres and minio<br/>• Has healthcheck to ensure availability |
 | 
					| palmr | [kyantech/palmr:latest](https://hub.docker.com/repository/docker/kyantech/palmr/general) | **3333** (API)<br/>**5487** (Web) | • Combined backend API and frontend service<br/>• Depends on services: postgres and minio<br/>• Has healthcheck to ensure availability |
 | 
				
			||||||
| palmr-app (Frontend) | [kyantech/palmr-app:latest](https://hub.docker.com/repository/docker/kyantech/palmr-app/tags/latest/sha256-33f568673ae8cc8529532146b6afc1acafa203387ced6c7bb3451a7ab4198a2f) | **5487** | • Web application interface<br/>• Depends on palmr-api service<br/>• Configured for production environment |
 | 
					 | 
				
			||||||
| minio (Storage) | [minio/minio:RELEASE.2025-03-12T18-04-18Z](https://hub.docker.com/layers/minio/minio/RELEASE.2025-03-12T18-04-18Z/images/sha256-85f3e4cd1ca92a2711553ab79f222bcd8b75aa2c77a1a0b0ccf80d38e8ab2fe5) | **6421**(API)<br/>**6422**(Console) | • File storage service<br/>• Persistent volume for data |
 | 
					| minio (Storage) | [minio/minio:RELEASE.2025-03-12T18-04-18Z](https://hub.docker.com/layers/minio/minio/RELEASE.2025-03-12T18-04-18Z/images/sha256-85f3e4cd1ca92a2711553ab79f222bcd8b75aa2c77a1a0b0ccf80d38e8ab2fe5) | **6421**(API)<br/>**6422**(Console) | • File storage service<br/>• Persistent volume for data |
 | 
				
			||||||
| minio-init (Config) | [minio/mc:RELEASE.2025-03-12T17-29-24Z](https://hub.docker.com/layers/minio/mc/RELEASE.2025-03-12T17-29-24Z/images/sha256-68d8c80f43908b02daa285e55547131870a1d36b3ffe272c26d7d8f4d52d1e5c) | N/A | • Initially configures the "files" bucket<br/>• Runs only once during initialization |
 | 
					| minio-init (Config) | [minio/mc:RELEASE.2025-03-12T17-29-24Z](https://hub.docker.com/layers/minio/mc/RELEASE.2025-03-12T17-29-24Z/images/sha256-68d8c80f43908b02daa285e55547131870a1d36b3ffe272c26d7d8f4d52d1e5c) | N/A | • Initially configures the "files" bucket<br/>• Runs only once during initialization |
 | 
				
			||||||
| postgres (Database) | [bitnami/postgresql:17.2.0](https://hub.docker.com/layers/bitnami/postgresql/17.2.0/images/sha256-29c614afad4f514b12b5c0f4d006f38c98fa4b18c3582732ff93b3fe9a79d875) | **5432** | • PostgreSQL database<br/>• Persistent volume for data |
 | 
					| postgres (Database) | [bitnami/postgresql:17.2.0](https://hub.docker.com/layers/bitnami/postgresql/17.2.0/images/sha256-29c614afad4f514b12b5c0f4d006f38c98fa4b18c3582732ff93b3fe9a79d875) | **5432** | • PostgreSQL database<br/>• Persistent volume for data |
 | 
				
			||||||
@@ -197,13 +184,17 @@ The table below shows all environment variables that can be set
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
In a localhost environment, there's no mystery. If you don't want to change any service exposure ports, you can simply run:
 | 
					In a localhost environment, there's no mystery. If you don't want to change any service exposure ports, you can simply run:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```bash
 | 
				
			||||||
 | 
					docker compose pull && docker compose up -d
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
This will execute all necessary services and give you access to the following URLs (if you haven't changed any ports):
 | 
					This will execute all necessary services and give you access to the following URLs (if you haven't changed any ports):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- **Frontend:** [http://localhost:5487](http://localhost:5487)
 | 
					- **Frontend:** [http://localhost:5487](http://localhost:5487)
 | 
				
			||||||
- **Backend:** [http://localhost:3333](http://localhost:3333/)
 | 
					- **Backend:** [http://localhost:3333](http://localhost:3333/)
 | 
				
			||||||
- **MinIO API:** [http://localhost:6421](http://localhost:6421)
 | 
					- **MinIO API:** [http://localhost:6421](http://localhost:6421)
 | 
				
			||||||
- **MinIO Console:** [http://localhost:6422](http://localhost:6422)
 | 
					- **MinIO Console:** [http://localhost:6422](http://localhost:6422)
 | 
				
			||||||
- **Postgres Database:** [http://localhost:5423](http://localhost:5423/) (Connection only)
 | 
					- **Postgres Database:** [http://localhost:5432](http://localhost:5432/) (Connection only)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
> *If you have changed any port, simply access the URL with the port you configured.*
 | 
					> *If you have changed any port, simply access the URL with the port you configured.*
 | 
				
			||||||
> 
 | 
					> 
 | 
				
			||||||
@@ -247,7 +238,7 @@ If you haven't changed the execution ports, you'll have access on your server at
 | 
				
			|||||||
- **Backend:** `[server_ip]:3333`
 | 
					- **Backend:** `[server_ip]:3333`
 | 
				
			||||||
- **MinIO API:** `[server_ip]:6421`
 | 
					- **MinIO API:** `[server_ip]:6421`
 | 
				
			||||||
- **MinIO Console:** `[server_ip]:6422`
 | 
					- **MinIO Console:** `[server_ip]:6422`
 | 
				
			||||||
- **Postgres Database:** `[server_ip]:5423` (Connection only)
 | 
					- **Postgres Database:** `[server_ip]:5432` (Connection only)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
> *If you've changed any port, simply access the URL with the port you configured.*
 | 
					> *If you've changed any port, simply access the URL with the port you configured.*
 | 
				
			||||||
> 
 | 
					> 
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -25,4 +25,4 @@
 | 
				
			|||||||
    "gh-sponsor",
 | 
					    "gh-sponsor",
 | 
				
			||||||
    "..."
 | 
					    "..."
 | 
				
			||||||
  ]
 | 
					  ]
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -83,7 +83,12 @@ export default function HomePage() {
 | 
				
			|||||||
function Hero() {
 | 
					function Hero() {
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <section className="relative z-[2] flex flex-col border-x border-t  px-6 pt-12 pb-10 md:px-12 md:pt-16 max-md:text-center">
 | 
					    <section className="relative z-[2] flex flex-col border-x border-t  px-6 pt-12 pb-10 md:px-12 md:pt-16 max-md:text-center">
 | 
				
			||||||
      <h1 className="mb-8 text-5xl font-bold">🌴 Palmr. <span className="text-[10px] font-light text-muted-foreground/50 font-mono">v2.0.0-beta</span></h1>
 | 
					      <h1 className="mb-8 text-5xl font-bold">
 | 
				
			||||||
 | 
					        🌴 Palmr.{" "}
 | 
				
			||||||
 | 
					        <span className="text-[10px] font-light text-muted-foreground/50 font-mono">
 | 
				
			||||||
 | 
					          v2.0.0-beta
 | 
				
			||||||
 | 
					        </span>
 | 
				
			||||||
 | 
					      </h1>
 | 
				
			||||||
      <h1 className="hidden text-4xl font-medium max-w-[600px] md:block mb-4">
 | 
					      <h1 className="hidden text-4xl font-medium max-w-[600px] md:block mb-4">
 | 
				
			||||||
        Modern & efficient file sharing
 | 
					        Modern & efficient file sharing
 | 
				
			||||||
      </h1>
 | 
					      </h1>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
import { source } from '@/lib/source';
 | 
					import { source } from "@/lib/source";
 | 
				
			||||||
import { createFromSource } from 'fumadocs-core/search/server';
 | 
					import { createFromSource } from "fumadocs-core/search/server";
 | 
				
			||||||
 
 | 
					
 | 
				
			||||||
export const { GET } = createFromSource(source, (page) => {
 | 
					export const { GET } = createFromSource(source, (page) => {
 | 
				
			||||||
  return {
 | 
					  return {
 | 
				
			||||||
    title: page.data.title,
 | 
					    title: page.data.title,
 | 
				
			||||||
@@ -8,6 +8,8 @@ export const { GET } = createFromSource(source, (page) => {
 | 
				
			|||||||
    url: page.url,
 | 
					    url: page.url,
 | 
				
			||||||
    id: page.url,
 | 
					    id: page.url,
 | 
				
			||||||
    structuredData: page.data.structuredData,
 | 
					    structuredData: page.data.structuredData,
 | 
				
			||||||
    tag: page.url.startsWith('/docs/2.0.0-beta') ? 'v2.0.0-beta' : 'v1.1.7-beta'
 | 
					    tag: page.url.startsWith("/docs/2.0.0-beta")
 | 
				
			||||||
 | 
					      ? "v2.0.0-beta"
 | 
				
			||||||
 | 
					      : "v1.1.7-beta",
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,14 +11,15 @@ const inter = Inter({
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
export const metadata = {
 | 
					export const metadata = {
 | 
				
			||||||
  title: "🌴 Palmr. | Official Website",
 | 
					  title: "🌴 Palmr. | Official Website",
 | 
				
			||||||
  description: "Palmr. is a fast, simple and powerful document sharing platform.",
 | 
					  description:
 | 
				
			||||||
 | 
					    "Palmr. is a fast, simple and powerful document sharing platform.",
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default function Layout({ children }: { children: ReactNode }) {
 | 
					export default function Layout({ children }: { children: ReactNode }) {
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <html lang="en" className={inter.className} suppressHydrationWarning>
 | 
					    <html lang="en" className={inter.className} suppressHydrationWarning>
 | 
				
			||||||
      <body className="flex flex-col min-h-screen">
 | 
					      <body className="flex flex-col min-h-screen">
 | 
				
			||||||
        <Banner variant="rainbow" id="banner-v-2">
 | 
					        <Banner variant="rainbow" id="banner-v-3">
 | 
				
			||||||
          <Link href="/docs/2.0.0-beta">Palmr. v2.0.0-beta has released!</Link>
 | 
					          <Link href="/docs/2.0.0-beta">Palmr. v2.0.0-beta has released!</Link>
 | 
				
			||||||
        </Banner>
 | 
					        </Banner>
 | 
				
			||||||
        <RootProvider
 | 
					        <RootProvider
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,7 +11,10 @@
 | 
				
			|||||||
    "lint:fix": "eslint \"src/**/*.{js,jsx,ts,tsx}\" --fix",
 | 
					    "lint:fix": "eslint \"src/**/*.{js,jsx,ts,tsx}\" --fix",
 | 
				
			||||||
    "format": "prettier . --write",
 | 
					    "format": "prettier . --write",
 | 
				
			||||||
    "format:check": "prettier . --check",
 | 
					    "format:check": "prettier . --check",
 | 
				
			||||||
    "db:seed": "ts-node prisma/seed.ts"
 | 
					    "db:seed": "ts-node prisma/seed.js"
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "prisma": {
 | 
				
			||||||
 | 
					    "seed": "node prisma/seed.js"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "keywords": [],
 | 
					  "keywords": [],
 | 
				
			||||||
  "author": "",
 | 
					  "author": "",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,8 @@
 | 
				
			|||||||
import { prisma } from "../src/shared/prisma";
 | 
					/* eslint-disable no-undef */
 | 
				
			||||||
import crypto from "node:crypto";
 | 
					const { PrismaClient } = require('@prisma/client');
 | 
				
			||||||
import { env } from '../src/env';
 | 
					const crypto = require('crypto');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const prisma = new PrismaClient();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const defaultConfigs = [
 | 
					const defaultConfigs = [
 | 
				
			||||||
  // General Configurations
 | 
					  // General Configurations
 | 
				
			||||||
@@ -37,7 +39,7 @@ const defaultConfigs = [
 | 
				
			|||||||
  // Storage Configurations
 | 
					  // Storage Configurations
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
    key: "maxFileSize",
 | 
					    key: "maxFileSize",
 | 
				
			||||||
    value: env.MAX_FILESIZE, // default 1GiB in bytes - 1073741824
 | 
					    value: process.env.MAX_FILESIZE || "1073741824", // default 1GiB in bytes
 | 
				
			||||||
    type: "bigint",
 | 
					    type: "bigint",
 | 
				
			||||||
    group: "storage",
 | 
					    group: "storage",
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
@@ -124,28 +126,37 @@ const defaultConfigs = [
 | 
				
			|||||||
];
 | 
					];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async function main() {
 | 
					async function main() {
 | 
				
			||||||
  console.log("Seeding app configurations...");
 | 
					  console.log("🌱 Starting app configurations seed...");
 | 
				
			||||||
 | 
					  console.log("🛡️  Protected mode: Only creates missing configurations");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  let createdCount = 0;
 | 
				
			||||||
 | 
					  let skippedCount = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  for (const config of defaultConfigs) {
 | 
					  for (const config of defaultConfigs) {
 | 
				
			||||||
    if (config.key === "jwtSecret") {
 | 
					    // Check if configuration already exists
 | 
				
			||||||
      const existingSecret = await prisma.appConfig.findUnique({
 | 
					    const existingConfig = await prisma.appConfig.findUnique({
 | 
				
			||||||
        where: { key: "jwtSecret" },
 | 
					      where: { key: config.key },
 | 
				
			||||||
      });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      if (existingSecret) {
 | 
					    if (existingConfig) {
 | 
				
			||||||
        console.log("JWT secret already exists, skipping...");
 | 
					      console.log(`⏭️  Configuration '${config.key}' already exists, skipping...`);
 | 
				
			||||||
        continue;
 | 
					      skippedCount++;
 | 
				
			||||||
      }
 | 
					      continue;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    await prisma.appConfig.upsert({
 | 
					    // Only create if it doesn't exist
 | 
				
			||||||
      where: { key: config.key },
 | 
					    await prisma.appConfig.create({
 | 
				
			||||||
      update: config,
 | 
					      data: config,
 | 
				
			||||||
      create: config,
 | 
					 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    console.log(`✅ Created configuration: ${config.key}`);
 | 
				
			||||||
 | 
					    createdCount++;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  console.log("App configurations seeded successfully!");
 | 
					  console.log("\n📊 Seed Summary:");
 | 
				
			||||||
 | 
					  console.log(`   ✅ Created: ${createdCount} configurations`);
 | 
				
			||||||
 | 
					  console.log(`   ⏭️  Skipped: ${skippedCount} configurations`);
 | 
				
			||||||
 | 
					  console.log("🎉 App configurations seeded successfully!");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
main()
 | 
					main()
 | 
				
			||||||
@@ -155,4 +166,4 @@ main()
 | 
				
			|||||||
  })
 | 
					  })
 | 
				
			||||||
  .finally(async () => {
 | 
					  .finally(async () => {
 | 
				
			||||||
    await prisma.$disconnect();
 | 
					    await prisma.$disconnect();
 | 
				
			||||||
  });
 | 
					  }); 
 | 
				
			||||||
@@ -1,17 +0,0 @@
 | 
				
			|||||||
import { PrismaClient } from '@prisma/client';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const prisma = new PrismaClient();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
async function main() {
 | 
					 | 
				
			||||||
  const count = await prisma.user.count();
 | 
					 | 
				
			||||||
  console.log(count);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
main()
 | 
					 | 
				
			||||||
  .catch((e) => {
 | 
					 | 
				
			||||||
    console.error(e);
 | 
					 | 
				
			||||||
    process.exit(1);
 | 
					 | 
				
			||||||
  })
 | 
					 | 
				
			||||||
  .finally(async () => {
 | 
					 | 
				
			||||||
    await prisma.$disconnect();
 | 
					 | 
				
			||||||
  });
 | 
					 | 
				
			||||||
@@ -1,27 +0,0 @@
 | 
				
			|||||||
#!/bin/sh
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
echo "Waiting for PostgreSQL..."
 | 
					 | 
				
			||||||
while ! nc -z postgres 5432; do
 | 
					 | 
				
			||||||
  sleep 1
 | 
					 | 
				
			||||||
done
 | 
					 | 
				
			||||||
echo "PostgreSQL is up!"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
echo "Generating Prisma client..."
 | 
					 | 
				
			||||||
npx prisma generate --schema=./prisma/schema.prisma
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Check if database needs migrations
 | 
					 | 
				
			||||||
echo "Checking migrations..."
 | 
					 | 
				
			||||||
npx prisma migrate deploy
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Check if database is empty using Prisma
 | 
					 | 
				
			||||||
USER_COUNT=$(node ./scripts/check-db.mjs)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
if [ "$USER_COUNT" -eq "0" ]; then
 | 
					 | 
				
			||||||
    echo "Database is empty, running seeds..."
 | 
					 | 
				
			||||||
    pnpm db:seed
 | 
					 | 
				
			||||||
else
 | 
					 | 
				
			||||||
    echo "Database already has data, skipping seeds..."
 | 
					 | 
				
			||||||
fi
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
echo "Starting application..."
 | 
					 | 
				
			||||||
pnpm start
 | 
					 | 
				
			||||||
@@ -1,16 +1,17 @@
 | 
				
			|||||||
services:
 | 
					services:
 | 
				
			||||||
  palmr-api:
 | 
					  palmr:
 | 
				
			||||||
    image: kyantech/palmr-api:latest # Make sure to use the correct version (latest) of the image
 | 
					    image: kyantech/palmr:latest # Make sure to use the correct version (latest) of the image
 | 
				
			||||||
    container_name: palmr-api
 | 
					    container_name: palmr
 | 
				
			||||||
    depends_on:
 | 
					    depends_on:
 | 
				
			||||||
      postgres:
 | 
					      postgres:
 | 
				
			||||||
        condition: "service_healthy"
 | 
					        condition: "service_healthy"
 | 
				
			||||||
      minio:
 | 
					      minio:
 | 
				
			||||||
        condition: "service_healthy"
 | 
					        condition: "service_healthy"
 | 
				
			||||||
    environment:
 | 
					    environment:
 | 
				
			||||||
 | 
					      # Server environment variables
 | 
				
			||||||
      - PORT=${API_INTERNAL_PORT:-3333} # Port for the backend service
 | 
					      - PORT=${API_INTERNAL_PORT:-3333} # Port for the backend service
 | 
				
			||||||
      - DATABASE_URL=postgresql://postgres:${POSTGRESQL_PASSWORD:-postgresRootPassword}@postgres:5432/palmr_db?schema=public # Database URL with configurable password through POSTGRESQL_PASSWORD env var
 | 
					      - DATABASE_URL=postgresql://postgres:${POSTGRESQL_PASSWORD:-postgresRootPassword}@postgres:5432/palmr_db?schema=public # Database URL with configurable password through POSTGRESQL_PASSWORD env var
 | 
				
			||||||
      - MINIO_ENDPOINT=minio # This can change if your MinIO is at a different address
 | 
					      - MINIO_ENDPOINT=${MINIO_ENDPOINT:-minio} # This can change if your MinIO is at a different address
 | 
				
			||||||
      - MINIO_PORT=${MINIO_INTERNAL_API_PORT:-6421} # Default MinIO port (Change if yours is not the default)
 | 
					      - MINIO_PORT=${MINIO_INTERNAL_API_PORT:-6421} # Default MinIO port (Change if yours is not the default)
 | 
				
			||||||
      - MINIO_USE_SSL=false # MinIO uses SSL by default, but you can change it to true if needed
 | 
					      - MINIO_USE_SSL=false # MinIO uses SSL by default, but you can change it to true if needed
 | 
				
			||||||
      - MINIO_ROOT_USER=${MINIO_ROOT_USER:-minio_root_user} # MinIO credentials can be configured through MINIO_ROOT_USER env vars
 | 
					      - MINIO_ROOT_USER=${MINIO_ROOT_USER:-minio_root_user} # MinIO credentials can be configured through MINIO_ROOT_USER env vars
 | 
				
			||||||
@@ -20,34 +21,21 @@ services:
 | 
				
			|||||||
      - FRONTEND_URL=${APP_URL:-http://${SERVER_IP:-localhost}:${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
 | 
					      - FRONTEND_URL=${APP_URL:-http://${SERVER_IP:-localhost}:${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
 | 
				
			||||||
      - SERVER_IP=${SERVER_IP:-localhost} # Server IP - Make sure to use the correct server IP if you running on a cloud provider or a virtual machine. This prepared for localhost, but you can change it to your server IP if needed
 | 
					      - SERVER_IP=${SERVER_IP:-localhost} # Server IP - Make sure to use the correct server IP if you running on a cloud provider or a virtual machine. This prepared for localhost, but you can change it to your server IP if needed
 | 
				
			||||||
      - MAX_FILESIZE=${MAX_FILESIZE:-1073741824} # Max Filesize for upload - Declared in Bytes. Default is 1GiB
 | 
					      - MAX_FILESIZE=${MAX_FILESIZE:-1073741824} # Max Filesize for upload - Declared in Bytes. Default is 1GiB
 | 
				
			||||||
    ports:
 | 
					      
 | 
				
			||||||
      - "${API_EXTERNAL_PORT:-3333}:${API_INTERNAL_PORT:-3333}" # Backend port mapping 
 | 
					      # Web environment variables
 | 
				
			||||||
    restart: unless-stopped
 | 
					 | 
				
			||||||
    healthcheck:
 | 
					 | 
				
			||||||
      test: ["CMD", "curl", "-f", "http://localhost:${API_INTERNAL_PORT:-3333}/health"]
 | 
					 | 
				
			||||||
      interval: 10s
 | 
					 | 
				
			||||||
      timeout: 5s
 | 
					 | 
				
			||||||
      retries: 5
 | 
					 | 
				
			||||||
      start_period: 30s
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  palmr-app:
 | 
					 | 
				
			||||||
    image: kyantech/palmr-app:latest # Make sure to use the correct version (latest) of the image
 | 
					 | 
				
			||||||
    container_name: palmr-web
 | 
					 | 
				
			||||||
    depends_on:
 | 
					 | 
				
			||||||
      palmr-api:
 | 
					 | 
				
			||||||
        condition: "service_healthy"
 | 
					 | 
				
			||||||
    ports:
 | 
					 | 
				
			||||||
      - "${APP_EXTERNAL_PORT:-5487}:5487" # Frontend port mapping
 | 
					 | 
				
			||||||
    environment:
 | 
					 | 
				
			||||||
      - NODE_ENV=production
 | 
					      - NODE_ENV=production
 | 
				
			||||||
      - NEXT_TELEMETRY_DISABLED=1
 | 
					      - NEXT_TELEMETRY_DISABLED=1
 | 
				
			||||||
      - API_BASE_URL=http://palmr-api:${API_INTERNAL_PORT:-3333} # Here we use docker's internal network to reference the backend service (can be changed if needed)
 | 
					      - API_BASE_URL=http://palmr:${API_INTERNAL_PORT:-3333} # Using Docker service name for internal communication
 | 
				
			||||||
 | 
					    ports:
 | 
				
			||||||
 | 
					      - "${API_EXTERNAL_PORT:-3333}:3333"  # Server port
 | 
				
			||||||
 | 
					      - "${APP_EXTERNAL_PORT:-5487}:5487"  # Web port
 | 
				
			||||||
    restart: unless-stopped
 | 
					    restart: unless-stopped
 | 
				
			||||||
    healthcheck:
 | 
					    healthcheck:
 | 
				
			||||||
      test: ["CMD", "curl", "-f", "http://localhost:5487"]
 | 
					      test: ["CMD", "wget", "--no-verbose", "http://palmr:${API_INTERNAL_PORT:-3333}/health", "&&", "wget", "--no-verbose", "http://palmr:${APP_INTERNAL_PORT:-5487}"]
 | 
				
			||||||
      interval: 30s
 | 
					      interval: 30s
 | 
				
			||||||
      timeout: 10s
 | 
					      timeout: 10s
 | 
				
			||||||
      retries: 3
 | 
					      retries: 3
 | 
				
			||||||
 | 
					      start_period: 60s
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  minio:
 | 
					  minio:
 | 
				
			||||||
    image: minio/minio:RELEASE.2025-03-12T18-04-18Z # Use only version RELEASE.2025-03-12T18-04-18Z to avoid compatibility issues with the backend
 | 
					    image: minio/minio:RELEASE.2025-03-12T18-04-18Z # Use only version RELEASE.2025-03-12T18-04-18Z to avoid compatibility issues with the backend
 | 
				
			||||||
@@ -108,4 +96,4 @@ services:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
volumes:
 | 
					volumes:
 | 
				
			||||||
  minio_data:
 | 
					  minio_data:
 | 
				
			||||||
  postgres_data:
 | 
					  postgres_data: 
 | 
				
			||||||
							
								
								
									
										33
									
								
								infra/SCRIPTS.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								infra/SCRIPTS.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,33 @@
 | 
				
			|||||||
 | 
					## 🚀 Quick Start
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Palmr. includes a convenient Makefile to simplify development and deployment tasks:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```bash
 | 
				
			||||||
 | 
					# Show all available commands
 | 
				
			||||||
 | 
					make help
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Build Docker image with multi-platform support
 | 
				
			||||||
 | 
					make build
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Start the application
 | 
				
			||||||
 | 
					make start
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# View application logs
 | 
				
			||||||
 | 
					make logs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Stop the application
 | 
				
			||||||
 | 
					make stop
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Clean up containers and images
 | 
				
			||||||
 | 
					make clean
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Available Commands:
 | 
				
			||||||
 | 
					- `make build` - Build Docker image using the build script in `./infra/`
 | 
				
			||||||
 | 
					- `make start` - Start the application using docker-compose
 | 
				
			||||||
 | 
					- `make stop` - Stop all running containers
 | 
				
			||||||
 | 
					- `make logs` - Show application logs
 | 
				
			||||||
 | 
					- `make clean` - Clean up containers and images
 | 
				
			||||||
 | 
					- `make shell` - Access the application container shell
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					All infrastructure scripts are organized in the `./infra/` directory for better project organization.
 | 
				
			||||||
							
								
								
									
										43
									
								
								infra/build-docker.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										43
									
								
								infra/build-docker.sh
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,43 @@
 | 
				
			|||||||
 | 
					#!/bin/bash
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Ask for tag interactively
 | 
				
			||||||
 | 
					echo "🏷️  Please enter a tag for the build (e.g., v1.0.0, production, beta):"
 | 
				
			||||||
 | 
					read -p "Tag: " TAG
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Check if tag was provided
 | 
				
			||||||
 | 
					if [ -z "$TAG" ]; then
 | 
				
			||||||
 | 
					    echo "❌ Error: Tag cannot be empty"
 | 
				
			||||||
 | 
					    echo "Please run the script again and provide a valid tag"
 | 
				
			||||||
 | 
					    exit 1
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					echo "🚀 Building Palmr Unified Image for AMD64 and ARM..."
 | 
				
			||||||
 | 
					echo "📦 Building tags: latest and $TAG"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Ensure buildx is available and create/use a builder instance
 | 
				
			||||||
 | 
					docker buildx create --name palmr-builder --use 2>/dev/null || docker buildx use palmr-builder
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Build the unified image for multiple platforms without cache
 | 
				
			||||||
 | 
					docker buildx build \
 | 
				
			||||||
 | 
					    --platform linux/amd64,linux/arm64 \
 | 
				
			||||||
 | 
					    --no-cache \
 | 
				
			||||||
 | 
					    -t kyantech/palmr:latest \
 | 
				
			||||||
 | 
					    -t kyantech/palmr:$TAG \
 | 
				
			||||||
 | 
					    --load \
 | 
				
			||||||
 | 
					    .
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if [ $? -eq 0 ]; then
 | 
				
			||||||
 | 
					    echo "✅ Multi-platform build completed successfully!"
 | 
				
			||||||
 | 
					    echo ""
 | 
				
			||||||
 | 
					    echo "Built for platforms: linux/amd64, linux/arm64"
 | 
				
			||||||
 | 
					    echo "Built tags: palmr:latest and palmr:$TAG"
 | 
				
			||||||
 | 
					    echo ""
 | 
				
			||||||
 | 
					    echo "Access points:"
 | 
				
			||||||
 | 
					    echo "- API: http://localhost:3333"
 | 
				
			||||||
 | 
					    echo "- Web App: http://localhost:5487"
 | 
				
			||||||
 | 
					    echo ""
 | 
				
			||||||
 | 
					    echo "Read the docs for more information"
 | 
				
			||||||
 | 
					else
 | 
				
			||||||
 | 
					    echo "❌ Build failed!"
 | 
				
			||||||
 | 
					    exit 1
 | 
				
			||||||
 | 
					fi 
 | 
				
			||||||
							
								
								
									
										29
									
								
								infra/server-start.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								infra/server-start.sh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,29 @@
 | 
				
			|||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					echo "Starting Palmr Server..."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Set proper environment
 | 
				
			||||||
 | 
					export HOME=/home/palmr
 | 
				
			||||||
 | 
					export NPM_CONFIG_CACHE=/home/palmr/.npm
 | 
				
			||||||
 | 
					export PNPM_HOME=/home/palmr/.pnpm
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Wait for PostgreSQL
 | 
				
			||||||
 | 
					echo "Waiting for PostgreSQL..."
 | 
				
			||||||
 | 
					while ! nc -z postgres 5432; 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 "Running database seeds..."
 | 
				
			||||||
 | 
					node prisma/seed.js || echo "Seeds failed or already exist, continuing..."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					echo "Starting server application..."
 | 
				
			||||||
 | 
					exec node dist/server.js 
 | 
				
			||||||
		Reference in New Issue
	
	Block a user