# Schedule Task Manager Tracks scheduled tasks (cron jobs, systemd timers) across your homelab servers, grouped by server and schedule type. Servers push their task list to this app via a small agent script; sign-in is delegated to Authentik (OIDC). v1 scope: Linux servers only (cron + systemd timers). Windows Task Scheduler support is a documented future addition — see [`agent/windows/README.md`](agent/windows/README.md). ## Architecture - `server/` — Express + TypeScript API, SQLite (via libSQL) storage, Authentik OIDC login. - `web/` — React + Vite single-page app, served as static files by the Express server. - `agent/linux/` — `report-tasks.sh` (collects cron + systemd timer data), `install.sh` (installs it as a systemd timer on a target server), and `uninstall.sh` (removes it). Data model, API contract, and sync behavior are documented in code: [`server/src/db/schema.ts`](server/src/db/schema.ts), [`server/src/routes/agentReport.ts`](server/src/routes/agentReport.ts), [`server/src/services/taskSync.ts`](server/src/services/taskSync.ts). ## 1. Set up an Authentik application In Authentik: 1. Create an **OAuth2/OpenID Provider**: - Redirect URI: `/auth/callback` (e.g. `https://schedule.example.lan/auth/callback`) - Scopes: `openid`, `email`, `profile` 2. Create an **Application** using that provider, and assign the users/groups who should be allowed to sign in — Authentik controls who can authenticate; the app itself has no separate user list. 3. Copy the provider's issuer URL, client ID, and client secret into `.env` (see `.env.example`). ## 2. Run with Docker (recommended) ```sh cp .env.example .env # edit .env: APP_BASE_URL, SESSION_SECRET, AUTHENTIK_* ``` Two compose files, depending on where the image comes from: - **`docker-compose.yml`** (production) — pulls `gitea.labsconnect.se/bobban/scheduletaskmanager-schedule-task-manager:latest`. Requires that image to already exist at that tag (pushed manually or by a CI pipeline) and, if the registry is private, `docker login gitea.labsconnect.se` first. ```sh docker compose pull docker compose up -d ``` - **`docker-compose.dev.yml`** — builds the image locally from source instead of pulling. Use this for local testing or before a build pipeline exists. ```sh docker compose -f docker-compose.dev.yml up -d --build ``` Either way, the app listens on `HOST_PORT` (default `3000`), and SQLite data and session files persist in `./data` on the host. ## 3. Local development Requires Node.js 20+. ```sh npm install cp .env.example .env # fill in AUTHENTIK_* to test real login, or leave # blank to run everything except /auth/login locally npm run dev:server # http://localhost:3000 (API) npm run dev:web # http://localhost:5173 (Vite dev server, proxies /api and /auth to :3000) ``` Visit `http://localhost:5173` during development. Database migrations run automatically on server start. ## 4. Add a server and install the agent 1. Sign in, go to **Servers**, and add a server. The generated API token is shown once — copy it. 2. On the target Linux server, as root. If you're not already root, put `sudo` right after the pipe so it elevates `bash`, not `curl` — `sudo curl ... | bash` would still fail the root check: ```sh curl -fsSL https://schedule.example.lan/agent/linux/install.sh | \ sudo API_URL=https://schedule.example.lan API_TOKEN=stm_xxx bash ``` This installs `report-tasks.sh` to `/usr/local/bin`, writes the API credentials to `/etc/schedule-task-manager-agent.env`, and installs a `schedule-task-manager-agent.timer` systemd timer that reports every 15 minutes (override with `INTERVAL_MINUTES=5` before the `bash` above). Requires `curl`, `jq`, and `systemd` on the target server — if either `curl` or `jq` is missing, both this script and `report-tasks.sh` print the right install command for the server's package manager (apt, dnf, yum, apk, pacman, or zypper) and exit. 3. Tasks appear on the Dashboard, grouped by server and then by schedule type, within one reporting interval. Tasks that stop appearing in a server's report are marked **stale** rather than deleted (so a temporary agent failure doesn't wipe history) and are hidden by default — toggle "Show stale/missing tasks" to see them. To remove the agent from a server, run: ```sh curl -fsSL https://schedule.example.lan/agent/linux/uninstall.sh | sudo bash ``` This stops and deletes the systemd timer/service, the installed script, and `/etc/schedule-task-manager-agent.env` (which holds the API token). It does not delete the server's entry or task history in the app — the same "Uninstall" button on the Servers page shows this command, and "Delete" removes the entry entirely if you no longer want it tracked. ## 5. Manually tracked tasks Not everything is discoverable by the agent — e.g. a scheduled job running inside a Docker container. Use **Add task** on the Dashboard to log those by hand. Manually entered tasks are never touched by agent reports (they have their own `origin`), so they won't be marked stale or overwritten by the next sync. ## Environment variables See [`.env.example`](.env.example) for the full list with descriptions.