From ad9518ba432778f48d16da453659e339df254f5c Mon Sep 17 00:00:00 2001 From: Dennis Philipps Date: Wed, 18 Mar 2026 20:31:33 +0100 Subject: [PATCH 01/11] feat: Add GitHub Actions workflow to automate building, deploying, and initializing the demo instance, including frontend build, rsync deployment, database reset, and permission setting. --- .github/workflows/deploy-demo.yml | 82 +++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 .github/workflows/deploy-demo.yml diff --git a/.github/workflows/deploy-demo.yml b/.github/workflows/deploy-demo.yml new file mode 100644 index 0000000..5f4a199 --- /dev/null +++ b/.github/workflows/deploy-demo.yml @@ -0,0 +1,82 @@ +name: Deploy Demo Instance + +on: + push: + branches: + - main + - dev + +jobs: + deploy: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + + - name: Install Frontend Dependencies & Build + run: | + npm ci + npm run build + + - name: Deploy via rsync + uses: easingthemes/ssh-deploy@v5.0.3 + with: + SSH_PRIVATE_KEY: ${{ secrets.DEMO_SSH_KEY }} + ARGS: "-avzr --delete" + SOURCE: "/" + TARGET: "/home/philippsnesterdemo/web/nester-demo/" + REMOTE_HOST: ${{ secrets.DEMO_HOST }} + REMOTE_USER: ${{ secrets.DEMO_USERNAME }} + EXCLUDE: "/node_modules/, /.git/, /.github/, /src/, /public/, /vite.config.js, /package.json, /package-lock.json, /README.md, /eslint.config.js, /docs/, /CONTRIBUTING.md, /sync_www.command, /backend/uploads/, /backend/create_admin.php, /.DS_Store" + + - name: Redeploy Database & Set Permissions + uses: appleboy/ssh-action@v1.0.3 + with: + host: ${{ secrets.DEMO_HOST }} + username: ${{ secrets.DEMO_USERNAME }} + key: ${{ secrets.DEMO_SSH_KEY }} + script: | + cd /home/philippsnesterdemo/web/nester-demo/backend + + # Since you wanted the database redeployed on every deployment, + # we run a PHP script to clean it, apply schema, and create users. + php -r " + require 'api/db.php'; + try { + \$pdo->query('SET FOREIGN_KEY_CHECKS = 0'); + \$tables = \$pdo->query('SHOW TABLES')->fetchAll(PDO::FETCH_COLUMN); + foreach (\$tables as \$table) { + \$pdo->query('DROP TABLE IF EXISTS \`' . \$table . '\`'); + } + \$pdo->query('SET FOREIGN_KEY_CHECKS = 1'); + + \$sql = file_get_contents('schema.sql'); + // Strip statements that might cause permission errors on shared hosting + \$sql = preg_replace('/CREATE DATABASE[^;]+;/i', '', \$sql); + \$sql = preg_replace('/USE[^;]+;/i', '', \$sql); + \$pdo->exec(\$sql); + + \$adminHash = password_hash('admin123', PASSWORD_DEFAULT); + \$demoHash = password_hash('demo123', PASSWORD_DEFAULT); + + \$stmt = \$pdo->prepare('INSERT INTO users (id, username, email, password_hash, is_admin) VALUES (?, ?, ?, ?, ?)'); + \$stmt->execute([bin2hex(random_bytes(18)), 'admin', 'admin@example.com', \$adminHash, 1]); + \$stmt->execute([bin2hex(random_bytes(18)), 'demo', 'demo@example.com', \$demoHash, 0]); + + echo \"Database successfully cleaned, schema imported, and users created!\n\"; + } catch (Exception \$e) { + echo \"DB Error: \" . \$e->getMessage() . \"\n\"; + exit(1); + } + " + + # Fix permissions for the webserver (assuming the usual www-data or client user) + chown -R client1:web21 /home/philippsnesterdemo/web/nester-demo/ || true + find /home/philippsnesterdemo/web/nester-demo/ -type d -exec chmod 755 {} \; + find /home/philippsnesterdemo/web/nester-demo/ -type f -exec chmod 644 {} \; From 9cb977444abae31988fc736e72e69f49b38078b5 Mon Sep 17 00:00:00 2001 From: Dennis Philipps Date: Wed, 18 Mar 2026 20:42:27 +0100 Subject: [PATCH 02/11] fix: correct chown user and group order in deploy workflow --- .github/workflows/deploy-demo.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy-demo.yml b/.github/workflows/deploy-demo.yml index 5f4a199..053fa8c 100644 --- a/.github/workflows/deploy-demo.yml +++ b/.github/workflows/deploy-demo.yml @@ -77,6 +77,6 @@ jobs: " # Fix permissions for the webserver (assuming the usual www-data or client user) - chown -R client1:web21 /home/philippsnesterdemo/web/nester-demo/ || true + chown -R web21:client1 /home/philippsnesterdemo/web/nester-demo/ || true find /home/philippsnesterdemo/web/nester-demo/ -type d -exec chmod 755 {} \; find /home/philippsnesterdemo/web/nester-demo/ -type f -exec chmod 644 {} \; From 32db3669a335894ea4438e64e917e941ba1adad6 Mon Sep 17 00:00:00 2001 From: Dennis Philipps Date: Wed, 18 Mar 2026 20:48:30 +0100 Subject: [PATCH 03/11] ci: exclude `.env` from demo deployment and disable explicit file permission setting. --- .github/workflows/deploy-demo.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/deploy-demo.yml b/.github/workflows/deploy-demo.yml index 053fa8c..6562b51 100644 --- a/.github/workflows/deploy-demo.yml +++ b/.github/workflows/deploy-demo.yml @@ -33,7 +33,7 @@ jobs: TARGET: "/home/philippsnesterdemo/web/nester-demo/" REMOTE_HOST: ${{ secrets.DEMO_HOST }} REMOTE_USER: ${{ secrets.DEMO_USERNAME }} - EXCLUDE: "/node_modules/, /.git/, /.github/, /src/, /public/, /vite.config.js, /package.json, /package-lock.json, /README.md, /eslint.config.js, /docs/, /CONTRIBUTING.md, /sync_www.command, /backend/uploads/, /backend/create_admin.php, /.DS_Store" + EXCLUDE: "/node_modules/, /.git/, /.github/, /src/, /public/, /vite.config.js, /package.json, /package-lock.json, /README.md, /eslint.config.js, /docs/, /CONTRIBUTING.md, /sync_www.command, /backend/uploads/, /backend/create_admin.php, /.DS_Store, /.env" - name: Redeploy Database & Set Permissions uses: appleboy/ssh-action@v1.0.3 @@ -77,6 +77,6 @@ jobs: " # Fix permissions for the webserver (assuming the usual www-data or client user) - chown -R web21:client1 /home/philippsnesterdemo/web/nester-demo/ || true - find /home/philippsnesterdemo/web/nester-demo/ -type d -exec chmod 755 {} \; - find /home/philippsnesterdemo/web/nester-demo/ -type f -exec chmod 644 {} \; + # chown -R web21:client1 /home/philippsnesterdemo/web/nester-demo/ || true + # find /home/philippsnesterdemo/web/nester-demo/ -type d -exec chmod 755 {} \; + # find /home/philippsnesterdemo/web/nester-demo/ -type f -exec chmod 644 {} \; From 19b2a5385e6af4796cf08fa3d2c225da9194a215 Mon Sep 17 00:00:00 2001 From: Dennis Philipps Date: Wed, 18 Mar 2026 21:03:23 +0100 Subject: [PATCH 04/11] refactor: Enhance `$_SERVER['REQUEST_METHOD']` check and refine SQL stripping regex patterns in the deploy workflow. --- .github/workflows/deploy-demo.yml | 4 ++-- backend/api/db.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/deploy-demo.yml b/.github/workflows/deploy-demo.yml index 6562b51..7e57e74 100644 --- a/.github/workflows/deploy-demo.yml +++ b/.github/workflows/deploy-demo.yml @@ -58,8 +58,8 @@ jobs: \$sql = file_get_contents('schema.sql'); // Strip statements that might cause permission errors on shared hosting - \$sql = preg_replace('/CREATE DATABASE[^;]+;/i', '', \$sql); - \$sql = preg_replace('/USE[^;]+;/i', '', \$sql); + \$sql = preg_replace('/\bCREATE\s+DATABASE\b[^;]+;/i', '', \$sql); + \$sql = preg_replace('/\bUSE\b\s+[^;]+;/i', '', \$sql); \$pdo->exec(\$sql); \$adminHash = password_hash('admin123', PASSWORD_DEFAULT); diff --git a/backend/api/db.php b/backend/api/db.php index 03c1a52..3dea9bd 100644 --- a/backend/api/db.php +++ b/backend/api/db.php @@ -39,7 +39,7 @@ function set_cors_headers() header("Access-Control-Allow-Headers: Content-Type, Authorization"); // Handle preflight requests - if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') { + if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'OPTIONS') { exit(0); } } From 2b606c85fa34fff7100788e55117f1bd9978ee39 Mon Sep 17 00:00:00 2001 From: Dennis Philipps Date: Wed, 18 Mar 2026 21:06:30 +0100 Subject: [PATCH 05/11] fix: Re-enable foreign key checks after schema import in the deploy workflow. --- .github/workflows/deploy-demo.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/deploy-demo.yml b/.github/workflows/deploy-demo.yml index 7e57e74..8d2c1a8 100644 --- a/.github/workflows/deploy-demo.yml +++ b/.github/workflows/deploy-demo.yml @@ -54,7 +54,6 @@ jobs: foreach (\$tables as \$table) { \$pdo->query('DROP TABLE IF EXISTS \`' . \$table . '\`'); } - \$pdo->query('SET FOREIGN_KEY_CHECKS = 1'); \$sql = file_get_contents('schema.sql'); // Strip statements that might cause permission errors on shared hosting @@ -62,6 +61,8 @@ jobs: \$sql = preg_replace('/\bUSE\b\s+[^;]+;/i', '', \$sql); \$pdo->exec(\$sql); + \$pdo->query('SET FOREIGN_KEY_CHECKS = 1'); + \$adminHash = password_hash('admin123', PASSWORD_DEFAULT); \$demoHash = password_hash('demo123', PASSWORD_DEFAULT); From 33d343a0351f9276e3561bf66d67316c5e7c4479 Mon Sep 17 00:00:00 2001 From: Dennis Philipps Date: Wed, 18 Mar 2026 21:09:02 +0100 Subject: [PATCH 06/11] refactor: relocate `taubennest_logs` foreign key constraints. --- backend/schema.sql | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/backend/schema.sql b/backend/schema.sql index 7fe0614..799dd8b 100644 --- a/backend/schema.sql +++ b/backend/schema.sql @@ -48,13 +48,6 @@ ALTER TABLE `taubennest_logs` ADD KEY `nest_id` (`nest_id`), ADD KEY `user_id` (`user_id`); --- --- Constraints --- -ALTER TABLE `taubennest_logs` - ADD CONSTRAINT `taubennest_logs_ibfk_1` FOREIGN KEY (`nest_id`) REFERENCES `taubennester` (`id`) ON DELETE CASCADE, - ADD CONSTRAINT `taubennest_logs_ibfk_2` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE SET NULL; - -- -------------------------------------------------------- -- @@ -119,6 +112,10 @@ ALTER TABLE `password_resets` ALTER TABLE `user_tokens` ADD CONSTRAINT `user_tokens_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE; +ALTER TABLE `taubennest_logs` + ADD CONSTRAINT `taubennest_logs_ibfk_1` FOREIGN KEY (`nest_id`) REFERENCES `taubennester` (`id`) ON DELETE CASCADE, + ADD CONSTRAINT `taubennest_logs_ibfk_2` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE SET NULL; + -- -------------------------------------------------------- -- From cdd7e7e5b813d1c3b3d4e934eae13d68b1e9794b Mon Sep 17 00:00:00 2001 From: Dennis Philipps Date: Wed, 18 Mar 2026 21:19:12 +0100 Subject: [PATCH 07/11] fix: correctly deploy frontend build output by moving it to the root and expanding rsync exclusions. --- .github/workflows/deploy-demo.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/deploy-demo.yml b/.github/workflows/deploy-demo.yml index 8d2c1a8..7c279b8 100644 --- a/.github/workflows/deploy-demo.yml +++ b/.github/workflows/deploy-demo.yml @@ -23,6 +23,8 @@ jobs: run: | npm ci npm run build + # Move compiled frontend to root so rsync uploads it to the base path + rsync -a dist/ ./ - name: Deploy via rsync uses: easingthemes/ssh-deploy@v5.0.3 @@ -33,7 +35,7 @@ jobs: TARGET: "/home/philippsnesterdemo/web/nester-demo/" REMOTE_HOST: ${{ secrets.DEMO_HOST }} REMOTE_USER: ${{ secrets.DEMO_USERNAME }} - EXCLUDE: "/node_modules/, /.git/, /.github/, /src/, /public/, /vite.config.js, /package.json, /package-lock.json, /README.md, /eslint.config.js, /docs/, /CONTRIBUTING.md, /sync_www.command, /backend/uploads/, /backend/create_admin.php, /.DS_Store, /.env" + EXCLUDE: "/node_modules/, /.git/, /.github/, /src/, /public/, /vite.config.js, /package.json, /package-lock.json, /README.md, /eslint.config.js, /docs/, /CONTRIBUTING.md, /sync_www.command, /backend/uploads/, /backend/create_admin.php, /.DS_Store, /.env, /dist/, /INSTALLATION.md, /LICENSE, /.gitignore, /.env.example" - name: Redeploy Database & Set Permissions uses: appleboy/ssh-action@v1.0.3 From 4ec83964fe9a73450630bbd28695a22fe5bf2eca Mon Sep 17 00:00:00 2001 From: Dennis Philipps Date: Wed, 18 Mar 2026 21:25:43 +0100 Subject: [PATCH 08/11] feat: Add VITE_API_BASE_URL environment variable to the frontend build step in the deploy-demo workflow. --- .github/workflows/deploy-demo.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/deploy-demo.yml b/.github/workflows/deploy-demo.yml index 7c279b8..90c7dd3 100644 --- a/.github/workflows/deploy-demo.yml +++ b/.github/workflows/deploy-demo.yml @@ -20,6 +20,8 @@ jobs: node-version: '20' - name: Install Frontend Dependencies & Build + env: + VITE_API_BASE_URL: "https://${{ secrets.DEMO_HOST }}/backend/api" run: | npm ci npm run build From 5dca853a67162aa92e833e19315993306473dff2 Mon Sep 17 00:00:00 2001 From: Dennis Philipps Date: Wed, 18 Mar 2026 21:33:59 +0100 Subject: [PATCH 09/11] reorder code --- backend/api/db.php | 43 ++++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/backend/api/db.php b/backend/api/db.php index 3dea9bd..07c4f1a 100644 --- a/backend/api/db.php +++ b/backend/api/db.php @@ -3,6 +3,28 @@ require_once dirname(__DIR__) . '/config.php'; +// Function to handle CORS so the React app can communicate with this API +function set_cors_headers() +{ + // Allow any localhost origin (like frontend on 5173) + if (isset($_SERVER['HTTP_ORIGIN']) && strpos($_SERVER['HTTP_ORIGIN'], 'localhost') !== false) { + header("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}"); + } else { + header("Access-Control-Allow-Origin: *"); + } + header("Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS"); + header("Access-Control-Allow-Headers: Content-Type, Authorization"); + + // Handle preflight requests + if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'OPTIONS') { + exit(0); + } +} + +// Set JSON header and CORS for all API endpoints including this file +header('Content-Type: application/json'); +set_cors_headers(); + $host = get_config('DB_HOST', 'localhost'); $db = get_config('DB_NAME', 'nester_db'); $user = get_config('DB_USER', 'root'); @@ -26,25 +48,4 @@ exit; } -// Function to handle CORS so the React app (port 5173) can communicate with this API -function set_cors_headers() -{ - // Allow any localhost origin (like frontend on 5173) - if (isset($_SERVER['HTTP_ORIGIN']) && strpos($_SERVER['HTTP_ORIGIN'], 'localhost') !== false) { - header("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}"); - } else { - header("Access-Control-Allow-Origin: *"); - } - header("Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS"); - header("Access-Control-Allow-Headers: Content-Type, Authorization"); - - // Handle preflight requests - if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'OPTIONS') { - exit(0); - } -} - -// Set JSON header and CORS for all API endpoints including this file -header('Content-Type: application/json'); -set_cors_headers(); ?> \ No newline at end of file From be9a5571b72bec958679bf5d8b6bc3f8ef428cf0 Mon Sep 17 00:00:00 2001 From: Dennis Philipps Date: Wed, 18 Mar 2026 22:01:15 +0100 Subject: [PATCH 10/11] chore: hardcode VITE_API_BASE_URL and add build output verification for "tabit" in demo deployment workflow. --- .github/workflows/deploy-demo.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/deploy-demo.yml b/.github/workflows/deploy-demo.yml index 90c7dd3..a3057a5 100644 --- a/.github/workflows/deploy-demo.yml +++ b/.github/workflows/deploy-demo.yml @@ -21,10 +21,13 @@ jobs: - name: Install Frontend Dependencies & Build env: - VITE_API_BASE_URL: "https://${{ secrets.DEMO_HOST }}/backend/api" + VITE_API_BASE_URL: "https://nester-demo.philip.ps/backend/api" run: | + echo "Building with VITE_API_BASE_URL=$VITE_API_BASE_URL" npm ci npm run build + echo "Verifying compiled output does not contain tabit:" + grep -r "tabit" dist/ || echo "OK: no 'tabit' found in build output" # Move compiled frontend to root so rsync uploads it to the base path rsync -a dist/ ./ From d4f8f53836a8e813e0431062213471f2d3650fd1 Mon Sep 17 00:00:00 2001 From: Dennis Philipps Date: Wed, 18 Mar 2026 22:21:45 +0100 Subject: [PATCH 11/11] feat: Add demo section to README including live link and credentials. --- README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/README.md b/README.md index 319073a..49b1bb5 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,17 @@ NesterApp ist eine Open-Source-Webanwendung zur Erfassung und Verwaltung von Tau - **Standortverfolgung**: Automatische Benennung basierend auf OpenStreetMap-Einrichtungen oder Straßenadressen. - **PWA-fähig**: Kann auf Mobilgeräten für die Berichterstattung von unterwegs installiert werden. +## Demo + +Eine Live-Demo ist verfügbar unter: **[nester-demo.philip.ps](https://nester-demo.philip.ps)** + +> **Hinweis:** Die Demo-Datenbank wird bei jedem Deployment automatisch zurückgesetzt. + +| Konto | Benutzername | Passwort | Rolle | +|-------|-------------|----------|-------| +| Admin | `admin` | `admin123` | Administrator | +| Demo | `demo` | `demo123` | Standardbenutzer | + ## Erste Schritte Siehe [INSTALLATION.md](INSTALLATION.md) für Anweisungen zur Einrichtung der lokalen Entwicklungsumgebung und zur Bereitstellung in der Produktion.