Repository navigation
Releases
Quire Server 0.4.0
Docker behind a gate, each site on a network link of its own, problems told to the owner, backups that prove where they come from, Quire's code checked against its signed feed, and a server that holds hundreds of sites. Also every Low and Info of the server audit of 2026-10-29.
Updating from 0.3.1
quire-server update moves a server to 0.4.0, checked by 0.3.1's own updater. The first start of 0.4.0's agent then:
- removes what 0.3.1 ran: the docker-proxy, its network and the privileged builders. Docker is reached through YorvoGate from then on;
- moves each site to its link: each site is started again on its own networks, every container made again (a few seconds offline each, one site after the other), with
restart: unless-stoppedfor every service, its own PostgreSQL included.
Then:
- Run
quire-server uponce. It sizes PostgreSQL's connections for the machine's memory (QUIRE_SERVER_DATABASE_CONNECTIONS): PostgreSQL starts again with them, every site offline a few seconds. Until then it keeps 200, the limit of 0.3.1. - Keep the backups' new public key. With backups off the server set up, the first night makes the server's key for them;
quire-server statusshows its public key. Keep it with the backups' password, somewhere other than the server: another server needs it to restore this one's backups. - Backups made by 0.3.1 aren't signed: restoring one needs
--unsigned(only for a backup you know comes from your server). - Sites that ask for more are refused when they're next started, updated or deployed, until their files change: a service name with a
-, a site or project name of exactly 12 hex digits, Docker's or the server's own labels, annotations, a set-user-IDtmpfs, memory above 64 GiB, ulimits other thannofile,nproc,coreandstack. Sites made from Quire's skeleton ask for none of these. - Ubuntu 26.04 LTS or a later LTS release is what the server runs on. A server on another system keeps running, but sites' rootless builders rely on Ubuntu's AppArmor profile, and nothing checks the server there.
Added
- Docker behind YorvoGate 0.2.2 (pinned by digest), which reads every request's body before Docker gets it. Each site's Compose runs on a socket of its own, held to what the server allows the site; the agent's own operations go to a trusted socket. Before the gate is replaced (an install, an update), the new gate checks every site's scope (
yorvogate check). - Rootless builders: each site builds on a BuildKit of its own, as user 1000, not privileged, with no capabilities.
host-setuploads an AppArmor profile that grants only them a user namespace, at every start of the server. - A network link per site (D-34): its own range of addresses (a /26 per site from
QUIRE_SERVER_SITE_NETWORKS,10.72.0.0/16by default, room for 1,024 sites), shared only with the front door and PostgreSQL. No site reaches another, a site's PostgreSQL role logs in only from its link, and sites trust only the front door as their proxy. The installer refuses a range the machine routes elsewhere and names a free one (--site-networks=);quire-server upandupdatename a route on it that appeared since. - Problems reach the owner (D-35): failed nightly work (backups, automatic updates, rebuilds, Git deploys), backups that stopped running, certificates missing or not renewed, a disk filling up, memory running out, notifications that couldn't be sent. Each is told once when it starts, weekly while it lasts and once when it's over, by email and to a webhook (HTTPS, signed as GitHub signs its webhooks).
quire-server statuslists them,--dismiss=<key>stops one,quire-server notify:testsends a test. - Backups prove where they come from (D-36): the server records each snapshot it makes and signs the list of those it keeps with a key of its own (Ed25519). A restore takes only a snapshot this server made, or one another server's signed list vouches for (
--signed-by=ed25519:…). - Backups that survive a stolen
server.env(D-37): a bucket with Object Lock and versioning keeps what's deleted; setup and every night prove whether it does, and say so. Each night checks every backup the server made is still there;quire-server backups:recover --before=<time>brings the repository back as it was. - Quire's code is the code Quire released (D-38): every build checks each
quire/*package in the site'scomposer.lockagainst the commit Quire's signed feed names for its version, and a new site's skeleton against the feed's files. - A way back after removing, restoring or undoing:
quire-server site:restore-removed,quire-server backups <site> --localandquire-server backups:restore <site> --file=<name>; each of those operations ends with the command that undoes it. quire-server database:upgrade: the server's PostgreSQL to a newer major (18 to 19) and back, copied beside the old one and checked before the switch;--check,--undo,--clean,--recover.quire-server site:domains: a site's domains, or others instead.quire-server helplists the commands by what they're for;quire-server site:auto-updates; the installer offers Let's Encrypt's staging certificates (--staging-certificates).
Changed
- Ubuntu 26.04 LTS and later LTS releases only. The installer refuses interim releases and other distributions;
--unsupported-osinstalls anyway, with a warning. - Sites at scale (D-39, D-40), from two scale tests of 133 and 139 sites on 32 GB:
- a site's builder runs only while it builds, its cache trimmed to its newest 512 MB after each build;
- a site's php runs 4 PHP threads, whatever the machine's CPUs; a session idle for 11 minutes ends; a site's role holds at most 16 connections; PostgreSQL's connections follow the machine's memory (200 to 1,000);
- when memory runs out, the kernel stops a site's container first, PostgreSQL last; a new site isn't built while less than 1.5 GB is free (
QUIRE_SERVER_BUILD_MEMORY_MB).
- Failures say what happened and what to do, not a tool's raw output; the tool's own words go to the operation's log. A long build says every 30 seconds that it still runs.
- A build that fails for a reason that passes by itself (a host's 5xx or 429, a connection cut) is tried once more, 30 seconds later.
- The Compose policy refuses service names with a
-, site and project names of 12 hex digits, the server's and Docker's labels, annotations, set-user-IDtmpfs, memory above 64 GiB and ulimits other than the gate's; one live site per Compose project. - Inputs are held tighter: domains (punycode, lookalike and mixed scripts, special-use names), Git addresses (no token, no private address unless
QUIRE_SERVER_GIT_PRIVATE_HOSTSnames it, Git held to the address checked, no redirects), branches. no-new-privilegesis written in Docker's own spelling (no-new-privileges=true), so Docker 29 no longer warns; the policy still takes every spelling.- Webhooks are sent over TLS 1.2 or newer, said in the sender.
- Symfony 8.1.11, with the fixes for the twelve advisories published on 2026-11-04.
Fixed
- Sites come back after a reboot: every container of a site gets
restart: unless-stopped, its own PostgreSQL too, and the server's PostgreSQL reloads its logins without Docker counting it as stopped by hand. quire-server update --undo, and the rollback of a failed update, restore the server's registry whole, in one transaction: an older release's registry over a newer one failed when a newer migration had added a table with a key on an older one (0.4.0'ssite_network), and the server stayed on the newer release. A restore that fails at any point changes nothing.- A failed add, restore as a new site or adoption no longer leaves its builder, its cache and its gate scope behind.
- A deploy that would delete files edited in the site's folder is refused, naming them.
- Operation logs are scrubbed of secrets also when encoded (base64, JSON), and of passwords in addresses.
- The updater trusts only the records it sealed, with a key the agent doesn't reach; release archives with links or paths outside them are refused.
- The installer builds the server beside and moves it in whole, takes over a lock a cut-short run left, and stops when a release file changed since it was installed.
- The front door says "No site here" over HTTP for a domain it doesn't serve.
Security
The server audit of 2026-10-29: its Mediums left open in 0.3.1 (M-01 the Docker gate, M-06 the feed's commits, M-08 the sites' links, M-11 the backups' origin, M-13 the backups' protection, M-14 problems told, M-19 a way back, M-20 failures said), and every Low and Info.
Image: ghcr.io/quirecms/server@sha256:fd236f5fe649a461045c2e5b4e32999e9af58bcbc2afd365fd33cc9283fe2e09
Quire Server 0.4.0-rc.2
Docker behind a gate, each site on a network link of its own, problems told to the owner, backups that prove where they come from, Quire's code checked against its signed feed, and a server that holds hundreds of sites. Also every Low and Info of the server audit of 2026-10-29.
Updating from 0.3.1
quire-server update moves a server to 0.4.0, checked by 0.3.1's own updater. The first start of 0.4.0's agent then:
- removes what 0.3.1 ran: the docker-proxy, its network and the privileged builders. Docker is reached through YorvoGate from then on;
- moves each site to its link: each site is started again on its own networks, every container made again (a few seconds offline each, one site after the other), with
restart: unless-stoppedfor every service, its own PostgreSQL included.
Then:
- Run
quire-server uponce. It sizes PostgreSQL's connections for the machine's memory (QUIRE_SERVER_DATABASE_CONNECTIONS): PostgreSQL starts again with them, every site offline a few seconds. Until then it keeps 200, the limit of 0.3.1. - Keep the backups' new public key. With backups off the server set up, the first night makes the server's key for them;
quire-server statusshows its public key. Keep it with the backups' password, somewhere other than the server: another server needs it to restore this one's backups. - Backups made by 0.3.1 aren't signed: restoring one needs
--unsigned(only for a backup you know comes from your server). - Sites that ask for more are refused when they're next started, updated or deployed, until their files change: a service name with a
-, a site or project name of exactly 12 hex digits, Docker's or the server's own labels, annotations, a set-user-IDtmpfs, memory above 64 GiB, ulimits other thannofile,nproc,coreandstack. Sites made from Quire's skeleton ask for none of these. - Ubuntu 26.04 LTS or a later LTS release is what the server runs on. A server on another system keeps running, but sites' rootless builders rely on Ubuntu's AppArmor profile, and nothing checks the server there.
Added
- Docker behind YorvoGate 0.2.2 (pinned by digest), which reads every request's body before Docker gets it. Each site's Compose runs on a socket of its own, held to what the server allows the site; the agent's own operations go to a trusted socket. Before the gate is replaced (an install, an update), the new gate checks every site's scope (
yorvogate check). - Rootless builders: each site builds on a BuildKit of its own, as user 1000, not privileged, with no capabilities.
host-setuploads an AppArmor profile that grants only them a user namespace, at every start of the server. - A network link per site (D-34): its own range of addresses (a /26 per site from
QUIRE_SERVER_SITE_NETWORKS,10.72.0.0/16by default, room for 1,024 sites), shared only with the front door and PostgreSQL. No site reaches another, a site's PostgreSQL role logs in only from its link, and sites trust only the front door as their proxy. The installer refuses a range the machine routes elsewhere and names a free one (--site-networks=);quire-server upandupdatename a route on it that appeared since. - Problems reach the owner (D-35): failed nightly work (backups, automatic updates, rebuilds, Git deploys), backups that stopped running, certificates missing or not renewed, a disk filling up, memory running out, notifications that couldn't be sent. Each is told once when it starts, weekly while it lasts and once when it's over, by email and to a webhook (HTTPS, signed as GitHub signs its webhooks).
quire-server statuslists them,--dismiss=<key>stops one,quire-server notify:testsends a test. - Backups prove where they come from (D-36): the server records each snapshot it makes and signs the list of those it keeps with a key of its own (Ed25519). A restore takes only a snapshot this server made, or one another server's signed list vouches for (
--signed-by=ed25519:…). - Backups that survive a stolen
server.env(D-37): a bucket with Object Lock and versioning keeps what's deleted; setup and every night prove whether it does, and say so. Each night checks every backup the server made is still there;quire-server backups:recover --before=<time>brings the repository back as it was. - Quire's code is the code Quire released (D-38): every build checks each
quire/*package in the site'scomposer.lockagainst the commit Quire's signed feed names for its version, and a new site's skeleton against the feed's files. - A way back after removing, restoring or undoing:
quire-server site:restore-removed,quire-server backups <site> --localandquire-server backups:restore <site> --file=<name>; each of those operations ends with the command that undoes it. quire-server database:upgrade: the server's PostgreSQL to a newer major (18 to 19) and back, copied beside the old one and checked before the switch;--check,--undo,--clean,--recover.quire-server site:domains: a site's domains, or others instead.quire-server helplists the commands by what they're for;quire-server site:auto-updates; the installer offers Let's Encrypt's staging certificates (--staging-certificates).
Changed
- Ubuntu 26.04 LTS and later LTS releases only. The installer refuses interim releases and other distributions;
--unsupported-osinstalls anyway, with a warning. - Sites at scale (D-39, D-40), from two scale tests of 133 and 139 sites on 32 GB:
- a site's builder runs only while it builds, its cache trimmed to its newest 512 MB after each build;
- a site's php runs 4 PHP threads, whatever the machine's CPUs; a session idle for 11 minutes ends; a site's role holds at most 16 connections; PostgreSQL's connections follow the machine's memory (200 to 1,000);
- when memory runs out, the kernel stops a site's container first, PostgreSQL last; a new site isn't built while less than 1.5 GB is free (
QUIRE_SERVER_BUILD_MEMORY_MB).
- Failures say what happened and what to do, not a tool's raw output; the tool's own words go to the operation's log. A long build says every 30 seconds that it still runs.
- A build that fails for a reason that passes by itself (a host's 5xx or 429, a connection cut) is tried once more, 30 seconds later.
- The Compose policy refuses service names with a
-, site and project names of 12 hex digits, the server's and Docker's labels, annotations, set-user-IDtmpfs, memory above 64 GiB and ulimits other than the gate's; one live site per Compose project. - Inputs are held tighter: domains (punycode, lookalike and mixed scripts, special-use names), Git addresses (no token, no private address unless
QUIRE_SERVER_GIT_PRIVATE_HOSTSnames it, Git held to the address checked, no redirects), branches. no-new-privilegesis written in Docker's own spelling (no-new-privileges=true), so Docker 29 no longer warns; the policy still takes every spelling.- Webhooks are sent over TLS 1.2 or newer, said in the sender.
- Symfony 8.1.11, with the fixes for the twelve advisories published on 2026-11-04.
Fixed
- Sites come back after a reboot: every container of a site gets
restart: unless-stopped, its own PostgreSQL too, and the server's PostgreSQL reloads its logins without Docker counting it as stopped by hand. quire-server update --undo, and the rollback of a failed update, restore the server's registry whole, in one transaction: an older release's registry over a newer one failed when a newer migration had added a table with a key on an older one (0.4.0'ssite_network), and the server stayed on the newer release. A restore that fails at any point changes nothing.- A failed add, restore as a new site or adoption no longer leaves its builder, its cache and its gate scope behind.
- A deploy that would delete files edited in the site's folder is refused, naming them.
- Operation logs are scrubbed of secrets also when encoded (base64, JSON), and of passwords in addresses.
- The updater trusts only the records it sealed, with a key the agent doesn't reach; release archives with links or paths outside them are refused.
- The installer builds the server beside and moves it in whole, takes over a lock a cut-short run left, and stops when a release file changed since it was installed.
- The front door says "No site here" over HTTP for a domain it doesn't serve.
Security
The server audit of 2026-10-29: its Mediums left open in 0.3.1 (M-01 the Docker gate, M-06 the feed's commits, M-08 the sites' links, M-11 the backups' origin, M-13 the backups' protection, M-14 problems told, M-19 a way back, M-20 failures said), and every Low and Info.
Image: ghcr.io/quirecms/server@sha256:0603c218d161325e808f8c4cadcc91a2c75b4cda6a0e5b3749a025a2046595f2
Quire Server 0.4.0-rc.1
Docker behind a gate, each site on a network link of its own, problems told to the owner, backups that prove where they come from, Quire's code checked against its signed feed, and a server that holds hundreds of sites. Also every Low and Info of the server audit of 2026-10-29.
Updating from 0.3.1
quire-server update moves a server to 0.4.0, checked by 0.3.1's own updater. The first start of 0.4.0's agent then:
- removes what 0.3.1 ran: the docker-proxy, its network and the privileged builders. Docker is reached through YorvoGate from then on;
- moves each site to its link: each site is started again on its own networks, every container made again (a few seconds offline each, one site after the other), with
restart: unless-stoppedfor every service, its own PostgreSQL included.
Then:
- Run
quire-server uponce. It sizes PostgreSQL's connections for the machine's memory (QUIRE_SERVER_DATABASE_CONNECTIONS): PostgreSQL starts again with them, every site offline a few seconds. Until then it keeps 200, the limit of 0.3.1. - Keep the backups' new public key. With backups off the server set up, the first night makes the server's key for them;
quire-server statusshows its public key. Keep it with the backups' password, somewhere other than the server: another server needs it to restore this one's backups. - Backups made by 0.3.1 aren't signed: restoring one needs
--unsigned(only for a backup you know comes from your server). - Sites that ask for more are refused when they're next started, updated or deployed, until their files change: a service name with a
-, a site or project name of exactly 12 hex digits, Docker's or the server's own labels, annotations, a set-user-IDtmpfs, memory above 64 GiB, ulimits other thannofile,nproc,coreandstack. Sites made from Quire's skeleton ask for none of these. - Ubuntu 26.04 LTS or a later LTS release is what the server runs on. A server on another system keeps running, but sites' rootless builders rely on Ubuntu's AppArmor profile, and nothing checks the server there.
Added
- Docker behind YorvoGate 0.2.2 (pinned by digest), which reads every request's body before Docker gets it. Each site's Compose runs on a socket of its own, held to what the server allows the site; the agent's own operations go to a trusted socket. Before the gate is replaced (an install, an update), the new gate checks every site's scope (
yorvogate check). - Rootless builders: each site builds on a BuildKit of its own, as user 1000, not privileged, with no capabilities.
host-setuploads an AppArmor profile that grants only them a user namespace, at every start of the server. - A network link per site (D-34): its own range of addresses (a /26 per site from
QUIRE_SERVER_SITE_NETWORKS,10.72.0.0/16by default, room for 1,024 sites), shared only with the front door and PostgreSQL. No site reaches another, a site's PostgreSQL role logs in only from its link, and sites trust only the front door as their proxy. The installer refuses a range the machine routes elsewhere and names a free one (--site-networks=);quire-server upandupdatename a route on it that appeared since. - Problems reach the owner (D-35): failed nightly work (backups, automatic updates, rebuilds, Git deploys), backups that stopped running, certificates missing or not renewed, a disk filling up, memory running out, notifications that couldn't be sent. Each is told once when it starts, weekly while it lasts and once when it's over, by email and to a webhook (HTTPS, signed as GitHub signs its webhooks).
quire-server statuslists them,--dismiss=<key>stops one,quire-server notify:testsends a test. - Backups prove where they come from (D-36): the server records each snapshot it makes and signs the list of those it keeps with a key of its own (Ed25519). A restore takes only a snapshot this server made, or one another server's signed list vouches for (
--signed-by=ed25519:…). - Backups that survive a stolen
server.env(D-37): a bucket with Object Lock and versioning keeps what's deleted; setup and every night prove whether it does, and say so. Each night checks every backup the server made is still there;quire-server backups:recover --before=<time>brings the repository back as it was. - Quire's code is the code Quire released (D-38): every build checks each
quire/*package in the site'scomposer.lockagainst the commit Quire's signed feed names for its version, and a new site's skeleton against the feed's files. - A way back after removing, restoring or undoing:
quire-server site:restore-removed,quire-server backups <site> --localandquire-server backups:restore <site> --file=<name>; each of those operations ends with the command that undoes it. quire-server database:upgrade: the server's PostgreSQL to a newer major (18 to 19) and back, copied beside the old one and checked before the switch;--check,--undo,--clean,--recover.quire-server site:domains: a site's domains, or others instead.quire-server helplists the commands by what they're for;quire-server site:auto-updates; the installer offers Let's Encrypt's staging certificates (--staging-certificates).
Changed
- Ubuntu 26.04 LTS and later LTS releases only. The installer refuses interim releases and other distributions;
--unsupported-osinstalls anyway, with a warning. - Sites at scale (D-39, D-40), from two scale tests of 133 and 139 sites on 32 GB:
- a site's builder runs only while it builds, its cache trimmed to its newest 512 MB after each build;
- a site's php runs 4 PHP threads, whatever the machine's CPUs; a session idle for 11 minutes ends; a site's role holds at most 16 connections; PostgreSQL's connections follow the machine's memory (200 to 1,000);
- when memory runs out, the kernel stops a site's container first, PostgreSQL last; a new site isn't built while less than 1.5 GB is free (
QUIRE_SERVER_BUILD_MEMORY_MB).
- Failures say what happened and what to do, not a tool's raw output; the tool's own words go to the operation's log. A long build says every 30 seconds that it still runs.
- A build that fails for a reason that passes by itself (a host's 5xx or 429, a connection cut) is tried once more, 30 seconds later.
- The Compose policy refuses service names with a
-, site and project names of 12 hex digits, the server's and Docker's labels, annotations, set-user-IDtmpfs, memory above 64 GiB and ulimits other than the gate's; one live site per Compose project. - Inputs are held tighter: domains (punycode, lookalike and mixed scripts, special-use names), Git addresses (no token, no private address unless
QUIRE_SERVER_GIT_PRIVATE_HOSTSnames it, Git held to the address checked, no redirects), branches. no-new-privilegesis written in Docker's own spelling (no-new-privileges=true), so Docker 29 no longer warns; the policy still takes every spelling.- Webhooks are sent over TLS 1.2 or newer, said in the sender.
- Symfony 8.1.11, with the fixes for the twelve advisories published on 2026-11-04.
Fixed
- Sites come back after a reboot: every container of a site gets
restart: unless-stopped, its own PostgreSQL too, and the server's PostgreSQL reloads its logins without Docker counting it as stopped by hand. - A failed add, restore as a new site or adoption no longer leaves its builder, its cache and its gate scope behind.
- A deploy that would delete files edited in the site's folder is refused, naming them.
- Operation logs are scrubbed of secrets also when encoded (base64, JSON), and of passwords in addresses.
- The updater trusts only the records it sealed, with a key the agent doesn't reach; release archives with links or paths outside them are refused.
- The installer builds the server beside and moves it in whole, takes over a lock a cut-short run left, and stops when a release file changed since it was installed.
- The front door says "No site here" over HTTP for a domain it doesn't serve.
Security
The server audit of 2026-10-29: its Mediums left open in 0.3.1 (M-01 the Docker gate, M-06 the feed's commits, M-08 the sites' links, M-11 the backups' origin, M-13 the backups' protection, M-14 problems told, M-19 a way back, M-20 failures said), and every Low and Info.
Image: ghcr.io/quirecms/server@sha256:cbbe961cad2c88a6f97a16131bf6fff926419d7a819bc28a5d5ab21845bc1bda
Quire Server 0.3.1
What's Changed
Full Changelog: v0.3.0...v0.3.1
Quire Server 0.3.0
What's Changed
- A backup becomes a new site: a copy here, or a site moved from another server by @dpoposki in #10
- A whole server from its backups, in one step by @dpoposki in #11
Full Changelog: v0.2.0...v0.3.0
Quire Server 0.2.0
What's Changed
- The server updates itself: checked first, backed up, rolled back by itself by @dpoposki in #5
- Sites update themselves every night, and Quire's signed feed is checked by @dpoposki in #6
- Sites build on Quire's runtime images only when they check out by @dpoposki in #7
- Backups off the server: every night, encrypted, kept and checked by @dpoposki in #8
- Sites are built again on a newer runtime, every night by @dpoposki in #9
Full Changelog: v0.1.1...v0.2.0
Quire Server 0.1.1
What's Changed
- Bump mlocati/php-extension-installer from 2.8 to 2.12 by @dependabot[bot] in #3
- The installer installs releases: cosign may read their files by @dpoposki in #4
New Contributors
- @dependabot[bot] made their first contribution in #3
Full Changelog: v0.1.0...v0.1.1
Quire Server 0.1.0
What's Changed
- Quire Server: the foundation, adopting sites, updates and Git mode by @dpoposki in #1
- Releases you can trust: signed images and files, checked before installing by @dpoposki in #2
New Contributors
Full Changelog: https://github.com/quirecms/server/commits/v0.1.0