> ## Documentation Index
> Fetch the complete documentation index at: https://docs.xloud.tech/llms.txt
> Use this file to discover all available pages before exploring further.

# Security Hardening Guide

> Step-by-step pre-deployment security hardening for Xloud Platform — OS hardening, SSH configuration, service minimization, database and message queue hardening.

## Overview

This guide provides a structured hardening walkthrough for Xloud 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.

<Info>**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`.</Info>

<Note>
  **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
</Note>

<Warning>
  Apply hardening before deploying production workloads. Some controls (such as disabling unused kernel modules) require a reboot. Schedule accordingly.
</Warning>

***

## OS Hardening

<Steps titleSize="h3">
  <Step title="Configure SSH" icon="terminal">
    Restrict SSH to key-based authentication and disable direct root login on all nodes:

    ```bash title="Harden SSH configuration" theme={null}
    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
    ```

    <Check>Verify: `ssh root@<node>` is rejected. Key-based login as the `xloud` user succeeds.</Check>
  </Step>

  <Step title="Enable automatic security updates" icon="rotate-cw">
    Configure unattended upgrades for security patches:

    ```bash title="Configure unattended upgrades" theme={null}
    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
    ```
  </Step>

  <Step title="Configure host firewall (ufw)" icon="shield">
    Restrict inbound traffic to required service ports only:

    ```bash title="Configure ufw on control nodes" theme={null}
    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
    ```

    ```bash title="Configure ufw on compute nodes" theme={null}
    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
    ```
  </Step>

  <Step title="Disable unused kernel modules" icon="cpu">
    Remove attack surface by disabling kernel modules that are not required:

    ```bash title="Disable unused modules" theme={null}
    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
    ```
  </Step>

  <Step title="Configure kernel security parameters" icon="settings">
    ```bash title="Apply kernel hardening via sysctl" theme={null}
    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
    ```
  </Step>

  <Step title="Enable AppArmor enforcement" icon="shield-check">
    AppArmor profiles for hypervisor processes ship in enforce mode on XOS. Verify and enable:

    ```bash title="Verify AppArmor status" theme={null}
    aa-status | grep -E "profiles|enforce|complain"
    ```

    Switch complain-mode profiles to enforce:

    ```bash title="Enforce all complain-mode profiles" theme={null}
    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
    ```

    <Check>Run `aa-status` and confirm no profiles remain in complain mode for hypervisor-related processes.</Check>
  </Step>
</Steps>

***

## Service Hardening

<Steps titleSize="h3">
  <Step title="Minimize running services" icon="x-circle">
    Disable services that are not required on each node type:

    ```bash title="Disable unused services on control nodes" theme={null}
    # Services not needed on a dedicated control plane node
    systemctl disable --now cups bluetooth avahi-daemon
    systemctl mask cups bluetooth avahi-daemon
    ```

    ```bash title="Disable unused services on compute nodes" theme={null}
    systemctl disable --now cups bluetooth
    systemctl mask cups bluetooth
    ```
  </Step>

  <Step title="Set file permission baselines" icon="file-lock">
    ```bash title="Restrict sensitive configuration files" theme={null}
    chmod 600 /etc/xavs/passwords.yml
    chmod 750 /etc/xavs/
    find /etc/xavs/certificates/ -type f -name "*.key" -exec chmod 600 {} \;
    ```
  </Step>

  <Step title="Harden the metadata service" icon="server">
    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:

    ```yaml title="/etc/xavs/globals.d/_60_metadata.yml" theme={null}
    neutron_metadata_proxy_shared_secret: "<generate with: openssl rand -hex 32>"
    nova_metadata_enabled: "yes"
    ```

    ```bash title="Deploy metadata hardening" theme={null}
    xavs-ansible reconfigure --tags nova,neutron
    ```
  </Step>

  <Step title="Configure audit daemon (auditd)" icon="list">
    ```bash title="Install and configure auditd" theme={null}
    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
    ```
  </Step>
</Steps>

***

## Database Hardening

<Steps titleSize="h3">
  <Step title="Remove anonymous and test accounts" icon="user-x">
    ```bash title="Audit MariaDB accounts" theme={null}
    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.
  </Step>

  <Step title="Restrict remote root access" icon="lock">
    ```bash title="Disable remote root login" theme={null}
    docker exec mariadb mysql -uroot -p"${MYSQL_ROOT_PASSWORD}" \
      -e "DELETE FROM mysql.user WHERE User='root' AND Host != 'localhost'; FLUSH PRIVILEGES;"
    ```
  </Step>

  <Step title="Enable binary log encryption" icon="database">
    ```yaml title="/etc/xavs/globals.d/_60_db_security.yml" theme={null}
    mariadb_enable_binlog: "yes"
    mariadb_binlog_format: "ROW"
    mariadb_expire_logs_days: "7"
    ```
  </Step>
