Deploying on Dokploy¶
Dokploy is a self-hosted PaaS that already includes Docker and a Traefik reverse proxy. This page covers every way to run Jeff on Dokploy, in the order most people should try them, plus a dedicated section for Dokploy running inside a Proxmox LXC (e.g. on a mini PC such as a MINISFORUM UM890 Pro).
Recommended path
Compose service with docker-compose.dokploy.yml (Mode A). It
pulls the prebuilt image, exposes no host port, joins
dokploy-network so the Domains tab works, and keeps the model in
named volumes across redeploys.
Before you start¶
| Check | Command (on the Dokploy host / inside the LXC) |
|---|---|
| Docker works | docker info |
| Free RAM ≥ 12 GB | free -h |
| Free disk ≥ 20 GB | df -h /var/lib/docker |
Outbound HTTPS to huggingface.co and ghcr.io |
curl -sI https://huggingface.co \| head -1 |
Generate your API key on any machine:
openssl rand -hex 32
Choosing a service type¶
| Compose service (recommended) | Application service | |
|---|---|---|
| Deploys | docker-compose.dokploy.yml from this repo |
One container from ghcr.io/... or docker/Dockerfile |
| Environment variables | Written to .env next to the compose file; reach the container only because the compose file references them with ${VAR} (this repo's files already do) |
Passed directly to the container |
| Volumes | Declared in the compose file (jeff-models, jeff-data) |
Must be added by hand in Advanced → Volumes |
| Network | Joins dokploy-network (declared in the file) |
Managed by Dokploy |
| Best for | Matching the tested setup exactly | Teams that standardize on Application services |
Mode A — Compose, prebuilt image (recommended)¶
- Create Project (e.g.
ai) → open it → Create Service → Compose. - Compose Type:
Docker Compose(notStack). - General tab — source of the compose file:
- Git-based: provider
GitHub(orGitwithhttps://github.com/tommasomarchionni/jeff-docker.git), branchmain, Compose Path./docker-compose.dokploy.yml. - Raw editor: paste the content of
docker-compose.dokploy.ymlif you don't want Dokploy to access GitHub.
- Git-based: provider
-
Environment tab — minimal set:
JEFF_API_KEYS=<paste the openssl key> JEFF_DOCKER_TAG=0.2.0 JEFF_DEVICE=cpu JEFF_THREADS=4 JEFF_MAX_BATCH=8 JEFF_RATE_LIMIT_RPS=4 JEFF_RATE_LIMIT_BURST=8 JEFF_CPU_LIMIT=0 JEFF_MEM_LIMIT=10gMatch the limits to the host
JEFF_CPU_LIMITmust not exceed the CPUs Docker can see (runnprocon the Dokploy host / inside the LXC). With a 4-core LXC andJEFF_CPU_LIMIT=8the deploy fails withrange of CPUs is from 0.01 to 4.00, as there are only 4 CPUs available. Use0(no limit) or a value ≤nproc, and keepJEFF_THREADS≤nproc(e.g.4on 4 cores,6on 8 cores).Everything else has sane defaults; see Environment variables. Pin
JEFF_DOCKER_TAGto a release in production instead oflatest.Does Dokploy pass these into the container?
Yes, but only because
docker-compose.dokploy.ymlreferences every variable as${VAR}insideenvironment:. Dokploy writes the Environment tab to a.envfile next to the compose file and does not inject it automatically (Dokploy docs). If you write your own compose file, keep the${VAR}references or addenv_file: .env. -
Domains tab → Add Domain:
- Service:
jeff - Host:
jeff.example.com(or a LAN name, see below) - Container Port:
8000 - HTTPS: on, Certificate: Let's Encrypt (public domains only)
- Service:
-
Deploy, then open Logs. First deploy:
[entrypoint] Downloading knowledgator/gliformer-large-v1 (revision main) into /models/gliformer-large-v1 ... [entrypoint] Model download complete. ... jeff ready: backend=torch model=gliformer-large-v1Later deploys print
Model already presentand start in seconds. 7. Test from your machine:curl https://jeff.example.com/healthz curl https://jeff.example.com/v1/models -H "Authorization: Bearer <key>" -
Optional: Volume Backups tab → schedule a backup of
jeff-models(saves the ~1.7 GB re-download after a disaster; not strictly needed).
Mode B — Compose, build from source¶
Same as Mode A, but Compose Path ./docker-compose.yml, and add to
docker-compose.yml the Dokploy network (or use the raw editor):
networks: [dokploy-network]
networks:
dokploy-network:
external: true
and remove the ports: block. Dokploy builds the image on every deploy
(5–10 minutes). Use this when you forked the repo or pin JEFF_REF.
Mode C — Application service¶
- Create Service → Application.
- General → Provider Docker, image
ghcr.io/tommasomarchionni/jeff-docker:0.2.0. (Or Provider GitHub, Build TypeDockerfile, Dockerfile pathdocker/Dockerfile, context..) - Environment: same variables as Mode A (passed directly).
- Advanced → Volumes: add two Volume Mounts:
jeff-models→/modelsandjeff-data→/data. Skipping this re-downloads the model on every deploy. - Advanced → Resources: memory limit 10 GB, CPU 8.
- Domains: container port
8000. - Deploy and check logs as in Mode A.
LAN-only access (no public domain)¶
If Jeff must stay inside your home network:
- Create a local DNS record (router, Pi-hole, AdGuard Home) such as
jeff.home.lan→ IP of the Dokploy host/LXC. - In Domains, use that host, HTTPS off (or a certificate from your
internal CA), port
8000. - Do not forward ports 80/443 on your router for this domain.
Alternatively, skip Domains entirely and reach Jeff only from other Dokploy
services at http://jeff:8000 on dokploy-network.
Dokploy inside a Proxmox LXC¶
Typical layout: Proxmox VE on a mini PC → unprivileged LXC with Docker → Dokploy → Jeff.
LXC settings (Proxmox UI → CT → Resources / Options):
| Setting | Recommended for gliformer-large-v1 |
|---|---|
| Cores | 8 (Jeff uses JEFF_THREADS=6, the rest stays for Dokploy/Traefik) |
| Memory | 16 GB (12 GB minimum) |
| Swap | 4 GB |
| Root disk | 30 GB+ |
| Features | nesting=1, keyctl=1 |
Why limits matter: if the container exceeds the LXC memory, the kernel
OOM killer may kill Jeff (exit code 137) or even other services. Keep
JEFF_MEM_LIMIT below the LXC memory minus ~3 GB for Dokploy, Traefik and
the OS.
CPU-only is the supported mode here. The integrated Radeon (780M on the UM890 Pro) can in theory be passed to an LXC and to Docker, but the chain is fragile; see AMD ROCm (experimental).
Updating¶
- Change
JEFF_DOCKER_TAG(e.g.0.2.0→0.3.0) in Environment. - Deploy. The model volume is reused.
- Roll back by setting the previous tag and deploying again.
Enable Autodeploy (Git provider) only if you track latest; with
pinned tags, updates are a deliberate change of JEFF_DOCKER_TAG.
Dokploy-specific troubleshooting¶
| Symptom | Cause / fix |
|---|---|
404 page not found on the domain |
Domain port isn't 8000, or the service isn't on dokploy-network (Mode B without the network block) |
Bad Gateway right after deploy |
Model still downloading; wait for jeff ready in Logs |
| Variables ignored | Custom compose file without ${VAR} references (see warning above) |
| Model re-downloaded on every deploy | Mode C without volume mounts, or volumes deleted |
network dokploy-network not found |
Running the Dokploy compose outside Dokploy: docker network create dokploy-network |
range of CPUs is from 0.01 to N.00, as there are only N CPUs available |
JEFF_CPU_LIMIT is higher than the CPUs of the host/LXC: set it to 0 or ≤ nproc and redeploy |
| Container killed, exit 137 | Raise LXC memory or lower JEFF_MEM_LIMIT/JEFF_MAX_BATCH |
More in Troubleshooting.