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
79 changes: 79 additions & 0 deletions .github/workflows/docker-publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
name: Publish Docker Image

on:
push:
branches: [main]
tags: ["v*"]

permissions:
contents: read
packages: write

concurrency:
group: docker-publish-${{ github.ref }}
cancel-in-progress: true

jobs:
docker:
name: Build & Push Docker Image
runs-on: ubuntu-latest
timeout-minutes: 30

steps:
# ── 1. Checkout (needed for path context so .dockerignore is respected) ──
- name: Checkout
uses: actions/checkout@v4

# ── 2. Multi-platform support ───────────────────────────────────────────
- name: Set up QEMU
uses: docker/setup-qemu-action@v4

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4

# ── 3. Registry authentication ─────────────────────────────────────────
- name: Log in to GitHub Container Registry
uses: docker/login-action@v4
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Log in to Docker Hub
if: vars.DOCKERHUB_USERNAME != ''
uses: docker/login-action@v4
with:
username: ${{ vars.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

# ── 4. Tag & label generation ──────────────────────────────────────────
- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@v6
with:
images: |
ghcr.io/${{ github.repository }}
name=reqcore/reqcore,enable=${{ vars.DOCKERHUB_USERNAME != '' }}
tags: |
type=edge,branch=main
type=raw,value=latest,enable={{is_default_branch}}
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=sha,prefix=sha-

# ── 5. Build & push ────────────────────────────────────────────────────
- name: Build and push
uses: docker/build-push-action@v7
with:
context: .
push: true
platforms: linux/amd64,linux/arm64
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
annotations: ${{ steps.meta.outputs.annotations }}
cache-from: type=gha
cache-to: type=gha,mode=max
provenance: mode=max
sbom: true
env:
DOCKER_METADATA_ANNOTATIONS_LEVELS: manifest,index
33 changes: 33 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
[![E2E Tests](https://github.com/reqcore-inc/reqcore/actions/workflows/e2e-tests.yml/badge.svg)](https://github.com/reqcore-inc/reqcore/actions/workflows/e2e-tests.yml)
[![PR Validation](https://github.com/reqcore-inc/reqcore/actions/workflows/pr-validation.yml/badge.svg)](https://github.com/reqcore-inc/reqcore/actions/workflows/pr-validation.yml)
[![Docker Integration](https://github.com/reqcore-inc/reqcore/actions/workflows/docker-readme-validation.yml/badge.svg)](https://github.com/reqcore-inc/reqcore/actions/workflows/docker-readme-validation.yml)
[![Docker Image](https://ghcr-badge.egpl.dev/reqcore-inc/reqcore/latest_tag?trim=major&label=docker)](https://github.com/reqcore-inc/reqcore/pkgs/container/reqcore)

[Live Demo](https://reqcore.com) · [Documentation](ARCHITECTURE.md) · [Roadmap](ROADMAP.md) · [Report Bug](https://github.com/reqcore-inc/reqcore/issues/new)

Expand Down Expand Up @@ -62,6 +63,29 @@ Hiring software shouldn't be complicated or expensive. Most applicant tracking s

---

### Option A — Use the pre-built image (fastest)

No cloning, no building. Pull the official image and run:

```bash
mkdir reqcore && cd reqcore
curl -fsSLO https://raw.githubusercontent.com/reqcore-inc/reqcore/main/docker-compose.production.yml
curl -fsSLO https://raw.githubusercontent.com/reqcore-inc/reqcore/main/setup.sh
chmod +x setup.sh
./setup.sh
docker compose -f docker-compose.production.yml up -d
```

Open **[http://localhost:3000](http://localhost:3000)** and sign up. That's it.

To update: `docker compose -f docker-compose.production.yml pull app && docker compose -f docker-compose.production.yml up -d`

---

### Option B — Build from source

---

### Step 1 — Install Docker

Docker packages the app, database, and file storage into containers so you don't have to install anything else manually.
Expand Down Expand Up @@ -153,6 +177,15 @@ Then sign in with:

When a new version of Reqcore is released, follow these steps **in order** to update your instance. Your data is safe — updates never delete the database or your uploaded files.

#### Pre-built image users

```bash
docker compose -f docker-compose.production.yml pull app
docker compose -f docker-compose.production.yml up -d
```

#### Build from source users

**Step 1 — Pull the latest code**

```bash
Expand Down
85 changes: 70 additions & 15 deletions SELF-HOSTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,17 @@ Everything you need to deploy, manage, and update your own Reqcore applicant tra
1. [What is Self-Hosting?](#what-is-self-hosting)
2. [Why Self-Host Reqcore?](#why-self-host-reqcore)
3. [Requirements](#requirements)
4. [Quick Start (5 Minutes)](#quick-start-5-minutes)
5. [Step-by-Step Installation](#step-by-step-installation)
6. [Updating Your Instance](#updating-your-instance)
7. [Backups & Data Safety](#backups--data-safety)
8. [Custom Domain & HTTPS](#custom-domain--https)
9. [Email Configuration](#email-configuration)
10. [Security Best Practices](#security-best-practices)
11. [Monitoring & Health Checks](#monitoring--health-checks)
12. [Troubleshooting](#troubleshooting)
13. [FAQ](#faq)
4. [Quick Start — Pre-built Image (Fastest)](#quick-start--pre-built-image-fastest)
5. [Quick Start — Build from Source (5 Minutes)](#quick-start--build-from-source-5-minutes)
6. [Step-by-Step Installation](#step-by-step-installation)
7. [Updating Your Instance](#updating-your-instance)
8. [Backups & Data Safety](#backups--data-safety)
9. [Custom Domain & HTTPS](#custom-domain--https)
10. [Email Configuration](#email-configuration)
11. [Security Best Practices](#security-best-practices)
12. [Monitoring & Health Checks](#monitoring--health-checks)
13. [Troubleshooting](#troubleshooting)
14. [FAQ](#faq)

---

Expand Down Expand Up @@ -79,9 +80,41 @@ All of these providers offer one-click Docker installation when creating a serve

---

## Quick Start (5 Minutes)
## Quick Start — Pre-built Image (Fastest)

If you have Docker already installed and just want to get running:
Use the official pre-built Docker image from GitHub Container Registry. No cloning, no building — just pull and run:

```bash
# 1. Download just the files you need
mkdir reqcore && cd reqcore
curl -fsSLO https://raw.githubusercontent.com/reqcore-inc/reqcore/main/docker-compose.production.yml
curl -fsSLO https://raw.githubusercontent.com/reqcore-inc/reqcore/main/setup.sh
chmod +x setup.sh

# 2. Generate secure passwords (one-time)
./setup.sh

# 3. Start everything
docker compose -f docker-compose.production.yml up -d

# 4. Open your browser
# → http://localhost:3000
```

That's it. Sign up, create your organization, and start hiring.

**Want to pin a specific version?** Edit `docker-compose.production.yml` and replace `latest` with a version tag (e.g., `1.3.0`):

```yaml
app:
image: ghcr.io/reqcore-inc/reqcore:1.3.0
```

---

## Quick Start — Build from Source (5 Minutes)

If you prefer to build from source (useful for development or customization):

```bash
# 1. Download Reqcore
Expand All @@ -98,7 +131,7 @@ docker compose up -d
# → http://localhost:3000
```

That's it. Sign up, create your organization, and start hiring.
Sign up, create your organization, and start hiring.

**Want demo data to explore first?**

Expand Down Expand Up @@ -217,9 +250,31 @@ Reqcore includes a built-in update system accessible from the Settings panel. No

The UI shows the progress of each update step and clearly indicates success or failure. Your data is always preserved — database migrations run automatically.

### Method 2: Update from the Command Line
### Method 2: Update from the Command Line (Pre-built Image)

If you're using the pre-built image (`docker-compose.production.yml`):

```bash
# Navigate to your Reqcore directory
cd /path/to/reqcore

# Pull the latest image and restart
docker compose -f docker-compose.production.yml pull app
docker compose -f docker-compose.production.yml up -d
```

To update to a specific version, edit `docker-compose.production.yml` and change the image tag:

```yaml
app:
image: ghcr.io/reqcore-inc/reqcore:1.4.0
```

Then run `docker compose -f docker-compose.production.yml up -d`.

### Method 3: Update from the Command Line (Build from Source)

If you prefer using the terminal, or the UI update isn't available:
If you cloned the repository and build locally:

```bash
# Navigate to your Reqcore directory
Expand Down
84 changes: 84 additions & 0 deletions docker-compose.production.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# docker-compose.production.yml
#
# Use this file to run Reqcore with the official pre-built Docker image
# instead of building from source. No git clone or local build required.
#
# Quick start:
# 1. Download this file and setup.sh from the repository
# 2. Run: ./setup.sh
# 3. Run: docker compose -f docker-compose.production.yml up -d
# 4. Open: http://localhost:3000

services:
db:
image: postgres:16-alpine
container_name: reqcore_db
restart: unless-stopped
environment:
POSTGRES_USER: ${DB_USER}
POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_DB: ${DB_NAME}
ports:
- "127.0.0.1:5432:5432" # Postgres — localhost only, never expose publicly
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${DB_USER} -d ${DB_NAME}"]
interval: 5s
timeout: 5s
retries: 10

minio:
image: minio/minio
container_name: reqcore_minio
restart: unless-stopped
ports:
- "127.0.0.1:9000:9000" # S3 API — localhost only, never expose publicly
- "127.0.0.1:9001:9001" # MinIO Console → http://localhost:9001
environment:
MINIO_ROOT_USER: ${STORAGE_USER}
MINIO_ROOT_PASSWORD: ${STORAGE_PASSWORD}
command: server /data --console-address ":9001"
volumes:
- minio_data:/data
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
interval: 5s
timeout: 5s
retries: 10

app:
image: ghcr.io/reqcore-inc/reqcore:latest
container_name: reqcore_app
restart: unless-stopped
env_file: .env
environment:
# Override localhost URLs with Docker-internal hostnames
DATABASE_URL: postgresql://${DB_USER}:${DB_PASSWORD}@db:5432/${DB_NAME}
S3_ENDPOINT: http://minio:9000
ports:
- "3000:3000"
depends_on:
db:
condition: service_healthy
minio:
condition: service_healthy
volumes:
- backups_data:/data/backups

# Optional DB browser — run with: docker compose -f docker-compose.production.yml --profile tools up
adminer:
image: adminer
container_name: reqcore_adminer
restart: unless-stopped
profiles: [tools]
ports:
- "127.0.0.1:8080:8080" # Adminer → http://localhost:8080
depends_on:
db:
condition: service_healthy

volumes:
postgres_data:
minio_data:
backups_data:
Loading