Local setup

Prerequisites

The local stack can run without live provider credentials. Purchases and SMS stay disabled until their integrations are configured.

Start

From the project root:

cp .env.example .env # Replace database and admin passwords; leave provider keys empty for local UI review. docker compose up -d --build docker compose ps

Open:

AppLocal URL
Guest portalhttp://localhost:3000
Admin consolehttp://localhost:3001/login
Documentationhttp://localhost:3002
API healthhttp://localhost:3000/api/v1/health (guest server proxy)

The API HTTP port stays private to Docker. The VPS overlay exposes it only on loopback for host Nginx. PostgreSQL has no host port mapping. On a fresh host, the optional Caddy profile can replace the host Nginx route.

First local configuration

  1. Sign in with TOWERS_ADMIN_EMAIL and TOWERS_ADMIN_PASSWORD from your local environment.
  2. Open Devices and register a Cudy AP record if you are preparing actual network testing.
  3. Open Access plans and create a plan worth at least TZS 500 with positive duration.
  4. Review Cudy captive portal for readiness and missing values.

The bootstrap admin is created only if its email does not already exist. Changing the local env password later does not reset an existing user’s password.

Stop and preserve data

docker compose down

This stops containers and keeps the PostgreSQL named volume. Do not use docker compose down -v unless you intend to erase all local data.

Live provider testing

Use a separate test environment and provider test credentials. A local webhook URL is not publicly reachable by the provider unless you intentionally expose a secure development tunnel. Do not point a live provider callback at an untrusted public tunnel.