# Running `media-img` as a service `media-img` is a normal **console process**: it has **no** dedicated config file for `serve` / `ipc` (no port in TOML/JSON inside this repo). You configure it with **command-line arguments** (and optionally **environment variables** such as `VIPS_CONCURRENCY`). At startup it loads **`.env` from the current working directory** if present ([dotenv-cpp](https://github.com/laserpants/dotenv-cpp)), so you can set env vars without a separate “config file” for ports—though **bind address and port are still CLI flags**, not read from `.env` unless you wrap the binary. **Practical approaches:** | Approach | Use when | |----------|----------| | **Flags only** in the unit / wrapper | Simplest; edit the service definition when ports change. | | **`EnvironmentFile=`** (systemd) or NSSM env | Centralize `VIPS_CONCURRENCY`, cache paths, etc.; still pass `--port` / `--host` in `ExecStart` or via a tiny wrapper script. | | **Wrapper script** | Reads env or a small file and `exec`s `media-img` with the right flags. | Defaults if you omit flags: `--host 127.0.0.1 -p 8080` for `serve`, and `--host 127.0.0.1 -p 9333` for `ipc` (see `media-img serve --help` / `ipc --help`). --- ## Linux: systemd (`systemctl`) Install the binary somewhere stable (e.g. `/usr/local/bin/media-img`) and ensure **libvips** and its dependencies are on the system `LD_LIBRARY_PATH` if you did not link statically. ### 1. REST service (`serve`) Create `/etc/systemd/system/media-img-serve.service`: ```ini [Unit] Description=media-img HTTP REST (libvips resize) After=network.target [Service] Type=simple User=mediaimg Group=mediaimg WorkingDirectory=/var/lib/media-img # Optional: VIPS_CONCURRENCY, cache location, etc. # EnvironmentFile=-/etc/default/media-img # Or: ExecStart=/usr/local/bin/run-media-img.sh (see scripts/run-media-img.sh + /etc/default/media-img) ExecStart=/usr/local/bin/media-img serve --host 127.0.0.1 --port 8080 --cache-dir /var/cache/media-img Restart=on-failure RestartSec=3 # Hardening (tune for your layout) NoNewPrivileges=true PrivateTmp=true [Install] WantedBy=multi-user.target ``` Create user/dirs if needed: ```bash sudo useradd -r -s /usr/sbin/nologin -d /var/lib/media-img mediaimg sudo mkdir -p /var/lib/media-img /var/cache/media-img sudo chown mediaimg:mediaimg /var/lib/media-img /var/cache/media-img ``` Enable and start: ```bash sudo systemctl daemon-reload sudo systemctl enable --now media-img-serve sudo systemctl status media-img-serve journalctl -u media-img-serve -f ``` **Optional** `/etc/default/media-img` (referenced by `EnvironmentFile=`): ```bash # Not used for --port unless you add a wrapper script; useful for libvips: VIPS_CONCURRENCY=4 ``` ### 2. IPC service (`ipc` TCP or Unix socket) Use a **second** unit, e.g. `media-img-ipc.service`, with a different `ExecStart`: ```ini ExecStart=/usr/local/bin/media-img ipc --host 127.0.0.1 --port 9333 --cache-dir /var/cache/media-img ``` Or Unix socket on Linux: ```ini ExecStart=/usr/local/bin/media-img ipc --unix /run/media-img/ipc.sock --cache-dir /var/cache/media-img RuntimeDirectory=media-img ``` ### 3. Firewall If you bind beyond `127.0.0.1`, open the port in `firewalld` / `ufw` as usual. --- ## Windows: running as a service `pm-image.exe` does **not** register with the Windows Service Control Manager by itself. Use a **service wrapper** that runs your command line as a service. ### Option A — NSSM (Non-Sucking Service Manager) 1. Install [NSSM](https://nssm.cc/). 2. Either run **`pm-image.exe` directly** or use **[`scripts/run-media-img.ps1`](../scripts/run-media-img.ps1)** with `MEDIA_IMG_*` env vars (see [Wrapper scripts](#wrapper-scripts-ports-via-environment)). **Direct executable:** ```powershell nssm install MediaImgServe "C:\Apps\media\pm-image.exe" nssm set MediaImgServe AppDirectory "C:\Apps\media" nssm set MediaImgServe AppParameters "serve --host 127.0.0.1 --port 8080 --cache-dir C:\Apps\media\cache\images" nssm set MediaImgServe AppStdout "C:\Apps\media\logs\serve.log" nssm set MediaImgServe AppStderr "C:\Apps\media\logs\serve.err.log" nssm set MediaImgServe AppEnvironmentExtra "VIPS_CONCURRENCY=4" nssm start MediaImgServe ``` 3. Ensure DLLs (libvips) are on `PATH` or next to the exe, as in your dev layout. ### Option B — WinSW Use [WinSW](https://github.com/winsw/winsw) with an XML that points `executable` to `pm-image.exe` and passes `serve` arguments in `arguments`. ### Option C — Task Scheduler Not a true service, but often enough: run `pm-image.exe serve ...` at logon or startup with “Run whether user is logged on or not”. No SCM integration; fewer recovery options than NSSM. ### Firewall Allow the chosen TCP port in **Windows Defender Firewall** if clients are remote. --- ## Wrapper scripts (ports via environment) The repo includes small wrappers so you can set **bind address, port, and cache dir** from the environment (e.g. systemd `EnvironmentFile`, NSSM, or CI) without editing the unit XML every time: | Script | Platform | |--------|----------| | [`scripts/run-media-img.sh`](../scripts/run-media-img.sh) | Linux / macOS / Git Bash | | [`scripts/run-media-img.ps1`](../scripts/run-media-img.ps1) | Windows (PowerShell) | **Environment variables** (both scripts): | Variable | Meaning | |----------|---------| | `MEDIA_IMG_CMD` | `serve` (default) or `ipc` | | `MEDIA_IMG_BIN` | Path to `media-img` / `pm-image.exe` (optional; scripts default to `PATH` or `dist/` next to the script) | | `MEDIA_IMG_HOST` | Bind address (default `127.0.0.1`) | | `MEDIA_IMG_PORT` | TCP port — default **8080** for `serve`, **9333** for `ipc` | | `MEDIA_IMG_CACHE_DIR` | Passed as `--cache-dir` if set | | `MEDIA_IMG_NO_CACHE` | Set to `1` to add `--no-cache` | | `MEDIA_IMG_IPC_UNIX` | **Linux `.sh` only:** if set with `MEDIA_IMG_CMD=ipc`, uses `--unix` instead of TCP | Install the shell script on Linux: `chmod +x scripts/run-media-img.sh`, copy to e.g. `/usr/local/bin/`, then: ```ini EnvironmentFile=-/etc/default/media-img ExecStart=/usr/local/bin/run-media-img.sh ``` Example **`/etc/default/media-img`**: ```bash MEDIA_IMG_CMD=serve MEDIA_IMG_HOST=127.0.0.1 MEDIA_IMG_PORT=8080 MEDIA_IMG_CACHE_DIR=/var/cache/media-img VIPS_CONCURRENCY=4 ``` **Windows (NSSM)** — point the service at PowerShell and the script, then set **`MEDIA_IMG_*` in the NSSM GUI** (Environment tab) or via `nssm edit` (recommended for several variables): ```powershell nssm install MediaImgServe "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" nssm set MediaImgServe AppDirectory "C:\Apps\media" nssm set MediaImgServe AppParameters "-NoProfile -ExecutionPolicy Bypass -File C:\Apps\media\scripts\run-media-img.ps1" ``` Example environment entries: `MEDIA_IMG_CMD=serve`, `MEDIA_IMG_PORT=8080`, `MEDIA_IMG_CACHE_DIR=C:\Apps\media\cache\images`, `VIPS_CONCURRENCY=4`. --- ## Do you need config files? **No, not for `media-img` itself**—ports and bind addresses are normally **CLI flags**. The wrappers above map **environment variables** to those flags. Optional extras: - **systemd `EnvironmentFile`** for `MEDIA_IMG_*` and `VIPS_CONCURRENCY`. - **`.env`** beside `WorkingDirectory` for variables `media-img` loads itself (see main README); it does **not** set `--port` unless you use the wrapper. For a **database** or other apps in the same repo, `config/postgres.toml` is unrelated to `media-img` HTTP/IPC ports.