Velld LogoVelld

Installation

Get started with Velld in minutes

Installation

Velld is designed to be simple to install and run. Choose the installation method that works best for you.

Prerequisites

Before you begin, ensure you have:

  • Docker and Docker Compose installed
  • At least 512MB RAM and 1GB disk space
  • A database you want to backup (PostgreSQL, MySQL, or MongoDB)

Velld only installs the database clients you need. This keeps the Docker image lightweight and secure.

Quick Start

Fastest way - Pull and run pre-built images directly (no git clone needed):

# Pull images
docker pull ghcr.io/dendianugerah/velld/api:latest
docker pull ghcr.io/dendianugerah/velld/web:latest

# Create .env file
cat > .env << EOF
NEXT_PUBLIC_API_URL=http://localhost:8080
JWT_SECRET=your-super-secret-jwt-key
ENCRYPTION_KEY=your-32-byte-encryption-key / $(openssl rand -hex 32)
ADMIN_USERNAME_CREDENTIAL=admin
ADMIN_PASSWORD_CREDENTIAL=changeme
ALLOW_REGISTER=true
EOF

# Run API
docker run -d \
  --name velld-api \
  -p 8080:8080 \
  --env-file .env \
  -v velld-data:/app/internal/database \
  -v velld-backups:/app/backups \
  ghcr.io/dendianugerah/velld/api:latest

# Run Web
docker run -d \
  --name velld-web \
  -p 3000:3000 \
  -e NEXT_PUBLIC_API_URL=http://localhost:8080 \
  -e ALLOW_REGISTER=true \
  ghcr.io/dendianugerah/velld/web:latest

Open http://localhost:3000 in your browser.


Using Docker Compose

If you prefer docker-compose:

git clone https://github.com/dendianugerah/velld.git
cd velld
cp .env.example .env
docker compose -f docker-compose.prebuilt.yml up -d

Build from Source

If you want to build the images yourself:

git clone https://github.com/dendianugerah/velld.git
cd velld
cp .env.example .env
docker compose up -d

Database-Specific Installation

Choose only the database client you need to keep your installation lightweight:

PostgreSQL Only

1. Create a custom Dockerfile

Create apps/api/Dockerfile.postgres:

FROM golang:1.24-alpine AS builder

WORKDIR /app

RUN apk add --no-cache gcc musl-dev

COPY go.mod go.sum ./
RUN go mod download

COPY . .

RUN CGO_ENABLED=1 GOOS=linux go build -o main cmd/api-server/main.go

FROM alpine:latest

# Install only PostgreSQL client
RUN apk add --no-cache \
    sqlite-libs \
    postgresql-client

WORKDIR /app

COPY --from=builder /app/main .
COPY --from=builder /app/internal/database ./internal/database

EXPOSE 8080

CMD ["./main"]

2. Update docker-compose.yml

services:
  api:
    build:
      context: ./apps/api
      dockerfile: Dockerfile.postgres  # Use PostgreSQL-only Dockerfile
    ports:
      - "8080:8080"
    env_file:
      - .env
    volumes:
      - api_data:/app/internal/database
      - backup_data:/app/backups
    restart: unless-stopped

  web:
    build:
      context: ./apps/web
      dockerfile: Dockerfile
    ports:
      - "3000:3000"
    environment:
      NEXT_PUBLIC_API_URL: ${NEXT_PUBLIC_API_URL}
      ALLOW_REGISTER: ${ALLOW_REGISTER}
    depends_on:
      - api
    restart: unless-stopped

volumes:
  api_data:
  backup_data:

3. Start the services

docker compose up -d

Your PostgreSQL-only installation is now running! Image size: ~50MB lighter.

MySQL Only

1. Create a custom Dockerfile

Create apps/api/Dockerfile.mysql:

FROM golang:1.24-alpine AS builder

WORKDIR /app

RUN apk add --no-cache gcc musl-dev

COPY go.mod go.sum ./
RUN go mod download

COPY . .

RUN CGO_ENABLED=1 GOOS=linux go build -o main cmd/api-server/main.go

FROM alpine:latest

# Install only MySQL client
RUN apk add --no-cache \
    sqlite-libs \
    mysql-client

WORKDIR /app

COPY --from=builder /app/main .
COPY --from=builder /app/internal/database ./internal/database

EXPOSE 8080

CMD ["./main"]

2. Update docker-compose.yml

