# Deploying to Dokploy The app is a single Node process with no dependencies. Dokploy builds it from the `Dockerfile` in this repo and puts Traefik in front of it. ## 1. Push the repo to a Git host Dokploy pulls from GitHub/GitLab/Gitea (or a raw Git URL over SSH). **Before the first push:** `.env` and `.env.testcopy` contain a real DeepL API key. They are untracked from now on via `.gitignore`, but if they were already committed they still exist in history — remove them from tracking and rotate the key rather than relying on the file being gone from the working tree. ## 2. Create the application in Dokploy Project → **Create Service** → **Application**. | Field | Value | | ------------- | ------------------------------ | | Source | Git provider + this repo/branch | | Build Type | **Dockerfile** | | Dockerfile | `Dockerfile` | ## 3. Environment variables **Environment** tab: ``` DEEPL_API_KEY= ``` `PORT` and `DOMAINS_FILE` are already set in the Dockerfile — do not override them unless you also change the volume mount path to match. The key is server-side only; it is never sent to the browser. ## 4. Volume (required) Without this, every redeploy resets all glossary mappings. **Advanced → Volumes → Add** : | Field | Value | | ----------- | -------------- | | Type | Volume Mount | | Volume Name | `deepl-data` | | Mount Path | `/app/data` | `DOMAINS_FILE=/app/data/domains.json` writes into that volume. The path is a subdirectory of `/app` on purpose — mounting `/app` itself would hide `server.js` and `index.html`. ## 5. Domain **Domains** tab → Add: | Field | Value | | ------------- | ------------------------ | | Host | your hostname | | Container Port| `3000` | | HTTPS | on, Let's Encrypt | ## 6. Deploy Hit **Deploy**. Verify with: ``` curl https:///health # {"status":"ok","apiKeyConfigured":true} ``` `apiKeyConfigured: false` means `DEEPL_API_KEY` did not reach the container. ## Seeding existing glossary mappings A fresh volume starts empty and the app writes a default `domains.json` with all four domains and no glossaries. The `domains.json` in this repo is **not** copied into the image (it is in `.dockerignore`), so any glossary IDs recorded there are not carried over. Either re-save the glossaries through the UI after the first deploy, or copy the file in once: ``` docker cp domains.json :/app/data/domains.json docker restart ``` ## Notes - The app has **no authentication**. Anything on the public domain can use your DeepL quota and edit the shared glossaries. Put Traefik basic auth or an IP allowlist in front of it if it is internet-facing. - Docker `HEALTHCHECK` hits `/health` every 30s. It does not call DeepL, so a DeepL outage will not restart the container.