mono/packages/media/cpp/docs/integration.md

8.3 KiB

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), 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 execs 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).

serve: POST /v1/resize — JSON vs multipart

The same path accepts two shapes of request:

Content-Type Use case Response
application/json Server reads/writes input and output paths on the host (shared data dir, batch jobs). JSON (ok, optional batch fields). Output cache may apply.
multipart/form-data Clients upload a file (parts file, image, or upload) plus optional form fields (max_width, format, …). Binary image body; no on-disk cache for these requests (internal temp files only).

GET /health stays JSON for probes. If you put a reverse proxy in front of serve, raise client max body size for multipart uploads as needed; the cpp-httplib server itself does not read a separate config file for limits.


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:

[Unit]
Description=media-img HTTP REST (libvips resize; JSON + multipart /v1/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:

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:

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=):

# 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:

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:

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.
  2. Either run pm-image.exe directly or use scripts/run-media-img.ps1 with MEDIA_IMG_* env vars (see Wrapper scripts).

Direct executable:

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
  1. Ensure DLLs (libvips) are on PATH or next to the exe, as in your dev layout.

Option B — WinSW

Use 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 Linux / macOS / Git Bash
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:

EnvironmentFile=-/etc/default/media-img
ExecStart=/usr/local/bin/run-media-img.sh

Example /etc/default/media-img:

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):

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.