π BasicRum β Dokploy Deployment β
Overview β
We use Dokploy as a self-hosted PaaS to deploy the frontend and backend as Docker containers, with PostgreSQL and ClickHouse running as compose services.
Architecture β
βββββββββββββββββββββββββββββββββββββββββββββββ
β Traefik β
β (managed by Dokploy) β
ββββββββββββββββββββ¬βββββββββββββββββββββββββββ€
β dev.basicrum.com β dev.basicrum.com/backend β
β :3000 β :8080 β
ββββββββββββββββββββΌβββββββββββββββββββββββββββ€
β Frontend β Backend β
β (Dockerfile) β (Dockerfile) β
ββββββββββββββββββββ΄βββββββββββββββββββββββββββ€
β dokploy-network β
βββββββββββββββββββ¬ββββββββββββββββββββββββββββ€
β PostgreSQL β ClickHouse β
β :5432 β :8123 β
βββββββββββββββββββ΄ββββββββββββββββββββββββββββThe dokploy app itself runs on the :3000 port but it is not mapped to the public domain. Only the frontend and backend containers are exposed publicly through Traefik.
Services β
The frontend and backend are deployed as separate Docker containers, while PostgreSQL and ClickHouse run as compose services. The compose services are not exposed publicly and can only be accessed by the backend container over the internal dokploy-network.
PostgreSQL (Compose) β
- Compose file:
compose/dokploy/postgres-compose.yaml - Container name:
basicrum_postgres - Internal host:
basicrum_postgres:5432
In the dokploy dashboard:
Select Compose path: ./compose/dokploy/postgres-compose.yaml
ClickHouse (Compose) β
- Compose file:
compose/dokploy/clickhouse-compose.yaml - Container name:
basicrum_clickhouse - Internal host:
basicrum_clickhouse:8123

Backend (Dockerfile) β
The backend is built from the backend/Dockerfile and runs in a separate container. It connects to PostgreSQL and ClickHouse over the internal dokploy-network using the service names as hosts.


- Dockerfile:
backend/Dockerfile - Build context:
./(repo root β needed forapi_contractworkspace dependency) - Port:
8080 - Domain:
dev.basicrum.comwith path/backend

Note: the backend must be accessed through the full domain
dev.basicrum.com/backend, since both the frontend and backend are on the same domain, any requests made to any url starting withdev.basicrum.com/backendwill be routed to the backend container by Traefik. Any other urls (e.g.dev.basicrum.com/some-random-url) will be routed to the frontend container.
Environment variables β
HOST=0.0.0.0
PORT=8080
NODE_ENV=production
PG_URL=postgresql://basicrum:basicrumXYZ%21@basicrum_postgres:5432/basicrum
CLICKHOUSE_URL=http://basicrum_clickhouse:8123
CLICKHOUSE_USER=default
CLICKHOUSE_PASSWORD=local_dev_pass
# AES-256-GCM key for encrypting org AI tokens (bring-your-own-key).
# Generate with: openssl rand -base64 32
ORG_TOKEN_ENC_KEY_V1=your_base64_32_byte_key
HOSTmust be0.0.0.0β otherwise the container only listens on loopback and Traefik returns 502.
Frontend (Dockerfile) β
Frontend follows a similar setup. It is built from the frontend/Dockerfile and runs in a separate container. However, it talks to the backend by addressing it with the full qualified domain dev.basicrum.com/backend (not the internal container name) so that requests go through Traefik. (Todo: check if we can use the internal container name here to bypass Traefik and speed up requests).
- Dockerfile:
frontend/Dockerfile - Build context:
./(repo root) - Port:
3000 - Domain:
dev.basicrum.com

Environment variables β
NEXTAUTH_SECRET=<your-secret>
NEXTAUTH_URL=http://dev.basicrum.com
AUTH_TRUST_HOST=true
NEXT_PUBLIC_API_URL=https://dev.basicrum.com
BACKEND_URL_FOR_AUTH=https://dev.basicrum.com/backend/v1Find the backend container name with:
docker ps --filter "name=basicrum" --format "{{.Names}}"
Useful Commands β
SSH into the server β
ssh <user>@<server-ip>Check running containers β
docker ps --filter "name=basicrum" --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"PostgreSQL β
Connect to psql:
docker exec -it basicrum_postgres psql -U basicrum -d basicrumList tables:
\dtInspect a table:
\d usersQuery rows:
SELECT * FROM users;
SELECT * FROM organizations;Delete a user:
DELETE FROM users WHERE email = 'user@example.com';ClickHouse β
Connect to clickhouse-client:
docker exec -it basicrum_clickhouse clickhouse-clientList tables:
SHOW TABLES;View container logs β
docker logs -f basicrum_postgres
docker logs -f basicrum_clickhouse
docker logs -f <backend-container-name>
docker logs -f <frontend-container-name>Restart a container β
docker restart <container-name>Check Docker networks β
docker network inspect dokploy-network