Palmr.

Deprecated version documentation

This documentation refers to a previous version of Palmr. It may contain more complex configurations and bugs that have already been fixed.

View latest documentation (v3.0-beta)

🐳 Installation (Docker Compose)

Installation via Docker Compose is the simplest way to run the project across different environments. For it to run correctly, we need two main tools installed in our environment:

It's worth emphasizing that Palmr. was fully developed in a MacOS environment and extensively tested on Linux servers. Therefore, we can guarantee the best system performance in these environments. Windows and other environments have not been tested yet, and potential bugs may occur during execution. However, remember that we are still in a beta version of Palmr., and errors or bugs can occur in any operating system. If you identify any issues, we appreciate your help in notifying us through our GitHub issues page.


⚡ Quick Start

Having installed Docker and Docker Compose in our environment, we can proceed with the simple installation using these tools.

In the root folder of our project, we can find our docker-compose.yaml file, which is the only file needed to run the project via Docker and Docker Compose. This is because the pre-built images are already in our DockerHub and are only referenced in the docker-compose.yaml

Any changes needed for execution can be made directly in our docker-compose.yaml or via environment variables, which we will show later in this tutorial.

Next, let's look at the content of our docker-compose.yaml.


🐳 Docker Compose Content

Below is the complete content of our docker-compose.yaml that can be copied directly from here or from our official repository (Docker Compose).

services:
  palmr:
    image: kyantech/palmr:latest # Make sure to use the correct version (latest) of the image
    container_name: palmr
    depends_on:
      postgres:
        condition: "service_healthy"
      minio:
        condition: "service_healthy"
    environment:
      # Server environment variables
      - 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
      - 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_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_PASSWORD=${MINIO_ROOT_PASSWORD:-minioRootPassword} # MinIO credentials can be configured through MINIO_ROOT_PASSWORD env vars
      - MINIO_REGION=sa-east-1 # MinIO region - This is needed for MinIO to work properly
      - MINIO_BUCKET_NAME=files # MinIO bucket name - This is needed for MinIO to work properly, dont change it if you don't know what you are doing
      - 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
      - MAX_FILESIZE=${MAX_FILESIZE:-1073741824} # Max Filesize for upload - Declared in Bytes. Default is 1GiB
      
      # Web environment variables
      - NODE_ENV=production
      - NEXT_TELEMETRY_DISABLED=1
      - 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
    healthcheck:
      test: ["CMD", "wget", "--no-verbose", "http://palmr:${API_INTERNAL_PORT:-3333}/health", "&&", "wget", "--no-verbose", "http://palmr:${APP_INTERNAL_PORT:-5487}"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 60s
 
  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
    container_name: minio
    environment:
      # MinIO credentials - same as above, configurable through environment variables
      - MINIO_ROOT_USER=${MINIO_ROOT_USER:-minio_root_user}
      - MINIO_ROOT_PASSWORD=${MINIO_ROOT_PASSWORD:-minioRootPassword}
      - MINIO_SITE_REGION=sa-east-1
    command: server /data --address ":${MINIO_INTERNAL_API_PORT:-6421}" --console-address ":${MINIO_INTERNAL_CONSOLE_PORT:-6422}"
    volumes:
      - minio_data:/data
    ports:
      - "${MINIO_EXTERNAL_API_PORT:-6421}:${MINIO_INTERNAL_API_PORT:-6421}"
      - "${MINIO_EXTERNAL_CONSOLE_PORT:-6422}:${MINIO_INTERNAL_CONSOLE_PORT:-6422}"
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:${MINIO_INTERNAL_API_PORT:-6421}/minio/health/ready"]
      interval: 10s
      timeout: 5s
      retries: 5
 
  minio-init:
    image: minio/mc:RELEASE.2025-03-12T17-29-24Z # Use only version RELEASE.2025-03-12T17-29-24Z to avoid compatibility issues with the backend and MinIO
    container_name: minio-init
    depends_on:
      minio:
        condition: "service_healthy"
    restart: "no"
    # The entrypoint script will create a bucket called "files" and set it to be publicly readable using the MinIO client (mc).
    entrypoint: >
      sh -c "
        sleep 5 &&
        mc alias set myminio http://minio:${MINIO_INTERNAL_API_PORT:-6421} ${MINIO_ROOT_USER:-minio_root_user} ${MINIO_ROOT_PASSWORD:-minioRootPassword} &&
        mc mb myminio/files --ignore-existing &&
        mc anonymous set download myminio/files
      "
 
  postgres:
    image: bitnami/postgresql:17.2.0 # You can use any postgres version you prefer, but remember that some versions might not be compatible
    container_name: palmr-postgres
    environment:
      # PostgreSQL credentials configurable through environment variables
      # POSTGRESQL_USERNAME, POSTGRESQL_PASSWORD, and POSTGRES_DB can be set to override defaults
      - POSTGRESQL_USERNAME=${POSTGRESQL_USERNAME:-postgres}
      - POSTGRESQL_PASSWORD=${POSTGRESQL_PASSWORD:-postgresRootPassword}
      - POSTGRESQL_DATABASE=${POSTGRES_DATABASE:-palmr_db}
    volumes:
      - postgres_data:/bitnami/postgresql
    ports:
      - "5432:5432"
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "pg_isready", "-U", "palmr"]
      interval: 10s
      timeout: 5s
      retries: 5
 
