Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ updates:
ignore:
- dependency-name: "next"
update-types: ["version-update:semver-major"]
# Prisma 7 has breaking changes incompatible with our schema
- dependency-name: "prisma"
update-types: ["version-update:semver-major"]
- dependency-name: "@prisma/client"
update-types: ["version-update:semver-major"]

- package-ecosystem: "github-actions"
directory: "/"
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# CI Workflow - Validates PRs and pushes, builds Docker images for version tags
# Builds multi-platform images (amd64 + arm64) and pushes to Docker Hub
# Builds amd64 images and pushes to Docker Hub

name: CI

Expand Down Expand Up @@ -99,7 +99,7 @@ jobs:
uses: docker/build-push-action@v6
with:
context: .
platforms: linux/amd64,linux/arm64
platforms: linux/amd64
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
Expand Down
21 changes: 17 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ COPY prisma ./prisma/
RUN npm ci

# Generate Prisma client (needs dummy DATABASE_URL for generation)
# SECURITY NOTE: This is ONLY for build time to generate client artifacts.
# It is NOT used in production and does NOT persist to the final image.
ENV DATABASE_URL="postgresql://user:pass@localhost:5432/db"
RUN npx prisma generate

Expand All @@ -31,8 +33,12 @@ FROM node:20-alpine AS runner
WORKDIR /app

# Install runtime dependencies
# Added: prisma for migrations
RUN apk add --no-cache libc6-compat openssl git curl docker-cli

# Install global prisma for the entrypoint script (pinned to match project version)
RUN npm install -g prisma@6.19.1

# Create non-root user
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
Expand All @@ -44,11 +50,17 @@ COPY --from=builder /app/.next/static ./.next/static
COPY --from=builder /app/prisma ./prisma
COPY --from=builder /app/node_modules/.prisma ./node_modules/.prisma

# Set ownership
# Copy entrypoint script
COPY scripts/docker-entrypoint.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/docker-entrypoint.sh

# Set ownership of app directory
RUN chown -R nextjs:nodejs /app

# Switch to non-root user
USER nextjs
# Note: We run as root because:
# 1. Docker socket access requires root
# 2. Mounted volumes (/data/core, /data/projects) are created as root
# In a more secure setup, you could use rootless Docker or adjust volume permissions

# Expose port
EXPOSE 3000
Expand All @@ -63,5 +75,6 @@ ENV HOSTNAME="0.0.0.0"
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD curl -f http://localhost:3000/api/health || exit 1

# Start the application
# Start the application using entrypoint
ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"]
CMD ["node", "server.js"]
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ SupaPanel is a web-based control panel that simplifies the deployment and manage
- [Quick Start](#quick-start)
- [Tech Stack](#tech-stack)
- [Usage Guide](#usage-guide)
- [Uninstallation](#uninstallation)
- [Project Structure](#project-structure)
- [Configuration](#configuration)
- [Contributing](#contributing)
Expand Down Expand Up @@ -196,6 +197,28 @@ After configuration:

---

## Uninstallation

To completely remove SupaPanel from your server, follow these steps:

1. **Stop and remove containers**:
```bash
cd /etc/supapanel
docker compose down -v
```

2. **Remove data directory** (WARNING: This will delete all your projects and data):
```bash
sudo rm -rf /etc/supapanel
```

3. **Remove Docker image** (optional):
```bash
docker rmi alanmf30/supapanel:latest
```

---

## Project Structure

```
Expand Down
24 changes: 12 additions & 12 deletions install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,18 @@ set -e
SUPAPANEL_VERSION="${SUPAPANEL_VERSION:-latest}"
SUPAPANEL_DATA_DIR="/etc/supapanel"

echo "╔═══════════════════════════════════════════════════════════════╗"
echo "║ ║"
echo "║ ███████╗██╗ ██╗██████╗ █████╗ ██████╗███╗ ██╗███████╗ ║"
echo "║ ██╔════╝██║ ██║██╔══██╗██╔══██╗██╔════╝████╗ ██║██╔════╝ ║"
echo "║ ███████╗██║ ██║██████╔╝███████║██║ ██╔██╗ ██║███████╗ ║"
echo "║ ╚════██║██║ ██║██╔═══╝ ██╔══██║██║ ██║╚██╗██║╚════██║ ║"
echo "║ ███████║╚██████╔╝██║ ██║ ██║╚██████╗██║ ╚████║███████║ ║"
echo "║ ╚══════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═══╝╚══════╝ ║"
echo "║ ║"
echo "║ Self-Hosted Supabase Management Panel ║"
echo "║ ║"
echo "╚═══════════════════════════════════════════════════════════════╝"
echo "╔══════════════════════════════════════════════════════════════════════════════╗"
echo "║ ║"
echo "║ ███████╗██╗ ██╗██████╗ █████╗ ██████╗ █████╗ ███╗ ██╗███████╗██╗ ║"
echo "║ ██╔════╝██║ ██║██╔══██╗██╔══██╗██╔══██╗██╔══██╗████╗ ██║██╔════╝██║ ║"
echo "║ ███████╗██║ ██║██████╔╝███████║██████╔╝███████║██╔██╗ ██║█████╗ ██║ ║"
echo "║ ╚════██║██║ ██║██╔═══╝ ██╔══██║██╔═══╝ ██╔══██║██║╚██╗██║██╔══╝ ██║ ║"
echo "║ ███████║╚██████╔╝██║ ██║ ██║██║ ██║ ██║██║ ╚████║███████╗███████╗║"
echo "║ ╚══════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝╚═╝ ╚═══╝╚══════╝╚══════╝║"
echo "║ ║"
echo "║ Self-Hosted Supabase Management Panel ║"
echo "║ ║"
echo "╚══════════════════════════════════════════════════════════════════════════════╝"
echo ""

# Check if running as root
Expand Down
23 changes: 23 additions & 0 deletions scripts/docker-entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#!/bin/sh
set -e

# Wait for the database to be ready
# (Optional: we can rely on Docker Compose healthcheck, but a quick check here is good)

echo "Starting SupaPanel..."

if [ -z "$DATABASE_URL" ]; then
echo "Error: DATABASE_URL is not set."
exit 1
fi

# Run database migrations
echo "Running database migrations..."
# We use db push for now to ensure schema is in sync.
# --skip-generate is needed because the client was already generated during build,
# and the nextjs user doesn't have write permissions to regenerate it.
npx prisma db push --accept-data-loss --skip-generate

# Execute the main command
echo "Starting application..."
exec "$@"
8 changes: 7 additions & 1 deletion src/app/api/auth/login/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,17 @@ export async function POST(request: NextRequest) {
},
})

// Only set secure if actually using HTTPS (not just based on NODE_ENV)
// This allows HTTP access via IP:3000 while still being secure over HTTPS
const isSecure = request.headers.get('x-forwarded-proto') === 'https' ||
request.url.startsWith('https://')

response.cookies.set('session', token, {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
secure: isSecure,
sameSite: 'lax',
maxAge: 24 * 60 * 60, // 24 hours
path: '/',
})

return response
Expand Down
8 changes: 7 additions & 1 deletion src/app/api/auth/register/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,17 @@ export async function POST(request: NextRequest) {
},
})

// Only set secure if actually using HTTPS (not just based on NODE_ENV)
// This allows HTTP access via IP:3000 while still being secure over HTTPS
const isSecure = request.headers.get('x-forwarded-proto') === 'https' ||
request.url.startsWith('https://')

response.cookies.set('session', token, {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
secure: isSecure,
sameSite: 'lax',
maxAge: 24 * 60 * 60, // 24 hours
path: '/',
})

return response
Expand Down
Loading