This tutorial takes a developer from a fresh checkout to a running single-tenant server with the web app in the browser. It uses the commands that the repository itself runs in continuous integration and in the node scripts. It does not cover a Linux node (see install a Linux node) or the graphical Windows installer (see Windows installer).
What you will build¶
At the end, one server process answers on the address set by CLUSTER_ERP_SERVER_HOST and CLUSTER_ERP_SERVER_PORT, its database is migrated to the newest revision, and the web app opens under /app/. Optionally the desktop client connects to the same server.
Before you start¶
- Python 3.12 or newer (
pyproject.toml:9). - A PostgreSQL server. Continuous integration tests against PostgreSQL 16 (
.github/workflows/ci.yml:79-81). - A shell in the repository root: Alembic and the server read
alembic.iniandmigrations/from the working directory (src/cluster_erp/core/tenancy.py:681-684).
Step 1: Install the Python packages¶
Install the tested pins with hash checking, then the project without dependency resolution, then the development tools and the desktop toolkit at the pinned version.
python -m pip install --quiet --require-hashes -r requirements.lock
python -m pip install --quiet --no-deps -e . && python -m pip install --quiet -e ".[dev]" "PySide6==6.8.3"
Source: .github/workflows/ci.yml:47-50. The desktop extra holds the Qt toolkit; the dev extra holds pinned mypy and ruff, plus pytest (pyproject.toml:64-84). You need the toolkit only for the desktop client.
Step 2: Create the database roles and the database¶
Edit the two password placeholders in deploy/postgres-roles.sql, then run it as the PostgreSQL superuser.
psql -U postgres -f deploy/postgres-roles.sql
Source: deploy/postgres-roles.sql:1-11. The script creates the application role with CREATEDB and without BYPASSRLS, and a separate backup role (deploy/postgres-roles.sql:13-42). Then create an empty database owned by the application role, named as you will set CLUSTER_ERP_DB_NAME. The repository has no command line for this step; the Windows setup wizard does it with createdb (installer/setup_wizard.pyw:598-610).
Step 3: Write the settings file¶
Settings reads environment variables with the prefix CLUSTER_ERP_ and a .env file in the working directory (src/cluster_erp/config/settings.py:64-70). Create .env in the repository root with at least these lines:
CLUSTER_ERP_DB_HOST=<value>
CLUSTER_ERP_DB_NAME=<value>
CLUSTER_ERP_DB_USER=<value>
CLUSTER_ERP_DB_PASSWORD=<value>
CLUSTER_ERP_SECRET_KEY=<value>
Illustrative file built from the fields at src/cluster_erp/config/settings.py:72-76 and src/cluster_erp/config/settings.py:186. Generate the secret with the command from the template:
python -c "import secrets; print(secrets.token_hex(32))"
Source: deploy/env.example:16-17. Outside debug mode a default, short, or weak secret stops the start-up (src/cluster_erp/config/settings.py:771-808). Every other variable is described in the settings reference.
Step 4: Migrate the database¶
python -m alembic upgrade head
Source: .github/workflows/ci.yml:113. A single-tenant server does not migrate its database at start-up; only a multi-tenant server does (src/cluster_erp/server/app.py:99-113, deploy/install.sh:222-225). See database migrations.
Step 5: Start the server¶
python -m cluster_erp.server.main
Source: src/cluster_erp/server/main.py:12-62. With CLUSTER_ERP_DEBUG=true the server reloads when files under src/cluster_erp/server, core, or modules change (src/cluster_erp/server/main.py:15-24). On Windows it always runs one process (src/cluster_erp/server/main.py:27-35).
Expected result, derived from src/cluster_erp/server/app.py:876-943: on a database without users the start-up creates the first administrator; on a database that holds the migration-seeded default account it replaces that account's password. In both cases, unless CLUSTER_ERP_BOOTSTRAP_ADMIN_PASSWORD is set, the generated password is written to an owner-only file and the log names the file, not the password (src/cluster_erp/server/app.py:591-608).
Step 6: Open the web app¶
Open /app/ on the server address in a browser and sign in with the first administrator. The server mounts the repository folder webapp/ at /app and /app/v (src/cluster_erp/server/app.py:1633-1644). Change the password at the first sign-in and delete the password file, as the log line says (src/cluster_erp/server/app.py:918-922).
Step 7: Start the desktop client (optional)¶
python -m cluster_erp.desktop.main
Source: installer/setup_wizard.pyw:722. The client and its settings are described in run the desktop client.
Check your result¶
GET /healthanswers{"status": "healthy", "version": ...}without touching the database (src/cluster_erp/server/app.py:1469-1474).GET /readyanswers HTTP 200 with"status": "ready"and"database": "pass"(src/cluster_erp/server/app.py:1476-1504).
What you learned¶
- Settings come from
CLUSTER_ERP_variables and.env; see configuration reference. - The schema comes from the one Alembic history; see database migrations.
- The health and readiness probes; see security.txt and readiness.
Next steps¶
Terms introduced¶
| Term | Code identifier | Definition | Turkish term | Source |
|---|---|---|---|---|
| bootstrap administrator | ensure_bootstrap_admin |
The first administrator account that the start-up creates on a database without users. | ilk yönetici | src/cluster_erp/server/app.py:894-900 |
| bootstrap password file | bootstrap_password_file |
The owner-only file that receives a generated first password. | ilk parola dosyası | src/cluster_erp/config/settings.py:205 |
Related pages¶
Verified against commit 92f8051 on 2026-11-13.