---
title: "Como hospedar Laravel na VPS com Nginx, PHP 8.3 e MariaDB"
description: "Hospede Laravel na VPS Ubuntu 24.04: PHP 8.3 FPM, Composer, MariaDB, permissões certas em storage, Nginx com HTTPS, filas, agendador e deploy."
url: "https://streethosting.com.br/guias/vps/hospedar-laravel-vps"
category: "vps"
slug: "hospedar-laravel-vps"
datePublished: "2026-09-28"
dateModified: "2026-09-28"
author: "Equipe StreetHosting"
difficulty: "intermediario"
language: "pt-BR"
keywords:
  - "hospedar laravel vps"
  - "deploy laravel ubuntu 24.04"
  - "laravel nginx php fpm"
  - "permissao storage laravel"
  - "laravel queue worker systemd"
---

# Laravel na sua VPS: PHP FPM, banco, permissões e HTTPS sem erro 500

Do servidor zerado ao Laravel respondendo em HTTPS: PHP 8.3 FPM do Ubuntu 24.04, Composer, MariaDB, permissões de storage e bootstrap/cache, Nginx no formato oficial, filas com systemd e um script de deploy.

> **Resposta rápida**
>
> Para **hospedar Laravel na VPS**, instale no Ubuntu 24.04 o PHP 8.3 FPM com as extensões do framework, o Composer e o MariaDB, clone o projeto em `/var/www`, dê permissão de escrita ao `www-data` só em `storage` e `bootstrap/cache`, e aponte o Nginx para a pasta `public` com HTTPS do Let's Encrypt. Filas e agendador rodam com systemd e cron.

## O que a VPS precisa ter

Diferente de Node ou Java, o Laravel não roda como um processo que escuta uma porta. Quem recebe as requisições é o Nginx, que entrega arquivos estáticos direto do disco e repassa o resto ao PHP FPM, um conjunto de processos PHP prontos para executar o código. Por isso a configuração do Nginx é diferente de um proxy reverso comum.

| Peça | Função | Versão no Ubuntu 24.04 |
| --- | --- | --- |
| Nginx | Recebe o tráfego, serve estáticos e termina o HTTPS | Pacote nginx |
| PHP FPM | Executa o código do Laravel | PHP 8.3 |
| Composer | Instala as dependências PHP do projeto | Pacote composer (2.7) |
| MariaDB | Banco de dados | MariaDB 10.11 |
| Node.js | Compila CSS e JavaScript com Vite, se o projeto usar | Node 24 pela NodeSource |
| systemd e cron | Mantêm filas e tarefas agendadas rodando | Já vêm no sistema |

O PHP 8.3 do repositório padrão do Ubuntu 24.04 atende ao Laravel 13, que exige exatamente essa versão como mínima, e ao Laravel 12. Se a sua VPS estiver no Ubuntu 22.04, o PHP de lá é o 8.1, velho demais; reinstalar com o 24.04 é mais simples do que manter repositório externo de PHP.

## Instalar PHP 8.3, Composer e MariaDB

As extensões abaixo cobrem o que o Laravel exige (mbstring, XML, cURL, PDO e as que já vêm embutidas no PHP) e o que quase todo projeto usa, como zip para o Composer, intl para formatação e bcmath para cálculos com dinheiro:

```
sudo apt update
sudo apt install -y nginx php8.3-fpm php8.3-cli php8.3-mysql \
  php8.3-mbstring php8.3-xml php8.3-curl php8.3-zip php8.3-bcmath \
  php8.3-intl php8.3-gd unzip git composer
php -v
composer --version
```

Instalar o Composer pelo apt é o caminho mais simples e já traz a versão 2. Se algum pacote do projeto pedir uma versão mais nova do Composer, siga o instalador oficial descrito no site do Composer.

Em seguida, o banco. O script de segurança remove usuários anônimos e o banco de teste; depois crie um banco e um usuário exclusivos para a aplicação:

