Self-hosted web app to manage Ring Intercom access for B&B and small hospitality workflows.
Main use case: create temporary guest links (check-in/check-out window) so guests can unlock the door only during their stay.
Supported languages: English, Italian, Spanish, German.
Most project details are maintained in Docusaurus:
- Docs source:
website/ - Intro:
website/docs/intro.md - Architecture:
website/docs/architecture.md - API (generated from backend docstrings):
website/docs/api/reference.md - Deployment:
website/docs/deployment.md - Development:
website/docs/development.md - Security:
website/docs/security.md - Contributing:
website/docs/contributing.md
Published docs:
https://mrgionsi.github.io/ring-intercom-control/
- Ring account integration (single or multiple accounts per user)
- Intercom unlock from web dashboard
- Guest links with start/end window and max-use limit
- Admin/user role model
- Audit trails for unlocks and login attempts
Prerequisite: Node.js 24.14.1 or newer. The repository includes .nvmrc
with the CI/docs baseline (24.14.1).
cd backend && npm install
cd ../frontend && npm installcd backend
cp .env.example .env
openssl rand -hex 32
openssl rand -base64 32
npm run hash-password -- yourAdminPasswordIf you prefer not to use npm run, generate the same bcrypt hash directly with
Node after backend/npm install:
node -e "const bcrypt=require('./backend/node_modules/bcryptjs'); console.log(bcrypt.hashSync('yourAdminPassword', 12));"Set the generated values in backend/.env:
ADMIN_USERNAME=admin
ADMIN_PASSWORD_HASH=<paste the hash from `npm run hash-password -- yourAdminPassword`>
SESSION_SECRET=<paste the hex value from `openssl rand -hex 32`>
MASTER_KEY=<paste the Base64 value from `openssl rand -base64 32`>MASTER_KEY must be a Base64-encoded 32-byte key because the backend uses
AES-256-GCM to encrypt Ring refresh tokens.
If you place ADMIN_PASSWORD_HASH directly in Docker Compose YAML, escape each
$ as $$. Bcrypt hashes contain $ separators and Docker Compose treats $
as variable interpolation syntax. In Portainer stack deployments, keep the same
rule and escape the bcrypt hash as $$ there as well.
cd backend
npm run devcd frontend
npm run devApp URLs:
- Frontend:
http://localhost:5173 - Backend:
http://localhost:3001
For complete setup, security, Docker, and CI/CD instructions, use the Docusaurus docs above.
The project supports containerized deployment for both backend and frontend.
- Backend image:
backend/Dockerfile - Frontend image:
frontend/Dockerfile - Compose stack:
docker-compose/docker-compose.yml - Env template:
docker-compose/.env.example
Build:
docker build ./frontend -t mrgionsi/ring-intercom-control-frontend:0.1.0-betaRun:
docker run --rm -p 5173:5173 \
-e PORT=5173 \
-e BACKEND_URL=http://host.docker.internal:3001 \
mrgionsi/ring-intercom-control-frontend:0.1.0-betaNotes:
BACKEND_URLis optional. If set,/api/*requests are proxied to backend.host.docker.internalworks by default on Docker Desktop (Windows/macOS). On Linux, add:--add-host=host.docker.internal:host-gateway
- Health endpoint inside container:
GET /healthreturns{ "ok": true }. - Static cache policy:
index.html:no-cache/assets/*:public, max-age=31536000, immutable
Files:
docker-compose/docker-compose.ymldocker-compose/.envdocker-compose/docker-compose.portainer.yml
Run:
cd docker-compose
cp .env.example .env
docker compose up -dEnvironment notes:
NODE_ENV=production: use for real deployments. Cookies are treated as secure in current releases, so pair this with HTTPS.NODE_ENV=development: useful for local or private-LAN HTTP testing when you are not terminating TLS yet.TRUST_PROXY=0: use this when the backend is not behind a reverse proxy. Use this for plain Docker Compose setups where requests go straight to the app containers.TRUST_PROXY=1: use this when the backend sits behind one trusted proxy hop, for example Traefik or another HTTPS-terminating reverse proxy. This affectsreq.ip, login audit IPs, rate limiting, and secure-cookie handling behind HTTPS termination.CLIENT_ORIGIN: set this to the browser-facing frontend URL, for examplehttp://192.168.1.50:5173.BACKEND_URLin the frontend container should usually point to the Docker service name, for examplehttp://backend:3001, not the host LAN IP.
Stop:
cd docker-compose
docker compose downContainer logs are written to stdout/stderr, so they are visible with:
docker logs ring-intercom-backend
docker logs ring-intercom-frontendUse docker-compose/docker-compose.portainer.yml when exposing only the
frontend through Traefik and keeping the backend private on the internal
ring-intercom Docker network.
Create the external Docker networks first if they do not already exist:
docker network create ring-intercomPortainer notes:
- Import or paste
docker-compose/docker-compose.portainer.ymlinto a stack. - Add the required environment variables in Portainer.
- Set
TRUST_PROXY=1when running behind Traefik. frontendis attached to bothtraefik_defaultandring-intercom.backendis attached only toring-intercomand is not exposed publicly.CLIENT_ORIGINshould be the public browser URL, for examplehttps://intercom.srv.home.gionsi.me.BACKEND_URLshould stay internal ashttp://backend:3001.traefik_defaultis expected to already exist as the external network used by your Traefik deployment.- In Portainer stack deployments, escape bcrypt
$characters as$$forADMIN_PASSWORD_HASH.
cd backend && npm run build
cd ../frontend && npm run buildPowerShell:
scripts/smoke-test.ps1Bash:
scripts/smoke-test.shOptional authenticated smoke checks:
SMOKE_USERNAME=<username>SMOKE_PASSWORD=<password>SMOKE_BASE_URL=http://localhost:3001
PowerShell:
scripts/security-check.ps1Bash:
scripts/security-check.shCurrent npm audit reports high-severity vulnerabilities in transitive dependencies:
ipviaring-client-api->werift/werift-ice;ip@2.0.1is still the latest published version and npm's fix path is a breaking downgrade ofring-client-api.
These are currently tracked and deferred until upstream fix availability.
The docs site currently reports moderate dev-server advisories through
Docusaurus' webpack-dev-server -> sockjs -> uuid dependency chain. The
static production docs build is successful, and npm reports no available
Docusaurus fix yet.
main: stable, production-ready branchdev: integration and pre-release branchfeature/*: short-lived implementation brancheshotfix/*: emergency fixes frommain
- Optional managed DB migration path (Supabase/Postgres)
- Extended automated test coverage (API + UI)
- See
LICENSE.
- Contribution guide:
CONTRIBUTING.md - Security policy:
SECURITY.md - Support:
SUPPORT.md - Issues:
https://github.com/mrgionsi/ring-intercom-control/issues





