CentOS Server Preparation
This guide prepares a fresh CentOS server to run a Django project in production using uWSGI and Nginx.
Access the Server
Set permissions on your SSH private key and connect to the server:
chmod 400 file_name.pem
ssh -i path-to-your-key.pem ec2-user@your-server-ip
Initial System Setup
Update packages:
sudo dnf -y update
Enable the extra package repositories and install build tools:
sudo dnf -y install epel-release
sudo dnf config-manager --set-enabled crb
sudo dnf -y groupinstall "Development Tools"
Install base tools:
sudo dnf -y install nano wget git nginx gcc cmake curl firewalld policycoreutils-python-utils
Enable Nginx at boot and start it now:
sudo systemctl enable --now nginx
Enable and start firewall:
sudo systemctl enable --now firewalld
Allow HTTP and HTTPS through the firewall:
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload
sudo firewall-cmd --list-all
Optional: Passwordless Sudo
Open the sudoers file safely:
sudo EDITOR=nano visudo
Add this line at the bottom (replace username):
username ALL=(ALL) NOPASSWD: ALL
Generate SSH Keys (ED25519)
Generate a dedicated SSH key on the server and add it to the SSH agent:
ssh-keygen -t ed25519 -a 100 -C "shahed@aws-server" -f ~/.ssh/id_ed25519_[project_name]
Optional: configure SSH for GitHub key selection:
nano ~/.ssh/config
Host *
AddKeysToAgent yes
Host github-[project_name]
HostName github.com
User git
IdentityFile ~/.ssh/id_rsa_[project_name]
Optional: add your local public key to the server authorized keys:
sudo nano ~/.ssh/authorized_keys
Install Dependencies
sudo dnf -y install bzip2-devel cairo cairo-devel cryptopp-devel \
expat-devel gdal gdal-devel libffi-devel libpcap-devel libcurl-devel \
libxml2-devel ncurses-devel openssl-devel proj proj-devel python3-devel \
pango pango-devel readline-devel sqlite sqlite-devel tk-devel \
xz-devel xerces-c-devel zlib-devel gcc python3 python3-pip
If you need Python 3.8.15 specifically, build it from source:
cd /tmp/ && wget https://www.python.org/ftp/python/3.8.15/Python-3.8.15.tgz &&
tar xzf Python-3.8.15.tgz && cd Python-3.8.15 && ./configure --enable-optimizations &&
make && sudo make altinstall && python3.8 --version
If your project uses PostgreSQL client libraries, also install:
sudo dnf -y install postgresql-devel
Configure Django Environment
Create an environment file:
nano /var/www/myproject/.env
Example values:
DEBUG=False
SECRET_KEY=change-me
ALLOWED_HOSTS=example.com,www.example.com
DATABASE_URL=postgres://user:password@127.0.0.1:5432/dbname
Make sure your Django settings load these values (for example with
python-decouple or django-environ).
Run Django Production Tasks
cd /var/www/myproject
source venv/bin/activate
python manage.py migrate
python manage.py collectstatic --noinput
python manage.py check --deploy
Configure uWSGI Service
Create a systemd unit file:
sudo nano /etc/systemd/system/uwsgi-myproject.service
Use this template (replace myproject and config.wsgi):
[Unit]
Description=uWSGI daemon for Django project
After=network.target
[Service]
User=django
Group=nginx
WorkingDirectory=/var/www/myproject
EnvironmentFile=/var/www/myproject/.env
RuntimeDirectory=uwsgi
RuntimeDirectoryMode=0755
ExecStart=/var/www/myproject/venv/bin/uwsgi \
--master \
--processes 3 \
--chdir /var/www/myproject \
--module config.wsgi:application \
--home /var/www/myproject/venv \
--socket /run/uwsgi/myproject.sock \
--chmod-socket=660 \
--vacuum \
--die-on-term
Restart=always
KillSignal=SIGQUIT
Type=simple
[Install]
WantedBy=multi-user.target
Enable and start uWSGI:
sudo systemctl daemon-reload
sudo systemctl enable --now uwsgi-myproject
sudo systemctl status uwsgi-myproject
Configure Nginx
Create Nginx server config:
sudo nano /etc/nginx/conf.d/myproject.conf
Example configuration:
server {
listen 80;
server_name example.com www.example.com;
location /static/ {
alias /var/www/myproject/static/;
}
location / {
include uwsgi_params;
uwsgi_pass unix:/run/uwsgi/myproject.sock;
}
}
Test and start Nginx:
sudo nginx -t
Install Certbot (Let’s Encrypt)
Install Certbot using Snap and issue certificates with the Nginx plugin:
sudo dnf install snapd -y
sudo systemctl enable --now snapd.socket
sudo ln -s /var/lib/snapd/snap /snap
sudo snap install core
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot
sudo certbot --nginx
Firewall and SELinux
Allow HTTP/HTTPS:
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload
sudo firewall-cmd --list-all
Allow Nginx to connect to uWSGI through socket/proxy:
sudo setsebool -P httpd_can_network_connect 1
Validate Server Health
After deployment, verify the core service layers before handing traffic to the application.
sudo systemctl status nginx
sudo systemctl status uwsgi-myproject
sudo journalctl -u uwsgi-myproject -n 50 --no-pager
curl -I http://127.0.0.1/
Check resource pressure and availability:
uptime
free -h
df -h
top
If your application exposes a dedicated health endpoint, use it for automated checks and load balancer probes:
curl -f https://example.com/health/