AWS

Getting Started with Ansible: Your First Automated Deployment

If you’ve ever found yourself manually configuring servers, installing packages, or deploying applications across multiple machines, you know how tedious and error-prone this process can be. Enter Ansible – a powerful automation tool that can transform your infrastructure management from a manual chore into an elegant, repeatable process. What is Ansible? Ansible is an open-source automation platform that simplifies complex tasks such as configuration management, application deployment, and orchestration. Unlike other automation tools, Ansible is agentless, which means you don’t need to install any software on the machines you want to manage. Furthermore, it uses SSH for Linux/Unix systems and WinRM for Windows, making it lightweight and easy to adopt. As a result, teams can implement automation quickly and efficiently. Why Choose Ansible? Simple and Human-Readable: Ansible uses YAML syntax, which reads almost like plain English. No complex programming knowledge required. Agentless Architecture: No need to install agents on target machines – just SSH access is enough. Idempotent Operations: Run the same playbook multiple times safely. Ansible only makes changes when necessary. Extensive Module Library: Over 3,000+ modules covering everything from cloud providers to network devices. Installing Ansible Let’s get Ansible installed on your control machine (the computer you’ll run Ansible from). On Ubuntu/Debian: sudo apt update sudo apt install ansible CentOS/RHEL: sudo yum install epel-release sudo yum install ansible macOS: brew install ansible Using pip (any OS): pip install ansible Verify your installation: ansible –version Key Concepts Before diving into our first deployment, let’s understand some core concepts: Inventory: A file that defines the hosts and groups of hosts you want to manage. Playbooks: YAML files containing a series of tasks to execute on your hosts. Tasks: Individual actions like installing packages, copying files, or starting services. Modules: Pre-built code that performs specific tasks (like apt package management or copy file operations). Roles: Reusable collections of tasks, files, templates, and variables. Setting Up Your First Project Let’s create a simple project structure: mkdir ansible-tutorial cd ansible-tutorial mkdir -p group_vars host_vars roles touch inventory.ini ansible.cfg site.yml Your directory should look like this: ansible-tutorial/ ├── ansible.cfg ├── group_vars/ ├── host_vars/ ├── inventory.ini ├── roles/ └── site.yml Creating Your Inventory The inventory file tells Ansible which servers to manage. Create a simple inventory.ini: [webservers]web1 ansible_host=192.168.1.100 ansible_user=ubuntuweb2 ansible_host=192.168.1.101 ansible_user=ubuntu#webservers databases[databases]db1 ansible_host=192.168.1.200 ansible_user=ubuntu[production:children] This inventory defines: Your First Playbook Now let’s create a playbook to deploy a simple web application. Edit site.yml: — – name: Deploy Simple Web Application hosts: webservers become: yes vars: app_name: “my-web-app” app_port: 8080 tasks: – name: Update package cache apt: update_cache: yes cache_valid_time: 3600 – name: Install required packages apt: name: – nginx – python3 – python3-pip – git state: present – name: Create application directory file: path: “/opt/{{ app_name }}” state: directory owner: www-data group: www-data mode: ‘0755’ – name: Clone application repository git: repo: “https://github.com/your-username/simple-flask-app.git” dest: “/opt/{{ app_name }}” version: main notify: restart application – name: Install Python dependencies pip: requirements: “/opt/{{ app_name }}/requirements.txt” executable: pip3 – name: Create systemd service file template: src: app.service.j2 dest: “/etc/systemd/system/{{ app_name }}.service” notify: restart application – name: Configure Nginx template: src: nginx.conf.j2 dest: “/etc/nginx/sites-available/{{ app_name }}” notify: restart nginx – name: Enable Nginx site file: src: “/etc/nginx/sites-available/{{ app_name }}” dest: “/etc/nginx/sites-enabled/{{ app_name }}” state: link notify: restart nginx – name: Start and enable services systemd: name: “{{ item }}” state: started enabled: yes daemon_reload: yes loop: – “{{ app_name }}” – nginx handlers: – name: restart application systemd: name: “{{ app_name }}” state: restarted – name: restart nginx systemd: name: nginx state: restarted Creating Templates Ansible uses Jinja2 templates to create dynamic configuration files. Create a templates directory and add these files: templates/app.service.j2 [Unit] Description={{ app_name }} Web Application After=network.target [Service] User=www-data Group=www-data WorkingDirectory=/opt/{{ app_name }} ExecStart=/usr/bin/python3 app.py Restart=always RestartSec=3 [Install] WantedBy=multi-user.target templates/nginx.conf.j2 server { listen 80; server_name {{ ansible_host }}; location / { proxy_pass http://127.0.0.1:{{ app_port }}; 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; } } Configuration File Create an ansible.cfg file to set some defaults: [defaults]inventory = inventory.inihost_key_checking = Falseretry_files_enabled = Falsestdout_callback = yaml[ssh_connection]pipelining = True Running Your First Deployment Before running the full playbook, test connectivity to your hosts: ansible all -m ping If that works, you can run your playbook: ansible-playbook site.yml For a dry run to see what would change without actually making changes: ansible-playbook site.yml –check To run only specific tasks with tags: ansible-playbook site.yml –tags “packages” Advanced Tips Using Vault for Secrets Never store passwords or API keys in plain text. Use Ansible Vault: ansible-vault create group_vars/all/vault.yml Organizing with Roles For larger projects, organize your tasks into roles: ansible-galaxy init roles/webserver This creates a structured role directory with tasks, handlers, templates, and variables. Testing Your Playbooks Consider using tools like Molecule to test your playbooks: pip install molecule[docker] molecule init scenario –driver-name docker Troubleshooting Common Issues SSH Connection Issues: Ensure SSH keys are set up or use –ask-pass the flag. Permission Denied: Use –ask-become-pass for sudo password or configure passwordless sudo. Module Not Found: Check if the required Python modules are installed on target hosts. Idempotency Issues: Always use appropriate modules and parameters to ensure tasks are idempotent. Next Steps Now that you’ve completed your first automated deployment, consider exploring: Conclusion Ansible transforms infrastructure management from a manual, error-prone process into reliable, repeatable automation. With just YAML and SSH, you can manage everything from a single server to thousands of machines across multiple cloud providers. Start small, automate one task at a time, and gradually build more complex playbooks. Before you know it, you’ll wonder how you ever managed infrastructure without Ansible.

