Antes de começar
sudo apt update
sudo apt upgrade -y
sudo reboot
Criar user, se não existir: sudo useradd $NEW_USER
Então configurar senha: sudo passwd $NEW_USER
não perca a senha nova!!!
1Adicionar novo user ao sudoers
sudo echo "$NEW_USER ALL=(ALL) NOPASSWD:ALL" > "/etc/sudoers.d/config-$NEW_USER-sudo"
2Configure deploy key
ssh-keygen
eval "$(ssh-agent -s)"
ssh-add .ssh/id_ed25519
cat .ssh/id_ed25519.pub
Colocar no repositório em Settings > Deploy Keys.
3Clonar repo
git clone git@github.com:user/repo.git
cd repo
4Configurar virtualenv
Se necessário:
sudo apt install python3-dev python3-venv build-essential gcc g++ pkg-config
Configurar virtualenv:
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
5Config Django
python manage.py migrate
python manage.py createsuperuser
6Config Caddy
sudo apt install caddy
sudo vi /etc/caddy/Caddyfile
sudo systemctl restart caddy
sudo systemctl enable caddy
seudominio.com.br {
log {
output file /var/log/caddy/access.log
format console
}
handle /static/* {
root * /var/staticfiles
file_server
}
handle {
reverse_proxy localhost:8080
}
}
7Arquivos estáticos
sudo mkdir -m 755 /var/staticfiles/
sudo chown ubuntu:ubuntu /var/staticfiles
python manage.py collectstatic
8Configuração swap
sudo fallocate -l 1G /swapfile # trocar tamanho de acordo com a sua memoria
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
swapon --show
9Config unattended-upgrades
sudo apt install unattended-upgrades
Editar /etc/apt/apt.conf.d/20auto-upgrades:
APT::Periodic::Enable "1";
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";
Then enable the schedulers:
sudo systemctl enable --now apt-daily.timer apt-daily-upgrade.timer
Test without installing anything:
sudo unattended-upgrade --dry-run
Your existing /etc/apt/apt.conf.d/50unattended-upgrades already limits automatic installation to Ubuntu and ESM security repositories. Normal noble-updates packages will not be installed automatically, and automatic reboot remains disabled.
10Config UFW
sudo apt install ufw
sudo ufw enable
sudo ufw default allow outgoing
sudo ufw default deny incoming
sudo ufw allow 22
sudo ufw allow 80
sudo ufw allow 443
11Config SSHD
sudo vim /etc/ssh/sshd_config
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
sudo sshd -t
sudo systemctl restart ssh
12Deploy automático com cron
crontab -e
* * * * * /home/ubuntu/repo/scripts/deploy.sh
Para conferir se está rodando: grep CRON /var/log/syslog
Configurar fail2ban
sudo apt install -y fail2ban
sudoedit /etc/fail2ban/jail.d/sshd.local
[DEFAULT]
ignoreip = 127.0.0.1/8 ::1 179.228.151.152
bantime = 1h
findtime = 10m
maxretry = 5
[sshd]
enabled = true
backend = systemd
port = 22
mode = normal
banaction = ufw
Validate and activate it:
sudo fail2ban-client -t
sudo systemctl enable fail2ban
sudo systemctl restart fail2ban
Verify:
sudo systemctl status fail2ban
sudo fail2ban-client status sshd
sudo ufw status numbered
Config service via systemd
Referência: Gunicorn, systemd.
systemd can create a UNIX socket and launch Gunicorn on demand.
Service file
# /etc/systemd/system/gunicorn.service
[Unit]
Description=gunicorn daemon
Requires=gunicorn.socket
After=network.target
[Service]
Type=notify
NotifyAccess=main
User=someuser
Group=someuser
WorkingDirectory=/home/someuser/applicationroot
EnvironmentFile=/var/www/myproject/.env
ExecStart=/usr/bin/gunicorn applicationname.wsgi
ExecReload=/bin/kill -s HUP $MAINPID
KillMode=mixed
TimeoutStopSec=5
PrivateTmp=true
[Install]
WantedBy=multi-user.target
Type=notify lets Gunicorn report readiness to systemd. If the service should run under a transient user consider adding DynamicUser=true. Tighten permissions further with ProtectSystem=strict if the app permits.
Socket activation file
# /etc/systemd/system/gunicorn.socket
[Unit]
Description=gunicorn socket
[Socket]
ListenStream=/run/gunicorn.sock
SocketUser=www-data
SocketGroup=www-data
SocketMode=0660
[Install]
WantedBy=sockets.target
Enable and start the socket so it begins listening immediately and on reboot:
systemctl enable --now gunicorn.socket
Test connectivity from the nginx user (Debian defaults to www-data):
sudo -u www-data curl --unix-socket /run/gunicorn.sock http
Use systemctl show --value -p MainPID gunicorn.service to retrieve the main process ID or systemctl kill -s HUP gunicorn.service to send signals.
Nginx proxy
user www-data;
...
http {
server {
listen 8000;
server_name 127.0.0.1;
location / {
proxy_pass http://unix:/run/gunicorn.sock;
}
}
}
...
Adjust listen and server_name for production (typically port 80 and your site's domain).
systemctl enable nginx.service
systemctl start nginx
Browse to http://127.0.0.1:8000/ to verify Gunicorn + Nginx + systemd.
- Socket vs. Port: In a non-Docker environment, it is often more efficient to bind Gunicorn to a Unix socket (e.g.,
unix:/run/gunicorn.sock) rather than a TCP port to reduce overhead. - Worker Selection: A common rule of thumb for the
--workersflag is(2 x number of cores) + 1.
Banco de dados
sudo apt install mariadb-server
sudo mariadb
CREATE DATABASE cognitrilha;
USE cognitrilha;
CREATE USER 'cognitrilha'@'localhost' IDENTIFIED BY '<sua_senha_aqui>';
GRANT ALL PRIVILEGES ON cognitrilha.* TO 'cognitrilha'@'localhost';
Redis server
sudo apt install redis-server -y
sudo vim /etc/redis/redis.conf
Add lines:
supervised auto
maxmemory 256mb
maxmemory-policy allkeys-lru
sudo systemctl restart redis-server