Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New tutorial: How to setup a Nginx webserver using ansible on Ubuntu #1032

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
342 changes: 342 additions & 0 deletions tutorials/devops-recipe-using-ansible-to-build-a-web-server/01.en.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,342 @@
---
SPDX-License-Identifier: MIT
path: "/tutorials/devops-recipe-using-ansible-to-build-a-web-server"
slug: "devops-recipe-using-ansible-to-build-a-web-server"
date: "2024-12-28"
title: "How to setup a Nginx webserver using ansible on Ubuntu"
short_description: "This tutorial is for beginner DevOps enthusiasts and it illustrate how to simple setup a Nginx web server, install Docker,
DockerCompose and configure a Let’s Encrypt certificate managed by Certbot"
tags: ["Ansible", "Docker", "Nginx", "Certbot"]
author: "Sergiu Chilat"
author_link: "https://github.com/sergiuchilat"
author_img: "https://avatars.githubusercontent.com/u/14886372"
author_description: "IT enthusiast for almost 20 years:)"
language: "en"
available_languages: ["en"]
header_img: "header-4"
cta: "dedicated"
---
## Introduction

This tutorial is for beginner DevOps enthusiasts and it illustrate how to simple setup a Nginx web server, install Docker,
DockerCompose and configure a Let’s Encrypt certificate managed by Certbot.
The proposed solution is based on Ansible playbooks.

**Prerequisites**