```
sudo apt install -y mariadb-server
sudo mariadb-secure-installation

sudo mariadb
CREATE DATABASE meu_app CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'meu_app'@'localhost' IDENTIFIED BY 'troque-esta-senha';
GRANT ALL PRIVILEGES ON meu_app.* TO 'meu_app'@'localhost';
FLUSH PRIVILEGES;
EXIT;
```

O `utf8mb4` é o que aceita emojis e qualquer caractere; o antigo utf8 do MySQL corta esses caracteres. O guia de [MariaDB e MySQL na VPS](https://streethosting.com.br/guias/vps/instalar-mariadb-mysql-vps-ubuntu) detalha acesso remoto seguro, backup com dump e ajuste de memória do banco.

## Código, .env e permissões

Crie a pasta da aplicação com o seu usuário como dono e clone o repositório. O código fica em `/var/www` e não na sua pasta pessoal porque, no Ubuntu 24.04, as pastas pessoais são fechadas para outros usuários, e o Nginx e o PHP FPM rodam como `www-data`.

```
sudo mkdir -p /var/www/meu-app
sudo chown usuario:usuario /var/www/meu-app
git clone https://github.com/sua-conta/meu-app.git /var/www/meu-app
cd /var/www/meu-app

composer install --no-dev --optimize-autoloader
cp .env.example .env
php artisan key:generate
```

Edite o `.env` com os dados de produção:

```
APP_ENV=production
APP_DEBUG=false
APP_URL=https://seu-dominio.com.br

DB_CONNECTION=mariadb
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=meu_app
DB_USERNAME=meu_app
DB_PASSWORD=troque-esta-senha
```

> **Atenção**
>
> `APP_DEBUG=false` não é detalhe. Com debug ligado, qualquer erro mostra ao visitante uma página com trechos de código, consultas e variáveis de ambiente, incluindo senhas. Nunca deixe ligado em produção.

### Permissões de storage e bootstrap/cache

O Laravel só precisa escrever em duas pastas: `storage`, com logs, cache, sessões e uploads, e `bootstrap/cache`, com os arquivos gerados pelo cache de configuração e rotas. O resto do código deve ser apenas legível para o PHP. Dar `chmod 777` em tudo "resolve" o erro, mas permite que uma falha de upload grave um arquivo PHP executável dentro do projeto.

```
cd /var/www/meu-app
sudo chown -R usuario:www-data /var/www/meu-app
sudo chmod -R u=rwX,g=rX,o= /var/www/meu-app

sudo apt install -y acl
sudo setfacl -R -m u:www-data:rwX -m u:usuario:rwX storage bootstrap/cache
sudo setfacl -dR -m u:www-data:rwX -m u:usuario:rwX storage bootstrap/cache
```

- **Dono usuario, grupo do servidor web:** o código é seu, e o PHP lê pelo grupo, sem poder alterar nada. O chmod tira a escrita do grupo e fecha tudo para outros usuários do sistema, inclusive o `.env`, que fica com 640.
- **Primeira linha do setfacl:** dá escrita ao PHP FPM e ao seu usuário nas duas pastas, com o que já existe nelas.
- **Segunda linha, com -d:** define a regra padrão para arquivos novos. É ela que evita o erro clássico em que o `laravel.log` é criado por um comando seu e depois o site não consegue escrever nele, ou o contrário.

Com as permissões certas, rode as migrações, o link público de uploads e, se o projeto usa Vite, a compilação dos assets. Para o Node.js, siga a mesma instalação pela NodeSource usada no guia de [aplicação Node.js na VPS](https://streethosting.com.br/guias/vps/hospedar-api-nodejs-vps-brasil), ou compile no CI e envie a pasta pronta.

```
php artisan migrate --force
php artisan storage:link
npm ci && npm run build
php artisan optimize
```

O `--force` é exigido porque o Laravel pede confirmação para migrar em produção. O `optimize` gera cache de configuração, rotas, eventos e views, o que reduz o trabalho de cada requisição. Depois dele, mudanças no `.env` só valem após rodar o comando de novo.

## Nginx, domínio e HTTPS

Aponte o domínio para o IP da VPS com um registro A, como mostra o guia de [apontar domínio para a VPS](https://streethosting.com.br/guias/vps/apontar-dominio-vps-registro-dns). A configuração abaixo segue a recomendada pela documentação do Laravel, com o caminho e o domínio ajustados:

```
sudo nano /etc/nginx/sites-available/meu-app

server {
    listen 80;
    listen [::]:80;
    server_name seu-dominio.com.br www.seu-dominio.com.br;
    root /var/www/meu-app/public;

    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-Content-Type-Options "nosniff";

    index index.php;
    charset utf-8;
    client_max_body_size 20m;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location = /favicon.ico { access_log off; log_not_found off; }
    location = /robots.txt  { access_log off; log_not_found off; }

    error_page 404 /index.php;

    location ~ ^/index\.php(/|$) {
        fastcgi_pass unix:/var/run/php/php8.3-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        include fastcgi_params;
        fastcgi_buffer_size 32k;
        fastcgi_buffers 8 32k;
        fastcgi_busy_buffers_size 64k;
        fastcgi_hide_header X-Powered-By;
    }

    location ~ /\.(?!well-known).* {
        deny all;
    }
}
```

Três detalhes importam. O `root` aponta para `public`, nunca para a raiz do projeto, senão o `.env` e o código ficam acessíveis pela web. Só o `index.php` é executado, então um arquivo PHP enviado por upload não roda. E o último bloco nega arquivos ocultos, liberando apenas a pasta usada pela validação do certificado.

```
sudo ln -s /etc/nginx/sites-available/meu-app /etc/nginx/sites-enabled/
sudo rm /etc/nginx/sites-enabled/default
sudo nginx -t && sudo systemctl reload nginx

sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enable

sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d seu-dominio.com.br -d www.seu-dominio.com.br
```

A remoção do site `default` apaga apenas o atalho para a página padrão do Nginx, que de outro modo responderia por qualquer acesso feito pelo IP. As regras do firewall e como não perder o acesso SSH ao ligar o UFW estão no guia de [firewall UFW](https://streethosting.com.br/guias/vps/firewall-ufw-vps-ubuntu).

O Certbot adiciona o bloco HTTPS e o redirecionamento sozinho, e a renovação é automática. Cabeçalhos extras de segurança e o teste de renovação estão no guia de [certificado SSL com Let's Encrypt](https://streethosting.com.br/guias/vps/certificado-ssl-vps-lets-encrypt-nginx). O `client_max_body_size` libera uploads maiores no Nginx, mas o PHP tem limites próprios: `upload_max_filesize` (2 MB por padrão) e `post_max_size` (8 MB), em `/etc/php/8.3/fpm/php.ini`. Depois de mudar, recarregue o PHP FPM.

## Filas, agendador e deploy

Se a aplicação usa filas para enviar emails ou processar tarefas pesadas, alguém precisa rodar o worker o tempo todo. Uma unidade systemd resolve sem instalar nada:

```
sudo nano /etc/systemd/system/meu-app-fila.service

[Unit]
Description=Worker de filas do meu-app
After=network.target mariadb.service

[Service]
User=www-data
Group=www-data
WorkingDirectory=/var/www/meu-app
ExecStart=/usr/bin/php artisan queue:work --sleep=3 --tries=3 --max-time=3600
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target

sudo systemctl daemon-reload
sudo systemctl enable --now meu-app-fila
```

O `Restart=always` é proposital. O `--max-time` faz o worker encerrar a cada hora para liberar memória acumulada, e o `queue:restart` do deploy também o encerra de propósito. Nos dois casos a saída é normal, e só `always` garante que ele volte.

O agendador do Laravel precisa de uma única entrada de cron, rodando a cada minuto como `www-data`. Abra com `sudo crontab -u www-data -e` e adicione a linha abaixo. A sintaxe do cron e como depurar tarefas que não rodam estão no guia de [cron e tarefas agendadas](https://streethosting.com.br/guias/vps/configurar-cron-tarefas-agendadas-vps).

```
* * * * * cd /var/www/meu-app && php artisan schedule:run >> /dev/null 2>&1
```

### Script de deploy

Atualizar à mão, na ordem certa, toda vez, é onde nascem os erros. Salve este script como `/var/www/meu-app/deploy.sh` e rode com o seu usuário:

```
#!/usr/bin/env bash
set -e
umask 022
cd /var/www/meu-app

php artisan down
git pull origin main
composer install --no-dev --optimize-autoloader
npm ci && npm run build
php artisan migrate --force
php artisan optimize
php artisan queue:restart
sudo systemctl reload php8.3-fpm
php artisan up
```

O `set -e` interrompe o script no primeiro erro. Isso evita migrar um banco com código quebrado, mas deixa o site em manutenção: corrija o problema e rode `php artisan up`. O `umask 022` garante que os arquivos novos trazidos pelo git e pelo Composer nasçam sem escrita para o grupo, mantendo a regra de que o PHP só lê o código. O reload do PHP FPM limpa o OPcache, que guarda o código compilado em memória, para que a versão nova valha na hora. Para rodar o deploy a cada push, basta o seu CI abrir uma conexão SSH e chamar esse mesmo script.

## Erros comuns e desempenho do PHP FPM

| Sintoma | Causa provável | Como resolver |
| --- | --- | --- |
| Erro 500 com Permission denied no log | PHP sem escrita em storage ou bootstrap/cache | Refaça as regras de setfacl nas duas pastas |
| No application encryption key | APP_KEY vazia no .env | Rode php artisan key:generate e depois optimize |
| 502 Bad Gateway | PHP FPM parado ou caminho do socket errado | Confira se o serviço do PHP FPM está ativo e o caminho em fastcgi_pass |
| Mudança no .env não aparece | Configuração em cache | Rode php artisan optimize de novo |
| Página em branco ou 404 em todas as rotas | Nginx apontando para a raiz em vez de public | Corrija o root e recarregue o Nginx |
| Links e assets com http | APP_URL errada ou proxy na frente sem confiança | Corrija APP_URL e configure os proxies confiáveis |

O primeiro lugar para olhar em qualquer erro é `storage/logs/laravel.log`. Se ele não mostrar nada, o problema aconteceu antes do Laravel, e a resposta está em `/var/log/nginx/error.log`. No caso de proxy na frente, como CDN, os proxies confiáveis ficam em `bootstrap/app.php`, no método `trustProxies` do middleware.

### Quantos processos o PHP FPM deve ter

O pool padrão do Ubuntu permite no máximo 5 processos PHP simultâneos, definido em `pm.max_children` no arquivo `/etc/php/8.3/fpm/pool.d/www.conf`. Com tráfego, a sexta requisição simultânea espera na fila e o site parece lento mesmo com CPU sobrando. Não chute o número: meça quanto cada processo ocupa depois de algum uso real.

```
ps --no-headers -o rss -C php-fpm8.3 | awk '{s+=$1} END {print s/NR/1024 " MB por processo"}'
```

Divida a memória que sobra para o PHP, depois de descontar banco, Redis e sistema, por esse valor. Se sobram 2 GB e cada processo usa cerca de 60 MB, um limite perto de 30 é seguro. Acima da conta, a VPS passa a usar swap e tudo fica mais lento. Recarregue com `sudo systemctl reload php8.3-fpm` após a mudança.

> **Dica**
>
> Se a aplicação usa cache e sessões no banco, o padrão das versões recentes do Laravel, trocar esses dois para Redis alivia o MariaDB em sites com muitas visitas.

## Qual VPS escolher para Laravel

O PHP FPM atende cada requisição em um processo separado, então vários vCPUs permitem atender mais visitantes ao mesmo tempo. Por isso a [VPS Xeon](https://streethosting.com.br/vps/xeon), que entrega mais vCPU por real, é a indicação principal para a maioria dos projetos Laravel. Quando o gargalo é o tempo de cada requisição, como relatórios pesados ou muita lógica por página, o clock alto da linha Ryzen 9 9950X ajuda mais. As duas estão na página de [planos de VPS](https://streethosting.com.br/vps).

| Cenário | Plano sugerido | Preço mensal |
| --- | --- | --- |
| Site pequeno ou ambiente de testes | Xeon 2 vCPU, 2 GB DDR4, 20 GB NVMe | R$ 23,00 |
| Site Laravel com MariaDB | Xeon 3 vCPU, 4 GB DDR4, 40 GB NVMe | R$ 40,00 |
| Loja ou SaaS com filas e Redis | Xeon 6 vCPU, 8 GB DDR4, 80 GB NVMe | R$ 74,00 |
| Vários projetos ou tráfego alto | Xeon 9 vCPU, 16 GB DDR4, 160 GB NVMe | R$ 142,00 |
| Requisições pesadas, prioridade em clock | Ryzen 2 vCPU, 4 GB DDR5, 40 GB NVMe | R$ 64,00 |

Todas ficam em São Paulo, com AntiDDoS incluso, disco NVMe, acesso root e ativação em até 60 segundos. Se o site crescer, o upgrade pelo painel cobra só a diferença proporcional e exige um reinício da VM; depois, refaça a conta do `pm.max_children` com a nova memória.

- [ ] PHP 8.3 FPM com as extensões do Laravel
- [ ] Banco e usuário exclusivos com utf8mb4
- [ ] APP_ENV=production e APP_DEBUG=false
- [ ] Escrita do PHP só em storage e bootstrap/cache
- [ ] Nginx com root na pasta public
- [ ] HTTPS com Certbot e UFW liberando só SSH, 80 e 443
- [ ] Worker de filas no systemd e agendador no cron
- [ ] pm.max_children calculado pela memória real

## Perguntas frequentes

### Qual versão do PHP usar para Laravel na VPS?

O Laravel 13 exige PHP 8.3 e o Laravel 12 aceita PHP 8.2 ou mais novo. O Ubuntu 24.04 traz o PHP 8.3 no repositório padrão, o que atende as duas versões sem repositório externo. O Ubuntu 22.04 traz o PHP 8.1, que já não serve para as versões atuais.

### Posso usar SQLite em vez de MariaDB em produção?

Pode, para sites pequenos com pouca escrita simultânea. O Laravel já vem configurado com SQLite, e ele dispensa servidor de banco. Quando há muitos usuários gravando ao mesmo tempo, filas pesadas ou mais de uma aplicação acessando os dados, MariaDB ou PostgreSQL lidam melhor com a concorrência.

### Por que o Laravel dá erro 500 logo depois do deploy?

As causas mais comuns são falta de permissão de escrita em storage ou bootstrap/cache, APP_KEY vazia no .env e cache de configuração antigo. O motivo exato aparece em storage/logs/laravel.log e no log de erros do Nginx.

### Preciso instalar o Supervisor para as filas?

Não é obrigatório. A documentação do Laravel usa o Supervisor como exemplo, mas o systemd, que já vem no Ubuntu, faz o mesmo papel: mantém o worker rodando, reinicia quando ele encerra e guarda os logs.

### Quanto de RAM uma aplicação Laravel precisa?

Um site Laravel pequeno com MariaDB na mesma VPS roda bem com 2 GB. Com filas, Redis e mais tráfego, 4 GB dão folga. O que mais pesa é o número de processos do PHP FPM, porque cada um ocupa dezenas de MB; meça o consumo real antes de aumentar esse limite.

## Guias relacionados

- [Como instalar MariaDB ou MySQL numa VPS Ubuntu](https://streethosting.com.br/guias/vps/instalar-mariadb-mysql-vps-ubuntu.md)
- [Certificado SSL na VPS com Let's Encrypt e Nginx](https://streethosting.com.br/guias/vps/certificado-ssl-vps-lets-encrypt-nginx.md)
- [Como agendar tarefas na VPS com cron](https://streethosting.com.br/guias/vps/configurar-cron-tarefas-agendadas-vps.md)
- [Como instalar e configurar Redis na VPS Ubuntu](https://streethosting.com.br/guias/vps/configurar-redis-vps-ubuntu.md)
- [Hospedar WordPress na VPS: Nginx, PHP 8.3 e MariaDB](https://streethosting.com.br/guias/vps/hospedar-wordpress-vps-nginx.md)

## Produtos citados

- https://streethosting.com.br/vps/xeon
- https://streethosting.com.br/vps

## Dados estruturados

```json
[
  {
    "@context": "https://schema.org",
    "@type": [
      "Article",
      "TechArticle"
    ],
    "headline": "Laravel na sua VPS: PHP FPM, banco, permissões e HTTPS sem erro 500",
    "name": "Como hospedar Laravel na VPS com Nginx, PHP 8.3 e MariaDB",
    "abstract": "Do servidor zerado ao Laravel respondendo em HTTPS: PHP 8.3 FPM do Ubuntu 24.04, Composer, MariaDB, permissões de storage e bootstrap/cache, Nginx no formato oficial, filas com systemd e um script de deploy.",
    "description": "Hospede Laravel na VPS Ubuntu 24.04: PHP 8.3 FPM, Composer, MariaDB, permissões certas em storage, Nginx com HTTPS, filas, agendador e deploy.",
    "datePublished": "2026-09-28",
    "dateModified": "2026-09-28",
    "author": {
      "@type": "Organization",
      "name": "Equipe StreetHosting"
    },
    "publisher": {
      "@type": "Organization",
      "name": "StreetHosting",
      "url": "https://streethosting.com.br"
    },
    "inLanguage": "pt-BR",
    "mainEntityOfPage": {
      "@type": "WebPage",
      "@id": "https://streethosting.com.br/guias/vps/hospedar-laravel-vps"
    }
  },
  {
    "@context": "https://schema.org",
    "@type": "FAQPage",
    "mainEntity": [
      {
        "@type": "Question",
        "name": "Qual versão do PHP usar para Laravel na VPS?",
        "acceptedAnswer": {
          "@type": "Answer",
          "text": "O Laravel 13 exige PHP 8.3 e o Laravel 12 aceita PHP 8.2 ou mais novo. O Ubuntu 24.04 traz o PHP 8.3 no repositório padrão, o que atende as duas versões sem repositório externo. O Ubuntu 22.04 traz o PHP 8.1, que já não serve para as versões atuais."
        }
      },
      {
        "@type": "Question",
        "name": "Posso usar SQLite em vez de MariaDB em produção?",
        "acceptedAnswer": {
          "@type": "Answer",
          "text": "Pode, para sites pequenos com pouca escrita simultânea. O Laravel já vem configurado com SQLite, e ele dispensa servidor de banco. Quando há muitos usuários gravando ao mesmo tempo, filas pesadas ou mais de uma aplicação acessando os dados, MariaDB ou PostgreSQL lidam melhor com a concorrência."
        }
      },
      {
        "@type": "Question",
        "name": "Por que o Laravel dá erro 500 logo depois do deploy?",
        "acceptedAnswer": {
          "@type": "Answer",
          "text": "As causas mais comuns são falta de permissão de escrita em storage ou bootstrap/cache, APP_KEY vazia no .env e cache de configuração antigo. O motivo exato aparece em storage/logs/laravel.log e no log de erros do Nginx."
        }
      },
      {
        "@type": "Question",
        "name": "Preciso instalar o Supervisor para as filas?",
        "acceptedAnswer": {
          "@type": "Answer",
          "text": "Não é obrigatório. A documentação do Laravel usa o Supervisor como exemplo, mas o systemd, que já vem no Ubuntu, faz o mesmo papel: mantém o worker rodando, reinicia quando ele encerra e guarda os logs."
        }
      },
      {
        "@type": "Question",
        "name": "Quanto de RAM uma aplicação Laravel precisa?",
        "acceptedAnswer": {
          "@type": "Answer",
          "text": "Um site Laravel pequeno com MariaDB na mesma VPS roda bem com 2 GB. Com filas, Redis e mais tráfego, 4 GB dão folga. O que mais pesa é o número de processos do PHP FPM, porque cada um ocupa dezenas de MB; meça o consumo real antes de aumentar esse limite."
        }
      }
    ]
  }
]
```
