From 1bc3a3d3ff6f43e812df5876247cc4385c31f22f Mon Sep 17 00:00:00 2001 From: AlexCherrypi <19236891+AlexCherrypi@users.noreply.github.com> Date: Sat, 24 Jan 2026 07:55:49 +0100 Subject: [PATCH 01/22] Add FTP deployment workflow --- .github/workflows/deploy.yml | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 .github/workflows/deploy.yml diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000..3ffc398 --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,32 @@ +name: Deploy to FTP +concurrency: + group: ${{ github.workflow }} + cancel-in-progress: true +run-name: ${{ github.actor }} triggered deployment to FTP + +on: + push: + branches: + - main + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Upload to FTP + uses: SamKirkland/FTP-Deploy-Action@v4.3.5 + with: + server: ${{ secrets.FTP_SERVER }} + username: ${{ secrets.FTP_USERNAME }} + password: ${{ secrets.FTP_PASSWORD }} + local-dir: ./ + server-dir: ${{ secrets.FTP_REMOTE_DIR }}/ + exclude: | + **/.git* + **/.git*/** + **/example/** + **/README.md + **/LICENSE + **/composer.json From 4536aed658b21a71f01e2e6eeb0d14273f348a69 Mon Sep 17 00:00:00 2001 From: AlexCherrypi <19236891+AlexCherrypi@users.noreply.github.com> Date: Sat, 24 Jan 2026 08:05:26 +0100 Subject: [PATCH 02/22] Simplify FTP remote dir - user already in target folder --- .github/workflows/deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 3ffc398..124d9c0 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -22,7 +22,7 @@ jobs: username: ${{ secrets.FTP_USERNAME }} password: ${{ secrets.FTP_PASSWORD }} local-dir: ./ - server-dir: ${{ secrets.FTP_REMOTE_DIR }}/ + server-dir: ./ exclude: | **/.git* **/.git*/** From b7654e7a43f2f81895b6a3a01f6fa0ea569b3b19 Mon Sep 17 00:00:00 2001 From: AlexCherrypi <19236891+AlexCherrypi@users.noreply.github.com> Date: Sat, 24 Jan 2026 08:06:44 +0100 Subject: [PATCH 03/22] Trigger FTP deployment From 7deee54fef3a21dec30a052ee5db9aecb30eab9a Mon Sep 17 00:00:00 2001 From: AlexCherrypi <19236891+AlexCherrypi@users.noreply.github.com> Date: Sat, 24 Jan 2026 08:10:33 +0100 Subject: [PATCH 04/22] Fix: trigger on master branch instead of main --- .github/workflows/deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 124d9c0..5db87b4 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -7,7 +7,7 @@ run-name: ${{ github.actor }} triggered deployment to FTP on: push: branches: - - main + - master jobs: deploy: From 6ea88c1897345bce6d8ae8a710f18699d62f6d40 Mon Sep 17 00:00:00 2001 From: AlexCherrypi <19236891+AlexCherrypi@users.noreply.github.com> Date: Sat, 24 Jan 2026 08:11:44 +0100 Subject: [PATCH 05/22] Enable FTPS (TLS) for FTP connection --- .github/workflows/deploy.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 5db87b4..86ec525 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -21,6 +21,7 @@ jobs: server: ${{ secrets.FTP_SERVER }} username: ${{ secrets.FTP_USERNAME }} password: ${{ secrets.FTP_PASSWORD }} + protocol: ftps local-dir: ./ server-dir: ./ exclude: | From d655a9044ccd449e433b671ecddb3044abe1a82f Mon Sep 17 00:00:00 2001 From: AlexCherrypi <19236891+AlexCherrypi@users.noreply.github.com> Date: Sat, 24 Jan 2026 08:16:11 +0100 Subject: [PATCH 06/22] Add .htaccess, index.php and update .gitignore --- public/.gitignore | 3 ++- public/.htaccess | 13 +++++++++++++ public/index.php | 16 ++++++++++++++++ 3 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 public/.htaccess create mode 100644 public/index.php diff --git a/public/.gitignore b/public/.gitignore index a5baada..a1ca214 100644 --- a/public/.gitignore +++ b/public/.gitignore @@ -1,3 +1,4 @@ * !.gitignore - +!.htaccess +!index.php diff --git a/public/.htaccess b/public/.htaccess new file mode 100644 index 0000000..3ca0618 --- /dev/null +++ b/public/.htaccess @@ -0,0 +1,13 @@ +RewriteEngine on + +# Block requests without valid referer +RewriteCond %{HTTP_REFERER} !^$ +RewriteCond %{HTTP_REFERER} !^https?://(.*\.)?lammers-krueger\.de [NC] +RewriteCond %{HTTP_REFERER} !^https?://localhost [NC] +RewriteCond %{HTTP_REFERER} !^https?://127\.0\.0\.1 [NC] +RewriteRule \.(png|jpg|jpeg|webp)$ - [F,L] + +# Route all requests to index.php +RewriteCond %{REQUEST_FILENAME} !-d +RewriteCond %{REQUEST_FILENAME} !-f +RewriteRule . /index.php [L] diff --git a/public/index.php b/public/index.php new file mode 100644 index 0000000..7fdf666 --- /dev/null +++ b/public/index.php @@ -0,0 +1,16 @@ +setMirrors(array("http://a.tile.openstreetmap.org", "http://b.tile.openstreetmap.org", "http://c.tile.openstreetmap.org")); + +//$style_osm->setEffectModulate(100, 50, 100); +//$style_osm->setEffectSepia(90); +//$style_osm->setEffectNegate(); + +$tileproxy = new \com\augmentedlogic\osmtileproxy\TileProxy(); +$tileproxy->addStyle($style_osm); +$tileproxy->setLogLevel(\com\augmentedlogic\osmtileproxy\TileProxy::LOGLEVEL_OFF); +$tileproxy->handle(); From f81dcc2822cf988e5132bb5430a3d708a487f811 Mon Sep 17 00:00:00 2001 From: AlexCherrypi <19236891+AlexCherrypi@users.noreply.github.com> Date: Sat, 24 Jan 2026 08:22:22 +0100 Subject: [PATCH 07/22] Remove referer restriction for testing --- public/.htaccess | 7 ------- 1 file changed, 7 deletions(-) diff --git a/public/.htaccess b/public/.htaccess index 3ca0618..2d8d58e 100644 --- a/public/.htaccess +++ b/public/.htaccess @@ -1,12 +1,5 @@ RewriteEngine on -# Block requests without valid referer -RewriteCond %{HTTP_REFERER} !^$ -RewriteCond %{HTTP_REFERER} !^https?://(.*\.)?lammers-krueger\.de [NC] -RewriteCond %{HTTP_REFERER} !^https?://localhost [NC] -RewriteCond %{HTTP_REFERER} !^https?://127\.0\.0\.1 [NC] -RewriteRule \.(png|jpg|jpeg|webp)$ - [F,L] - # Route all requests to index.php RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-f From 8727d3fba08e13ff979dd2c3550d1306eed10cc3 Mon Sep 17 00:00:00 2001 From: AlexCherrypi <19236891+AlexCherrypi@users.noreply.github.com> Date: Sat, 24 Jan 2026 08:27:22 +0100 Subject: [PATCH 08/22] Add debug script --- public/.gitignore | 1 + public/debug.php | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 public/debug.php diff --git a/public/.gitignore b/public/.gitignore index a1ca214..d37ca1a 100644 --- a/public/.gitignore +++ b/public/.gitignore @@ -2,3 +2,4 @@ !.gitignore !.htaccess !index.php +!debug.php diff --git a/public/debug.php b/public/debug.php new file mode 100644 index 0000000..70a91f2 --- /dev/null +++ b/public/debug.php @@ -0,0 +1,37 @@ + Date: Sat, 24 Jan 2026 08:28:15 +0100 Subject: [PATCH 09/22] Add request parsing debug --- public/debug.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/public/debug.php b/public/debug.php index 70a91f2..0290cc3 100644 --- a/public/debug.php +++ b/public/debug.php @@ -21,6 +21,14 @@ echo "Log dir exists: " . (is_dir($logDir) ? 'YES' : 'NO') . "\n"; echo "Log dir writable: " . (is_writable($logDir) ? 'YES' : 'NO') . "\n\n"; +echo "=== Request Info ===\n"; +echo "REQUEST_URI: " . $_SERVER['REQUEST_URI'] . "\n"; +$path_only = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH); +echo "Path only: " . $path_only . "\n"; +$parts = explode("/", $path_only); +array_shift($parts); +echo "Parts: " . print_r($parts, true) . "\n"; + echo "=== Test URL fetch ===\n"; $testUrl = "http://a.tile.openstreetmap.org/0/0/0.png"; $ch = curl_init($testUrl); From 8b8e7fd3416deaea11a9b7bf48993b6fce68d13e Mon Sep 17 00:00:00 2001 From: AlexCherrypi <19236891+AlexCherrypi@users.noreply.github.com> Date: Sat, 24 Jan 2026 08:28:34 +0100 Subject: [PATCH 10/22] Enable debug logging and error reporting --- public/index.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/public/index.php b/public/index.php index 7fdf666..dce022d 100644 --- a/public/index.php +++ b/public/index.php @@ -1,4 +1,7 @@ addStyle($style_osm); -$tileproxy->setLogLevel(\com\augmentedlogic\osmtileproxy\TileProxy::LOGLEVEL_OFF); +$tileproxy->setLogLevel(\com\augmentedlogic\osmtileproxy\TileProxy::LOGLEVEL_DEBUG); $tileproxy->handle(); From ab57afd29666eebaf877b82d1e69a8a8b46dff0b Mon Sep 17 00:00:00 2001 From: AlexCherrypi <19236891+AlexCherrypi@users.noreply.github.com> Date: Sat, 24 Jan 2026 08:29:27 +0100 Subject: [PATCH 11/22] Fix curl error checking and double slash in cache path --- src/TileProxy.php | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/TileProxy.php b/src/TileProxy.php index 0455540..7962e8d 100644 --- a/src/TileProxy.php +++ b/src/TileProxy.php @@ -37,8 +37,8 @@ class TileProxy private $user_agent = "Mozilla/5.0 (X11; Linux i586; rv:31.0) Gecko/20100101 Firefox/74.0"; - private $option_storage_dir = "../cache/"; - private $option_log_dir = "../log/"; + private $option_storage_dir = "../cache"; + private $option_log_dir = "../log"; private $option_loglevel = 0; private $option_ttl = 86400; // default browser expiry time private $option_refresh = null; // refresh after n days, null = ignored @@ -140,14 +140,22 @@ private function fetchTile(MapStyle $current_style, string $filepath, string $ta curl_setopt($ch, CURLOPT_FILE, $fp); curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_USERAGENT, $this->user_agent); + curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); curl_exec($ch); + $curlError = curl_errno($ch); + $curlErrorMsg = curl_error($ch); + $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); fflush($fp); fclose($fp); // check if image downloaded successfully - if (curl_errno($ch) !== 0) { - throw new RuntimeException(curl_error($ch)); + if ($curlError !== 0) { + throw new RuntimeException($curlErrorMsg); + } elseif ($httpCode !== 200) { + $content = @file_get_contents($save_to); + @unlink($save_to); + throw new RuntimeException("HTTP $httpCode: $content"); } elseif ($this->is_valid_image($save_to, $current_style)) { if($current_style->getImageChecktype() !== MapStyle::IMAGE_FORMAT_PNG) { From 54656d309667287c2bdb2cacb5508b2c079c09fa Mon Sep 17 00:00:00 2001 From: AlexCherrypi <19236891+AlexCherrypi@users.noreply.github.com> Date: Sat, 24 Jan 2026 08:32:17 +0100 Subject: [PATCH 12/22] Clear server on deploy + scheduled cache cleanup every 5 days --- .github/workflows/deploy.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 86ec525..acd8115 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -8,6 +8,9 @@ on: push: branches: - master + schedule: + # Cache cleanup: every 5 days at 3am UTC + - cron: '0 3 */5 * *' jobs: deploy: @@ -24,6 +27,7 @@ jobs: protocol: ftps local-dir: ./ server-dir: ./ + dangerous-clean-slate: true exclude: | **/.git* **/.git*/** From 5aefd3ffa4a2119d757dc01926fc75c91c0b03a2 Mon Sep 17 00:00:00 2001 From: AlexCherrypi <19236891+AlexCherrypi@users.noreply.github.com> Date: Sat, 24 Jan 2026 08:33:22 +0100 Subject: [PATCH 13/22] Clean server on every deploy --- .github/workflows/deploy.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index acd8115..ab3c9da 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -8,9 +8,6 @@ on: push: branches: - master - schedule: - # Cache cleanup: every 5 days at 3am UTC - - cron: '0 3 */5 * *' jobs: deploy: From 3688c23480518384cac0a84fd4c6837d20d8011a Mon Sep 17 00:00:00 2001 From: AlexCherrypi <19236891+AlexCherrypi@users.noreply.github.com> Date: Sat, 24 Jan 2026 08:34:19 +0100 Subject: [PATCH 14/22] Add referer restriction (block all invalid requests) --- public/.htaccess | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/public/.htaccess b/public/.htaccess index 2d8d58e..e41ba50 100644 --- a/public/.htaccess +++ b/public/.htaccess @@ -1,5 +1,12 @@ RewriteEngine on +# Block requests without valid referer (allow empty referer for direct API calls) +RewriteCond %{HTTP_REFERER} !^$ +RewriteCond %{HTTP_REFERER} !^https?://(.*\.)?lammers-krueger\.de [NC] +RewriteCond %{HTTP_REFERER} !^https?://localhost [NC] +RewriteCond %{HTTP_REFERER} !^https?://127\.0\.0\.1 [NC] +RewriteRule .* - [F,L] + # Route all requests to index.php RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-f From b871f8665b68dca3fbf86d89d2f058c71c808a2a Mon Sep 17 00:00:00 2001 From: AlexCherrypi <19236891+AlexCherrypi@users.noreply.github.com> Date: Sat, 24 Jan 2026 08:37:27 +0100 Subject: [PATCH 15/22] Enable tile refresh after 5 days --- public/index.php | 1 + 1 file changed, 1 insertion(+) diff --git a/public/index.php b/public/index.php index dce022d..de90864 100644 --- a/public/index.php +++ b/public/index.php @@ -15,5 +15,6 @@ $tileproxy = new \com\augmentedlogic\osmtileproxy\TileProxy(); $tileproxy->addStyle($style_osm); +$tileproxy->setRefresh(5); $tileproxy->setLogLevel(\com\augmentedlogic\osmtileproxy\TileProxy::LOGLEVEL_DEBUG); $tileproxy->handle(); From 08fb9cd5b8ff312cffbf4b7293f903b6cbf9e999 Mon Sep 17 00:00:00 2001 From: AlexCherrypi <19236891+AlexCherrypi@users.noreply.github.com> Date: Sat, 24 Jan 2026 08:42:14 +0100 Subject: [PATCH 16/22] Add cache cleanup script for cron --- scripts/cleanup-cache.sh | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 scripts/cleanup-cache.sh diff --git a/scripts/cleanup-cache.sh b/scripts/cleanup-cache.sh new file mode 100644 index 0000000..d17f652 --- /dev/null +++ b/scripts/cleanup-cache.sh @@ -0,0 +1,27 @@ +#!/bin/bash +# OSM Tile Cache Cleanup Script +# Run via cron, e.g.: 0 3 */5 * * /path/to/cleanup-cache.sh + +CACHE_DIR="/usr/www/users/lammerki/mapproxy/cache" +MAX_AGE_DAYS=13 +MAX_SIZE_BYTES=1073741824 # 1GB per style folder + +# Delete files older than MAX_AGE_DAYS +find "$CACHE_DIR" -type f -mtime +$MAX_AGE_DAYS -delete + +# Shrink folders over 1GB by deleting oldest files +for dir in "$CACHE_DIR"/*/; do + [ -d "$dir" ] || continue + while true; do + size=$(du -sb "$dir" 2>/dev/null | cut -f1) + [ -z "$size" ] && break + [ "$size" -le $MAX_SIZE_BYTES ] && break + + oldest=$(find "$dir" -type f -printf '%T+ %p\n' 2>/dev/null | sort | head -1 | cut -d' ' -f2-) + [ -z "$oldest" ] && break + rm -f "$oldest" + done +done + +# Remove empty directories +find "$CACHE_DIR" -type d -empty -delete From 469a24650c72c6dab0e97aca0916a04bece164ec Mon Sep 17 00:00:00 2001 From: AlexCherrypi <19236891+AlexCherrypi@users.noreply.github.com> Date: Sat, 24 Jan 2026 08:46:45 +0100 Subject: [PATCH 17/22] Remove cleanup script - lives outside deploy dir --- scripts/cleanup-cache.sh | 27 --------------------------- 1 file changed, 27 deletions(-) delete mode 100644 scripts/cleanup-cache.sh diff --git a/scripts/cleanup-cache.sh b/scripts/cleanup-cache.sh deleted file mode 100644 index d17f652..0000000 --- a/scripts/cleanup-cache.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/bash -# OSM Tile Cache Cleanup Script -# Run via cron, e.g.: 0 3 */5 * * /path/to/cleanup-cache.sh - -CACHE_DIR="/usr/www/users/lammerki/mapproxy/cache" -MAX_AGE_DAYS=13 -MAX_SIZE_BYTES=1073741824 # 1GB per style folder - -# Delete files older than MAX_AGE_DAYS -find "$CACHE_DIR" -type f -mtime +$MAX_AGE_DAYS -delete - -# Shrink folders over 1GB by deleting oldest files -for dir in "$CACHE_DIR"/*/; do - [ -d "$dir" ] || continue - while true; do - size=$(du -sb "$dir" 2>/dev/null | cut -f1) - [ -z "$size" ] && break - [ "$size" -le $MAX_SIZE_BYTES ] && break - - oldest=$(find "$dir" -type f -printf '%T+ %p\n' 2>/dev/null | sort | head -1 | cut -d' ' -f2-) - [ -z "$oldest" ] && break - rm -f "$oldest" - done -done - -# Remove empty directories -find "$CACHE_DIR" -type d -empty -delete From 45ae9c3ddb293e65a97bf43a60d7bc9db95bf231 Mon Sep 17 00:00:00 2001 From: AlexCherrypi <19236891+AlexCherrypi@users.noreply.github.com> Date: Sat, 24 Jan 2026 08:51:33 +0100 Subject: [PATCH 18/22] Add generic cache cleanup script template --- scripts/cleanup-cache.sh | 53 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 scripts/cleanup-cache.sh diff --git a/scripts/cleanup-cache.sh b/scripts/cleanup-cache.sh new file mode 100644 index 0000000..0cb8b04 --- /dev/null +++ b/scripts/cleanup-cache.sh @@ -0,0 +1,53 @@ +#!/bin/bash +# OSM Tile Cache Cleanup Script +# +# Usage: ./cleanup-cache.sh [CACHE_DIR] [MAX_AGE_DAYS] [MAX_SIZE_BYTES] +# +# Example cron entry (every 5 days at 3am): +# 0 3 */5 * * /path/to/cleanup-cache.sh /path/to/cache 13 1073741824 + +# Configuration - override via command line arguments +CACHE_DIR="${1:-./cache}" +MAX_AGE_DAYS="${2:-13}" +MAX_SIZE_BYTES="${3:-1073741824}" # 1GB default + +echo "Cache cleanup started: $(date)" +echo "Cache dir: $CACHE_DIR" +echo "Max age: $MAX_AGE_DAYS days" +echo "Max size per folder: $((MAX_SIZE_BYTES / 1024 / 1024))MB" + +# Validate cache directory exists +if [ ! -d "$CACHE_DIR" ]; then + echo "Error: Cache directory does not exist: $CACHE_DIR" + exit 1 +fi + +# Delete files older than MAX_AGE_DAYS +echo "Deleting files older than $MAX_AGE_DAYS days..." +deleted_old=$(find "$CACHE_DIR" -type f -mtime +$MAX_AGE_DAYS -delete -print | wc -l) +echo "Deleted $deleted_old old files" + +# Shrink folders over max size by deleting oldest files +echo "Checking folder sizes..." +for dir in "$CACHE_DIR"/*/; do + [ -d "$dir" ] || continue + deleted_size=0 + while true; do + size=$(du -sb "$dir" 2>/dev/null | cut -f1) + [ -z "$size" ] && break + [ "$size" -le $MAX_SIZE_BYTES ] && break + + oldest=$(find "$dir" -type f -printf '%T+ %p\n' 2>/dev/null | sort | head -1 | cut -d' ' -f2-) + [ -z "$oldest" ] && break + rm -f "$oldest" + ((deleted_size++)) + done + [ $deleted_size -gt 0 ] && echo "Deleted $deleted_size files from $(basename "$dir") (over size limit)" +done + +# Remove empty directories +echo "Removing empty directories..." +deleted_dirs=$(find "$CACHE_DIR" -type d -empty -delete -print | wc -l) +echo "Deleted $deleted_dirs empty directories" + +echo "Cache cleanup completed: $(date)" From 0c671eeac7a15c5daf99fdf197728da0c9f49526 Mon Sep 17 00:00:00 2001 From: AlexCherrypi <19236891+AlexCherrypi@users.noreply.github.com> Date: Sat, 24 Jan 2026 08:53:10 +0100 Subject: [PATCH 19/22] Make cache path a required argument --- scripts/cleanup-cache.sh | 41 ++++++++-------------------------------- 1 file changed, 8 insertions(+), 33 deletions(-) diff --git a/scripts/cleanup-cache.sh b/scripts/cleanup-cache.sh index 0cb8b04..6e9b4d1 100644 --- a/scripts/cleanup-cache.sh +++ b/scripts/cleanup-cache.sh @@ -1,37 +1,18 @@ #!/bin/bash # OSM Tile Cache Cleanup Script -# -# Usage: ./cleanup-cache.sh [CACHE_DIR] [MAX_AGE_DAYS] [MAX_SIZE_BYTES] -# -# Example cron entry (every 5 days at 3am): -# 0 3 */5 * * /path/to/cleanup-cache.sh /path/to/cache 13 1073741824 +# Usage: ./cleanup-cache.sh [CACHE_DIR] +# Cron: 0 3 */5 * * /path/to/cleanup-cache.sh /path/to/cache -# Configuration - override via command line arguments -CACHE_DIR="${1:-./cache}" -MAX_AGE_DAYS="${2:-13}" -MAX_SIZE_BYTES="${3:-1073741824}" # 1GB default - -echo "Cache cleanup started: $(date)" -echo "Cache dir: $CACHE_DIR" -echo "Max age: $MAX_AGE_DAYS days" -echo "Max size per folder: $((MAX_SIZE_BYTES / 1024 / 1024))MB" - -# Validate cache directory exists -if [ ! -d "$CACHE_DIR" ]; then - echo "Error: Cache directory does not exist: $CACHE_DIR" - exit 1 -fi +CACHE_DIR="${1:?Usage: $0 CACHE_DIR}" +MAX_AGE_DAYS=13 +MAX_SIZE_BYTES=1073741824 # 1GB per style folder # Delete files older than MAX_AGE_DAYS -echo "Deleting files older than $MAX_AGE_DAYS days..." -deleted_old=$(find "$CACHE_DIR" -type f -mtime +$MAX_AGE_DAYS -delete -print | wc -l) -echo "Deleted $deleted_old old files" +find "$CACHE_DIR" -type f -mtime +$MAX_AGE_DAYS -delete -# Shrink folders over max size by deleting oldest files -echo "Checking folder sizes..." +# Shrink folders over 1GB by deleting oldest files for dir in "$CACHE_DIR"/*/; do [ -d "$dir" ] || continue - deleted_size=0 while true; do size=$(du -sb "$dir" 2>/dev/null | cut -f1) [ -z "$size" ] && break @@ -40,14 +21,8 @@ for dir in "$CACHE_DIR"/*/; do oldest=$(find "$dir" -type f -printf '%T+ %p\n' 2>/dev/null | sort | head -1 | cut -d' ' -f2-) [ -z "$oldest" ] && break rm -f "$oldest" - ((deleted_size++)) done - [ $deleted_size -gt 0 ] && echo "Deleted $deleted_size files from $(basename "$dir") (over size limit)" done # Remove empty directories -echo "Removing empty directories..." -deleted_dirs=$(find "$CACHE_DIR" -type d -empty -delete -print | wc -l) -echo "Deleted $deleted_dirs empty directories" - -echo "Cache cleanup completed: $(date)" +find "$CACHE_DIR" -type d -empty -delete \ No newline at end of file From 96b8fd6b828f6a0f48be1272f3f4e05caef1c958 Mon Sep 17 00:00:00 2001 From: AlexCherrypi <19236891+AlexCherrypi@users.noreply.github.com> Date: Sat, 24 Jan 2026 08:55:06 +0100 Subject: [PATCH 20/22] Remove debug mode and debug.php --- public/.gitignore | 1 - public/debug.php | 45 --------------------------------------------- public/index.php | 5 +---- 3 files changed, 1 insertion(+), 50 deletions(-) delete mode 100644 public/debug.php diff --git a/public/.gitignore b/public/.gitignore index d37ca1a..a1ca214 100644 --- a/public/.gitignore +++ b/public/.gitignore @@ -2,4 +2,3 @@ !.gitignore !.htaccess !index.php -!debug.php diff --git a/public/debug.php b/public/debug.php deleted file mode 100644 index 0290cc3..0000000 --- a/public/debug.php +++ /dev/null @@ -1,45 +0,0 @@ -addStyle($style_osm); $tileproxy->setRefresh(5); -$tileproxy->setLogLevel(\com\augmentedlogic\osmtileproxy\TileProxy::LOGLEVEL_DEBUG); +$tileproxy->setLogLevel(\com\augmentedlogic\osmtileproxy\TileProxy::LOGLEVEL_OFF); $tileproxy->handle(); From 7b4da0c2f93baaed31d1e63a8e0733d79077e381 Mon Sep 17 00:00:00 2001 From: AlexCherrypi <19236891+AlexCherrypi@users.noreply.github.com> Date: Sat, 24 Jan 2026 09:01:57 +0100 Subject: [PATCH 21/22] Fix curl error handling and add cache cleanup script --- scripts/cleanup-cache.sh | 28 ++++++++++++++++++++++++++++ src/TileProxy.php | 16 ++++++++++++---- 2 files changed, 40 insertions(+), 4 deletions(-) create mode 100644 scripts/cleanup-cache.sh diff --git a/scripts/cleanup-cache.sh b/scripts/cleanup-cache.sh new file mode 100644 index 0000000..6e9b4d1 --- /dev/null +++ b/scripts/cleanup-cache.sh @@ -0,0 +1,28 @@ +#!/bin/bash +# OSM Tile Cache Cleanup Script +# Usage: ./cleanup-cache.sh [CACHE_DIR] +# Cron: 0 3 */5 * * /path/to/cleanup-cache.sh /path/to/cache + +CACHE_DIR="${1:?Usage: $0 CACHE_DIR}" +MAX_AGE_DAYS=13 +MAX_SIZE_BYTES=1073741824 # 1GB per style folder + +# Delete files older than MAX_AGE_DAYS +find "$CACHE_DIR" -type f -mtime +$MAX_AGE_DAYS -delete + +# Shrink folders over 1GB by deleting oldest files +for dir in "$CACHE_DIR"/*/; do + [ -d "$dir" ] || continue + while true; do + size=$(du -sb "$dir" 2>/dev/null | cut -f1) + [ -z "$size" ] && break + [ "$size" -le $MAX_SIZE_BYTES ] && break + + oldest=$(find "$dir" -type f -printf '%T+ %p\n' 2>/dev/null | sort | head -1 | cut -d' ' -f2-) + [ -z "$oldest" ] && break + rm -f "$oldest" + done +done + +# Remove empty directories +find "$CACHE_DIR" -type d -empty -delete \ No newline at end of file diff --git a/src/TileProxy.php b/src/TileProxy.php index 0455540..7962e8d 100644 --- a/src/TileProxy.php +++ b/src/TileProxy.php @@ -37,8 +37,8 @@ class TileProxy private $user_agent = "Mozilla/5.0 (X11; Linux i586; rv:31.0) Gecko/20100101 Firefox/74.0"; - private $option_storage_dir = "../cache/"; - private $option_log_dir = "../log/"; + private $option_storage_dir = "../cache"; + private $option_log_dir = "../log"; private $option_loglevel = 0; private $option_ttl = 86400; // default browser expiry time private $option_refresh = null; // refresh after n days, null = ignored @@ -140,14 +140,22 @@ private function fetchTile(MapStyle $current_style, string $filepath, string $ta curl_setopt($ch, CURLOPT_FILE, $fp); curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_USERAGENT, $this->user_agent); + curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); curl_exec($ch); + $curlError = curl_errno($ch); + $curlErrorMsg = curl_error($ch); + $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); fflush($fp); fclose($fp); // check if image downloaded successfully - if (curl_errno($ch) !== 0) { - throw new RuntimeException(curl_error($ch)); + if ($curlError !== 0) { + throw new RuntimeException($curlErrorMsg); + } elseif ($httpCode !== 200) { + $content = @file_get_contents($save_to); + @unlink($save_to); + throw new RuntimeException("HTTP $httpCode: $content"); } elseif ($this->is_valid_image($save_to, $current_style)) { if($current_style->getImageChecktype() !== MapStyle::IMAGE_FORMAT_PNG) { From 75c2648cc16f3e2570c0f906570587c7f17abfee Mon Sep 17 00:00:00 2001 From: AlexCherrypi <19236891+AlexCherrypi@users.noreply.github.com> Date: Fri, 1 May 2026 00:57:27 +0200 Subject: [PATCH 22/22] Forward Referer header to upstream tile servers OSM blocks tile requests without a Referer per its usage policy. The proxy now passes the incoming HTTP_REFERER through on the outgoing curl request, with an optional fallback configurable via setOutgoingReferrer() for cases where no incoming Referer is present. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/TileProxy.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/TileProxy.php b/src/TileProxy.php index 7962e8d..b8999b6 100644 --- a/src/TileProxy.php +++ b/src/TileProxy.php @@ -44,6 +44,7 @@ class TileProxy private $option_refresh = null; // refresh after n days, null = ignored private $allow_referrer = null; + private $outgoing_referrer = null; /** * @var MapStyle[] */ @@ -91,6 +92,11 @@ public function setReferrer(?string $referrer = null): void $this->allow_referrer = $referrer; } + public function setOutgoingReferrer(?string $referrer = null): void + { + $this->outgoing_referrer = $referrer; + } + public function setLogLevel(int $loglevel): void { $this->option_loglevel = $loglevel; @@ -141,6 +147,10 @@ private function fetchTile(MapStyle $current_style, string $filepath, string $ta curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_USERAGENT, $this->user_agent); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); + $referer = !empty($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : $this->outgoing_referrer; + if (!empty($referer)) { + curl_setopt($ch, CURLOPT_REFERER, $referer); + } curl_exec($ch); $curlError = curl_errno($ch); $curlErrorMsg = curl_error($ch);