root@server.marketmenia.com Knowledge Base

Server Administration Reference

Derived from root history log · cPanel/AlmaLinux · NexaForce + MarketMenia hosting

Last activity: 18 Jul 2026 · Generated from 600 history entries

🖥️

Server Overview

Hostname
server.marketmenia.com
OS
AlmaLinux (RHEL-based)
Control Panel
cPanel / WHM
Web Server
Apache 2.4.68 (cPanel)
Apache Binary
/usr/local/apache/bin/httpd
Apache Config
/usr/local/apache/conf/httpd.conf
Apache Logs
/usr/local/apache/logs/
SSL Provider
cPanel AutoSSL
Firewall
CSF (ConfigServer)
Package Manager
dnf (rpm-based)
PHP
ea-php (cPanel EasyApache)
Container Runtime
Docker + Compose
⚠️ This server runs cPanel's Apache, not the system Apache2. Always use /usr/local/cpanel/scripts/restartsrv_httpd to restart, and /usr/local/apache/bin/apachectl for config tests. Standard systemctl reload httpd also works but goes through cPanel's layer.

Key Hosted Sites / Services

Domain / ServiceUser / PathTypeStatus
nexaforceai.in nexaforceai Docker Live
api.nexaforceai.in nexaforceai Docker Live
nexaforce-connector.marketmenia.com /home/marketmenia/nexaforce-connector Docker Live
demo.marketmenia.com /home/marketmenia/demo.marketmenia.com PHP Live
sandbox.marketmenia.com /home/marketmenia/sandbox.marketmenia.com PHP Live
crm.safalacademy.com hosted on this server PHP Live
👤

Users & Access

UserHomeRoleNotes
root /root System administrator Full access; session timeout configured in /etc/profile
nexaforceai /home/nexaforceai NexaForce Platform owner Shell enabled via whmapi1 modifyacct … HASSHELL=1; added to wheel group with sudo; visudo configured
marketmenia /home/marketmenia MarketMenia account owner Hosts connector, demo, and sandbox sites; also runs nexaforce-connector Docker stack
cashpeloan_dev — MySQL DB user Access to cashpeloan_dev DB; needed Docker subnet grant (172.22.0.%)

Switching Users

su - nexaforceai # switch to NexaForce user sudo su - nexaforceai # from root with sudo whmlogin # generate WHM one-time login URL (root only)
ℹ️ Shell login for nexaforceai was originally disabled (cPanel default). It was enabled via WHM API (HASSHELL=1) and sudo was configured via visudo. If it stops working after a cPanel update, re-run the modifyacct command.

Session Timeout

Root shell timeout was adjusted in /etc/profile (the TMOUT variable). Run source /etc/profile after editing for the change to take effect in the current session.

🔌

NexaForce Connector

A Docker-based middleware service that bridges the NexaForce AI Platform with the client's local MySQL database. Deployed under the marketmenia cPanel account.

Location
/home/marketmenia/nexaforce-connector/
Public URL
nexaforce-connector.marketmenia.com
Internal Port
127.0.0.1:8090 → container:8080
SSL
cPanel AutoSSL
Container Name
nexaforce-connector
DB Connected
cashpeloan_dev (MySQL)

Files

FilePurpose
.envAll runtime config: DB credentials, webhook token, HMAC secret, NexaForce API URL
docker-compose.ymlService definition; port mapped as 127.0.0.1:8090:8080

Key .env Variables

VariableDescription
DB_HOSTMySQL host (Docker gateway IP, e.g. 172.22.0.1 or host.docker.internal)
DB_PORTMySQL port (default 3306)
DB_USERcashpeloan_dev
DB_PASSWORDMySQL password for cashpeloan_dev
DB_NAMEcashpeloan_dev
DB_FIELD_MAPJSON mapping of NexaForce field names → DB column names
NEXAFORCE_SECRETHMAC-SHA256 signing secret (32-byte hex); must match NexaForce Platform config
WEBHOOK_TOKENBearer token for inbound webhook from NexaForce (X-Webhook-Token header)
NEXAFORCE_API_URLhttps://api.nexaforceai.in

