Deployment¶
The verified deployment model is one Linux control-plane host running Apache/PHP, PostgreSQL/PostGIS connectivity, a systemd backend, and one templated service instance per project. Treat all checked-in credentials as exposed and rotate/replace them before deployment.
Production checklist¶
- Use PHP 8.1+ with required extensions; disable
display_errors. - Create a dedicated application database/role and apply schema/migrations explicitly.
- Replace
admin/incl/const.php,incl/oidc_config.php, and deploy environment files with secret-managed values and restrictive permissions. - Align PHP path constants,
/etc/default/qz-sync-backend, units, and publisher storage. - Run PHP as a constrained web identity; run workers as
quartz; grant only required shared-group access. - Restrict the web root from serving
deploy/,installer/,sql/, config files, logs, generated project files, and repository metadata. - Put Central, FormBuilder, analysis, and QGIS Publish upstreams on trusted loopback/private interfaces.
- Terminate TLS at the front proxy and set secure session-cookie policy in the session/Central platform configuration.
- Back up and restore-test metadata, target databases, project config/data, and published projects.
- Verify auth, one real sync of each enabled type, publishing, logs, and failure alerts.
systemd¶
Current units under deploy/:
qz-sync-backend.service: FIFO manager, restart on failure, file log.qf-sync@.service: QField worker asquartz.gdb-sync@.service: ArcGIS worker asquartz.db-sync@.service: external Mergin DB Sync daemon asquartz.geosync-formbuilder.service: external binary on port 9095.geosync-analysis.service: external binary configured for port 8081.
Install only reviewed units:
sudo install -m 0644 deploy/qz-sync-backend.service /etc/systemd/system/
sudo install -m 0644 deploy/qf-sync@.service deploy/gdb-sync@.service deploy/db-sync@.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now qz-sync-backend.service
Project instances are controlled as qf-sync@<id>, gdb-sync@<id>, or db-sync@<id>. Unit paths are hard-coded and must match the installed scripts/environments. The backend unit has no explicit User, so it runs as root; its FIFO permits the www-data group to submit a fixed but powerful set of systemctl operations. Harden the host and do not expose FIFO access to other users.
Apache¶
The installer deploys Apache with libapache2-mod-php, but this repository supplies no complete Apache virtual host. A production vhost must:
- set the document root or alias to the reviewed GeoSync files;
- route PHP and preserve the mount prefix used by
GEOSYNC_BASE_PATH; - deny dotfiles, config/environment, SQL, installer, deploy, and worker directories;
- set
auto_prepend_fileonly if usingincl/auth_gate.php; most current entry points explicitly includegeosync_auth_prepend.php; - preserve the
Authorizationheader if legacy OIDC/OAuth requires it; - forward the original HTTPS/host context consistently;
- allow request bodies/timeouts large enough for QGIS publish bundles only on the required action.
Do not enable both old auth_gate.php and current Central prepend without testing redirect/public-path behavior; they use different mode resolution.
Nginx and reverse proxy¶
No Nginx configuration is supplied or verified. If Nginx fronts PHP-FPM or Apache, use an explicit GeoSync location, deny sensitive paths, set SCRIPT_NAME/REQUEST_URI correctly, and pass:
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
That fragment is an operator pattern, not a drop-in vhost. GeoSync itself derives scheme from $_SERVER['HTTPS'], not X-Forwarded-Proto, so configure the trusted web tier to translate forwarded HTTPS into the PHP HTTPS server variable. Never trust forwarded headers from the public network directly.
The PHP application already proxies FormBuilder and analysis; do not also expose their loopback ports unless needed. api/proxy.php is safer for API calls because it has an exact allow-list. The broader analysis/ and formbuilder/ proxies should be protected by the same authentication and mount rules.
TLS¶
installer/post-install.sh and extras/ssl.sh use Certbot’s Apache plugin for the host FQDN. They are environment-specific automation, not a general certificate policy. In production:
- automate issuance/renewal and alert on expiry;
- redirect HTTP to HTTPS and use HSTS only after all subdomains are ready;
- mark session cookies Secure, HttpOnly, and an appropriate SameSite value in the component that creates them;
- use TLS to Central and databases where traffic leaves the host;
- do not rely on GeoSync’s QGIS Publish client for certificate validation—it currently disables peer/host verification. Prefer loopback/private transport and fix validation before remote HTTPS use.
Docker and Compose¶
GeoSync contains no Dockerfile or Compose file. There is no verified image, entrypoint, volume layout, or container health check, so Docker/Compose deployment is unsupported. Do not infer commands from sibling repositories. Containerization must redesign systemd/FIFO control or separate PHP, workers, and databases into supervised services with durable configuration/data volumes.
Scaling¶
Run one active GeoSync control plane per FIFO/config/data set. Horizontal control-plane scaling is unsupported because commands, generated files, PID files, logs, and worker directories are host-local and not transactionally locked. Scale PostgreSQL and optional upstream services according to their own documentation, and isolate projects across worker hosts only with an explicit scheduler/config ownership design.
Backups and recovery¶
Back up:
- GeoSync PostgreSQL database, including optional migrations/bridge data;
- every target PostGIS database;
/etc/quartz-sync.d(contains plaintext secrets),/etc/default/qz-sync-backend, and protected auth/PHP configuration;QZ_DATAif downloaded project history/images are required for recovery;- QGIS Publish
PROJECTS_ROOT; - service units and external worker version/patch records.
Use pg_dump/pg_restore or organization-managed PostgreSQL backups. Quiesce affected workers or take database-consistent snapshots before filesystem capture. Encrypt backups, restrict access, define retention outside this repository, and regularly restore into an isolated host. Retained GeoPackages are not a substitute for database backups.
Health and monitoring¶
There is no dedicated GeoSync PHP health/readiness endpoint and no metrics exporter. The allow-listed FormBuilder upstream has GET health, but that checks the external service, not the whole system.
Monitor:
- an authenticated synthetic request to a low-risk GeoSync page;
- PostgreSQL connectivity and migration state;
systemctl is-active qz-sync-backendand enabled project units;- FIFO existence/type/ownership;
- worker last-success time, exit/restart counts, and stale sync age;
- disk/inodes for
QZ_DATA, logs, temporary files, and published projects; - upstream reachability, certificate expiry, backup success, and restore tests.
Collect journald plus /var/log/qz_sync_backend.log, /var/log/qz_sync<id>.log, and rsync logs. Redact connection strings/passwords: legacy workers and generated scripts can emit sensitive command context. Log rotation and alert thresholds are not supplied and must be defined by operations.