Architecture¶
Strawly runs as a set of Docker containers, one set per instance, started by Docker Compose. This page describes how the pieces fit together.
Services¶
Caddy (instance proxy)¶
- Purpose: Serves the web interface and the API on one address and one port (
STRAWLY_HTTP_PORT). Requests to/apigo to the backend, everything else to the frontend. - Why one address: The browser talks to a single origin, so there is no cross-origin setup, and the login cookie works the same in every mode.
Frontend¶
- Framework: Next.js
- Purpose: Web interface. It talks only to the backend API, never to modules or the database.
- Configuration: Reads its settings when it starts, not when the image is built, so the same image works in every deployment.
Backend¶
- Framework: Express.js, with PostgreSQL through Prisma
- Purpose: The API. It handles sign-in and permissions, stores settings, serves the data modules collect, and proxies module requests that need the module itself.
- Schema ownership: The backend owns the database schema. Only its
migrationscontainer changes it. Modules never run migrations.
PostgreSQL¶
- Purpose: One database per instance, shared by the backend and the modules.
- Exposure: Reachable only inside the instance's Docker network.
- Data separation: Each module writes its own prefixed tables, for example
az_*in theazureschema.
Migrations and seeder (one-shot containers)¶
- migrations runs
prisma migrate deploy, then exits. It runs on every start, so an upgrade updates the database before the new backend starts. - seeder creates the default roles and, on a new database, the first admin account. It can run any number of times.
Modules (optional)¶
Each module is its own service, enabled with a compose profile. The Azure Optimizations module runs two containers from one image: the API (optimizations-azure) and the collector scheduler (optimizations-azure-worker). See Modules Overview.
Edge proxy (domain mode)¶
One Caddy server per machine, shared by every instance that uses a domain. It owns ports 80 and 443, gets a Let's Encrypt certificate for each domain, and forwards each domain to that instance's proxy. See Multiple Instances.
Data flow¶
Browser ──HTTPS──> Edge proxy (domain mode only)
│
▼
Instance proxy (Caddy, one port)
├── /api/* ──> Backend ──> PostgreSQL <── Module
└── /* ──> Frontend │
▼
Azure APIs
The frontend never talks to modules directly. Modules write their findings to the database, and the backend serves them.
Startup order¶
- postgres starts and reports healthy.
- migrations updates the schema and exits.
- seeder creates roles and the first admin, and exits.
- backend starts.
- frontend, caddy and the modules start once the backend is healthy.
Module registration¶
When a module starts, and every minute after, it registers with the backend. It sends its version, the core versions it supports, the database schema it was built for, and its default settings.
- On a new instance, registration creates the module's settings, so the module appears in Strawly without any setup step. Later registrations never overwrite settings you changed.
- Version check. The backend replies whether the module fits the running core and database. A module that does not fit pauses its collectors and reports
incompatiblein its health check, and the backend refuses requests to it with a message naming both versions.
Versioning¶
The frontend and backend share one version, the core version. Modules have their own versions and declare the core versions they support. See Updating.
Images are built when a version is tagged in the source repository, for linux/amd64 and linux/arm64, and published as:
| Image | Tags |
|---|---|
git.strawly.app/strawly/strawly-backend |
1.5.0, 1.5, 1, latest |
git.strawly.app/strawly/strawly-frontend |
the same as the backend |
git.strawly.app/strawly/strawly-optimizations-azure |
its own versions |
Pre-releases such as 1.6.0-rc.1 are published only under their own tag. Each image carries its version, source commit and, for modules, the supported core range as image labels.
Repositories¶
| Repository | Contains |
|---|---|
Strawly/backend |
The API |
Strawly/frontend |
The web interface |
Strawly/optimizations-azure |
The Azure module |
Strawly/shared |
Code and the database schema shared by the backend and modules |
Strawly/deployment |
Compose files, the strawly command, the installer and versions.json |
Secrets¶
Secrets are passed to the containers as environment variables when they start and are never built into images. The installer generates them into the instance's .env. See Environment Variables.