Deployment¶
Plain HTTP and custom ports¶
Many ZKTeco firmwares only push over plain HTTP, often to a non-standard port, and cannot validate certificates. Accept that safely:
- Separate listener. Expose ADMS on its own port or host through a reverse proxy that only
forwards
/<ADMS_URL_PREFIX>paths to Django. The REST API and admin stay on HTTPS. - Restrict sources. Allow only your sites' public IPs (proxy ACL and/or
ADMS_ALLOWED_IPS), or better, connect devices over a site-to-site VPN and never expose ADMS publicly. - Trust the proxy explicitly. Set
ADMS_TRUSTED_PROXY_IPSso device IPs come fromX-Forwarded-Foronly when the request comes from your proxy. - Keep the device unapproved until verified, and consider disabling auto-registration once rollout is complete.
- Template data travels between device and server in whatever form the firmware uses. On untrusted networks, use a VPN.
Example nginx:
server {
listen 8081; # the port configured on the devices
location /iclock/ {
allow 203.0.113.0/24; # your sites
deny all;
client_max_body_size 20m; # backlogs after long outages
proxy_read_timeout 120s;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
proxy_pass http://127.0.0.1:8000;
}
location / { return 404; }
}
If firmware cannot set a path and you use a secret ADMS_URL_PREFIX, rewrite in the proxy:
location /iclock/ { proxy_pass http://127.0.0.1:8000/k3j2h/iclock/; }.
Workers and timeouts¶
- Backlog uploads can hold thousands of lines. Keep
ADMS_MAX_REQUEST_BYTESand the proxy body limit in step, and allow ~60–120 s timeouts. - Use
TASK_BACKEND="celery"(ordjango) in production so processing, hooks, webhooks and backfills run off the request path, and schedulebeat_schedule(). - The ADMS rate limiter and the offline detector use the Django cache. Use a shared cache (Redis/Memcached) with several web workers.
fpa_live_capture(pull mode) is a long-running process. Run one instance per set of devices under a supervisor.
Database¶
Any Django-supported database works. PostgreSQL is recommended (row locking with
SKIP LOCKED for command hand-out, and good bulk_create conflict handling). Indexes cover
punch lookups by enrollee/device/PIN and time, the command queue, and retry scans.
Time¶
USE_TZ=True is required. Set TIME_ZONE or DEFAULT_DEVICE_TIMEZONE to where most devices
are, and give devices in other zones their own timezone. Keep server clocks on NTP. Server
time is the reference for drift detection.
Checklist¶
- [ ]
python manage.py check --deployandcheckare clean (nofpa.Eerrors) - [ ] Encryption keys come from a secret store; a backup key is recorded
- [ ] ADMS port is restricted; devices are approved and have timezones set
- [ ] Celery (or cron) runs the periodic jobs
- [ ] Retention settings match your policy
- [ ] Admin and API permissions reviewed (who has
view_template_data,clear_device_*)