{"id":24708359,"url":"https://github.com/surface-security/django-dkron","last_synced_at":"2025-10-09T10:32:10.579Z","repository":{"id":37933719,"uuid":"448953171","full_name":"surface-security/django-dkron","owner":"surface-security","description":"Manage and run jobs in Dkron from your django project","archived":false,"fork":false,"pushed_at":"2024-02-16T14:41:52.000Z","size":127,"stargazers_count":1,"open_issues_count":6,"forks_count":1,"subscribers_count":2,"default_branch":"develop","last_synced_at":"2025-01-14T22:53:00.906Z","etag":null,"topics":["django","dkron"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/surface-security.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-01-17T15:43:12.000Z","updated_at":"2023-03-19T10:11:56.000Z","dependencies_parsed_at":"2022-09-02T10:52:12.179Z","dependency_job_id":null,"html_url":"https://github.com/surface-security/django-dkron","commit_stats":null,"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/surface-security%2Fdjango-dkron","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/surface-security%2Fdjango-dkron/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/surface-security%2Fdjango-dkron/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/surface-security%2Fdjango-dkron/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/surface-security","download_url":"https://codeload.github.com/surface-security/django-dkron/tar.gz/refs/heads/develop","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":235812503,"owners_count":19048924,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["django","dkron"],"created_at":"2025-01-27T06:31:38.989Z","updated_at":"2025-10-09T10:32:05.266Z","avatar_url":"https://github.com/surface-security.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# django-dkron\n\n[![build-status-image]][build-status]\n[![coverage-status-image]][codecov]\n[![pypi-version]][pypi]\n\n**Manage and run jobs in Dkron from your django project**\n\n* Command to launch dkron agent `run_dkron`\n* django-admin integration for managing dkron jobs\n* notifications ([django-notification-sender](https://github.com/surface-security/django-notification-sender)) on failed jobs\n* reverse proxy for dkron dashboard to leverage django authenticated user permissions\n* `run_async` utility method to launch long running tasks (in a one-time temporary dkron job)\n\n![image](https://user-images.githubusercontent.com/63779195/152008384-51dd34d5-f0f8-4e68-ab3a-32d92f2aeb43.png)\n\n## Setup\n\nAdd `dkron` to `INSTALLED_APPS` in your `settings.py`.\n\nThe following app settings are available for customization (from [dkron/apps.py](dkron/apps.py))\n\n| Name | Default | Description |\n| ---- | -----   | -------     |\n| DKRON_URL | `http://localhost:8888` | dkron server URL |\n| DKRON_PATH |  | used to build browser-visible URLs to dkron - can be a full URL if no reverse proxy is being used |\n| DKRON_BIN_DIR | | directory to store and execute the dkron binaries, defaults to temporary one - hardly optimal, do set one up! |\n| DKRON_VERSION | `3.2.7` | dkron version to (download and) use |\n| DKRON_DOWNLOAD_URL_TEMPLATE | `https://github.com/distribworks/dkron/releases/download/v{version}/dkron_{version}_{system}_{machine}.tar.gz` | can be changed in case a dkron fork is meant to be used |\n| DKRON_SERVER | `False` | always `run_dkron` in server mode |\n| DKRON_TAGS | `[]` | tags for the agent/server created by `run_dkron` - `label=` tag is not required as it is added by `DKRON_JOB_LABEL` |\n| DKRON_JOB_LABEL | | label for the jobs managed by this app, used to make this app agent run only jobs created by this app |\n| DKRON_JOIN | `[]` | --join when using `run_dkron` |\n| DKRON_WORKDIR |  | workdir of `run_dkron` |\n| DKRON_ENCRYPT |  | gossip encrypt key for `run_dkron` |\n| DKRON_API_AUTH |  | HTTP Basic auth header value, if dkron instance is protected with it (really recommended, if instance is exposed) |\n| DKRON_TOKEN |  | Token used by `run_dkron` for webhook calls into this app |\n| DKRON_PRE_WEBHOOK_URL |  | URL called by dkron webhooks to post job start to this app - passed as `--pre-webhook-url` to dkron, so you need to map `dkron.views.pre_webhook` in your project urls.py and this should be full URL to that route and reachable by dkron. Requires DKRON_SENTRY_CRON_URL otherwise nothing would happen. |\n| DKRON_WEBHOOK_URL |  | URL called by dkron webhooks to post job status to this app - passed as `--webhook-url` to dkron, so you need to map `dkron.views.webhook` in your project urls.py and this should be full URL to that route and reachable by dkron |\n| DKRON_NAMESPACE | | string to be prefixed to each job created by this app in dkron so the same dkron cluster can be used by different apps/instances without conflicting job names (assuming unique namespaces ^^) |\n| DKRON_SENTRY_CRON_URL | Optional Sentry URL used for monitoring jobs. Use placeholder `\u003cmonitor_slug\u003e` in URL for job name. |\n\nBesides starting the django app (with `./manage.py runserver`, `gunicorn` or similar) also start dkron agent with `./manage.py run_dkron`:\n\n```\n$ ./manage.py run_dkron -h\nusage: manage.py run_dkron [-h] [-s] [-p HTTP_ADDR] [-j JOIN] [-e ENCRYPT] [--version] [-v {0,1,2,3}] [--settings SETTINGS] [--pythonpath PYTHONPATH] [--traceback] [--no-color] [--force-color]\n                           [--skip-checks]\n\nRun dkron agent\n\noptional arguments:\n  -h, --help            show this help message and exit\n  -s, --server          Run in server mode\n  -p HTTP_ADDR, --http-addr HTTP_ADDR\n                        Port used by the web UI\n  -j JOIN, --join JOIN  Initial agent(s) to join with (can be used multiple times)\n  -e ENCRYPT, --encrypt ENCRYPT\n                        Key for encrypting network traffic. Must be a base64-encoded 16-byte key\n  --version             show program's version number and exit\n  -v {0,1,2,3}, --verbosity {0,1,2,3}\n                        Verbosity level; 0=minimal output, 1=normal output, 2=verbose output, 3=very verbose output\n  --settings SETTINGS   The Python path to a settings module, e.g. \"myproject.settings.main\". If this isn't provided, the DJANGO_SETTINGS_MODULE environment variable will be used.\n  --pythonpath PYTHONPATH\n                        A directory to add to the Python path, e.g. \"/home/djangoprojects/myproject\".\n  --traceback           Raise on CommandError exceptions\n  --no-color            Don't colorize the command output.\n  --force-color         Force colorization of the command output.\n  --skip-checks         Skip system checks.\n```\n\n## Background tasks\n\nBesides managing the scheduled jobs in django-admin, this app also has the [run_async](https://github.com/surface-security/django-dkron/blob/8df5dbdbd1392b07dcedd4c7bc402cb948f64fc7/dkron/utils.py#L219) utility method to run one-time temporary jobs.\n\n```python\nfrom dkron.utils import run_async\njob_name, job_link = utils.run_async('some_management_command', 'arg1', kwarg='value', enable=True)\n```\n\nThis will return the `job_name` (`tmp_some_management_command_1` in example) created in Dkron and `job_link` (`/dkron/proxy/ui/#/jobs/tmp_somecommand_1/show/executions` in example) as the direct link to the job executions in Dkron UI (this uses the setting `DKRON_PATH` to build the link).\n\nIf dkron is not running, `run_async` falls back to [after-response](https://github.com/defrex/django-after-response) to simplify the dev setup of your project.\n\n## Authentication\n\nDkron does not have authorization (nor authentication). The [Pro](https://dkron.io/products/pro/) version does (and you should definitely get it if you're using it in a paid product/service :)) but this app provides a way to authenticate seamlessly to the Dkron dashboard from your project, by proxying access.\n\nThere are two options: native django (default) and using nginx (or similar)\n\n### django\n\nThis is the simplest way to implement it. Do not set `DKRON_PATH` setting, as it will default to this but do set `DKRON_URL` properly so the app can access dkron instance.\n\nThis is will use [dkron.views.proxy](https://github.com/surface-security/django-dkron/blob/8df5dbdbd1392b07dcedd4c7bc402cb948f64fc7/dkron/views.py#L61) to forward any requests to `/dkron/_/` to Dkron URL, but not before requiring a valid django session with the permission `dkron.can_use_dashboard` (or superuser).\n\nThis does make every user access to Dkron UI to go through the full django project stack (and `MIDDLEWARE`s). If that's an issue (shouldn't be...), the old approach (using `nginx` with `proxy_pass` and `auth_request`) might interest you.\n\n### nginx\n\nThis was the original setup to leverage django sessions to access Dkron UI.\n\n`nginx` might already be part of your production stack for caching and serving static files, so it's just adding an extra location to it.\n\n```\nhttp {\n  ...\n  upstream dkronserver {\n    server DKRON_SERVER_IP:DKRON_SERVER_PORT fail_timeout=0;\n  }\n  upstream appserver {\n    server DJANGO_SERVER_IP:DJANGO_SERVER_PORT fail_timeout=0;\n  }\n\n  # IMPORTANT: cache nginx auth requests!\n  proxy_cache_path /var/cache/nginx/auth_cache levels=1:2 keys_zone=auth_cache:1m max_size=100m inactive=60m;\n  ...\n  server {\n    ...\n    # path for django static files\n    location /static/ {\n      ...\n    }\n\n    location = /dkronauth {\n      internal;\n      # point to django app on `/dkron/auth`, this will validate the existing django session\n      proxy_pass              appserver/dkron/auth/;\n      proxy_cache             auth_cache;\n      proxy_cache_key         \"$host$request_uri $cookie_sessionid\";\n      proxy_pass_request_body off;\n      proxy_set_header        Content-Length \"\";\n      proxy_set_header        X-Original-URI $request_uri;\n      proxy_set_header        Host $host;\n      proxy_cache_valid       403 30s;\n      proxy_cache_valid       200 5m;\n    }\n\n    location /dkron/ui/ {\n      error_page 401 @dkronerror401;\n      error_page 403 /403.html;\n      error_page 404 /404.html;\n      error_page 500 502 503 504 /500.html;\n      auth_request     /dkronauth;\n      auth_request_set $auth_status $upstream_status;\n      proxy_pass http://dkronserver/;\n      proxy_set_header Host $host;\n      # if dkron is behind an nginx with basic auth required, uncomment to inject authorization header\n      # proxy_set_header Authorization \"Basic XXXXXX\";\n      proxy_redirect / $real_scheme://$host/dkron/ui/;\n    }\n\n    location @dkronerror401 {\n      # force relative redirect - https://stackoverflow.com/a/39462409\n\t    return 302 \" /login?next=$request_uri\";\n    }\n\n    location / {\n      ...\n      proxy_pass $appserver;\n    }\n    ...\n```\n\n## ToDo\n\n* Make notifications dependency optional?\n* Document reverse proxy usage (for authentication) or create the JWT/oauth app (and recommend it from here).\n* document WEBHOOK configuration (add to `urls.py`) as done in testapp.\n* how to set DKRON_TOKEN.\n* find any `FIXME`/`TODO` in code\n\n[build-status-image]: https://github.com/surface-security/django-dkron/actions/workflows/test.yml/badge.svg\n[build-status]: https://github.com/surface-security/django-dkron/actions/workflows/test.yml\n[coverage-status-image]: https://img.shields.io/codecov/c/github/surface-security/django-dkron/main.svg\n[codecov]: https://codecov.io/github/surface-security/django-dkron?branch=main\n[pypi-version]: https://img.shields.io/pypi/v/django-dkron.svg\n[pypi]: https://pypi.org/project/django-dkron/\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsurface-security%2Fdjango-dkron","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsurface-security%2Fdjango-dkron","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsurface-security%2Fdjango-dkron/lists"}