1. Pré-requisitos
Para que o seu código vire negócio de forma fluida e sem paradas técnicas, certifique-se de validar os seguintes requisitos:
- Uma conta ativa no painel do Locaweb Cloud.
- Uma chave privada SSH (arquivo .key ou .pem) salva localmente com permissões restritas (chmod 400).
- Uma máquina virtual (VM) ativa rodando Ubuntu 22.04 LTS.
- Uma aplicação Django estruturada com um repositório Git ou arquivos locais.
- Um domínio de site registrado com apontamento do tipo A para o IP público da VM.
Está com dúvidas sobre como começar no Locaweb Cloud? Acesse nosso tutorial de apoio.
2. Configuração da infraestrutura (painel Locaweb Cloud)
Prepare toda a infraestrutura de rede e armazenamento diretamente no painel do Locaweb Cloud antes de abrir o terminal local. A VM só receberá tráfego externo após a liberação das portas.
Passo 1: Criar o disco adicional
- Acesse a Central do Cliente e entre no painel do Locaweb Cloud.
- No menu esquerdo, clique em Armazenamento > Discos > Criar e adicionar disco.
- Preencha o formulário com os dados da sua conta, defina um nome descritivo (ex.: disco-media-django-prod) e escolha a oferta de armazenamento em SSD para garantir alta taxa de leitura e escrita.
Passo 2: Anexar o disco à máquina virtual
- Na listagem de Discos, clique sobre o volume criado.
- Na barra de ferramentas superior direita, clique no ícone Anexar VM.
- Selecione a instância correspondente ao seu projeto Django e deixe o ID do dispositivo em branco para o sistema mapear automaticamente.
Passo 3: Liberar portas com Port Forwarding
Navegue até Rede > IPs Públicos (ou selecione sua VPC), clique no IP alocado e, na aba Encaminhamento de porta (Port Forwarding), adicione as seguintes regras:
| Finalidade | Porta Pública | Porta Privada | Protocolo | VM de Destino |
| HTTP | 80 | 80 | TCP | VM Django |
| HTTPS | 443 | 443 | TCP | VM Django |
| Aplicação Gunicorn | 8000 | 8000 | TCP | VM Django |
| SSH Administrativo | 22 | 22 | TCP | VM Django |
Passo 4: Configurar as regras de Firewall
Na mesma tela do IP público, acesse a aba Firewall e adicione as regras de entrada (inbound) para espelhar as portas liberadas:
| CIDR de Origem | Porta Inicial | Porta Final | Protocolo | Finalidade |
| 0.0.0.0/0 | 80 | 80 | TCP | Acesso público HTTP |
| 0.0.0.0/0 | 443 | 443 | TCP | Acesso público HTTPS |
| 0.0.0.0/0 | 8000 | 8000 | TCP | Validação direta do Gunicorn |
| <SEU_IP_ADMIN>/32 | 22 | 22 | TCP | SSH restrito à sua rede de TI |
3. Configuração do sistema operacional (Terminal Linux)
Passo 1: Identificar e formatar o novo disco
Conecte-se à sua instância via SSH pelo terminal local:
Bash
ssh -i /caminho/sua-chave.key ubuntu@<SEU_IP_PUBLICO>
Localize a designação de barramento atribuída ao novo volume utilizando o comando abaixo:
Bash
# Lista os dispositivos de bloco conectados à instância lsblk
Identificado o disco secundário (ex: /dev/vdb), aplique a formatação utilizando o sistema de arquivos ext4:
Bash
# Cria o sistema de arquivos otimizado no disco adicional sudo mkfs.ext4 /dev/vdb
Passo 2: Configurar a Montagem Persistente (fstab)
Colete o identificador universal (UUID) do novo volume para garantir a segurança da montagem, evitando que letras dinâmicas de barramento causem falhas no boot:
Bash
# Exibe os dados de UUID do bloco formatado sudo blkid /dev/vdb
Crie a pasta física que servirá como ponto de acesso para os uploads do Django:
Bash
sudo mkdir -p /mnt/django_media
Abra o arquivo /etc/fstab e insira a regra de montagem permanente utilizando o UUID coletado:
Bash
# Adiciona a entrada persistente com parâmetros de alta performance (noatime) echo 'UUID=seu-uuid-aqui /mnt/django_media ext4 defaults,nofail,noatime 0 2' | sudo tee -a /etc/fstab
Mande o sistema operacional ler as novas tabelas e ajuste o proprietário do diretório para o usuário de execução web do ecossistema:
Bash
# Monta os volumes declarados e valida a pasta sudo mount -a df -h | grep /mnt/django_media # Atribui a governança da pasta ao usuário www-data de forma recursiva sudo chown -R www-data:www-data /mnt/django_media sudo chmod -R 775 /mnt/django_media
4. Configuração do banco de dados: PostgreSQL
Instale e gerencie o motor do banco de dados relacional localmente para centralizar a operação e mitigar o uso de ferramentas desconexas:
Bash
sudo apt update && sudo apt install -y postgresql postgresql-contrib sudo systemctl enable --now postgresql
Acesse o console administrativo SQL e configure a base de dados do Django:
Bash
sudo -u postgres psql
SQL
-- Comandos executados dentro do shell psql CREATE DATABASE django_app_db; CREATE USER django_user WITH ENCRYPTED PASSWORD '<SENHA_SEGURA>'; -- Ajustes de codificação recomendados para a performance do Django ALTER ROLE django_user SET client_encoding TO 'utf8'; ALTER ROLE django_user SET default_transaction_isolation TO 'read committed'; ALTER ROLE django_user SET timezone TO 'America/Sao_Paulo'; GRANT ALL PRIVILEGES ON DATABASE django_app_db TO django_user; \q
5. Configuração do Django (Python)
Edite o arquivo de parametrização do seu projeto (settings.py), garantindo que o banco aponte para o endereço local (127.0.0.1) e que a rota de mídias aponte diretamente para o ponto de montagem do disco secundário:
Python
# settings.py import os from pathlib import Path BASE_DIR = Path(__file__).resolve().parent.parent SECRET_KEY = os.environ.get('DJANGO_SECRET_KEY') DEBUG = False ALLOWED_HOSTS = ['meusite.com.br', 'www.meusite.com.br', '<SEU_IP_PUBLICO>'] DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql', 'NAME': 'django_app_db', 'USER': 'django_user', 'PASSWORD': os.environ.get('DJANGO_DB_PASSWORD'), 'HOST': '127.0.0.1', 'PORT': '5432', } } # Configuração de mídias amarrada ao disco secundário de dados MEDIA_URL = '/media/' MEDIA_ROOT = '/mnt/django_media/' # Configuração de estáticos para coleta unificada do Nginx STATIC_URL = '/static/' STATIC_ROOT = '/var/www/django_app/static/'
Garantida a estrutura das variáveis, execute os comandos do framework para rodar as migrações iniciais e reunir os componentes estáticos:
Bash
export DJANGO_SECRET_KEY='<SUA_CHAVE_SECRETA>' export DJANGO_DB_PASSWORD='<SENHA_SEGURA>' python manage.py migrate python manage.py collectstatic --noinput
6. Deploy da aplicação
Método 1: Deploy manual com Gunicorn e systemd
Crie o arquivo de unidade de serviço do systemd para gerenciar a resiliência da aplicação:
Bash
sudo nano /etc/systemd/system/gunicorn.service
Ini, TOML
[Unit] Description=Gunicorn servindo a aplicacao Django After=network.target [Service] User=www-data Group=www-data WorkingDirectory=/var/www/django_app Environment="DJANGO_SECRET_KEY=<SUA_CHAVE_SECRETA>" Environment="DJANGO_DB_PASSWORD=<SENHA_SEGURA>" ExecStart=/var/www/django_app/venv/bin/gunicorn --workers 3 --bind 127.0.0.1:8000 projeto.wsgi:application [Install] WantedBy=multi-user.target
Bash
# Recarrega o daemon e inicia o serviço em segundo plano sudo systemctl daemon-reload sudo systemctl enable --now gunicorn
Método 2: Deploy moderno (Docker + GitHub Actions)
Caso utilize contêineres para manter a imutabilidade do ambiente, execute a instalação do Docker e configure o arquivo docker-compose.yml mapeando o volume físico para dentro do container:
YAML
services: web: build: . restart: always ports: - "8000:8000" volumes: # Mapeia o disco secundário para a pasta de mídias do contêiner - /mnt/django_media:/mnt/django_media environment: DJANGO_SECRET_KEY: ${DJANGO_SECRET_KEY} DJANGO_DB_PASSWORD: ${DJANGO_DB_PASSWORD} depends_on: - db db: image: postgres:16-alpine restart: always environment: POSTGRES_DB: django_app_db POSTGRES_USER: django_user POSTGRES_PASSWORD: ${DJANGO_DB_PASSWORD} volumes: - pgdata:/var/lib/postgresql/data volumes: pgdata:
Ative a esteira automatizada salvando o arquivo .github/workflows/deploy.yml no seu repositório Git, vinculando os Secrets de conexão SSH (SSH_HOST, SSH_USER, SSH_KEY) para rodar os comandos de build e migrate de forma 100% self-service a cada push.
7. Configuração do Servidor Web Nginx e HTTPS
O Nginx atuará na borda da infraestrutura para realizar o proxy reverso e entregar os arquivos estáticos diretamente do disco de dados, poupando recursos da aplicação.
Passo 1: Configurar o bloco de servidor
Instale os pacotes e configure o arquivo de virtualhost do Nginx:
Bash
sudo apt install -y nginx certbot python3-certbot-nginx sudo nano /etc/nginx/sites-available/meusite.conf
Nginx
server { listen 80; server_name meusite.com.br www.meusite.com.br; location / { proxy_pass http://127.0.0.1:8000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } # Entrega direta de uploads a partir do disco secundário location /media/ { alias /mnt/django_media/; expires 30d; add_header Cache-Control "public, no-transform"; access_log off; } location /static/ { alias /var/www/django_app/static/; expires 30d; access_log off; } }
Bash
# Ativa o site criando o link simbólico e recarrega o serviço sudo ln -s /etc/nginx/sites-available/meusite.conf /etc/nginx/sites-enabled/ sudo nginx -t sudo systemctl reload nginx
Passo 2: Ativar criptografia SSL Let’s Encrypt
Gere as chaves de segurança digital e configure o redirecionamento automático de tráfego para HTTPS:
Bash
sudo certbot --nginx -d meusite.com.br -d www.meusite.com.br
8. Validação
Teste de escrita e armazenamento
Abra o interpretador de comandos interativo do Django no servidor e valide a gravação de um arquivo simulado no ponto de montagem:
Bash
python manage.py shell
Python
# Executado dentro do shell do Django from django.core.files.base import ContentFile from django.core.files.storage import default_storage path = default_storage.save( "testes/test_file.txt", ContentFile(b"Validacao do disco secundario Locaweb Cloud"), ) print(f"Arquivo salvo com sucesso em: {path}")
Saia do shell e verifique diretamente no terminal do Linux se os dados foram gravados de forma física no volume secundário alocado:
Bash
cat /mnt/django_media/testes/test_file.txt
Teste externo e segurança
Do prompt de comando da sua máquina local, faça requisições externas para verificar a resposta correta via HTTPS e o bloqueio da porta de dados (5432):
Bash
# Deve retornar o status HTTP 200 OK vindo do Nginx curl -I https://meusite.com.br/media/testes/test_file.txt # Deve falhar por timeout, provando que o banco de dados está isolado nc -zv <SEU_IP_PUBLICO> 5432
9. Solução de problemas (Troubleshooting)
- Erro 502 Bad Gateway ao carregar o site: Indica que o Nginx está operacional, mas o serviço do Gunicorn está inativo localmente. Verifique as falhas e saídas executando sudo journalctl -u gunicorn -n 50 –no-pager.
- Os uploads desaparecem após reiniciar a VM: A entrada no arquivo /etc/fstab pode estar incorreta. Execute sudo blkid /dev/vdb para confirmar se o UUID bate exatamente com a linha inserida e use sudo mount -a para restabelecer os pontos de montagem.
- Quedas por timeout ou lentidão em requisições de mídia: Garanta que a governança recursiva do diretório /mnt/django_media esteja amarrada ao usuário web executando sudo chown -R www-data:www-data /mnt/django_media.