Update example webserver post

Update the example webserver to use Leap 15.4 and remove some issues
with the playbook and description.
This commit is contained in:
Felix Niederwanger 2022-06-29 10:15:49 +02:00
parent 717534bdd0
commit 0349adaedf
Signed by: phoenix
GPG key ID: 31860289A704FB3C
9 changed files with 146 additions and 79 deletions

View file

@ -2,65 +2,94 @@
title: "Example: Webserver (nginx+php-fpm)"
author: "phoenix"
date: 2021-03-26T10:49:29+01:00
PublishDate: 2021-03-26T10:49:29+01:00
Lastmod: 2022-06-29T09:56:07+01:00
---
In this post we are going to setup our example `jellyfish` host to run `nginx `and `php-fpm`. The provided [example playbook](jellyfish.yml) should be a good starting point for your own webserver.
In this post we are going to setup our example `jellyfish` host to run `nginx `and `php-fpm`. Checkout the provided [jellyfish.yml](jellyfish.yml) playbook for a quickstart. This example playbook also configures a virtual host and creates a typical `phpinfo.php` file to test your setup.
In addition, the exaple playbook also setups the `jellyfish.conf` nginx virtual host file to run `php` files with `php-fpm` and we create a typical `phpinfo.php` file to test our setup
This provides a solid example to setup your own webserver running `nginx` with `php-fpm` atop which you can later on run other php applications like [nextcloud](https://nextcloud.com/) or [MediaWiki](https://www.mediawiki.org/wiki/MediaWiki).
# Example
## Playbook
This [example playbook](jellyfish.yml) sets up a webserver with `nginx` and `php-fpm`.
The [jellyfish.yml](jellyfish.yml) example playbook sets up a webserver with `nginx` and `php-fpm`:
---
- hosts: jellyfish
user: root
roles:
- role: geekoops-nginx
vars:
config_firewall: true
firewall_zone: "public"
- role: geekoops-php-fpm
vars:
apcu_enable: true
apcu_shm_size: 32M
php_memlimit: 256M
php_maxuploadsize: 64M
tasks:
- name: Deploy jellyfish config for nginx
copy:
content: |
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name jellyfish;
location / {
proxy_pass http://127.0.0.1:3000/;
}
}
dest: "/etc/nginx/vhosts.d/jellyfish.conf"
group: "root"
owner: "root"
mode: 0754
notify: Restart nginx
- name: Deploy phpinfo script
copy:
content: "<?php phpinfo(); phpinfo(INFO_MODULES); ?>"
dest: "/srv/www/phpinfo.php"
group: "www"
owner: "wwwrun"
mode: 0754
handlers:
- name: Restart nginx
systemd:
name: nginx
state: restarted
```yaml
---
- hosts: jellyfish
user: root
# Example
roles:
- role: geekoops-nginx
vars:
config_firewall: true
firewall_zone: "public"
- role: geekoops-php-fpm
vars:
apcu_enable: true
apcu_shm_size: 32M
php_memlimit: 256M
php_maxuploadsize: 64M
For this example, ensure you have installed `ansible` on your host machine
tasks:
- name: Deploy jellyfish config for nginx
copy:
content: |
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name jellyfish;
root /srv/www/htdocs;
location / {
try_files $uri $uri/ =404;
}
location ~ \.php$ {
fastcgi_pass unix:/run/php-fpm/php-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
dest: "/etc/nginx/vhosts.d/jellyfish.conf"
group: "root"
owner: "root"
mode: 0754
notify: Restart nginx
- name: Ensure nginx is in the www group
user:
name: nginx
groups: www
append: yes
notify: Restart nginx
- name: Deploy phpinfo script
copy:
content: "<?php phpinfo(); phpinfo(INFO_MODULES); ?>"
dest: "/srv/www/htdocs/phpinfo.php"
group: "www"
owner: "wwwrun"
mode: 0754
# Note: The current php-fpm apparmor profile does not allow access to /srv/www.
# We set app-armor to complain in this role. Note that you should use e.g.
# `yast apparmor` to update your AppArmor profile instead of disabling AppArmor
# as a whole!
- name: Ensure aa-complain is installed
package:
name: apparmor-utils
state: present
- name: Put app-armor to complain mode
shell: aa-complain /etc/apparmor.d/php-fpm
handlers:
- name: Restart nginx
systemd:
name: nginx
state: restarted
```
# Step-by-setup guid
Let's start with the basics. First ensure you have `ansible` installed on your host machine
sudo zypper in ansible
@ -71,27 +100,40 @@ Then, we need a working directory, let's say `jellyfish`.
All next steps should be run in this directory.
## No install required: JeOS VM
We first setup a JeOS VM as our playing ground. Skip down to the [Running the playbook](#running-the-playbook) section in case you have already your VM up and running and just want the playbook to run.
The most easy way of just getting a openSUSE Leap VM running, is to use the JeOS image, available at https://get.opensuse.org/leap. Download the KVM or XEN HVM image, import it into your `virt-manager` and your're ready to go!
## Ready in under 5 minutes: openSUSE JeOS
Once you fire the machine up, you just need a handful of configuration steps, and then your have a functional JeOS VM, which is enough for this setup.
> No installation required! This VM image is ready in under 5 minutes.
### JeOS installation
The most easy way of just getting a openSUSE Leap VM running, is to use the JeOS image. JeOS (or MinimalVM) is a slimmed down image that contains just enough to run as a VM. It boots directly from the provided `qcow2` image and does not need to be installed. A handful of configuration steps in the first-run wizard and you're good to go! You have your openSUSE Leap VM up and running in under 5 minutes.
JeOS can be downloaded from https://get.opensuse.org/leap in Alternative Downloads". Download the KVM and XEN image, import it into your `virt-manager` and we're ready to go.
### JeOS VM: Step-by-step guide
Back in our `jellyfish` directory, we first download the VM image (which is also our hard disk)
$ wget -O jellyfish.cow2 https://download.opensuse.org/distribution/leap/15.2/appliances/openSUSE-Leap-15.2-JeOS.x86_64-kvm-and-xen.qcow2
$ wget -O jeos-openSUSE-Leap-15_4.qcow2 https://download.opensuse.org/distribution/leap/15.4/appliances/openSUSE-Leap-15.4-JeOS.x86_64-kvm-and-xen.qcow2
Create a `qcow2` overlay, so that multiple machines could in principle use the same `qcow2` image as base and we only store the overlay in a separate image file:
qemu-img create -b jeos-openSUSE-Leap-15_4.qcow2 -f qcow2 -F qcow2 jellyfish.qcow2 30G
Then we run `virt-install` to setup and run our `jellyfish` server:
$ virt-install --name=jellyfish --file=$PWD/jellyfish.qcow2 --vcpus=2 --ram=2048 --os-type=linux --os-variant=opensuse15.2 --boot hd
$ virt-install --name=jellyfish --file=$PWD/jellyfish.qcow2 --vcpus=2 --ram=2048 --os-variant=opensuse15.4 --boot hd
After a handful of configuration steps, you have a functional system in just some minutes
After a handful of configuration steps, you have a functional system in just some minutes.
![Jellyfish setup](/img/jellyfish-jeos.gif)
![Jellyfish setup](jellyfish-jeos.gif)
Now, you have to ensure, you have root ssh access to `jellyfish`. For that, first log in, then find out the ip address using `ip address` (or `ip a` in short):
As you can see in this gif, it only took me 1:30 minutes to get a functional openSUSE Leap 15.4 system using the JeOS image.
### Provide ssh access for ansible
Ansible requies ssh access to the machines it is expected to provision. In this example we will assign the `jellyfish` hostname to the VM IP address via `/etc/hosts`. In a more mature environment you might need to update the DHCP server but that's outside of the scope of this tutorial.
First we need to find out the IP address of the VM. For that, we log in via the `virt-manager` console, then run `ip address` (or `ip a` in short) to list the currently assigned IP addresses. See the `192.168.122.116` in the output below:
# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
@ -107,14 +149,9 @@ Now, you have to ensure, you have root ssh access to `jellyfish`. For that, firs
inet6 fe80::5054:ff:fe85:f7a/64 scope link
valid_lft forever preferred_lft forever
Then on your host system, do
ssh-copy-id root@jellyfish
Done. Now it's a good time to create a VM snapshot, in case you want to have a fresh system.
Also, add the IP address to `/etc/hosts` otherwise you will need to replace `jellyfish` by the ip address in all following commands.
Add the last line `192.168.122.116 jellyfish` to your `/etc/hosts` file.
Now, as root on your local machine, add the IP address to `/etc/hosts` otherwise you will need to replace `jellyfish` by the ip address in all following commands.
We have been adding the last line `192.168.122.116 jellyfish` to your `/etc/hosts` file.
vim /etc/hosts
@ -136,17 +173,25 @@ Add the last line `192.168.122.116 jellyfish` to your `/etc/hosts` file.
::1 hotdog
[...]
# This is what we add here to assign an IP our amazing jellyfish VM
192.168.122.116 jellyfish
Remember to remove this line afterwards, in case you don't want to keep your `jellyfish` :-)
Now let's copy the ssh-key from your host via
ssh-copy-id root@jellyfish
Done. Check if you can login via `ssh root@jellyfish`. Now would be a good time to power off your VM and create a VM snapshot, so in case something goes wrong in the next step you have your "saved game" slot you can always rollback to.
Remember to remove the `jellyfish` from `/etc/hosts` afterwards, in case you don't want to keep your `jellyfish` :-)
## Running the playbook
First ensure, that you have root access to `jellyfish`
First ensure (one more time), that you have root access to `jellyfish`
ssh root@jellyfish
Back in our `jellyfish` directory, we need to get the roles and the playbook. Let's say
Back in our `jellyfish` directory, we need to get the roles and the playbook:
# Download the ansible repositories
git clone https://github.com/GeekOops/geekoops-nginx
@ -154,16 +199,28 @@ Back in our `jellyfish` directory, we need to get the roles and the playbook. Le
# Download playbook
curl -o jellyfish.yml https://geekoops.github.io/posts/20210326-example-webserver/jellyfish.yml
Next we need to create an [inventory](https://docs.ansible.com/ansible/latest/user_guide/intro_inventory.html). And inventory is a list of hosts or host groups that belongs to a certain deployment. In our basic setup we only hold the `jellyfish` host, but you can see this really as an inventory of all servers that you would manage via ansible. Let's stay simple here:
# Create inventory
echo "jellyfish" > inventory
Now let's run the playbook. `ansible` will then install all packages and configure `nginx` for you
We now have all ingredients that we need. We have the playbook, we have the roles and we have the inventory. So from here nothing is holding us back, let's fire `ansible` up and run the playbook using `ansible-playbook`:
ansible-playbook -i inventory jellyfish.yml
ansible-playbook -i inventory jellyfish.yml # Use the custom inventory instead of the default (/etc/ansible)
Go grab something to drink and let `ansible` sparkle it's magical fairy dust. When you return the playbook has hopefully setup your machines to the desired state:
![ansible running](jellyfish-running.gif)
What you hope for is to see something like the following after about 1-2 minutes of ansible running:
![Screenshot of ansible completing its task](jellyfish-completed.png)
The `ok=22 changed=17 failed=0` tells you that ansible was successful.
Now in your browser navigate to [http://jellyfish/phpinfo.php](http://jellyfish/phpinfo.php) and you should see, the output of phpinfo:
![Output of phpinfo in webbrowser](/img/jellyfish-phpinfo.png)
![Output of phpinfo in webbrowser](jellyfish-phpinfo.png)
Congratulations. You have successfully deployed a `nginx` + `php-fpm` webserver instance. Time to celebrate!

Binary file not shown.

After

Width:  |  Height:  |  Size: 436 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 896 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 230 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 375 KiB

View file

@ -27,7 +27,7 @@
try_files $uri $uri/ =404;
}
location ~ \.php$ {
fastcgi_pass unix:/var/run/php-fpm.sock;
fastcgi_pass unix:/run/php-fpm/php-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
@ -38,10 +38,10 @@
owner: "root"
mode: 0754
notify: Restart nginx
- name: Ensure nginx has access to php
- name: Ensure nginx is in the www group
user:
name: nginx
group: www
groups: www
append: yes
notify: Restart nginx
- name: Deploy phpinfo script
@ -51,6 +51,16 @@
group: "www"
owner: "wwwrun"
mode: 0754
# Note: The current php-fpm apparmor profile does not allow access to /srv/www.
# We set app-armor to complain in this role. Note that you should use e.g.
# `yast apparmor` to update your AppArmor profile instead of disabling AppArmor
# as a whole!
- name: Ensure aa-complain is installed
package:
name: apparmor-utils
state: present
- name: Put app-armor to complain mode
shell: aa-complain /etc/apparmor.d/php-fpm
handlers:
- name: Restart nginx

View file

@ -9,7 +9,7 @@ This role works with openSUSE Leap and is intended to ship enough requirements f
## Role Variables
This ansible role comes with a minimal set of configuration parameters.
This ansible role comes with a large set of [configuration parameters](https://github.com/GeekOops/geekoops-php-fpm#role-variables). Among others here are some of the most important ones:
| Value | Description | Default |

Binary file not shown.

Before

Width:  |  Height:  |  Size: 203 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 120 KiB