</Steps>

***

## Message Queue Hardening

<Steps titleSize="h3">
  <Step title="Enable RabbitMQ TLS" icon="lock">
    ```yaml title="/etc/xavs/globals.d/_60_rabbitmq.yml" theme={null}
    rabbitmq_enable_tls: "yes"
    rabbitmq_management_enabled: "yes"
    ```
  </Step>

  <Step title="Remove default guest account" icon="user-x">
    The `guest` account in RabbitMQ is restricted to `localhost` by default in the Xloud deployment. Verify it is not accessible remotely:

    ```bash title="Verify guest user restrictions" theme={null}
    docker exec rabbitmq rabbitmqctl list_users
    # guest user should not appear, or should be tagged as non-admin
    ```
  </Step>

  <Step title="Set queue and message TTLs" icon="clock">
    Configure message TTLs to prevent message queue buildup from accumulating sensitive data:

    ```yaml title="RabbitMQ TTL policy" theme={null}
    rabbitmq_message_ttl: "3600000"
    rabbitmq_queue_ttl: "86400000"
    ```
  </Step>
</Steps>

***

## Pre-Deployment Hardening Checklist

Use this checklist to verify hardening is complete before going to production.

| Category    | Control                    | Verification Command                                                                                        |
| ----------- | -------------------------- | ----------------------------------------------------------------------------------------------------------- |
| SSH         | Root login disabled        | `grep PermitRootLogin /etc/ssh/sshd_config`                                                                 |
| SSH         | Password auth disabled     | `grep PasswordAuthentication /etc/ssh/sshd_config`                                                          |
| OS          | Auto-updates active        | `systemctl is-enabled unattended-upgrades`                                                                  |
| OS          | Host firewall enabled      | `ufw status`                                                                                                |
| OS          | ASLR enabled               | `sysctl kernel.randomize_va_space`                                                                          |
| OS          | AppArmor enforcing         | `aa-status --json \| python3 -c "import sys,json; d=json.load(sys.stdin); print(len(d.get('enforce',[])))"` |
| Services    | Unused services disabled   | `systemctl list-units --state=active --type=service`                                                        |
| TLS         | External TLS active        | `openssl s_client -connect <vip>:443 \| openssl x509 -noout -enddate`                                       |
| TLS         | Internal TLS active        | `grep "enable_tls_internal" /etc/xavs/globals.d/_60_tls.yml`                                                |
| Certs       | Certificate not expired    | `openssl x509 -in /etc/xavs/certificates/haproxy.crt -noout -enddate`                                       |
| Permissions | Passwords files restricted | `stat -c "%a %U %G" /etc/xavs/passwords.yml`                                                                |
| Metadata    | Shared secret set          | `grep "neutron_metadata_proxy_shared_secret" /etc/xavs/globals.d/`                                          |
| Database    | No anonymous users         | `docker exec mariadb mysql -e "SELECT user,host FROM mysql.user WHERE user=''"`                             |
| Audit       | auditd running             | `systemctl is-active auditd`                                                                                |
| Audit       | Audit rules loaded         | `auditctl -l \| wc -l`                                                                                      |

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Infrastructure Security" href="/security/infrastructure" color="#197560">
    TLS configuration and certificate management
  </Card>

  <Card title="Compliance" href="/security/compliance" color="#197560">
    Map hardening controls to SOC 2, ISO 27001, and PCI-DSS requirements
  </Card>

  <Card title="Network Security" href="/security/network-security" color="#197560">
    Security groups, FWaaS, and network segmentation
  </Card>

  <Card title="Troubleshooting" href="/security/hardening-guide" color="#197560">
    Diagnose and resolve common security configuration issues
  </Card>
</CardGroup>
