feat: vollst. Installations-Doku, Ansible-Rollen ausimplementiert, claude_workspace-Rolle
- docs/installation.md: Netinstall + Dualboot Schritt-für-Schritt (LUKS nur am Notebook) - docs/postinstall-ansible.md: Ablauf + restmanuelle Schritte - roles/base: APT-Sources mit non-free-firmware + Backports, Locale, Tastatur, Zeitzone, Grundpakete - roles/desktop_kde: Plasma 6 + SDDM (ohne Recommends, kompakt) - roles/hardening: SSH key-only, UFW, unattended-upgrades - roles/dev_tools: Node.js via NodeSource, Python, Perl, Git-Defaults - roles/workstation_apps: Firefox, Thunderbird, LibreOffice, Codecs, KeePassXC - roles/claude_workspace (NEU): Claude Code + ccusage, SSH-Key für Gitea, Workspace-Clone (recurse-submodules), ~/.claude/settings.json - site.yml: alle Rollen mit Tags
This commit is contained in:
@@ -1,3 +1,84 @@
|
||||
---
|
||||
# Grundsystem: APT-Quellen, Lokalisierung, Firmware, Hilfspakete
|
||||
# TODO: implementieren — Skeleton-Datei
|
||||
- name: APT-Quellen mit contrib + non-free-firmware + (Backports)
|
||||
ansible.builtin.copy:
|
||||
dest: /etc/apt/sources.list
|
||||
mode: '0644'
|
||||
content: |
|
||||
deb http://deb.debian.org/debian/ trixie main contrib non-free-firmware
|
||||
deb http://security.debian.org/debian-security trixie-security main contrib non-free-firmware
|
||||
deb http://deb.debian.org/debian/ trixie-updates main contrib non-free-firmware
|
||||
{% if enable_backports | default(true) %}
|
||||
deb http://deb.debian.org/debian/ trixie-backports main contrib non-free-firmware
|
||||
{% endif %}
|
||||
register: apt_sources
|
||||
|
||||
- name: APT cache aktualisieren
|
||||
ansible.builtin.apt:
|
||||
update_cache: true
|
||||
when: apt_sources.changed
|
||||
|
||||
- name: Locale-Paket
|
||||
ansible.builtin.apt:
|
||||
name: locales
|
||||
state: present
|
||||
cache_valid_time: 3600
|
||||
|
||||
- name: Locale aktivieren
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/locale.gen
|
||||
regexp: "^# ?{{ locale }} "
|
||||
line: "{{ locale }} UTF-8"
|
||||
register: locale_line
|
||||
|
||||
- name: locale-gen ausführen
|
||||
ansible.builtin.command: locale-gen
|
||||
when: locale_line.changed
|
||||
|
||||
- name: Standard-Locale setzen
|
||||
ansible.builtin.copy:
|
||||
dest: /etc/default/locale
|
||||
mode: '0644'
|
||||
content: "LANG={{ locale }}\n"
|
||||
|
||||
- name: Tastaturlayout
|
||||
ansible.builtin.copy:
|
||||
dest: /etc/default/keyboard
|
||||
mode: '0644'
|
||||
content: |
|
||||
XKBMODEL="pc105"
|
||||
XKBLAYOUT="{{ keyboard_layout }}"
|
||||
XKBVARIANT=""
|
||||
XKBOPTIONS=""
|
||||
BACKSPACE="guess"
|
||||
|
||||
- name: Zeitzone
|
||||
ansible.builtin.command: "timedatectl set-timezone {{ timezone }}"
|
||||
changed_when: false
|
||||
|
||||
- name: Grundpakete
|
||||
ansible.builtin.apt:
|
||||
name:
|
||||
- sudo
|
||||
- curl
|
||||
- wget
|
||||
- gnupg
|
||||
- ca-certificates
|
||||
- apt-transport-https
|
||||
- vim
|
||||
- htop
|
||||
- tmux
|
||||
- rsync
|
||||
- net-tools
|
||||
- dnsutils
|
||||
- firmware-linux
|
||||
- firmware-linux-nonfree
|
||||
- lsb-release
|
||||
- bash-completion
|
||||
- man-db
|
||||
state: present
|
||||
|
||||
- name: Extra-Pakete je Host
|
||||
ansible.builtin.apt:
|
||||
name: "{{ extra_packages }}"
|
||||
state: present
|
||||
when: extra_packages | default([]) | length > 0
|
||||
|
||||
11
ansible/roles/claude_workspace/defaults/main.yml
Normal file
11
ansible/roles/claude_workspace/defaults/main.yml
Normal file
@@ -0,0 +1,11 @@
|
||||
---
|
||||
claude_workspace_repo: "ssh://git@docker.egonlebt.lan:2222/egon/claude-workspace.git"
|
||||
claude_workspace_dest: "/home/{{ primary_user }}/Claude"
|
||||
gitea_ssh_host: docker.egonlebt.lan
|
||||
gitea_ssh_port: 2222
|
||||
claude_settings:
|
||||
model: opus
|
||||
advisorModel: opus
|
||||
statusLine:
|
||||
type: command
|
||||
command: "node ~/Claude/.claude/statusline.js"
|
||||
106
ansible/roles/claude_workspace/tasks/main.yml
Normal file
106
ansible/roles/claude_workspace/tasks/main.yml
Normal file
@@ -0,0 +1,106 @@
|
||||
---
|
||||
# Setzt voraus: Node.js + git (aus dev_tools), npm verfügbar
|
||||
|
||||
- name: Claude Code (npm global)
|
||||
ansible.builtin.command: npm install -g @anthropic-ai/claude-code
|
||||
args:
|
||||
creates: /usr/lib/node_modules/@anthropic-ai/claude-code/package.json
|
||||
|
||||
- name: ccusage (npm global, für Statusline-Tokenverbrauch)
|
||||
ansible.builtin.command: npm install -g ccusage
|
||||
args:
|
||||
creates: /usr/lib/node_modules/ccusage/package.json
|
||||
|
||||
- name: ~/.ssh existiert
|
||||
become_user: "{{ primary_user }}"
|
||||
ansible.builtin.file:
|
||||
path: "/home/{{ primary_user }}/.ssh"
|
||||
state: directory
|
||||
mode: '0700'
|
||||
|
||||
- name: SSH-Key für Gitea (ed25519, ohne Passphrase)
|
||||
become_user: "{{ primary_user }}"
|
||||
ansible.builtin.command: >
|
||||
ssh-keygen -t ed25519
|
||||
-f /home/{{ primary_user }}/.ssh/id_ed25519_gitea
|
||||
-N "" -C "{{ primary_user }}@{{ inventory_hostname }} -> gitea"
|
||||
args:
|
||||
creates: "/home/{{ primary_user }}/.ssh/id_ed25519_gitea"
|
||||
|
||||
- name: known_hosts für Gitea vorpopulieren
|
||||
become_user: "{{ primary_user }}"
|
||||
ansible.builtin.shell: |
|
||||
ssh-keyscan -p {{ gitea_ssh_port }} -H {{ gitea_ssh_host }} 2>/dev/null \
|
||||
| grep -v '^#' >> /home/{{ primary_user }}/.ssh/known_hosts
|
||||
sort -u /home/{{ primary_user }}/.ssh/known_hosts \
|
||||
-o /home/{{ primary_user }}/.ssh/known_hosts
|
||||
args:
|
||||
creates: "/home/{{ primary_user }}/.ssh/known_hosts"
|
||||
|
||||
- name: SSH-Config für Gitea
|
||||
become_user: "{{ primary_user }}"
|
||||
ansible.builtin.blockinfile:
|
||||
path: "/home/{{ primary_user }}/.ssh/config"
|
||||
create: true
|
||||
mode: '0600'
|
||||
marker: "# {mark} ANSIBLE MANAGED — gitea"
|
||||
block: |
|
||||
Host {{ gitea_ssh_host }}
|
||||
Port {{ gitea_ssh_port }}
|
||||
IdentityFile ~/.ssh/id_ed25519_gitea
|
||||
IdentitiesOnly yes
|
||||
User git
|
||||
|
||||
- name: Check ob Workspace schon geklont
|
||||
become_user: "{{ primary_user }}"
|
||||
ansible.builtin.stat:
|
||||
path: "{{ claude_workspace_dest }}/.git"
|
||||
register: ws_git
|
||||
|
||||
- name: claude-workspace klonen (mit Submodules)
|
||||
become_user: "{{ primary_user }}"
|
||||
ansible.builtin.git:
|
||||
repo: "{{ claude_workspace_repo }}"
|
||||
dest: "{{ claude_workspace_dest }}"
|
||||
recursive: true
|
||||
update: false
|
||||
accept_hostkey: true
|
||||
key_file: "/home/{{ primary_user }}/.ssh/id_ed25519_gitea"
|
||||
when: not ws_git.stat.exists
|
||||
ignore_errors: true # scheitert bevor Pubkey in Gitea liegt — wird erneut versucht
|
||||
register: clone_result
|
||||
|
||||
- name: ~/.claude existiert
|
||||
become_user: "{{ primary_user }}"
|
||||
ansible.builtin.file:
|
||||
path: "/home/{{ primary_user }}/.claude"
|
||||
state: directory
|
||||
mode: '0700'
|
||||
|
||||
- name: Globale Claude-Settings (~/.claude/settings.json)
|
||||
become_user: "{{ primary_user }}"
|
||||
ansible.builtin.copy:
|
||||
dest: "/home/{{ primary_user }}/.claude/settings.json"
|
||||
mode: '0644'
|
||||
content: "{{ claude_settings | to_nice_json }}\n"
|
||||
|
||||
- name: Public-Key für Gitea-Upload anzeigen
|
||||
become_user: "{{ primary_user }}"
|
||||
ansible.builtin.command: "cat /home/{{ primary_user }}/.ssh/id_ed25519_gitea.pub"
|
||||
register: pubkey
|
||||
changed_when: false
|
||||
|
||||
- name: HINWEIS — Public-Key auf Gitea hochladen
|
||||
ansible.builtin.debug:
|
||||
msg:
|
||||
- "==========================================================="
|
||||
- "Public-Key dieser Maschine ({{ inventory_hostname }}):"
|
||||
- ""
|
||||
- "{{ pubkey.stdout }}"
|
||||
- ""
|
||||
- "→ http://{{ gitea_ssh_host }}:3000/user/settings/keys"
|
||||
- " → 'Schlüssel hinzufügen', oben einfügen, speichern."
|
||||
- ""
|
||||
- "Danach ggf. Workspace nachholen:"
|
||||
- " ansible-playbook ... --tags claude_workspace --limit {{ inventory_hostname }}"
|
||||
- "==========================================================="
|
||||
@@ -1,3 +1,39 @@
|
||||
---
|
||||
# KDE Plasma 6, SDDM, KDE-Anwendungen
|
||||
# TODO: implementieren — Skeleton-Datei
|
||||
- name: KDE Plasma + SDDM (Standardumfang ohne riesige Discover-Hänger)
|
||||
ansible.builtin.apt:
|
||||
name:
|
||||
- kde-plasma-desktop
|
||||
- sddm
|
||||
- plasma-nm
|
||||
- plasma-pa
|
||||
- kde-config-sddm
|
||||
- konsole
|
||||
- dolphin
|
||||
- kate
|
||||
- okular
|
||||
- gwenview
|
||||
- spectacle
|
||||
- ark
|
||||
- kcalc
|
||||
- kfind
|
||||
- partitionmanager
|
||||
- xdg-utils
|
||||
- fonts-noto
|
||||
- fonts-noto-color-emoji
|
||||
state: present
|
||||
install_recommends: false
|
||||
|
||||
- name: SDDM aktivieren als Default-Display-Manager
|
||||
ansible.builtin.copy:
|
||||
dest: /etc/X11/default-display-manager
|
||||
mode: '0644'
|
||||
content: "/usr/bin/sddm\n"
|
||||
|
||||
- name: Graphical Target als Default
|
||||
ansible.builtin.command: systemctl set-default graphical.target
|
||||
changed_when: false
|
||||
|
||||
- name: SDDM aktivieren
|
||||
ansible.builtin.systemd:
|
||||
name: sddm
|
||||
enabled: true
|
||||
|
||||
@@ -1,3 +1,50 @@
|
||||
---
|
||||
# Git, Editor, Sprachen (Python/Node/Perl für FHEM)
|
||||
# TODO: implementieren — Skeleton-Datei
|
||||
- name: Dev-Pakete (Sprachen, Build-Tools, Editor)
|
||||
ansible.builtin.apt:
|
||||
name:
|
||||
- git
|
||||
- build-essential
|
||||
- python3
|
||||
- python3-venv
|
||||
- python3-pip
|
||||
- pipx
|
||||
- perl
|
||||
- jq
|
||||
- direnv
|
||||
- shellcheck
|
||||
- meld
|
||||
state: present
|
||||
|
||||
- name: NodeSource Keyring (für Node.js LTS)
|
||||
ansible.builtin.get_url:
|
||||
url: https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key
|
||||
dest: /etc/apt/keyrings/nodesource.asc
|
||||
mode: '0644'
|
||||
register: ns_key
|
||||
|
||||
- name: NodeSource Repo
|
||||
ansible.builtin.copy:
|
||||
dest: /etc/apt/sources.list.d/nodesource.list
|
||||
mode: '0644'
|
||||
content: "deb [signed-by=/etc/apt/keyrings/nodesource.asc] https://deb.nodesource.com/node_20.x nodistro main\n"
|
||||
register: ns_repo
|
||||
|
||||
- name: APT update nach NodeSource
|
||||
ansible.builtin.apt:
|
||||
update_cache: true
|
||||
when: ns_key.changed or ns_repo.changed
|
||||
|
||||
- name: Node.js (LTS) installieren
|
||||
ansible.builtin.apt:
|
||||
name: nodejs
|
||||
state: present
|
||||
|
||||
- name: Git globale Defaults für {{ primary_user }}
|
||||
become_user: "{{ primary_user }}"
|
||||
ansible.builtin.command: "git config --global {{ item.k }} {{ item.v }}"
|
||||
loop:
|
||||
- { k: 'user.name', v: 'egon' }
|
||||
- { k: 'user.email', v: 'egon@egonlebt.de' }
|
||||
- { k: 'pull.rebase', v: 'true' }
|
||||
- { k: 'init.defaultBranch', v: 'main' }
|
||||
changed_when: false
|
||||
|
||||
5
ansible/roles/hardening/handlers/main.yml
Normal file
5
ansible/roles/hardening/handlers/main.yml
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
- name: restart sshd
|
||||
ansible.builtin.systemd:
|
||||
name: ssh
|
||||
state: restarted
|
||||
@@ -1,3 +1,48 @@
|
||||
---
|
||||
# SSH-Hardening, UFW, unattended-upgrades, fail2ban
|
||||
# TODO: implementieren — Skeleton-Datei
|
||||
- name: Security-Pakete
|
||||
ansible.builtin.apt:
|
||||
name:
|
||||
- ufw
|
||||
- unattended-upgrades
|
||||
- apt-listchanges
|
||||
state: present
|
||||
|
||||
- name: SSH — Passwort-Login deaktivieren
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/ssh/sshd_config
|
||||
regexp: '^#?\s*PasswordAuthentication\s'
|
||||
line: 'PasswordAuthentication no'
|
||||
validate: 'sshd -t -f %s'
|
||||
notify: restart sshd
|
||||
|
||||
- name: SSH — Root-Login deaktivieren
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/ssh/sshd_config
|
||||
regexp: '^#?\s*PermitRootLogin\s'
|
||||
line: 'PermitRootLogin no'
|
||||
validate: 'sshd -t -f %s'
|
||||
notify: restart sshd
|
||||
|
||||
- name: UFW Default Policy (incoming deny)
|
||||
ansible.builtin.command: ufw default deny incoming
|
||||
register: ufw_default
|
||||
changed_when: "'Default incoming policy changed' in ufw_default.stdout"
|
||||
|
||||
- name: UFW — SSH erlauben
|
||||
ansible.builtin.command: ufw allow OpenSSH
|
||||
register: ufw_allow
|
||||
changed_when: "'Rule added' in ufw_allow.stdout or 'Rules updated' in ufw_allow.stdout"
|
||||
|
||||
- name: UFW aktivieren
|
||||
ansible.builtin.command: ufw --force enable
|
||||
register: ufw_enable
|
||||
changed_when: "'Firewall is active' in ufw_enable.stdout"
|
||||
|
||||
- name: unattended-upgrades konfigurieren
|
||||
ansible.builtin.copy:
|
||||
dest: /etc/apt/apt.conf.d/20auto-upgrades
|
||||
mode: '0644'
|
||||
content: |
|
||||
APT::Periodic::Update-Package-Lists "1";
|
||||
APT::Periodic::Unattended-Upgrade "1";
|
||||
APT::Periodic::AutocleanInterval "7";
|
||||
|
||||
@@ -1,3 +1,16 @@
|
||||
---
|
||||
# Browser, Office, Multimedia-Codecs
|
||||
# TODO: implementieren — Skeleton-Datei
|
||||
- name: Anwendungen (Browser, Office, Multimedia, Tools)
|
||||
ansible.builtin.apt:
|
||||
name:
|
||||
- firefox-esr
|
||||
- libreoffice
|
||||
- libreoffice-l10n-de
|
||||
- thunderbird
|
||||
- thunderbird-l10n-de
|
||||
- keepassxc
|
||||
- vlc
|
||||
- ffmpeg
|
||||
- libavcodec-extra
|
||||
- gimp
|
||||
- inkscape
|
||||
state: present
|
||||
|
||||
Reference in New Issue
Block a user