- Technologies Used
- Infrastructure
- Configurations
Note
In this documentation, blocks that start with π emojii or in NOTE block are for educational purposes (for explaining elements or some keywords. If you are not a beginner, you can skip those blocks and continue following instructions). Also, links with π emojii are links to full config files.
Note
Technologies were chosen either by project requirements (like OS) or by hardware limitations for Apple silicon (VMWare)
- VMWare Fusion (Free Version)
- OS: OpenBSD, FreeBSD, Debian Bookworm
- Tool: Ansible
The infrastucture consists of 4 virtual machines:
- VM1 - Gateway
- OS: OpenBSD 7.6
- has 4 network cards: NAT and 3 private
- DHCP and DNS server
- declares firewall rules
- VM2 - Server
- OS: FreeBSD 14
- acts as NGINX and MySQL server
- VM3 - Employee
- OS: Debian 12
- has GUI
- VM4 - Administration
- OS: Debian 12
- has GUI
- lan-1: administration
- network : 192.168.42.0
- broadcast : 192.168.42.63
- range DHCP : 192.168.42.40 - 192.168.42.60
- lan-2: server
- network : 192.168.42.64
- broadcast : 192.168.42.127
- range DHCP : 192.168.42.70 - 192.168.42.110
- lan-3: employee
- network : 192.168.42.128
- broadcast : 192.168.42.191
- range DHCP : 192.168.42.140 - 192.168.42.180
For security reasons, right segregation and access control must be applied:
- administration LAN can reach any server through the server network, on all ports.
- employee LAN can reach only reach the server on HTTP and HTTPS protocols.
- employee, administration and server LANs can go out on the internet, ping devices on another subnet, and retrieve DHCP and DNS information from the gateway.
The plan is to firstly configure gateway, then create client VMs (employee and administration) to test firewall rules, dhcp/dns configs and internet connection, and after that create server VM and configure it with help of Ansible.
Before creating first VM, it is necessary to create 3 private custom networks:
- open VMWare general settings (
command
+,
) - go to Network tab
- on the left bottom, click the lock to make changes
- click on + on the left bottom 3 times. It will create 3 custom network cards. For now leave all configs as they are. They will be changed later after the creation of the first VM.
- by double clicking on the name, you can change it. For the better comprehension, I have named mine
lan-1
,lan-2
, andlan-3
.
- by double clicking on the name, you can change it. For the better comprehension, I have named mine
Here we need to configure our network cards, DHCP and DNS servers, as well as firewall fules as per requirements above described in Infrastructure section.
- Download OpenBSD 7.6
iso
image (install76.iso
file forarm64
(Apple Silicon))
- click on + on the top left corner -> New
- drag downloaded
.iso
file to the specified place - for OS system - choose Other > Other 64-bit arm
- do not click on Finish yet, instead, click on Customise Settings, choose name of the VM, and Save.
- in the settings, go to Processors & Memory, choose 2 cores and 2048 MB of memory
- next got to Hard Disk (NVMe) and choose 20GB of memory on Virtual Disk.
- go to Network Adapter and make sure that SHare with my Mac option is chosen, and well as on top Connect Network Adapter box is ticked.
- next, on the top right corner, click on Add Device..., choose Network Adapter, and from the list choose
lan-1
custom network. Repeat the process forlan-2
andlan-3
. Always make sure that box for Connect Network Adapter is chosen.
- Choose
Installation
(typeI
) - For keyboard choice, if you need QWERTY, choose
default
(just click onEnter
) - Hostname name:
gateway
- Network interface to configure: type
em0
Note
In OpenBSD usually names of network interfaces are emX
, for our inftrastructure, em0
is NAT, and em1
, em2
, and em3
are private network interfaces.
- IPv4 address for em0? - type dhcp
- IPv6 adress for em0? - leave none (just click on Enter
)
Note
IPv4: Format: XXX.XXX.XXX.XXX (e.g., 192.168.42.1). Used widely but limited due to exhaustion of available addresses. IPv6: Format: XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX (e.g., 2001:0db8:85a3:0000:0000:8a2e:0370:7334).
- Next network to configure is em1. Type
em1
.- symbolic name:
lan-1
- IPv4 adress for em1:
192.168.42.1/26
(it is a static IP address within the subnet. The first usable IP in each subnet is assigned to the gateway interface./26
is netmask that =255.255.255.192
. This subnet mask splits the IP range into groups of 64 addresses.)
- symbolic name:
- Now the same with
em2
:- symbolic name:
lan-2
- ip:
192.168.42.65/26
- symbolic name:
- For
em3
:- symbolic name:
lan-3
- ip:
192.168.42.129/26
- symbolic name:
- DNS domain name: you can choose default
- Password for root account: type whiever you wish
- Start sshd (8) by default? - type
yes
- Create a user? - type
no
(usually you need a user, for this project exactly for simplicity I will use root user for VM1 and VM2 - generally not recommended) - Allow root ssh login? - type
yes
(generally not recommended as it is security risk. Again, for simplicity of the infrastructure I will aloow it) - What timezone are you in? - just click on
Enter
- Which disk is the root disk? Type
Enter
for default value - Encrypt the root disk? -
no
- Use whole disk and accept default layout.
- Location of sets? (cd0 disk http nfs or 'done') - type
cd0
(since you use.iso
image to istall this OS) - Pathname to the sets - type on
Enter
- Set name -
done
- Directory does not contain SHA256.sig, continue without verification? -
yes
- After installation -
reboot
- After the reboot, log in as root user using your password. Check the following commands:
ifconfig
check if 4 network interfaces are there (em0
,em1
,em2
,em3
)ifconfig em1
must have inet192.168.42.1
ifconfig em2
must have inet192.168.42.65
ifconfig em3
must have inet192.168.42.129
ping -c 1 8.8.8.8
must be successful and lost packages must be at 0%ping -c 1 google.com
must be successful and lost packages must be at 0%
- Go to the general settings of the VMWare > Network.
- As before, unlcok the possibility to change by clicking on the lock.
- Go to
lan-1
network. There, change first Subnet Mask value to255.255.255.192
and Subnet IP to192.168.42.0
. Make sure that from all the options, onlyConnect the host Mac to this network
is chosen. Untick all the rest. - Repeat the same with
lan-2
:- Subnet Mask:
255.255.255.192
- Subnet IP:
192.168.42.64
- Subnet Mask:
- And with
lan-3
:- Subnet Mask:
255.255.255.192
- Subnet IP:
192.168.42.128
- Subnet Mask:
- Apply all of the changes and close settings.
Configure files for network interfaces:
/etc/hostname.em0
/etc/hostname.em1
/etc/hostname.em2
/etc/hostname.em3
There you need to verify (or write if no yet correct) static ip of the interface, netmask, and add keyword up
, that is used to indicate that the network interface should be enabled (brought "up") during system boot.
π You can find correct version of files here.
Configure DHCP in the file /etc/dhcpd.conf
. It is normal that this file does not exist. The DHCP server configuration file needs to be created manually when you set up a DHCP server.
touch /etc/dhcpd.conf
chmod 644 /etc/dhcpd.conf
vi /etc/dhcpd.conf
to edit the file.
π Find the file here.
- to check if file does not have any syntax errors:
dhcpd -n -f -d em1 em2 em3
βοΈ Important note:
- this line
hardware ethernet 00:00:00:00:00:00;
will be configured later. For now you can comment the whole blockhost server
with help of#
.
π Explanation for the elements:
option domain-name "local"
- sets the domain name for the DHCP clients.host server { ... }
- defines a specific client with a static IP (192.168.42.70
) assigned based on its MAC address (hardware ethernet
).subnet 192.168.42.x netmask 255.255.255.192 { ... }
- configures the IP range, router, broadcast address, and DNS for the network. Aftersubnet
is IP of the subnet - network adress, and then netmask, meaning that the last number can change in this subnet.range ...
- defines the dynamic IP range within each subnet for DHCP clients.option routers ...
- specifies the default gateway for clients in the subnet (address = first usable address in the subnet). The gateway IP (or router IP) is the address of the device that routes traffic between the local subnet and other networks (e.g., the internet).option broadcast-address ...
- sets the broadcast address for the subnet (address = last address in the subnet). The broadcast address is a special IP address used to send messages to all devices on a specific subnet.option domain-name-servers ...
- defines the DNS server(s) for clients in the subnet.
- Create the
/etc/rc.conf.local
file if it doesn't already exist. In OpenBSD, this file is used to override default system settings and specify custom configurations. - Set correct permissions:
chown root:wheel /etc/rc.conf.local
chmod 600 /etc/rc.conf.local
- In this file, add the line:
dhcpd_flags="em1 em2 em3"
. This tells the system to run the DHCP server on the em1, em2, and em3 interfaces (your private LAN interfaces). - Start dhcp service:
rcctl enable dhcpd
rcctl start dhcpd
π When you create next machines, you can check if DHCP server is working correctly by checking DHCP leases here: /var/db/dhcpd.leases
. There you will see which IP was given and to which machine.
- Create a file:
echo "net.inet.ip.forwarding=1" > /etc/sysctl.conf
- Set the correct permissions:
chown root:wheel /etc/sysctl.conf
chmod 640 /etc/sysctl.conf
This will allow the system to forward packets between different networks (LANs and the internet).
To immediately enable IP forwarding, you can run this command:
sysctl net.inet.ip.forwarding=1
.
To check if IP forwarding is enabled: To immediately enable IP forwarding, you can run this command:
sysctl net.inet.ip.forwarding. If it shows
1- it is enabled,
0` - not enabled.
πnet.inet.ip.forwarding
is a system control (sysctl) setting that determines whether the operating system forwards IPv4 packets between network interfaces. If you have multiple network interfaces and want your OpenBSD system to route traffic between them (e.g., in a gateway or router setup), you need to enable net.inet.ip.forwarding.
- Add the following lines to the file
/var/unbound/etc/unbound.conf
:
server:
interface: 192.168.42.1 # em1
interface: 192.168.42.65 # em2
interface: 192.168.42.129 # em3
access-control: 192.168.42.0/26 allow # LAN-1 network
access-control: 192.168.42.64/26 allow # LAN-2 network
access-control: 192.168.42.128/26 allow # LAN-3 network
do-udp: yes
do-tcp: yes
forward-zone:
name: "."
forward-addr: 8.8.8.8
forward-addr: 8.8.4.4
π Full file can be found here.
π In OpenBSD, Unbound is a validating, recursive, and caching DNS resolver. It is included in the base system and serves as a lightweight and secure DNS service. It is primarily used to resolve DNS queries locally and cache responses for faster subsequent lookups.
π Elements of the file:
server:
configures Unbound's server behavior, including network interfaces, access controls, and query handling.interface:
specifies which network interfaces Unbound listens on for DNS queries. Unbound will only respond to DNS queries received on these IP addresses.access-control:
defines rules for allowing or denying DNS query access based on client IP ranges.do-udp: yes
- enables DNS resolution over UDP, the default transport for most DNS queriesdo-tcp: yes
- enables DNS resolution over TCP, which is used when responses exceed the UDP size limit or for DNSSEC validation.forward-zone:
configures Unbound to forward DNS queries to external resolvers, such as public DNS serversname: "."
- the"."
indicates the root zone, meaning this configuration applies to all DNS queries.forward-addr:
- specifies the upstream DNS servers to which Unbound forwards queries. Unbound acts as a forwarder in this setup, sending queries to these upstream resolvers for names it cannot resolve locally.
- Check if config is valid:
unbound-checkconf
. If mistake is/var/unbound/db/root.key: No such file or directory unbound-checkconf
:- Create file:
unbound-anchor -a /var/unbound/db/root.key
- Verify it was created:
ls -l /var/unbound/db/root.key
- Give permissions:
chown _unbound:_unbound /var/unbound/db/root.key
andchmod 644 /var/unbound/db/root.key
- Create file:
- In
/etc/rc.conf.local
add this line:unbound_flags=
π You donβt need to specify the flags, because it will rely on configuration file (/var/unbound/etc/unbound.conf
).
- Restart Unbound:
rcctl restart unbound
- Restart dhcpd:
rcctl restart dhcpd
Packet Filter is OpenBSD built-in firewall. PF controls the flow of traffic between interfaces and enforces rules about which types of network traffic are allowed to pass through the system.
- Edit the
/etc/pf.conf
file. You can find full file here. - Reload PF configuration
pfctl -f /etc/pf.conf
- Enable PF if it's not enabled yet
pfctl -e
and pf service:rcctl enable pf
- Add the following line to the
/etc/rc.conf.local
:pf=YES
To check PF rules: pfctl -sr
πSome details for the file:
-
pass
/block
/match
:pass
: allows traffic that matches the rule's criteria to pass through.pass in
- to the mentioned interface,pass out
- from the mentioned interfaceblock
: blocks traffic that matches the rule's criteria. Works same within
andout
aspass
match
: modifies or applies special handling to traffic (e.g., NAT or QoS). It does not block or pass traffic but works alongside other rules
-
keep state
: tracks the state of a connection. Once a connection is established, return traffic matching the same state is automatically allowed without needing additional rules. This is essential for protocols like TCP, which involve multiple packets for a single session -
configuration options (
set
commands):set optimization aggressive
: optimizes firewall performance with an "aggressive" profile, which is suitable for high-throughput or low-latency environments. It affects how PF manages states and timeouts.set ruleset-optimization basic
: simplifies the ruleset to improve efficiency during processing. This "basic" optimization focuses on straightforward reductions like collapsing redundant rules.set skip on lo0
: skips filtering on the loopback interface (lo0
). This is common since loopback traffic is typically local-only and trusted.set block-policy return
: specifies how blocked packets are handled. Thereturn
policy sends a rejection (e.g., TCP RST for TCP packets or ICMP Unreachable for others) back to the sender. This contrasts with adrop
policy, which silently discards packets.set state-policy if-bound
: limits state tracking to the interface where the connection was established. This is useful in multi-homed environments, ensuring state entries are interface-specific, improving security.
-
match in all scrub
- normalizes incoming traffic, correcting any anomalies (like overlapping fragments). This makes packets safer and more predictable to process.no-df
: removes the "Don't Fragment" flag from packets, ensuring compatibility with MTU-based fragmentation.random-id
: replaces predictable packet IDs with random ones to enhance security against spoofing and tracking.
-
Network Address Translation (NAT) (
nat-to ($ext_if)
): translates the source address of outgoing packets to the external interface's IP. This is key for allowing private (internal) networks to access external resources like the internet.
βοΈ Do not do this step until you test internet connection in other VMs.
Generally, it is possible what with all these configurations you will have Internet access just on VM2 running on FreeBSD and not on the others. But you will receive internet access on VM3 and VM4 after reboot of VM1 (exactly reboot!) or after running the command sh /etc/netstart
.
This suggests that there's a state issue with PF rules or NAT translation table that gets reset during reboot. One reason for this could be the ordering of PF rules and interface initialization during boot. This is common in virtualized environments, especially with VMware Fusion, where network interface initialization timing can sometimes cause issues.
Why then FreeBSD has internet? Some reasons:
- The timing of DHCP requests and responses
- How different operating systems (FreeBSD vs Debian) handle network interface initialization
- The static vs dynamic nature of the configurations (FreeBSD server has static ip)
Very general fix for this issue:
- Create a script
/usr/local/sbin/network-init.sh
:
#!/bin/sh
# Initialize interfaces
sh /etc/netstart
# Reload PF
pfctl -f /etc/pf.conf
-
Make it executable:
chmod +x /usr/local/sbin/network-init.sh
-
Add this script a cron job:
crontab -e
-
Add this line to make the script execute itself every minute:
* * * * * /usr/local/sbin/network-init.sh
. You can add your line anywhere after the PATH and HOME settings but before the end of the file.
- Download Debian 12
iso
image forarm64
.
- click on + on the top left corner -> New
- drag downloaded
.iso
file to the specified place - do not click on Finish yet, instead, click on Customise Settings, choose name of the VM, and Save.
- in the settings, go to Processors & Memory, choose 2 cores and 2048 MB of memory
- next got to Hard Disk (NVMe) and choose 20GB of memory on Virtual Disk.
- go to Network Adapter and make sure that Share with my Mac option is chosen, and well as on top Connect Network Adapter box is ticked. It will be changed, but for instalaltion, we need Internet connection.
- Choose graphical interface for simplicity.
- Language:
English
- Country Territory:
US
- Keymap: for QWERTY -
American English
- Hostname:
employee
for VM3,administration
for VM4 - Domain name: empty
- Root password - choose whatever you want
- Full name for the user with non-administrative activities:
employee
for VM3,administration
for VM4 - Same for user name
- For time - choose any. I have chosen
Central
- Partitioning method:
Guided - use entire disk
- Select list to partition: select the
default
- Partitioning scheme:
all files in one partition
- Next click on
Finish partitioning
and write changed to disk. Confirm changes - Scan extra installation media?
No
- Debian archive mirror country: choose yours
- Debian archive mirror: choose default one (first one)
- HTTP proxy: leave empty
- Participate in survey: no
- Choose software to install: Check
SSH server
,standard system utilities
, andβ¦GNOME
(for GUI) - After the installation, press
Continue
to reboot
Once the machine is started, on the top you have <...>
button (to the right of the π§ button). Click on this button, then on Network Adapter Settings, and there choose lan-3
private network for VM3(Employee) machine, and lan-1
for VM4(Administration).
- Once you see the screen to log in as a user, click on
fn
+control
+option
+F3
to open CLI. - Type user
root
and a password you have chosen for a root. - Make user a sudoer:
- for employee:
usermod -aG sudo employee
- for administration:
usermod -aG sudo administration
- for employee:
- check the name of the network with
ip a
- Add the following lines to
/etc/network/interfaces
(change ens160 to the name of your network):
auto ens160
allow-hotplug ens160
iface ens160 inet dhcp
π Full files are here (for employee) and here (for administration).
- Add ip of the corresponding subnets to the file
/etc/resolv.conf
:- for employee:
nameserver 192.168.42.129
- for administration:
nameserver 192.168.42.1
- for employee:
π Full files are here (for employee) and here (for administration).
- Restart networking:
systemctl restart networking
- To check if DHCP is working correctly, run
dhclient -v ens160
, where ens160 is the name of the network.- here:
DHCPACK of 192.168.42.161 from 192.168.42.129
you should see first IP to be in the range configured indhcpd.conf
file in the VM1, and second IP must be the IP of the gateway (configured in the previous step)
- here:
To restart DHCP connection: dhclient -r ens160
, and to start again: dhclient ens160
- server should always get the same IP (192.168.42.70) and the configuration must be in DHCP mode.
- install and setup a NGINX web server
- install also php7.4 and required modules
- deploy the page provided (
data.php
). - install mysql80-server using the system port and install the provided
nsa501
database - create a user for this database with the following features:
- user: backend
- rights: All rights on nsa501 table
- password: Bit8Q6a6G.
π Additional files provided here.
- Download FreeBSD 14
iso
image forarm64
(file calledFreeBSD-14.2-RELEASE-arm64-aarch64-disc1.iso
).
- click on + on the top left corner -> New
- Click on
Create custom virtual machine
- Choose
FreeBSD 14 64-bit Arm
- Create a new virtual disk for 20GB
- Customise Settings: On
CD/DVD
select your ISO and tick onConnect CD/DVD drive
. - Select one more time 2 cores and 2048 memory.
- On Network Adapter and make sure that Share with my Mac option is chosen, and well as on top Connect Network Adapter box is ticked. It will be changed, but for instalation, we need Internet connection.
- Boot installer -> Install
- Choose keyboard - for qwerty just press
Enter
- Hostname:
server
- Choose optional system components to install: Choose all except
lib32-dbg
,tests
,base-dbg
, andkernel-dbg
(you need to press space to select). - Network configs:
- Choose network interface
- Configure IPv4?
yes
- Use DHCP:
yes
- Configure IPv6:
no
- Enable wireless:
no
- For partitioning:
- Choose "Auto (ZFS)"
- Select "stripe" for pool type
- Choose your virtual disk
- Use default pool name "zroot"
- Select GPT partitioning
- Accept default swap size
- Select
Install
and click onEnter
- Next select a mirror (just
default
) - Choose root password
- Choose the needed timezone and date (or just press
Enter
for defaults) - For system configuration, enable sshd.
- After everything -
reboot
Donβt forget to delete an ISO from CD/DVD (disconnect from CD/DVD
).
Next, you can restart and start Boot
.
Once the machine is started, on the top you have <...>
button (to the right of the π§ button). Click on this button, then on Network Adapter Settings, and there choose lan-2
private network.
- from the result of command
ifconfig
, save the value ofether
ofem0
(in the formatxx:xx:xx:xx:xx:xx
). - Configure
/etc/rc.conf
: add the value of thether
to the fieldifconfig_em0
:ifconfig_em0="DHCP ether 00:00:00:00:00:00"
.
π Full file here.
- Come back to VM1 to the file
/etc/dhcpd.conf
. Uncomment blockhost server
and for the value ofhardware ethernet
write down you Mac adress taken from VM2.
- Temporary allow ssh in
/etc/ssh/sshd_config
:PermitRootLogin yes
PasswordAuthentication yes
- Restart ssh:
service sshd restart
- In VM1, do the same (
vi /etc/ssh/sshd_config
). Restart ssh:rcctl restart sshd
- On VM1, generate ssh key:
ssh-keygen -t ed25519 -C "ansible"
. Select default file (/root/.ssh/id_ed25519
) and empty passphrase. - Send public key to VM2. From VM1:
cat /root/.ssh/id_ed25519.pub | ssh root@192.168.42.70 "mkdir -p /root/.ssh; chmod 700 /root/.ssh; cat >> /root/.ssh/authorized_keys; chmod 600 /root/.ssh/authorized_keys"
- Test the connection from VM1:
ssh root@192.168.42.70
. If connection does not require pass and is successfuly connected, then everything is fine.
On VM1:
pkg_add ansible
mkdir -p ~/ansible/
cd ~/ansible/
On VM2, install Python:
pkg update
pkg install python311
π Ansible itself is written in Python. To execute its code, Python needs to be available on the control node (the machine where Ansible is installed), as well as on managed nodes (the target machines) to execute tasks. When you run Ansible playbooks, it typically connects to target nodes using SSH and executes Python scripts or modules to perform tasks like managing files, installing packages, or configuring services.
On VM1 (in ~/ansible
):
touch inventory.ini
. Check the content of the file here. This file is used to connect to VM2 from VM1.- Test connectivity:
ansible webservers -i inventory.ini -m ping
. If successful:
server | SUCCESS => {
"changed": false,
"ping": "pong"
}
π .ini
file is an inventory file used by Ansible to define the hosts (managed nodes) that it will manage, along with optional variables for configuring how Ansible interacts with each host.
[webservers]
: the name of a host group. A group is a collection of hosts that share a purpose or need similar configurations.server
is an alias for a host. This alias is used in playbooks to reference the host, rather than using its IP address directly (in my case, it is hostname of VM2)ansible_host=192.168.42.70
specifies the actual IP address (or hostname) of the target machine.ansible_user=root
specifies the SSH username Ansible will use to connect to the host.ansible_python_interpreter=/usr/local/bin/python3.11
specifies the Python interpreter Ansible should use on the target host. If the target host doesn't use the defaultpython
orpython3
path (e.g.,/usr/bin/python3
), you need to explicitly specify the correct path.
- From Terminal on local machine where this file is saved, run command:
scp ~/Downloads/app_t-nsa-501.zip root@192.168.42.70:/root/
Since there is no more php74 in FreeBSD14, you have to install and compile it manually. for reference, on site php.net
you can navigate to archive and find there all old files.
- Create and edit
vi ~/ansible/install_php74.yml
π Check the content here.
mkdir ~/ansible/templates
- for additional config files used by Ansiblevi ~/ansible/templates/www.conf.j2
- for PHP-FPM configurations
π Check the content here.
- Run playbook on VM1:
ansible-playbook -i inventory.ini install_php74.yml
π Explanation for the files:
- before first task, there is general information for the project, like
name
,hosts
(described ininventory.ini
file,become: yes
- means that ansible can run tasks with elevated privileges (sudo
or root), andvars
- variables used throughout the playbook
Tasks are executed step by step on the target hosts.
- first task is instalation of the required packages using
pkgng
- package manager for FreeBSD.state: present
- ensures that the package, file, or resource exists - next its creating a working directory.
state: directory
ensures that the specified path is a directory. If it doesn't exist, Ansible creates it.mode
parameter sets the permissions of the file or directory. It follows the standard UNIX/Linux file permission format.
0 7 5 5
| | | |
| | | βββ Others (world)
| | βββββ Group
| βββββββ Owner
βββββββββ Special bits (optional, e.g., 0)
Numeric Values for Permissions:
4 β Read (r)
2 β Write (w)
1 β Execute (x)
Combine values to get permissions:
7 = 4 + 2 + 1 β Read, Write, and Execute.
5 = 4 + 1 β Read and Execute.
- next Ansible downloads PHP source from the url and saves it to
dest
. Taslget_url
is likewget
orcurl
in Linux - after that goes unarchiving the file.
remote_src: yes
means thatsrc
value is located in the target machine (by defaultsrc
is located in the machine where Ansible is running, in our case it is VM1. We need to specify thatsrc
is in VM2). Also, forunarchive
task Ansible uses additional option withextra_opts: "--use-compress-program=xz"
, and we specify tool to use to unarchive:gtar
- withenvironment: TAR: /usr/local/bin/gtar
- before compilation and installation, we need to configure php using
./configure
script with several options.cmd
is used to execute a command-line instruction on the target system.cmd: >
is a YAML "folded block scalar" style that allows you to write a long command on multiple lines for readability. Basically it allows the configure command to span multiple lines but be treated as a single-line command.chdir
stands for "change directory." It changes the working directory before running the command.creates
parameter checks if the specified file already exists. If it does, the task is skipped. - next are compilation and instalaltion of the php file using commands
gmake
for compilation, andgmake install
for installation - after that is a sut up of PHP config file. Ansible creates file and copies default
php.ini-production
file (php.ini-production
is a sample configuration file provided with the PHP source code. ) - then we start the process of configuring
php-fpm
(it is an alternative PHP implementation for handling FastCGI requests, optimized for high-performance web applications. PHP-FPM acts as a process manager for PHP, running in the background and handling PHP requests efficiently). First Ansible creates symlinks (a shortcut or reference that points to another file or directory). In general it is done for future simplicity. Instead of runningphp
andphp-fpm
binaries using full path (e.g.,/usr/local/php74/bin/php
), you can simply use commandsphp
orphp-fpm
(by placing them to/usr/local/bin/
and creating a symlink to original binary) - configuration of PHP-FPM is done with template
www.conf.j2
provided intemplates
directory:- sets the user/group as
www
- uses a socket file for communication (
/var/run/php-fpm.sock
) - configures process management (
pm
) to dynamic mode with limits for workers.
- sets the user/group as
- next is a tsak to enable php-fpm (by writing a line
php_fpm_enable="YES"
into the config filerc.conf
and starting the servicephp-fpm
- cleanup task is done to delete temporary build directory to clean up disk space
- handlers are triggered when a task notifiec them (e.g., modifying the
www.conf
file as mentioned in thenotify
option in the task of configuringphp-fpm
)
- Create and edit
vi ~/ansible/webserver.yml
π Check the content here.
- For Additional NGINX configs: create and edit file
vi ~/ansible/templates/nginx.conf.j2
π Check the content here.
-
Run playbook on VM1:
ansible-playbook -i inventory.ini webserver.yml
-
Test nginx on VM2:
nginx -t
π Explanation of the files:
- as in the playbook for php configuration, first we declare general information:
name
,hosts
andgather_facts: yes
- gathers information (facts) about the remote system.
Tasks:
- first goes installation of the packages
nginx
andmysql80-server
withpkgng
- next goes enabling the services by adding approproate line into the file
rc.conf
.lineinfile
- adds lines to the file.create: yes
: creates the file if it does not exist. service
task start the service (in this case we start withmysql-server
), and ensures thatstate
isstarted
before going to the next task- after that Ansibles takes care of unarchiving tha saving source files provided in the zip.
- to work with
mysql
database, Ansible uses SQL queries (for some usescommand
task, and for oneshell
- becausecommand
does not accept<
:- to create database:
command: mysql -e "CREATE DATABASE IF NOT EXISTS nsa501;"
- to import database:
shell: mysql nsa501 < /root/app_t-nsa-501/nsa501.sql
- create user and set privilages:
command: mysql -e "CREATE USER IF NOT EXISTS 'backend'@'localhost' IDENTIFIED WITH mysql_native_password BY 'Bit8Q6a6G'; GRANT ALL PRIVILEGES ON nsa501.* TO 'backend'@'localhost'; FLUSH PRIVILEGES;"
- to create database:
- moving to configuration of thw webserver, similarly, first Ansible creates web directory and gives necessary permissions and ownership. Then it copies extracted file
data.php
and start configuring nginx withnginx.conf.j2
template:listen 80
: Listens for HTTP traffic on port 80.root
: Web root directory is /usr/local/www/nsa501.location /
: All requests are passed to data.php (e.g., a front-controller PHP script).location ~ \.php$
: Handles .php files.fastcgi_pass
: Forwards PHP requests to PHP-FPM via the Unix socket/var/run/php-fpm.sock
.SCRIPT_FILENAME
: Ensures the correct PHP file is processed.- worker_connections`: Sets the maximum number of simultaneous connections per worker process.
- after nginx configuration, Ansible starts webserver
- handler restarts Nginx when notified, ensuring changes to the configuration take effect.
PHP_FPM For some reason, previous process of php-fpm is not alwyas stopped after the reboot or turning off. So to be safe, once the VM2 is running, run:
pkill -f 'php-fpm'
service php-fpm start
Or create a script:
vi /usr/local/etc/rc.d/php_restart
π Check the content here.
- Make the script executable:
chmod +x /usr/local/etc/rc.d/php_restart
- Enable the script by adding this line to /etc/rc.conf:
php_restart_enable="YES"
Also, you can run this script manually: service php_restart start
IP FORWARDING
To enable IP forwarding permanently on FreeBSD (VM2), add this line to /etc/sysctl.conf: net.inet.ip.forwarding=1
ADDITIONAL FIREWALL
If you have an issue with internet connection on VM3 and VM4 described on the section VM1 > Optional: Internet Access Issue
, it is possible that there will be also issues with firewall after restarting network interfaces on VM1. To ensure that VM2 is protected from VM3 (VM3 should not be able to connect to VM2 via ssh), create firewall rules in VM2:
touch /etc/pf.conf
vi /etc/pf.conf
.
π Check the content here.
- Load the PF kernel modules:
kldload pf
andkldload pflog
- To make these modules load automatically at boot, add these lines to
/etc/rc.conf
:
pf_enable="YES"
pf_rules="/etc/pf.conf"
pflog_enable="YES"
- Load the rules:
pfctl -f /etc/pf.conf
- Start pf:
service pf start