338 lines
11 KiB
YAML
338 lines
11 KiB
YAML
---
|
|
- name: Minimal check for doc/rpc Sol host
|
|
hosts: sol_rpc
|
|
gather_facts: true
|
|
become: true
|
|
vars_files:
|
|
- ../group_vars/sol_rpc.yml
|
|
|
|
tasks:
|
|
- name: Install operator packages (Debian/Ubuntu)
|
|
ansible.builtin.apt:
|
|
name:
|
|
- tmux
|
|
- mc
|
|
- git
|
|
- neovim
|
|
state: present
|
|
update_cache: true
|
|
when: ansible_facts.os_family == "Debian"
|
|
|
|
- name: Install Solana host base packages (Debian/Ubuntu)
|
|
ansible.builtin.apt:
|
|
name:
|
|
- chrony
|
|
- curl
|
|
- jq
|
|
- smartmontools
|
|
- nvme-cli
|
|
- prometheus-node-exporter
|
|
state: present
|
|
update_cache: true
|
|
when: ansible_facts.os_family == "Debian"
|
|
|
|
- name: Ensure solana group exists
|
|
ansible.builtin.group:
|
|
name: "{{ solana_group }}"
|
|
system: true
|
|
|
|
- name: Ensure solana user exists
|
|
ansible.builtin.user:
|
|
name: "{{ solana_user }}"
|
|
group: "{{ solana_group }}"
|
|
home: "{{ solana_home }}"
|
|
system: true
|
|
create_home: true
|
|
|
|
- name: Ensure root config directories exist
|
|
ansible.builtin.file:
|
|
path: "{{ item }}"
|
|
state: directory
|
|
owner: root
|
|
group: root
|
|
mode: "0755"
|
|
loop:
|
|
- /root/.config
|
|
- /root/.config/mc
|
|
- /root/.config/nvim
|
|
- /root/.config/nvim/lua
|
|
|
|
- name: Ensure Solana directories exist
|
|
ansible.builtin.file:
|
|
path: "{{ item.path }}"
|
|
state: directory
|
|
owner: "{{ item.owner }}"
|
|
group: "{{ item.group }}"
|
|
mode: "{{ item.mode }}"
|
|
loop:
|
|
- { path: "/etc/solana", owner: "root", group: "root", mode: "0755" }
|
|
- { path: "{{ solana_home }}", owner: "{{ solana_user }}", group: "{{ solana_group }}", mode: "0750" }
|
|
- { path: "{{ solana_ledger_dir }}", owner: "{{ solana_user }}", group: "{{ solana_group }}", mode: "0750" }
|
|
- { path: "{{ solana_accounts_dir }}", owner: "{{ solana_user }}", group: "{{ solana_group }}", mode: "0750" }
|
|
- { path: "{{ solana_log_dir }}", owner: "{{ solana_user }}", group: "{{ solana_group }}", mode: "0750" }
|
|
- { path: "/opt/solana/bin", owner: "root", group: "root", mode: "0755" }
|
|
|
|
- name: Deploy Solana sysctl tuning (network buffers)
|
|
ansible.builtin.copy:
|
|
dest: /etc/sysctl.d/99-solana-rpc.conf
|
|
owner: root
|
|
group: root
|
|
mode: "0644"
|
|
content: |
|
|
# Required by agave-validator startup checks
|
|
net.core.rmem_max = 134217728
|
|
net.core.wmem_max = 134217728
|
|
register: solana_sysctl_conf
|
|
|
|
- name: Apply sysctl tuning when changed
|
|
ansible.builtin.command: sysctl --system
|
|
changed_when: true
|
|
when: solana_sysctl_conf.changed
|
|
|
|
- name: Deploy tmux config (Ctrl+a prefix)
|
|
ansible.builtin.copy:
|
|
src: ../files/operator-dotfiles/tmux.conf
|
|
dest: /root/.tmux.conf
|
|
owner: root
|
|
group: root
|
|
mode: "0644"
|
|
|
|
- name: Deploy Midnight Commander config
|
|
ansible.builtin.copy:
|
|
src: "../files/operator-dotfiles/mc/{{ item.src }}"
|
|
dest: "/root/.config/mc/{{ item.dest }}"
|
|
owner: root
|
|
group: root
|
|
mode: "0644"
|
|
loop:
|
|
- { src: "ini", dest: "ini" }
|
|
- { src: "panels.ini", dest: "panels.ini" }
|
|
|
|
- name: Deploy Neovim config files
|
|
ansible.builtin.copy:
|
|
src: "../files/operator-dotfiles/nvim/{{ item.src }}"
|
|
dest: "/root/.config/nvim/{{ item.dest }}"
|
|
owner: root
|
|
group: root
|
|
mode: "0644"
|
|
loop:
|
|
- { src: "init.lua", dest: "init.lua" }
|
|
- { src: "lazy-lock.json", dest: "lazy-lock.json" }
|
|
- { src: "lua/options.lua", dest: "lua/options.lua" }
|
|
- { src: "lua/keymaps.lua", dest: "lua/keymaps.lua" }
|
|
- { src: "lua/plugins.lua", dest: "lua/plugins.lua" }
|
|
- { src: "lua/utils.lua", dest: "lua/utils.lua" }
|
|
- { src: "lua/hazard3_dap.lua", dest: "lua/hazard3_dap.lua" }
|
|
|
|
- name: Deploy solana-rpc systemd unit (runs as solana user)
|
|
ansible.builtin.template:
|
|
src: ../templates/solana-rpc.service.j2
|
|
dest: /etc/systemd/system/{{ solana_rpc_service_name }}.service
|
|
owner: root
|
|
group: root
|
|
mode: "0644"
|
|
register: solana_rpc_unit
|
|
|
|
- name: Reload systemd after unit change
|
|
ansible.builtin.systemd:
|
|
daemon_reload: true
|
|
when: solana_rpc_unit.changed
|
|
|
|
- name: Check validator binary exists
|
|
ansible.builtin.stat:
|
|
path: "{{ solana_validator_bin }}"
|
|
register: solana_validator_bin_stat
|
|
|
|
- name: Install Agave toolchain for solana user when validator missing
|
|
ansible.builtin.shell: |
|
|
set -euo pipefail
|
|
sh -c "$(curl -sSfL {{ solana_install_script_url }})"
|
|
become_user: "{{ solana_user }}"
|
|
environment:
|
|
HOME: "{{ solana_home }}"
|
|
args:
|
|
executable: /bin/bash
|
|
when: not solana_validator_bin_stat.stat.exists
|
|
|
|
- name: Link Agave binaries into /opt/solana/bin
|
|
ansible.builtin.shell: |
|
|
set -euo pipefail
|
|
if [ ! -d "{{ solana_active_release_bin_dir }}" ]; then
|
|
echo "Active release bin dir missing: {{ solana_active_release_bin_dir }}" >&2
|
|
exit 1
|
|
fi
|
|
for bin in "{{ solana_active_release_bin_dir }}"/*; do
|
|
name="$(basename "$bin")"
|
|
ln -sfn "$bin" "/opt/solana/bin/$name"
|
|
done
|
|
args:
|
|
executable: /bin/bash
|
|
when: not solana_validator_bin_stat.stat.exists
|
|
|
|
- name: Re-check validator binary after install
|
|
ansible.builtin.stat:
|
|
path: "{{ solana_validator_bin }}"
|
|
register: solana_validator_bin_stat
|
|
|
|
- name: Install Agave build dependencies (Debian/Ubuntu) when validator missing
|
|
ansible.builtin.apt:
|
|
name:
|
|
- build-essential
|
|
- pkg-config
|
|
- libssl-dev
|
|
- clang
|
|
- llvm-dev
|
|
- libclang-dev
|
|
- cmake
|
|
- protobuf-compiler
|
|
- libudev-dev
|
|
- zlib1g-dev
|
|
state: present
|
|
update_cache: true
|
|
when:
|
|
- ansible_facts.os_family == "Debian"
|
|
- not solana_validator_bin_stat.stat.exists
|
|
|
|
- name: Ensure Agave source parent directory exists
|
|
ansible.builtin.file:
|
|
path: "{{ agave_src_dir | dirname }}"
|
|
state: directory
|
|
owner: "{{ solana_user }}"
|
|
group: "{{ solana_group }}"
|
|
mode: "0755"
|
|
when: not solana_validator_bin_stat.stat.exists
|
|
|
|
- name: Install rustup (Agave build) for solana user when validator missing
|
|
ansible.builtin.shell: |
|
|
set -euo pipefail
|
|
curl -sSfL https://sh.rustup.rs | sh -s -- -y --default-toolchain "{{ agave_rust_toolchain }}"
|
|
become_user: "{{ solana_user }}"
|
|
environment:
|
|
HOME: "{{ solana_home }}"
|
|
args:
|
|
executable: /bin/bash
|
|
creates: "{{ solana_home }}/.cargo/bin/cargo"
|
|
when: not solana_validator_bin_stat.stat.exists
|
|
|
|
- name: Ensure Rust toolchain is installed for solana user when validator missing
|
|
ansible.builtin.shell: |
|
|
set -euo pipefail
|
|
export PATH="{{ solana_home }}/.cargo/bin:$PATH"
|
|
rustup toolchain install "{{ agave_rust_toolchain }}"
|
|
become_user: "{{ solana_user }}"
|
|
environment:
|
|
HOME: "{{ solana_home }}"
|
|
args:
|
|
executable: /bin/bash
|
|
when: not solana_validator_bin_stat.stat.exists
|
|
|
|
- name: Clone Agave sources when validator missing
|
|
ansible.builtin.git:
|
|
repo: "{{ agave_repo_url }}"
|
|
dest: "{{ agave_src_dir }}"
|
|
version: "{{ agave_version_tag }}"
|
|
depth: 1
|
|
update: true
|
|
become_user: "{{ solana_user }}"
|
|
environment:
|
|
HOME: "{{ solana_home }}"
|
|
when: not solana_validator_bin_stat.stat.exists
|
|
|
|
- name: Build agave-validator from sources when validator missing
|
|
ansible.builtin.shell: |
|
|
set -euo pipefail
|
|
export PATH="{{ solana_home }}/.cargo/bin:$PATH"
|
|
cd "{{ agave_src_dir }}"
|
|
cargo +{{ agave_rust_toolchain }} build --release -p agave-validator
|
|
become_user: "{{ solana_user }}"
|
|
environment:
|
|
HOME: "{{ solana_home }}"
|
|
args:
|
|
executable: /bin/bash
|
|
creates: "{{ agave_src_dir }}/target/release/agave-validator"
|
|
when: not solana_validator_bin_stat.stat.exists
|
|
|
|
- name: Install agave-validator to /opt/solana/bin when built
|
|
ansible.builtin.copy:
|
|
remote_src: true
|
|
src: "{{ agave_src_dir }}/target/release/agave-validator"
|
|
dest: "{{ solana_validator_bin }}"
|
|
owner: root
|
|
group: root
|
|
mode: "0755"
|
|
when: not solana_validator_bin_stat.stat.exists
|
|
|
|
- name: Re-check validator binary after source build
|
|
ansible.builtin.stat:
|
|
path: "{{ solana_validator_bin }}"
|
|
register: solana_validator_bin_stat
|
|
|
|
- name: Ensure identity key exists
|
|
ansible.builtin.shell: |
|
|
set -euo pipefail
|
|
"{{ solana_keygen_bin }}" new --no-passphrase -o "{{ solana_identity_path }}"
|
|
become_user: "{{ solana_user }}"
|
|
environment:
|
|
HOME: "{{ solana_home }}"
|
|
args:
|
|
executable: /bin/bash
|
|
creates: "{{ solana_identity_path }}"
|
|
|
|
- name: Check identity key exists
|
|
ansible.builtin.stat:
|
|
path: "{{ solana_identity_path }}"
|
|
register: solana_identity_stat
|
|
|
|
- name: Ensure solana-rpc service state when prerequisites exist
|
|
ansible.builtin.systemd:
|
|
name: "{{ solana_rpc_service_name }}"
|
|
enabled: "{{ solana_rpc_enable_on_boot | bool }}"
|
|
state: "{{ 'started' if (solana_rpc_start_now | bool) else 'stopped' }}"
|
|
when:
|
|
- solana_rpc_manage_service | bool
|
|
- solana_validator_bin_stat.stat.exists
|
|
- solana_identity_stat.stat.exists
|
|
|
|
- name: Verify solana-rpc is active
|
|
ansible.builtin.command: systemctl is-active {{ solana_rpc_service_name }}
|
|
register: solana_rpc_is_active
|
|
changed_when: false
|
|
retries: 10
|
|
delay: 3
|
|
until: solana_rpc_is_active.stdout.strip() == "active"
|
|
when:
|
|
- solana_rpc_manage_service | bool
|
|
- solana_validator_bin_stat.stat.exists
|
|
- solana_identity_stat.stat.exists
|
|
|
|
- name: Report skipped solana-rpc start due to missing prerequisites
|
|
ansible.builtin.debug:
|
|
msg:
|
|
- "solana-rpc start skipped: missing prerequisites"
|
|
- "validator_bin={{ solana_validator_bin }} exists={{ solana_validator_bin_stat.stat.exists }}"
|
|
- "identity={{ solana_identity_path }} exists={{ solana_identity_stat.stat.exists }}"
|
|
when:
|
|
- solana_rpc_manage_service | bool
|
|
- not (solana_validator_bin_stat.stat.exists and solana_identity_stat.stat.exists)
|
|
|
|
- name: Validate Ansible transport
|
|
ansible.builtin.ping:
|
|
|
|
- name: Show host basics
|
|
ansible.builtin.debug:
|
|
msg:
|
|
- "inventory_hostname={{ inventory_hostname }}"
|
|
- "ansible_host={{ ansible_host | default('n/a') }}"
|
|
- "hostname={{ ansible_facts['hostname'] | default('n/a') }}"
|
|
- "os_family={{ ansible_facts['os_family'] | default('n/a') }}"
|
|
- "kernel={{ ansible_facts['kernel'] | default('n/a') }}"
|
|
|
|
- name: Read uptime
|
|
ansible.builtin.command: uptime
|
|
register: uptime_cmd
|
|
changed_when: false
|
|
|
|
- name: Print uptime
|
|
ansible.builtin.debug:
|
|
var: uptime_cmd.stdout
|