Configuration¶
unit3dprep reads configuration from three layers, in order of priority:
- Environment variables — always win.
Unit3Dbot.json— shared with theunit3dupCLI, editable from the Web UI.- Built-in defaults — used when neither env nor file sets a value.
U3DP_* and W_* keys are re-read on every access via config.runtime_setting(): changing them from the Web UI takes effect immediately, no restart needed. Exceptions are U3DP_HOST, U3DP_PORT, U3DP_ROOT_PATH, and U3DP_HTTPS_ONLY, which are read once at server startup.
Environment variables¶
Required by the Web UI¶
| Variable | Description |
|---|---|
U3DP_PASSWORD_HASH |
Bcrypt hash of the web password. Generated by generate_hash.py. |
U3DP_SECRET |
Hex secret that signs session cookies. Generated by generate_hash.py. |
TMDB¶
| Variable | Default | Description |
|---|---|---|
TMDB_API_KEY |
— | TMDB v3 API key. Needed for automatic TMDB search and metadata fetch. The CLI prompts the user if missing. |
Runtime (re-read on every access)¶
| Variable | Default | Description |
|---|---|---|
U3DP_HOST |
127.0.0.1 |
uvicorn bind address. Use 0.0.0.0 on a public VPS with firewall, 127.0.0.1 behind an nginx reverse proxy. |
U3DP_PORT |
8765 |
Listening port. On Ultra.cc pick a reserved port (app-ports free). |
U3DP_ROOT_PATH |
"" |
Nginx prefix (e.g. /unit3dprep). See ROOT_PATH notes. |
U3DP_HTTPS_ONLY |
0 |
1 sets the https_only flag on the session cookie (required behind HTTPS). |
U3DP_MEDIA_ROOT |
~/media |
Base media folder. Subfolders become categories. |
U3DP_SEEDINGS_DIR |
~/seedings |
Hardlink destination. Must live on the same FS as U3DP_MEDIA_ROOT. |
U3DP_TMDB_LANG |
it-IT |
TMDB response language. Examples: en-US, es-ES. |
U3DP_DB_PATH |
~/.unit3dprep_db.json |
Upload history (JSON). |
U3DP_TMDB_CACHE_PATH |
~/.unit3dprep_tmdb_cache.json |
TMDB query cache. |
U3DP_LANG_CACHE_PATH |
~/.unit3dprep_lang_cache.json |
Audio language detection cache. |
U3DP_SYSTEMD_UNIT |
unit3dprep.service |
Systemd user unit name used by the "Update app" button for systemctl --user cat/restart. On Ultra.cc set to unit3dprep-web.service. |
U3DP_GITHUB_REPO |
davidesidoti/unit3dprep |
owner/repo slug used to poll GitHub releases (env-only, read at import). |
Install / path¶
| Variable | Default | Description |
|---|---|---|
UNIT3DUP_CONFIG |
~/Unit3Dup_config/Unit3Dbot.json |
Override path to Unit3Dbot.json. Read only at startup. |
Web UI wizard (W_*)¶
Control the default state of the upload wizard toggles. Stored in Unit3Dbot.json, editable from Settings.
| Key | Default | Description |
|---|---|---|
W_AUDIO_CHECK |
true |
Enable Italian audio check inside the wizard. |
W_AUTO_TMDB |
true |
Auto-fetch TMDB metadata if an ID is already present. |
W_HIDE_UPLOADED |
true |
Hide already-uploaded items from the Library. |
W_HARDLINK_ONLY |
false |
End the wizard after the hardlink, without calling unit3dup. |
W_CONFIRM_NAMES |
true |
Require confirmation of the final name before hardlinking. |
Unit3Dbot.json file¶
Unit3Dbot.json is the same file unit3dup consumes. Default path: ~/Unit3Dup_config/Unit3Dbot.json, override via UNIT3DUP_CONFIG.
It contains ~100 keys, grouped by purpose:
| Group | Key examples |
|---|---|
| Trackers | ITT_URL, ITT_APIKEY, ITT_PID, PTT_URL, PTT_APIKEY, PTT_PID, SIS_URL, SIS_APIKEY, SIS_PID, MULTI_TRACKER |
| Metadata | TMDB_APIKEY, TVDB_APIKEY, YOUTUBE_KEY, IGDB_* |
| Torrent client | TORRENT_CLIENT (qbittorrent / transmission / rtorrent), QBIT_*, TRASM_*, RTORR_* |
| Image host | PTSCREENS_KEY, PASSIMA_KEY, IMGBB_KEY, IMGFI_KEY, IMAGE_HOST_ORDER, … |
| Behavior | DUPLICATE_ON, SKIP_DUPLICATE, ANON, PERSONAL_RELEASE, NUMBER_OF_SCREENSHOTS, … |
| Seeding Flow | all U3DP_* (overrides defaults) |
| Wizard defaults | all W_* |
Secret masking¶
Secrets (API keys, passwords, PIDs) are masked as "__SET__" in responses to GET /api/settings. On PUT, if the client sends back "__SET__" the server preserves the original value on disk. This avoids leaks in browser logs while letting you edit other keys without reentering secrets.
Masked keys are defined in unit3dprep/web/config.py (constant MASKED_KEYS):
ITT_APIKEY, ITT_PID, PTT_APIKEY, PTT_PID, SIS_APIKEY, SIS_PID, TMDB_APIKEY, TVDB_APIKEY, YOUTUBE_KEY, IGDB_CLIENT_ID, IGDB_ID_SECRET, QBIT_PASS, TRASM_PASS, RTORR_PASS, FTPX_PASS, PTSCREENS_KEY, PASSIMA_KEY, IMGBB_KEY, IMGFI_KEY, FREE_IMAGE_KEY, LENSDUMP_KEY, IMARIDE_KEY.
Atomic writes¶
Writes to Unit3Dbot.json go through tempfile.mkstemp + os.replace → the unit3dup CLI never sees a half-written file.
U3DP_ROOT_PATH and nginx¶
When you serve the Web UI behind a reverse proxy at a subpath (e.g. /unit3dprep), set:
Important — on Ultra.cc the nginx user-proxy does not strip the prefix: requests arrive at uvicorn with /unit3dprep still in place. That is why the app mounts routes under the prefix with app.include_router(r, prefix=ROOT_PATH) instead of FastAPI(root_path=...) (the latter is only for proxies that do strip).
The SPA reads window.__ROOT_PATH__ injected at serve-time into index.html, so assets and API calls automatically hit the right prefix with no rebuild.
On a generic VPS where nginx strips the prefix (proxy_pass http://127.0.0.1:8765/; with trailing slash), set U3DP_ROOT_PATH="" instead and handle the path from the server block.
In-app auto-update¶
The Web UI ships an integrated update system (badge at the bottom-left of the Sidebar, above the trackers list):
- App: compares the installed version (
importlib.metadata.version("unit3dprep")) against the latest GitHub release. Ifnewer == truethe "Update app" button appears. - unit3dup: compares against PyPI (
https://pypi.org/pypi/unit3dup/json).
Clicking triggers the SSE endpoint /api/version/update/{app|unit3dup}/stream: live-streamed pip install in the modal, systemd service restart, browser auto-reload with a changelog popup.
App prerequisites¶
The "Update app" button stays disabled (can_update_app: false) when:
systemctlis not inPATH, or- the configured unit does not exist (
systemctl --user cat <unit>fails).
On Ultra.cc the user unit is typically unit3dprep-web.service, not the default unit3dprep.service. Set it via:
# ~/.config/systemd/user/unit3dprep-web.service
[Service]
Environment=U3DP_SYSTEMD_UNIT=unit3dprep-web.service
or save the key through Settings › App Auto-Update. The key is read at runtime, so a Save takes effect immediately. daemon-reload + restart are only needed when you add a fresh Environment= entry.
Install mode¶
_install_mode() picks the flow based on the install layout:
- git — source has a reachable
.git(typical forpip install -e .from a checkout). Runsgit pull --ff-only origin main+pip install -e .. - pip — installed via
pip install git+https://...@vX(no.git). Runspip install --upgrade --force-reinstall git+URL@vX.
Editable install + service WorkingDirectory
If the systemd [Service] has WorkingDirectory=<repo> and that folder contains .git, Python imports unit3dprep from the local source (editable) even when you installed via pip install git+.... The flow becomes "git" as a consequence. To force the pip flow, use WorkingDirectory=%h and remove/rename the checkout.
GitHub token (optional)¶
The api.github.com anonymous rate limit is 60 requests/hour per IP. This should be enough (polling every 15 min), but in case of saturation a token-via-env path is tracked as a follow-up — not yet implemented.
Complete examples¶
Local deploy (just you, on a trusted machine)¶
export U3DP_PASSWORD_HASH="$2b$12$..."
export U3DP_SECRET="..."
export TMDB_API_KEY="..."
export U3DP_HOST="127.0.0.1"
export U3DP_PORT="8765"
unit3dprep-web
Behind nginx with HTTPS and a subpath¶
export U3DP_PASSWORD_HASH="..."
export U3DP_SECRET="..."
export TMDB_API_KEY="..."
export U3DP_HOST="127.0.0.1"
export U3DP_PORT="45678" # backend port, not exposed
export U3DP_ROOT_PATH="/unit3dprep" # public subpath
export U3DP_HTTPS_ONLY="1"
unit3dprep-web
Media on a separate disk¶
Same filesystem
U3DP_SEEDINGS_DIR must live on the same device as U3DP_MEDIA_ROOT, otherwise hardlink creation fails with OSError: [Errno 18] Invalid cross-device link. Check with df <media> <seedings>.