Self-Hosting (Docker Compose)
The easiest way to run JobOps is via Docker Compose. The app is self-configuring and guides you through setup on first launch.
Prerequisites
- Docker Desktop or Docker Engine + Compose v2
1) Start the stack
No environment variables are required to boot:
docker compose up -d
This pulls the pre-built image from GHCR and starts the API, UI, and scrapers in one container.
To build locally instead:
docker compose up -d --build
2) Access the app and onboard
Open:
- Dashboard:
http://localhost:3005
The onboarding wizard helps you validate and save:
- LLM Provider: OpenRouter by default (or OpenAI/Gemini/local URL).
- Import your current resume: Either upload a PDF/DOCX into JobOps or choose the Reactive Resume option and connect with your v5 API key.
- Search terms: JobOps generates a first list of job-title search terms from your selected resume. Edit or regenerate them before saving.
- Basic Auth: Enable protection for write actions now or explicitly skip it for later.
Settings are saved to the local database.
Codex sign-in
For full Codex auth troubleshooting (including device-code authorization errors), see:
Gmail OAuth (Tracking Inbox)
If you want Gmail integration, configure OAuth credentials.
1) Create Google OAuth credentials
In Google Cloud:
- Configure OAuth consent screen.
- Enable Gmail API.
- Create OAuth client ID (
Web application). - Add redirect URI:
http://localhost:3005/oauth/gmail/callback- Or your production URL, for example
https://your-domain.com/oauth/gmail/callback
2) Configure environment variables
GMAIL_OAUTH_CLIENT_ID(required)GMAIL_OAUTH_CLIENT_SECRET(required)GMAIL_OAUTH_REDIRECT_URI(optional, recommended in production)
3) Restart and connect
- Restart container
- Open Tracking Inbox and click Connect Gmail
For a full step-by-step setup, exact scope requirements, and troubleshooting, see:
Email-to-job matching overview
flowchart TD
A[Recruitment email arrives in Gmail] --> B[Smart Router AI analyzes content]
B --> C{How confident is the match?}
C -->|95-100%| D[Auto-linked to job]
D --> E[Timeline updated automatically]
C -->|50-94%| F[Goes to Inbox for review with suggested job match]
C -->|<50%| G{Is it relevant?}
G -->|Yes| H[Goes to Inbox as orphan]
G -->|No| I[Ignored]
F --> J{User review}
H --> J
J -->|Approve| K[Linked to job + timeline update]
J -->|Ignore| L[Marked not relevant]
Persistent data
./data bind-mount stores:
- SQLite DB:
data/jobs.db - Generated PDFs:
data/pdfs/
Public demo mode
Set DEMO_MODE=true for sandbox deployments.
Behavior in demo mode:
- Works locally: browsing/filtering/status/timeline edits
- Simulated: pipeline run/summarize/process/rescore/pdf/apply
- Blocked: settings writes, DB clear, backups
- Auto-reset: every 6 hours
Updating
git pull
docker compose pull
docker compose up -d
Self-hosted Reactive Resume
If you self-host Reactive Resume, set:
RXRESUME_URL=http://rxresume.local.netRXRESUME_API_KEY=...(or configurerxresumeApiKeyin JobOps Settings)
Local LaTeX PDF rendering
JobOps supports 2 PDF renderers:
rxresume: export the final PDF through RxResumelatex: render locally from tailored resume data using LaTeX andtectonic
When using the LaTeX renderer:
- The Docker image installs
tectonicfor you. - For non-Docker local runs, install
tectonicyourself and optionally setTECTONIC_BINif it is not on yourPATH.
RxResume remains the source of truth for base resume data, project visibility, and tailoring inputs in both modes.