Deploy JobSync — job search tracker on ringtail k3s #288

Merged
eblume merged 20 commits from mikado/jobsync into main 2026-03-08 11:02:06 -07:00
Owner

Summary

C2 Mikado chain to deploy JobSync — a self-hosted job application tracker — to ringtail's k3s cluster.

Mikado Graph

deploy-jobsync (goal)
├── build-jobsync-container
│   └── mirror-jobsync
└── integrate-jobsync-ollama

What is JobSync?

Next.js app with SQLite for tracking job applications. Features resume management, application pipeline tracking, and AI-powered resume review/job matching.

Key Decisions

  • Ringtail k3s (not minikube-indri) — colocates with Ollama for zero-latency AI
  • Nix container via buildLayeredImage — no Dockerfile, mirrors upstream source on forge
  • Ollama for AI — uses existing deployment, no API keys needed for AI features
  • No upstream fork — vanilla JobSync, Anthropic AI deferred to future work if needed

Current Status

Planning phase — cards committed, ready for review before implementation begins.

## Summary C2 Mikado chain to deploy [JobSync](https://github.com/Gsync/jobsync) — a self-hosted job application tracker — to ringtail's k3s cluster. ### Mikado Graph ``` deploy-jobsync (goal) ├── build-jobsync-container │ └── mirror-jobsync └── integrate-jobsync-ollama ``` ### What is JobSync? Next.js app with SQLite for tracking job applications. Features resume management, application pipeline tracking, and AI-powered resume review/job matching. ### Key Decisions - **Ringtail k3s** (not minikube-indri) — colocates with Ollama for zero-latency AI - **Nix container** via `buildLayeredImage` — no Dockerfile, mirrors upstream source on forge - **Ollama for AI** — uses existing deployment, no API keys needed for AI features - **No upstream fork** — vanilla JobSync, Anthropic AI deferred to future work if needed ### Current Status Planning phase — cards committed, ready for review before implementation begins.
Cards:
- deploy-jobsync (goal): Deploy JobSync to ringtail k3s via ArgoCD
- build-jobsync-container: Nix container build (buildLayeredImage)
- mirror-jobsync: Mirror upstream to forge
- integrate-jobsync-ollama: Wire up existing Ollama for AI features

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
eblume force-pushed mikado/jobsync from d479bc3140 to 9d8afbc743 2026-03-07 20:48:05 -08:00 Compare
Nix derivation for JobSync v1.1.4 container using buildLayeredImage.
Prefetches Prisma engines as Fixed-Output Derivations to avoid network
access in the nix sandbox. Patches Google Fonts import to system font
fallback. Verified building successfully on ringtail.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Ollama verified running on ringtail k3s (ollama.ollama.svc.cluster.local:11434)
with all documented models available. Integration is env var config in the
deployment manifest, handled by the root deploy-jobsync card.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
ArgoCD app, k8s manifests (deployment, service, PVC, ExternalSecret,
Tailscale ingress), and Caddy route for jobsync.ops.eblu.me.

1Password item "JobSync" created with auth_secret and encryption_key.
Container build v1.1.4 in progress.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
All manifests created: ArgoCD app, deployment, service, PVC, ExternalSecret,
Tailscale ingress, and Caddy route. 1Password secrets provisioned.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The nix container has no /app directory — the app lives at
/nix/store/<hash>/app/ and the container's WorkingDir is set
to that path. Remove the cd /app that caused @prisma/engines
to not be found.

Also add jobsync to service-versions.yaml.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Rebuilt with fixed entrypoint (no cd /app).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
eblume force-pushed mikado/jobsync from f0aef1f4c6 to 60507ee719 2026-03-07 22:00:27 -08:00 Compare
Mirror already exists at forge.ops.eblu.me/mirrors/jobsync from
previous cycle.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add containers/jobsync/default.nix (buildNpmPackage + dockerTools) and
entrypoint.sh (prisma migrate + node server.js). Hashes are empty
placeholders — will be filled from first build attempt on ringtail.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Use nixpkgs prisma-engines to avoid network downloads in nix sandbox.
Patch out Google Fonts import (Inter) since sandbox blocks network;
falls back to system sans-serif font stack.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
build-jobsync-container: Updated with lessons learned (prisma-engines
from nixpkgs, Google Fonts sandbox workaround, arm64 vs x86_64).
integrate-jobsync-ollama: Configuration-only card, env var will be
set in the deployment manifest.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
ArgoCD Application targeting ringtail k3s cluster.
Manifests: Deployment, Service, Tailscale Ingress, PVC (local-path),
ExternalSecret (1Password auth_secret + encryption_key).
Caddy route: jobsync.ops.eblu.me -> jobsync.tail8d86e.ts.net.
Ollama integration via OLLAMA_BASE_URL env var in deployment.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
npx is not available in the nix container. Call prisma directly via
node node_modules/prisma/build/index.js instead.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Point kustomization at the container with the fixed entrypoint.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The cp -r of @prisma/ into an existing node_modules/@prisma/ nested
incorrectly. Use cp -rn with glob to merge contents instead.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Container with fixed @prisma/engines copy and local prisma binary.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Prisma's get-platform module requires /tmp for temp files. Nix
containers don't create standard directories by default.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Container with /tmp directory fix for prisma get-platform.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Prisma CLI (devDep) has a deep transitive dependency tree that must
be present at runtime for `migrate deploy`. Skip npm prune entirely
and explicitly copy all prisma packages and their transitive deps
into the output.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Instead of bundling prisma CLI and its deep dependency tree in the nix
image, use `npx -y prisma@6.19.0 migrate deploy` like upstream does.
npx downloads prisma at container startup — network is available at
runtime, only blocked during nix build.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Simplified container with npx -y for prisma migrations.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
npx-downloaded prisma has `#!/usr/bin/env node` shebang. Nix containers
lack FHS paths; create the symlink in extraCommands.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Container with /usr/bin/env symlink for npx shebang resolution.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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>
eblume merged commit 3a811fb188 into main 2026-03-08 11:02:06 -07:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
eblume/blumeops!288
No description provided.