Skip to content

reactive-resume Reactive Resume

Reactive Resume is a one-of-a-kind resume builder that keeps your privacy in mind.

🛠 Installation

Default Port: 3000

homelab/docker/reactive-resume

task up
docker compose up

âš™ Config

homelab/docker/reactive-resume/.env

CONTAINER_NAME=reactive-resume

# -- Postgress --
POSTGRES_USER=postgres
POSTGRES_PASSWORD=postgres

# -- Minio --
MINIO_ROOT_USER=minioadmin
MINIO_ROOT_PASSWORD=minioadmin

# -- Auth --
ACCESS_TOKEN_SECRET=access_token_secret
REFRESH_TOKEN_SECRET=refresh_token_secret

# -- Storage (Minio) --
STORAGE_ACCESS_KEY=minioadmin
STORAGE_SECRET_KEY=minioadmin

# -- Chrome --
CHROME_TOKEN=chrome_token

# -- age backup --
# AGE_PUBLIC_KEYS=age123456
homelab/docker/reactive-resume/compose.yaml
name: reactive_resume

services:
  postgres:
    image: postgres:latest
    restart: unless-stopped
    environment:
      - POSTGRES_DB=postgres
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres
    volumes:
      - postgres_data:/var/lib/postgresql
    healthcheck:
      test: ["CMD", "pg_isready", "-U", "postgres", "-d", "postgres"]
      start_period: 10s
      interval: 30s
      timeout: 10s
      retries: 3

  browserless:
    image: ghcr.io/browserless/chromium:latest
    restart: unless-stopped
    environment:
      - QUEUED=10
      - HEALTH=true
      - CONCURRENT=5
      - TOKEN=1234567890
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/pressure?token=1234567890"]
      interval: 10s
      timeout: 5s
      retries: 10

  # As an alternative to browserless, you can also use a lightweight image like chromedp/headless-shell:latest
  # See https://docs.rxresu.me/self-hosting/docker#alternative-printer-options for more information.
  # chrome:
  #   image: chromedp/headless-shell:latest
  #   restart: unless-stopped
  #   ports:
  #     - "9222:9222"

  seaweedfs:
    image: chrislusf/seaweedfs:latest
    restart: unless-stopped
    command: server -s3 -filer -dir=/data -ip=0.0.0.0
    environment:
      - AWS_ACCESS_KEY_ID=seaweedfs
      - AWS_SECRET_ACCESS_KEY=seaweedfs
    volumes:
      - seaweedfs_data:/data
    healthcheck:
      test: ["CMD", "wget", "-q", "-O", "/dev/null", "http://localhost:8888"]
      start_period: 10s
      interval: 30s
      timeout: 10s
      retries: 3

  seaweedfs_create_bucket:
    image: quay.io/minio/mc:latest
    restart: on-failure
    entrypoint: >
      /bin/sh -c "
        sleep 5;
        mc alias set seaweedfs http://seaweedfs:8333 seaweedfs seaweedfs;
        mc mb seaweedfs/reactive-resume;
        exit 0;
      "
    depends_on:
      seaweedfs:
        condition: service_healthy

  reactive_resume:
    # image: amruthpillai/reactive-resume:latest
    image: ghcr.io/amruthpillai/reactive-resume:v5.0.16
    env_file:
      - .env
    environment:
      # Server
      - TZ=Etc/UTC
      - NODE_ENV=production
      # - APP_URL=http://localhost:3000
      - APP_URL=https://resume.l.nicholaswilde.io
      # - STORAGE_URL: http://192.168.2.147:9000/default

      - PRINTER_APP_URL=http://reactive_resume:3000
      # Printer
      - PRINTER_ENDPOINT=ws://browserless:3000?token=1234567890
      # - PRINTER_ENDPOINT=http://chrome:9222 # Or, if you're using chromedp/headless-shell
      # Database
      - DATABASE_URL=postgresql://postgres:postgres@postgres:5432/postgres
      # Authentication
      - AUTH_SECRET=change-me-to-a-secure-secret-key-in-production
      # Storage
      - S3_ACCESS_KEY_ID=seaweedfs
      - S3_SECRET_ACCESS_KEY=seaweedfs
      - S3_ENDPOINT=http://seaweedfs:8333
      - S3_BUCKET=reactive-resume
      - S3_FORCE_PATH_STYLE=true
    volumes:
      - reactive_resume_data:/app/data
    ports:
      - "3000:3000"
    depends_on:
      postgres:
        condition: service_healthy
      browserless:
        condition: service_healthy
      seaweedfs_create_bucket:
        condition: service_completed_successfully
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/api/health"]
      start_period: 10s
      interval: 30s
      timeout: 10s
      retries: 3

volumes:
  postgres_data:
  seaweedfs_data:
  reactive_resume_data:

Traefik

homelab/pve/traefik/conf.d/reactive-resume.yaml
---
http:
 #region routers 
  routers:
    reactive-resume:
      entryPoints:
        - "websecure"
      rule: "Host(`resume.l.nicholaswilde.io`)"
      middlewares:
        - default-headers@file
        - https-redirectscheme@file
      tls: {}
      service: reactive-resume
#endregion
#region services
  services:
    reactive-resume:
      loadBalancer:
        servers:
          - url: "http://192.168.2.147:3000"
        passHostHeader: true
#endregion
  middlewares:
    https-redirectscheme:
      redirectScheme:
        scheme: https
        permanent: true
    default-headers:
      headers:
        frameDeny: true
        browserXssFilter: true
        contentTypeNosniff: true
        forceSTSHeader: true
        stsIncludeSubdomains: true
        stsPreload: true
        stsSeconds: 15552000
        customFrameOptionsValue: SAMEORIGIN
        customRequestHeaders:
          X-Forwarded-Proto: https

    default-whitelist:
      ipAllowList:
        sourceRange:
        - "10.0.0.0/8"
        - "192.168.0.0/16"
        - "172.16.0.0/12"

    secured:
      chain:
        middlewares:
        - default-whitelist
        - default-headers

Task List

task: Available tasks for this project:
* backup:        Backup the application's volume data.
* decrypt:       Decrypt sensitive configuration files using SOPS.
* default:       List all available tasks.
* encrypt:       Encrypt sensitive configuration files using SOPS.
* export:        Export the task list to `task-list.txt`.
* init:          Initialize the application's environment and configuration files.
* pull:          Pull Docker images for the application.
* restart:       Restart the application's Docker containers.
* status:        Check the status of the application's Docker containers.
* stop:          Stop the application's Docker containers.
* up:            Run Docker Compose in the foreground.
* up-d:          Run Docker Compose in the background.
* update:        Update the application or its running containers.
* upgrade:       Upgrade the application by pulling the latest changes and updating.
* watch:         Watch the application's Docker container logs.

🔗 References