Getting Started with Ansible: Your First Automated Deployment Read More »

Flat-style illustration showing a laptop with the Django logo, surrounded by Ubuntu, AWS, Nginx, and Gunicorn icons, representing Django project deployment on AWS EC2 with Ubuntu, Gunicorn, and Nginx.

How to Deploy a Django Project on AWS EC2 with Ubuntu, Gunicorn, and Nginx

Deploying a Django project to a live server can be challenging, especially for the first time. In this guide, I’ll walk you through a clear, step-by-step process to deploy your Django application on an AWS EC2 instance using Ubuntu, Gunicorn, and Nginx. Step 1: Install Required Packages Update the package and the Linux sudo apt update && sudo apt upgrade -y Install Python Nginx dependencies: sudo apt install python3-pip python3-venv python3-dev libpq-dev nginx curl git -y Step 2: Create a Virtual Environment and Activate python3 -m venv myenv source myenv/bin/activate Step 3: Clone or Upload Your Django Project Clone your project to AWS. Generally, the AWS user name is Ubuntu git clone https://github.com/ubuntu/yourproject.git cd yourproject Install all the project’s libraries: pip install -r requirements.txt Step 4: Configure Django Settings Add your EC2 IP or domain in ALLOWED_HOSTS like this ALLOWED_HOSTS = [‘aws-ec2-ip’, ‘yourdomain.com’] Step 5: Install PostgreSQL on Ubuntu sudo apt update sudo apt install postgresql postgresql-contrib -y Check PostgreSQL Status and Start PostgreSQL sudo systemctl status postgresql sudo systemctl start postgresql Switch to the postgres User and create a Database sudo -i -u postgres psql \l create database CREATE DATABASE ensdb; –set password ALTER USER postgres WITH PASSWORD ‘new_secure_password’; Exit psql and the user: \q exit Step 4: Migrate and collect static files python3 manage.py makemigrations python3 manage.py migrate #now collaect all static files python3 manage.py collectstatic Create a superuser for the django admin python3 manage.py createsuperuser Step 5: Install & Run Gunicorn pip install gunicorn Run Gunicorn and verify it’s working : gunicorn –workers 3 myproject.wsgi:application Test it by accessing http://your-ec2-ip:8000 if Gunicorn runs. Step 6: Run Gunicorn in the Background with Systemd Create a socket file sudo nano /etc/systemd/system/gunicorn.socket Please copy and paste the code below into the socket file and save it [Unit] Description=gunicorn socket [Socket] ListenStream=/run/gunicorn.sock [Install] WantedBy=sockets.target Now, create a service file sudo nano /etc/systemd/system/gunicorn.service Be careful with the socket file because your project depends on this configuration. Make sure your path to the project is correct [Unit] Description=gunicorn daemon Requires=gunicorn.socket After=network.target [Service] User=root Group=www-data WorkingDirectory=/home/ubuntu/project-dir/myproject ExecStart=/home/ubuntu/project-dir/env/bin/gunicorn \ –access-logfile – \ –workers 3 \ –bind unix:/run/gunicorn.sock \ myproject.wsgi:application [Install] WantedBy=multi-user.target myproject is inside the project dir, that’s why my env is inside it. For any error, comment me, and I will help you out Enable and start it: sudo systemctl start gunicorn.socket sudo systemctl enable gunicorn.socke Restart Gunicorn and check the status: sudo systemctl daemon-reload sudo systemctl restart gunicorn sudo systemctl status gunicorn Step 7: Set up Nginx We have already installed nginx, now it is time to configure it sudo nano /etc/nginx/sites-available/myproject server { listen 80; server_name mysite.com; location = /favicon.ico { access_log off; log_not_found off; } location /static/ { alias /home/ubuntu/project-dir/myproject/myproject/static/; } location /media/ { alias /home/ubuntu/project-dir/myproject/media/; } location / { include proxy_params; proxy_pass http://unix:/run/gunicorn.sock; } } Run the commands to create a symlink and allow nginx to fully sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled sudo nginx -t sudo systemctl restart nginx sudo ufw allow ‘Nginx Full’ Open the Nginx configuration file sudo nano /etc/nginx/nginx.conf Edit the user directive, Find the top line that looks like: user www-data; Change it to your desired user (e.g., ubuntu): user ubuntu; Check if your user has permission Ensure the user you set has permission to access: Test Nginx configuration sudo nginx -t Comment below if you have an issue with deployment, and I will help you Get Lifetime Free SSL: To get a free SSL certificate, create a Cloudflare account and configure your DNS records there

How to Deploy a Django Project on AWS EC2 with Ubuntu, Gunicorn, and Nginx Read More »

Scroll to Top