Iocage is a container (jails) manager that makes use of the best functionalities and technologies that FreeBSD offers us. This will facilitate management throughout the jail’s life cycle, creation, destruction, and updating.
The article is composed of several parts:
- Installation
- Creating a Jail
- Assigning an IP address
- Defining boot dependencies
- Managing snapshots
- Automatic software installation
- Import/Export of Jails
- Mount points in Jails
- Querying Jail resources
- Types of Jails
- Update
- Update Base
- Update Packages/Ports
- Update script
- New jail script
- Firewall
- Recommendations
Installation
The first step will be to install the software:
We can tell it to show us colors:
To make it permanent, we will have to export the variable in the shell we use, in my case it is bash:
export IOCAGE_COLOR=TRUE
If it is a server that will contain many jails, we must mount the
file descriptor file system
, in this way access will be faster:
To make it permanent:
fdescfs /dev/fd fdescfs rw 0 0
If we have more than one zpool, we must indicate to Iocage which one to use:
NAME SIZE ALLOC FREE CKPOINT EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT
storage 928G 35.8G 892G - - 1% 3% 1.00x ONLINE -
zroot 109G 16.0G 93.0G - - 3% 14% 1.00x ONLINE -
In my case, zroot:
We download the version of FreeBSD that will act as the base for the jails:
Press [Enter] to fetch the default selection: (12.1)
ENTER
To provide network to the Jails, aliases are used on the parent interface. Since these are aliases, they are IPs of the parent and the Jail simultaneously, which implies certain problems if we bind the parent’s services in all available directions. For example, if we do it with the Ssh service while the Jail has the service started, the Ssh of the Jail will be served on that IP. If the Ssh of the Jail is turned off, the Ssh of the parent will be served, which can lead to confusion.
Any service of the parent must be bound exclusively to its IP address. In the jail, there is no problem since it only sees the assigned IP, and with a wildcard, it is bound to this unique existing IP.
In the parent, we must avoid generic bindings like these:
ListenAddress 0.0.0.0
listen *
Creating a Jail
We create our jail:
We check that it is up:
+-----+---------+-------+--------------+--------------+
| JID | NAME | STATE | RELEASE | IP4 |
+=====+=========+=======+==============+==============+
+-----+---------+-------+--------------+--------------+
| 5 | test | up | 12.1-RELEASE | - |
+-----+---------+-------+--------------+--------------+
We can access the console with the console command:
root@test:~ # hostname
test
exit
Iocage comes with several jails ready to be used, they are called plugins. With the command list –plugins –remote, we can see which jails are available:
Some of the most popular ones are:
+-------------------+-------------------+-------------------+------------------+
| NAME | DESCRIPTION | PKG | ICON |
+===================+===================+===================+==================+
| Bacula-server | Manage, backup, | bacula-server | https://www.true |
+-------------------+-------------------+-------------------+------------------+
| GitLab | DevOps lifecycle | gitlab | https://www.true |
+-------------------+-------------------+-------------------+------------------+
| Jenkins | Open source build | jenkins | https://www.true |
+-------------------+-------------------+-------------------+------------------+
| Nextcloud | Suite of client- | nextcloud | https://www.true |
+-------------------+-------------------+-------------------+------------------+
| Zoneminder | Closed-circuit | zoneminder | https://www.true |
+-------------------+-------------------+-------------------+------------------+
Assigning an IP address
Regarding the assignment of IP addresses, Iocage supports two modes: sharedIP/Vnet, but the latter is considered unstable, so we will focus on sharedIP.
The jail IPs will be automatically configured on the parent host through aliases when starting the corresponding jail.
First, we make sure that Vnet is not enabled in the jail:
0
We assign an IP address:
iocage list
+-----+---------+-------+--------------+--------------+
| JID | NAME | STATE | RELEASE | IP4 |
+=====+=========+=======+==============+==============+
+-----+---------+-------+--------------+--------------+
| 5 | test | up | 12.1-RELEASE | IP_JAIL |
+-----+---------+-------+--------------+--------------+
We check that the jail knows its IP:
nfe0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
options=8210b<RXCSUM,TXCSUM,VLAN_MTU,TSO4,WOL_MAGIC,LINKSTATE>
ether 00:00:ca:fe:00:00
inet IP_JAIL netmask 0xffffff00 broadcast 192.168.1.255
media: Ethernet autoselect (1000baseT <full-duplex,master>)
status: active
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> metric 0 mtu 16384
options=680003<RXCSUM,TXCSUM,LINKSTATE,RXCSUM_IPV6,TXCSUM_IPV6>
groups: lo
ipfw0: flags=8800<SIMPLEX,MULTICAST> metric 0 mtu 65536
groups: ipfw
Defining boot dependencies
Iocage allows defining dependencies between jails, so that the jail in question will not start until its dependencies have started:
Managing snapshots
One of the most interesting features is snapshots. To create them, we execute:
iocage snapshot -n testJail01 test
To view the snapshots of a jail:
+-----------------+-----------------------+-------+------+
| NAME | CREATED | RSIZE | USED |
+=================+=======================+=======+======+
| testJail00 | Sun Mar 29 14:06 2020 | 92K | 60K |
+-----------------+-----------------------+-------+------+
| testJail00/root | Sun Mar 29 14:06 2020 | 1.33G | 264K |
+-----------------+-----------------------+-------+------+
| testJail01 | Sun Mar 29 14:14 2020 | 92K | 0 |
+-----------------+-----------------------+-------+------+
| testJail01/root | Sun Mar 29 14:14 2020 | 1.33G | 220K |
+-----------------+-----------------------+-------+------+
NOTE: We can see that there are two snapshots, one of the directory where the Jail configuration is located (config.json/fstab) and another of the root of that Jail.
If we want to revert, we first stop the jail:
Then we perform the rollback:
NOTE: If we do not revert to the last snapshot, the intermediate snapshots will be deleted. In my case, I had the snapshots testJail00 and testJail01, and by reverting to testjail00, testjail01 has been deleted:
+-----------------+-----------------------+-------+------+
| NAME | CREATED | RSIZE | USED |
+=================+=======================+=======+======+
| testJail00 | Sun Mar 29 14:06 2020 | 92K | 0 |
+-----------------+-----------------------+-------+------+
| testJail00/root | Sun Mar 29 14:06 2020 | 1.33G | 0 |
+-----------------+-----------------------+-------+------+
To remove snapshots, we execute:
Automatic software installation
It is possible to automatically install certain packages in a jail when it is created. We just need to prepare the list in json format:
{
"pkgs": [
"ngrep",
"tcpdump"
]
}
We start the jail with the following command:
Import/Export of Jails
The import functionality in Iocage is buggy and consumes all the RAM+SWAP of the system. As a workaround, we can export normally, but we will have to import manually using ZFS commands:
scp /zroot/iocage/images/test_2020-03-28.zip REMOTE_SERVER:/zroot/iocage/images/test_2020-03-28.zip
On the receiving server:
zfs recv -F zroot/iocage/jails/test < zroot/iocage/images/test_2020-03-28
zfs recv -F zroot/iocage/jails/test/root < zroot/iocage/images/test_2020-03-28_root
Mount Points in Jails
If we want to mount external directories inside the jail, we will use the Iocage fstab command. In this case, we mount the /storage directory inside the jail (/mnt/storage):
mkdir /mnt/storage
We can check the mount points with:
+-------+-------------------------------------------------------------------------------------------+
| INDEX | FSTAB ENTRY |
+=======+===========================================================================================+
| 0 | /storage /zroot/iocage/jails/test/root/mnt/storage nullfs rw 0 0 |
+-------+-------------------------------------------------------------------------------------------+
Quering jail resources
Another very useful option is to be able to see which resources each jail is occupying:
+---------+-------+------+------+-------+-------+
| NAME | CRT | RES | QTA | USE | AVA |
+=========+=======+======+======+=======+=======+
| test | 1.04x | none | none | 396K | 84.1G |
+---------+-------+------+------+-------+-------+
Types of Jails
Iocage supports several types of jails.
-
Clone: iocage create -r [RELEASE]
This is the default jail type. When a jail of this type is created, a clone of the RELEASE snapshot is made. It consumes little space since the base is shared between jails and only the data that is changed inside is saved. Each jail of this type must be updated independently. Since jails of this type have the RELEASE as their base, we cannot delete the RELEASE until we have deleted all jails that depend on it. -
Base: iocage create -r [RELEASE] -b
This is a jail generated from a complete copy of the RELEASE, but certain directories of the RELEASE are mounted inside the jail through nullfs. This type of jail takes up less space than thick jails but more than clone jails. It is the ideal type for patching massively since by running iocage update on one of the jails, we will be updating all those that share the RELEASE with it. All jails of that RELEASE can also be updated by running iocage fetch RELEASE again. -
Thick: iocage create -r [RELEASE] -T
A complete copy of the RELEASE is made, taking up more space than the other types. It is a jail completely independent of the others, and each jail of this type must be updated independently. -
Template
Templates are jails tweaked to serve as a template for quick deployment. To generate a template from an existing jail, follow these steps:
iocage set template=yes test
We can check the local templates:
+-----+------+-------+--------------+--------------+
| JID | NAME | STATE | RELEASE | IP4 |
+=====+======+=======+==============+==============+
| - | test | down | 12.1-RELEASE | JAIL_IP |
+-----+------+-------+--------------+--------------+
To create a jail from a template:
The conversion process to a template can be reversed using the template parameter:
- Empty: iocage create -e
These jails are designed for testing or unsupported functionalities, ideal for experimenting with unsupported RELEASES or Linux jails.
We will normally use clone jails unless we use templates where we must bear in mind that these cannot be updated without restarting the jails that descend from them. To be able to perform updates on the templates without having to restart the jails, they will have to be created as Thick type.
Update
Like any other FreeBSD system the operating system update is divided in two parts, the base system and the installed binary packages/ports.
Update BASE
If we stay within the same version, it will be enough to run:
To move from one version to another, consult the latest
RELEASE
available.
If it is a minor update, e.g. 12.0 -> 12.1:
iocage update JAILNAME
If it is a major update, e.g. 12.1 -> 13.0, in addition to the steps of a minor update, we must reinstall binary/ports packages and finish the update.
If we are working with binary packages:
pkg-static upgrade -f
exit
iocage update JAILNAME
If we are working with ports:
git -C /usr/ports pull
cd /usr/ports
make fetchindex
for PORT in $(pkg info|awk '{print$1}'); do PORT_PATH=$(pkg info $PORT|grep Origin|awk '{print$3}') && echo PORT: $PORT - $PORT_PATH && cd /usr/ports/$PORT_PATH && export BATCH="yes" && make clean reinstall clean; done
exit
iocage update JAILNAME
NOTA: Updates using Iocage automatically take a snapshot with each update, so if something goes wrong, it can be easily reverted.
Update PACKAGES/PORTS
Update the binary packages inside a jail:
Update the ports inside a jail:
git -C /usr/ports pull
for PORT in $(pkg info|awk '{print$1}'); do PORT_PATH=$(pkg info $PORT|grep Origin|awk '{print$3}') && echo PORT: $PORT - $PORT_PATH && cd /usr/ports/$PORT_PATH && export BATCH="yes" && make clean reinstall clean; done
Update script
To make jail updates more convenient, we can write a script like the following, which always leaves the last snapshot in case it needs to be reverted and snapshots called PRESERVER*:
#!/usr/local/bin/bash
source /root/.scripts/cecho.sh
function sendTelegram {
message=${@:1}
curl -s -X POST https://api.telegram.org/bot535179217:AAGXRe1df_1WNgqxOCfC8VrCNKGqouhslLw/sendMessage -d chat_id=30418601 -d text="$message"
}
clear
cecho "Cyan" "<== Iocage Jail updater by kr0m ==>"
echo ""
echo ""
cecho "Cyan" ">> Converting basic_template to regular jail"
iocage set template=no basic_template
iocage start basic_template
for JAIL in $(iocage list|grep up|awk '{print$4}'); do
echo ""
echo ""
cecho "Cyan" ">> Updating Base: $JAIL"
iocage update $JAIL
done
echo ""
cecho "Green" "----------------------------------------------------"
for JAIL in $(iocage list|grep up|awk '{print$4}'); do
echo ""
echo ""
cecho "Cyan" ">> Clearing $JAIL snapshots"
SNAPSNUMBER=$(iocage snaplist $JAIL|grep -v root|grep -v '+'|grep -v 'NAME'|wc -l|awk '{print$1}')
# Check testJail
echo $JAIL |grep test_ 1>/dev/null
if [ $? -eq 0 ]; then
TESTJAIL=1
else
TESTJAIL=0
fi
if [ $SNAPSNUMBER -gt 0 ]; then
# TestJail: Delete all snapshots
if [ $TESTJAIL -eq 1 ]; then
for SNAPTOREMOVE in $(iocage snaplist $JAIL|grep -v root|grep -v '+'|grep -v 'NAME'|awk '{print$2}'); do
cecho "Cyan" "-- Removing: $SNAPTOREMOVE"
iocage snapremove -n $SNAPTOREMOVE $JAIL
done
else
# If you want to preserve some snapshot from being deleted in update process, name it PRESERVE
# Additionally we will preserve las IOC update snapshot, it always will be present because script always execute iocage update $JAIL in previous step
LAST_IOC_UPDATE=$(iocage snaplist $JAIL|grep ioc_update|grep -v 'root'|awk '{print$2}'|tail -n 1)
for SNAPTOREMOVE in $(iocage snaplist $JAIL|grep -v root|grep -v '+'|grep -v 'NAME'|grep -v 'PRESERVE'|grep -v "$LAST_IOC_UPDATE"|awk '{print$2}'); do
cecho "Cyan" "-- Removing: $SNAPTOREMOVE"
iocage snapremove -n $SNAPTOREMOVE $JAIL
done
fi
else
cecho "Cyan" "-- No snapshots to remove"
fi
done
echo ""
cecho "Green" "----------------------------------------------------"
for JAIL in $(iocage list|grep up|awk '{print$4}'); do
echo ""
echo ""
cecho "Cyan" ">> Updating PKGs: $JAIL"
iocage exec $JAIL 'ASSUME_ALWAYS_YES=yes pkg upgrade'
echo ""
cecho "Cyan" ">> Executing AUTO-REMOVE: $JAIL"
iocage exec $JAIL 'ASSUME_ALWAYS_YES=yes pkg autoremove'
done
echo ""
echo ""
cecho "Cyan" ">> Converting basic_template jail to template"
iocage stop basic_template
iocage set template=yes basic_template
echo ""
cecho "Green" "----------------------------------------------------"
echo ""
echo ""
cecho "Cyan" ">> Updating SpamAssasin: DrWho"
iocage exec DrWho 'sa-update -v'
iocage exec DrWho 'service sa-spamd restart'
echo ""
echo ""
cecho "Cyan" ">> Restarting Mail services: DrWho"
iocage exec DrWho 'service sendmail restart'
iocage exec DrWho 'service dovecot restart'
echo ""
cecho "Cyan" ">> Visit: https://mail.alfaexploit.com/?admin#/about"
echo ""
cecho "Cyan" ">> Checking if Mail system still works: DrWho"
DATE=$(date "+%d/%m/%Y %H:%M:%S")
#echo "DrWho updated: $DATE" | mail -s "DrWho updated: $DATE" kr0m@alfaexploit.com
echo -e "Subject: DrWho updated: $DATE" | sendmail -f root@alfaexploit.com kr0m@alfaexploit.com
sleep 10
grep -r "DrWho updated: $DATE" /zroot/iocage/jails/DrWho/root/var/mail/kr0m 1>/dev/null
if [ $? -ne 0 ]; then
cecho "Red" "++ ERROR: Mail system is not working"
MESSAGE="ERROR: Mail system is not working"
sendTelegram $MESSAGE
else
cecho "Cyan" ">> Mail system is working"
fi
echo ""
cecho "Green" "----------------------------------------------------"
echo ""
echo ""
cecho "Cyan" ">> Updating Python PIP: rxWod"
iocage exec rxWod 'su -l kr0m -c "/usr/home/kr0m/rxWod/bin/python3.7 -m pip install --upgrade pip"'
echo ""
cecho "Green" "----------------------------------------------------"
echo ""
echo ""
cecho "Cyan" ">> Updating git: rxWod"
iocage exec rxWod 'su -l kr0m -c "cd /home/kr0m/rxWod/rxWodProject && git status"'|grep 'nothing to commit, working tree clean' 1>/dev/null
if [ $? -eq 1 ]; then
iocage exec rxWod 'su -l kr0m -c "cd /home/kr0m/rxWod/rxWodProject && git stash"'
iocage exec rxWod 'su -l kr0m -c "cd /home/kr0m/rxWod/rxWodProject && git stash drop"'
fi
iocage exec rxWod 'su -l kr0m -c "cd /home/kr0m/rxWod/rxWodProject && git pull"'
echo ""
cecho "Green" "----------------------------------------------------"
echo ""
echo ""
cecho "Cyan" ">> Updating Python libraries: rxWod"
iocage exec rxWod 'su -l kr0m -c "cd /home/kr0m/rxWod && source bin/activate && cd rxWodProject/ && pip-upgrade -p all"'
echo ""
cecho "Green" "----------------------------------------------------"
echo ""
echo ""
cecho "Cyan" ">> Making Django migrations: rxWod"
iocage exec rxWod 'su -l kr0m -c "cd /home/kr0m/rxWod && source bin/activate && cd rxWodProject && python manage.py makemigrations"'
iocage exec rxWod 'su -l kr0m -c "cd /home/kr0m/rxWod && source bin/activate && cd rxWodProject && python manage.py migrate"'
echo ""
cecho "Green" "----------------------------------------------------"
echo ""
echo ""
cecho "Cyan" ">> Updating Yarn libraries: rxWod"
iocage exec rxWod 'su -l kr0m -c "cd /home/kr0m/rxWod/rxWodProject/ && yarn install --force"'
iocage exec rxWod 'su -l kr0m -c "cd /home/kr0m/rxWod/rxWodProject/ && yarn upgrade"'
iocage exec rxWod 'su -l kr0m -c "cd /home/kr0m/rxWod/rxWodProject/ && yarn prod-build"'
echo ""
cecho "Green" "----------------------------------------------------"
echo ""
echo ""
cecho "Cyan" ">> Collecting Django static files: rxWod"
iocage exec rxWod 'su -l kr0m -c "cd /home/kr0m/rxWod && source bin/activate && cd rxWodProject && python manage.py collectstatic --noinput"'
echo ""
cecho "Green" "----------------------------------------------------"
echo ""
echo ""
cecho "Cyan" ">> Restarting Daphne service: rxWod"
iocage exec rxWod '/usr/sbin/service daphne restart'
echo ""
cecho "Green" "----------------------------------------------------"
echo ""
echo ""
cecho "Cyan" ">> Updating owasp-modsecurity: Infinity"
iocage exec Infinity 'cd /usr/local/owasp-modsecurity-crs/ && git pull'
echo ""
cecho "Cyan" ">> Updating Hugo theme: Infinity"
iocage exec Infinity 'su -l kr0m -c "cd /home/kr0m/AlfaExploit/alfaexploit_zzo/ && git submodule update --remote --merge"'
echo ""
cecho "Cyan" ">> Redeploying Alfaexploit: Infinity"
iocage exec Infinity 'su -l kr0m -c "cd /home/kr0m/AlfaExploit/alfaexploit_zzo/ && hugo && rm -rf /usr/local/www/alfaexploit/* && cp -r public/* /usr/local/www/alfaexploit/"'
NOTE: I leave the script cecho a little further down, if we don’t want to use it, we just have to change the cechos to echos.
New jail script
To automate the creation of new jails, we must first create a jail that will serve as a base:
iocage set ip4_addr=“nfe0|192.168.69.9/24” basic_template
We install the base software and perform basic configuration:
We convert the jail into a template:
iocage set template=yes basic_template
Now we can automate the creation of jails with the following script:
#!/usr/local/bin/bash
source /root/.scripts/cecho.sh
clear
cecho "Cyan" "<== Iocage Jail creator by kr0m ==>"
echo ""
echo ""
cecho "Green" "-- Jail name: $1"
cecho "Green" "-- IP address: $2"
if [ -z $3 ]; then
cecho "Green" "-- VNET: NO"
VNET=0
else
if [ $3 == "vnet" ]; then
cecho "Green" "-- VNET: YES"
cecho "Yellow" "-- VNET: Remember to check configuration for bridge interface"
VNET=1
else
cecho "Green" "-- VNET: NO"
VNET=0
fi
fi
echo ""
echo ""
cecho "Cyan" ">> Making basic checks"
if [ $# -ne 2 ] && [ $# -ne 3 ]; then
cecho "Red" "++ ERROR: Script needs JAIL_NAME IP_ADDRESS VNET(optional) arguments"
exit
fi
JAIL_NAME=$1
IP_ADDRESS=$2
cecho "Cyan" ">> Checking ip in correct net/range"
first_ip_address=$(echo $IP_ADDRESS|awk -F "." '{print$1}')
second_ip_address=$(echo $IP_ADDRESS|awk -F "." '{print$2}')
third_ip_address=$(echo $IP_ADDRESS|awk -F "." '{print$3}')
fourth_ip_address=$(echo $IP_ADDRESS|awk -F "." '{print$4}')
if [ $first_ip_address -eq 192 ] && [ $second_ip_address -eq 168 ] && [ $third_ip_address -eq 69 ] && [ $fourth_ip_address -lt 200 ]; then
cecho "Green" "-- Correct ip net/range"
else
if [ $first_ip_address -ne 192 ] || [ $second_ip_address -ne 168 ] || [ $third_ip_address -ne 69 ]; then
cecho "Red" "++ ERROR: Incorrect ip address NET: $IP_ADDRESS"
exit
fi
if [ $fourth_ip_address -ge 200 ]; then
cecho "Red" "++ ERROR: Ip address in DHCP range: $IP_ADDRESS"
exit
fi
fi
cecho "Cyan" ">> Checking jail names"
for JAIL in $(iocage list|grep up|awk '{print$4}'); do
if [ "$JAIL_NAME" == "$JAIL" ]; then
cecho "Red" "++ ERROR: Already running jail with name: $JAIL_NAME"
exit
fi
done
cecho "Green" "-- Correct jail name"
cecho "Cyan" ">> Checking duplicated jail ips"
for IP in $(iocage list|grep up|awk '{print$10}'); do
if [ "$IP_ADDRESS" == "$IP" ]; then
cecho "Red" "++ ERROR: Already running jail with ip: $IP_ADDRESS"
exit
fi
done
cecho "Green" "-- Correct jail ip"
cecho "Cyan" ">> Checking if base template exists"
BASE_TEMPLATE_EXISTS=$(iocage list -t|grep 'basic_template'|awk '{print$4}'|wc -l|awk '{print$1}')
if [ $BASE_TEMPLATE_EXISTS -eq 1 ]; then
cecho "Green" "-- Base template found"
else
cecho "Red" "++ ERROR: Base template not found"
exit
fi
echo ""
cecho "Green" "----------------------------------------------------"
echo ""
echo ""
cecho "Cyan" ">> Deploying: $JAIL_NAME"
iocage create -T -t basic_template -n $JAIL_NAME
if [ $VNET -eq 1 ]; then
iocage set vnet=on $JAIL_NAME
#iocage set allow_raw_sockets="1" $JAIL_NAME
iocage set defaultrouter=192.168.69.200 $JAIL_NAME
iocage set ip4_addr="vnet0|$IP_ADDRESS/24" $JAIL_NAME
else
#iocage set ip4_addr="bridge0|$IP_ADDRESS/24" $JAIL_NAME
iocage set ip4_addr="nfe0|$IP_ADDRESS/24" $JAIL_NAME
fi
iocage start $JAIL_NAME
echo ""
cecho "Green" "----------------------------------------------------"
if [ $VNET -eq 1 ]; then
echo ""
echo ""
cecho "Cyan" ">> Disabling FW: $JAIL_NAME"
iocage exec $JAIL_NAME "sysrc firewall_enable=YES"
iocage exec $JAIL_NAME "sysrc firewall_type=open"
fi
echo ""
cecho "Green" "----------------------------------------------------"
echo ""
echo ""
cecho "Cyan" ">> Setting FQDN: $JAIL_NAME"
iocage exec $JAIL_NAME "sysrc hostname=$JAIL_NAME.alfaexploit.com"
cecho "Cyan" ">> Patching /etc/hosts: $JAIL_NAME"
iocage exec $JAIL_NAME "sed -i '' 's/$JAIL_NAME//g' /etc/hosts"
JAIL_NAME2=$(echo $JAIL_NAME | tr '[:upper:]' '[:lower:]')
if [ "$JAIL_NAME" == "$JAIL_NAME2" ]; then
iocage exec $JAIL_NAME "sed -i '' 's/CUSTOM_ENTRY/$IP_ADDRESS\t\t$JAIL_NAME.alfaexploit.com $JAIL_NAME/g' /etc/hosts"
else
iocage exec $JAIL_NAME "sed -i '' 's/CUSTOM_ENTRY/$IP_ADDRESS\t\t$JAIL_NAME.alfaexploit.com $JAIL_NAME $JAIL_NAME2.alfaexploit.com $JAIL_NAME2/g' /etc/hosts"
fi
echo ""
cecho "Green" "----------------------------------------------------"
echo ""
echo ""
cecho "Cyan" ">> Restarting: $JAIL_NAME"
iocage stop $JAIL_NAME
iocage start $JAIL_NAME
echo ""
cecho "Green" "----------------------------------------------------"
echo ""
echo ""
cecho "Cyan" ">> Updating Base: $JAIL_NAME"
iocage update $JAIL_NAME
echo ""
cecho "Green" "----------------------------------------------------"
echo ""
echo ""
cecho "Cyan" ">> Clearing $JAIL_NAME snapshots"
N=$(iocage snaplist $JAIL_NAME|grep 'ioc_update'|grep -v root|grep -v '+'|grep -v 'NAME'|wc -l|awk '{print$1}')
if [ $N -gt 0 ]; then
for SNAPTOREMOVE in $(iocage snaplist $JAIL_NAME|grep 'ioc_update'|grep -v root|grep -v '+'|grep -v 'NAME'|awk '{print$2}'); do
cecho "Cyan" "-- Removing: $SNAPTOREMOVE"
iocage snapremove -n $SNAPTOREMOVE $JAIL_NAME
done
else
cecho "Cyan" "-- No snapshots to remove"
fi
echo ""
cecho "Green" "----------------------------------------------------"
echo ""
echo ""
cecho "Cyan" ">> Updating PKGs: $JAIL_NAME"
iocage exec $JAIL_NAME 'ASSUME_ALWAYS_YES=yes pkg upgrade'
iocage exec $JAIL_NAME 'ASSUME_ALWAYS_YES=yes pkg autoremove'
echo ""
cecho "Green" "----------------------------------------------------"
echo ""
echo ""
cecho "Cyan" ">> Updating pip: $JAIL_NAME"
iocage exec $JAIL_NAME 'pip install --upgrade pip'
echo ""
cecho "Green" "----------------------------------------------------"
echo ""
echo ""
cecho "Cyan" ">> Configuring SendMail Stats: $JAIL_NAME"
iocage exec $JAIL_NAME 'cd /etc/mail && make'
echo "define(\`STATUS_FILE',\`/var/log/sendmail.stats')dnl" >> /zroot/iocage/jails/$JAIL_NAME/root/etc/mail/$JAIL_NAME.alfaexploit.com.mc
iocage exec $JAIL_NAME 'cd /etc/mail && make'
iocage exec $JAIL_NAME "cp /etc/mail/$JAIL_NAME.alfaexploit.com.cf /etc/mail/sendmail.cf"
iocage exec $JAIL_NAME 'service sendmail restart'
echo ""
cecho "Green" "----------------------------------------------------"
echo ""
echo ""
cecho "Cyan" ">> Making last restart: $JAIL_NAME"
iocage stop $JAIL_NAME
iocage start $JAIL_NAME
echo ""
cecho "Green" "----------------------------------------------------"
echo ""
echo ""
cecho "Red" ">> Remember to add $JAIL_NAME to Prometheus: /etc/hosts and /usr/local/etc/prometheus.yml: sendmail_exporter"
cecho "Red" ">> Remember to add fstab entry via iocage and CRON job for backups"
echo ""
cecho "Green" "----------------------------------------------------"
echo ""
echo ""
cecho "Cyan" ">> Jail $JAIL_NAME deployed and updated"
An initial version of the script created clone-type jails, but this corrupted the jails already created from the template. As it is a clone, the shared base cannot be modified while it is running. Restarting the jail made it work again, but to avoid this downtime, it was decided to create them as Thick type .
Here’s the translation:
Below is the cecho script:
cecho(){
# Reset
Color_Off='\033[0m' # Text Reset
# Regular Colors
Black='\033[0;30m' # Black
Red='\033[0;31m' # Red
Green='\033[0;32m' # Green
Yellow='\033[0;33m' # Yellow
Blue='\033[0;34m' # Blue
Purple='\033[0;35m' # Purple
Cyan='\033[0;36m' # Cyan
White='\033[0;37m' # White
# Bold
BBlack='\033[1;30m' # Black
BRed='\033[1;31m' # Red
BGreen='\033[1;32m' # Green
BYellow='\033[1;33m' # Yellow
BBlue='\033[1;34m' # Blue
BPurple='\033[1;35m' # Purple
BCyan='\033[1;36m' # Cyan
BWhite='\033[1;37m' # White
# Underline
UBlack='\033[4;30m' # Black
URed='\033[4;31m' # Red
UGreen='\033[4;32m' # Green
UYellow='\033[4;33m' # Yellow
UBlue='\033[4;34m' # Blue
UPurple='\033[4;35m' # Purple
UCyan='\033[4;36m' # Cyan
UWhite='\033[4;37m' # White
# Background
On_Black='\033[40m' # Black
On_Red='\033[41m' # Red
On_Green='\033[42m' # Green
On_Yellow='\033[43m' # Yellow
On_Blue='\033[44m' # Blue
On_Purple='\033[45m' # Purple
On_Cyan='\033[46m' # Cyan
On_White='\033[47m' # White
# High Intensity
IBlack='\033[0;90m' # Black
IRed='\033[0;91m' # Red
IGreen='\033[0;92m' # Green
IYellow='\033[0;93m' # Yellow
IBlue='\033[0;94m' # Blue
IPurple='\033[0;95m' # Purple
ICyan='\033[0;96m' # Cyan
IWhite='\033[0;97m' # White
# Bold High Intensity
BIBlack='\033[1;90m' # Black
BIRed='\033[1;91m' # Red
BIGreen='\033[1;92m' # Green
BIYellow='\033[1;93m' # Yellow
BIBlue='\033[1;94m' # Blue
BIPurple='\033[1;95m' # Purple
BICyan='\033[1;96m' # Cyan
BIWhite='\033[1;97m' # White
# High Intensity backgrounds
On_IBlack='\033[0;100m' # Black
On_IRed='\033[0;101m' # Red
On_IGreen='\033[0;102m' # Green
On_IYellow='\033[0;103m' # Yellow
On_IBlue='\033[0;104m' # Blue
On_IPurple='\033[0;105m' # Purple
On_ICyan='\033[0;106m' # Cyan
On_IWhite='\033[0;107m' # White
printf "${!1}${2} ${Color_Off}\n"
}
Firewall
As a final note, we must keep in mind that all firewall rules must be defined on the parent host. When referring to “me,” it includes all the IPs of the aliases. Therefore, generic rules will be configured using “me,” and the more specific ones for each service will indicate the source and destination IP of the jail.
Recommendations
Some recommendations are:
- It is more efficient to restart jails using iocage restart -s than to do a stop/start.
- Every so often, clean up old snapshots, especially for jails whose data changes frequently.