Common Operations

# Start / restart cd /home/marketmenia/nexaforce-connector docker compose up -d # Pull latest image and restart docker compose pull && docker compose up -d # Check status docker compose ps # View live logs docker compose logs connector -f # Health check curl http://localhost:8090/health curl https://nexaforce-connector.marketmenia.com/health

Test Lookup Endpoint

PHONE="919990671176" BODY="{\"phone\": \"$PHONE\"}" SECRET="<NEXAFORCE_SECRET from .env>" SIG=$(python3 -c "import hashlib,hmac; print(hmac.new(b'$SECRET', b'$BODY', hashlib.sha256).hexdigest())") curl -X POST https://nexaforce-connector.marketmenia.com/lookup \ -H "Content-Type: application/json" \ -H "X-NexaForce-Signature: $SIG" \ -H "X-NexaForce-Timestamp: $(date -u +%Y-%m-%dT%H:%M:%SZ)" \ -d "$BODY"

Test Webhook Endpoint

curl -X POST https://nexaforce-connector.marketmenia.com/webhook \ -H "Content-Type: application/json" \ -H "X-Webhook-Token: <WEBHOOK_TOKEN from .env>" \ -d '{"phone": "919990671176", "name": "Test Lead", "loan_type": "personal"}'
⚠️ MySQL access from Docker: The connector runs in a Docker subnet (172.22.0.x). The MySQL user cashpeloan_dev must have a grant for 'cashpeloan_dev'@'172.22.0.%' — not just localhost. See the Database section for the grant command.

Apache Reverse Proxy

SSL termination is handled by Apache (cPanel AutoSSL). The connector domain proxies to 127.0.0.1:8090. The config was attempted at /etc/apache2/conf.d/nexaforce-connector.conf but on this cPanel server the correct path is the cPanel include system. If Apache breaks after editing conf.d, rename or remove the file and use cPanel's reverse proxy UI instead.

🗄️

MySQL / Database

DB Name
cashpeloan_dev
DB User (local)
cashpeloan_dev@localhost
DB User (Docker)
cashpeloan_dev@172.22.0.%
Key Table
lead (mobile_number field)

Grant Docker Subnet Access

Run this whenever the Docker network subnet changes or a new DB user is needed for the connector:

mysql -u root -p -- Create user for Docker subnet (if not exists) CREATE USER IF NOT EXISTS 'cashpeloan_dev'@'172.22.0.%' IDENTIFIED BY '<password>'; -- Grant SELECT on the lead table (minimum needed for /lookup) GRANT SELECT ON cashpeloan_dev.lead TO 'cashpeloan_dev'@'172.22.0.%'; FLUSH PRIVILEGES; EXIT;

Find Docker Gateway IP

# Get the gateway IP the connector container uses to reach the host MySQL docker inspect nexaforce-connector | grep Gateway # or ip route | grep docker

Test DB Connection from Inside Container

docker exec nexaforce-connector python3 -c " import asyncio, aiomysql, os async def test(): conn = await aiomysql.connect( host=os.environ.get('DB_HOST'), port=int(os.environ.get('DB_PORT', 3306)), user=os.environ.get('DB_USER'), password=os.environ.get('DB_PASSWORD'), db=os.environ.get('DB_NAME'), ) print('Connected OK') async with conn.cursor() as cur: await cur.execute('SELECT mobile_number FROM lead LIMIT 3') print('Rows:', await cur.fetchall()) conn.close() asyncio.run(test()) "

Root .my.cnf

Root MySQL credentials may be stored in /root/.my.cnf for passwordless CLI access.

cat /root/.my.cnf
⚙️

Apache / httpd

