Skip to main content

Overview

This guide provides a structured hardening walkthrough for Xloud Cloud Platform nodes. Apply these controls before the first production deployment. The checklist at the end of this page provides a verification reference for compliance audits. Hardening operates at four levels: the host operating system (XOS), the Xloud platform services, supporting infrastructure components (database, message queue), and the metadata service.
Xloud-Developed — XAVS ships with automated hardening roles that enforce CIS benchmarks out of the box. Automated controls include SSH hardening and allowlisting, audit logging configuration, Docker security benchmarks, and AppArmor profile enforcement. These roles run during initial deployment and can be re-applied at any time via xavs-ansible reconfigure --tags hardening.
Prerequisites
  • XOS installed on all control and compute nodes
  • XDeploy access with bootstrap credentials
  • SSH access to all cluster nodes
  • A change management window — some steps require service restarts
Apply hardening before deploying production workloads. Some controls (such as disabling unused kernel modules) require a reboot. Schedule accordingly.

OS Hardening

Configure SSH

Restrict SSH to key-based authentication and disable direct root login on all nodes:
Harden SSH configuration
cat >> /etc/ssh/sshd_config << 'EOF'
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
X11Forwarding no
AllowTcpForwarding no
MaxAuthTries 3
ClientAliveInterval 300
ClientAliveCountMax 2
LoginGraceTime 30
EOF

systemctl restart sshd
Verify: ssh root@<node> is rejected. Key-based login as the xloud user succeeds.

Enable automatic security updates

Configure unattended upgrades for security patches:
Configure unattended upgrades
apt-get install -y unattended-upgrades apt-listchanges

cat > /etc/apt/apt.conf.d/50unattended-upgrades << 'EOF'
Unattended-Upgrade::Allowed-Origins {
  "${distro_id}:${distro_codename}-security";
};
Unattended-Upgrade::AutoFixInterruptedDpkg "true";
Unattended-Upgrade::MinimalSteps "true";
Unattended-Upgrade::Mail "security@your-org.com";
Unattended-Upgrade::Remove-Unused-Kernel-Packages "true";
Unattended-Upgrade::Remove-Unused-Dependencies "true";
EOF

systemctl enable unattended-upgrades
systemctl start unattended-upgrades

Configure host firewall (ufw)

Restrict inbound traffic to required service ports only:
Configure ufw on control nodes
ufw default deny incoming
ufw default allow outgoing
ufw allow from 10.0.0.0/8 to any port 22    # SSH from management network
ufw allow from 10.0.0.0/8 to any port 443   # HTTPS API
ufw allow from 10.0.0.0/8 to any port 5000  # Keystone
ufw allow from 10.0.0.0/8 to any port 8774  # Nova API
ufw allow from 10.0.0.0/8 to any port 9696  # Neutron
ufw enable
Configure ufw on compute nodes
ufw default deny incoming
ufw default allow outgoing
ufw allow from 10.0.0.0/8 to any port 22      # SSH
ufw allow from 10.0.0.0/8 to any port 16509   # libvirt
ufw allow from 10.0.0.0/8 to any port 49152:49215/tcp  # live migration
ufw enable

Disable unused kernel modules

Remove attack surface by disabling kernel modules that are not required:
Disable unused modules
cat > /etc/modprobe.d/hardening.conf << 'EOF'
# Disable uncommon filesystems
install cramfs /bin/true
install freevxfs /bin/true
install jffs2 /bin/true
install hfs /bin/true
install hfsplus /bin/true
install squashfs /bin/true
install udf /bin/true

# Disable uncommon network protocols
install dccp /bin/true
install sctp /bin/true
install rds /bin/true
install tipc /bin/true
EOF

Configure kernel security parameters

Apply kernel hardening via sysctl
cat > /etc/sysctl.d/99-hardening.conf << 'EOF'
# Network hardening
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.all.secure_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.icmp_ignore_bogus_error_responses = 1
net.ipv4.tcp_syncookies = 1
net.ipv4.conf.all.log_martians = 1

# Memory hardening
kernel.randomize_va_space = 2
kernel.dmesg_restrict = 1
kernel.kptr_restrict = 2
fs.protected_hardlinks = 1
fs.protected_symlinks = 1
EOF

sysctl -p /etc/sysctl.d/99-hardening.conf

Enable AppArmor enforcement

