Skip to content

Deploying a Huly App

Introduction

Huly is an open-source project management and issue-tracking platform built with a modern TypeScript/Node.js stack and PostgreSQL. Deploying Huly on Klutch.sh with a Dockerfile provides reproducible builds, managed secrets, and persistent storage for file uploads—all orchestrated from klutch.sh/app. This guide covers installation, repository setup, Dockerfile configuration, deployment steps, Nixpacks overrides, and production best practices.


Prerequisites

  • A Klutch.sh account (create one)
  • A GitHub repository containing your Huly code (GitHub is the only supported git source)
  • Docker familiarity and Node.js 18+ installed locally for testing
  • PostgreSQL connection details (host, port, database, user, password)
  • Optional object storage credentials if you offload attachments

  • Serve the Huly web app over HTTP with an internal container port of 3000.
  • Run PostgreSQL as a separate Klutch.sh TCP app; expose it on port 8000 and connect internally on port 5432.
  • Use persistent storage for user uploads, exports, and cached assets (for example /app/storage/uploads).

Repository layout

huly/
├── apps/web/ # Next.js/React frontend
├── apps/server/ # API/backend services
├── packages/ # Shared libraries
├── public/ # Static assets
├── storage/ # Uploads and generated files (mount as a volume)
├── Dockerfile # Must live at the repo root for Klutch.sh detection
├── package.json
├── pnpm-lock.yaml # or yarn.lock / package-lock.json
└── .env.example # Template only; no secrets

Keep secrets out of Git and rely on Klutch.sh environment variables.


Installation (local) and starter scripts

Install dependencies locally before pushing to GitHub:

Terminal window
pnpm install
pnpm build
pnpm start

If your project uses migrations, add a script such as:

Terminal window
pnpm prisma migrate deploy

Consider a helper start.sh for portability and Nixpacks fallback:

#!/usr/bin/env bash
set -euo pipefail
pnpm prisma migrate deploy
pnpm start -- --port 3000

Make it executable with chmod +x start.sh.


Dockerfile for Huly (production-ready)

Place this at the repository root so Klutch.sh auto-detects it; there is no Docker selection in the UI:

FROM node:18-alpine AS build
WORKDIR /app
# Install dependencies
COPY package.json pnpm-lock.yaml* yarn.lock* package-lock.json* ./
RUN corepack enable
# Use pnpm by default; adjust if you prefer npm or yarn
RUN pnpm install --frozen-lockfile
# Copy source and build
COPY . .
RUN pnpm build
# Production image
FROM node:18-alpine
WORKDIR /app
ENV NODE_ENV=production \
PORT=3000
# Copy built assets
COPY --from=build /app /app
# Install only production dependencies
RUN corepack enable && pnpm install --prod --frozen-lockfile
EXPOSE 3000
CMD ["pnpm", "start", "--", "--port", "3000"]

Notes:

  • If you compile native modules, install the required Alpine build tools in the build stage (apk add --no-cache python3 make g++).
  • Keep the storage/ path writable for uploads; mount it as a volume in Klutch.sh.

Environment variables (Klutch.sh)

Set these in the Klutch.sh app settings (Secrets tab) before deploying:

  • NODE_ENV=production
  • PORT=3000
  • APP_BASE_URL=https://example-app.klutch.sh
  • DATABASE_URL=postgresql://<user>:<password>@<host>:<port>/<db>
  • JWT_SECRET or equivalent auth secret
  • STORAGE_DIR=/app/storage/uploads (or your chosen path)
  • NEXT_PUBLIC_APP_URL=https://example-app.klutch.sh (for frontends)

If you customize Nixpacks (for times you deploy without the Dockerfile), use:

  • NIXPACKS_BUILD_CMD=pnpm install --frozen-lockfile && pnpm build
  • NIXPACKS_START_CMD=pnpm start -- --port 3000
  • NIXPACKS_NODE_VERSION=18

These ensure Huly builds and serves correctly with Nixpacks defaults.


Attach persistent volumes

In Klutch.sh storage settings, add mount paths and sizes (names are not required):

  • /app/storage/uploads — for attachments and exported assets.
  • /app/.cache — optional cache to speed rebuilds if your app writes there.

Confirm the Node process can write to these directories inside the container.


Deploy Huly on Klutch.sh (Dockerfile workflow)

  1. Push your repository (with the Dockerfile at the root) to GitHub.
  2. Open klutch.sh/app, create a project, and add an app.
  3. Connect the GitHub repository; Klutch.sh automatically detects the Dockerfile.
  4. Choose HTTP traffic for the Huly web app.
  5. Set the internal port to 3000.
  6. Add the environment variables listed above (including database and JWT secrets).
  7. Attach persistent volumes for /app/storage/uploads (and /app/.cache if used), selecting sizes that match your storage needs.
  8. Deploy. Your app will be live at https://example-app.klutch.sh; attach a custom domain if desired.

For PostgreSQL on Klutch.sh, create a separate TCP app, expose it on port 8000, and point DATABASE_URL to that endpoint (internal port 5432).


Health checks and production tips

  • Add a lightweight health route (e.g., /api/health) for uptime monitoring.
  • Enable structured logging and route logs to your observability stack.
  • Keep lockfiles committed and dependency versions pinned for reproducible builds.
  • Monitor disk usage on mounted paths and resize volumes before they fill.
  • Back up PostgreSQL regularly; do not rely on container filesystems for data durability.

Huly on Klutch.sh combines fast, reproducible Docker builds with managed secrets, persistent volumes, and flexible HTTP/TCP traffic options. With the Dockerfile at the repo root and ports set to 3000 for the app (8000 externally for TCP databases), you can ship a stable project management experience without extra YAML or workflow overhead.