🚨 cPanel manages Apache config. Do NOT directly edit /usr/local/apache/conf/httpd.conf for vhost settings — cPanel will overwrite it. Use cPanel's MultiPHP, Apache configuration tools, or include files.

MPM Worker Tuning

A traffic spike caused Apache to hit MaxRequestWorkers. The limit was raised by editing httpd.conf directly (emergency fix). The proper way is via cPanel's Apache Global Configuration or /var/cpanel/conf/apache/local.

# Check current MPM and limits apachectl -V | grep MPM apachectl -t -D DUMP_RUN_CFG | egrep "ServerLimit|MaxRequestWorkers|ThreadsPerChild" # Check local cPanel overrides grep -i "maxclients\|maxrequestworkers\|serverlimit" /var/cpanel/conf/apache/local

Essential Commands

# Test config syntax /usr/local/apache/bin/apachectl -t # Graceful reload (preferred — no dropped connections) /usr/local/cpanel/scripts/restartsrv_httpd # or systemctl reload httpd # Full restart (use only if reload fails) systemctl restart httpd # Error log tail -f /usr/local/apache/logs/error_log tail -500 /usr/local/apache/logs/error_log # Active connections on 80/443 ss -antp | grep ':80\|:443' | wc -l

PHP-FPM

systemctl status php-fpm journalctl -u php-fpm --since "1 hour ago" grep -Ri "max_children\|slow\|timeout\|fatal" /opt/cpanel/ea-php*/root/usr/var/log/

SSL Certificates

# Check AutoSSL for an account /usr/local/cpanel/bin/autossl_check --user=marketmenia # List installed certs ls /var/cpanel/ssl/installed/certs/ | grep nexaforce
⚠️ An SSL cert warning was seen: "server certificate does NOT include an ID which matches the server name" for nexaforceai.in:443. This is a warning, not a fatal error, but should be resolved by ensuring AutoSSL has issued a cert for all configured server aliases.
🐳

Docker

Running Containers

ContainerManaged byNotes
nexaforce-nextjs nexaforceai user Next.js frontend dashboard (has health check configured)
nexaforce-caddy nexaforceai user Reverse proxy / SSL for NexaForce containers
nexaforce_db nexaforceai user PostgreSQL for NexaForce platform (psql -U nexaforce nexaforce)
nexaforce-connector marketmenia / root CRM connector at /home/marketmenia/nexaforce-connector

Useful Commands

# Overview docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" docker stats --no-stream # Logs docker logs --tail 300 nexaforce-nextjs docker logs --since 30m nexaforce-nextjs # Health check status docker inspect nexaforce-nextjs | grep -A 50 Health # Check NexaForce DB tables docker exec nexaforce_db psql -U nexaforce nexaforce "\dt;" # Check env inside container docker exec nexaforce-connector env | grep DB_
ℹ️ The NexaForce platform stack (nextjs, caddy, db, api, worker) is managed by the nexaforceai user. The connector stack is managed from /home/marketmenia/nexaforce-connector — often run as root or marketmenia user.
🔒

Firewall / CSF / Security

Firewall
CSF (ConfigServer Security)
CSF Config
/etc/csf/csf.conf

Block / Unblock an IP

# Block (permanent via CSF) csf -d 35.240.162.123 # Block (immediate via iptables — not persistent across csf restart) iptables -I INPUT -s 35.240.162.123 -j DROP # Check current rules iptables -L INPUT -n -v csf -g 35.240.162.123 # grep CSF for an IP

SMTP Redirect Issue (Jul 2026)

SMTP emails from PHP (port 587) were being silently redirected. The fix was removing a NAT redirect rule:

# Check if SMTP is being redirected grep SMTP_REDIRECT /etc/csf/csf.conf grep SMTP_BLOCK /etc/csf/csf.conf iptables-save | grep REDIRECT # If a rogue NAT rule exists, remove it iptables -t nat -D OUTPUT -p tcp -m multiport --dports 25,465,587 -j REDIRECT

