5 Commits

19 changed files with 1072 additions and 1 deletions

View File

@@ -0,0 +1,145 @@
[Midnight-Commander]
verbose=true
shell_patterns=true
auto_save_setup=true
preallocate_space=false
auto_menu=false
use_internal_view=true
use_internal_edit=false
clear_before_exec=true
confirm_delete=true
confirm_overwrite=true
confirm_execute=false
confirm_history_cleanup=true
confirm_exit=false
confirm_directory_hotlist_delete=false
confirm_view_dir=false
safe_delete=false
safe_overwrite=false
use_8th_bit_as_meta=false
mouse_move_pages_viewer=true
mouse_close_dialog=false
fast_refresh=false
drop_menus=false
wrap_mode=true
old_esc_mode=true
cd_symlinks=true
show_all_if_ambiguous=false
use_file_to_guess_type=true
alternate_plus_minus=false
only_leading_plus_minus=true
show_output_starts_shell=false
xtree_mode=false
file_op_compute_totals=true
classic_progressbar=true
use_netrc=true
ftpfs_always_use_proxy=false
ftpfs_use_passive_connections=true
ftpfs_use_passive_connections_over_proxy=false
ftpfs_use_unix_list_options=true
ftpfs_first_cd_then_ls=true
ignore_ftp_chattr_errors=true
editor_fill_tabs_with_spaces=false
editor_return_does_auto_indent=false
editor_backspace_through_tabs=false
editor_fake_half_tabs=true
editor_option_save_position=true
editor_option_auto_para_formatting=false
editor_option_typewriter_wrap=false
editor_edit_confirm_save=true
editor_syntax_highlighting=true
editor_persistent_selections=true
editor_drop_selection_on_copy=true
editor_cursor_beyond_eol=false
editor_cursor_after_inserted_block=false
editor_visible_tabs=true
editor_visible_spaces=true
editor_line_state=false
editor_simple_statusbar=false
editor_check_new_line=false
editor_show_right_margin=false
editor_group_undo=true
editor_state_full_filename=true
editor_ask_filename_before_edit=false
nice_rotating_dash=true
shadows=true
mcview_remember_file_position=false
auto_fill_mkdir_name=true
copymove_persistent_attr=true
pause_after_run=1
mouse_repeat_rate=100
double_click_speed=250
old_esc_mode_timeout=1000000
max_dirt_limit=10
num_history_items_recorded=60
vfs_timeout=60
ftpfs_directory_timeout=900
ftpfs_retry_seconds=30
shell_directory_timeout=900
editor_tab_spacing=8
editor_word_wrap_line_length=72
editor_option_save_mode=0
editor_backup_extension=~
editor_filesize_threshold=64M
editor_stop_format_chars=-+*\\,.;:&>
mcview_eof=
skin=default
[Layout]
output_lines=0
left_panel_size=73
top_panel_size=0
message_visible=true
keybar_visible=true
xterm_title=true
command_prompt=true
menubar_visible=true
free_space=true
horizontal_split=false
vertical_equal=true
horizontal_equal=true
[Misc]
timeformat_recent=%-d %b, %H:%M
timeformat_old=%-d %b %Y
ftp_proxy_host=gate
ftpfs_password=anonymous@
display_codepage=UTF-8
source_codepage=Other_8_bit
autodetect_codeset=
spell_language=en
clipboard_store=
clipboard_paste=
[Colors]
base_color=
xterm-256color=
color_terminals=
tmux-256color=
[Panels]
show_mini_info=true
kilobyte_si=false
mix_all_files=false
show_backups=true
show_dot_files=true
fast_reload=false
fast_reload_msg_shown=false
mark_moves_down=true
reverse_files_only=true
auto_save_setup_panels=false
navigate_with_arrows=false
panel_scroll_pages=true
panel_scroll_center=false
mouse_move_pages=true
filetype_mode=true
permission_mode=false
torben_fj_mode=false
quick_search_mode=2
select_flags=6
[Panelize]
Modyfikowane pliki git=git ls-files --modified
Znajdź programy SUID i SGID=find . \\( \\( -perm -04000 -a -perm /011 \\) -o \\( -perm -02000 -a -perm /01 \\) \\) -print
Znajdź odrzuty po łataniu=find . -name \\*.rej -print
Znajdź pliki *.orig po łataniu=find . -name \\*.orig -print