volumes:
  minio_data:
  postgres_data: 

Notice that the docker-compose.yaml has several comments that help you configure your own compose to meet your environment's needs. Let's give an overview of some changes we can make.


⚙️ Services Overview

Palmr. consists of four main services, each with specific responsibilities. Below, we present a detailed view of each component:

ServiceImageExposed PortsMain Features
palmrkyantech/palmr:latest3333 (API)
5487 (Web)
• Combined backend API and frontend service
• Depends on services: postgres and minio
• Has healthcheck to ensure availability
minio (Storage)minio/minio:RELEASE.2025-03-12T18-04-18Z6421(API)
6422(Console)
• File storage service
• Persistent volume for data
minio-init (Config)minio/mc:RELEASE.2025-03-12T17-29-24ZN/A• Initially configures the "files" bucket
• Runs only once during initialization
postgres (Database)bitnami/postgresql:17.2.05432• PostgreSQL database
• Persistent volume for data

🛠️ Available Environment Variables

The table below shows all environment variables that can be set

VariableDefault ValueDescription
API_INTERNAL_PORT3333Internal API port in container
API_EXTERNAL_PORT3333Exposed port on host for API
POSTGRES_PASSWORDpostgresRootPasswordPostgreSQL database password
APP_EXTERNAL_PORT5487Exposed port on host for frontend
APP_URLhttp://localhost:5487Complete frontend URL
SERVER_IPlocalhostIP of the server where the application is running
MINIO_ROOT_USERminio_root_userMinIO admin user
MINIO_ROOT_PASSWORDminioRootPasswordMinIO admin password
MINIO_INTERNAL_API_PORT6421Internal MinIO API port
MINIO_INTERNAL_CONSOLE_PORT6422Internal MinIO console port
MINIO_EXTERNAL_API_PORT6421Exposed port on host for MinIO API
MINIO_EXTERNAL_CONSOLE_PORT6422Exposed port on host for MinIO console
POSTGRESQL_USERNAMEpostgresPostgreSQL user
POSTGRESQL_DATABASEpalmr_dbDatabase name
MAX_FILESIZE1073741824Max Uploadsize per file. Unit in Bytes

All these variables can be configured through a .env file in the project root or defined directly in the environment where docker-compose will be executed. The best way to do this is up to you. But be careful to replace correctly if doing directly in the compose instead of providing an environment var.

🗂️ Persistent Volumes

  • minio_data: Stores MinIO files
  • postgres_data: Stores PostgreSQL data

💻 Local Execution

In a localhost environment, there's no mystery. If you don't want to change any service exposure ports, you can simply run:

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):

If you have changed any port, simply access the URL with the port you configured.


🌐 Production (VPS or other)

For production environments, whether it's your VPS, Homelab Server, or other, the execution is very similar to the localhost environment, except for some particularities that may occur in some cases.

We mainly need to pay attention to the following points:

  • Correctly set the SERVER_IP env var with our server's IP, otherwise some redirects and queries will fail during App execution.
  • Set the APP_URL - regardless of whether the frontend is on the same server and with the same IP, it's extremely important to set this environment variable, otherwise sharing links will be generated incorrectly.
  • For all environment variables that are PASSWORD, it's highly recommended to generate secure passwords and replace them as env vars.
  • Lastly, make sure no docker service will conflict with any existing ones in your environment. If there is a conflict, simply change the execution ports via environment var or in the docker compose.

To generate a .env file with just the server_ip configuration, you can run this command:

curl -fsSL https://gist.githubusercontent.com/danielalves96/5a68913d70e5e31b68b7331dc17dfa9c/raw | bash

execute this command in your server terminal, at same path of docker-compose.yaml.

Basically, by paying attention to these points, you can quickly execute the project with the same command we used for localhost:

docker compose pull && docker compose up -d

⚠️ This makes sure you're always running the latest beta version of the image, otherwise, Docker might reuse an outdated one from cache.

At this stage, if you encounter any errors, it's worth reviewing your docker-compose.yaml and trying again, paying close attention to the points mentioned above.

First test without using reverse proxies like Caddy, Traefik, etc... if you plan to use them. Access the services via server_ip:port after confirming they work, then make the necessary routing configurations as desired.

If you haven't changed the execution ports, you'll have access on your server at:

  • Frontend: [server_ip]:5487
  • Backend: [server_ip]:3333
  • MinIO API: [server_ip]:6421
  • MinIO Console: [server_ip]:6422
  • Postgres Database: [server_ip]:5432 (Connection only)

If you've changed any port, simply access the URL with the port you configured.

It's worth noting that this is just a quick start and we're not going into details about any of the developed services, but it's recommended for execution in any environment. However, if your focus is on using Palmr. with high availability in mind, it's recommended to use a container orchestrator prepared for this, such as Kubernetes or similar, but we don't cover this type of configuration in our documentation.


📚 Additional Resources

On this page