Deployment
Quazzar Cloud OS is designed for bare metal servers and VPS instances. It is distributed as a .deb package through the Quazzar APT repository.
APT Installation
Add the Quazzar APT repository and install the package:
# Import GPG key
curl -fsSL https://apt.quazzar.cloud/apt/gpg-key.asc | sudo gpg --dearmor -o /usr/share/keyrings/quazzar.gpg
# Add Quazzar repositories (stable + testing)
sudo tee /etc/apt/sources.list.d/quazzar.list <<'EOF'
deb [signed-by=/usr/share/keyrings/quazzar.gpg] https://apt.quazzar.cloud/apt stable main
deb [signed-by=/usr/share/keyrings/quazzar.gpg] https://apt.quazzar.cloud/apt testing main
EOF
# Update and install
sudo apt update
sudo apt install quazzarDuring installation, a terminal installer lets you choose which optional components to install (S3 storage, VPN, local AI, mail, WhatsApp, system tuning, network management). The package no longer installs Docker on its own: the installer keeps, replaces or installs it according to your choice. Without a terminal, defaults are used; to choose in a script, set QUAZZAR_COMPONENTS. See Components.
After installation, the setup output will show:
Quazzar service installed. To start:
sudo systemctl start quazzar.service
Edit configuration:
sudo nano /etc/quazzar/quazzar.envStart the Service
sudo systemctl start quazzar.service
sudo systemctl enable quazzar.serviceDocker
Alternatively, run Cloud OS as a Docker container. The image is hosted on the Quazzar private registry.
docker run -d \
--name quazzar \
--restart unless-stopped \
-p 8080:8080 \
-p 443:443 \
-p 80:80 \
-v /var/run/docker.sock:/var/run/docker.sock \
-v quazzar-data:/var/lib/quazzar \
docker.quazzar.space/cloud-os:latestCloud OS needs access to the Docker socket to manage application containers. When running Cloud OS itself in Docker, mount the host’s Docker socket into the container.
Health Checks
Cloud OS exposes a health endpoint at GET /health for load balancers and monitoring tools. It returns 200 OK when the service is running and the database is accessible.
Upgrading
Upgrade via APT like any other system package:
sudo apt update
sudo apt full-upgrade -yThe quazzar.service is automatically restarted after the upgrade.
Docker
docker pull docker.quazzar.space/cloud-os:latest
docker compose up -dAlways back up the data directory before upgrading. Database migrations run automatically on startup.
Schema migrations (0.6.35)
0.6.35 ships with database migrations that run automatically on startup — no manual step is required. For reference, the release includes:
| Side | Migration | What it does |
|---|---|---|
Node (quazzar.db) | 068 | Creates the notes table for the Memory MCP + Orbit Notes surface |
Node (quazzar.db) | 069 | Adds the notes_embed_queue + cosine index for semantic search |
Node (quazzar.db) | 070 | Adds widget_size_shape storage columns for the free-form dashboard grid |
Control Panel (cc.db) | 058 | Extends billing_packages.features with Orbit Pro keys (orbit_collab, orbit_pivot, …) |
Control Panel (cc.db) | 059 | Adds mcp_memory_snapshots for cross-node sync |
Migrations are idempotent and run in order. If a migration fails, the service refuses to start and logs the migration index; restore from backup before retrying.
Back up /var/lib/quazzar/data/quazzar.db (node) and the Control Panel PostgreSQL database before upgrading to 0.6.35. The new tables hold durable state for Memory MCP and Orbit, and restoring a pre-0.6.35 backup after running migrations requires reapplying them manually.
Ownerless MSP clients and policies
MSP clients and fleet governance policies belong to a workspace (Control Center migrations 100 and 101). Rows created before those migrations had no owner and are hidden from every workspace until they get one. On every start, migration 104 assigns an owner wherever the data points at exactly one workspace:
- an MSP client linked from the nodes of a single workspace (Fleet → node → Client), or named only in that workspace’s audit log;
- a policy whose recorded violations are all on one workspace’s nodes, or named only in that workspace’s audit log;
- on a single-workspace install (self-hosted with one tenant), every remaining ownerless client and policy goes to that workspace.
Anything else stays ownerless. To find and assign those rows, run against the Control Center PostgreSQL database:
-- What is still ownerless
SELECT id, name, slug, contact_email, created_at FROM msp_clients WHERE tenant_id IS NULL;
SELECT id, name, policy_type, created_at FROM fleet_policies WHERE tenant_id IS NULL;
-- Find the workspace (tenant) to give them to
SELECT id, name, email FROM tenants ORDER BY created_at;
-- Assign
UPDATE msp_clients SET tenant_id = '<tenant id>' WHERE id = '<client id>' AND tenant_id IS NULL;
UPDATE fleet_policies SET tenant_id = '<tenant id>' WHERE id = '<policy id>' AND tenant_id IS NULL;
-- Or remove what nobody needs any more
DELETE FROM fleet_policies WHERE id = '<policy id>' AND tenant_id IS NULL;A client assigned to an MSP workspace is also visible to its parent MSP (the MSP that created that client workspace). Policies take effect for the new owner on the next evaluation pass (every 10 minutes).
CI: GOTOOLCHAIN pin
Starting in 0.6.34, builds require GOTOOLCHAIN=go1.25.5 to sidestep a runner-vs-toolchain mismatch in the Go 1.24/1.25 rollout. If you build from source or run CI jobs against the repo, export the variable at the top of your pipeline:
variables:
GOTOOLCHAIN: "go1.25.5"The upstream Dockerfile and .gitlab-ci.yml already pin this. The requirement disappears once the standard runner image upgrades to Go 1.25+.