1 Commits

Author SHA1 Message Date
raucao b34c3ad20b Add default tmux config and plugins 2026-07-13 15:39:47 +02:00
17 changed files with 381 additions and 74 deletions
+22 -2
View File
@@ -8,7 +8,27 @@ data_bag_path "data_bags"
encrypted_data_bag_secret "#{current_dir}/encrypted_data_bag_secret"
local_mode true # Chef local mode, replacing Solo
# Knife-Zero config, see https://knife-zero.github.io/40_configuration/
# Prevent attributes from being saved to the node files
knife[:automatic_attribute_whitelist] = %w[
fqdn
os
os_version
hostname
ipaddress
roles
recipes
ipaddress
platform
platform_version
cloud
cloud_v2
chef_packages
]
# Added to /etc/chef/client.rb on node bootstrap
# https://docs.chef.io/attribute_persistence/
# Source of truth: site-cookbooks/kosmos-base/files/default/chef_attributes.rb
client_d_dir(File.expand_path("../site-cookbooks/kosmos-base/files/default/chef_attributes.rb"))
# Source of truth: site-cookbooks/kosmos-base/files/default/chef_normal_attributes.yml
normal_attrs = YAML.load_file(File.expand_path("../site-cookbooks/kosmos-base/files/default/chef_normal_attributes.yml", __dir__))
knife[:normal_attribute_allowlist] = normal_attrs
knife[:allowed_normal_attributes] = normal_attrs
+40
View File
@@ -0,0 +1,40 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT="$(git rev-parse --show-toplevel)/scripts/util/sanitize_node.sh"
FILES=$(git diff --cached --name-only --diff-filter=ACM -- 'nodes/*.json' || true)
[[ -z "$FILES" ]] && exit 0
DIRTY=0
while IFS= read -r file; do
staged_tmp=$(mktemp)
sanitized_tmp=$(mktemp)
# 1. get staged version
git show ":$file" > "$staged_tmp"
# 2. sanitize IN PLACE (on temp copy)
cp "$staged_tmp" "$sanitized_tmp"
"$SCRIPT" "$sanitized_tmp"
# 3. if sanitizer changed file, update working tree
if ! diff -q "$staged_tmp" "$sanitized_tmp" >/dev/null; then
cp "$sanitized_tmp" "$file"
echo "Sanitized: $file"
DIRTY=1
fi
rm -f "$staged_tmp" "$sanitized_tmp"
done <<< "$FILES"
if [[ "$DIRTY" -ne 0 ]]; then
echo ""
echo "Commit paused, sanitized files must be re-staged."
exit 1
fi
exit 0
+4
View File
@@ -28,6 +28,10 @@ Clone this repository, `cd` into it, and run:
bundle install
### Enable Git hooks
git config core.hooksPath .githooks
## Common tasks
### Bootstrap a new host server
+1
View File
@@ -36,6 +36,7 @@
"kosmos-base::systemd_emails",
"apt::unattended-upgrades",
"kosmos-base::firewall",
"kosmos-base::tmux",
"kosmos-postfix::default",
"postfix::default",
"postfix::_common",
-18
View File
@@ -22,7 +22,6 @@
"kosmos-base",
"kosmos-base::default",
"kosmos_prometheus::node_exporter",
"kosmos_zerotier::ohai_plugin",
"kosmos_kvm::guest",
"kosmos_prometheus::server",
"kosmos_prometheus::alertmanager",
@@ -39,7 +38,6 @@
"postfix::_attributes",
"postfix::sasl_auth",
"hostname::default",
"zerotier::ohai_plugin",
"firewall::default"
],
"platform": "ubuntu",
@@ -55,22 +53,6 @@
"version": "18.2.13",
"ohai_root": "/opt/chef/embedded/lib/ruby/gems/3.1.0/gems/ohai-18.2.13/lib/ohai"
}
},
"zerotier": {
"version": "1.16.2",
"node_id": "77fcedcdce",
"networks": {
"8541e5153eb4327c": {
"network_name": "virgo",
"mac": "7e:45:48:d3:d8:2b",
"status": "OK",
"type": "PRIVATE",
"interface": "ztsb7vcj2c",
"addresses": [
"10.1.1.146/24"
]
}
}
}
},
"run_list": [
-1
View File
@@ -3,5 +3,4 @@ name "base"
run_list %w(
kosmos-base::default
kosmos_prometheus::node_exporter
kosmos_zerotier::ohai_plugin
)
+69
View File
@@ -0,0 +1,69 @@
#!/usr/bin/env bash
# Strip the top-level "override" and "default" attributes from Chef node JSON files.
#
# Usage:
# ./scripts/util/strip_node_attrs.sh <node> [<node> ...]
# ./scripts/util/strip_node_attrs.sh --all
#
# A <node> may be a bare node name (e.g. "prometheus-1"), a path relative to the
# repository root (e.g. "nodes/prometheus-1.json"), or an absolute path.
#
# Exit codes:
# 0 - all target files processed successfully
# 1 - one or more targets could not be processed (missing args, missing jq,
# file not found, invalid JSON, or write failure)
set -uo pipefail
command -v jq >/dev/null 2>&1 || exit 1
root="$(git rev-parse --show-toplevel 2>/dev/null)" || root="$(pwd)"
targets=()
if [ "$#" -eq 0 ]; then
exit 1
fi
for arg in "$@"; do
if [ "$arg" = "--all" ]; then
shopt -s nullglob
for f in "$root"/nodes/*.json; do
targets+=("$f")
done
shopt -u nullglob
continue
fi
if [[ "$arg" == */* ]]; then
if [[ "$arg" = /* ]]; then
targets+=("$arg")
else
targets+=("$root/$arg")
fi
else
targets+=("$root/nodes/$arg.json")
fi
done
if [ "${#targets[@]}" -eq 0 ]; then
exit 1
fi
rc=0
for file in "${targets[@]}"; do
[ -f "$file" ] || { rc=1; continue; }
jq -e . "$file" >/dev/null 2>&1 || { rc=1; continue; }
tmp="$(mktemp "${file}.XXXXXX")" || { rc=1; continue; }
if jq --indent 2 'del(.override, .default)' "$file" > "$tmp" 2>/dev/null; then
truncate -s -1 "$tmp" 2>/dev/null || true
mv "$tmp" "$file" || { rm -f "$tmp"; rc=1; continue; }
else
rm -f "$tmp"
rc=1
continue
fi
done
exit "$rc"
@@ -1,2 +1,15 @@
node.default["kosmos-base"]["journald"]["system_max_use"] = "256M"
node.default["kosmos-base"]["journald"]["max_retention_sec"] = "7d"
node.default["kosmos-base"]["tmux"]["plugins_dir"] = "/usr/local/share/tmux/plugins"
node.default["kosmos-base"]["tmux"]["default_conf"] = "/usr/local/share/tmux/tmux.conf.default"
node.default["kosmos-base"]["tmux"]["tpm_redux"]["repo"] = "https://github.com/RyanMacG/tpm-redux.git"
node.default["kosmos-base"]["tmux"]["tpm_redux"]["revision"] = "c5347f71a291eadf26dbecacc43154ecd8ad061b"
# Keys are tpm shorthand names (used in `set -g @plugin`). Values contain the
# git repo and the exact commit SHA the plugin is pinned to.
node.default["kosmos-base"]["tmux"]["plugins"] = {
"tmux-plugins/tmux-resurrect" => {
"repo" => "https://github.com/tmux-plugins/tmux-resurrect.git",
"revision" => "e87d7d592cac97fa38c12395ebec042c154a1844",
},
}
@@ -1,8 +0,0 @@
allowed_automatic_attributes ["fqdn", "os", "os_version", "hostname",
"ipaddress", "roles", "recipes", "ipaddress",
"platform", "platform_version", "cloud",
"cloud_v2", "chef_packages", "zerotier"]
allowed_default_attributes []
allowed_override_attributes []
allowed_normal_attributes ["knife_zero", "kosmos_kvm", "kosmos-ejabberd",
"openresty", "vm_host"]
@@ -0,0 +1,6 @@
---
- knife_zero
- kosmos_kvm
- kosmos-ejabberd
- openresty
- vm_host
@@ -0,0 +1,44 @@
# basti's tmux overrides — appended after the system default config is sourced.
set -g prefix C-a
set -sg escape-time 1
set -g base-index 1
set -g history-limit 20000
set -g mouse off
set -g status-justify centre
set -g status-style dim
set -ag status-style fg=white
set -ag status-style bg=colour236
set -g window-status-current-style bright
set -ag window-status-current-style fg=white
set -ag window-status-current-style bg=colour238
set -g pane-border-style fg=colour238
set -g pane-active-border-style fg=colour244
setw -g pane-base-index 1
setw -g mode-keys vi
bind C-a send-prefix
bind r source-file ~/.tmux.conf \; display "Reloaded!"
bind | split-window -h
bind - split-window -v
bind h select-pane -L
bind j select-pane -D
bind k select-pane -U
bind l select-pane -R
bind -r H resize-pane -L 5
bind -r J resize-pane -D 5
bind -r K resize-pane -U 5
bind -r L resize-pane -R 5
unbind p
bind p paste-buffer
bind-key -T copy-mode-vi v send-keys -X begin-selection
bind-key -T copy-mode-vi y send-keys -X copy-selection-and-cancel
unbind Up
bind Up new-window -d -n tmp \; swap-pane -s tmp.1 \; select-window -t tmp
unbind Down
bind Down last-window \; swap-pane -s tmp.1 \; kill-window -t tmp
bind P pipe-pane -o "cat >>~/#W.log" \; display "Toggled logging to ~/#W.log"
+50 -22
View File
@@ -2,31 +2,57 @@
# Cookbook Name:: kosmos-base
# Recipe:: default
#
ruby_block "cleanup client.rb" do
block do
fe = Chef::Util::FileEdit.new("/etc/chef/client.rb")
# Delete old attributes, replaced by allow_*_attributes
fe.search_file_delete_line(/^.*_attribute_whitelist.*/)
fe.write_file
end
end
cookbook_file "/etc/chef/client.d/attributes.rb" do
source "chef_attributes.rb"
mode "0644"
notifies :create, "ruby_block[reload_client_config]", :immediately
end
ruby_block "reload_client_config" do
block do
Chef::Config.from_file("/etc/chef/client.rb")
end
action :nothing
end
# The MIT License (MIT)
#
# Copyright:: 2019, Kosmos Developers
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
include_recipe "apt"
cookbook_file "/etc/chef/chef_normal_attributes.yml" do
source "chef_normal_attributes.yml"
owner "root"
group "root"
mode "0644"
end
ruby_block "update allowed_normal_attributes in client.rb" do
block do
whitelist = YAML.load_file("/etc/chef/chef_normal_attributes.yml")
fe = Chef::Util::FileEdit.new("/etc/chef/client.rb")
fe.search_file_replace_line(
/^allowed_normal_attributes.*/,
"allowed_normal_attributes #{whitelist.inspect}"
)
fe.write_file
Chef::Config[:allowed_normal_attributes] = whitelist
Chef::Config[:normal_attribute_allowlist] = whitelist
end
not_if do
whitelist = YAML.load_file("/etc/chef/chef_normal_attributes.yml")
client_rb = ::File.read("/etc/chef/client.rb")
whitelist.all? { |attr| client_rb.include?(attr) }
end
end
directory "/etc/apt/keyrings" do
mode "0755"
action :create
@@ -81,6 +107,8 @@ unless node.chef_environment == "development"
include_recipe "kosmos-base::firewall"
include_recipe "kosmos-base::tmux"
include_recipe "kosmos-postfix"
node.override["set_fqdn"] = "*"
+102
View File
@@ -0,0 +1,102 @@
#
# Cookbook Name:: kosmos-base
# Recipe:: tmux
#
package "tmux"
plugins_dir = node["kosmos-base"]["tmux"]["plugins_dir"]
default_conf = node["kosmos-base"]["tmux"]["default_conf"]
tpm_redux = node["kosmos-base"]["tmux"]["tpm_redux"]
plugins = node["kosmos-base"]["tmux"]["plugins"]
directory plugins_dir do
owner "root"
group "root"
mode "0755"
recursive true
action :create
end
# Install tpm-redux (the plugin manager) at a pinned commit.
git "#{plugins_dir}/tpm-redux" do
repository tpm_redux["repo"]
revision tpm_redux["revision"]
user "root"
group "root"
action :sync
end
# Install each managed plugin at a pinned commit. Plugins are cloned by Chef
# into a shared, root-owned directory so that users never need to install them
# themselves.
plugins.each do |shorthand, meta|
git "#{plugins_dir}/#{shorthand.split('/').last}" do
repository meta["repo"]
revision meta["revision"]
user "root"
group "root"
action :sync
end
end
# System default tmux config: minimal — only the plugin manager environment,
# the @plugin declarations for the chef-managed plugins, and the tpm-redux
# initialisation line (which must be the last line of the file).
template default_conf do
source "tmux.conf.default.erb"
owner "root"
group "root"
mode "0644"
variables(
plugins_dir: plugins_dir,
plugins: plugins
)
action :create
end
# Write a per-user ~/.tmux.conf. Users who submit their own overrides as a
# cookbook file at files/default/tmux_users/<username>.conf get a fully
# managed config: it sources the system default (so chef-managed plugins
# always load) and then appends the user's overrides. Users who have not
# submitted a file get a blank importer written only if ~/.tmux.conf does
# not already exist, so any hand-written/local config is left untouched.
cookbook = run_context.cookbook_collection["kosmos-base"]
search(:users, "groups:sysadmin AND NOT action:remove") do |u|
username = u["username"] || u["id"]
home_dir = u["home"] || "/home/#{username}"
group_name = u["gid"] || username
next unless Dir.exist?(home_dir)
user_conf_source = "tmux_users/#{username}.conf"
if cookbook.has_cookbook_file_for_node?(node, user_conf_source)
disk_path = cookbook.preferred_filename_on_disk_location(node, :files, user_conf_source)
# Chef reads ERB templates with IO.binread, so the template output buffer
# is ASCII-8BIT. File.read returns UTF-8 on the node; concatenating a UTF-8
# string into an ASCII-8BIT buffer raises an encoding error on non-ASCII
# content. Retag as ASCII-8BIT to match the buffer — the raw bytes are
# still valid UTF-8, so the written file is correct.
user_content = File.read(disk_path).force_encoding("ASCII-8BIT")
template "#{home_dir}/.tmux.conf" do
source "tmux.conf.user.erb"
owner username
group group_name
mode "0644"
variables(default_conf: default_conf, user_content: user_content)
action :create
end
else
template "#{home_dir}/.tmux.conf" do
source "tmux.conf.user.erb"
owner username
group group_name
mode "0644"
variables(default_conf: default_conf, user_content: nil)
action :create_if_missing
end
end
end
@@ -0,0 +1,14 @@
# Managed by Chef (kosmos-base::tmux). Do not edit on this host.
#
# This is the system default tmux config. It is sourced by each user's
# ~/.tmux.conf via `source-file`. Plugins are managed by Chef and live in
# a shared, root-owned directory; users do not install plugins themselves.
set-environment -g TMUX_PLUGIN_MANAGER_PATH '<%= @plugins_dir %>'
<% @plugins.each do |shorthand, _meta| -%>
set -g @plugin '<%= shorthand %>'
<% end -%>
# Initialize TPM Redux (must remain the last line of the file)
run '<%= @plugins_dir %>/tpm-redux/tpm'
@@ -0,0 +1,15 @@
# ~/.tmux.conf — created/managed by Chef (kosmos-base::tmux).
#
# This file imports the system default config below, then appends any overrides
# the user has submitted to files/default/tmux_users/<username>.conf in the
# kosmos-base cookbook. If you manage your own tmux config locally and have not
# submitted a file, Chef will not overwrite it.
source-file <%= @default_conf %>
<% if @user_content && !@user_content.empty? -%>
# === user overrides (from files/default/tmux_users/<username>.conf) ===
<%= @user_content %>
<% else -%>
# === Add your custom settings below this line ===
<% end -%>
+1 -2
View File
@@ -4,8 +4,7 @@ maintainer_email 'mail@kosmos.org'
license 'MIT'
description 'Installs/Configures zerotier'
long_description 'Installs/Configures zerotier'
version '0.2.0'
version '0.1.0'
chef_version '>= 14.0'
depends 'kosmos-base'
depends 'zerotier'
@@ -1,21 +0,0 @@
#
# Cookbook:: kosmos_zerotier
# Recipe:: ohai_plugin
#
include_recipe "zerotier::ohai_plugin"
ohai "reload_zerotier" do
action :reload
plugin "zerotier"
notifies :run, "ruby_block[save_chef_zero_node]", :delayed
end
# Force save the node back to disk in Chef Zero
ruby_block "save_chef_zero_node" do
block do
node.save
Chef::Log.info("Node #{node.name} saved to disk with ZeroTier data")
end
action :nothing
end