| title | Installation |
|---|---|
| description | Install CDNFoundry for local development or prepare a production deployment. |
::: danger Preserve development data
The named PostgreSQL and Compose volumes persist between phases. Never use
docker compose down -v, destructive database refreshes, or PostgreSQL-backed
RefreshDatabase tests. The supported test command forces in-memory SQLite.
:::
- Docker Engine with the Compose plugin
- GNU Make
- Python 3 for real-runtime qualification
- at least 8 GiB RAM for the complete local topology
- free ports
8080,8081,8082,8444,8445,9443,9191,1053/tcp,1053/udp,9090, and9093
The normal workflow builds PHP, Composer, Node, Go, PostgreSQL, Valkey, PowerDNS, OpenResty, and ClickHouse dependencies inside containers.
git clone https://github.com/vaheed/CDNFoundry.git cdnfoundry
cd cdnfoundry
make dev-control-up
make dev-migrate
make dev-upmake dev-control-up starts only the services needed to run Laravel migrations.
After the explicit migration, make dev-up builds and starts the full topology,
including Grafana's read-only PostgreSQL role, development PKI, and GeoIP data.
Neither startup target runs Laravel or PowerDNS migrations implicitly.
Create the first administrator:
docker compose -f compose.dev.yml exec core \
php artisan cdnf:admin:create \
--name="Local Administrator" \
--email="admin@example.test"The command prompts twice for a password and rejects a duplicate email or
mismatch. Open http://localhost:8080/admin.
curl --fail http://localhost:8080/api/health
curl --fail http://localhost:8080/api/ready
docker compose -f compose.dev.yml psRun isolated application tests:
make dev-testThe target sets the only supported destructive-test database combination:
APP_ENV=testing, DB_CONNECTION=sqlite, and DB_DATABASE=:memory:.
Run non-browser real-runtime qualification only after the stack and migrations are healthy:
make dev-e2eThis job uses real HTTP APIs, PostgreSQL, queues, DNSdist, PowerDNS, OpenResty, mutual TLS, Pebble, Vector, and ClickHouse. It does not inspect the rendered UI.
The two OpenResty hosts run before the agents because edge IDs and one-time tokens must come from administrator-created edge rows.
- In Infrastructure → Edges, create edge A and edge B.
- Copy the displayed UUID and bootstrap token for each.
- Create the ignored local environment:
cp .env.dev.example .env.dev
chmod 600 .env.dev- Set
CDNF_DEV_EDGE_A_ID,CDNF_DEV_EDGE_A_BOOTSTRAP_TOKEN,CDNF_DEV_EDGE_B_ID, andCDNF_DEV_EDGE_B_BOOTSTRAP_TOKEN. - Start and inspect the agents:
make dev-edge-up
make dev-edge-status- After both identities are registered and heartbeats are fresh, remove both
bootstrap-token values from
.env.dev.
Named agent volumes retain issued identities. Losing a volume requires the administrator Rotate identity workflow. Its one-time recovery modal provides the unchanged ID plus replacement token as a deployment-neutral environment block; never copy another edge's identity volume.
Do not promote the development environment. Production uses published images,
host-private .env.prod files, explicit PKI, explicit Laravel and PowerDNS
migrations, firewalls, a tested recovery method (optionally the built-in
encrypted Restic integration), and the profiles described in
Production deployment.