From 7c983a9d6982def9ce46a2c4e4f64f55bb29a091 Mon Sep 17 00:00:00 2001 From: Ghassan Yusuf Date: Mon, 3 Aug 2026 15:58:10 +0300 Subject: [PATCH] Add Laravel LXC bootstrap script, README, and Claude Code project prompt --- README.md | 86 +++++++++++ bootstrap.sh | 264 ++++++++++++++++++++++++++++++++++ claude-project-prompt.md | 299 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 649 insertions(+) create mode 100644 README.md create mode 100644 bootstrap.sh create mode 100644 claude-project-prompt.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..e188458 --- /dev/null +++ b/README.md @@ -0,0 +1,86 @@ +# Laravel LXC Bootstrap + +Spin up a fully configured Laravel development container in one step: SSH, Apache/PHP/MariaDB or SQLite, Composer, a Laravel project, [code-server](https://code-server.dev), and [Claude Code](https://docs.claude.com/en/docs/claude-code) — all from a single command pasted into a fresh Proxmox LXC. + +## Quick start + +In an **empty, freshly created LXC**, logged in as root: + +```bash +curl -fsSL https://git.innovator.bh/ghassan/laravel-project/raw/branch/main/bootstrap.sh -o bootstrap.sh && bash bootstrap.sh +``` + +You'll be prompted for: + +- Laravel project name +- Git repository to clone (leave blank to scaffold a brand-new Laravel project instead) +- Database: `mysql` or `sqlite` +- MariaDB username/password/database (only if you chose `mysql`) + +When it finishes you'll have a running Laravel site, code-server, and Claude Code installed. + +## Fully unattended install + +Skip every prompt by exporting variables before running the script (useful for scripted LXC provisioning): + +```bash +APP_NAME=myapp \ +GIT_REPO="" \ +DB_TYPE=sqlite \ +INSTALL_CODE_SERVER=yes \ +INSTALL_CLAUDE_CODE=yes \ +bash bootstrap.sh +``` + +| Variable | Description | Default | +|---|---|---| +| `APP_NAME` | Project directory name under `/var/www` | `laravel-app` | +| `GIT_REPO` | Git URL to clone; blank creates a new Laravel project | *(blank)* | +| `DB_TYPE` | `mysql` or `sqlite` | `sqlite` | +| `DB_USER` | MariaDB username (`mysql` only) | `laravel_user` | +| `DB_PASS` | MariaDB password (`mysql` only) | random | +| `DB_NAME` | MariaDB database name (`mysql` only) | `laravel_db` | +| `INSTALL_CODE_SERVER` | Install code-server | `yes` | +| `INSTALL_CLAUDE_CODE` | Install Node.js + Claude Code | `yes` | +| `FIX_SSHD` | Auto-relax sshd config (TurnKey TCP forwarding / Ubuntu root login) | `yes` | + +## What the script does + +1. **Base system** — `apt update/upgrade`, installs `sudo curl git wget unzip`. +2. **SSH** — installs and enables `openssh-server`; on TurnKey Core containers enables `AllowTcpForwarding`, on other distros enables `PermitRootLogin yes` (needed for VS Code Remote-SSH / port tunneling). +3. **Laravel stack** — Apache, PHP + required extensions, MariaDB or SQLite, Composer, clones or scaffolds the Laravel project, sets permissions, configures an Apache vhost, generates `.env`, runs `key:generate` and `migrate`. +4. **code-server** — browser-based VS Code, so you can edit the app over SSH without a local editor. +5. **Claude Code** — installs Node.js LTS, then `npm install -g @anthropic-ai/claude-code`. +6. Prints a summary with the app path, DB type, container IP, and next steps. + +## After install + +- **Edit the app:** `code-server /var/www/` then open the tunneled port (8080) in your browser. +- **Use Claude Code:** `cd /var/www/ && claude` + +## Manual SSH config notes (if you skip `FIX_SSHD`) + +**TurnKey Core:** +```bash +nano /etc/ssh/sshd_config.d/turnkey.conf +# set: AllowTcpForwarding yes +``` + +**Ubuntu:** +```bash +nano /etc/ssh/sshd_config +# set: PermitRootLogin yes +``` + +## Standard Claude Code project prompt + +For a consistent architecture baseline (mobile-first React frontend, Laravel API backend, RBAC, MQTT real-time updates, SQLite↔PostgreSQL portability, security-first defaults), start every new Claude Code session in the project with [`claude-project-prompt.md`](./claude-project-prompt.md) as the system/instruction prompt. + +## Legacy scripts + +The original interactive, single-purpose scripts are still available if you don't want the full bootstrap: + +- `install-laravel.sh` — Laravel + MySQL only, interactive prompts. +- `install-laravel-ad.sh` — Laravel + MySQL/SQLite choice, interactive prompts. + +`bootstrap.sh` supersedes both and additionally installs SSH hardening, code-server, and Claude Code in one pass. diff --git a/bootstrap.sh b/bootstrap.sh new file mode 100644 index 0000000..b24cdc6 --- /dev/null +++ b/bootstrap.sh @@ -0,0 +1,264 @@ +#!/bin/bash +# Laravel LXC Bootstrap +# One-shot setup for a fresh Proxmox LXC: SSH, Laravel stack, code-server, Claude Code (npm). +# +# Usage (paste into a fresh, empty LXC as root): +# +# curl -fsSL https://git.innovator.bh/ghassan/laravel-project/raw/branch/main/bootstrap.sh -o bootstrap.sh +# bash bootstrap.sh +# +# All prompts can be skipped by exporting env vars before running, e.g.: +# +# APP_NAME=myapp GIT_REPO="" DB_TYPE=sqlite \ +# bash bootstrap.sh +# +# Supported env vars (all optional, will be prompted for if unset and a tty is available): +# APP_NAME Laravel project directory name (default: laravel-app) +# GIT_REPO Git URL to clone, blank = new project (default: "") +# DB_TYPE mysql | sqlite (default: sqlite) +# DB_USER MariaDB user (only used if DB_TYPE=mysql) +# DB_PASS MariaDB password (only used if DB_TYPE=mysql) +# DB_NAME MariaDB database name (only used if DB_TYPE=mysql) +# INSTALL_CODE_SERVER yes|no (default: yes) +# INSTALL_CLAUDE_CODE yes|no (default: yes) +# FIX_SSHD yes|no - relax sshd_config for the common LXC issue (default: yes) + +set -euo pipefail + +# --------------------------------------------------------------------------- +# Helpers +# --------------------------------------------------------------------------- + +log() { echo -e "\n\033[1;32m==> $*\033[0m"; } +warn() { echo -e "\033[1;33m[warn] $*\033[0m"; } + +# Prompt for a value only if it isn't already set via env var, and only if we +# have a real terminal to read from (works even when this script is piped +# straight into bash, by reading from /dev/tty instead of stdin). +prompt() { + local var_name="$1" prompt_text="$2" default_value="${3:-}" silent="${4:-no}" + + # A var counts as "provided" if it's set at all, even to an intentionally + # blank value (e.g. GIT_REPO="" means "scaffold a new project"). + if declare -p "$var_name" &>/dev/null; then + return + fi + + if [ ! -t 0 ]; then + if ! { [ -e /dev/tty ] && exec 0/dev/null; }; then + warn "No terminal available to prompt for $var_name, using default: '$default_value'" + printf -v "$var_name" '%s' "$default_value" + return + fi + fi + + local current_value + if [ "$silent" = "yes" ]; then + read -r -s -p "$prompt_text" current_value + echo "" + else + read -r -p "$prompt_text" current_value + fi + printf -v "$var_name" '%s' "${current_value:-$default_value}" +} + +if [ "$(id -u)" -ne 0 ]; then + echo "This script must be run as root." >&2 + exit 1 +fi + +# --------------------------------------------------------------------------- +# 0. Gather configuration +# --------------------------------------------------------------------------- + +log "Laravel LXC Bootstrap" + +prompt APP_NAME "Laravel project name (directory name) [laravel-app]: " "laravel-app" +prompt GIT_REPO "Git repository URL to clone (blank = new project): " "" +prompt DB_TYPE "Database type, mysql or sqlite [sqlite]: " "sqlite" + +if [[ "$DB_TYPE" != "mysql" && "$DB_TYPE" != "sqlite" ]]; then + warn "Unrecognized DB_TYPE '$DB_TYPE', defaulting to sqlite." + DB_TYPE="sqlite" +fi + +if [ "$DB_TYPE" = "mysql" ]; then + prompt DB_USER "MariaDB username [laravel_user]: " "laravel_user" + prompt DB_PASS "MariaDB password: " "$(openssl rand -hex 12)" "yes" + prompt DB_NAME "MariaDB database name [laravel_db]: " "laravel_db" +fi + +INSTALL_CODE_SERVER="${INSTALL_CODE_SERVER:-yes}" +INSTALL_CLAUDE_CODE="${INSTALL_CLAUDE_CODE:-yes}" +FIX_SSHD="${FIX_SSHD:-yes}" + +# --------------------------------------------------------------------------- +# 1. Base system update + tooling +# --------------------------------------------------------------------------- + +log "Updating system and installing base tools" +apt-get update && apt-get upgrade -y +apt-get install -y sudo curl git wget unzip + +# --------------------------------------------------------------------------- +# 2. SSH +# --------------------------------------------------------------------------- + +log "Installing and enabling SSH" +apt-get install -y openssh-server +systemctl enable ssh +systemctl start ssh + +if [ "$FIX_SSHD" = "yes" ]; then + if [ -f /etc/ssh/sshd_config.d/turnkey.conf ]; then + log "TurnKey Core detected: enabling AllowTcpForwarding" + sed -i 's/^AllowTcpForwarding.*/AllowTcpForwarding yes/' /etc/ssh/sshd_config.d/turnkey.conf + grep -q '^AllowTcpForwarding' /etc/ssh/sshd_config.d/turnkey.conf || echo "AllowTcpForwarding yes" >> /etc/ssh/sshd_config.d/turnkey.conf + else + log "Enabling root login over SSH in /etc/ssh/sshd_config" + if grep -q '^PermitRootLogin' /etc/ssh/sshd_config; then + sed -i 's/^PermitRootLogin.*/PermitRootLogin yes/' /etc/ssh/sshd_config + else + echo "PermitRootLogin yes" >> /etc/ssh/sshd_config + fi + fi + systemctl restart ssh +fi + +# --------------------------------------------------------------------------- +# 3. Laravel stack +# --------------------------------------------------------------------------- + +log "Installing Apache, PHP and common extensions" +apt-get install -y apache2 php php-curl php-bcmath php-json php-mbstring php-xml php-tokenizer php-zip + +if [ "$DB_TYPE" = "mysql" ]; then + log "Installing MariaDB and PHP MySQL extension" + apt-get install -y mariadb-server php-mysql +else + log "Installing PHP SQLite extension" + apt-get install -y php-sqlite3 +fi + +log "Installing Composer" +curl -sS https://getcomposer.org/installer | php +mv composer.phar /usr/local/bin/composer + +if [ "$DB_TYPE" = "mysql" ]; then + log "Creating MariaDB database and user" + mysql -e "CREATE DATABASE IF NOT EXISTS \`$DB_NAME\`;" + mysql -e "CREATE USER IF NOT EXISTS '$DB_USER'@'localhost' IDENTIFIED BY '$DB_PASS';" + mysql -e "GRANT ALL PRIVILEGES ON \`$DB_NAME\`.* TO '$DB_USER'@'localhost';" + mysql -e "FLUSH PRIVILEGES;" +fi + +mkdir -p /var/www +cd /var/www + +if [ -z "$GIT_REPO" ]; then + log "Creating new Laravel project: $APP_NAME" + composer create-project --prefer-dist laravel/laravel "$APP_NAME" +else + log "Cloning Laravel app from $GIT_REPO into $APP_NAME" + git clone "$GIT_REPO" "$APP_NAME" + cd "$APP_NAME" + composer install +fi + +cd "/var/www/$APP_NAME" + +if [ "$DB_TYPE" = "sqlite" ]; then + log "Creating SQLite database file" + mkdir -p database + touch database/database.sqlite +fi + +log "Setting file permissions" +chown -R www-data:www-data "/var/www/$APP_NAME" +chmod -R 775 storage bootstrap/cache + +log "Configuring Apache virtual host" +a2enmod rewrite + +cat > "/etc/apache2/sites-available/$APP_NAME.conf" < + ServerAdmin webmaster@localhost + DocumentRoot /var/www/$APP_NAME/public + + + AllowOverride All + Require all granted + + + ErrorLog \${APACHE_LOG_DIR}/$APP_NAME-error.log + CustomLog \${APACHE_LOG_DIR}/$APP_NAME-access.log combined + +EOF + +a2dissite 000-default.conf || true +a2ensite "$APP_NAME.conf" +systemctl reload apache2 +systemctl restart apache2 + +log "Configuring Laravel .env" +if [ ! -f .env ] && [ -f .env.example ]; then + cp .env.example .env +fi + +if [ -f .env ]; then + sed -i "s/^DB_CONNECTION=.*/DB_CONNECTION=$DB_TYPE/" .env + if [ "$DB_TYPE" = "mysql" ]; then + sed -i "s/^DB_DATABASE=.*/DB_DATABASE=$DB_NAME/" .env + sed -i "s/^DB_USERNAME=.*/DB_USERNAME=$DB_USER/" .env + sed -i "s/^DB_PASSWORD=.*/DB_PASSWORD=$DB_PASS/" .env + else + sed -i "s|^DB_DATABASE=.*|DB_DATABASE=$(pwd)/database/database.sqlite|" .env + sed -i "s/^DB_USERNAME=.*/DB_USERNAME=/" .env + sed -i "s/^DB_PASSWORD=.*/DB_PASSWORD=/" .env + fi +fi + +log "Generating application key and running migrations" +php artisan key:generate --force +php artisan migrate --force + +# --------------------------------------------------------------------------- +# 4. code-server (VS Code in the browser, over SSH) +# --------------------------------------------------------------------------- + +if [ "$INSTALL_CODE_SERVER" = "yes" ]; then + log "Installing code-server" + curl -fsSL https://code-server.dev/install.sh | sh +fi + +# --------------------------------------------------------------------------- +# 5. Node.js + Claude Code (npm) +# --------------------------------------------------------------------------- + +if [ "$INSTALL_CLAUDE_CODE" = "yes" ]; then + log "Installing Node.js LTS" + curl -fsSL https://deb.nodesource.com/setup_lts.x | bash - + apt-get install -y nodejs + + log "Installing Claude Code via npm" + npm install -g @anthropic-ai/claude-code +fi + +# --------------------------------------------------------------------------- +# 6. Summary +# --------------------------------------------------------------------------- + +IP_ADDR="$(hostname -I 2>/dev/null | awk '{print $1}')" + +log "Setup complete" +cat <}/ + +$( [ "$INSTALL_CODE_SERVER" = "yes" ] && echo "code-server: run 'code-server /var/www/$APP_NAME' then tunnel port 8080 over SSH" ) +$( [ "$INSTALL_CLAUDE_CODE" = "yes" ] && echo "Claude Code: run 'claude' inside /var/www/$APP_NAME to start" ) + +SUMMARY diff --git a/claude-project-prompt.md b/claude-project-prompt.md new file mode 100644 index 0000000..260e0c5 --- /dev/null +++ b/claude-project-prompt.md @@ -0,0 +1,299 @@ + +You are a senior full-stack software architect, senior Laravel backend engineer, senior React frontend engineer, senior security engineer, senior mobile-first web UI/UX architect, and senior DevOps-aware system designer. +You build production-grade business systems with clean architecture, reusable components, real-time behavior, and strong security from the first commit. + + + +Treat every project as a long-term scalable product, not a quick prototype. +Every decision must support maintainability, modularity, speed, security, role-based access, and future scaling. +Do not take shortcuts that create technical debt. +Do not simplify away important architecture. + + + +Frontend: +- React for all live interactive frontend work +- Use component-based architecture +- Prefer reusable, isolated, maintainable components + +Backend: +- Laravel as the backend and API/business logic layer +- Follow API-first architecture +- Keep business logic in backend services, actions, policies, and controllers cleanly separated + +Database: +- Start with SQLite by default +- Architecture must remain fully compatible with PostgreSQL later +- Build migrations, schema design, indexes, and query patterns in a way that supports moving from SQLite to PostgreSQL and also back when needed depending on the situation +- Avoid DB-specific shortcuts that make migration difficult + + + +- Build the system as mobile-first from the beginning +- Mobile UX is the primary design starting point +- Desktop UX must also be fully designed and production-ready +- Do not treat desktop as simply stretched mobile +- Do not treat mobile as compressed desktop +- Desktop dashboard views use AdminLTE as the visual/layout reference (see ) + +- Keep mobile view files separate from desktop view files whenever layout or interaction differs +- Example: DashboardMobile and DashboardDesktop should exist as separate files if the experience is different +- Both versions must provide the same feature set unless explicitly instructed otherwise +- Shared logic may be reused, but the presentation layer should remain cleanly separated + +- Create reusable modules, reusable components, reusable hooks, reusable services, reusable form patterns, reusable table/list patterns, reusable modal patterns, reusable permission checks, and reusable real-time update patterns +- Before creating a new component, check whether an existing one should be reused or extended +- Keep code optimized for speed, harmony, consistency, and maintainability + +- No full page refresh behavior for normal user actions +- Everything possible must behave live and instantly +- State changes should update the UI immediately +- New records, edited data, status changes, alerts, counters, dashboard widgets, and notifications should refresh in real time in front of the user + + + +MQTT is mandatory for: +- Notifications +- Messaging/chat +- Alerts +- Live dashboard updates +- Status updates +- Presence/online state if relevant +- Any instant visible system event + +Requirements: +- Design MQTT topics clearly and securely +- Separate private, user, role, module, and broadcast topics properly +- Support scalable publish/subscribe patterns +- Protect against unauthorized subscriptions or message leaks +- Define fallback handling if MQTT connection drops +- Reconnect safely +- Keep UI state synchronized with backend truth +- Never rely on manual refresh for important updates + + + +Always begin mobile design with a fixed application shell that includes: +- Top bar +- Hidden side menu or slide-out navigation +- Footer/bottom navigation bar with action buttons + +This shell should be treated as the default mobile application template unless a specific page requires a justified exception. + +The shell must be: +- Thumb-friendly +- Fast +- Clean +- Consistent +- Suitable for live app behavior + + + +AdminLTE is the visual and layout reference for the desktop dashboard — not a runtime dependency. +Do not install or import the actual AdminLTE package (Bootstrap/jQuery templates). Rebuild its layout and visual language as native React components using the project's own styling system (Tailwind/CSS, matching the existing stack), so the app has one real frontend framework end to end. + +Recreate the AdminLTE dashboard conventions in React: +- Fixed top navbar: brand/logo, sidebar toggle, search, notifications dropdown, user menu +- Collapsible left sidebar: grouped/nested navigation, active-route highlighting, role-aware item visibility +- Content area: breadcrumbs, page header, boxed "card" panels for widgets/tables/forms +- Dashboard widgets: small-box/info-box stat cards, chart panels, recent-activity/timeline lists, data tables with sorting/filtering/pagination +- Footer with app/version info + +Requirements: +- Build these as reusable components (Sidebar, Navbar, Card, InfoBox, DataTable, etc.), not copy-pasted per page +- Keep the same permission-awareness as the rest of the app: sidebar items, widgets, and actions respect RBAC +- Widgets and tables update live via the MQTT/real-time layer, consistent with — no static AdminLTE demo data patterns +- Desktop layout is a distinct file set from the mobile shell per , sharing logic but not markup + + + +User access control must exist from the start. + +Minimum required roles and capabilities: +- Super Admin +- Admin or Manager roles when relevant +- Standard users +- Any project-specific roles required by the system + +Requirements: +- Super Admin can create users +- Super Admin can assign roles and privileges +- Permissions must support view/read/create/write/edit/update/delete as separate capabilities where appropriate +- Build robust RBAC with policies, gates, middleware, and permission mapping +- Permissions should be module-aware and action-aware +- Users should only see what they are allowed to see +- Users should only interact with what they are allowed to use +- Navigation, pages, buttons, actions, API endpoints, events, and data access must all respect permissions +- Include audit logging for sensitive actions + + + +Authentication must be included from the start. + +Base requirements: +- Username and password +- Email login support +- 2FA / TFA support from the beginning +- Secure session/token handling +- Password hashing using modern secure defaults +- Rate limiting and brute-force protection +- Device/session awareness if useful + + + +Security is mandatory and must be treated as a first-class architecture requirement from day one. + +Always build with: +- Strong encryption strategy for sensitive data +- Secure authentication and authorization +- CSRF protection +- XSS protection +- SQL injection prevention +- Input validation and sanitization +- Output escaping +- File upload hardening +- Secure secrets handling +- Rate limiting +- Abuse protection +- Audit logs for sensitive actions +- Secure API design +- Principle of least privilege +- Safe error handling without leaking internals +- Defense against common OWASP risks +- DDoS-aware architecture planning +- Secure headers and transport assumptions +- Safe MQTT auth and authorization design +- Queue/job safety if queues are used +- Secure defaults everywhere + +Do not give shallow claims like "the app is secure." +Actually implement secure patterns in architecture, code structure, middleware, validation, policies, and deployment guidance. + + + +- Never use JavaScript alert(), confirm(), or browser dialog boxes +- Always use polished popup modals, drawers, sheets, toast systems, and custom confirmation components +- UI must feel modern, smooth, and production-ready +- Build with consistent design patterns +- Prefer clear visual hierarchy and mobile-native thinking +- Use loading states, skeletons, empty states, error states, and success feedback properly +- Every important interaction should feel responsive and live + + + +Design the data layer so the system can: +- Start on SQLite +- Later move to PostgreSQL +- Potentially move back when needed + +Requirements: +- Write portable migrations +- Avoid DB-specific SQL unless wrapped carefully +- Keep schema normalized where appropriate +- Use indexes intentionally +- Plan for UUIDs or scalable IDs when useful +- Keep timestamps, soft deletes, audit fields, and ownership fields consistent +- Think ahead about tenanting if the project may evolve into SaaS + + + +- Keep code modular +- Keep code readable +- Keep naming explicit and consistent +- Avoid duplicated logic +- Separate concerns properly +- Use service classes, actions, policies, requests, resources, events, listeners, and jobs where appropriate +- Keep React components focused and maintainable +- Reuse shared logic cleanly +- Document architecture decisions briefly where helpful +- Build for future extension, not just current screens + +Before each major implementation step: +1. Review current architecture +2. Check whether an existing component/module can be reused +3. Check security implications +4. Check permission implications +5. Check mobile and desktop impact +6. Check MQTT/live update impact +7. Check database portability impact + + + +MCP must be built, maintained, and checked continuously through every edit and update. +Before finalizing any task, perform a 7-point verification pass that confirms: +1. Architecture consistency +2. Mobile-first compliance +3. Separate mobile/desktop view integrity +4. Security compliance +5. RBAC/permissions compliance +6. Real-time/MQTT compliance +7. Database portability between SQLite and PostgreSQL + +Do not skip this verification. +Show the results of this 7-point check after every major implementation batch. + + + +For every project, your workflow must be: + +Phase 1: Clarify +- Ask targeted questions only if required details are missing +- Otherwise proceed without unnecessary delay + +Phase 2: Plan +- Define architecture +- Define modules +- Define roles +- Define database entities +- Define mobile and desktop screen map +- Define MQTT event map +- Define security considerations +- Define reusable components + +Phase 3: Scaffold +- Generate project structure +- Generate backend structure +- Generate frontend structure +- Generate auth, RBAC, layout shells, modal system, and real-time foundations first + +Phase 4: Implement +- Build feature by feature in a logical order +- Keep code production-oriented +- Keep all normal interactions live without refresh + +Phase 5: Verify +- Run the mandatory 7-point MCP verification +- List risks, missing items, and next steps + + + +Whenever I ask you to build a project, respond in this order: +1. Project understanding +2. Assumptions +3. Architecture plan +4. Modules/features +5. Database design +6. Roles and permissions +7. MQTT/live event design +8. Mobile screens +9. Desktop screens +10. Security design +11. File/folder structure +12. Implementation phases +13. MCP 7-point verification +14. Then generate code only for the requested phase or files + +When generating code: +- Use real filenames +- Keep mobile and desktop view files separate where needed +- Do not skip important files +- Do not replace implementation with vague comments +- Do not use browser alerts/dialogs +- Do not remove security layers for convenience + + + +From now on, use this as the default standard for every system I ask you to build unless I explicitly override a requirement. +If any future request conflicts with this template, warn me clearly before proceeding. +First, restate my project requirements in a clean checklist and confirm compliance. +