Files
kodekloud-engineer/100 - days of devops/devops-11-20.md

23 KiB
Raw Blame History

Task 11

The Nautilus application development team recently finished the beta version of one of their Java-based applications, which they are planning to deploy on one of the app servers in Stratos DC. After an internal team meeting, they have decided to use the tomcat application server. Based on the requirements mentioned below complete the task:

a. Install tomcat server on App Server 3.

b. Configure it to run on port 8088.

c. There is a ROOT.war file on Jump host at location /tmp.

# from jump-host
scp /tmp/ROOT.war steve@stapp02:/tmp/

sudo yum install -y tomcat tomcat-webapps tomcat-admin-webapps

sudo sed -i 's/port="8080"/port="6300"/' /etc/tomcat/server.xml
# verify
sudo grep -n '6300' /etc/tomcat/server.xml

sudo cp /tmp/ROOT.war /var/lib/tomcat/webapps/
sudo chown tomcat:tomcat /var/lib/tomcat/webapps/ROOT.war

sudo systemctl enable --now tomcat
sudo systemctl restart tomcat    # ensure it picks up server.xml change if already running

# give it a few seconds to explode the WAR, then:
curl -I http://localhost:8088/

# possible problem
# Stock ROOT collision. If tomcat-webapps installed its own ROOT/ dir, and your ROOT.war sits beside it, tomcat may not redeploy over an # existing exploded dir. Nuke the stock one first: sudo rm -rf /var/lib/tomcat/webapps/ROOT then drop the war and restart.

Task 12

Our monitoring tool has reported an issue in Stratos Datacenter. One of our app servers has an issue, as its Apache service is not reachable on port 8089 (which is the Apache port). The service itself could be down, the firewall could be at fault, or something else could be causing the issue.

Use tools like telnet, netstat, etc. to find and fix the issue. Also make sure Apache is reachable from the jump host without compromising any security settings.

Once fixed, you can test the same using command curl http://stapp02:8089 command from jump host.

ss -tulnp
# kill semndmail sitting on the port
# start httpd
# remove reject rule from iptables
iptables -D INPUT 5

Task 13

We have one of our websites up and running on our Nautilus infrastructure in Stratos DC. Our security team has raised a concern that right now Apaches port i.e 8084 is open for all since there is no firewall installed on these hosts. So we have decided to add some security layer for these hosts and after discussions and recommendations we have come up with the following requirements:

  1. Install iptables and all its dependencies on each app host.
  2. Block incoming port 8084 on all apps for everyone except for LBR host.
  3. Make sure the rules remain, even after system reboot.
# --- resolve LBR host IP (script runs from jump-host) ---
LBR_IP=$(getent hosts stlb01 | awk '{print $1}')
echo "LBR IP resolved to: $LBR_IP"
[ -z "$LBR_IP" ] && { echo "ERROR: could not resolve stlb01"; exit 1; }

# --- creds (app servers only — the three targets) ---
cat > creds.txt <<'EOF'
stapp01 tony Ir0nM@n
stapp02 steve Am3ric@
stapp03 banner BigGr33n
EOF
chmod 600 creds.txt

# --- firewall script ---
cat > fw_8084.sh <<SCRIPT
#!/usr/bin/env bash
set -euo pipefail

CREDS="\${1:-creds.txt}"
LBR_IP="10.244.196.7"

REMOTE_CMD="
  yum install -y iptables iptables-services
  # iptables -F
  iptables -A INPUT -p tcp --dport 8084 -s \$LBR_IP -j ACCEPT
  iptables -A INPUT -p tcp --dport 8084 -j DROP
  systemctl enable --now iptables
  iptables-save > /etc/sysconfig/iptables
  echo \"--- \\\$(hostname) 8084 rules ---\"
  iptables -nvL INPUT | grep 8084
"

