From 87261e0b072e39eeffe6600a967330f26d892e5b Mon Sep 17 00:00:00 2001 From: juancjc Date: Mon, 11 May 2026 12:44:24 -0500 Subject: [PATCH] =?UTF-8?q?Adiciona=20configura=C3=A7=C3=A3o=20inicial=20d?= =?UTF-8?q?a=20stack=20Docker=20para=20projetos=20Laravel,=20incluindo=20D?= =?UTF-8?q?ockerfile,=20docker-compose,=20scripts=20de=20gerenciamento=20e?= =?UTF-8?q?=20configura=C3=A7=C3=A3o=20do=20Nginx.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 16 ++ Dockerfile | 73 +++++++ README.md | 408 ++++++++++++++++++++++++++++++++++++ docker-compose.yml | 31 +++ host-deploy.sh | 15 ++ host-remove.sh | 17 ++ host-status.sh | 6 + nginx/nginx.conf | 66 ++++++ php/php.ini | 14 ++ scripts/deploy.sh | 284 +++++++++++++++++++++++++ scripts/remove.sh | 41 ++++ scripts/start.sh | 31 +++ scripts/status.sh | 64 ++++++ supervisor/supervisord.conf | 25 +++ 14 files changed, 1091 insertions(+) create mode 100644 .gitignore create mode 100644 Dockerfile create mode 100644 README.md create mode 100644 docker-compose.yml create mode 100644 host-deploy.sh create mode 100644 host-remove.sh create mode 100644 host-status.sh create mode 100644 nginx/nginx.conf create mode 100644 php/php.ini create mode 100644 scripts/deploy.sh create mode 100644 scripts/remove.sh create mode 100644 scripts/start.sh create mode 100644 scripts/status.sh create mode 100644 supervisor/supervisord.conf diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..38fb6ab --- /dev/null +++ b/.gitignore @@ -0,0 +1,16 @@ +# Sistema +.DS_Store +Thumbs.db + +# Logs +*.log + +# Segredos locais +.env +.env.local + +# Pastas geradas no host +projects/ +nginx-dynamic/ +composer-cache/ +npm-cache/ diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..3fff616 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,73 @@ +FROM php:8.3-fpm-bookworm + +ARG NODE_MAJOR=20 + +ENV COMPOSER_ALLOW_SUPERUSER=1 \ + COMPOSER_CACHE_DIR=/tmp/composer-cache \ + NPM_CONFIG_CACHE=/root/.npm + +RUN apt-get update && apt-get install -y --no-install-recommends \ + nginx \ + supervisor \ + git \ + bash \ + curl \ + unzip \ + zip \ + ca-certificates \ + gnupg \ + libpq-dev \ + libzip-dev \ + libpng-dev \ + libjpeg62-turbo-dev \ + libfreetype6-dev \ + libicu-dev \ + libonig-dev \ + libxml2-dev \ + libssl-dev \ + libcurl4-openssl-dev \ + && docker-php-ext-configure gd --with-freetype --with-jpeg \ + && docker-php-ext-install -j"$(nproc)" \ + pdo \ + pdo_pgsql \ + pgsql \ + pdo_mysql \ + mysqli \ + zip \ + gd \ + intl \ + bcmath \ + exif \ + opcache \ + pcntl \ + && pecl install redis \ + && docker-php-ext-enable redis \ + && curl -fsSL "https://deb.nodesource.com/setup_${NODE_MAJOR}.x" | bash - \ + && apt-get install -y --no-install-recommends nodejs \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +COPY --from=composer:2 /usr/bin/composer /usr/local/bin/composer + +RUN mkdir -p /home/deploy/projects \ + /home/deploy/scripts \ + /etc/nginx/sites-dynamic \ + /var/log/nginx \ + /run/nginx \ + /var/log/supervisor \ + /tmp/composer-cache \ + /root/.npm + +COPY php/php.ini /usr/local/etc/php/conf.d/99-laravel-stack.ini +COPY nginx/nginx.conf /etc/nginx/nginx.conf +COPY supervisor/supervisord.conf /etc/supervisor/conf.d/supervisord.conf +COPY scripts/ /home/deploy/scripts/ + +RUN chmod +x /home/deploy/scripts/*.sh \ + && chown -R www-data:www-data /home/deploy/projects /tmp/composer-cache + +WORKDIR /home/deploy + +EXPOSE 80 + +CMD ["/home/deploy/scripts/start.sh"] diff --git a/README.md b/README.md new file mode 100644 index 0000000..6b050a6 --- /dev/null +++ b/README.md @@ -0,0 +1,408 @@ +# Laravel Multi-Projeto Stack + +Stack Docker para hospedar vários projetos Laravel no mesmo container, acessando por rota: + +```txt +https://laravel.juancjc.com.br/projeto1 +https://laravel.juancjc.com.br/projeto2 +https://laravel.juancjc.com.br/sistema-alunos +``` + +A ideia é parecida com sua stack NestJS, mas para Laravel: + +- Nginx na frente. +- PHP-FPM para rodar Laravel. +- Composer dentro do container. +- Node + NPM dentro do container para projetos com Vite/Vue. +- Detecta automaticamente: + - `laravel-vue` + - `laravel-blade-vite` + - `laravel-blade` + - `laravel-node` +- Cria automaticamente a rota `/nome-da-pasta`. + +--- + +## Estrutura do repositório + +```txt +laravel-stack/ +├── Dockerfile +├── docker-compose.yml +├── .gitignore +├── nginx/ +│ └── nginx.conf +├── php/ +│ └── php.ini +├── supervisor/ +│ └── supervisord.conf +├── scripts/ +│ ├── start.sh +│ ├── deploy.sh +│ ├── remove.sh +│ └── status.sh +├── host-deploy.sh +├── host-remove.sh +└── host-status.sh +``` + +--- + +## Estrutura no servidor + +```txt +/srv/projects/laravel/ +├── projects/ +│ ├── projeto1/ +│ ├── projeto2/ +│ └── sistema-alunos/ +├── nginx-dynamic/ +├── composer-cache/ +└── npm-cache/ +``` + +Cada pasta dentro de `/srv/projects/laravel/projects` vira uma rota. + +Exemplo: + +```txt +/srv/projects/laravel/projects/sistema-alunos +``` + +vira: + +```txt +https://laravel.juancjc.com.br/sistema-alunos +``` + +--- + +## Setup inicial no servidor + +```bash +mkdir -p /srv/projects/laravel/projects +mkdir -p /srv/projects/laravel/nginx-dynamic +mkdir -p /srv/projects/laravel/composer-cache +mkdir -p /srv/projects/laravel/npm-cache +``` + +Clone esta stack: + +```bash +git clone /srv/projects/laravel/laravel-stack +cd /srv/projects/laravel/laravel-stack +chmod +x host-*.sh +``` + +Suba com Docker Compose: + +```bash +docker compose up -d --build +``` + +Ou pelo Portainer: + +1. Stacks +2. Add Stack +3. Repository +4. Cole a URL deste repositório +5. Deploy + +--- + +## Adicionar um projeto Laravel + +Entre na pasta de projetos: + +```bash +cd /srv/projects/laravel/projects +``` + +Clone ou coloque o código: + +```bash +git clone https://github.com/seu-usuario/meu-projeto.git meu-projeto +``` + +Crie ou edite o `.env`: + +```bash +nano /srv/projects/laravel/projects/meu-projeto/.env +``` + +Depois faça o deploy: + +```bash +/srv/projects/laravel/laravel-stack/host-deploy.sh meu-projeto +``` + +Acesse: + +```txt +https://laravel.juancjc.com.br/meu-projeto +``` + +--- + +## Atualizar um projeto + +```bash +cd /srv/projects/laravel/projects/meu-projeto +git pull + +/srv/projects/laravel/laravel-stack/host-deploy.sh meu-projeto +``` + +--- + +## Ver status + +```bash +/srv/projects/laravel/laravel-stack/host-status.sh +``` + +--- + +## Remover projeto + +Remove rota Nginx e arquivos: + +```bash +/srv/projects/laravel/laravel-stack/host-remove.sh meu-projeto +``` + +Remove só a rota, mantendo os arquivos: + +```bash +/srv/projects/laravel/laravel-stack/host-remove.sh meu-projeto --keep-files +``` + +--- + +## Como ele identifica Vue ou Blade + +O script olha os arquivos do projeto: + +### Laravel Vue + +Se existir `package.json` com: + +```json +"vue" +``` + +ou: + +```json +"@inertiajs/vue3" +``` + +ou: + +```json +"@vitejs/plugin-vue" +``` + +ele marca como: + +```txt +laravel-vue +``` + +### Laravel Blade com Vite + +Se existir `package.json` com Vite, mas sem Vue: + +```txt +laravel-blade-vite +``` + +### Laravel Blade simples + +Se não tiver `package.json`: + +```txt +laravel-blade +``` + +O tipo fica salvo em: + +```txt +.projeto/.project-type +``` + +--- + +## Importante para rodar em `/projeto` + +Como cada sistema roda em subpasta, o deploy ajusta automaticamente no `.env` do projeto: + +```env +APP_URL=https://laravel.juancjc.com.br/meu-projeto +ASSET_URL=/meu-projeto +``` + +Isso ajuda CSS, JS, imagens e links gerados pelo Laravel. + +--- + +## Projetos Vue/Inertia com Vite + +Se algum projeto Vue tiver problema com assets em `/build`, ajuste o `vite.config.js` para respeitar `VITE_BASE`. + +Exemplo: + +```js +import { defineConfig } from 'vite'; +import laravel from 'laravel-vite-plugin'; +import vue from '@vitejs/plugin-vue'; + +export default defineConfig({ + base: process.env.VITE_BASE || '/', + plugins: [ + laravel({ + input: 'resources/js/app.js', + refresh: true, + }), + vue(), + ], +}); +``` + +O deploy já executa: + +```bash +ASSET_URL="/meu-projeto" VITE_BASE="/meu-projeto/build/" npm run build +``` + +--- + +## Rodar migrations automaticamente + +Por padrão, a stack não roda migrations para evitar acidente em produção. + +Se quiser que rode no deploy, coloque no `.env` do projeto: + +```env +RUN_MIGRATIONS=true +``` + +Aí no deploy ele executa: + +```bash +php artisan migrate --force +``` + +--- + +## Comandos úteis + +Logs do container: + +```bash +docker logs laravel-stack -f +``` + +Entrar no container: + +```bash +docker exec -it laravel-stack bash +``` + +Deploy manual dentro do container: + +```bash +docker exec laravel-stack /home/deploy/scripts/deploy.sh meu-projeto +``` + +Ver Nginx: + +```bash +docker exec laravel-stack nginx -T +``` + +Testar Nginx: + +```bash +docker exec laravel-stack nginx -t +``` + +--- + +## Variáveis principais no docker-compose + +```env +PROJECTS_DIR=/home/deploy/projects +DOMAIN=laravel.juancjc.com.br +PUBLIC_BASE_URL=https://laravel.juancjc.com.br +AUTO_DEPLOY_ON_START=false +PHP_MEMORY_LIMIT=512M +``` + +### `AUTO_DEPLOY_ON_START` + +Se deixar: + +```env +AUTO_DEPLOY_ON_START=false +``` + +o container apenas recria as rotas Nginx ao iniciar. + +Se trocar para: + +```env +AUTO_DEPLOY_ON_START=true +``` + +o container roda deploy em todos os projetos sempre que iniciar. + +Eu recomendo deixar `false` e usar: + +```bash +./host-deploy.sh projeto +``` + +quando quiser atualizar. + +--- + +## Banco Postgres + +A stack já está ligada na rede externa: + +```yaml +postgres-18_default: + external: true +``` + +Então, no `.env` do Laravel, use o nome do serviço/container do Postgres como host. + +Exemplo: + +```env +DB_CONNECTION=pgsql +DB_HOST=postgres +DB_PORT=5432 +DB_DATABASE=meu_banco +DB_USERNAME=meu_usuario +DB_PASSWORD=minha_senha +``` + +Se seu container Postgres tiver outro nome, ajuste o `DB_HOST`. + +--- + +## Observação + +Para produção, prefira colocar o domínio principal no Nginx Proxy Manager apontando para: + +```txt +laravel-stack:80 +``` + +ou para a porta publicada: + +```txt +IP_DO_SERVIDOR:3452 +``` diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..53a26e7 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,31 @@ +services: + laravel-stack: + build: + context: . + dockerfile: Dockerfile + container_name: laravel-stack + restart: unless-stopped + ports: + - "3452:80" + volumes: + - /srv/projects/laravel/projects:/home/deploy/projects + - /srv/projects/laravel/nginx-dynamic:/etc/nginx/sites-dynamic + - /srv/projects/laravel/composer-cache:/tmp/composer-cache + - /srv/projects/laravel/npm-cache:/root/.npm + environment: + - PROJECTS_DIR=/home/deploy/projects + - DOMAIN=laravel.juancjc.com.br + - PUBLIC_BASE_URL=https://laravel.juancjc.com.br + - AUTO_DEPLOY_ON_START=false + - PHP_MEMORY_LIMIT=512M + labels: + - "com.laravelstack.managed=true" + networks: + - proxy-net + - postgres-18_default + +networks: + proxy-net: + external: true + postgres-18_default: + external: true diff --git a/host-deploy.sh b/host-deploy.sh new file mode 100644 index 0000000..faa1ae6 --- /dev/null +++ b/host-deploy.sh @@ -0,0 +1,15 @@ +#!/bin/bash +# host-deploy.sh — rode NO HOST para deployar um projeto Laravel +# Uso: ./host-deploy.sh meu-projeto +# Uso: ./host-deploy.sh # deploya todos + +CONTAINER="${CONTAINER:-laravel-stack}" +TARGET="${1:-}" + +if [ -n "$TARGET" ]; then + echo ">>> Deployando $TARGET via container..." + docker exec "$CONTAINER" /home/deploy/scripts/deploy.sh "$TARGET" +else + echo ">>> Deployando todos os projetos via container..." + docker exec "$CONTAINER" /home/deploy/scripts/deploy.sh +fi diff --git a/host-remove.sh b/host-remove.sh new file mode 100644 index 0000000..ed73bb6 --- /dev/null +++ b/host-remove.sh @@ -0,0 +1,17 @@ +#!/bin/bash +# host-remove.sh — remove um projeto da Laravel Stack +# Uso: ./host-remove.sh meu-projeto +# Uso: ./host-remove.sh meu-projeto --keep-files + +CONTAINER="${CONTAINER:-laravel-stack}" +TARGET="${1:-}" +KEEP_FILES="${2:-}" + +if [ -z "$TARGET" ]; then + echo "❌ Informe o nome do projeto." + echo "Uso: ./host-remove.sh meu-projeto" + echo "Uso: ./host-remove.sh meu-projeto --keep-files" + exit 1 +fi + +docker exec "$CONTAINER" /home/deploy/scripts/remove.sh "$TARGET" "$KEEP_FILES" diff --git a/host-status.sh b/host-status.sh new file mode 100644 index 0000000..cd68c2c --- /dev/null +++ b/host-status.sh @@ -0,0 +1,6 @@ +#!/bin/bash +# host-status.sh — status dos projetos Laravel + +CONTAINER="${CONTAINER:-laravel-stack}" + +docker exec "$CONTAINER" /home/deploy/scripts/status.sh diff --git a/nginx/nginx.conf b/nginx/nginx.conf new file mode 100644 index 0000000..bb18b1b --- /dev/null +++ b/nginx/nginx.conf @@ -0,0 +1,66 @@ +user www-data; +worker_processes auto; +error_log /var/log/nginx/error.log warn; +pid /run/nginx.pid; + +events { + worker_connections 2048; +} + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + + access_log /var/log/nginx/access.log main; + + sendfile on; + tcp_nopush on; + tcp_nodelay on; + keepalive_timeout 65; + server_tokens off; + client_max_body_size 100M; + + gzip on; + gzip_comp_level 5; + gzip_min_length 256; + gzip_types + text/plain + text/css + text/javascript + application/javascript + application/json + application/xml + image/svg+xml; + + map $http_x_forwarded_proto $fastcgi_https { + default ""; + https on; + } + + server { + listen 80; + server_name _; + + absolute_redirect off; + + location = / { + add_header Content-Type text/plain; + return 200 'Laravel Stack pronta. Use /nome-do-projeto para acessar seus projetos.'; + } + + location = /health { + add_header Content-Type text/plain; + return 200 'ok'; + } + + include /etc/nginx/sites-dynamic/*.conf; + + location ~ /\.(?!well-known).* { + deny all; + } + } +} diff --git a/php/php.ini b/php/php.ini new file mode 100644 index 0000000..235553e --- /dev/null +++ b/php/php.ini @@ -0,0 +1,14 @@ +memory_limit=${PHP_MEMORY_LIMIT} +upload_max_filesize=100M +post_max_size=100M +max_execution_time=300 +max_input_time=300 +date.timezone=America/Rio_Branco + +opcache.enable=1 +opcache.enable_cli=1 +opcache.validate_timestamps=0 +opcache.max_accelerated_files=20000 +opcache.memory_consumption=256 +opcache.interned_strings_buffer=16 +opcache.fast_shutdown=1 diff --git a/scripts/deploy.sh b/scripts/deploy.sh new file mode 100644 index 0000000..92e1271 --- /dev/null +++ b/scripts/deploy.sh @@ -0,0 +1,284 @@ +#!/bin/bash +set -e + +PROJECTS_DIR="${PROJECTS_DIR:-/home/deploy/projects}" +DOMAIN="${DOMAIN:-localhost}" +PUBLIC_BASE_URL="${PUBLIC_BASE_URL:-http://${DOMAIN}}" +TARGET="" +NGINX_ONLY=false + +for arg in "$@"; do + case "$arg" in + --nginx-only) NGINX_ONLY=true ;; + *) TARGET="$arg" ;; + esac +done + +safe_name() { + echo "$1" | sed 's/[^A-Za-z0-9._-]/-/g' +} + +env_get() { + local file="$1" + local key="$2" + + if [ -f "$file" ]; then + grep -E "^${key}=" "$file" | tail -n1 | cut -d '=' -f2- | sed -e 's/^"//' -e 's/"$//' -e "s/^'//" -e "s/'$//" + fi +} + +env_set() { + local file="$1" + local key="$2" + local value="$3" + + touch "$file" + + if grep -qE "^${key}=" "$file"; then + sed -i "s|^${key}=.*|${key}=${value}|g" "$file" + else + echo "${key}=${value}" >> "$file" + fi +} + +detect_type() { + local project_dir="$1" + + if [ ! -f "$project_dir/artisan" ]; then + echo "nao-laravel" + return + fi + + if [ -f "$project_dir/package.json" ]; then + if grep -qiE '"(@inertiajs/vue3|vue|@vitejs/plugin-vue)"' "$project_dir/package.json"; then + echo "laravel-vue" + elif grep -qiE '"vite"|'"'@laravel/vite-plugin'" "$project_dir/package.json"; then + echo "laravel-blade-vite" + else + echo "laravel-node" + fi + else + echo "laravel-blade" + fi +} + +has_npm_build() { + node -e "const p=require('./package.json'); process.exit(p.scripts && p.scripts.build ? 0 : 1)" >/dev/null 2>&1 +} + +reload_nginx_if_running() { + if pgrep nginx >/dev/null 2>&1; then + nginx -t && nginx -s reload + fi +} + +generate_nginx_config() { + local project="$1" + local project_dir="$2" + local safe_project + safe_project="$(safe_name "$project")" + + cat > "/etc/nginx/sites-dynamic/${safe_project}.conf" < "$project_dir/.project-type" + + echo "→ Tipo identificado: $type" + + generate_nginx_config "$project" "$project_dir" + echo "✓ Nginx criado: /${project}" + + if [ "$NGINX_ONLY" = "true" ]; then + return 0 + fi + + cd "$project_dir" + + if [ ! -f "$env_file" ] && [ -f "$project_dir/.env.example" ]; then + echo "→ .env não encontrado, copiando .env.example" + cp "$project_dir/.env.example" "$env_file" + fi + + if [ -f "$env_file" ]; then + env_set "$env_file" "APP_URL" "$project_url" + env_set "$env_file" "ASSET_URL" "/${project}" + else + echo "⚠ Sem .env. Crie $env_file antes de usar banco/cache em produção." + fi + + echo "→ composer install..." + composer install \ + --no-dev \ + --prefer-dist \ + --no-interaction \ + --optimize-autoloader + + if [ -f "$env_file" ]; then + app_key="$(env_get "$env_file" "APP_KEY")" + if [ -z "$app_key" ] || [ "$app_key" = "null" ]; then + echo "→ Gerando APP_KEY..." + php artisan key:generate --force + fi + fi + + echo "→ Limpando caches Laravel..." + php artisan optimize:clear || true + + if [ -f "package.json" ]; then + echo "→ Dependências front-end encontradas." + + if [ -f "package-lock.json" ]; then + echo "→ npm ci..." + npm ci --no-audit --no-fund + else + echo "→ npm install..." + npm install --no-audit --no-fund + fi + + if has_npm_build; then + echo "→ npm run build..." + ASSET_URL="/${project}" VITE_BASE="/${project}/build/" npm run build + else + echo "⚠ package.json sem script build. Pulando build." + fi + else + echo "→ Sem package.json. Projeto identificado como Blade/PHP puro." + fi + + echo "→ storage:link..." + php artisan storage:link || true + + run_migrations="$(env_get "$env_file" "RUN_MIGRATIONS")" + if [ "$run_migrations" = "true" ]; then + echo "→ RUN_MIGRATIONS=true, rodando migrations..." + php artisan migrate --force + fi + + echo "→ Otimizando Laravel..." + php artisan config:cache || true + php artisan route:cache || { + echo "⚠ route:cache falhou, limpando cache de rotas." + php artisan route:clear || true + } + php artisan view:cache || true + php artisan event:cache || true + + echo "→ Ajustando permissões..." + mkdir -p storage bootstrap/cache + chown -R www-data:www-data storage bootstrap/cache public || true + chmod -R ug+rwX storage bootstrap/cache || true + + echo "✓ $project deployado em /$project" +} + +deploy_all() { + local found=0 + + for project_dir in "$PROJECTS_DIR"/*/; do + [ -d "$project_dir" ] || continue + project="$(basename "$project_dir")" + found=$((found + 1)) + deploy_project "$project" || true + done + + if [ "$found" -eq 0 ]; then + echo "Nenhum projeto encontrado em $PROJECTS_DIR" + fi +} + +mkdir -p "$PROJECTS_DIR" /etc/nginx/sites-dynamic + +if [ -n "$TARGET" ]; then + deploy_project "$TARGET" +else + deploy_all +fi + +echo "" +echo "→ Recarregando Nginx se estiver em execução..." +reload_nginx_if_running || true + +echo "" +echo "================================================" +echo " Deploy concluído!" +for project_dir in "$PROJECTS_DIR"/*/; do + [ -d "$project_dir" ] || continue + project="$(basename "$project_dir")" + type="$(cat "$project_dir/.project-type" 2>/dev/null || echo '?')" + echo " ✓ /$project → $type" +done +echo "================================================" diff --git a/scripts/remove.sh b/scripts/remove.sh new file mode 100644 index 0000000..5fd2cf8 --- /dev/null +++ b/scripts/remove.sh @@ -0,0 +1,41 @@ +#!/bin/bash +set -e + +PROJECTS_DIR="${PROJECTS_DIR:-/home/deploy/projects}" +TARGET="${1:-}" +KEEP_FILES="${2:-}" + +if [ -z "$TARGET" ]; then + echo "❌ Informe o nome do projeto." + echo "Uso: /home/deploy/scripts/remove.sh meu-projeto" + echo "Uso: /home/deploy/scripts/remove.sh meu-projeto --keep-files" + exit 1 +fi + +safe_target="$(echo "$TARGET" | sed 's/[^A-Za-z0-9._-]/-/g')" + +echo "================================================" +echo " Removendo projeto: $TARGET" +echo "================================================" + +echo "→ Removendo config do Nginx..." +rm -f "/etc/nginx/sites-dynamic/${safe_target}.conf" + +if pgrep nginx >/dev/null 2>&1; then + echo "→ Recarregando Nginx..." + nginx -t && nginx -s reload +fi + +if [ "$KEEP_FILES" = "--keep-files" ]; then + echo "→ Arquivos mantidos em $PROJECTS_DIR/$TARGET" +else + if [ -d "$PROJECTS_DIR/$TARGET" ]; then + echo "→ Removendo arquivos do projeto..." + rm -rf "$PROJECTS_DIR/$TARGET" + echo "✓ Pasta removida" + else + echo "⚠ Pasta não encontrada" + fi +fi + +echo "✓ Projeto $TARGET removido." diff --git a/scripts/start.sh b/scripts/start.sh new file mode 100644 index 0000000..95a2a48 --- /dev/null +++ b/scripts/start.sh @@ -0,0 +1,31 @@ +#!/bin/bash +set -e + +PROJECTS_DIR="${PROJECTS_DIR:-/home/deploy/projects}" +AUTO_DEPLOY_ON_START="${AUTO_DEPLOY_ON_START:-false}" + +echo "================================================" +echo " Laravel Stack — Iniciando..." +echo "================================================" + +mkdir -p "$PROJECTS_DIR" /etc/nginx/sites-dynamic /run/nginx /var/log/nginx + +echo "→ Verificando projetos em $PROJECTS_DIR" + +if [ "$AUTO_DEPLOY_ON_START" = "true" ]; then + echo "→ AUTO_DEPLOY_ON_START=true, rodando deploy de todos os projetos..." + /home/deploy/scripts/deploy.sh || true +else + echo "→ AUTO_DEPLOY_ON_START=false, apenas recriando configs Nginx existentes..." + /home/deploy/scripts/deploy.sh --nginx-only || true +fi + +echo "→ Testando Nginx..." +nginx -t + +echo "================================================" +echo " Stack pronta!" +echo " Acesse: ${PUBLIC_BASE_URL:-http://${DOMAIN:-localhost}}/" +echo "================================================" + +exec /usr/bin/supervisord -c /etc/supervisor/conf.d/supervisord.conf diff --git a/scripts/status.sh b/scripts/status.sh new file mode 100644 index 0000000..c20697f --- /dev/null +++ b/scripts/status.sh @@ -0,0 +1,64 @@ +#!/bin/bash + +PROJECTS_DIR="${PROJECTS_DIR:-/home/deploy/projects}" +PUBLIC_BASE_URL="${PUBLIC_BASE_URL:-http://${DOMAIN:-localhost}}" + +echo "" +echo "================================================" +echo " Laravel Stack — Status dos Projetos" +echo "================================================" + +if [ ! -d "$PROJECTS_DIR" ]; then + echo "✗ Pasta $PROJECTS_DIR não encontrada" + exit 1 +fi + +found=0 + +for project_dir in "$PROJECTS_DIR"/*/; do + [ -d "$project_dir" ] || continue + project="$(basename "$project_dir")" + type="$(cat "$project_dir/.project-type" 2>/dev/null || echo '?')" + nginx_file="/etc/nginx/sites-dynamic/${project}.conf" + + found=$((found + 1)) + + if [ -f "$project_dir/artisan" ]; then + laravel="✓" + else + laravel="✗" + fi + + if [ -f "$project_dir/vendor/autoload.php" ]; then + vendor="✓" + else + vendor="✗" + fi + + if [ -d "$project_dir/public/build" ]; then + build="✓" + elif [ -f "$project_dir/package.json" ]; then + build="✗" + else + build="-" + fi + + if [ -f "$nginx_file" ]; then + nginx="✓" + else + nginx="✗" + fi + + echo "Projeto: $project" + echo "URL: ${PUBLIC_BASE_URL%/}/$project" + echo "Tipo: $type" + echo "Laravel: $laravel | vendor: $vendor | build front: $build | nginx: $nginx" + echo "" +done + +if [ "$found" -eq 0 ]; then + echo "Nenhum projeto encontrado em $PROJECTS_DIR" +fi + +echo "================================================" +echo "" diff --git a/supervisor/supervisord.conf b/supervisor/supervisord.conf new file mode 100644 index 0000000..870f96f --- /dev/null +++ b/supervisor/supervisord.conf @@ -0,0 +1,25 @@ +[supervisord] +nodaemon=true +user=root +logfile=/var/log/supervisor/supervisord.log +pidfile=/var/run/supervisord.pid + +[program:php-fpm] +command=php-fpm -F +autostart=true +autorestart=true +priority=10 +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0 + +[program:nginx] +command=nginx -g "daemon off;" +autostart=true +autorestart=true +priority=20 +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0