View File

@@ -0,0 +1 @@

View File

@@ -0,0 +1,44 @@
-- ======================================================================
-- init.lua — Neovim configuration with modular structure
-- ======================================================================
-- Set leader keys before lazy.nvim
vim.g.mapleader = " "
vim.g.maplocalleader = " "
-- Bootstrap lazy.nvim
local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
if not vim.loop.fs_stat(lazypath) then
vim.fn.system({
"git", "clone", "--filter=blob:none",
"https://github.com/folke/lazy.nvim.git", "--branch=stable",
lazypath,
})
end
vim.opt.rtp:prepend(lazypath)
-- Load configuration modules
require("options")
require("keymaps")
-- Load plugins
require("lazy").setup("plugins", {
change_detection = { notify = false },
})
-- Load utilities and create commands
local utils = require("utils")
vim.api.nvim_create_user_command("ShowFileNameRight", utils.show_filename_right, {})
-- MCP Server Integration - Start socket if not already listening
if vim.fn.serverstart then
local socket_path = "/tmp/nvim"
-- Only start server if not already listening
if vim.v.servername == "" or vim.v.servername ~= socket_path then
-- Try to start server, ignore if address already in use
local ok, err = pcall(vim.fn.serverstart, socket_path)
if not ok and not string.match(err or "", "address already in use") then
vim.notify("Failed to start MCP server: " .. tostring(err), vim.log.levels.WARN)
end
end
end

View File

@@ -0,0 +1,13 @@
{
"coc.nvim": { "branch": "release", "commit": "c89ed8d5c393c60e0baf796f097598a8da14816d" },
"lazy.nvim": { "branch": "main", "commit": "85c7ff3711b730b4030d03144f6db6375044ae82" },
"nerdtree": { "branch": "master", "commit": "690d061b591525890f1471c6675bcb5bdc8cdff9" },
"nvim-dap": { "branch": "master", "commit": "818cd8787a77a97703eb1d9090543a374f79a9ac" },
"nvim-dap-ui": { "branch": "master", "commit": "cf91d5e2d07c72903d052f5207511bf7ecdb7122" },
"nvim-dap-virtual-text": { "branch": "master", "commit": "fbdb48c2ed45f4a8293d0d483f7730d24467ccb6" },
"nvim-nio": { "branch": "master", "commit": "21f5324bfac14e22ba26553caf69ec76ae8a7662" },
"vim-commentary": { "branch": "master", "commit": "64a654ef4a20db1727938338310209b6a63f60c9" },
"vim-fugitive": { "branch": "master", "commit": "61b51c09b7c9ce04e821f6cf76ea4f6f903e3cf4" },
"vim-oscyank": { "branch": "main", "commit": "d67d76b2f19b868b70a1cf33a779d71dc092cb30" },
"vim-slime": { "branch": "main", "commit": "3fb77a9d1d3dd3abfbdbd4840eb20947f39f688b" }
}

View File