services:
  api:
    build:
      context: ./apps/api
      dockerfile: Dockerfile.mysql  # Use MySQL-only Dockerfile
    ports:
      - "8080:8080"
    env_file:
      - .env
    volumes:
      - api_data:/app/internal/database
      - backup_data:/app/backups
    restart: unless-stopped

  web:
    build:
      context: ./apps/web
      dockerfile: Dockerfile
    ports:
      - "3000:3000"
    environment:
      NEXT_PUBLIC_API_URL: ${NEXT_PUBLIC_API_URL}
      ALLOW_REGISTER: ${ALLOW_REGISTER}
    depends_on:
      - api
    restart: unless-stopped

volumes:
  api_data:
  backup_data:

3. Start the services

docker compose up -d

Your MySQL-only installation is now running! Image size: ~45MB lighter.

MongoDB Only

1. Create a custom Dockerfile

Create apps/api/Dockerfile.mongo:

FROM golang:1.24-alpine AS builder

WORKDIR /app

RUN apk add --no-cache gcc musl-dev

COPY go.mod go.sum ./
RUN go mod download

COPY . .

RUN CGO_ENABLED=1 GOOS=linux go build -o main cmd/api-server/main.go

FROM alpine:latest

# Install only MongoDB tools
RUN apk add --no-cache \
    sqlite-libs \
    mongodb-tools

WORKDIR /app

COPY --from=builder /app/main .
COPY --from=builder /app/internal/database ./internal/database

EXPOSE 8080

CMD ["./main"]

2. Update docker-compose.yml

services:
  api:
    build:
      context: ./apps/api
      dockerfile: Dockerfile.mongo  # Use MongoDB-only Dockerfile
    ports:
      - "8080:8080"
    env_file:
      - .env
    volumes:
      - api_data:/app/internal/database
      - backup_data:/app/backups
    restart: unless-stopped

  web:
    build:
      context: ./apps/web
      dockerfile: Dockerfile
    ports:
      - "3000:3000"
    environment:
      NEXT_PUBLIC_API_URL: ${NEXT_PUBLIC_API_URL}
      ALLOW_REGISTER: ${ALLOW_REGISTER}
    depends_on:
      - api
    restart: unless-stopped

volumes:
  api_data:
  backup_data:

3. Start the services

docker compose up -d

Your MongoDB-only installation is now running! Image size: ~60MB lighter.


Environment Configuration

Create a .env file in the project root or copy from .env.example:

cp .env.example .env

Environment Variables

VariableDescriptionRequiredDefault Behavior
NEXT_PUBLIC_API_URLBase URL for the API serverYeshttp://localhost:8080
JWT_SECRETSecret key for JWT token signingOptionalAuto-generated if missing
ENCRYPTION_KEYKey for encrypting sensitive data (database credentials)OptionalAuto-generated if missing
ALLOW_REGISTEREnable/disable user registrationOptionaltrue
ADMIN_USERNAME_CREDENTIALAdmin username for loginOnly if ALLOW_REGISTER=false-
ADMIN_PASSWORD_CREDENTIALAdmin password for loginOnly if ALLOW_REGISTER=false-
SMTP_HOSTSMTP server hostname for email notificationsOptional-
SMTP_PORTSMTP server portOptional587
SMTP_USEREmail address for sending notificationsOptional-
SMTP_PASSWORDSMTP password or app-specific passwordOptional-
SMTP_FROM"From" address in notification emailsOptional-

ALLOW_REGISTER Behavior:

  • true (default) - Anyone can register via /register. Admin credentials are not required.
  • false - Registration disabled. ADMIN_USERNAME_CREDENTIAL and ADMIN_PASSWORD_CREDENTIAL are required for login.

Verify Installation

Once the services are running, verify everything works:

  1. Check service status

    docker compose ps
  2. View logs

    docker compose logs -f
  3. Access the web interface

    Open http://localhost:3000 in your browser.

  4. Create your account

    Sign up with your email and start managing backups!


Updating Velld

To update to the latest version:

# Pull the latest changes
git pull origin main

# Rebuild and restart
docker compose down
docker compose up -d --build

Troubleshooting

Services won't start

# Check logs for errors
docker compose logs api
docker compose logs web

# Ensure ports 3000 and 8080 are available
lsof -i :3000
lsof -i :8080

Database connection fails

  • Ensure your database is accessible from the Docker container
  • Use host.docker.internal instead of localhost to connect to databases on your host machine
  • Check firewall rules

Backup fails

  • Verify the database client is installed (check which Dockerfile you're using)
  • Test connection credentials manually
  • Check backup directory permissions

Next Steps