In this blog post, I’m documenting my step-by-step journey of migrating a production-ready Django application (with Celery and Gunicorn) and setting up a WordPress instance on the same server using Nginx as the web server, PostgreSQL for Django, and MariaDB for WordPress. This guide is ideal for developers looking to consolidate services efficiently on a single Ubuntu-based VPS.
Step 1: Provision the New Server
I created a new Ubuntu server on UpCloud with a public IP and root SSH access. This server would eventually host:
- A Django + Gunicorn + Celery app
- PostgreSQL (for Django)
- Nginx (as reverse proxy)
- MariaDB (for WordPress)
- RabbitMQ as a message broker
- A future WordPress website
Step 2: Migrate Django App with Systemd
My Django project is structured with:
- A virtual environment
- Gunicorn systemd service
- Celery systemd service
I transferred it using rsync
from the old server:
rsync -avz /home/myproject/ user@new-server:/home/myproject/
I copied over the Gunicorn and Celery systemd unit files:
rsync -avz /etc/systemd/system/myproject.service /etc/systemd/system/myprojectcelery.service user@new-server:/etc/systemd/system/
On the new server, I ensured:
- All ownerships and permissions were set
- Python dependencies were installed via
requirements.txt
- The virtual environment was re-created
Then I enabled and started both services:
sudo systemctl daemon-reload
sudo systemctl enable myproject myprojectcelery
sudo systemctl start myproject myprojectcelery
Step 3: Nginx Setup for Django
I configured Nginx to reverse proxy to the Gunicorn socket:
server {
listen 80;
server_name app.example.com;
location /static/ {
alias /home/myproject/static/;
}
location /media/ {
alias /home/myproject/media/;
}
location / {
include proxy_params;
proxy_pass http://unix:/home/myproject/myproject.sock;
}
}
Enabled the site:
ln -s /etc/nginx/sites-available/app.example.com /etc/nginx/sites-enabled/
systemctl reload nginx
Step 4: PostgreSQL Migration for Django
Dumped the DB from old server:
pg_dump -U postgres myprojectdb > /root/myproject.sql
Transferred and restored on new server:
scp /root/myproject.sql user@new-server:/root/
psql -U postgres -c "CREATE DATABASE myprojectdb;"
psql -U postgres myprojectdb < /root/myproject.sql
Granted permissions to the myproject
DB user:
GRANT ALL PRIVILEGES ON DATABASE myprojectdb TO myproject;
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO myproject;
Step 5: Set Up RabbitMQ
RabbitMQ was installed to support Celery as the task queue. Installation on Ubuntu:
sudo apt install rabbitmq-server -y
The broker was configured using environment variables in the Django project, pointing to:
amqp://myuser:mypassword@localhost:5672/myvhost
Access control and users were set up via:
rabbitmqctl add_user myuser mypassword
rabbitmqctl set_user_tags myuser administrator
rabbitmqctl set_permissions -p / myuser ".*" ".*" ".*"
Step 6: Set Up SSL with Let’s Encrypt
apt install certbot python3-certbot-nginx -y
certbot --nginx -d app.example.com
Automatically issued and configured HTTPS with redirection.
Step 7: Add a WordPress Site (MariaDB + Nginx)
Install MariaDB:
apt install mariadb-server mariadb-client -y
mysql_secure_installation
Create DB for WordPress:
CREATE DATABASE wp_db;
CREATE USER 'wp_user'@'localhost' IDENTIFIED BY 'strongpassword';
GRANT ALL PRIVILEGES ON wp_db.* TO 'wp_user'@'localhost';
FLUSH PRIVILEGES;
Install WordPress:
wget https://wordpress.org/latest.tar.gz
mkdir -p /var/www/wordpress
cd /var/www && tar -xzf latest.tar.gz
chown -R www-data:www-data /var/www/wordpress
Configure Nginx for WordPress:
server {
listen 80;
server_name blog.example.com;
root /var/www/wordpress;
index index.php index.html index.htm;
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
}
location ~ /\.ht {
deny all;
}
}
Enable and reload:
ln -s /etc/nginx/sites-available/blog.example.com /etc/nginx/sites-enabled/
systemctl reload nginx
Add SSL:
certbot --nginx -d blog.example.com
Conclusion
Now, my single Ubuntu VPS is successfully running:
- A fully migrated Django app with Gunicorn, Celery, and PostgreSQL
- RabbitMQ as the message broker
- A new WordPress blog with Nginx + MariaDB
- HTTPS for both domains
This setup gives me complete control, performance, and flexibility on a single cost-effective server.
If you’re looking to consolidate your apps or move to a cleaner architecture, this approach works great.
Let me know if you want my full deployment script or CircleCI integration setup next!