- Dockerfile: node:24-alpine, production deps only, runs as the node user, healthcheck on /healthz. No volume, because the server keeps no state. - docker-compose.yml: example for the VPS. It publishes no ports, since Docker's port publishing bypasses ufw and would skip NPM's IP access list. It joins NPM's network instead. - .gitea/workflows/docker.yml: on v*-prod* tags, builds on the self-hosted runner and pushes v0idf1sh/sdp-dashboard:<tag> and :latest using the DHUB_UNAME and DHUB_PASS secrets. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
26 lines
995 B
YAML
26 lines
995 B
YAML
# Example compose file for the VPS. Copy src/env.example to .env next to this file and fill it in.
|
|
# Nginx Proxy Manager forwards the subdomain to sdp-dashboard:3000 and enforces the IP allow list.
|
|
|
|
services:
|
|
sdp-dashboard:
|
|
image: v0idf1sh/sdp-dashboard:latest
|
|
container_name: sdp-dashboard
|
|
restart: unless-stopped
|
|
env_file: .env
|
|
environment:
|
|
# must match the redirect URI registered in the Zoho API console, minus /auth/callback
|
|
PUBLIC_URL: https://dashboard.example.com
|
|
# No published ports on purpose. Docker's port publishing bypasses ufw, so "3000:3000" would
|
|
# let anyone reach the app directly and skip NPM's access list. NPM reaches it over the
|
|
# shared network instead, using the container name as the forward hostname.
|
|
expose:
|
|
- "3000"
|
|
networks:
|
|
- proxy
|
|
|
|
networks:
|
|
proxy:
|
|
# the network Nginx Proxy Manager's container is on; check with `docker network ls`
|
|
external: true
|
|
name: ${NPM_NETWORK:-npm_default}
|