Ansible Web App Deployment Playbook | Generated by AI

Home 2025.11

Here’s a complete, production-ready Ansible playbook to deploy a Python web application with the exact flow you described:

Git checkout → pip install → gunicorn → nginx reverse proxy
inventory.ini
deploy.yml
roles/
  webapp/
    tasks/
      main.yml
    templates/
      gunicorn.service.j2
      nginx-site.conf.j2
    files/
      (optional static files)
    handlers/
      main.yml

1. inventory.ini

[webservers]
app.example.com ansible_user=ubuntu ansible_ssh_private_key_file=~/.ssh/yourkey.pem

[webservers:vars]
app_name=myflaskapp
app_repo=https://github.com/youruser/myflaskapp.git
app_branch=main
app_port=8000          # internal Gunicorn port
python_version=3.11

2. deploy.yml (main playbook)

---
- name: Deploy Python web application with Gunicorn + Nginx
  hosts: webservers
  become: yes
  vars:
    app_dir: /opt/
    venv_dir: /opt//venv
    requirements_file: "/requirements.txt"

  roles:
    - webapp

3. roles/webapp/tasks/main.yml

---
- name: Install system dependencies
  apt:
    name:
      - git
      - python-venv
      - python
      - python3-pip
      - gunicorn
      - nginx
    state: present
    update_cache: yes

- name: Create application directory
  file:
    path: ""
    state: directory
    owner: www-data
    group: www-data
    mode: '0755'

- name: Clone or update application from Git
  git:
    repo: ""
    dest: ""
    version: ""
    force: yes
    update: yes
  notify: Restart gunicorn

- name: Create Python virtual environment
  pip:
    virtualenv: ""
    virtualenv_python: python

- name: Install Python requirements
  pip:
    requirements: ""
    virtualenv: ""
  notify: Restart gunicorn

- name: Copy Gunicorn systemd service
  template:
    src: gunicorn.service.j2
    dest: /etc/systemd/system/.service
    mode: '0644'
  notify:
    - Reload systemd
    - Restart gunicorn

- name: Enable and start Gunicorn service
  systemd:
    name: ""
    enabled: yes
    state: started
    daemon_reload: yes

- name: Configure Nginx reverse proxy
  template:
    src: nginx-site.conf.j2
    dest: /etc/nginx/sites-available/
    mode: '0644'
  notify: Reload nginx

- name: Enable Nginx site
  file:
    src: /etc/nginx/sites-available/
    dest: /etc/nginx/sites-enabled/
    state: link
  notify: Reload nginx

- name: Remove default Nginx site (optional)
  file:
    path: /etc/nginx/sites-enabled/default
    state: absent
  notify: Reload nginx

4. roles/webapp/templates/gunicorn.service.j2

[Unit]
Description=Gunicorn instance for 
After=network.target

[Service]
User=www-data
Group=www-data
WorkingDirectory=
Environment="PATH=/bin"
ExecStart=/bin/gunicorn --workers 3 --bind unix:/run/.sock app:app
       # or use your wsgi entrypoint, e.g.: main:app or wsgi:app

Restart=always
RestartSec=3

[Install]
WantedBy=multi-user.target

5. roles/webapp/templates/nginx-site.conf.j2

server {
    listen 80;
    server_name _;  # or your domain: app.example.com

    location / {
        include proxy_params;
        proxy_pass http://unix:/run/.sock;
    }

    location /static/ {
        alias /static/;
    }

    # Optional: serve media files
    # location /media/ {
    #     alias /media/;
    # }
}

6. roles/webapp/handlers/main.yml

---
- name: Reload systemd
  systemd:
    daemon_reload: yes

- name: Restart gunicorn
  systemd:
    name: ""
    state: restarted

- name: Reload nginx
  service:
    name: nginx
    state: reloaded

Run the deployment

ansible-playbook -i inventory.ini deploy.yml

Subsequent deployments (zero-downtime)

Just run the same command again. Git pull + pip install will trigger Gunicorn restart automatically thanks to the handlers.

Optional improvements

This playbook is idempotent, secure (runs as www-data), and used in many production environments.


Back

x-ai/grok-4.1-fast

Donate