Skip to content

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

  1. Use PHP 8.1+ with required extensions; disable display_errors.
  2. Create a dedicated application database/role and apply schema/migrations explicitly.
  3. Replace admin/incl/const.php, incl/oidc_config.php, and deploy environment files with secret-managed values and restrictive permissions.
  4. Align PHP path constants, /etc/default/qz-sync-backend, units, and publisher storage.
  5. Run PHP as a constrained web identity; run workers as quartz; grant only required shared-group access.
  6. Restrict the web root from serving deploy/, installer/, sql/, config files, logs, generated project files, and repository metadata.
  7. Put Central, FormBuilder, analysis, and QGIS Publish upstreams on trusted loopback/private interfaces.
  8. Terminate TLS at the front proxy and set secure session-cookie policy in the session/Central platform configuration.
  9. Back up and restore-test metadata, target databases, project config/data, and published projects.
  10. 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 as quartz.
  • gdb-sync@.service: ArcGIS worker as quartz.
  • db-sync@.service: external Mergin DB Sync daemon as quartz.
  • 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_file only if using incl/auth_gate.php; most current entry points explicitly include geosync_auth_prepend.php;
  • preserve the Authorization header 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_DATA if 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-backend and 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.