Check Outbound Connectivity

ping smtp.gmail.com openssl s_client -connect smtp.gmail.com:587 -starttls smtp
📅

Change Timeline

3 May 2026
cPanel Update
Ran /scripts/upcp --force to force cPanel version upgrade. Verified version and ran IOC session check script.
23 May 2026
nexaforceai User Setup
Enabled shell for nexaforceai cPanel account via whmapi1 modifyacct HASSHELL=1. Added to wheel group and configured sudo via visudo.
16 Jun 2026
Apache Traffic Spike Investigation
Apache hit MaxRequestWorkers limit. Investigated PHP-FPM, connection counts, OOM killer. Blocked a suspicious IP (35.240.162.123). Raised worker limits in httpd.conf as emergency fix.
26 Jun – 4 Jul 2026
Memory Optimisation & SMTP Fix
Dropped OS page cache (drop_caches). Diagnosed SMTP redirect issue — CSF was blocking outbound SMTP on 587. Removed the NAT redirect rule.
5 Jul 2026
System Package Update
Ran dnf update -y and installed git, curl, vim, tar, unzip. Tested Docker and Compose versions. Nginx install attempted but port 80 conflict with Apache — not activated.
11–12 Jul 2026
NexaForce Connector Deployed
Created /home/marketmenia/nexaforce-connector/. Downloaded docker-compose.yml and .env.example from NexaForce repo. Configured with cashpeloan_dev MySQL credentials. Fixed port binding to 127.0.0.1:8090:8080. Attempted Apache reverse proxy via /etc/apache2/conf.d/ — caused issues; conf backed up and removed. AutoSSL issued cert for nexaforce-connector.marketmenia.com.
12–13 Jul 2026
MySQL Docker Access & Connector Testing
Granted MySQL access for Docker subnet (172.22.0.%). Tested /lookup and /webhook endpoints. Verified DB connection from inside the container. New NEXAFORCE_SECRET and WEBHOOK_TOKEN generated.
13 Jul 2026
Connector Image Pull & Full Restart
Pulled latest connector image (docker compose pull && docker compose up -d). Webhook test confirmed end-to-end flow working.
16–17 Jul 2026
.env Updates & Connector Re-test
Multiple .env edits (DB credentials/field map adjustments). Connector pulled and restarted. MySQL grants re-verified.
18 Jul 2026
History Documented
This knowledge base generated from root bash history.
⚡

Quick Reference

Daily Operations

# Health check all services systemctl status httpd --no-pager docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" free -mh uptime # Check Apache error log (last 100 lines) tail -100 /usr/local/apache/logs/error_log # Connector health curl https://nexaforce-connector.marketmenia.com/health # Switch to NexaForce user to manage platform sudo su - nexaforceai

Generate a Secret Key

python3 -c "import secrets; print(secrets.token_hex(32))"

cPanel Specific

# WHM one-time login URL whmlogin # Restart Apache via cPanel (preferred over systemctl) /usr/local/cpanel/scripts/restartsrv_httpd # Run AutoSSL for a user /usr/local/cpanel/bin/autossl_check --user=marketmenia # Check cPanel version cat /usr/local/cpanel/version

Emergency: Apache Won't Start

# 1. Test config /usr/local/apache/bin/apachectl -t # 2. Check for syntax errors — look at what file failed grep -i "error\|invalid\|cannot" /usr/local/apache/logs/error_log | tail -20 # 3. If a conf.d file is the problem, back it up and remove mv /etc/apache2/conf.d/problem-file.conf /etc/apache2/conf.d/problem-file.conf.bak # 4. Restart /usr/local/cpanel/scripts/restartsrv_httpd

Emergency: Connector Down

cd /home/marketmenia/nexaforce-connector docker compose ps # check status docker compose logs connector --tail 50 # check errors nano .env # verify credentials docker compose down && docker compose up -d # full restart