C2(jobsync): finalize — rework cards into standalone docs
Delete mirror-jobsync and integrate-jobsync-ollama (no standalone value). Rework build-jobsync-container and deploy-jobsync into operational reference documentation. Add changelog fragment. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
9d1e7eff12
commit
ae72092ed7
6 changed files with 54 additions and 129 deletions
1
docs/changelog.d/mikado-jobsync.feature.md
Normal file
1
docs/changelog.d/mikado-jobsync.feature.md
Normal file
|
|
@ -0,0 +1 @@
|
|||
Deploy JobSync to ringtail k3s — nix-built container, Tailscale Ingress, Caddy route at `jobsync.ops.eblu.me`, Ollama integration for AI features.
|
||||
|
|
@ -92,8 +92,6 @@ tags:
|
|||
|
||||
- [[deploy-jobsync]]
|
||||
- [[build-jobsync-container]]
|
||||
- [[mirror-jobsync]]
|
||||
- [[integrate-jobsync-ollama]]
|
||||
|
||||
## Forgejo Runner
|
||||
|
||||
|
|
|
|||
|
|
@ -1,70 +1,61 @@
|
|||
---
|
||||
title: Build JobSync Container
|
||||
modified: 2026-03-08
|
||||
requires:
|
||||
- mirror-jobsync
|
||||
tags:
|
||||
- how-to
|
||||
- jobsync
|
||||
- nix
|
||||
---
|
||||
|
||||
# Build JobSync Container
|
||||
|
||||
Build a nix container image for JobSync using `dockerTools.buildLayeredImage`, following the ntfy pattern.
|
||||
Build and release the JobSync nix container image.
|
||||
|
||||
## Context
|
||||
```fish
|
||||
mise run container-release jobsync 1.1.4
|
||||
```
|
||||
|
||||
JobSync is a Next.js standalone app with Prisma (SQLite). The nix build needs to:
|
||||
The derivation is at `containers/jobsync/default.nix`. It uses `buildNpmPackage` for the Next.js app and `dockerTools.buildLayeredImage` for the container. The entrypoint (`containers/jobsync/entrypoint.sh`) runs `prisma migrate deploy` then starts `node server.js`.
|
||||
|
||||
1. Fetch source from `forge.ops.eblu.me/mirrors/jobsync` (v1.1.4)
|
||||
2. `buildNpmPackage` — install deps, run `prisma generate`, run `next build`
|
||||
3. Package the standalone output with `nodejs` runtime into a layered image
|
||||
4. Include an entrypoint that runs `prisma migrate deploy` before `node server.js`
|
||||
## Upgrading JobSync
|
||||
|
||||
## Key Details
|
||||
1. Update the forge mirror: `mise run mirror-sync jobsync`
|
||||
2. Update `version` in `default.nix` to match the new upstream tag
|
||||
3. Clear `hash` in `fetchgit` (set to `""`), build, grab the correct hash from the error
|
||||
4. Clear `npmDepsHash` (set to `""`), build again, grab the correct hash
|
||||
5. Check if `postPatch` still applies — the Google Fonts import may change between versions
|
||||
6. `mise run container-release jobsync <new-version>`
|
||||
7. Update `newTag` in `argocd/manifests/jobsync/kustomization.yaml`
|
||||
|
||||
- **Runtime dependency:** `nodejs_20` must be in the image (unlike Go apps that compile to static binaries)
|
||||
- **Prisma native engine:** Use `pkgs.prisma-engines` from nixpkgs — do NOT let Prisma download engines at build time (nix sandbox blocks network)
|
||||
- **`npmDepsHash`:** Computed on first build (set to empty, let it fail, grab the hash)
|
||||
- **Standalone output:** Next.js `output: "standalone"` produces a self-contained `server.js` with minimal `node_modules`
|
||||
## Nix + Prisma + Next.js Pitfalls
|
||||
|
||||
## Nix Container Pitfalls
|
||||
### Prisma engine downloads blocked by sandbox
|
||||
|
||||
### Prisma engine downloads in nix sandbox
|
||||
Prisma tries to download platform-specific engine binaries during `prisma generate`. The nix sandbox blocks network access at build time.
|
||||
|
||||
Prisma tries to download platform-specific engine binaries during `prisma generate`. The nix sandbox blocks network access, causing the build to fail.
|
||||
**Fix:** Use `pkgs.prisma-engines` from nixpkgs and set env vars pointing at the nix store paths: `PRISMA_QUERY_ENGINE_LIBRARY`, `PRISMA_QUERY_ENGINE_BINARY`, `PRISMA_SCHEMA_ENGINE_BINARY`, `PRISMA_FMT_BINARY`. Set `PRISMA_ENGINES_CHECKSUM_IGNORE_MISSING=1` to tolerate minor version mismatch.
|
||||
|
||||
**Fix:** Use `pkgs.prisma-engines` from nixpkgs and set environment variables:
|
||||
- `PRISMA_QUERY_ENGINE_LIBRARY`, `PRISMA_QUERY_ENGINE_BINARY`, `PRISMA_SCHEMA_ENGINE_BINARY`, `PRISMA_FMT_BINARY` — point at nixpkgs engines
|
||||
- `PRISMA_ENGINES_CHECKSUM_IGNORE_MISSING=1` — tolerate minor version mismatch between nixpkgs engines and npm prisma package
|
||||
### Google Fonts blocked by sandbox
|
||||
|
||||
### Google Fonts blocked by nix sandbox
|
||||
|
||||
`next/font/google` (Inter font) fetches from `fonts.googleapis.com` during `next build`. Nix sandbox blocks this.
|
||||
`next/font/google` fetches from `fonts.googleapis.com` during `next build`.
|
||||
|
||||
**Fix:** Patch `src/app/layout.tsx` in `postPatch` to replace the Google font import with a no-op object. The app falls back to system sans-serif.
|
||||
|
||||
### Prisma devDependency pruning
|
||||
### Missing FHS paths in nix containers
|
||||
|
||||
`buildNpmPackage` runs `npm prune --omit=dev` between `buildPhase` and `installPhase`. The `prisma` CLI and `@prisma/engines` are devDependencies, so they get removed. But they're needed at runtime for `prisma migrate deploy` in the entrypoint.
|
||||
Nix containers lack `/usr/bin/env`, `/tmp`, etc. `npx`-downloaded packages use `#!/usr/bin/env node` shebangs.
|
||||
|
||||
**Fix:** Save prisma packages to a temp directory during `postBuild` (before prune), then copy them into the output during `installPhase`.
|
||||
**Fix:** In `extraCommands`: `mkdir -p tmp data usr/bin` and `ln -s ${pkgs.coreutils}/bin/env usr/bin/env`.
|
||||
|
||||
### Entrypoint filesystem paths
|
||||
### Runtime migrations via npx
|
||||
|
||||
Nix containers have no `/app` directory. The app lives at `/nix/store/<hash>/app/` and the container's `WorkingDir` is set to that path. The entrypoint must not `cd /app` — it should rely on the `WorkingDir` set in the container config.
|
||||
The nix sandbox blocks network at build time, but runtime has full network access. Use `npx -y prisma@<version> migrate deploy` in the entrypoint — npx downloads the prisma CLI on first run.
|
||||
|
||||
### Build on ringtail, not via Dagger
|
||||
|
||||
The Dagger `build-nix` pipeline runs in a container matching the host architecture. On macOS (arm64), this produces `linux-arm64` builds, which won't run on ringtail (x86_64). Build directly on ringtail or use the CI workflow.
|
||||
|
||||
## Files
|
||||
|
||||
- `containers/jobsync/default.nix` — nix derivation
|
||||
- `containers/jobsync/entrypoint.sh` — startup script (migrations + server)
|
||||
The Dagger `build-nix` pipeline runs in host architecture. On macOS (arm64), this produces arm64 images. Build on ringtail (x86_64) using the CI workflow or `mise run container-release`.
|
||||
|
||||
## Related
|
||||
|
||||
- [[mirror-jobsync]]
|
||||
- [[deploy-jobsync]]
|
||||
- [[build-container-image]]
|
||||
|
|
|
|||
|
|
@ -1,10 +1,6 @@
|
|||
---
|
||||
title: Deploy JobSync
|
||||
modified: 2026-03-08
|
||||
branch: mikado/jobsync
|
||||
requires:
|
||||
- build-jobsync-container
|
||||
- integrate-jobsync-ollama
|
||||
tags:
|
||||
- how-to
|
||||
- jobsync
|
||||
|
|
@ -12,21 +8,25 @@ tags:
|
|||
|
||||
# Deploy JobSync
|
||||
|
||||
Deploy [JobSync](https://github.com/Gsync/jobsync) — a self-hosted job application tracker — to ringtail's k3s cluster via ArgoCD.
|
||||
[JobSync](https://github.com/Gsync/jobsync) is a self-hosted job application tracker (Next.js + Prisma/SQLite) running on ringtail's k3s cluster via ArgoCD.
|
||||
|
||||
## Context
|
||||
- **URL:** `https://jobsync.ops.eblu.me`
|
||||
- **Auth:** Local accounts (email/password), no SSO
|
||||
- **Storage:** 5Gi PVC at `/data` (SQLite DB + resume uploads)
|
||||
- **AI:** Ollama at `ollama.ollama.svc.cluster.local:11434`
|
||||
|
||||
JobSync is a Next.js app with SQLite storage that provides job application tracking, resume management, and AI-powered resume review/job matching. It runs as a single container with persistent storage at `/data` (SQLite DB + uploaded files).
|
||||
## Manifests
|
||||
|
||||
## What This Card Covers
|
||||
All in `argocd/manifests/jobsync/`:
|
||||
|
||||
With the container built and Ollama integration configured, this card wires up the deployment:
|
||||
|
||||
- ArgoCD Application targeting `ringtail.tail8d86e.ts.net:6443`
|
||||
- k8s manifests: Deployment, Service, Tailscale Ingress, PVC, ExternalSecret
|
||||
- PVC using k3s local-path for `/data` (SQLite + resume uploads)
|
||||
- ExternalSecret for `ENCRYPTION_KEY` and `AUTH_SECRET` from 1Password
|
||||
- Caddy route: `jobsync.ops.eblu.me` → Tailscale ingress
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `deployment.yaml` | Single-replica deployment |
|
||||
| `service.yaml` | ClusterIP on port 3000 |
|
||||
| `ingress-tailscale.yaml` | Tailscale Ingress (ProxyGroup) |
|
||||
| `pvc.yaml` | 5Gi local-path for `/data` |
|
||||
| `external-secret.yaml` | `auth_secret` + `encryption_key` from 1Password |
|
||||
| `kustomization.yaml` | Image tag override |
|
||||
|
||||
## Environment Variables
|
||||
|
||||
|
|
@ -40,16 +40,21 @@ With the container built and Ollama integration configured, this card wires up t
|
|||
| `TZ` | Hardcoded | `America/Los_Angeles` |
|
||||
| `OLLAMA_BASE_URL` | Hardcoded | `http://ollama.ollama.svc.cluster.local:11434` |
|
||||
|
||||
## Deployment Notes
|
||||
## Updating the Container
|
||||
|
||||
- **`service-versions.yaml`:** Add a `jobsync` entry before committing container changes — the `container-version-check` pre-commit hook rejects commits touching `containers/<name>/` without a matching entry.
|
||||
- **Image tag format:** `container-build-and-release` produces tags like `v1.1.4-<sha>-nix`, not bare `v1.1.4`. Set `newTag` in `kustomization.yaml` to the full tag from `mise run container-list`.
|
||||
- **1Password item:** "JobSync" in blumeops vault, with `auth_secret` and `encryption_key` fields (already created).
|
||||
- **Nix container FHS:** Nix containers lack `/usr/bin/env` — add `ln -s ${pkgs.coreutils}/bin/env usr/bin/env` in `extraCommands`. Also `mkdir -p tmp` for `/tmp`.
|
||||
- **Runtime migrations:** Use `npx -y prisma@<version> migrate deploy` — nix sandbox blocks network at build time but runtime has full network access.
|
||||
1. Build and push: `mise run container-release jobsync <version>`
|
||||
2. Update `newTag` in `kustomization.yaml` to the full tag (e.g. `v1.1.4-e51ec83-nix`)
|
||||
3. Sync: `argocd app sync jobsync`
|
||||
|
||||
See [[build-jobsync-container]] for nix build details.
|
||||
|
||||
## Notes
|
||||
|
||||
- **1Password item:** "JobSync" in blumeops vault, fields `auth_secret` and `encryption_key`
|
||||
- **Caddy route:** `jobsync.ops.eblu.me` → `https://jobsync.tail8d86e.ts.net` (in `ansible/roles/caddy/defaults/main.yml`)
|
||||
- **`service-versions.yaml`:** Must have a `jobsync` entry or the pre-commit hook rejects container changes
|
||||
|
||||
## Related
|
||||
|
||||
- [[build-jobsync-container]]
|
||||
- [[integrate-jobsync-ollama]]
|
||||
- [[deploy-k8s-service]]
|
||||
|
|
|
|||
|
|
@ -1,44 +0,0 @@
|
|||
---
|
||||
title: Integrate JobSync with Ollama
|
||||
modified: 2026-03-08
|
||||
tags:
|
||||
- how-to
|
||||
- jobsync
|
||||
---
|
||||
|
||||
# Integrate JobSync with Ollama
|
||||
|
||||
Configure JobSync to use the existing Ollama deployment on ringtail for AI features (resume review, job matching).
|
||||
|
||||
## Context
|
||||
|
||||
Ollama already runs on ringtail's k3s cluster at `ollama.ollama.svc.cluster.local:11434` with several models available (qwen2.5:14b, deepseek-r1:14b, phi4:14b, gemma3:12b, qwen3.5:9b).
|
||||
|
||||
JobSync supports Ollama natively via `OLLAMA_BASE_URL`. Since both services run on the same k3s cluster, this is a cluster-internal connection with no auth required.
|
||||
|
||||
## Configuration
|
||||
|
||||
Set in the JobSync deployment manifest:
|
||||
|
||||
```yaml
|
||||
env:
|
||||
- name: OLLAMA_BASE_URL
|
||||
value: "http://ollama.ollama.svc.cluster.local:11434"
|
||||
```
|
||||
|
||||
## Verification
|
||||
|
||||
After deployment:
|
||||
|
||||
1. Open JobSync settings
|
||||
2. Select Ollama as the AI provider
|
||||
3. Verify model list populates from the Ollama instance
|
||||
4. Test resume review with one of the available models
|
||||
|
||||
## Model Recommendations
|
||||
|
||||
For resume review and job matching, `qwen2.5:14b` or `gemma3:12b` are good choices — capable enough for structured text analysis without being overly slow on the RTX 4080.
|
||||
|
||||
## Related
|
||||
|
||||
- [[deploy-jobsync]]
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
---
|
||||
title: Mirror JobSync
|
||||
modified: 2026-03-07
|
||||
tags:
|
||||
- how-to
|
||||
- jobsync
|
||||
---
|
||||
|
||||
# Mirror JobSync
|
||||
|
||||
Mirror the upstream [JobSync](https://github.com/Gsync/jobsync) repository to `forge.ops.eblu.me/mirrors/jobsync` for supply chain control.
|
||||
|
||||
## Context
|
||||
|
||||
JobSync is not in nixpkgs. Building a nix container requires fetching source from a controlled mirror on forge, following the same pattern as [[mirror-authentik-build-deps]] and the ntfy mirror.
|
||||
|
||||
## Steps
|
||||
|
||||
1. Create the mirror: `mise run mirror-create jobsync https://github.com/Gsync/jobsync.git`
|
||||
2. Verify the mirror syncs: check `forge.ops.eblu.me/mirrors/jobsync`
|
||||
3. Note the tag for v1.1.4 (current upstream release)
|
||||
|
||||
## Related
|
||||
|
||||
- [[build-jobsync-container]]
|
||||
- [[manage-forgejo-mirrors]]
|
||||
Loading…
Add table
Add a link
Reference in a new issue