diff --git a/CHANGELOG.md b/CHANGELOG.md index 19a5a28a..03df62ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +* **role:tmux**: Installs tmux and deploys a system-wide `/etc/tmux.conf` with sensible defaults, such as a larger scrollback buffer and mouse support. Selections are copied to the local clipboard over SSH via OSC 52 (where the terminal emulator supports it), and `prefix + P` dumps a pane's whole scrollback buffer to a file. * **role:graylog_server**: Make more HTTP, Elasticsearch, processing/output buffer and message journal settings configurable via `graylog_server__http_external_uri`, `graylog_server__http_enable_cors`, `graylog_server__elasticsearch_max_total_connections`, `graylog_server__elasticsearch_max_total_connections_per_route`, `graylog_server__output_batch_size`, `graylog_server__processbuffer_processors`, `graylog_server__outputbuffer_processors`, `graylog_server__ring_size`, `graylog_server__inputbuffer_ring_size`, `graylog_server__message_journal_max_age` and `graylog_server__message_journal_max_size`. * **role:mariadb_server**: Make `aria_pagecache_buffer_size`, `key_buffer_size` and `sort_buffer_size` configurable via the corresponding `mariadb_server__cnf_*` variables. * **plugin:platform_select**: New filter plugin for selecting a value from a platform-keyed dictionary by OS family / distribution / version. @@ -20,6 +21,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * **role:system_update**: Add a security lane for Rocky Linux. A second timer (twice a day by default) installs only Rocky Linux security hot-fixes from the dedicated `security` repository (provided by `repo_baseos`) and reboots the host if needed. The reboot time is steered per host group (for example immediately on test hosts, deferred to the evening on production hosts). Enabled by default; a no-op where the `security` repository is not enabled, and can be turned off with `system_update__security_enabled: false`. This keeps critical security fixes flowing daily while the regular update lane stays on its weekly schedule. * **role:mariadb_server**: Add `mariadb_server__cnf_innodb_snapshot_isolation` variable (MariaDB 10.6+), defaulting to `'ON'`. +### Changed + +* **role:tools**: No longer installs tmux. Use the dedicated `tmux` role instead, which also ships a configuration with sensible defaults. + ### Security * **plugin:gpg_key**: The cleartext passphrase is no longer included in the module's failure output when key generation fails. diff --git a/COMPATIBILITY.md b/COMPATIBILITY.md index 132f6645..c597bd09 100644 --- a/COMPATIBILITY.md +++ b/COMPATIBILITY.md @@ -157,6 +157,7 @@ Which Ansible role is proven to run on which OS? | systemd_unit | | | x | x | x | | | | | | telegraf | | | x | (x) | (x) | | | | | | timezone | (x) | (x) | x | x | x | (x) | (x) | (x) | Fedora 35 | +| tmux | (x) | (x) | (x) | x | (x) | (x) | (x) | (x) | | | tools | | | x | x | x | | | | Fedora | | unattended_upgrades | (x) | (x) | | | | (x) | (x) | (x) | | | uptimerobot | | | | | | | | | controller-side, talks to UptimeRobot API | diff --git a/playbooks/README.md b/playbooks/README.md index 1babb9b2..1bd633c8 100644 --- a/playbooks/README.md +++ b/playbooks/README.md @@ -1007,6 +1007,7 @@ Calls the following roles (in order): * [python](https://github.com/Linuxfabrik/lfops/tree/main/roles/python): `setup_basic__skip_python`, `setup_basic__skip_python_venv` * [glances](https://github.com/Linuxfabrik/lfops/tree/main/roles/glances): `setup_basic__skip_glances` * [tools](https://github.com/Linuxfabrik/lfops/tree/main/roles/tools): `setup_basic__skip_tools` +* [tmux](https://github.com/Linuxfabrik/lfops/tree/main/roles/tmux): `setup_basic__skip_tmux` * [at](https://github.com/Linuxfabrik/lfops/tree/main/roles/at): `setup_basic__skip_at` * [yum_utils](https://github.com/Linuxfabrik/lfops/tree/main/roles/yum_utils): `setup_basic__skip_yum_utils` * [lvm](https://github.com/Linuxfabrik/lfops/tree/main/roles/lvm): `setup_basic__skip_lvm` @@ -1338,6 +1339,13 @@ Calls the following roles (in order): * [timezone](https://github.com/Linuxfabrik/lfops/tree/main/roles/timezone) +## tmux.yml + +Calls the following roles (in order): + +* [tmux](https://github.com/Linuxfabrik/lfops/tree/main/roles/tmux) + + ## tools.yml Calls the following roles (in order): diff --git a/playbooks/all.yml b/playbooks/all.yml index 5d66638c..1d08113a 100644 --- a/playbooks/all.yml +++ b/playbooks/all.yml @@ -140,6 +140,7 @@ - import_playbook: 'systemd_unit.yml' - import_playbook: 'telegraf.yml' - import_playbook: 'timezone.yml' +- import_playbook: 'tmux.yml' - import_playbook: 'tools.yml' - import_playbook: 'unattended_upgrades.yml' - import_playbook: 'vsftpd.yml' diff --git a/playbooks/setup_basic.yml b/playbooks/setup_basic.yml index 8556dec6..2263df7c 100644 --- a/playbooks/setup_basic.yml +++ b/playbooks/setup_basic.yml @@ -112,6 +112,10 @@ when: - 'not setup_basic__skip_tools | d(false)' + - role: 'linuxfabrik.lfops.tmux' + when: + - 'not setup_basic__skip_tmux | d(false)' + - role: 'linuxfabrik.lfops.at' when: - 'not setup_basic__skip_at | d(false)' diff --git a/playbooks/tmux.yml b/playbooks/tmux.yml new file mode 100644 index 00000000..17565be5 --- /dev/null +++ b/playbooks/tmux.yml @@ -0,0 +1,29 @@ +- name: 'Playbook linuxfabrik.lfops.tmux' + hosts: + - 'lfops_tmux' + + pre_tasks: + - ansible.builtin.import_role: + name: 'shared' + tasks_from: 'log-start.yml' + tags: + - 'always' + + - ansible.builtin.import_role: + name: 'shared' + tasks_from: 'global-variables.yml' + tags: + - 'always' + + + roles: + + - role: 'linuxfabrik.lfops.tmux' + + + post_tasks: + - ansible.builtin.import_role: + name: 'shared' + tasks_from: 'log-end.yml' + tags: + - 'always' diff --git a/roles/tmux/README.md b/roles/tmux/README.md new file mode 100644 index 00000000..2c782241 --- /dev/null +++ b/roles/tmux/README.md @@ -0,0 +1,75 @@ +# Ansible Role linuxfabrik.lfops.tmux + +This role installs [tmux](https://github.com/tmux/tmux) and deploys a system-wide `/etc/tmux.conf` with sensible defaults, for example a larger scrollback buffer. + + +*Available in the next LFOps release.* + + +## How the Role Behaves + +* The configuration is fully templated. On every run `/etc/tmux.conf` is re-rendered from the role's template (a timestamped backup is kept), so out-of-band manual edits are overwritten. Manage all settings through the role variables below. +* A changed configuration takes effect for newly started tmux sessions. Already running sessions keep their loaded configuration until they are restarted or the file is sourced manually. +* Copy-mode selections are sent to the clipboard of the local terminal emulator through the OSC 52 escape sequence (`set-clipboard on`). This works over SSH, but only if the local terminal emulator supports OSC 52. Terminals without OSC 52 support simply ignore the sequence. +* As a terminal-independent alternative, `prefix + P` writes the complete scrollback buffer of the current pane to `/tmp/tmux-scrollback---..txt` (mode `0600`, since the scrollback may contain secrets). From there it can be copied off the host, searched or archived. A confirmation with the exact path is shown in the status line. + + +## Tags + +`tmux` + +* Installs tmux and deploys the configuration. +* Triggers: none. + + +## Optional Role Variables + +`tmux__history_limit` + +* Maximum number of lines kept in the scrollback buffer per pane. +* Type: Number. +* Default: `100000` + +`tmux__mouse` + +* Enable mouse support (scroll, select and resize panes/windows). +* Type: Bool. +* Default: `true` + +Example: +```yaml +# optional +tmux__history_limit: 50000 +tmux__mouse: false +``` + + +## Troubleshooting + +**Copy mode does not reach the local clipboard over SSH** + +* OSC 52 (`set-clipboard on`) hands the selection to the *local* terminal emulator, which this role cannot configure. The emulator must support and allow OSC 52 clipboard writes. foot, kitty, WezTerm and Alacritty work out of the box. xterm needs `XTerm*disallowedWindowOps: 20,21,SetXprop` in `~/.Xresources` (OSC 52 is disabled by default there). gnome-terminal and other VTE terminals only support OSC 52 from VTE 0.78 onwards. +* Note that the relevant terminal is the one running *locally*. Over SSH the remote-only tools `wl-copy` / `xclip` cannot reach your local clipboard; OSC 52 is what carries the data back through the connection. +* Independent of any terminal support, `prefix + P` dumps the whole scrollback to a file (see [How the Role Behaves](#how-the-role-behaves)) that can be copied off the host. + +**Clipboard does not work through nested tmux (tmux inside tmux)** + +* Each tmux layer relays the OSC 52 of an inner tmux only when its own `set-clipboard` is `on`; the tmux default `external` sets the clipboard from its own copy mode but swallows OSC 52 coming from an inner tmux. Set `set-clipboard on` in any outer tmux you manage yourself, for example a local `~/.tmux.conf`. + +**Copied text pastes with middle-click but not with Ctrl+V** + +* The terminal stored the OSC 52 data in the PRIMARY selection (middle-click) instead of CLIPBOARD (Ctrl+V). tmux sends an empty selection target and terminals differ in how they interpret it. On xterm, add `XTerm*selectToClipboard: true` to `~/.Xresources` to route it to CLIPBOARD. + +**`missing or unsuitable terminal: ` when starting tmux over SSH** + +* The remote host has no terminfo entry for your local terminal (common with `foot` and `xterm-kitty`). This is a terminfo gap, not a role problem. Either connect with a `TERM` the host already knows, for example `TERM=xterm-256color ssh `, or copy your terminfo to the host once with `infocmp -x | ssh tic -x -`. + + +## License + +[The Unlicense](https://unlicense.org/) + + +## Author Information + +[Linuxfabrik GmbH, Zurich](https://www.linuxfabrik.ch) diff --git a/roles/tmux/defaults/main.yml b/roles/tmux/defaults/main.yml new file mode 100644 index 00000000..fce7fbc0 --- /dev/null +++ b/roles/tmux/defaults/main.yml @@ -0,0 +1,2 @@ +tmux__history_limit: 100000 +tmux__mouse: true diff --git a/roles/tmux/meta/argument_specs.yml b/roles/tmux/meta/argument_specs.yml new file mode 100644 index 00000000..4e513469 --- /dev/null +++ b/roles/tmux/meta/argument_specs.yml @@ -0,0 +1,18 @@ +# argument_specs validates required variables and types automatically at role entry. +# use this for simple "is defined" / type checks. for complex validations +# (value ranges, cross-variable logic), use ansible.builtin.assert in the tasks. +argument_specs: + main: + options: + + tmux__history_limit: + type: 'int' + required: false + default: 100000 + description: 'Maximum number of lines kept in the scrollback buffer per pane.' + + tmux__mouse: + type: 'bool' + required: false + default: true + description: 'Enable mouse support (scroll, select and resize panes/windows).' diff --git a/roles/tmux/tasks/main.yml b/roles/tmux/tasks/main.yml new file mode 100644 index 00000000..c355a082 --- /dev/null +++ b/roles/tmux/tasks/main.yml @@ -0,0 +1,18 @@ +- block: + + - name: 'Install tmux' + ansible.builtin.package: + name: 'tmux' + state: 'present' + + - name: 'Deploy /etc/tmux.conf' + ansible.builtin.template: + backup: true + src: 'etc/tmux.conf.j2' + dest: '/etc/tmux.conf' + owner: 'root' + group: 'root' + mode: 0o644 + + tags: + - 'tmux' diff --git a/roles/tmux/templates/etc/tmux.conf.j2 b/roles/tmux/templates/etc/tmux.conf.j2 new file mode 100644 index 00000000..6ec4ba59 --- /dev/null +++ b/roles/tmux/templates/etc/tmux.conf.j2 @@ -0,0 +1,39 @@ +# {{ ansible_managed }} +# 20260529 + +# Larger scrollback buffer. +set -g history-limit {{ tmux__history_limit }} + +# Mouse support (scroll, select and resize panes/windows). +set -g mouse {{ tmux__mouse | ternary('on', 'off') }} + +# Start window and pane numbering at 1, matching the keyboard layout. +set -g base-index 1 +setw -g pane-base-index 1 + +# Renumber windows when one is closed, so there are no gaps. +set -g renumber-windows on + +# Shorten the escape delay, which otherwise gets in the way of editors like vim. +set -sg escape-time 10 + +# Terminal type advertised to programs running inside tmux. tmux-256color adds +# italics and undercurl (styled underlines) over the older screen-256color, and +# is shipped by ncurses-base on RHEL 8+ / present on Debian 12+ / Ubuntu 22.04+. +set -g default-terminal 'tmux-256color' + +# Reflect the active window in the terminal title. +set -g set-titles on + +# vi-style key bindings in copy mode. +setw -g mode-keys vi + +# Copy selections to the clipboard of the local terminal emulator via the OSC 52 +# escape sequence. This works over SSH, but only if the local terminal emulator +# supports OSC 52. +set -g set-clipboard on + +# Dump the whole scrollback buffer of the current pane to a file, regardless of +# terminal emulator support. The file is per user, session, window and pane, and +# is created with mode 0600 because the scrollback may contain secrets. +bind-key P run-shell 'umask 077; f="/tmp/tmux-scrollback-$(id -un)-#{session_name}-#{window_index}.#{pane_index}.txt"; tmux capture-pane -pS - -t "#{pane_id}" > "$f"; tmux display-message "scrollback saved: $f"' diff --git a/roles/tools/README.md b/roles/tools/README.md index e22aae5a..8ef07c53 100644 --- a/roles/tools/README.md +++ b/roles/tools/README.md @@ -11,7 +11,6 @@ Tools that this role installs: * nano * rsync * sudo -* tmux * vim * wget diff --git a/roles/tools/tasks/main.yml b/roles/tools/tasks/main.yml index bbc61009..c987d1bc 100644 --- a/roles/tools/tasks/main.yml +++ b/roles/tools/tasks/main.yml @@ -19,7 +19,6 @@ - 'nano' - 'rsync' - 'sudo' # sometimes missing on Debian - - 'tmux' - 'vim' - 'wget' state: 'present'