From f389533d1c1be73652d567c0d671b909d0215263 Mon Sep 17 00:00:00 2001 From: Erich Blume Date: Tue, 24 Mar 2026 08:43:19 -0700 Subject: [PATCH] Decommission JobSync service Remove ArgoCD app, k8s manifests, container build, Caddy proxy, Homepage entry, service-versions entry, and documentation. Runtime resources (ArgoCD app, k8s namespace, PVC) deleted via cascade. Forge mirror deleted, 1Password item archived, local clone removed. Replaced by datasette-based job tracking (to follow). Co-Authored-By: Claude Opus 4.6 (1M context) --- ansible/roles/caddy/defaults/main.yml | 3 - argocd/apps/jobsync.yaml | 18 --- argocd/manifests/homepage/services.yaml | 5 - argocd/manifests/jobsync/deployment.yaml | 78 ----------- argocd/manifests/jobsync/external-secret.yaml | 27 ---- .../manifests/jobsync/ingress-tailscale.yaml | 26 ---- argocd/manifests/jobsync/kustomization.yaml | 15 --- argocd/manifests/jobsync/pvc.yaml | 13 -- argocd/manifests/jobsync/service.yaml | 13 -- containers/jobsync/default.nix | 126 ------------------ containers/jobsync/entrypoint.sh | 15 --- .../changelog.d/decommission-jobsync.infra.md | 1 + .../how-to/jobsync/build-jobsync-container.md | 62 --------- docs/how-to/jobsync/deploy-jobsync.md | 74 ---------- docs/reference/infrastructure/ringtail.md | 1 - docs/reference/services/jobsync.md | 104 --------------- mise-tasks/services-check | 1 - service-versions.yaml | 7 - 18 files changed, 1 insertion(+), 588 deletions(-) delete mode 100644 argocd/apps/jobsync.yaml delete mode 100644 argocd/manifests/jobsync/deployment.yaml delete mode 100644 argocd/manifests/jobsync/external-secret.yaml delete mode 100644 argocd/manifests/jobsync/ingress-tailscale.yaml delete mode 100644 argocd/manifests/jobsync/kustomization.yaml delete mode 100644 argocd/manifests/jobsync/pvc.yaml delete mode 100644 argocd/manifests/jobsync/service.yaml delete mode 100644 containers/jobsync/default.nix delete mode 100644 containers/jobsync/entrypoint.sh create mode 100644 docs/changelog.d/decommission-jobsync.infra.md delete mode 100644 docs/how-to/jobsync/build-jobsync-container.md delete mode 100644 docs/how-to/jobsync/deploy-jobsync.md delete mode 100644 docs/reference/services/jobsync.md diff --git a/ansible/roles/caddy/defaults/main.yml b/ansible/roles/caddy/defaults/main.yml index dbf0b13..6b1ec61 100644 --- a/ansible/roles/caddy/defaults/main.yml +++ b/ansible/roles/caddy/defaults/main.yml @@ -85,9 +85,6 @@ caddy_services: - name: ntfy host: "ntfy.{{ caddy_domain }}" backend: "https://ntfy.tail8d86e.ts.net" - - name: jobsync - host: "jobsync.{{ caddy_domain }}" - backend: "https://jobsync.tail8d86e.ts.net" - name: ollama host: "ollama.{{ caddy_domain }}" backend: "https://ollama.tail8d86e.ts.net" diff --git a/argocd/apps/jobsync.yaml b/argocd/apps/jobsync.yaml deleted file mode 100644 index 11d8beb..0000000 --- a/argocd/apps/jobsync.yaml +++ /dev/null @@ -1,18 +0,0 @@ ---- -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: jobsync - namespace: argocd -spec: - project: default - source: - repoURL: ssh://forgejo@forge.ops.eblu.me:2222/eblume/blumeops.git - targetRevision: main - path: argocd/manifests/jobsync - destination: - server: https://ringtail.tail8d86e.ts.net:6443 - namespace: jobsync - syncPolicy: - syncOptions: - - CreateNamespace=true diff --git a/argocd/manifests/homepage/services.yaml b/argocd/manifests/homepage/services.yaml index 0305a42..58b8bb7 100644 --- a/argocd/manifests/homepage/services.yaml +++ b/argocd/manifests/homepage/services.yaml @@ -68,11 +68,6 @@ enableBlocks: true enableNowPlaying: false fields: ["movies", "series", "episodes"] -- Services: - - JobSync: - href: https://jobsync.ops.eblu.me - icon: mdi-briefcase-search - description: Job application tracker - Infrastructure: - Authentik: href: https://authentik.ops.eblu.me diff --git a/argocd/manifests/jobsync/deployment.yaml b/argocd/manifests/jobsync/deployment.yaml deleted file mode 100644 index be19a81..0000000 --- a/argocd/manifests/jobsync/deployment.yaml +++ /dev/null @@ -1,78 +0,0 @@ ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: jobsync - namespace: jobsync -spec: - replicas: 1 - strategy: - type: Recreate - selector: - matchLabels: - app: jobsync - template: - metadata: - labels: - app: jobsync - spec: - containers: - - name: jobsync - image: blumeops/jobsync:kustomized - ports: - - containerPort: 3000 - name: http - env: - - name: DATABASE_URL - value: "file:/data/dev.db" - - name: NEXTAUTH_URL - value: "https://jobsync.ops.eblu.me" - - name: AUTH_TRUST_HOST - value: "true" - - name: NEXT_TELEMETRY_DISABLED - value: "1" - - name: TZ - value: "America/Los_Angeles" - - name: OLLAMA_BASE_URL - value: "http://ollama.ollama.svc.cluster.local:11434" - - name: AUTH_SECRET - valueFrom: - secretKeyRef: - name: jobsync-secrets - key: auth_secret - - name: ENCRYPTION_KEY - valueFrom: - secretKeyRef: - name: jobsync-secrets - key: encryption_key - - name: RAPIDAPI_KEY - valueFrom: - secretKeyRef: - name: jobsync-secrets - key: rapidapi_key - volumeMounts: - - name: data - mountPath: /data - resources: - requests: - memory: "256Mi" - cpu: "100m" - limits: - memory: "512Mi" - cpu: "500m" - livenessProbe: - httpGet: - path: / - port: 3000 - initialDelaySeconds: 30 - periodSeconds: 30 - readinessProbe: - httpGet: - path: / - port: 3000 - initialDelaySeconds: 10 - periodSeconds: 10 - volumes: - - name: data - persistentVolumeClaim: - claimName: jobsync-data diff --git a/argocd/manifests/jobsync/external-secret.yaml b/argocd/manifests/jobsync/external-secret.yaml deleted file mode 100644 index 39d58dc..0000000 --- a/argocd/manifests/jobsync/external-secret.yaml +++ /dev/null @@ -1,27 +0,0 @@ ---- -apiVersion: external-secrets.io/v1 -kind: ExternalSecret -metadata: - name: jobsync-secrets - namespace: jobsync -spec: - refreshInterval: 1h - secretStoreRef: - kind: ClusterSecretStore - name: onepassword-blumeops - target: - name: jobsync-secrets - creationPolicy: Owner - data: - - secretKey: auth_secret - remoteRef: - key: JobSync - property: auth_secret - - secretKey: encryption_key - remoteRef: - key: JobSync - property: encryption_key - - secretKey: rapidapi_key - remoteRef: - key: JobSync - property: rapidapi_key diff --git a/argocd/manifests/jobsync/ingress-tailscale.yaml b/argocd/manifests/jobsync/ingress-tailscale.yaml deleted file mode 100644 index 54b7ce6..0000000 --- a/argocd/manifests/jobsync/ingress-tailscale.yaml +++ /dev/null @@ -1,26 +0,0 @@ ---- -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: jobsync-tailscale - namespace: jobsync - annotations: - tailscale.com/proxy-class: "default" - tailscale.com/proxy-group: "ingress" - gethomepage.dev/enabled: "true" - gethomepage.dev/name: "JobSync" - gethomepage.dev/group: "Services" - gethomepage.dev/icon: "mdi-briefcase-search" - gethomepage.dev/description: "Job application tracker" - gethomepage.dev/href: "https://jobsync.ops.eblu.me" - gethomepage.dev/pod-selector: "app=jobsync" -spec: - ingressClassName: tailscale - defaultBackend: - service: - name: jobsync - port: - number: 3000 - tls: - - hosts: - - jobsync diff --git a/argocd/manifests/jobsync/kustomization.yaml b/argocd/manifests/jobsync/kustomization.yaml deleted file mode 100644 index 7929f1e..0000000 --- a/argocd/manifests/jobsync/kustomization.yaml +++ /dev/null @@ -1,15 +0,0 @@ ---- -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization -namespace: jobsync -resources: - - pvc.yaml - - external-secret.yaml - - deployment.yaml - - service.yaml - - ingress-tailscale.yaml - -images: - - name: blumeops/jobsync - newName: registry.ops.eblu.me/blumeops/jobsync - newTag: "v1.1.4-3a811fb-nix" diff --git a/argocd/manifests/jobsync/pvc.yaml b/argocd/manifests/jobsync/pvc.yaml deleted file mode 100644 index 01ab796..0000000 --- a/argocd/manifests/jobsync/pvc.yaml +++ /dev/null @@ -1,13 +0,0 @@ ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: jobsync-data - namespace: jobsync -spec: - accessModes: - - ReadWriteOnce - storageClassName: local-path - resources: - requests: - storage: 5Gi diff --git a/argocd/manifests/jobsync/service.yaml b/argocd/manifests/jobsync/service.yaml deleted file mode 100644 index dc2d73a..0000000 --- a/argocd/manifests/jobsync/service.yaml +++ /dev/null @@ -1,13 +0,0 @@ ---- -apiVersion: v1 -kind: Service -metadata: - name: jobsync - namespace: jobsync -spec: - selector: - app: jobsync - ports: - - name: http - port: 3000 - targetPort: 3000 diff --git a/containers/jobsync/default.nix b/containers/jobsync/default.nix deleted file mode 100644 index 198dd70..0000000 --- a/containers/jobsync/default.nix +++ /dev/null @@ -1,126 +0,0 @@ -# Nix-built JobSync container -# Next.js job application tracker with Prisma/SQLite -# Built with dockerTools.buildLayeredImage for efficient layer caching -{ pkgs ? import { } }: - -let - version = "1.1.4"; - - prismaEngines = pkgs.prisma-engines; - - src = pkgs.fetchgit { - url = "https://forge.ops.eblu.me/mirrors/jobsync.git"; - rev = "v${version}"; - hash = "sha256-59W5OF36yD67jEK5xa9jSL4EVN9RG+Ez/w9Mq2VykSA="; - }; - - jobsync = pkgs.buildNpmPackage { - inherit src version; - pname = "jobsync"; - npmDepsHash = "sha256-yRNOxtz66qSlmfjR3QDPUQe0C8sdg06tBbuK1Ws1gEA="; - - nodejs = pkgs.nodejs_20; - - # Patch out Google Fonts import (nix sandbox blocks network access at - # build time). Replace with a simple object; app uses system sans-serif. - postPatch = '' - substituteInPlace src/app/layout.tsx \ - --replace-fail 'import { Inter } from "next/font/google";' "" \ - --replace-fail 'const inter = Inter({ - subsets: ["latin"], - variable: "--font-inter", -});' 'const inter = { variable: "" };' - ''; - - # Point Prisma at nixpkgs-built engines (no network download in sandbox) - env = { - PRISMA_QUERY_ENGINE_LIBRARY = "${prismaEngines}/lib/libquery_engine.node"; - PRISMA_QUERY_ENGINE_BINARY = "${prismaEngines}/bin/query-engine"; - PRISMA_SCHEMA_ENGINE_BINARY = "${prismaEngines}/bin/schema-engine"; - PRISMA_FMT_BINARY = "${prismaEngines}/bin/prisma-fmt"; - PRISMA_ENGINES_CHECKSUM_IGNORE_MISSING = "1"; - DATABASE_URL = "file:/tmp/build.db"; - NEXT_TELEMETRY_DISABLED = "1"; - }; - - buildPhase = '' - runHook preBuild - - # Generate Prisma client using nixpkgs engines - npx prisma generate - - # Build Next.js - npm run build - - runHook postBuild - ''; - - installPhase = '' - runHook preInstall - - mkdir -p $out/app - - # Copy Next.js standalone output - cp -r .next/standalone/. $out/app/ - cp -r .next/static $out/app/.next/static - cp -r public $out/app/public - - # Copy Prisma schema and migrations for runtime migrate deploy - cp -r prisma $out/app/prisma - - # Copy entrypoint - cp ${./entrypoint.sh} $out/app/entrypoint.sh - - runHook postInstall - ''; - - dontNpmBuild = true; - }; - - entrypoint = pkgs.writeShellScript "jobsync-entrypoint" '' - cd ${jobsync}/app - exec ${pkgs.bash}/bin/bash entrypoint.sh "$@" - ''; -in - -pkgs.dockerTools.buildLayeredImage { - name = "blumeops/jobsync"; - tag = "latest"; - - contents = [ - jobsync - prismaEngines - pkgs.nodejs_20 - pkgs.cacert - pkgs.tzdata - pkgs.bash - pkgs.coreutils - ]; - - # Create writable directories and FHS symlinks for nix container - extraCommands = '' - mkdir -p tmp data usr/bin - ln -s ${pkgs.coreutils}/bin/env usr/bin/env - ''; - - config = { - Entrypoint = [ "${entrypoint}" ]; - WorkingDir = "${jobsync}/app"; - Env = [ - "SSL_CERT_FILE=${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt" - "TZDIR=${pkgs.tzdata}/share/zoneinfo" - "NODE_ENV=production" - "PORT=3000" - "DATABASE_URL=file:/data/dev.db" - "PRISMA_QUERY_ENGINE_LIBRARY=${prismaEngines}/lib/libquery_engine.node" - "PRISMA_SCHEMA_ENGINE_BINARY=${prismaEngines}/bin/schema-engine" - "PRISMA_ENGINES_CHECKSUM_IGNORE_MISSING=1" - ]; - ExposedPorts = { - "3000/tcp" = { }; - }; - Volumes = { - "/data" = { }; - }; - }; -} diff --git a/containers/jobsync/entrypoint.sh b/containers/jobsync/entrypoint.sh deleted file mode 100644 index 4dc611f..0000000 --- a/containers/jobsync/entrypoint.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/sh -set -e - -# Auto-generate AUTH_SECRET if not provided -if [ -z "$AUTH_SECRET" ]; then - AUTH_SECRET="$(node -e "console.log(require('crypto').randomBytes(32).toString('base64'))")" - export AUTH_SECRET - echo "AUTH_SECRET was not set — generated a temporary secret for this container." -fi - -# Run Prisma migrations (npx -y downloads prisma if not in local node_modules) -npx -y prisma@6.19.0 migrate deploy - -# Start the Next.js server -exec node server.js diff --git a/docs/changelog.d/decommission-jobsync.infra.md b/docs/changelog.d/decommission-jobsync.infra.md new file mode 100644 index 0000000..c0e81ee --- /dev/null +++ b/docs/changelog.d/decommission-jobsync.infra.md @@ -0,0 +1 @@ +Decommission JobSync service — removed ArgoCD app, k8s manifests, container build, Caddy proxy, Homepage entry, docs, and forge mirror. Replaced by datasette-based job tracking (coming soon). diff --git a/docs/how-to/jobsync/build-jobsync-container.md b/docs/how-to/jobsync/build-jobsync-container.md deleted file mode 100644 index d9653e9..0000000 --- a/docs/how-to/jobsync/build-jobsync-container.md +++ /dev/null @@ -1,62 +0,0 @@ ---- -title: Build JobSync Container -modified: 2026-03-11 -last-reviewed: 2026-03-11 -tags: - - how-to - - jobsync - - nix ---- - -# Build JobSync Container - -Build and release the JobSync nix container image. - -```fish -mise run container-release jobsync 1.1.4 -``` - -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`. - -## Upgrading JobSync - -1. Verify the forge mirror is current: check `https://forge.eblu.me/mirrors/jobsync` (mirrors sync automatically) -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 ` -7. Update `newTag` in `argocd/manifests/jobsync/kustomization.yaml` - -## Nix + Prisma + Next.js Pitfalls - -### Prisma engine downloads blocked by sandbox - -Prisma tries to download platform-specific engine binaries during `prisma generate`. The nix sandbox blocks network access at build time. - -**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. - -### Google Fonts blocked by sandbox - -`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. - -### Missing FHS paths in nix containers - -Nix containers lack `/usr/bin/env`, `/tmp`, etc. `npx`-downloaded packages use `#!/usr/bin/env node` shebangs. - -**Fix:** In `extraCommands`: `mkdir -p tmp data usr/bin` and `ln -s ${pkgs.coreutils}/bin/env usr/bin/env`. - -### Runtime migrations via npx - -The nix sandbox blocks network at build time, but runtime has full network access. Use `npx -y prisma@ 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 host architecture. On macOS (arm64), this produces arm64 images. Build on ringtail (x86_64) using the CI workflow or `mise run container-release`. - -## Related - -- [[deploy-jobsync]] -- [[build-container-image]] diff --git a/docs/how-to/jobsync/deploy-jobsync.md b/docs/how-to/jobsync/deploy-jobsync.md deleted file mode 100644 index 325af62..0000000 --- a/docs/how-to/jobsync/deploy-jobsync.md +++ /dev/null @@ -1,74 +0,0 @@ ---- -title: Deploy JobSync -modified: 2026-03-13 -last-reviewed: 2026-03-13 -tags: - - how-to - - jobsync ---- - -# Deploy JobSync - -[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. - -- **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` - -## Manifests - -All in `argocd/manifests/jobsync/`: - -| 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 - -| Variable | Source | Purpose | -|----------|--------|---------| -| `DATABASE_URL` | Hardcoded | `file:/data/dev.db` | -| `AUTH_SECRET` | ExternalSecret | NextAuth session signing | -| `ENCRYPTION_KEY` | ExternalSecret | AES-256-GCM for stored API keys | -| `NEXTAUTH_URL` | Hardcoded | `https://jobsync.ops.eblu.me` | -| `AUTH_TRUST_HOST` | Hardcoded | `true` | -| `NEXT_TELEMETRY_DISABLED` | Hardcoded | `1` (opt out of Next.js telemetry) | -| `TZ` | Hardcoded | `America/Los_Angeles` | -| `OLLAMA_BASE_URL` | Hardcoded | `http://ollama.ollama.svc.cluster.local:11434` | -| `RAPIDAPI_KEY` | ExternalSecret | JSearch job search API key | - -## Updating the Container - -1. Build and push: `mise run container-release jobsync ` -2. Update `newTag` in `kustomization.yaml` to the full tag (e.g. `v1.1.4-3a811fb-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`, `encryption_key`, and `rapidapi_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 - -## Observability - -JobSync has no metrics endpoint. Logs are collected by Alloy on ringtail and shipped to Loki. Query in Grafana: - -```logql -{namespace="jobsync", app="jobsync"} -``` - -The app runs a scheduled job search daily at 4 AM. Search failures appear in logs during those executions. - -## Related - -- [[jobsync]] — Service reference card -- [[build-jobsync-container]] -- [[deploy-k8s-service]] diff --git a/docs/reference/infrastructure/ringtail.md b/docs/reference/infrastructure/ringtail.md index 74d5a7d..95d6ee2 100644 --- a/docs/reference/infrastructure/ringtail.md +++ b/docs/reference/infrastructure/ringtail.md @@ -70,7 +70,6 @@ Sync order: `1password-connect-ringtail` -> `external-secrets-crds-ringtail` -> | [[authentik]] | `authentik` | OIDC identity provider | | [[ntfy]] | `ntfy` | Push notification server | | [[ollama]] | `ollama` | LLM inference with GPU (RTX 4080) | -| [[jobsync]] | `jobsync` | Job application tracker | | nvidia-device-plugin | `nvidia-device-plugin` | Exposes GPU to pods via CDI + nvidia RuntimeClass | ### Manual Cluster Registration diff --git a/docs/reference/services/jobsync.md b/docs/reference/services/jobsync.md deleted file mode 100644 index 0a28de4..0000000 --- a/docs/reference/services/jobsync.md +++ /dev/null @@ -1,104 +0,0 @@ ---- -title: JobSync -modified: 2026-03-08 -tags: - - service - - job-search ---- - -# JobSync - -Self-hosted job application tracker. Tracks job applications, automates job searching via the JSearch API, and provides AI-powered resume tailoring via [[ollama|Ollama]]. - -## Quick Reference - -| Property | Value | -|----------|-------| -| **URL** | https://jobsync.ops.eblu.me | -| **Tailscale URL** | https://jobsync.tail8d86e.ts.net | -| **Namespace** | `jobsync` | -| **Cluster** | ringtail k3s | -| **Image** | `blumeops/jobsync` (Nix-built) | -| **Upstream** | https://github.com/Gsync/jobsync | -| **Manifests** | `argocd/manifests/jobsync/` | -| **Port** | 3000 | - -## Architecture - -``` -Browser ──HTTPS──► Caddy (jobsync.ops.eblu.me) - │ - ▼ - Tailscale ProxyGroup - │ - ▼ - JobSync (Next.js) - ┌───────┴───────┐ - │ │ - SQLite (/data) Ollama (in-cluster) - │ │ - PVC 5Gi GPU-accelerated LLM -``` - -- **Framework:** Next.js 15 + Prisma ORM -- **Database:** SQLite on a 5Gi PVC at `/data` -- **Auth:** Local email/password accounts (NextAuth v5), no SSO -- **AI:** Ollama at `http://ollama.ollama.svc.cluster.local:11434` for resume tailoring -- **Job Search:** JSearch API via RapidAPI (requires `RAPIDAPI_KEY`) - -## Job Search (JSearch / RapidAPI) - -The automated job search feature uses the [JSearch API](https://rapidapi.com/letscrape-6bRBa3QguO5/api/jsearch) on RapidAPI. The API key can be configured two ways (checked in order): - -1. **Per-user:** Added via Settings > API Keys in the web UI (encrypted with `ENCRYPTION_KEY`) -2. **Environment variable:** `RAPIDAPI_KEY` env var as a fallback for all users - -Without either, job search automations fail with: `Search failed: network - RAPIDAPI_KEY is not configured` - -The free tier allows 200 requests/month. The key is stored in 1Password ("JobSync" item, `rapidapi_key` field) and synced via ExternalSecret. - -## Secrets - -All secrets are in the **JobSync** 1Password item (blumeops vault), synced by ExternalSecret: - -| Secret | 1Password Field | Purpose | -|--------|-----------------|---------| -| `auth_secret` | `auth_secret` | NextAuth session signing | -| `encryption_key` | `encryption_key` | AES-256-GCM for stored API keys | -| `rapidapi_key` | `rapidapi_key` | JSearch job search API | - -## Observability - -JobSync has no metrics endpoint or Grafana dashboard. Logs are collected by [[alloy|Alloy]] on ringtail and shipped to Loki on indri. - -**Querying logs in Grafana:** - -```logql -{namespace="jobsync", app="jobsync"} -``` - -To search for job search errors specifically: - -```logql -{namespace="jobsync", app="jobsync"} |~ "(?i)(rapid|search failed|error)" -``` - -The app runs a scheduled job search daily at 4 AM. Failures appear in logs during those executions. - -## Container - -Built with Nix on ringtail (x86_64). See [[build-jobsync-container]] for details. - -```fish -mise run container-release jobsync -``` - -Update `newTag` in `argocd/manifests/jobsync/kustomization.yaml` after building, then `argocd app sync jobsync`. - -## Related - -- [[ollama]] — AI backend for resume tailoring -- [[ringtail]] — Host node -- [[deploy-jobsync]] — Deployment how-to -- [[build-jobsync-container]] — Container build guide -- [[apps]] — ArgoCD application registry diff --git a/mise-tasks/services-check b/mise-tasks/services-check index 9ba2c8e..2417f74 100755 --- a/mise-tasks/services-check +++ b/mise-tasks/services-check @@ -161,7 +161,6 @@ check_http "CV" "https://cv.ops.eblu.me/" check_http "Ntfy" "https://ntfy.ops.eblu.me/v1/health" check_http "Authentik" "https://authentik.ops.eblu.me/-/health/live/" check_http "Frigate" "https://nvr.ops.eblu.me/api/version" -check_http "JobSync" "https://jobsync.ops.eblu.me/" echo "" echo "Frigate (via alerting):" diff --git a/service-versions.yaml b/service-versions.yaml index 2711b32..370e134 100644 --- a/service-versions.yaml +++ b/service-versions.yaml @@ -157,13 +157,6 @@ services: current-version: "2026.2.0" upstream-source: https://github.com/goauthentik/authentik/releases - - name: jobsync - type: argocd - last-reviewed: 2026-03-11 - current-version: "1.1.4" - upstream-source: https://github.com/Gsync/jobsync/releases - notes: Job application tracker; nix container on ringtail k3s - - name: ollama type: argocd last-reviewed: "2026-03-02"