Setup react app, python api and mysql database.
sudo apt-get update
-
Create a New Non-Root User:
adduser deployuser usermod -aG sudo deployuser
- This limits root-level access, reducing risks from accidental or malicious changes.
-
Disable Root Login via SSH:
-
Edit
/etc/ssh/sshd_config
:PermitRootLogin no
-
Restart SSH:
systemctl restart ssh
-
-
Use SSH Keys for Authentication:
-
Generate SSH keys locally:
ssh-keygen -t rsa -b 4096
-
Copy the public key to the server:
ssh-copy-id deployuser@your_server_ip
-
Disable password login in/etc/ssh/sshd_config
:~~PasswordAuthentication no~~
#open ssh port sudo ufw allow 22 sudo ufw allow 443 sudo ufw allow 80
to remove port allow
💡sudo ufw delete allow 8089
Note: For now don’t disable password authentication
-
Python 3.10.15
sudo apt-get install python3 python3-dev python3-pip
To clear pip cache
pip cache purge
git clone repo@github.git
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
pip install gunicorn
sudo apt install supervisor
sudo nano /etc/supervisor/conf.d/django.conf
[program:gunicorn]
command=/home/deployuser/api.domain.com/.env/bin/gunicorn core.wsgi:application \
--workers 4 \ # Number of worker processes
--threads 4 \ # Number of threads per worker
--bind 127.0.0.1:8000 \
--timeout 120 # Adjust timeout for long-running requests
directory=/home/deployuser/api.domain.com
user=deployuser
autostart=true
autorestart=true
stdout_logfile=/var/log/gunicorn.log
stderr_logfile=/var/log/gunicorn_err.log
sudo apt install supervisor
sudo supervisorctl reread
sudo supervisorctl update
sudo systemctl restart supervisor
sudo supervisorctl stop gunicorn
sudo tail -f /var/log/gunicorn.log
sudo tail -f /var/log/gunicorn_err.log
https://www.digitalocean.com/community/tutorials/how-to-install-nginx-on-ubuntu-20-04
sudo apt install nginx
sudo nano /etc/nginx/sites-available/api.domain.com
server {
server_name new-api.domain.com;
error_log /home/deployuser/nginx_error.log;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/new-api.domain.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/new-api.domain.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
if ($host = new-api.domain.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
server_name new-api.domain.com;
return 404; # managed by Certbot
}
sudo nano /etc/nginx/sites-available/erp.domain.com
server {
listen 80;
server_name new-erp.domain.com;
root /var/www/erp.domain.com/dist;
index index.html;
location / {
# try_files $uri $uri/ /index.html;
try_files $uri /index.html;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
# add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self';";
}
error_page 404 /index.html;
location ~* \.(?:ico|css|js|gif|jpe?g|png|woff2?|eot|ttf|svg|map|mp4)$ {
expires 6M;
access_log off;
add_header Cache-Control "public";
}
}
sudo ln -s /etc/nginx/sites-available/erp.domain.com /etc/nginx/sites-enabled
sudo ln -s /etc/nginx/sites-available/api.domain.com /etc/nginx/sites-enabled
sudo chown -R www-data:www-data /home/deployuser/api.domain.com
sudo chmod -R 755 /home/deployuser/api.domain.com
cd /home/deployuser/erp.domain.com/ && npm i
sudo /home/deployuser/erp.domain.com/node_modules/vite/bin/vite.js build
sudo chown -R www-data:www-data /home/deployuser/erp.domain.com
sudo chmod -R 755 /home/deployuser/erp.domain.com
sudo systemctl restart nginx
sudo systemctl enable nginx
sudo systemctl reload nginx
sudo tail -f /var/log/nginx/error.log
Certbot install auto add to config file
sudo apt update && sudo apt upgrade -y
sudo apt install --reinstall python3-pip python3-venv python3-setuptools python3-certbot python3-cffi
sudo apt install python3-dev libffi-dev libssl-dev build-essential -y
sudo apt remove --purge certbot python3-certbot -y
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot
sudo certbot --nginx
Certificate is saved at: /etc/letsencrypt/live/new-api.domain.com/fullchain.pem
Key is saved at: /etc/letsencrypt/live/new-api.domain.com/privkey.pem
Certificate is saved at: /etc/letsencrypt/live/new-erp.domain.com/fullchain.pem
Key is saved at: /etc/letsencrypt/live/new-erp.domain.com/privkey.pem
sudo apt install fail2ban
sudo ufw enable
sudo apt install unattended-upgrades
Setup Server like above → here
https://www.cyberciti.biz/faq/how-to-delete-a-ufw-firewall-rule-on-ubuntu-debian-linux/
sudo ufw allow 22
sudo ufw allow 3306
sudo apt update
sudo apt install mysql-server
sudo apt install mysql-client
sudo service mysql start
sudo mysql_secure_installation
sudo mysql -u root -p
CREATE USER 'lg_user'@'ip' IDENTIFIED BY 'newpass';
By default, MySQL binds only to 127.0.0.1
(localhost). To allow remote connections, you need to change the bind address to 0.0.0.0
sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf
bind-address = 0.0.0.0
This allows MySQL to listen for connections on all IP addresses. Save the file and exit the editor.
sudo apt install mysqltuner
sudo mysqltuner
update .my.cnf file
nano ~/.my.cnf
locust -f locustfile.py
Setup VPS
https://github.com/dreamsofcode-io/zenstats/blob/main/docs/vps-setup.md