Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/danizd/geoviable/llms.txt

Use this file to discover all available pages before exploring further.

The GeoViable production environment runs on an Oracle Cloud Infrastructure Always Free ARM instance. The Always Free tier provides enough RAM and storage for the full stack — PostGIS database, FastAPI backend, PDF generation with WeasyPrint, and the React frontend — with no ongoing cost. An Nginx Proxy Manager instance handles SSL termination and routes external HTTPS traffic into the Docker network.

Infrastructure

AspectDetail
ProviderOracle Cloud Infrastructure (OCI) Always Free
ArchitectureARM (Ampere A1)
RAM24 GB
Storage200 GB block storage
OSUbuntu 22.04 LTS (ARM64)

Port Mapping

The Oracle-specific compose file (docker-compose-oracle.yml) exposes the API on a different host port than the default local development compose file. This lets Nginx Proxy Manager sit in front of both services on the host and route traffic without port conflicts.
ServiceExternal port (host)Internal port (container)
Frontend (Nginx)300080
API (FastAPI)80018000
Databasenot exposed5432
The database is never accessible from outside the Docker network in production.
ARM64 is fully supported. All images used by GeoViable — kartoza/postgis:15-3.4, public.ecr.aws/docker/library/nginx:1.25-alpine, python:3.11-slim, and the system packages that WeasyPrint and GDAL depend on — provide native linux/arm64 builds. No emulation layer is required on Ampere A1.

First Deployment

1

Clone the repository on the OCI server

git clone https://github.com/danizd/geoviable.git
cd geoviable
2

Configure production environment variables

cp .env.example .env
nano .env
Set the following values for production:
  • POSTGRES_PASSWORD — generate a strong password with openssl rand -base64 32
  • DATABASE_URL — update the password portion to match POSTGRES_PASSWORD
  • ENVIRONMENT=production
  • LOG_LEVEL=INFO
  • CORS_ORIGINS=https://your-domain.example.com
See the Environment Variables reference for the full list of settings.
3

Upload environmental data ZIPs (optional)

If you want to load data immediately after startup, upload the ZIP files to backend/data/ via scp or your preferred file transfer method before proceeding. You can also load data after the containers are running.
scp red_natura_2000.zip user@your-oci-host:~/geoviable/backend/data/
# repeat for each ZIP
4

Start all services

Use the Oracle-specific compose file for all production operations:
docker compose -f docker-compose-oracle.yml up -d --build
Docker will build the backend image and start all three containers. The database container initialises PostGIS and runs the backend/initdb/ SQL scripts on first boot.
5

Load environmental data

docker compose -f docker-compose-oracle.yml exec geoviable-api python -m scripts.load_initial_data
See the Loading Data guide for full details, including how to load a single layer or verify record counts.
6

Note: no npm required on the server

The frontend/build/ directory is committed to the repository, so the compiled React application is already present after git clone. There is no need to install Node.js or run npm run build on the production server.

Updating Production

To deploy a new version of the application:
git pull origin master
docker compose -f docker-compose-oracle.yml up -d --build
Docker rebuilds the backend image if the Dockerfile or requirements.txt changed, otherwise it reuses the cached image. The pgdata volume persists across restarts — data is never lost by a regular update.

Frontend-Only Update

When only the React frontend has changed, you can avoid a full image rebuild by compiling locally and restarting only Nginx:
# Locally — build and commit the compiled assets:
cd frontend && npm run build && cd ..
git add frontend/build/
git commit -m "build: update frontend"
git push

# On the production server:
git pull origin master
docker compose -f docker-compose-oracle.yml restart geoviable-web
Nginx will pick up the new static files immediately because frontend/build/ is mounted as a read-only volume.

Full Reset

docker compose down -v permanently deletes the pgdata Docker volume and all data stored in the database. Only run this if you need a completely clean environment. You will need to reload all environmental layers afterwards.
docker compose -f docker-compose-oracle.yml down -v
docker compose -f docker-compose-oracle.yml up -d --build
# Reload all environmental data after the reset:
docker compose -f docker-compose-oracle.yml exec geoviable-api python -m scripts.load_initial_data

Database Backups

GeoViable’s backup strategy uses pg_dump to create compressed SQL dumps of the database. The environmental layer data can always be reloaded from the original ZIPs, but any user-generated content or layer_update_log entries are only persisted in the database.
AspectDetail
Toolpg_dump
FrequencyDaily at 02:00 UTC (host cron job)
Retention7 days
Storagebackups/ directory on the OCI host

Create a backup manually

docker compose exec geoviable-db pg_dump -U geoviable geoviable | gzip > backups/backup_$(date +%Y%m%d).sql.gz

Restore from a backup

gunzip -c backups/backup_20260401.sql.gz | docker compose exec -T geoviable-db psql -U geoviable -d geoviable

Automate daily backups (host cron)

Add the following entry to the host crontab with crontab -e:
0 2 * * * cd /home/ubuntu/geoviable && docker compose exec -T geoviable-db pg_dump -U geoviable geoviable | gzip > backups/backup_$(date +\%Y\%m\%d).sql.gz

Monitoring

Health endpoints

Check the overall service status at any time:
# API health (responds {"status": "ok"} when the backend is up)
curl http://localhost:8001/api/v1/health

# Layer data freshness and last update timestamps
curl http://localhost:8001/api/v1/layers/status

Container logs

# Follow logs from all services
docker compose -f docker-compose-oracle.yml logs -f

# Follow API logs only
docker compose -f docker-compose-oracle.yml logs -f geoviable-api

Monthly layer update log

The automated update_layers.py cron job runs on the first day of each month at 03:00 UTC and writes its output to a log file inside the container:
docker compose -f docker-compose-oracle.yml exec geoviable-api tail -f /var/log/geoviable_update.log
Use Nginx Proxy Manager for SSL termination in front of GeoViable. Point a proxy host at localhost:3000 for the frontend and localhost:8001 for the API, attach a Let’s Encrypt certificate, and enable “Force SSL”. This keeps certificate renewal automatic and decouples TLS configuration from the GeoViable Docker stack entirely.

Build docs developers (and LLMs) love