===== Darwin Setup ===== This page documents the main steps used to set up Darwin. ==== Head Node OS Installation ==== * **Download [[https://download.rockylinux.org/pub/rocky/9/isos/x86_64/Rocky-9.8f-x86_64-dvd.iso|Rocky Linux 9.8 x86_64 DVD ISO]]** * **Install ISO** * **Add password for root, unlock root, enable SSH with password** * **Add 'localadmin' administrator. DO NOT USE '!' OR '$' IN PASSWORD** * **Disable IPv6 on all network devices** * **Set hostname to 'darwin'** * **Merge '/' and '/home' (remove '/home' partition)** ==== Head Node Setup ==== * **Connect to the head node** ssh localadmin@192.168.1.152 sudo -i * **Enable persistent logging** systemd-tmpfiles --create --prefix /var/log/journal mkdir -p /etc/systemd/journald.conf.d printf '%s\n' '[Journal]' 'Storage=persistent' \ >/etc/systemd/journald.conf.d/persistent.conf systemctl restart systemd-journald * **Set up kdump and netconsole** install \ -d \ -m 0755 \ /var/log/netconsole \ /var/crash/compute tar -xzpf /root/assets/netconsole.tar.gz -C / systemctl daemon-reload cat > /etc/exports.d/kdump-compute.exports << 'EOF' /var/crash/compute 10.141.0.0/16(rw,sync,no_subtree_check,no_root_squash) EOF exportfs -ra systemctl reload nfs-server systemctl restart rsyslog * **Install the required packages** dnf install -y \ epel-release \ https://yum.osc.edu/ondemand/3.1/ondemand-release-compute-3.1-1.el9.noarch.rpm \ https://www.elrepo.org/elrepo-release-9.el9.elrepo.noarch.rpm && dnf config-manager --set-enabled crb && dnf --enablerepo=elrepo-kernel install -y kmod-mlx4 && dnf install -y \ git-core \ gh \ opensm \ ripgrep \ tmux \ fio \ iotop \ selinux-policy-devel \ fail2ban fail2ban-firewalld \ turbovnc && systemctl enable --now opensm fail2ban && reboot * **Disable %%GUI%% autoupdates** cat > /etc/dconf/db/local.d/00-gnome-software << EOF [org/gnome/software] allow-updates=false download-updates=false download-updates-notify=false EOF cat > /etc/dconf/db/local.d/locks/00-gnome-software << EOF /org/gnome/software/allow-updates /org/gnome/software/download-updates /org/gnome/software/download-updates-notify EOF dconf update * **Add network connections** nmcli con add \ type ethernet \ ifname eno2 \ con-name internal \ ipv4.method manual \ ipv4.addresses 10.141.255.254/16 \ ipv4.gateway "" \ ipv6.method disable nmcli con up internal nmcli con add \ type ethernet \ ifname enp2s0 \ con-name bmc \ ipv4.method manual \ ipv4.addresses 10.148.255.254/16 \ ipv4.gateway "" \ ipv6.method disable nmcli con up bmc nmcli con add \ type infiniband \ ifname ibp3s0 \ con-name ib \ ipv4.method manual \ ipv4.addresses 10.149.255.254/16 \ ipv4.gateway "" \ ipv6.method disable nmcli con up ib * **Set up RAID** cat >> /etc/fstab/ << EOF UUID=b5788192-0303-4ef5-944e-ac6354bd0938 /trinity/home ext4 defaults 0 0 UUID=fab54cdf-d1c6-4d7c-ae83-649a480ab3cb /trinity/structbio_home ext4 defaults,noatime 0 0 UUID=d27804ca-99df-4b46-ae65-1f04bfcb80fa /opt ext4 defaults 0 2 EOF systemctl daemon-reload cat > /etc/mdadm.conf << EOF ARRAY /dev/md/newton:2 metadata=1.2 UUID=080b6df8:ddb3019f:665d341e:5fcaabc7 ARRAY /dev/md/struct_biotech metadata=1.2 spares=1 UUID=72c25cfc:fc70a47f:3d22ce14:7e5a00cc EOF * **If a proxy is required** * **Set environment variables** cat >> ~/.bashrc << 'EOF' proxy() { local PROXY="http://localhost:10808" export http_proxy="$PROXY" export https_proxy="$PROXY" export HTTP_PROXY="$PROXY" export HTTPS_PROXY="$PROXY" } EOF . ~/.bashrc * **Forward a proxy port (use any free port if a VPN is enabled)** ssh -N -R 17890:127.0.0.1: root@192.168.1.152 OR cat > /etc/profile.d/aliases.sh << 'EOF' case "$-" in *i*) ;; *) return 0 2>/dev/null || exit 0 ;; esac alias vpn="ip route replace default via 192.168.1.182 dev eno1" alias disvpn="ip route del default via 192.168.1.182 dev eno1" EOF chmod 700 /etc/profile.d/aliases.sh * **Download trinityX** cd git clone http://github.com/clustervision/trinityX && cd trinityX * **Install trinityX** cd ~/trinityX bash prepare.sh && cd site Answer 'y' to a message about SELinux. Reboot and repeat script run if asked to. Answer 'n' to a message about ZFS. * **Disable SSL** sed -i \ -e 's/enable_ssl: true/enable_ssl: false/g' \ controller.yml sed -i \ '/grafana_prometheus_url/s/:9090"/:9090\/prometheus"/' \ /root/trinityX/site/controller.yml * **Enable RDMA for NFS and mount /home, /shared, /opt, /ohpc** sed -i \ "/^trix_ctrl_hostname:/a \ # -----------------------------------------------------------------------\ # Storage node IP address.\ # Used to mount shared filesystems (home, opt, shared, scratch) via NFS RDMA.\ # In a single-node setup, this should match the controller's InfiniBand IP.\ \ trix_storage_ip: 10.149.255.254" \ group_vars/all.yml.example && sed -i \ -e 's/nfs_enable_rdma: false/nfs_enable_rdma: true/' \ -e '/# easybuild/,/disabled:/ { /disabled:/a \ # opt ------------------------------------------------------------------------------ \ - path: '\''/opt'\'' \ options: '\''*(rw,async,no_root_squash)'\'' \ rwhosts: '\''{{ all_ctrl_hostname | join(" ") }} {{ trix_ctrl_hostname if ha else "" }}'\'' \ # structbio_home ------------------------------------------------------------------------------ \ - path: '\''/trinity/structbio_home'\'' \ options: '\''*(rw,no_root_squash)'\'' \ rwhosts: '\''{{ all_ctrl_hostname | join(" ") }} {{ trix_ctrl_hostname if ha else "" }}'\'' \ }' \ controller.yml && sed -i \ -e 's/nfs_enable_rdma: false/nfs_enable_rdma: true/' \ -e '/remote:/s/{{ trix_ctrl_hostname }}/{{ trix_storage_ip }}/g' \ -e "/- path: '{{ trix_shared }}'/,/options: 'defaults,nfsvers=4.2,ro,retrans=4,_netdev'/d" \ -e "/- path: '{{ trix_home }}'/,/options: 'defaults,nfsvers=4.2,rw,retrans=4,noatime,_netdev'/d" \ -e '1,/nfs_mounts:/!b' \ -e '/nfs_mounts:/a \ - path: '\''{{ trix_shared }}'\''\ remote: '\''{{ trix_storage_ip }}:{{ trix_shared }}'\''\ options: '\''defaults,nfsvers=4.2,rsize=1048576,wsize=1048576,hard,timeo=600,ro,retrans=4,noatime,_netdev'\''\ - path: '\''{{ trix_home }}'\''\ remote: '\''{{ trix_storage_ip }}:{{ trix_home }}'\''\ options: '\''defaults,nfsvers=4.2,rsize=1048576,wsize=1048576,hard,timeo=600,rw,retrans=4,noatime,_netdev'\''\ - path: '\''/trinity/structbio_home'\''\ remote: '\''{{ trix_storage_ip }}:/trinity/structbio_home'\''\ options: '\''defaults,nfsvers=4.2,rsize=1048576,wsize=1048576,hard,timeo=600,rw,retrans=4,noatime,_netdev'\''\ - path: '\''/opt'\''\ remote: '\''{{ trix_storage_ip }}:/opt'\''\ options: '\''defaults,nfsvers=4.2,rsize=1048576,wsize=1048576,hard,timeo=600,rw,retrans=4,noatime,_netdev'\'''\ imports/trinity-redhat-image-setup.yml * **Enable PAM Slurm adopt module** sed -i \ -e '/^account[[:space:]]\{1,\}include[[:space:]]\{1,\}password-auth$/a\account required pam_slurm_adopt.so' \ /root/trinityX/site/roles/trinity/slurm/files/pam-sshd sed -i \ 's/^enable_slurm_pam:[[:space:]]*false$/enable_slurm_pam: true/' \ /root/trinityX/site/roles/trinity/slurm/defaults/main.yml * **Fix Prometheus path** sed -i \ $'/when: luna2_daemon_pip is undefined/a\ - name: Patch luna2 daemon Prometheus route prefix\ ansible.builtin.replace:\ path: '\''{{ luna2_python_dir.stdout }}/site-packages/daemon/plugins/import/prometheus_hw_rules.py'\''\ regexp: '\''self\\.prometheus_url = "https://localhost:9090"'\''\ replace: '\''self.prometheus_url = "http://localhost:9090/prometheus"'\''' \ /root/trinityX/site/roles/trinity/luna2/tasks/controller.yml * **Prepare Ansible inventory** cat > hosts << EOF [controllers] darwin ansible_connection=local EOF * **Prepare the head node playbook** cp group_vars/all.yml.example group_vars/all.yml sed -i \ -e 's/^trix_ctrl1_hostname:.*/trix_ctrl1_hostname: darwin/' \ -e "s|^trix_external_fqdn:.*|trix_external_fqdn: 'portal.darwin.bioeng.ru'|" \ -e 's/^\([[:space:]]*\)-[[:space:]]*"8\.8\.8\.8"/\1- "192.168.1.3"/' \ -e 's/^\([[:space:]]*\)-[[:space:]]*"8\.8\.4\.4"/\1- "192.168.1.1"/' \ -e 's/^luna_password:.*/luna_password: .../' \ -e 's/^luna_protocol:.*/luna_protocol: http/' \ -e 's/^firewalld_public_interfaces:.*/firewalld_public_interfaces: [eno1]/' \ -e 's/^firewalld_trusted_interfaces:.*/firewalld_trusted_interfaces: [eno2, enp23s0, ibp180s0]/' \ -e 's/^firewalld_public_tcp_ports:.*/firewalld_public_tcp_ports: [22, 80, 443]/' \ group_vars/all.yml * **Patch playbook to install OOD apps idempotently** sed -i -f - /root/trinityX/site/roles/trinity/ood-apps/tasks/app.yml <<'SED' /^ - name: Make folder for app /,/^ notify: Run update_ood$/ { /^ notify: Run update_ood$/ a\ - name: Ensure web server can traverse trinity app directory\ ansible.posix.acl:\ path: "{{ app_path }}"\ entity: apache\ etype: user\ permissions: rx\ state: present\ when:\ - app_enabled\ - app.get('type') == 'trinity'\ notify: Run update_ood } SED * **Launch the head node playbook** ansible-playbook controller.yml * **Enable RDMA for NFS and mount /home, /shared, /opt, /ohpc** sed -i \ "/^trix_ctrl_hostname:/a \\ # -----------------------------------------------------------------------\ # Storage node IP address.\ # Used to mount shared filesystems (home, opt, shared, scratch) via NFS RDMA.\ # In a single-node setup, this should match the controller's InfiniBand IP.\ \ trix_storage_ip: 10.149.255.254" \ group_vars/all.yml.example && sed -i \ -e 's/nfs_enable_rdma: false/nfs_enable_rdma: true/' \ -e '/# easybuild/,/disabled:/ { /disabled:/a \ # opt ------------------------------------------------------------------------------ \ - path: '\''/opt'\'' \ options: '\''*(rw,async,no_root_squash)'\'' \ rwhosts: '\''{{ all_ctrl_hostname | join(" ") }} {{ trix_ctrl_hostname if ha else "" }}'\'' \ # structbio_home ------------------------------------------------------------------------------ \ - path: '\''/trinity/structbio_home'\'' \ options: '\''*(rw,no_root_squash)'\'' \ rwhosts: '\''{{ all_ctrl_hostname | join(" ") }} {{ trix_ctrl_hostname if ha else "" }}'\'' }' \ controller.yml && sed -i \ -e 's/nfs_enable_rdma: false/nfs_enable_rdma: true/' \ -e '/remote:/s/{{ trix_ctrl_hostname }}/{{ trix_storage_ip }}/g' \ -e "/- path: '{{ trix_shared }}'/,/options: 'defaults,nfsvers=4.2,ro,retrans=4,_netdev'/d" \ -e "/- path: '{{ trix_home }}'/,/options: 'defaults,nfsvers=4.2,rw,retrans=4,noatime,_netdev'/d" \ -e '1,/nfs_mounts:/!b' \ -e '/nfs_mounts:/a \ - path: '\''{{ trix_shared }}'\''\ remote: '\''{{ trix_storage_ip }}:{{ trix_shared }}'\''\ options: '\''defaults,nfsvers=4.2,rsize=1048576,wsize=1048576,hard,timeo=600,ro,retrans=4,noatime,_netdev'\''\ - path: '\''{{ trix_home }}'\''\ remote: '\''{{ trix_storage_ip }}:{{ trix_home }}'\''\ options: '\''defaults,nfsvers=4.2,rsize=1048576,wsize=1048576,hard,timeo=600,rw,retrans=4,noatime,_netdev'\''\ - path: '\''/trinity/structbio_home'\''\ remote: '\''{{ trix_storage_ip }}:/trinity/structbio_home'\''\ options: '\''defaults,nfsvers=4.2,rsize=1048576,wsize=1048576,hard,timeo=600,rw,retrans=4,noatime,_netdev'\''\ - path: '\''/opt'\''\ remote: '\''{{ trix_storage_ip }}:/opt'\''\ options: '\''defaults,nfsvers=4.2,rsize=1048576,wsize=1048576,hard,timeo=600,rw,retrans=4,noatime,_netdev'\'''\ imports/trinity-redhat-image-setup.yml * **Enable PAM Slurm adopt module** sed -i \ -e '/^account[[:space:]]\{1,\}include[[:space:]]\{1,\}password-auth$/a\account required pam_slurm_adopt.so' \ /root/trinityX/site/roles/trinity/slurm/files/pam-sshd sed -i \ 's/^enable_slurm_pam:[[:space:]]*false$/enable_slurm_pam: true/' \ /root/trinityX/site/roles/trinity/slurm/defaults/main.yml * **Fix Prometheus path** sed -i \ $'/when: luna2_daemon_pip is undefined/a\ - name: Patch luna2 daemon Prometheus route prefix\ ansible.builtin.replace:\ path: '\''{{ luna2_python_dir.stdout }}/site-packages/daemon/plugins/import/prometheus_hw_rules.py'\''\ regexp: '\''self\\.prometheus_url = "https://localhost:9090"'\''\ replace: '\''self.prometheus_url = "http://localhost:9090/prometheus"'\''' \ /root/trinityX/site/roles/trinity/luna2/tasks/controller.yml * **Prepare Ansible inventory** cat > hosts << EOF [controllers] darwin ansible_connection=local EOF * **Prepare the head node playbook** cp group_vars/all.yml.example group_vars/all.yml sed -i \ -e 's/^trix_ctrl1_hostname:.*/trix_ctrl1_hostname: darwin/' \ -e "s|^trix_external_fqdn:.*|trix_external_fqdn: '\''portal.darwin.bioeng.ru'\''|" \ -e 's/^\([[:space:]]*\)-[[:space:]]*"8\.8\.8\.8"/\1- "192.168.1.3"/' \ -e 's/^\([[:space:]]*\)-[[:space:]]*"8\.8\.4\.4"/\1- "192.168.1.1"/' \ -e 's/^luna_password:.*/luna_password: hKpT5APf@jfp5g/' \ -e 's/^luna_protocol:.*/luna_protocol: http/' \ -e 's/^firewalld_public_interfaces:.*/firewalld_public_interfaces: [eno1]/' \ -e 's/^firewalld_trusted_interfaces:.*/firewalld_trusted_interfaces: [eno2, enp23s0, ibp180s0]/' \ -e 's/^firewalld_public_tcp_ports:.*/firewalld_public_tcp_ports: [22, 80, 443]/' \ group_vars/all.yml * **Patch playbook to install OOD apps idempotently** sed -i -f - /root/trinityX/site/roles/trinity/ood-apps/tasks/app.yml <<'SED' /^ - name: Make folder for app /,/^ notify: Run update_ood$/ { /^ notify: Run update_ood$/ a\ - name: Ensure web server can traverse trinity app directory\ ansible.posix.acl:\ path: "{{ app_path }}"\ entity: apache\ etype: user\ permissions: rx\ state: present\ when:\ - app_enabled\ - app.get('type') == 'trinity'\ notify: Run update_ood } SED * **Launch the head node playbook** ansible-playbook controller.yml * **Limit non-admin users on the head node by 0.5 CPU and 256 %%MB%% RAM** cat > /usr/local/bin/select-slice.sh << EOF #!/bin/bash USER_NAME="${PAM_USER:-}" [ -z "$USER_NAME" ] && exit 0 UID_NUM="$(id -u "$USER_NAME" 2>/dev/null)" || exit 0 export DBUS_SYSTEM_BUS_ADDRESS="unix:path=/run/dbus/system_bus_socket" UNIT="user-${UID_NUM}.slice" if id -nG "$USER_NAME" | grep -qw admins; then pass else systemctl set-property --runtime "$UNIT" \ CPUQuota=50% \ MemoryMax=256M \ >/dev/null 2>&1 || true fi exit 0 EOF chmod +x /usr/local/bin/select-slice.sh authselect create-profile limitedslice -b sssd && authselect select custom/limitedslice \ with-fingerprint \ with-silent-lastlog \ with-mkhomedir && authselect apply-changes && sed -i \ '/pam_systemd\.so/a session optional pam_exec.so seteuid /usr/local/bin/select-slice.sh' \ /etc/authselect/custom/limitedslice/system-auth && sed -i \ '/pam_systemd\.so/a session optional pam_exec.so seteuid /usr/local/bin/select-slice.sh' \ /etc/authselect/custom/limitedslice/password-auth && authselect apply-changes * **Configure SELinux permissions** semanage fcontext -a \ -e /home \ /trinity/home semanage fcontext -a \ -t httpd_sys_rw_content_t \ '/home/[^/]+/ondemand(/.*)?' restorecon -RF /trinity/home semanage fcontext -a -t etc_t '/trinity/shared/etc/slurm/slurm.conf' restorecon /trinity/shared/etc/slurm/slurm.conf * **Configure Fail2Ban** cat > /etc/fail2ban/fail2ban.local << EOF [Definition] # Log levels: CRITICAL, ERROR, WARNING, NOTICE, INFO, DEBUG loglevel = NOTICE socket = /var/run/fail2ban/fail2ban.sock pidfile = /var/run/fail2ban/fail2ban.pid EOF cat > /etc/fail2ban/jail.local << EOF [sshd] enabled = true ignoreip = 127.0.0.1/8 ::1 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16 backend = systemd maxretry = 10 bantime = 20h findtime = 10m EOF fail2ban-client -t && systemctl restart fail2ban * **Disable DNSSEC-validation** sed -i \ 's/^\([[:space:]]*\)\/\/[[:space:]]*\(dnssec-validation no;\)$/\1\2/' \ /trinity/local/luna/daemon/templates/templ_dns_conf.cfg sed -i \ 's/^\([[:space:]]*\)\/\/[[:space:]]*\(dnssec-validation no;\)$/\1\2/' \ /etc/named.conf named-checkconf /etc/named.conf && systemctl restart named * **Export custom modules directory** mkdir -p /opt/modules cat > /etc/profile.d/modules.sh << EOF module use /opt/modules module use /opt/shared_modules EOF * **Add an administrator to log into OOD portal** /usr/local/sbin/obol user add \ --uid 1000 \ --group admins \ localadmin \ -P ==== OOD Portal Customization ==== * **Download assets** cd /root curl -LO https://nextcloud.bioeng.ru/s/jjkEtRcY5JFRBnb/download unzip -qo download rm -rf download assets mv darwin_assets assets * **Adjust page layouts and colors** tar -xzpf /root/assets/ood.tar.gz -C / sed -i \ -e '/^