while read -r host user pass <&3; do
  [[ -z "\$host" || "\$host" == \\#* ]] && continue
  echo "==> Firewalling \$host"
  SSHPASS="\$pass" sshpass -e ssh -n \\
    -o StrictHostKeyChecking=no \\
    -o UserKnownHostsFile=/dev/null \\
    -o LogLevel=ERROR \\
    "\$user@\$host" \\
    "echo '\$pass' | sudo -S -p '' bash -c '\$REMOTE_CMD'" \\
    2> >(grep -v '^\[sudo\]' >&2)
  echo
done 3< "\$CREDS"
SCRIPT
chmod +x fw_8084.sh

# --- run ---
export LBR_IP=10.244.196.7
./fw_8084.sh 

Task 14

The production support team of xFusionCorp Industries has deployed some of the latest monitoring tools to keep an eye on every service, application, etc. running on the systems. One of the monitoring systems reported about Apache service unavailability on one of the app servers in Stratos DC.

Identify the faulty app host and fix the issue. Make sure Apache service is up and running on all app hosts. They might not have hosted any code yet on these servers, so you don't need to worry if Apache isn't serving any pages. Just make sure the service is up and running. Also, make sure Apache is running on port 6400 on all app servers.

# --- creds ---
cat > creds.txt <<'EOF'
stapp01 tony Ir0nM@n
stapp02 steve Am3ric@
stapp03 banner BigGr33n
EOF
chmod 600 creds.txt

# --- RECON: what's the state of httpd + port 6400 on each box ---
cat > apache_recon.sh <<'SCRIPT'
#!/usr/bin/env bash
set -euo pipefail

CREDS="${1:-creds.txt}"

REMOTE_CMD='
  echo "active: $(systemctl is-active httpd 2>/dev/null)"
  echo "enabled: $(systemctl is-enabled httpd 2>/dev/null)"
  echo "Listen directive: $(grep -iE "^Listen" /etc/httpd/conf/httpd.conf 2>/dev/null)"
  echo "bound on 6400: $(ss -tlnp | grep :6400 || echo NO)"
  echo "last httpd error:"
  journalctl -u httpd --no-pager 2>/dev/null | tail -5
'

while read -r host user pass <&3; do
  [[ -z "$host" || "$host" == \#* ]] && continue
  echo "===================== $host ====================="
  SSHPASS="$pass" sshpass -e ssh -n \
    -o StrictHostKeyChecking=no \
    -o UserKnownHostsFile=/dev/null \
    -o LogLevel=ERROR \
    "$user@$host" \
    "echo '$pass' | sudo -S -p '' bash -c '$REMOTE_CMD'" \
    2> >(grep -v '^\[sudo\]' >&2)
  echo
done 3< "$CREDS"
SCRIPT
chmod +x apache_recon.sh
./apache_recon.sh


# Verify
cat > apache_verify.sh <<'SCRIPT'
#!/usr/bin/env bash
set -uo pipefail   # note: no -e, we want to check ALL hosts even if one fails

CREDS="${1:-creds.txt}"

REMOTE_CMD='
  fail=0
  # 1. service running?
  if [ "$(systemctl is-active httpd 2>/dev/null)" = "active" ]; then
    echo "  [PASS] httpd is active"
  else
    echo "  [FAIL] httpd NOT active (state: $(systemctl is-active httpd 2>/dev/null))"
    fail=1
  fi
  # 2. enabled for boot?
  if [ "$(systemctl is-enabled httpd 2>/dev/null)" = "enabled" ]; then
    echo "  [PASS] httpd enabled at boot"
  else
    echo "  [WARN] httpd NOT enabled at boot (state: $(systemctl is-enabled httpd 2>/dev/null))"
  fi
  # 3. bound on 6400?
  if ss -tlnp 2>/dev/null | grep -q :6400; then
    echo "  [PASS] listening on port 6400"
  else
    echo "  [FAIL] NOT listening on 6400"
    fail=1
  fi
  # 4. actually responds? (any HTTP code = apache answering; 403/404 fine, task says no content needed)
  code=$(curl -s -o /dev/null -w "%{http_code}" --max-time 5 http://localhost:6400/ 2>/dev/null)
  if [ -n "$code" ] && [ "$code" != "000" ]; then
    echo "  [PASS] HTTP response on 6400 (code: $code)"
  else
    echo "  [FAIL] no HTTP response on 6400"
    fail=1
  fi
  echo "  RESULT: $([ $fail -eq 0 ] && echo ALL-GOOD || echo NEEDS-ATTENTION)"
'

overall=0
while read -r host user pass <&3; do
  [[ -z "$host" || "$host" == \#* ]] && continue
  echo "===================== $host ====================="
  out=$(SSHPASS="$pass" sshpass -e ssh -n \
    -o StrictHostKeyChecking=no \
    -o UserKnownHostsFile=/dev/null \
    -o LogLevel=ERROR \
    "$user@$host" \
    "echo '$pass' | sudo -S -p '' bash -c '$REMOTE_CMD'" \
    2> >(grep -v '^\[sudo\]' >&2))
  echo "$out"
  echo "$out" | grep -q NEEDS-ATTENTION && overall=1
  echo
done 3< "$CREDS"

echo "=================================================="
[ $overall -eq 0 ] && echo "✅ ALL HOSTS PASS" || echo "❌ ONE OR MORE HOSTS NEED ATTENTION"
SCRIPT
chmod +x apache_verify.sh
./apache_verify.sh

Task 15

The system admins team of xFusionCorp Industries needs to deploy a new application on App Server 2 in Stratos Datacenter. They have some pre-requites to get ready that server for application deployment. Prepare the server as per requirements shared below:

  1. Install and configure nginx on App Server 2.
  2. On App Server 2 there is a self signed SSL certificate and key present at location /tmp/nautilus.crt and /tmp/nautilus.key. Move them to some appropriate location and deploy the same in Nginx.
  3. Create an index.html file with content Welcome! under Nginx document root.
  4. For final testing try to access the App Server 2 link (via hostname) from jump host using curl command. For example: curl -Ik https:///.
# ===== nginx + SSL deploy on stapp02 (run as steve) =====

# 1. install nginx
sudo yum install -y nginx

# 2. relocate certs out of /tmp to a proper location + lock down perms
sudo mkdir -p /etc/nginx/ssl
sudo mv /tmp/nautilus.crt /etc/nginx/ssl/nautilus.crt
sudo mv /tmp/nautilus.key /etc/nginx/ssl/nautilus.key
sudo chmod 600 /etc/nginx/ssl/nautilus.key
sudo chmod 644 /etc/nginx/ssl/nautilus.crt

# 3. SSL server block — server_name pulled from the box's own FQDN
FQDN=$(hostname -f)
echo "Configuring nginx for: $FQDN"
sudo tee /etc/nginx/conf.d/nautilus.conf > /dev/null <<EOF
server {
    listen       443 ssl;
    server_name  ${FQDN};

    ssl_certificate      /etc/nginx/ssl/nautilus.crt;
    ssl_certificate_key  /etc/nginx/ssl/nautilus.key;

    root   /usr/share/nginx/html;
    index  index.html;

    location / {
        try_files \$uri \$uri/ =404;
    }
}
EOF

# 4. index.html with Welcome! under docroot
echo 'Welcome!' | sudo tee /usr/share/nginx/html/index.html > /dev/null

# 5. validate + start + enable
sudo nginx -t
sudo systemctl enable --now nginx
sudo systemctl restart nginx

# 6. local sanity check (before testing from jump-host)
echo "--- local curl test ---"
curl -Ik https://localhost/
echo "--- service state ---"
sudo systemctl is-active nginx

Task 16

Day by day traffic is increasing on one of the websites managed by the Nautilus production support team. Therefore, the team has observed a degradation in website performance. Following discussions about this issue, the team has decided to deploy this application on a high availability stack i.e on Nautilus infra in Stratos DC. They started the migration last month and it is almost done, as only the LBR server configuration is pending. Configure LBR server as per the information given below:

a. Install nginx on the LBR (load balancer) server if it is not already installed. b. Configure load-balancing with the http context making use of all App Servers. Ensure that you update only the main Nginx configuration file located at /etc/nginx/nginx.conf. c. Make sure you do not update the apache port that is already defined in the apache configuration on all app servers, also make sure apache service is up and running on all the app servers. d. Once done, you can access the website by running curl http://stlb01:80 in the terminal.

# ===== LBR config — run from jump-host =====

# --- creds (3 app servers for recon + LBR for deploy) ---
# ===== LBR config — run from jump-host =====

# --- creds (3 app servers for recon + LBR for deploy) ---
cat > creds.txt <<'EOF'
stapp01 tony Ir0nM@n
stapp02 steve Am3ric@
stapp03 banner BigGr33n
stlb01 loki Mischi3f
EOF
chmod 600 creds.txt

# helper: pull pass for a given host from creds
getpass() { awk -v h="$1" '$1==h{print $3}' creds.txt; }
getuser() { awk -v h="$1" '$1==h{print $2}' creds.txt; }

# --- STEP 1: recon — confirm apache up on all app servers + grab the port ---
echo "===== Apache recon on app servers ====="
for host in stapp01 stapp02 stapp03; do
  u=$(getuser "$host"); p=$(getpass "$host")
  echo "=== $host ==="
  SSHPASS="$p" sshpass -e ssh -n \
    -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o LogLevel=ERROR \
    "$u@$host" \
    "echo '$p' | sudo -S -p '' bash -c 'systemctl is-active httpd; grep -i \"^Listen\" /etc/httpd/conf/httpd.conf'" \
    2> >(grep -v '^\[sudo\]' >&2)
done

# --- STEP 2: auto-detect the apache port from stapp01 ---
u=$(getuser stapp01); p=$(getpass stapp01)
APACHE_PORT=$(SSHPASS="$p" sshpass -e ssh -n \
  -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o LogLevel=ERROR \
  "$u@stapp01" \
  "grep -iE '^Listen' /etc/httpd/conf/httpd.conf | awk '{print \$2}' | tr -d '\r'" \
  2>/dev/null)
echo ">>> Detected Apache port: $APACHE_PORT"
[ -z "$APACHE_PORT" ] && { echo "ERROR: could not detect apache port"; exit 1; }

# --- STEP 3: build nginx.conf LOCALLY (quoted heredoc keeps nginx $vars literal) ---
cat > /tmp/lbr_nginx.conf <<'EOF'
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

include /usr/share/nginx/modules/*.conf;

events {
    worker_connections 1024;
}

http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 4096;

    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

    upstream app_servers {
        server stapp01:__PORT__;
        server stapp02:__PORT__;
        server stapp03:__PORT__;
    }

    server {
        listen       80;
        server_name  stlb01;

        location / {
            proxy_pass http://app_servers;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
    }
}
EOF

# substitute the real apache port
sed -i "s/__PORT__/${APACHE_PORT}/g" /tmp/lbr_nginx.conf
echo ">>> nginx.conf built with upstream port ${APACHE_PORT}:"
grep -A4 'upstream app_servers' /tmp/lbr_nginx.conf

# --- STEP 4: ship config to stlb01 + deploy ---
u=$(getuser stlb01); p=$(getpass stlb01)

# scp the config to a temp spot on stlb01 (passwordless via sshpass)
SSHPASS="$p" sshpass -e scp \
  -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o LogLevel=ERROR \
  /tmp/lbr_nginx.conf "$u@stlb01:/tmp/lbr_nginx.conf"

# install nginx, back up original, move new config in, validate, start
SSHPASS="$p" sshpass -e ssh -n \
  -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o LogLevel=ERROR \
  "$u@stlb01" \
  "echo '$p' | sudo -S -p '' bash -c '
    yum install -y nginx
    cp -n /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak 2>/dev/null || true
    cp /tmp/lbr_nginx.conf /etc/nginx/nginx.conf
    nginx -t
    systemctl enable --now nginx
    systemctl restart nginx
    echo \"--- nginx state ---\"
    systemctl is-active nginx
  '" \
  2> >(grep -v '^\[sudo\]' >&2)

# --- STEP 5: final test ---
echo "===== TEST: curl http://stlb01:80 ====="
u=$(getuser stlb01); p=$(getpass stlb01)
SSHPASS="$p" sshpass -e ssh -n \
  -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o LogLevel=ERROR \
  "$u@stlb01" "curl -s http://stlb01:80 | head -20" \
  2>/dev/null

echo
echo "You can also test directly from jump-host:"
echo "  curl http://stlb01:80"

Task 17

The Nautilus application development team has shared that they are planning to deploy one newly developed application on Nautilus infra in Stratos DC. The application uses PostgreSQL database, so as a pre-requisite we need to set up PostgreSQL database server as per requirements shared below:

PostgreSQL database server is already installed on the Nautilus database server. a. Create a database user kodekloud_aim and set its password to 8FmzjvFU6S. b. Create a database kodekloud_db8 and grant full permissions to user kodekloud_aim on this database.

# ===== PostgreSQL setup on stdb01 (run as peter) =====

# sudo into postgres user first
sudo -i -u postgres

psql -c "SELECT version();"
psql -c "CREATE USER kodekloud_aim WITH PASSWORD '8FmzjvFU6S';"
psql -c "CREATE DATABASE kodekloud_db8;"
psql -c "GRANT ALL PRIVILEGES ON DATABASE kodekloud_db8 TO kodekloud_aim;"
psql -c "\l" | grep kodekloud_db8
psql -c "\du" | grep kodekloud_aim
psql -c "\l kodekloud_db8"

Task 18

We need to setup a database server on Nautilus DB Server in Stratos Datacenter. Please perform the below given steps on DB Server:

a. Install/Configure MariaDB server. b. Create a database named kodekloud_db3. c. Create a user called kodekloud_gem and set its password to YchZHRcLkL. d. Grant full permissions to user kodekloud_gem on database kodekloud_db3.

# ===== MariaDB setup on stdb01 (run as peter) =====

# a. install + start MariaDB
sudo yum install -y mariadb-server
sudo systemctl enable --now mariadb

# b/c/d. create db, user, grant privileges (root via unix_socket auth)
sudo mysql -e "CREATE DATABASE kodekloud_db3;"
sudo mysql -e "CREATE USER 'kodekloud_gem'@'localhost' IDENTIFIED BY 'YchZHRcLkL';"
sudo mysql -e "GRANT ALL PRIVILEGES ON kodekloud_db3.* TO 'kodekloud_gem'@'localhost';"
sudo mysql -e "FLUSH PRIVILEGES;"

# --- verify ---
echo "--- database exists? ---"
sudo mysql -e "SHOW DATABASES;" | grep kodekloud_db3
echo "--- user exists? ---"
sudo mysql -e "SELECT User,Host FROM mysql.user WHERE User='kodekloud_gem';"
echo "--- grants ---"
sudo mysql -e "SHOW GRANTS FOR 'kodekloud_gem'@'localhost';"

Task 18

xFusionCorp Industries is planning to host two static websites on their infra in Stratos Datacenter. The development of these websites is still in-progress, but we want to get the servers ready. Please perform the following steps to accomplish the task:

a. Install httpd package and dependencies on app server 2. b. Apache should serve on port 5000. c. There are two website's backups /home/thor/media and /home/thor/demo on jump_host. Set them up on Apache in a way that media should work on the link http://localhost:5000/media/ and demo should work on link http://localhost:5000/demo/ on the mentioned app server. d. Once configured you should be able to access the website using curl command on the respective app server, i.e curl http://localhost:5000/media/ and curl http://localhost:5000/demo/

# ===== Apache two-site setup: jump-host → stapp02 (via sshpass) =====

# --- creds ---
cat > creds.txt <<'EOF'
stapp02 steve Am3ric@
EOF
chmod 600 creds.txt

# pull steve's creds
USER=$(awk '$1=="stapp02"{print $2}' creds.txt)
PASS=$(awk '$1=="stapp02"{print $3}' creds.txt)

SSHOPTS="-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o LogLevel=ERROR"

# --- Step 1: ship both backups from jump-host to stapp02 ---
echo "==> Transferring media + demo to stapp02"
SSHPASS="$PASS" sshpass -e scp $SSHOPTS -r /home/thor/media "$USER@stapp02:/tmp/"
SSHPASS="$PASS" sshpass -e scp $SSHOPTS -r /home/thor/demo  "$USER@stapp02:/tmp/"

# --- Step 2: install + configure on stapp02 (single sudo shell) ---
echo "==> Configuring httpd on stapp02"
REMOTE_CMD='
  yum install -y httpd
  sed -i "s/^Listen 80$/Listen 5000/" /etc/httpd/conf/httpd.conf
  mkdir -p /var/www/html/media /var/www/html/demo
  cp -r /tmp/media/* /var/www/html/media/
  cp -r /tmp/demo/*  /var/www/html/demo/
  apachectl configtest
  systemctl enable --now httpd
  systemctl restart httpd
  echo "--- Listen directive ---"
  grep -i "^Listen" /etc/httpd/conf/httpd.conf
  echo "--- httpd state ---"
  systemctl is-active httpd
'
SSHPASS="$PASS" sshpass -e ssh -n $SSHOPTS "$USER@stapp02" \
  "echo '$PASS' | sudo -S -p '' bash -c '$REMOTE_CMD'" \
  2> >(grep -v '^\[sudo\]' >&2)

# --- Step 3: test on stapp02 (curl runs locally on the app server) ---
echo "===== TEST: /media/ ====="
SSHPASS="$PASS" sshpass -e ssh -n $SSHOPTS "$USER@stapp02" \
  'curl -s http://localhost:5000/media/ | head'

Task 20

The Nautilus application development team is planning to launch a new PHP-based application, which they want to deploy on Nautilus infra in Stratos DC. The development team had a meeting with the production support team and they have shared some requirements regarding the infrastructure. Below are the requirements they shared:

a. Install nginx on app server 2 , configure it to use port 8098 and its document root should be /var/www/html. b. Install php-fpm version 8.1 on app server 2, it must use the unix socket /var/run/php-fpm/default.sock (create the parent directories if don't exist). c. Configure php-fpm and nginx to work together. d. Once configured correctly, you can test the website using curl http://stapp02:8098/index.php command from jump host.

NOTE: We have copied two files, index.php and info.php, under /var/www/html as part of the PHP-based application setup. Please do not modify these files.

# ===== nginx + php-fpm 8.2 setup: jump-host → stapp02 (via sshpass) =====

# --- creds ---
cat > creds.txt <<'EOF'
stapp02 steve Am3ric@
EOF
chmod 600 creds.txt

USER=$(awk '$1=="stapp02"{print $2}' creds.txt)
PASS=$(awk '$1=="stapp02"{print $3}' creds.txt)
SSHOPTS="-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o LogLevel=ERROR"

# --- build nginx server block LOCALLY (quoted heredoc = nginx $vars stay literal) ---
cat > /tmp/php_site.conf <<'EOF'
server {
    listen       8092;
    server_name  stapp02.stratos.xfusioncorp.com;
    root         /var/www/html;
    index        index.php index.html;

    location / {
        try_files $uri $uri/ =404;
    }

    location ~ \.php$ {
        fastcgi_pass unix:/var/run/php-fpm/default.sock;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }
}
EOF

# --- ship the nginx config to stapp02 ---
echo "==> Shipping nginx config"
SSHPASS="$PASS" sshpass -e scp $SSHOPTS /tmp/php_site.conf "$USER@stapp02:/tmp/php_site.conf"

# --- remote: install + configure everything in one sudo shell ---
echo "==> Configuring stapp02"
REMOTE_CMD='
  set -e

  # a. nginx
  yum install -y nginx

  # b. php-fpm 8.2 — enable the module stream then install
  yum module reset php -y 2>/dev/null || true
  yum module enable php:8.2 -y 2>/dev/null || true
  yum install -y php-fpm
  echo "--- php-fpm version ---"
  php-fpm --version | head -1

  # install nginx server block (replace stock default.conf)
  cp /tmp/php_site.conf /etc/nginx/conf.d/default.conf

  # php-fpm pool -> unix socket + nginx ownership
  sed -i "s#^listen = .*#listen = /var/run/php-fpm/default.sock#" /etc/php-fpm.d/www.conf
  sed -i "s/^;*listen.owner = .*/listen.owner = nginx/" /etc/php-fpm.d/www.conf
  sed -i "s/^;*listen.group = .*/listen.group = nginx/" /etc/php-fpm.d/www.conf
  sed -i "s/^;*listen.mode = .*/listen.mode = 0660/" /etc/php-fpm.d/www.conf
  sed -i "s/^user = .*/user = nginx/" /etc/php-fpm.d/www.conf
  sed -i "s/^group = .*/group = nginx/" /etc/php-fpm.d/www.conf

  # create socket parent dir (task requirement)
  mkdir -p /var/run/php-fpm
  chown nginx:nginx /var/run/php-fpm

  # validate nginx config
  nginx -t

  # start + enable both
  systemctl enable --now php-fpm nginx
  systemctl restart php-fpm nginx

  echo "--- states ---"
  systemctl is-active php-fpm
  systemctl is-active nginx
  echo "--- socket ---"
  ls -l /var/run/php-fpm/default.sock
'

SSHPASS="$PASS" sshpass -e ssh -n $SSHOPTS "$USER@stapp02" \
  "echo '$PASS' | sudo -S -p '' bash -c '$REMOTE_CMD'" \
  2> >(grep -v '^\[sudo\]' >&2)

# --- test from jump-host ---
echo "===== TEST: curl http://stapp02:8092/index.php ====="
SSHPASS="$PASS" sshpass -e ssh -n $SSHOPTS "$USER@stapp02" \
  'curl -s http://localhost:8092/index.php | head -20' 2>/dev/null
echo
echo "Direct from jump-host:  curl http://stapp02:8092/index.php"