github.repository_owner resolves to "nineAp" (mixed case), which Docker
rejects as an invalid repository reference — hardcode the lowercase
"nineap" used by the GHCR package and the compose files' image default.
Also apply the same secrets-interpolation fix from the dev job to
deploy-prod so a future manual prod deploy doesn't hit the same
"password is empty" failure from unforwarded SSH env vars.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
appleboy/ssh-action's envs: mechanism forwards vars via SSH SendEnv,
which sshd silently drops unless AcceptEnv is configured server-side.
On the freshly bootstrapped dev VPS that left GHCR_TOKEN empty on the
remote end, so `docker login --password-stdin` failed with "password
is empty" even though the SSH connection itself was fine. Interpolate
the secret directly into the script text instead.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Add slim docker-compose.dev-remote.yml (app+db+redis, no monitoring)
for the remote dev VPS, and a deploy-dev job that auto-runs after a
successful image build on main. Bump Dockerfile.dev's Rust image so
edition2024 dependencies build. Stop tracking .env.dev (real secrets
were committed) in favor of .env.dev.example / .env.dev-remote.example
templates.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>