{
  "$type": "site.standard.document",
  "bskyPostRef": {
    "cid": "bafyreieefho67lyoofjprnv7hf3ww5sjwtkkqbo6br3grnpb35bjsinqdq",
    "uri": "at://did:plc:4tuge3k3comfj4nfvqnwkemn/app.bsky.feed.post/3mldx4u5fwse2"
  },
  "path": "/user/Matija%20Nalis/diary/408636",
  "publishedAt": "2026-05-07T22:09:25.000Z",
  "site": "https://www.openstreetmap.org",
  "tags": [
    "https://docs.panoramax.fr/backend/install/tutorials/running_docker_osm_auth/",
    "https://forum.geocommuns.fr/t/deploying-a-panoramax-instance-the-pre-flight-check-list/1892",
    "https://forum.geocommuns.fr/t/storage-needs-for-a-panoramax-instance/3205",
    "http://openit.hr/",
    "https://carnet.hr/",
    "osm.org/",
    "https://docs.panoramax.fr/backend/install/tutorials/running_docker_osm_auth/#creating-our-osm-oauth2-client",
    "https://panoramax.ign.fr/api/configuration",
    "https://panoramax.osm-hr.org/",
    "https://docs.panoramax.fr/backend/install/deep_dive/excluded_areas",
    "https://api.panoramax.xyz/",
    "https://gitlab.com/panoramax/server/meta-catalog/-/work_items/56",
    "https://gitlab.com/ravenfeld/baba/-/merge_requests/390",
    "https://c.osm.org/t/konferencija-state-of-the-map-croatia-2026/143248/2",
    "https://c.osm.org/t/osm-fr-panoramax-server-only-for-testing-if-outside-of-france/143428/2",
    "https://docs.panoramax.fr/backend/install/cli/#set-the-role-of-an-account",
    "@exyu.geojson"
  ],
  "textContent": "So here are my experiences in installing Panoramax instance OSM-HR. I’ve made this from notes taken at a time, so hopefully I did not miss too much. Let me know if I did.\n\nThere are several ways to install, and I’ve decided to go with docker compose, and with regular OSM Oauth2 login.\n\nWe bumped into few issues during the deployment, but we reported them at appropriate repos, and they were fixed so nobody should be bothered by them anymore. Please do the same if you bump into some of your own!\n\nSo mostly I followed official instructions here: https://docs.panoramax.fr/backend/install/tutorials/running_docker_osm_auth/\n\nwith some preparation first as outlined in: https://forum.geocommuns.fr/t/deploying-a-panoramax-instance-the-pre-flight-check-list/1892\n\nand info about storage needs: https://forum.geocommuns.fr/t/storage-needs-for-a-panoramax-instance/3205\n\n## Hardware\n\nFirst actual hard step was getting the appropriate hardware and place to host it; see that pre-flight check list for other things like checking the law etc.\n\nhttp://openit.hr/ kindly donated the hardware, and https://carnet.hr/ the place and Internet to host it. Much thanks to them!\n\nWe got quite a beast: 4U Super-Micro cse-847 server with 2 * Xeon E5-2680v2 (40 CPU threads @ 2.80GHz), 256 GB DDR3 RAM, 2x1TB SATA SSD, and 34x3TB SAS HDD (54 TB of usable HDD space after RAID6 partitioning), Nvidia Tesla P4\n\nYou can get with (much) lower specs, depending on your needs. But we have a good-hearted sponsor so yay!\n\n## Creating Oauth2 app\n\nSo firstly, I went to osm.org/, logged in, clicked on menu / _“My account”_ / _“Oauth 2 Applications”_ / _“Register new application”_ and created Oauth2 application as described on: https://docs.panoramax.fr/backend/install/tutorials/running_docker_osm_auth/#creating-our-osm-oauth2-client\n\n_“Name”_ was set to `Panoramax HR` and _“Redirect URIs”_ to `https://panoramax.osm-hr.org/api/auth/redirect`\n\nMake sure to write down _“Client ID”_ and _“Client Secret”_ , as you’ll need them later and this is only time you’ll be able to see them.\n\n## Preparing the host OS\n\nWe use Debian. Originally at a time we tried going with Debian Bookworm GNU/Linux, but that had complained about Docker Compose configs, so we upgraded to Trixie. As it is Debian Stable at this moment, that is what I’d recommend anyway nowadays.\n\nWe also decided to use multiple HW RAID6 pools, LVM and EXT4, due to familiarity and stability and experience in recovering them (hopefully this won’t jinx it). Some people go with XFS instead of EXT4, and others swear by ZFS and replace both LVM and EXT4 with it – but I’ve never got too familiar with it (due to the way back in bad old days there were licensing issues with it. Never checked if that was resolved. Ha). And we decided on Docker Compose in order to hopefully have easy upgrades and keep host OS to pure Debian “main” packages.\n\nSo, we installed prerequisite packages, created a logical volume and formatted it.\n\n\n    apt install docker.io docker-compose docker-cli curl nginx certbot python3-certbot-nginx\n\n    lvcreate --name panoramax-pics --size 40T shrikehdd\n    mkfs.ext4 -T largefile /dev/shrikehdd/panoramax-pics\n    mkdir /osm/panoramax/storage\n    echo \"/dev/shrikehdd/panoramax-pics   /osm/panoramax/storage    ext4    defaults        0       3\" >> /etc/fstab\n    mount /osm/panoramax/storage\n    mkdir /osm/panoramax/storage/pics\n    chmod 1777 /osm/panoramax/storage/pics\n\n\nNote that our Debian root directory (and thus, where docker SQL database will live) is on SSD.\n\n## Getting and configuring Panoramax\n\nWe fetch it from git and copied template config file:\n\n\n    git clone https://gitlab.com/panoramax/server/api.git panoramax-api\n    # git checkout develop # only if you like to live on the edge -- we had to at a time, as we were finding some bugs on the way\n    cd panoramax-api/docker/full-osm-auth/\n    cp -ai env.example .env\n\n\nand then we edited that `.env` to configure for our instance:\n\n\n    INSTANCE_NAME=OSM-HR\n    FLASK_SESSION_COOKIE_DOMAIN=panoramax.osm-hr.org\n    PICTURES_DIR=/osm/panoramax/storage/pics/\n    INFRA_NB_PROXIES=2\n\n\n  * we also set the long (different) passwords for `FLASK_SECRET_KEY` and `PG_PASSWORD`. You can use output of `python3 -c 'import secrets; print(secrets.token_hex())` to generate appropriately long passwords.\n  * and we set `OAUTH_CLIENT_ID` and `OAUTH_CLIENT_SECRET` to those values we’ve written down when when we created Oauth2 app in previous steps.\n\n\n\nAlso, we needed to edit `docker-compose.yml` from that `panoramax-api/docker/full-osm-auth/` directory and update `API_SUMMARY` according to docs at https://panoramax.ign.fr/api/configuration We did this:\n\n\n       API_SUMMARY: >-\n         {\n          \"color\": \"#ff0000\",\n          \"description\": {\"en\": \"OpenStreetMap Croatia\", \"hr\": \"OpenStreetMap Hrvatska\"},\n          \"logo\": \"https://wiki.openstreetmap.org/w/images/6/6d/Logo_Croatia.svg\",\n          \"email\": \"panoramax@osm-hr.org\",\n          \"name\": {\"en\": \"${INSTANCE_NAME:-A Panoramax instance}\", \"hr\": \"${INSTANCE_NAME:-Panoramax instanca}\"},\n          \"geo_coverage\": {\"en\": \"Croatia and ex-YU region\", \"hr\": \"Hrvatska i regija\"}\n         }\n\n\n## Starting up Panoramax\n\nWe went to `panoramax-api/docker/full-osm-auth/` directory and started Docker Compose with `docker compose --project-name panoramax-hr up --pull=always -d`\n\nThat should pull up everything newest and start Panoramax in background.\n\nYou should verify here if it works by calling `curl --fail http://localhost:8080/api` - it should return some JSON.\n\n## Publishing it to the world\n\nWe’ve picked nginx. Since `panoramax.osm-hr.org` was setup in DNS to point to our server, we created `/etc/nginx/sites-available/panoramax` with following content:\n\n\n      server {\n            listen 80;\n            listen [::]:80;\n\n            server_name panoramax.osm-hr.org;\n\n            # Limit the files that can be sent to 100M\n            client_max_body_size  100M;\n\n            # buffer size when receiving big files. 6M should be enough for most pictures, but feel free to tune this value depending of your needs.\n            client_body_buffer_size 6M;\n\n            client_body_timeout     120s;\n            send_timeout            60s;\n            proxy_read_timeout      120s;\n            proxy_send_timeout      120s;\n\n            location / {\n                proxy_pass http://localhost:8080;\n                proxy_set_header Host $host;\n                proxy_set_header X-Real-IP $remote_addr;\n                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n                proxy_set_header X-Forwarded-Host $host;\n                proxy_set_header X-Forwarded-Proto $scheme;\n            }\n      }\n\n\nAnd then enabled it and started it:\n\n\n    ln -s /etc/nginx/sites-available/panoramax /etc/nginx/sites-enabled/\n    service nginx reload\n\n\n(note we don’t use systemd as I deem it a horrible idea; but service(8) on Debian should run regardless if you’re using SysVinit or Systemd)\n\nThen we fetch free Let’s Encrypt TLS certificates by running `certbot --nginx` and choosing out `panoramax.osm-hr.org` server from the list.\n\nThat makes people able to open https://panoramax.osm-hr.org/ and login and look and upload there!\n\n## Geo-limiting the uploads\n\nWhile the hardware we got was very powerful, we knew it wasn’t nowhere near infinite, so we couldn’t host the whole world. And cameras get better (and more Mpx) with time, and disk usage only rises.\n\nStill, it felt a shame to limit it only to Croatia (where the server and sponsors are from), so we decided to allow all countries from ex-Yugoslavia to use it. (not only we have great mapper friends there, but laws and language are similar, so there is also that).\n\nTo restrict what areas are allowed, we first had to get `.geojson` of the area (see https://docs.panoramax.fr/backend/install/deep_dive/excluded_areas for the info) and save it as `exyu.geojson`\n\nThen we used `docker compose -p panoramax-hr exec api /home/geovisio/.local/bin/panoramax_backend default-account-tokens get` to get a Bearer token (looong string of letters and numbers and few dots)\n\nAnd then we uploaded that config:\n\n\n      curl -X PUT \"https://panoramax.osm-hr.org/api/configuration/excluded_areas?invert=true\"\\\n           -H \"Authorization: Bearer xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.the.rest.ofthe.bearer.token.xxxxxxxx\" \\\n           -H \"Content-Type: application/geo+json\"     --data-binary \"@exyu.geojson\"\n\n\n\n(of course you replace bearer token with that string you got earlier)\n\n## Testing\n\nThen there was testing. Obviously, easiest was to use our new web at https://panoramax.osm-hr.org/ to try to upload pictures from both allowed and disallowed regions, to see if geo-limiting was working.\n\nThen we tried some sequences uploading from CLI (`sudo apt install pipx; pipx install panormax_cli`), using the mobile apps (Vespucci custom server) etc.\n\nWe first had test instance on different hardware that we nuked later and setup production, but that is not needed. (If you do something similar, make sure to nuke your panoramax-cli config cache, or it will behave strangely).\n\n## Announcing to the world\n\nWell, when you’re happy that everything is working great, you want to make your instance usable by others too!\n\n  * Firstly you need to make it a part of federation so it will be visible in meta-catalog on https://api.panoramax.xyz/ You just need to open a simple issue like this: https://gitlab.com/panoramax/server/meta-catalog/-/work_items/56\n\n  * While web and panoramax_cli will work automatically for uploads by just specifying the new instance, and Vespucci will pick instance from meta-catalog above automatically; we also quite like Baba mobile app for uploads - but they have a hard-coded list of servers. Opening issue might’ve been enough, but we’ve created a full PR to make it easier and quicker for Baba developer: https://gitlab.com/ravenfeld/baba/-/merge_requests/390\n\n  * and of course publicize - on OSM blog, on Fediverse, on SotM-HR 2026 (see https://c.osm.org/t/konferencija-state-of-the-map-croatia-2026/143248/2 ), etc.\n\n\n\n\n## Appendix A: managing the Docker Compose\n\nI’m not much of a docker guy, but here are some commands which seem to work for me and might come handy to you:\n\n\n    # startup in the future with fetching new versions if needed:\n    docker compose -p panoramax-hr up --pull=always -d\n\n\n\n    # shutdown with:\n    docker compose -p panoramax-hr down\n\n\n\n    # check logs:\n    docker compose -p panoramax-hr logs -f --tail 1000\n\n\n\n    # process list:\n    docker compose -p panoramax-hr ps\n\n\n\n    # DESTROY everything docker-related -- in case you mucked it up completely and want to start from scratch:\n    docker compose -p panoramax-hr down --volumes --rmi all --remove-orphans\n    docker system prune -a --volumes\n\n\n\n    # database access\n    docker compose -p panoramax-hr exec -it db psql postgres://gvs:thatlongPostgresqlPassword@db/geovisio\n\n\n\n## TODO\n\n  * try to setup our own blurring server (it was in initial plan, but there were issues with that blurring docker container, and we had deadlines to mean - SotM-HR 2026; where I presented Panoramax)\n  * backups (Database. And pictures. And hardware to store ‘em, uhhhh)\n  * move Croatian (and other ex-YU) pictures off the OSM-FR server to our OSM-HR, to help reduce their overload (see https://c.osm.org/t/osm-fr-panoramax-server-only-for-testing-if-outside-of-france/143428/2) once stable UUIDs are implemented\n  * encourage more users to setup their Panoramax instances – this can only work for whole world if there are a lot of us!\n  * admin user over the web (not just CLI Bearer - see https://docs.panoramax.fr/backend/install/cli/#set-the-role-of-an-account )\n  * figuring out how to check out blur / unblur requests and other moderation / flow checking\n  * look into few warnings / errors in the logs (and file some more issues)\n\n",
  "title": "Setting up OSM-HR Panoramax instance"
}