AppArmor profiles for hypervisor processes ship in enforce mode on XOS. Verify and enable:
Verify AppArmor status
aa-status | grep -E "profiles|enforce|complain"
Switch complain-mode profiles to enforce:
Enforce all complain-mode profiles
for profile in $(aa-status --json | python3 -c "
import sys, json
d = json.load(sys.stdin)
for p in d.get('complain', []): print(p)
"); do
  aa-enforce /etc/apparmor.d/$profile 2>/dev/null || true
done
Run aa-status and confirm no profiles remain in complain mode for hypervisor-related processes.

Service Hardening

Minimize running services

Disable services that are not required on each node type:
Disable unused services on control nodes
# Services not needed on a dedicated control plane node
systemctl disable --now cups bluetooth avahi-daemon
systemctl mask cups bluetooth avahi-daemon
Disable unused services on compute nodes
systemctl disable --now cups bluetooth
systemctl mask cups bluetooth

Set file permission baselines

Restrict sensitive configuration files
chmod 600 /etc/xavs/passwords.yml
chmod 750 /etc/xavs/
find /etc/xavs/certificates/ -type f -name "*.key" -exec chmod 600 {} \;

Harden the metadata service

The instance metadata service is accessible at 169.254.169.254 from all VMs. Enable the shared secret to prevent unauthorized cross-tenant metadata access:
/etc/xavs/globals.d/_60_metadata.yml
neutron_metadata_proxy_shared_secret: "<generate with: openssl rand -hex 32>"
nova_metadata_enabled: "yes"
Deploy metadata hardening
xavs-ansible reconfigure --tags nova,neutron

Configure audit daemon (auditd)

Install and configure auditd
apt-get install -y auditd audispd-plugins

cat >> /etc/audit/rules.d/hardening.rules << 'EOF'
# Monitor privileged command execution
-a always,exit -F arch=b64 -S execve -F euid=0 -k privileged
# Monitor file permission changes on sensitive paths
-w /etc/passwd -p wa -k identity
-w /etc/shadow -p wa -k identity
-w /etc/xavs/passwords.yml -p rwa -k xavs-passwords
# Monitor network configuration changes
-a always,exit -F arch=b64 -S sethostname -S setdomainname -k network-config
EOF

augenrules --load
systemctl enable auditd
systemctl start auditd

Database Hardening

Remove anonymous and test accounts

Audit MariaDB accounts
docker exec mariadb mysql -uroot -p"${MYSQL_ROOT_PASSWORD}" \
  -e "SELECT user, host, password FROM mysql.user ORDER BY user;"
Remove any anonymous accounts and the test database if present.

Restrict remote root access

Disable remote root login
docker exec mariadb mysql -uroot -p"${MYSQL_ROOT_PASSWORD}" \
  -e "DELETE FROM mysql.user WHERE User='root' AND Host != 'localhost'; FLUSH PRIVILEGES;"

Enable binary log encryption

/etc/xavs/globals.d/_60_db_security.yml
mariadb_enable_binlog: "yes"
mariadb_binlog_format: "ROW"
mariadb_expire_logs_days: "7"

Message Queue Hardening

Enable RabbitMQ TLS

/etc/xavs/globals.d/_60_rabbitmq.yml
rabbitmq_enable_tls: "yes"
rabbitmq_management_enabled: "yes"

Remove default guest account

The guest account in RabbitMQ is restricted to localhost by default in the Xloud deployment. Verify it is not accessible remotely:
Verify guest user restrictions
docker exec rabbitmq rabbitmqctl list_users
# guest user should not appear, or should be tagged as non-admin

Set queue and message TTLs

Configure message TTLs to prevent message queue buildup from accumulating sensitive data:
RabbitMQ TTL policy
rabbitmq_message_ttl: "3600000"
rabbitmq_queue_ttl: "86400000"

Pre-Deployment Hardening Checklist

Use this checklist to verify hardening is complete before going to production.
CategoryControlVerification Command
SSHRoot login disabledgrep PermitRootLogin /etc/ssh/sshd_config
SSHPassword auth disabledgrep PasswordAuthentication /etc/ssh/sshd_config
OSAuto-updates activesystemctl is-enabled unattended-upgrades
OSHost firewall enabledufw status
OSASLR enabledsysctl kernel.randomize_va_space
OSAppArmor enforcingaa-status --json | python3 -c "import sys,json; d=json.load(sys.stdin); print(len(d.get('enforce',[])))"
ServicesUnused services disabledsystemctl list-units --state=active --type=service
TLSExternal TLS activeopenssl s_client -connect <vip>:443 | openssl x509 -noout -enddate
TLSInternal TLS activegrep "enable_tls_internal" /etc/xavs/globals.d/_60_tls.yml
CertsCertificate not expiredopenssl x509 -in /etc/xavs/certificates/haproxy.crt -noout -enddate
PermissionsPasswords files restrictedstat -c "%a %U %G" /etc/xavs/passwords.yml
MetadataShared secret setgrep "neutron_metadata_proxy_shared_secret" /etc/xavs/globals.d/
DatabaseNo anonymous usersdocker exec mariadb mysql -e "SELECT user,host FROM mysql.user WHERE user=''"
Auditauditd runningsystemctl is-active auditd
AuditAudit rules loadedauditctl -l | wc -l

Next Steps

Infrastructure Security

TLS configuration and certificate management

Compliance

Map hardening controls to SOC 2, ISO 27001, and PCI-DSS requirements

Network Security

Security groups, FWaaS, and network segmentation

Troubleshooting

Diagnose and resolve common security configuration issues