- Create a VPS instance using this [tutorial](https://docs.hetzner.com/cloud/servers/getting-started/creating-a-server/)
- Add your public key to your remote VPS. A simple tutorial can be found [here](https://community.hetzner.com/tutorials/add-ssh-key-to-your-hetzner-cloud)

## Before you start

### Configure Ansible configuration file

Here you can set the inventory file that will be used by Ansible by default when running the playbooks.

``./ansible.cfg``

```ini
[defaults]
inventory = inventory
```

### Configure Ansible inventory

Here you can add the IP addresses of the servers that you want to configure.

``./inventory``

```ini
[all]
127.0.0.1
127.0.0.2
127.0.0.3
```

### Configure the environment variables
This project uses some variables that are stored in the ``env.yml`` file that is imported in all playbooks.

``./env.yml``

```yaml
APP_USERNAME: "super_user"
APP_USER_PASSWORD: "strong password"
APP_MAIN_DOMAIN: "domain.com"
LETS_ENCRYPT_EMAIL: "[email protected]"
NGINX_MAX_BODY_SIZE: "50M"
TIMEZONE: "Europe/Chisinau"
```

* APP_USERNAME: `super_user` - the username of the user that will be created on the server
* APP_USER_PASSWORD: `strong password` - the password of the user that will be created on the server
* APP_MAIN_DOMAIN: `domain.com` - the main domain that will be used for the server
* LETS_ENCRYPT_EMAIL: `[email protected]` - the email that will be used for the Let's Encrypt certificate generation
* NGINX_MAX_BODY_SIZE: `50M` - the maximum body size that Nginx will accept
* TIMEZONE: `Europe/Chisinau` - the timezone that will be set on the server

## Step 1 - Configure the web sever

In this sample the timezone of the server is set to ``TIMEZONE`` variable. This playbook can be extended to set other configurations as well, depending on your needs.

``./playbooks/configure-server.yml``

```yaml
- name: Set the system timezone
hosts: all
become: yes
user: root

vars_files:
- ../env.yml

tasks:
- name: Set timezone
ansible.builtin.command:
cmd: timedatectl set-timezone {{ TIMEZONE }}
```

## Step 2 - Install and configure Nginx

In this step we will install Nginx and configure it to serve the main domain.
Below is the code that will install Nginx and configure it to accept a maximum body size of 50M.

``./playbooks/install-nginx.yml``

```yaml
- name: Install Nginx
hosts: all
become: yes
user: root

vars_files:
- ../env.yml

tasks:
- name: Update apt cache
apt:
update_cache: yes

- name: Install nginx
apt:
name: nginx
state: latest

- name: Ensure client_max_body_size is set inside the http block
ansible.builtin.blockinfile:
path: /etc/nginx/nginx.conf
marker: "# {mark} ANSIBLE MANAGED BLOCK"
block: |
client_max_body_size {{ NGINX_MAX_BODY_SIZE }};
insertafter: '^http\s*{'
backup: yes

- name: Reload Nginx to apply changes
ansible.builtin.systemd:
name: nginx
state: reloaded
```


## Step 3 - Install Docker and Docker Compose

The following code will install Docker and Docker compose to your server.

```yaml
- name: Install Docker on Ubuntu
hosts: all
remote_user: root
become: true
vars:
arch_mapping: # Map ansible architecture {{ ansible_architecture }} names to Docker's architecture names
x86_64: amd64
aarch64: arm64

tasks:
- name: Update and upgrade all packages to the latest version
ansible.builtin.apt:
update_cache: true
upgrade: dist
cache_valid_time: 3600

- name: Install required packages
ansible.builtin.apt:
pkg:
- apt-transport-https
- ca-certificates
- curl
- gnupg
- software-properties-common

- name: Create directory for Docker's GPG key
ansible.builtin.file:
path: /etc/apt/keyrings
state: directory
mode: '0755'

- name: Add Docker's official GPG key
ansible.builtin.apt_key:
url: https://download.docker.com/linux/ubuntu/gpg
keyring: /etc/apt/keyrings/docker.gpg
state: present

- name: Print architecture variables
ansible.builtin.debug:
msg: "Architecture: {{ ansible_architecture }}, Codename: {{ ansible_lsb.codename }}"

- name: Add Docker repository
ansible.builtin.apt_repository:
repo: >-
deb [arch={{ arch_mapping[ansible_architecture] | default(ansible_architecture) }}
signed-by=/etc/apt/keyrings/docker.gpg]
https://download.docker.com/linux/ubuntu {{ ansible_lsb.codename }} stable
filename: docker
state: present

- name: Install Docker and related packages
ansible.builtin.apt:
name: "{{ item }}"
state: present
update_cache: true
loop:
- docker-ce
- docker-ce-cli
- containerd.io
- docker-buildx-plugin
- docker-compose-plugin

- name: Add Docker group
ansible.builtin.group:
name: docker
state: present

- name: Add user to Docker group
ansible.builtin.user:
name: "{{ ansible_user }}"
groups: docker
append: true

- name: Enable and start Docker services
ansible.builtin.systemd:
name: "{{ item }}"
enabled: true
state: started
loop:
- docker.service
- containerd.service

```

## Step 4 - Install Certbot and configure Let’s Encrypt certificate

``./playbooks/install-certbot.yml``

The following code will install Certbot and configure a Let's Encrypt certificate for the main domain.

```yaml

- name: Secure the site with Letsencrypt
hosts: all
become: true
user: root

vars_files:
- ../env.yml

vars:
webroot_path: '/var/www/html' # the root path of your site
certbot_source_directory: /usr/local/certbot-src
certbot_executable_path: "{{ certbot_source_directory }}/venv/bin/certbot"
email: "{{ LETS_ENCRYPT_EMAIL }}"
domain: "{{ APP_MAIN_DOMAIN }}"

tasks:
- name: Install required packages for certbot
ansible.builtin.apt:
name:
- python3-venv
- gcc
- libaugeas0
- libssl-dev
- libffi-dev
- ca-certificates
- openssl
- git
- python3-venv

- name: Clone the certbot source directory
ansible.builtin.git:
depth: 1
repo: https://github.com/certbot/certbot
dest: "{{ certbot_source_directory }}"
update: true

- name: Create certbot in virtual environment
ansible.builtin.command: python3 tools/venv.py
args:
chdir: "{{ certbot_source_directory }}"

- name: Generate the SSL certificate
ansible.builtin.command: "{{ certbot_executable_path }} --nginx -d {{ domain }} --non-interactive --agree-tos --email {{ email }}"

- name: Set up automatic renewal
ansible.builtin.cron:
name: "Certbot automatic renewal"
job: "{{ certbot_executable_path }} renew --quiet"
minute: "11"
hour: "11"

```

Variables used in the playbooks can be found in the `env.yml` file:

- LETS_ENCRYPT_EMAIL - the email that will be used for the Let's Encrypt certificate generation
- APP_MAIN_DOMAIN - the main domain that will be used for the server and the Let's Encrypt certificate


## Step 5 - Run the playbooks

To run the playbooks, execute the following commands:

```bash
ansible-playbook ./playbooks/configure-server.yml
ansible-playbook ./playbooks/install-nginx.yml
ansible-playbook ./playbooks/install-docker.yml
ansible-playbook ./playbooks/install-certbot.yml
```
After running the playbooks, you should have a web server running Nginx, Docker, Docker Compose and a Let's Encrypt certificate.


## Conclusion

This tutorial is a simple way to setup a web server using Ansible playbooks. The playbooks can be extended to include more configurations and services.

##### License: MIT

<!--

Contributor's Certificate of Origin

By making a contribution to this project, I certify that:

(a) The contribution was created in whole or in part by me and I have
the right to submit it under the license indicated in the file; or

(b) The contribution is based upon previous work that, to the best of my
knowledge, is covered under an appropriate license and I have the
right under that license to submit that work with modifications,
whether created in whole or in part by me, under the same license
(unless I am permitted to submit under a different license), as
indicated in the file; or

(c) The contribution was provided directly to me by some other person
who certified (a), (b) or (c) and I have not modified it.

(d) I understand and agree that this project and the contribution are
public and that a record of the contribution (including all personal
information I submit with it, including my sign-off) is maintained
indefinitely and may be redistributed consistent with this project
or the license(s) involved.

Signed-off-by: Sergiu Chilat <[email protected]>

-->