Operations
Dashboard
An optional web UI for watching jobs, schedules and run history.
Install
The dashboard ships with the package. There is nothing extra to install:
pip install fastapi-cronspip install fastapi-crons[dashboard] still works
Earlier versions documented a dashboard extra. It is kept as an empty extra so existing install commands and lockfiles keep working — it simply installs nothing beyond the base package.
Serving it
The dashboard is a route on the cron router. Mount the router and it is available at /dashboard underneath whatever prefix you chose.
from fastapi import FastAPI
from fastapi_crons import Crons, get_cron_router
app = FastAPI()
crons = Crons(app)
app.include_router(get_cron_router(), prefix="/api")
@crons.cron("*/5 * * * *", name="print_hello")
def print_hello():
print("Hello! I run every 5 minutes.")With the router mounted at /api, open:
http://127.0.0.1:8000/api/dashboardWhat it shows
The UI reads the same JSON the management endpoints expose, so it reflects whatever the API reports:
| Panel | Shows |
|---|---|
| Jobs | Every registered job, its cron expression and tags. |
| Schedule | Last run and next run times. |
| Status | Current status and the outcome of the most recent run. |
| Health | The result of the health endpoint. |
If the bundle is missing
Only possible if the package was built without its data files. The route answers 500 with a reinstall hint rather than an opaque traceback, and every other endpoint keeps working:
{
"detail": "The fastapi-crons dashboard bundle is missing from this installation.\nReinstall with: pip install --force-reinstall fastapi-crons"
}Securing it
The dashboard has no authentication of its own
It exposes job names, schedules and run history, and sits alongside the endpoint that can trigger a job on demand. Anyone who can reach the route can read all of it. Put it behind your own auth or keep it off the public internet.
The simplest approach is a router-level dependency, which covers the dashboard and the management endpoints together:
from fastapi import Depends, FastAPI, HTTPException, status
from fastapi.security import HTTPBasic, HTTPBasicCredentials
security = HTTPBasic()
def require_admin(credentials: HTTPBasicCredentials = Depends(security)):
if not is_valid_admin(credentials):
raise HTTPException(status.HTTP_401_UNAUTHORIZED)
# Everything under /api now requires authentication.
app.include_router(
get_cron_router(),
prefix="/api",
dependencies=[Depends(require_admin)],
)Alternatively, mount the router on an internal-only port, or restrict the path at your reverse proxy.
Size
The bundle is roughly 850 KB on disk, which compresses to about 270 KB in the wheel. That is the whole cost of having it built in, and it is why the dashboard is not gated behind an extra: a second distribution would have bought very little and cost a separate release train.