@@ -0,0 +1,154 @@
-- hazard3_dap.lua — Hazard3 helpers for nvim-dap (GDB DAP)
local M = {}
local disasm_buf ---@type integer|nil
local function ensure_disasm_buf()
if disasm_buf and vim.api.nvim_buf_is_valid(disasm_buf) then
return disasm_buf
end
disasm_buf = vim.api.nvim_create_buf(false, true)
pcall(vim.api.nvim_buf_set_name, disasm_buf, "[DAP Disassembly]")
vim.bo[disasm_buf].buftype = "nofile"
vim.bo[disasm_buf].bufhidden = "hide"
vim.bo[disasm_buf].swapfile = false
vim.bo[disasm_buf].filetype = "asm"
vim.bo[disasm_buf].modifiable = true
vim.api.nvim_buf_set_lines(disasm_buf, 0, -1, false, { "(DAP) Disassembly" })
vim.bo[disasm_buf].modifiable = false
return disasm_buf
end
local function show_buf(buf)
local wins = vim.fn.win_findbuf(buf)
if wins and #wins > 0 then
vim.api.nvim_set_current_win(wins[1])
vim.wo.cursorline = true
return
end
vim.cmd("vsplit")
vim.api.nvim_set_current_buf(buf)
vim.wo.cursorline = true
end
local function update_disassembly(buf, opts)
opts = opts or {}
local count = opts.count or 80
local before = opts.before or 20
local ok, dap = pcall(require, "dap")
if not ok then
return
end
local session = dap.session()
if not session then
return
end
session:request("stackTrace", { threadId = 1, startFrame = 0, levels = 1 }, function(err, resp)
if err then
vim.notify("DAP disasm: stackTrace failed: " .. tostring(err), vim.log.levels.ERROR)
return
end
local frames = resp and resp.stackFrames or {}
if #frames == 0 then
vim.notify("DAP disasm: no stack frames", vim.log.levels.WARN)
return
end
local frame = frames[1]
local memref = frame.instructionPointerReference
if memref == nil or memref == "" then
vim.notify("DAP disasm: no instructionPointerReference", vim.log.levels.WARN)
return
end
session:request("disassemble", {
memoryReference = memref,
instructionOffset = -before,
instructionCount = count,
resolveSymbols = true,
}, function(err2, resp2)
if err2 then
vim.notify("DAP disasm: disassemble failed: " .. tostring(err2), vim.log.levels.ERROR)
return
end
local insts = resp2 and resp2.instructions or {}
local lines = {}
lines[#lines + 1] = "memref: " .. memref
for _, i in ipairs(insts) do
local addr = i.address or "?"
local ins = i.instruction or ""
local mark = (addr == memref) and "=> " or " "
lines[#lines + 1] = mark .. addr .. " " .. ins
end
if not vim.api.nvim_buf_is_valid(buf) then
return
end
vim.bo[buf].modifiable = true
vim.api.nvim_buf_set_lines(buf, 0, -1, false, lines)
vim.bo[buf].modifiable = false
local pc_line
for idx, line in ipairs(lines) do
if line:sub(1, 3) == "=> " then
pc_line = idx
break
end
end
if pc_line then
local wins = vim.fn.win_findbuf(buf)
if wins and #wins > 0 then
for _, win in ipairs(wins) do
pcall(vim.api.nvim_win_set_cursor, win, { pc_line, 0 })
vim.wo[win].cursorline = true
end
end
end
end)
end)
end
function M.open_disassembly(opts)
local buf = ensure_disasm_buf()
local cur_win = vim.api.nvim_get_current_win()
show_buf(buf)
update_disassembly(buf, opts)
if opts and opts.keep_focus then
pcall(vim.api.nvim_set_current_win, cur_win)
end
end
function M.setup()
local ok, dap = pcall(require, "dap")
if not ok then
return
end
if vim.api.nvim_create_user_command then
pcall(vim.api.nvim_create_user_command, "DapDisassembly", function()
M.open_disassembly()
end, {})
end
dap.listeners.after.event_stopped["hazard3_disasm"] = function()
if disasm_buf and vim.api.nvim_buf_is_valid(disasm_buf) then
update_disassembly(disasm_buf, { keep_focus = true })
end
end
end
return M

View File

@@ -0,0 +1,107 @@
-- ======================================================================
-- keymaps.lua — Key mappings
-- ======================================================================
local map = vim.keymap.set
-- NERDTree
map("n", "<leader>n", ":NERDTreeFocus<CR>", { silent = true, desc = "NERDTree: Focus" })
map("n", "<C-n>", ":NERDTree<CR>", { silent = true, desc = "NERDTree: Open" })
map("n", "<C-t>", ":NERDTreeToggle<CR>", { silent = true, desc = "NERDTree: Toggle" })
map("n", "<C-f>", ":NERDTreeFind<CR>", { silent = true, desc = "NERDTree: Find current file" })
-- OSC52 (vim-oscyank)
map("n", "<leader>c", "<Plug>OSCYankOperator", { desc = "OSC Yank: Operator" })
map("n", "<leader>cc", "<leader>c_", { desc = "OSC Yank: Current line" })
map("v", "<leader>c", "<Plug>OSCYankVisual", { desc = "OSC Yank: Visual selection" })
-- vim-slime
vim.g.slime_no_mappings = 1
map("x", "<C-c><C-c>", "<Plug>SlimeRegionSend", { desc = "Slime: Send region" })
map("n", "<C-c><C-c>", function()
require("utils").send_cell("^#%%")
end, { silent = true, desc = "Slime: Send cell" })
map("n", "<C-c>v", "<Plug>SlimeConfig", { desc = "Slime: Configure" })
-- Claude Code
map("n", "<leader>ac", ":ClaudeCode<CR>", { silent = true, desc = "ClaudeCode: Toggle" })
map("n", "<leader>af", ":ClaudeCodeFocus<CR>", { silent = true, desc = "ClaudeCode: Focus" })
map("v", "<leader>as", ":ClaudeCodeSend<CR>", { silent = true, desc = "ClaudeCode: Send selection" })
map("n", "<leader>ad", ":ClaudeCodeAdd ", { desc = "ClaudeCode: Add file to context" })
map("n", "<leader>aa", ":ClaudeCodeDiffAccept<CR>", { silent = true, desc = "ClaudeCode: Accept diff" })
map("n", "<leader>ar", ":ClaudeCodeDiffDeny<CR>", { silent = true, desc = "ClaudeCode: Reject diff" })
-- DAP (GDB)
local function dap_attach_or(fn)
return function(...)
local dap = require("dap")
if dap.session() then
return fn(dap, ...)
end
if vim.fn.exists(":Hazard3Attach") == 2 then
vim.cmd("Hazard3Attach")
return
end
return fn(dap, ...)
end
end
map("n", "<F5>", dap_attach_or(function(dap)
dap.continue()
end), { desc = "DAP: Continue (or Hazard3Attach)" })
map("n", "<F10>", dap_attach_or(function(dap)
dap.step_over()
end), { desc = "DAP: Step over" })
map("n", "<F11>", dap_attach_or(function(dap)
dap.step_into()
end), { desc = "DAP: Step into" })
map("n", "<F12>", dap_attach_or(function(dap)
dap.step_out()
end), { desc = "DAP: Step out" })
map("n", "<leader>db", function()
require("dap").toggle_breakpoint()
end, { desc = "DAP: Toggle breakpoint" })
map("n", "<leader>dB", function()
require("dap").set_breakpoint(vim.fn.input("Condition: "))
end, { desc = "DAP: Conditional breakpoint" })
map("n", "<leader>dr", function()
require("dap").repl.open()
end, { desc = "DAP: REPL" })
map("n", "<leader>du", function()
require("dapui").toggle()
end, { desc = "DAP: Toggle UI" })
map("n", "<leader>dR", function()
local dapui = require("dapui")
dapui.close()
dapui.open({ reset = true })
end, { desc = "DAP UI: Reset layout" })
map("n", "<leader>da", function()
require("hazard3_dap").open_disassembly()
end, { desc = "DAP: Disassembly" })
map("n", "<leader>di", dap_attach_or(function(dap)
dap.step_into({ granularity = "instruction" })
end), { desc = "DAP: Step instruction into" })
map("n", "<leader>dI", dap_attach_or(function(dap)
dap.step_over({ granularity = "instruction" })
end), { desc = "DAP: Step instruction over" })
map("n", "<leader>dx", function()
require("dap").terminate()
end, { desc = "DAP: Terminate" })
map("n", "<leader>dp", function()
require("dap").pause()
end, { desc = "DAP: Pause" })

View File

@@ -0,0 +1,51 @@
-- ======================================================================
-- options.lua — Vim options and settings
-- ======================================================================
local opt = vim.opt
-- Clipboard
opt.clipboard = "unnamedplus"
-- Editing behavior
opt.backspace = { "indent", "eol", "start" }
opt.mouse = "r"
opt.compatible = false
-- UI
opt.number = true
opt.cursorline = true
opt.showcmd = true
opt.showmode = true
opt.showmatch = true
opt.scrolloff = 10
opt.wrap = false
-- Indentation
opt.shiftwidth = 4
opt.tabstop = 4
opt.expandtab = true
-- Search
opt.incsearch = true
opt.ignorecase = true
opt.smartcase = true
opt.hlsearch = true
-- Files
opt.backup = false
opt.history = 1000
opt.tags = { "./tags;,tags;" }
-- Completion
opt.wildmenu = true
opt.wildmode = { "list", "longest" }
opt.wildignore = {
"*.docx","*.jpg","*.png","*.gif","*.pdf","*.pyc","*.exe","*.flv","*.img","*.xlsx"
}
-- Filetype detection
vim.cmd("filetype on")
vim.cmd("filetype plugin on")
vim.cmd("filetype indent on")
vim.cmd("syntax on")

View File

@@ -0,0 +1,191 @@
-- ======================================================================
-- plugins.lua — Plugin specifications for lazy.nvim
-- ======================================================================
return {
-- File explorer
{
"preservim/nerdtree",
cmd = { "NERDTree", "NERDTreeToggle", "NERDTreeFind", "NERDTreeFocus" },
},
-- Git integration
{
"tpope/vim-fugitive",
event = "VeryLazy",
},
-- Commenting
{
"tpope/vim-commentary",
event = "VeryLazy",
},
-- LSP and completion
{
"neoclide/coc.nvim",
branch = "release",
build = "npm ci",
event = "VeryLazy",
},
-- REPL integration (tmux)
{
"jpalardy/vim-slime",
init = function()
vim.g.slime_target = "tmux"
if vim.fn.exists("g:slime_python_ipython") == 0 then
vim.g.slime_python_ipython = 1
end
end,
},
-- OSC52 clipboard (remote SSH/tmux)
{
"ojroques/vim-oscyank",
event = "VimEnter",
init = function()
vim.g.oscyank_term = "tmux"
vim.g.oscyank_silent = true
end,
config = function()
local grp = vim.api.nvim_create_augroup("osc52_yank", { clear = true })
vim.api.nvim_create_autocmd("TextYankPost", {
group = grp,
callback = function()
if vim.v.event.operator == "y" and vim.v.event.regname == "" then
vim.cmd([[OSCYankRegister "]])
end
end,
})
end,
},
-- Debugging (DAP)
{
"mfussenegger/nvim-dap",
config = function()
local dap = require("dap")
dap.adapters.gdb = {
type = "executable",
command = "gdb-multiarch",
args = { "-i", "dap" },
}
local function pick_elf()
return vim.fn.input("ELF: ", vim.fn.getcwd() .. "/", "file")
end
local function normalize_target(t)
t = t or ""
if vim.trim then
t = vim.trim(t)
else
t = t:gsub("^%s+", ""):gsub("%s+$", "")
end
t = t:gsub("^target%s+extended%-remote%s+", "")
t = t:gsub("^target%s+remote%s+", "")
t = t:gsub("^extended%-remote%s+", "")
t = t:gsub("^remote%s+", "")
return t
end
local function pick_target()
local default = normalize_target(vim.env.HAZARD3_GDB_TARGET)
if default == "" then
default = "localhost:3333"
end
return normalize_target(vim.fn.input("GDB target (host:port): ", default))
end
local hazard3_attach = {
name = "Hazard3 (attach gdb-remote)",
type = "gdb",
request = "attach",
program = pick_elf,
target = pick_target,
cwd = "${workspaceFolder}",
}
local function add_cfg(ft, cfg)
dap.configurations[ft] = dap.configurations[ft] or {}
for _, existing in ipairs(dap.configurations[ft]) do
if existing.name == cfg.name then
return
end
end
table.insert(dap.configurations[ft], cfg)
end
for _, ft in ipairs({ "c", "cpp", "asm", "" }) do
add_cfg(ft, hazard3_attach)
end
pcall(function()
vim.api.nvim_create_user_command("Hazard3Attach", function()
dap.run(hazard3_attach)
end, { desc = "DAP: Hazard3 attach" })
end)
vim.fn.sign_define("DapBreakpoint", { text = "", texthl = "DiagnosticError" })
vim.fn.sign_define("DapStopped", { text = "", texthl = "DiagnosticInfo", linehl = "Visual" })
pcall(function()
require("hazard3_dap").setup()
end)
end,
},
{
"rcarriga/nvim-dap-ui",
dependencies = {
"mfussenegger/nvim-dap",
"nvim-neotest/nvim-nio",
},
config = function()
local dap = require("dap")
local dapui = require("dapui")
dapui.setup({
-- ASCII/unicode-friendly icons (no codicons required)
icons = { expanded = "v", collapsed = ">", current_frame = ">" },
controls = {
enabled = true,
element = "repl",
icons = {
pause = "||",
play = ">",
step_into = "",
step_over = "",
step_out = "",
step_back = "",
run_last = "",
terminate = "X",
disconnect = "D",
},
},
})
dap.listeners.after.event_initialized["dapui"] = function()
dapui.open()
end
dap.listeners.before.event_terminated["dapui"] = function()
dapui.close()
end
dap.listeners.before.event_exited["dapui"] = function()
dapui.close()
end
end,
},
{
"theHamsta/nvim-dap-virtual-text",
dependencies = {
"mfussenegger/nvim-dap",
},
opts = {},
},
}

View File

@@ -0,0 +1,25 @@
-- ======================================================================
-- utils.lua — Helper functions
-- ======================================================================
local M = {}
-- Show filename aligned to the right
function M.show_filename_right()
local filename = vim.fn.expand("%:p")
local columns = vim.o.columns
local space = columns - #filename - 2
if space < 0 then space = 0 end
vim.api.nvim_echo({{string.rep(" ", space) .. filename, "None"}}, false, {})
end
-- Send cell to slime (delimited by pattern, e.g., "^#%%")
function M.send_cell(pattern)
local start_line = vim.fn.search(pattern, "bnW")
if start_line ~= 0 then start_line = start_line + 1 else start_line = 1 end
local stop_line = vim.fn.search(pattern, "nW")
if stop_line ~= 0 then stop_line = stop_line - 1 else stop_line = vim.fn.line("$") end
vim.fn["slime#send_range"](start_line, stop_line)
end
return M

View File

@@ -0,0 +1,4 @@
set-option -g prefix C-a
unbind-key C-b
bind-key C-a send-prefix
set -g set-clipboard on

View File

@@ -0,0 +1,31 @@
solana_user: solana
solana_group: solana
solana_home: /var/lib/solana
solana_validator_bin: /opt/solana/bin/agave-validator
solana_rpc_service_name: solana-rpc
solana_identity_path: /var/lib/solana/identity.json
solana_ledger_dir: /var/lib/solana/ledger
solana_accounts_dir: /var/lib/solana/accounts
solana_log_dir: /var/log/solana
solana_rpc_bind_address: 10.10.0.2
solana_rpc_port: 8899
solana_rpc_pubsub_port: 8900
solana_dynamic_port_range: "8000-8020"
solana_entrypoints:
- entrypoint.mainnet-beta.solana.com:8001
solana_known_validators: []
solana_geyser_enabled: false
solana_geyser_plugin_config_path: /etc/solana/yellowstone-geyser.json
solana_rpc_extra_args:
- --full-rpc-api
- --limit-ledger-size
solana_rpc_manage_service: true
solana_rpc_enable_on_boot: true
solana_rpc_start_now: true

View File

@@ -2,9 +2,154 @@
- name: Minimal check for doc/rpc Sol host
hosts: sol_rpc
gather_facts: true
become: false
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" }
- 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: 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: 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:

View File

@@ -0,0 +1,35 @@
[Unit]
Description=Solana RPC node (Agave)
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User={{ solana_user }}
Group={{ solana_group }}
WorkingDirectory={{ solana_home }}
Environment=RUST_LOG=info
LimitNOFILE=1048576
Restart=always
RestartSec=5
TimeoutStopSec=120
ExecStart={{ solana_validator_bin }} \
--identity {{ solana_identity_path }} \
--ledger {{ solana_ledger_dir }} \
--accounts {{ solana_accounts_dir }} \
--rpc-bind-address {{ solana_rpc_bind_address }} \
--rpc-port {{ solana_rpc_port }} \
--rpc-pubsub-port {{ solana_rpc_pubsub_port }} \
--dynamic-port-range {{ solana_dynamic_port_range }}{% for ep in solana_entrypoints %} \
--entrypoint {{ ep }}{% endfor %}{% for kv in solana_known_validators %} \
--known-validator {{ kv }}{% endfor %}{% if solana_geyser_enabled | bool %} \
--geyser-plugin-config {{ solana_geyser_plugin_config_path }}{% endif %}{% for arg in solana_rpc_extra_args %} \
{{ arg }}{% endfor %} \
--log {{ solana_log_dir }}/validator.log
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=full
ReadWritePaths={{ solana_ledger_dir }} {{ solana_accounts_dir }} {{ solana_log_dir }} /var/lib/solana
[Install]
WantedBy=multi-user.target

20
doc/etap-002-ssh-gitea.md Normal file
View File

@@ -0,0 +1,20 @@
# Etap 002: SSH flow dla `gitea.mpabi.pl`
Cel etapu: przejść z push przez HTTPS/token na standardowy push przez SSH do `trade/trade-iac`.
## Zakres
1. Wygenerować dedykowany klucz SSH dla Gitei (jeśli brak).
2. Dodać konfigurację hosta `gitea.mpabi.pl` w `~/.ssh/config`.
3. Dodać klucz publiczny do konta `u1` w Gitei.
4. Ustawić `origin` repo `trade-iac` na URL SSH.
5. Zweryfikować:
- `ssh -T git@gitea.mpabi.pl`,
- `git ls-remote origin`,
- `git push` bez hasła/tokena HTTP.
## Kryteria akceptacji
- SSH auth do Gitei działa dla użytkownika `git`.
- `trade-iac` używa `git@gitea.mpabi.pl:trade/trade-iac.git`.
- Push działa przez SSH.

View File

@@ -0,0 +1,26 @@
# Etap 003: Wystawienie SSH Gitei z k3s
Cel etapu: udostępnić SSH Gitei na publicznym porcie, żeby `git@gitea.mpabi.pl` trafiało do serwisu `gitea-ssh` w klastrze.
## Zakres
1. Dodać `HelmChartConfig` dla Traefika z entrypointem TCP `gitssh` na porcie `2222`.
2. Dodać `IngressRouteTCP` w namespace `gitea`, który kieruje ruch z `gitssh` do `service/gitea-ssh:22`.
3. Wdrożyć manifesty do klastra i zweryfikować:
- Traefik ma port `2222`,
- `IngressRouteTCP` jest aktywny,
- `ssh -p 2222 git@gitea.mpabi.pl` odpowiada Giteą.
## Decyzja techniczna
- Nie ruszamy hostowego `:22` (zostaje dla SSH systemu).
- Git SSH dla Gitei idzie przez `:2222`.
- Klienci Git powinni używać:
- `ssh://git@gitea.mpabi.pl:2222/trade/trade-iac.git`
- albo aliasu SSH z `Port 2222`.
## Kryteria akceptacji
- `kubectl -n kube-system get svc traefik` pokazuje port `2222/TCP`.
- `kubectl -n gitea get ingressroutetcp gitea-ssh` istnieje.
- Push/pull repo przez SSH na porcie `2222` działa.

View File

@@ -0,0 +1,30 @@
# Etap 004: Narzędzia operatora + dotfiles z laptopa
Cel etapu: doinstalować na `mevnode` podstawowe narzędzia operatorskie i wgrać konfiguracje terminalowe zgodne z tym laptopem.
## Zakres
1. Doinstalować pakiety:
- `tmux`
- `mc`
- `git`
- `neovim`
2. Ustawić `tmux` z prefiksem `Ctrl+a`.
3. Wgrać konfiguracje operatora (`root`):
- `~/.tmux.conf`
- `~/.config/mc/ini`
- `~/.config/nvim/init.lua`
- `~/.config/nvim/lua/*.lua`
- `~/.config/nvim/lazy-lock.json`
## Założenia
- Playbook działa na host `mevnode` jako `root`.
- Dotfiles są wersjonowane w repo `trade-iac` (źródło prawdy).
- `git` config globalny nie jest kopiowany, jeśli brak odpowiednika na laptopie.
## Kryteria akceptacji
- Polecenia `tmux`, `mc`, `git`, `nvim` są dostępne na `mevnode`.
- `~/.tmux.conf` zawiera prefix `C-a`.
- Pliki `~/.config/mc/ini` oraz `~/.config/nvim/*` istnieją na `mevnode`.

View File

@@ -0,0 +1,22 @@
# Etap 005: Solana RPC jako usługa użytkownika `solana`
Cel etapu: przygotować i wdrożyć baseline pod `solana-rpc`, uruchamiany jako dedykowany użytkownik systemowy `solana` (nie `root`).
## Zakres
1. Rozszerzyć playbook o:
- pakiety bazowe dla hosta RPC,
- utworzenie użytkownika i katalogów `solana`,
- deployment unitu `systemd` `solana-rpc.service` z `User=solana`.
2. Dodać zmienne grupowe `sol_rpc` (ścieżki, porty, opcje startu).
3. Dodać bezpieczną logikę startu:
- unit jest wdrażany zawsze,
- start usługi tylko gdy istnieją wymagane artefakty (`agave-validator`, identity keypair).
4. Wdrożyć na `mevnode` i zweryfikować stan.
## Kryteria akceptacji
- `id solana` istnieje na `mevnode`.
- `/etc/systemd/system/solana-rpc.service` istnieje i zawiera `User=solana`.
- Playbook kończy się bez błędów.
- Jeśli binarka/identity nie istnieją, playbook raportuje to jawnie i nie wymusza startu.

View File

@@ -0,0 +1,13 @@
apiVersion: traefik.io/v1alpha1
kind: IngressRouteTCP
metadata:
name: gitea-ssh
namespace: gitea
spec:
entryPoints:
- gitssh
routes:
- match: HostSNI(`*`)
services:
- name: gitea-ssh
port: 22

View File

@@ -0,0 +1,14 @@
apiVersion: helm.cattle.io/v1
kind: HelmChartConfig
metadata:
name: traefik
namespace: kube-system
spec:
valuesContent: |-
ports:
gitssh:
port: 2222
expose:
default: true
exposedPort: 2222
protocol: TCP