Migrate XRDP and Cloudflare playbooks
This commit is contained in:
parent
d195a21a66
commit
47504726a3
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,2 +1,3 @@
|
||||
.env
|
||||
.artifacts/acp_codex/xworkmate-go-core
|
||||
.artifacts/acp_opencode/xworkmate-go-core
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
[defaults]
|
||||
# 常用参数
|
||||
inventory = ./inventory # 默认清单文件路径,可按需改
|
||||
# 默认清单文件路径,可按需改
|
||||
inventory = ./inventory.ini
|
||||
vault_password_file = ~/.vault_password
|
||||
timeout = 10
|
||||
forks = 10
|
||||
|
||||
7
gnome_xrdp_minimal.yaml
Normal file
7
gnome_xrdp_minimal.yaml
Normal file
@ -0,0 +1,7 @@
|
||||
---
|
||||
- name: Setup minimal GNOME + XRDP desktop
|
||||
hosts: all
|
||||
become: true
|
||||
gather_facts: true
|
||||
roles:
|
||||
- roles/vhosts/gnome_xrdp_minimal/
|
||||
17
harden_ssh_root_key_only.yml
Normal file
17
harden_ssh_root_key_only.yml
Normal file
@ -0,0 +1,17 @@
|
||||
---
|
||||
- name: Harden SSH on all inventory hosts
|
||||
hosts: all
|
||||
become: true
|
||||
gather_facts: true
|
||||
|
||||
vars:
|
||||
sshd_config_path: /etc/ssh/sshd_config
|
||||
sshd_dropin_dir: /etc/ssh/sshd_config.d
|
||||
root_authorized_keys_path: /root/.ssh/authorized_keys
|
||||
local_public_key_path: "{{ lookup('env', 'HOME') }}/.ssh/id_rsa.pub"
|
||||
ansible_user: "{{ lookup('env', 'BOOTSTRAP_ROOT_USER') | default('root', true) }}"
|
||||
ansible_password: "{{ lookup('env', 'BOOTSTRAP_ROOT_PASSWORD') | default(omit, true) }}"
|
||||
ansible_become_password: "{{ lookup('env', 'BOOTSTRAP_BECOME_PASSWORD') | default(omit, true) }}"
|
||||
|
||||
roles:
|
||||
- role: harden_ssh_root_key_only
|
||||
@ -1,39 +1,19 @@
|
||||
[web]
|
||||
cn-website.svc.plus ansible_host=47.120.61.35
|
||||
global-console.svc.plus ansible_host=35.220.157.80 ansible_user=root
|
||||
hk-website ansible_host=35.220.224.163 ansible_user=root
|
||||
cn-front.svc.plus ansible_host=47.120.61.35 ansible_user=root
|
||||
|
||||
[deepflow_agents]
|
||||
192.168.1.101 ansible_user=root ansible_ssh_pass=pass101
|
||||
192.168.1.102 ansible_user=admin ansible_ssh_pass=pass102
|
||||
192.168.1.103 ansible_user=root ansible_ssh_pass=pass103 ansible_port=2222
|
||||
192.168.1.104 ansible_user=ubuntu ansible_ssh_private_key_file=~/.ssh/id_rsa_ubuntu
|
||||
|
||||
[mail]
|
||||
smtp.svc.plus ansible_host=45.130.167.90
|
||||
[agent_proxy]
|
||||
jp-xhttp-contabo.svc.plus ansible_host=46.250.251.132 ansible_user=root
|
||||
|
||||
[k3s]
|
||||
cn-k3s-vultr.svc.plus ansible_host=1.15.155.245 ansible_user=root ansible_ssh_private_key_file=~/.ssh/id_rsa
|
||||
jp-xhttp-contabo.svc.plus ansible_host=46.250.251.132 ansible_user=root ansible_ssh_private_key_file=~/.ssh/id_rsa
|
||||
jp-k3s-vultr.svc.plus ansible_host=jp-k3s-vultr.svc.plus ansible_user=root
|
||||
k3s_platform_git_private_key_path=~/.ssh/id_rsa
|
||||
|
||||
[bootstrap]
|
||||
auth.svc.plus ansible_host=34.92.122.119 ansible_user=root ansible_ssh_private_key_file=~/.ssh/id_rsa
|
||||
jp-k3s-vultr.svc.plus ansible_host=167.179.110.129 ansible_user=root
|
||||
|
||||
[all:vars]
|
||||
ansible_port=22
|
||||
ansible_user=root
|
||||
ansible_ssh_transfer_method=piped
|
||||
ansible_host_key_checking=False
|
||||
|
||||
# SSH 密钥或密码(二选一)
|
||||
# ansible_ssh_private_key_file=~/.ssh/id_rsa
|
||||
# ansible_ssh_pass=your_password
|
||||
ansible_ssh_private_key_file=~/.ssh/id_rsa
|
||||
k3s_platform_git_private_key=~/.ssh/id_rsa
|
||||
|
||||
# DeepFlow agent 配置变量
|
||||
controller_ips=["10.10.10.10", "10.10.10.11"]
|
||||
vtap_group_id="g-P22vLIMdB6"
|
||||
|
||||
# DeepFlow agent 安装包位置
|
||||
agent_base_dir="deepflow-agent-for-linux"
|
||||
agent_package_name="deepflow-agent-1.0-5407.systemd.x86_64.rpm"
|
||||
|
||||
7
plasma_xrdp_minimal.yaml
Normal file
7
plasma_xrdp_minimal.yaml
Normal file
@ -0,0 +1,7 @@
|
||||
---
|
||||
- name: Setup minimal Plasma + XRDP desktop
|
||||
hosts: all
|
||||
become: true
|
||||
gather_facts: true
|
||||
roles:
|
||||
- roles/vhosts/plasma_xrdp_minimal/
|
||||
@ -61,12 +61,16 @@
|
||||
- name: Set Cloudflare zone id
|
||||
ansible.builtin.set_fact:
|
||||
cloudflare_dns_zone_id: "{{ cloudflare_dns_zone_lookup.json.result[0].id }}"
|
||||
when: cloudflare_dns_zone_lookup is defined
|
||||
when:
|
||||
- cloudflare_dns_zone_lookup is defined
|
||||
- cloudflare_dns_zone_id | default('', true) | length == 0
|
||||
|
||||
- name: Show zone permissions for current token
|
||||
ansible.builtin.debug:
|
||||
msg: "Cloudflare token permissions for {{ cloudflare_dns_zone_name }}: {{ cloudflare_dns_zone_lookup.json.result[0].permissions | default([]) }}"
|
||||
when: cloudflare_dns_zone_lookup is defined
|
||||
when:
|
||||
- cloudflare_dns_zone_lookup is defined
|
||||
- cloudflare_dns_zone_lookup.json is defined
|
||||
|
||||
- name: Fail early when token does not have DNS edit permission
|
||||
ansible.builtin.assert:
|
||||
@ -77,7 +81,9 @@
|
||||
CLOUDFLARE_API_TOKEN is valid but lacks DNS edit permission for {{ cloudflare_dns_zone_name }}.
|
||||
Current permissions: {{ cloudflare_dns_zone_lookup.json.result[0].permissions | default([]) }}.
|
||||
Required: Zone read + DNS edit on the svc.plus zone.
|
||||
when: cloudflare_dns_zone_lookup is defined
|
||||
when:
|
||||
- cloudflare_dns_zone_lookup is defined
|
||||
- cloudflare_dns_zone_lookup.json is defined
|
||||
|
||||
- name: Query existing DNS records
|
||||
ansible.builtin.uri:
|
||||
|
||||
12
roles/cloudflare_svc_plus_dns/README.md
Normal file
12
roles/cloudflare_svc_plus_dns/README.md
Normal file
@ -0,0 +1,12 @@
|
||||
# cloudflare_svc_plus_dns
|
||||
|
||||
Specialized wrapper role for the `svc.plus` DNS set.
|
||||
|
||||
## What it does
|
||||
|
||||
- Loads the managed record manifest from `playbooks/vars/cloudflare_svc_plus_dns.yml`
|
||||
- Delegates the actual create/update/delete reconciliation to the shared `cloudflare_dns` role
|
||||
|
||||
## Entry point
|
||||
|
||||
Use `update_cloudflare_svc_plus_dns.yml` to apply this role.
|
||||
8
roles/cloudflare_svc_plus_dns/tasks/main.yml
Normal file
8
roles/cloudflare_svc_plus_dns/tasks/main.yml
Normal file
@ -0,0 +1,8 @@
|
||||
---
|
||||
- name: Load svc.plus DNS manifest
|
||||
ansible.builtin.include_vars:
|
||||
file: "{{ role_path }}/../../vars/cloudflare_svc_plus_dns.yml"
|
||||
|
||||
- name: Reconcile svc.plus DNS via shared Cloudflare role
|
||||
ansible.builtin.include_role:
|
||||
name: cloudflare_dns
|
||||
43
roles/harden_ssh_root_key_only/README.md
Normal file
43
roles/harden_ssh_root_key_only/README.md
Normal file
@ -0,0 +1,43 @@
|
||||
# harden_ssh_root_key_only
|
||||
|
||||
Harden SSH access for inventory hosts by installing the local operator public key for `root` and disabling password-based SSH authentication.
|
||||
|
||||
## What it does
|
||||
|
||||
- Reads `~/.ssh/id_rsa.pub` from the local machine by default
|
||||
- Installs that public key into `/root/.ssh/authorized_keys`
|
||||
- Writes an SSH daemon drop-in at `/etc/ssh/sshd_config.d/99-codex-root-key-only.conf`
|
||||
- Disables password and keyboard-interactive SSH auth
|
||||
- Reloads the SSH service after validating config syntax
|
||||
|
||||
## Variables
|
||||
|
||||
- `local_public_key_path`: path to the operator public key, default `~/.ssh/id_rsa.pub`
|
||||
- `root_authorized_keys_path`: root authorized_keys path, default `/root/.ssh/authorized_keys`
|
||||
- `sshd_dropin_dir`: SSH drop-in directory, default `/etc/ssh/sshd_config.d`
|
||||
- `ssh_service_name_override`: optional service name override, otherwise auto-detects `ssh` or `sshd`
|
||||
|
||||
## Example playbook
|
||||
|
||||
```yaml
|
||||
- hosts: all
|
||||
become: true
|
||||
roles:
|
||||
- role: harden_ssh_root_key_only
|
||||
```
|
||||
|
||||
## Validation
|
||||
|
||||
After running the role, verify:
|
||||
|
||||
```bash
|
||||
sshd -T | egrep '^(passwordauthentication|kbdinteractiveauthentication|pubkeyauthentication|permitrootlogin)'
|
||||
passwd -S root
|
||||
```
|
||||
|
||||
Expected:
|
||||
|
||||
- `PasswordAuthentication no`
|
||||
- `KbdInteractiveAuthentication no`
|
||||
- `PubkeyAuthentication yes`
|
||||
- `root` remains accessible with the installed key
|
||||
6
roles/harden_ssh_root_key_only/defaults/main.yml
Normal file
6
roles/harden_ssh_root_key_only/defaults/main.yml
Normal file
@ -0,0 +1,6 @@
|
||||
---
|
||||
sshd_config_path: /etc/ssh/sshd_config
|
||||
sshd_dropin_dir: /etc/ssh/sshd_config.d
|
||||
root_authorized_keys_path: /root/.ssh/authorized_keys
|
||||
local_public_key_path: "{{ lookup('env', 'HOME') }}/.ssh/id_rsa.pub"
|
||||
ssh_service_name_override: ""
|
||||
82
roles/harden_ssh_root_key_only/tasks/main.yml
Normal file
82
roles/harden_ssh_root_key_only/tasks/main.yml
Normal file
@ -0,0 +1,82 @@
|
||||
---
|
||||
- name: Read local SSH public key
|
||||
ansible.builtin.set_fact:
|
||||
local_ssh_public_key: "{{ lookup('ansible.builtin.file', local_public_key_path) | trim }}"
|
||||
|
||||
- name: Assert local SSH public key exists
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- local_ssh_public_key | length > 0
|
||||
fail_msg: "local_public_key_path must point to a readable SSH public key."
|
||||
|
||||
- name: Ensure root SSH directory exists
|
||||
ansible.builtin.file:
|
||||
path: /root/.ssh
|
||||
state: directory
|
||||
mode: "0700"
|
||||
owner: root
|
||||
group: root
|
||||
|
||||
- name: Install local public key for root
|
||||
ansible.posix.authorized_key:
|
||||
user: root
|
||||
key: "{{ local_ssh_public_key }}"
|
||||
state: present
|
||||
manage_dir: false
|
||||
|
||||
- name: Ensure sshd drop-in directory exists
|
||||
ansible.builtin.file:
|
||||
path: "{{ sshd_dropin_dir }}"
|
||||
state: directory
|
||||
mode: "0755"
|
||||
owner: root
|
||||
group: root
|
||||
|
||||
- name: Write sshd hardening drop-in
|
||||
ansible.builtin.copy:
|
||||
dest: "{{ sshd_dropin_dir }}/99-codex-root-key-only.conf"
|
||||
mode: "0644"
|
||||
owner: root
|
||||
group: root
|
||||
content: |
|
||||
PermitRootLogin yes
|
||||
PubkeyAuthentication yes
|
||||
PasswordAuthentication no
|
||||
KbdInteractiveAuthentication no
|
||||
ChallengeResponseAuthentication no
|
||||
UsePAM yes
|
||||
|
||||
- name: Validate sshd configuration syntax
|
||||
ansible.builtin.command: sshd -t
|
||||
changed_when: false
|
||||
when: not ansible_check_mode
|
||||
|
||||
- name: Collect service facts
|
||||
ansible.builtin.service_facts:
|
||||
changed_when: false
|
||||
|
||||
- name: Select SSH service name
|
||||
ansible.builtin.set_fact:
|
||||
ssh_service_name: >-
|
||||
{{
|
||||
ssh_service_name_override
|
||||
if ssh_service_name_override | length > 0
|
||||
else ('ssh' if 'ssh.service' in ansible_facts.services else 'sshd')
|
||||
}}
|
||||
|
||||
- name: Reload SSH service
|
||||
ansible.builtin.service:
|
||||
name: "{{ ssh_service_name }}"
|
||||
state: reloaded
|
||||
|
||||
- name: Read root authorized_keys
|
||||
ansible.builtin.slurp:
|
||||
src: "{{ root_authorized_keys_path }}"
|
||||
register: root_authorized_keys
|
||||
changed_when: false
|
||||
|
||||
- name: Assert public key was installed
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- local_ssh_public_key in (root_authorized_keys.content | b64decode)
|
||||
fail_msg: "Local public key was not installed into /root/.ssh/authorized_keys"
|
||||
@ -27,6 +27,18 @@
|
||||
mode: "0755"
|
||||
notify: Restart opencode acp bridge
|
||||
|
||||
- name: Ensure OpenCode runtime directories exist
|
||||
ansible.builtin.file:
|
||||
path: "{{ item }}"
|
||||
state: directory
|
||||
owner: "{{ acp_opencode_service_user }}"
|
||||
group: "{{ acp_opencode_service_group }}"
|
||||
mode: "0755"
|
||||
loop:
|
||||
- "{{ acp_opencode_home }}"
|
||||
- "{{ acp_opencode_home }}/.local"
|
||||
- "{{ acp_opencode_workdir }}"
|
||||
|
||||
- name: Deploy Caddy main file
|
||||
ansible.builtin.template:
|
||||
src: Caddyfile.j2
|
||||
|
||||
33
roles/vhosts/gnome_xrdp_minimal/README.md
Normal file
33
roles/vhosts/gnome_xrdp_minimal/README.md
Normal file
@ -0,0 +1,33 @@
|
||||
# gnome_xrdp_minimal
|
||||
|
||||
Minimal GNOME + XRDP role for Debian, Ubuntu, Fedora, and OpenSuse VPS hosts.
|
||||
|
||||
## What it does
|
||||
|
||||
- Installs a minimal GNOME desktop stack and XRDP
|
||||
- Installs the Xorg backend needed by XRDP (`xserver-xorg-core`, `xorgxrdp`)
|
||||
- Installs open-source Chromium browser
|
||||
- Installs Chinese font support (`fonts-noto-cjk`)
|
||||
- Creates `~/.xsession` for the target desktop user
|
||||
- Enables `xrdp` and `xrdp-sesman`
|
||||
- Optionally opens TCP `3389` with UFW if UFW is present
|
||||
- Creates or updates the desktop user and ensures it has a usable local password for XRDP login
|
||||
|
||||
## Variables
|
||||
|
||||
- `gnome_user`: desktop login user, default `ubuntu`
|
||||
- `gnome_packages`: minimal package list
|
||||
- `gnome_enable_ufw`: whether to allow the RDP port with UFW
|
||||
- `gnome_rdp_port`: RDP port, default `3389`
|
||||
- `gnome_user_groups`: supplemental groups for the desktop user, default `["sudo"]`
|
||||
- `gnome_user_password_plaintext`: required password for the desktop user so XRDP can authenticate
|
||||
- Supported platforms: Debian/Ubuntu, Fedora, OpenSuse
|
||||
|
||||
## Example playbook
|
||||
|
||||
```yaml
|
||||
- hosts: vps
|
||||
become: true
|
||||
roles:
|
||||
- role: roles/vhosts/gnome_xrdp_minimal
|
||||
```
|
||||
48
roles/vhosts/gnome_xrdp_minimal/defaults/main.yml
Normal file
48
roles/vhosts/gnome_xrdp_minimal/defaults/main.yml
Normal file
@ -0,0 +1,48 @@
|
||||
---
|
||||
gnome_user: ubuntu
|
||||
|
||||
gnome_packages_debian:
|
||||
- gnome-session
|
||||
- gnome-shell
|
||||
- gnome-terminal
|
||||
- nautilus
|
||||
- dbus-x11
|
||||
- x11-xserver-utils
|
||||
- xserver-xorg-core
|
||||
- xorgxrdp
|
||||
- chromium
|
||||
- fonts-noto-cjk
|
||||
- xrdp
|
||||
|
||||
gnome_packages_fedora:
|
||||
- gnome-session
|
||||
- gnome-shell
|
||||
- gnome-terminal
|
||||
- nautilus
|
||||
- dbus-x11
|
||||
- xorg-x11-server-Xorg
|
||||
- xorgxrdp
|
||||
- chromium
|
||||
- google-noto-sans-cjk-fonts
|
||||
- xrdp
|
||||
|
||||
gnome_packages_opensuse:
|
||||
- gnome-session
|
||||
- gnome-shell
|
||||
- gnome-terminal
|
||||
- nautilus
|
||||
- dbus-1-x11
|
||||
- xorg-x11-server
|
||||
- xorgxrdp
|
||||
- chromium
|
||||
- noto-sans-cjk-fonts
|
||||
- xrdp
|
||||
|
||||
gnome_enable_ufw: true
|
||||
gnome_rdp_port: 3389
|
||||
|
||||
gnome_manage_user: true
|
||||
gnome_user_shell: /bin/bash
|
||||
gnome_user_groups:
|
||||
- sudo
|
||||
gnome_user_password_plaintext: ""
|
||||
10
roles/vhosts/gnome_xrdp_minimal/handlers/main.yml
Normal file
10
roles/vhosts/gnome_xrdp_minimal/handlers/main.yml
Normal file
@ -0,0 +1,10 @@
|
||||
---
|
||||
- name: Restart xrdp
|
||||
ansible.builtin.service:
|
||||
name: xrdp
|
||||
state: restarted
|
||||
|
||||
- name: Restart xrdp sesman
|
||||
ansible.builtin.service:
|
||||
name: xrdp-sesman
|
||||
state: restarted
|
||||
53
roles/vhosts/gnome_xrdp_minimal/tasks/config.yml
Normal file
53
roles/vhosts/gnome_xrdp_minimal/tasks/config.yml
Normal file
@ -0,0 +1,53 @@
|
||||
---
|
||||
- name: Ensure the desktop user exists
|
||||
ansible.builtin.user:
|
||||
name: "{{ gnome_user }}"
|
||||
shell: "{{ gnome_user_shell }}"
|
||||
create_home: true
|
||||
state: present
|
||||
password_lock: false
|
||||
become: true
|
||||
when: gnome_manage_user | bool
|
||||
|
||||
- name: Fail when the desktop user password is not provided
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- gnome_user_password_plaintext | length > 0
|
||||
fail_msg: >-
|
||||
gnome_user_password_plaintext must be set so XRDP can authenticate the
|
||||
desktop user.
|
||||
when: gnome_manage_user | bool
|
||||
|
||||
- name: Set desktop user password for XRDP login
|
||||
ansible.builtin.user:
|
||||
name: "{{ gnome_user }}"
|
||||
password: "{{ gnome_user_password_plaintext | password_hash('sha512') }}"
|
||||
update_password: always
|
||||
password_lock: false
|
||||
become: true
|
||||
no_log: true
|
||||
when: gnome_manage_user | bool
|
||||
|
||||
- name: Ensure the desktop user can sudo
|
||||
ansible.builtin.user:
|
||||
name: "{{ gnome_user }}"
|
||||
groups: "{{ gnome_user_groups }}"
|
||||
append: true
|
||||
state: present
|
||||
become: true
|
||||
when:
|
||||
- gnome_manage_user | bool
|
||||
- gnome_user_groups | length > 0
|
||||
|
||||
- name: Ensure GNOME session file is present
|
||||
ansible.builtin.template:
|
||||
src: xsession.j2
|
||||
dest: "{{ gnome_xsession_file }}"
|
||||
owner: "{{ gnome_user }}"
|
||||
group: "{{ gnome_user }}"
|
||||
mode: "0644"
|
||||
become: true
|
||||
when: gnome_manage_user | bool
|
||||
notify:
|
||||
- Restart xrdp
|
||||
- Restart xrdp sesman
|
||||
99
roles/vhosts/gnome_xrdp_minimal/tasks/install.yml
Normal file
99
roles/vhosts/gnome_xrdp_minimal/tasks/install.yml
Normal file
@ -0,0 +1,99 @@
|
||||
---
|
||||
- name: Select GNOME package list for this platform
|
||||
ansible.builtin.set_fact:
|
||||
gnome_selected_packages: >-
|
||||
{{
|
||||
gnome_packages_debian if ansible_os_family == 'Debian'
|
||||
else gnome_packages_fedora if ansible_os_family == 'RedHat'
|
||||
else gnome_packages_opensuse if ansible_os_family == 'Suse'
|
||||
else []
|
||||
}}
|
||||
|
||||
- name: Fail on unsupported platform
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- gnome_selected_packages | length > 0
|
||||
fail_msg: "gnome_xrdp_minimal supports Debian, Ubuntu, Fedora, and OpenSuse only."
|
||||
|
||||
- name: Update apt cache
|
||||
ansible.builtin.apt:
|
||||
update_cache: true
|
||||
when: ansible_os_family == 'Debian'
|
||||
become: true
|
||||
|
||||
- name: Install minimal desktop packages
|
||||
ansible.builtin.apt:
|
||||
name: "{{ gnome_selected_packages }}"
|
||||
state: present
|
||||
install_recommends: false
|
||||
environment:
|
||||
DEBIAN_FRONTEND: noninteractive
|
||||
APT_LISTCHANGES_FRONTEND: none
|
||||
when: ansible_os_family == 'Debian'
|
||||
become: true
|
||||
|
||||
- name: Update DNF cache
|
||||
ansible.builtin.dnf:
|
||||
update_cache: true
|
||||
when: ansible_os_family == 'RedHat'
|
||||
become: true
|
||||
|
||||
- name: Install GNOME packages on Fedora
|
||||
ansible.builtin.dnf:
|
||||
name: "{{ gnome_selected_packages }}"
|
||||
state: present
|
||||
when: ansible_os_family == 'RedHat'
|
||||
become: true
|
||||
|
||||
- name: Refresh Zypper cache
|
||||
ansible.builtin.command: zypper --non-interactive refresh
|
||||
changed_when: false
|
||||
when: ansible_os_family == 'Suse'
|
||||
become: true
|
||||
|
||||
- name: Install GNOME packages on OpenSuse
|
||||
ansible.builtin.zypper:
|
||||
name: "{{ gnome_selected_packages }}"
|
||||
state: present
|
||||
type: package
|
||||
when: ansible_os_family == 'Suse'
|
||||
become: true
|
||||
|
||||
- name: Check whether the xrdp service account exists
|
||||
ansible.builtin.command: getent passwd xrdp
|
||||
register: gnome_xrdp_account
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
become: true
|
||||
|
||||
- name: Ensure xrdp user can read the TLS certificate group
|
||||
ansible.builtin.user:
|
||||
name: xrdp
|
||||
groups: ssl-cert
|
||||
append: true
|
||||
become: true
|
||||
when: gnome_xrdp_account.rc == 0
|
||||
|
||||
- name: Enable and start XRDP services
|
||||
ansible.builtin.service:
|
||||
name: "{{ item }}"
|
||||
enabled: true
|
||||
state: started
|
||||
loop: "{{ gnome_xrdp_services }}"
|
||||
become: true
|
||||
|
||||
- name: Check whether UFW is installed
|
||||
ansible.builtin.stat:
|
||||
path: /usr/sbin/ufw
|
||||
register: gnome_ufw_binary
|
||||
become: true
|
||||
|
||||
- name: Allow XRDP through UFW
|
||||
ansible.builtin.command: "ufw allow {{ gnome_rdp_port }}/tcp"
|
||||
register: gnome_ufw_allow
|
||||
changed_when: "'Skipping adding existing rule' not in gnome_ufw_allow.stdout"
|
||||
failed_when: false
|
||||
become: true
|
||||
when:
|
||||
- gnome_enable_ufw | bool
|
||||
- gnome_ufw_binary.stat.exists | default(false)
|
||||
16
roles/vhosts/gnome_xrdp_minimal/tasks/main.yml
Normal file
16
roles/vhosts/gnome_xrdp_minimal/tasks/main.yml
Normal file
@ -0,0 +1,16 @@
|
||||
---
|
||||
- name: Install minimal GNOME + XRDP stack
|
||||
ansible.builtin.import_tasks: install.yml
|
||||
tags: [gnome, gnome_install]
|
||||
|
||||
- name: Configure GNOME session and XRDP user setup
|
||||
ansible.builtin.import_tasks: config.yml
|
||||
tags: [gnome, gnome_config]
|
||||
|
||||
- name: Apply GNOME resource-saving tweaks
|
||||
ansible.builtin.import_tasks: optimize.yml
|
||||
tags: [gnome, gnome_optimize]
|
||||
|
||||
- name: Validate XRDP desktop readiness
|
||||
ansible.builtin.import_tasks: validate.yml
|
||||
tags: [gnome, gnome_validate]
|
||||
10
roles/vhosts/gnome_xrdp_minimal/tasks/optimize.yml
Normal file
10
roles/vhosts/gnome_xrdp_minimal/tasks/optimize.yml
Normal file
@ -0,0 +1,10 @@
|
||||
---
|
||||
- name: Ensure GNOME session settings are persisted
|
||||
ansible.builtin.file:
|
||||
path: "{{ gnome_user_home }}/.config"
|
||||
state: directory
|
||||
owner: "{{ gnome_user }}"
|
||||
group: "{{ gnome_user }}"
|
||||
mode: "0755"
|
||||
become: true
|
||||
when: gnome_manage_user | bool
|
||||
33
roles/vhosts/gnome_xrdp_minimal/tasks/validate.yml
Normal file
33
roles/vhosts/gnome_xrdp_minimal/tasks/validate.yml
Normal file
@ -0,0 +1,33 @@
|
||||
---
|
||||
- name: Check XRDP service status
|
||||
ansible.builtin.command: systemctl status xrdp --no-pager --full
|
||||
register: gnome_xrdp_status
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
become: true
|
||||
|
||||
- name: Show XRDP service status
|
||||
ansible.builtin.debug:
|
||||
var: gnome_xrdp_status.stdout_lines
|
||||
|
||||
- name: Check memory usage
|
||||
ansible.builtin.command: free -m
|
||||
register: gnome_memory_usage
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
- name: Show memory usage
|
||||
ansible.builtin.debug:
|
||||
var: gnome_memory_usage.stdout_lines
|
||||
|
||||
- name: Check current session type if available
|
||||
ansible.builtin.shell: 'printf "%s\n" "${XDG_SESSION_TYPE:-unknown}"'
|
||||
args:
|
||||
executable: /bin/bash
|
||||
register: gnome_session_type
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
- name: Show session type hint
|
||||
ansible.builtin.debug:
|
||||
msg: "XDG_SESSION_TYPE={{ gnome_session_type.stdout | default('unknown') }} (expected x11 inside the RDP session)"
|
||||
1
roles/vhosts/gnome_xrdp_minimal/templates/xsession.j2
Normal file
1
roles/vhosts/gnome_xrdp_minimal/templates/xsession.j2
Normal file
@ -0,0 +1 @@
|
||||
exec gnome-session
|
||||
6
roles/vhosts/gnome_xrdp_minimal/vars/main.yml
Normal file
6
roles/vhosts/gnome_xrdp_minimal/vars/main.yml
Normal file
@ -0,0 +1,6 @@
|
||||
---
|
||||
gnome_user_home: "/home/{{ gnome_user }}"
|
||||
gnome_xsession_file: "{{ gnome_user_home }}/.xsession"
|
||||
gnome_xrdp_services:
|
||||
- xrdp-sesman
|
||||
- xrdp
|
||||
33
roles/vhosts/plasma_xrdp_minimal/README.md
Normal file
33
roles/vhosts/plasma_xrdp_minimal/README.md
Normal file
@ -0,0 +1,33 @@
|
||||
# plasma_xrdp_minimal
|
||||
|
||||
Minimal Plasma + XRDP role for Debian, Ubuntu, Fedora, and OpenSuse VPS hosts.
|
||||
|
||||
## What it does
|
||||
|
||||
- Installs a minimal Plasma desktop stack and XRDP
|
||||
- Installs the Xorg backend needed by XRDP (`xserver-xorg-core`, `xorgxrdp`)
|
||||
- Installs open-source Chromium browser
|
||||
- Installs Chinese font support (`fonts-noto-cjk`)
|
||||
- Creates `~/.xsession` for the target desktop user
|
||||
- Enables `xrdp` and `xrdp-sesman`
|
||||
- Optionally opens TCP `3389` with UFW if UFW is present
|
||||
- Creates or updates the desktop user and ensures it has a usable local password for XRDP login
|
||||
|
||||
## Variables
|
||||
|
||||
- `plasma_user`: desktop login user, default `ubuntu`
|
||||
- `plasma_packages`: minimal package list
|
||||
- `plasma_enable_ufw`: whether to allow the RDP port with UFW
|
||||
- `plasma_rdp_port`: RDP port, default `3389`
|
||||
- `plasma_user_groups`: supplemental groups for the desktop user, default `["sudo"]`
|
||||
- `plasma_user_password_plaintext`: required password for the desktop user so XRDP can authenticate
|
||||
- Supported platforms: Debian/Ubuntu, Fedora, OpenSuse
|
||||
|
||||
## Example playbook
|
||||
|
||||
```yaml
|
||||
- hosts: vps
|
||||
become: true
|
||||
roles:
|
||||
- role: roles/vhosts/plasma_xrdp_minimal
|
||||
```
|
||||
48
roles/vhosts/plasma_xrdp_minimal/defaults/main.yml
Normal file
48
roles/vhosts/plasma_xrdp_minimal/defaults/main.yml
Normal file
@ -0,0 +1,48 @@
|
||||
---
|
||||
plasma_user: ubuntu
|
||||
|
||||
plasma_packages_debian:
|
||||
- plasma-desktop
|
||||
- kde-plasma-desktop
|
||||
- konsole
|
||||
- dolphin
|
||||
- dbus-x11
|
||||
- x11-xserver-utils
|
||||
- xserver-xorg-core
|
||||
- xorgxrdp
|
||||
- chromium
|
||||
- fonts-noto-cjk
|
||||
- xrdp
|
||||
|
||||
plasma_packages_fedora:
|
||||
- plasma-desktop
|
||||
- plasma-workspace
|
||||
- konsole
|
||||
- dolphin
|
||||
- dbus-x11
|
||||
- xorg-x11-server-Xorg
|
||||
- xorgxrdp
|
||||
- chromium
|
||||
- google-noto-sans-cjk-fonts
|
||||
- xrdp
|
||||
|
||||
plasma_packages_opensuse:
|
||||
- plasma-desktop
|
||||
- plasma5-session
|
||||
- konsole
|
||||
- dolphin
|
||||
- dbus-1-x11
|
||||
- xorg-x11-server
|
||||
- xorgxrdp
|
||||
- chromium
|
||||
- noto-sans-cjk-fonts
|
||||
- xrdp
|
||||
|
||||
plasma_enable_ufw: true
|
||||
plasma_rdp_port: 3389
|
||||
|
||||
plasma_manage_user: true
|
||||
plasma_user_shell: /bin/bash
|
||||
plasma_user_groups:
|
||||
- sudo
|
||||
plasma_user_password_plaintext: ""
|
||||
10
roles/vhosts/plasma_xrdp_minimal/handlers/main.yml
Normal file
10
roles/vhosts/plasma_xrdp_minimal/handlers/main.yml
Normal file
@ -0,0 +1,10 @@
|
||||
---
|
||||
- name: Restart xrdp
|
||||
ansible.builtin.service:
|
||||
name: xrdp
|
||||
state: restarted
|
||||
|
||||
- name: Restart xrdp sesman
|
||||
ansible.builtin.service:
|
||||
name: xrdp-sesman
|
||||
state: restarted
|
||||
53
roles/vhosts/plasma_xrdp_minimal/tasks/config.yml
Normal file
53
roles/vhosts/plasma_xrdp_minimal/tasks/config.yml
Normal file
@ -0,0 +1,53 @@
|
||||
---
|
||||
- name: Ensure the desktop user exists
|
||||
ansible.builtin.user:
|
||||
name: "{{ plasma_user }}"
|
||||
shell: "{{ plasma_user_shell }}"
|
||||
create_home: true
|
||||
state: present
|
||||
password_lock: false
|
||||
become: true
|
||||
when: plasma_manage_user | bool
|
||||
|
||||
- name: Fail when the desktop user password is not provided
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- plasma_user_password_plaintext | length > 0
|
||||
fail_msg: >-
|
||||
plasma_user_password_plaintext must be set so XRDP can authenticate the
|
||||
desktop user.
|
||||
when: plasma_manage_user | bool
|
||||
|
||||
- name: Set desktop user password for XRDP login
|
||||
ansible.builtin.user:
|
||||
name: "{{ plasma_user }}"
|
||||
password: "{{ plasma_user_password_plaintext | password_hash('sha512') }}"
|
||||
update_password: always
|
||||
password_lock: false
|
||||
become: true
|
||||
no_log: true
|
||||
when: plasma_manage_user | bool
|
||||
|
||||
- name: Ensure the desktop user can sudo
|
||||
ansible.builtin.user:
|
||||
name: "{{ plasma_user }}"
|
||||
groups: "{{ plasma_user_groups }}"
|
||||
append: true
|
||||
state: present
|
||||
become: true
|
||||
when:
|
||||
- plasma_manage_user | bool
|
||||
- plasma_user_groups | length > 0
|
||||
|
||||
- name: Ensure Plasma session file is present
|
||||
ansible.builtin.template:
|
||||
src: xsession.j2
|
||||
dest: "{{ plasma_xsession_file }}"
|
||||
owner: "{{ plasma_user }}"
|
||||
group: "{{ plasma_user }}"
|
||||
mode: "0644"
|
||||
become: true
|
||||
when: plasma_manage_user | bool
|
||||
notify:
|
||||
- Restart xrdp
|
||||
- Restart xrdp sesman
|
||||
99
roles/vhosts/plasma_xrdp_minimal/tasks/install.yml
Normal file
99
roles/vhosts/plasma_xrdp_minimal/tasks/install.yml
Normal file
@ -0,0 +1,99 @@
|
||||
---
|
||||
- name: Select Plasma package list for this platform
|
||||
ansible.builtin.set_fact:
|
||||
plasma_selected_packages: >-
|
||||
{{
|
||||
plasma_packages_debian if ansible_os_family == 'Debian'
|
||||
else plasma_packages_fedora if ansible_os_family == 'RedHat'
|
||||
else plasma_packages_opensuse if ansible_os_family == 'Suse'
|
||||
else []
|
||||
}}
|
||||
|
||||
- name: Fail on unsupported platform
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- plasma_selected_packages | length > 0
|
||||
fail_msg: "plasma_xrdp_minimal supports Debian, Ubuntu, Fedora, and OpenSuse only."
|
||||
|
||||
- name: Update apt cache
|
||||
ansible.builtin.apt:
|
||||
update_cache: true
|
||||
when: ansible_os_family == 'Debian'
|
||||
become: true
|
||||
|
||||
- name: Install minimal desktop packages
|
||||
ansible.builtin.apt:
|
||||
name: "{{ plasma_selected_packages }}"
|
||||
state: present
|
||||
install_recommends: false
|
||||
environment:
|
||||
DEBIAN_FRONTEND: noninteractive
|
||||
APT_LISTCHANGES_FRONTEND: none
|
||||
when: ansible_os_family == 'Debian'
|
||||
become: true
|
||||
|
||||
- name: Update DNF cache
|
||||
ansible.builtin.dnf:
|
||||
update_cache: true
|
||||
when: ansible_os_family == 'RedHat'
|
||||
become: true
|
||||
|
||||
- name: Install Plasma packages on Fedora
|
||||
ansible.builtin.dnf:
|
||||
name: "{{ plasma_selected_packages }}"
|
||||
state: present
|
||||
when: ansible_os_family == 'RedHat'
|
||||
become: true
|
||||
|
||||
- name: Refresh Zypper cache
|
||||
ansible.builtin.command: zypper --non-interactive refresh
|
||||
changed_when: false
|
||||
when: ansible_os_family == 'Suse'
|
||||
become: true
|
||||
|
||||
- name: Install Plasma packages on OpenSuse
|
||||
ansible.builtin.zypper:
|
||||
name: "{{ plasma_selected_packages }}"
|
||||
state: present
|
||||
type: package
|
||||
when: ansible_os_family == 'Suse'
|
||||
become: true
|
||||
|
||||
- name: Check whether the xrdp service account exists
|
||||
ansible.builtin.command: getent passwd xrdp
|
||||
register: plasma_xrdp_account
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
become: true
|
||||
|
||||
- name: Ensure xrdp user can read the TLS certificate group
|
||||
ansible.builtin.user:
|
||||
name: xrdp
|
||||
groups: ssl-cert
|
||||
append: true
|
||||
become: true
|
||||
when: plasma_xrdp_account.rc == 0
|
||||
|
||||
- name: Enable and start XRDP services
|
||||
ansible.builtin.service:
|
||||
name: "{{ item }}"
|
||||
enabled: true
|
||||
state: started
|
||||
loop: "{{ plasma_xrdp_services }}"
|
||||
become: true
|
||||
|
||||
- name: Check whether UFW is installed
|
||||
ansible.builtin.stat:
|
||||
path: /usr/sbin/ufw
|
||||
register: plasma_ufw_binary
|
||||
become: true
|
||||
|
||||
- name: Allow XRDP through UFW
|
||||
ansible.builtin.command: "ufw allow {{ plasma_rdp_port }}/tcp"
|
||||
register: plasma_ufw_allow
|
||||
changed_when: "'Skipping adding existing rule' not in plasma_ufw_allow.stdout"
|
||||
failed_when: false
|
||||
become: true
|
||||
when:
|
||||
- plasma_enable_ufw | bool
|
||||
- plasma_ufw_binary.stat.exists | default(false)
|
||||
16
roles/vhosts/plasma_xrdp_minimal/tasks/main.yml
Normal file
16
roles/vhosts/plasma_xrdp_minimal/tasks/main.yml
Normal file
@ -0,0 +1,16 @@
|
||||
---
|
||||
- name: Install minimal Plasma + XRDP stack
|
||||
ansible.builtin.import_tasks: install.yml
|
||||
tags: [plasma, plasma_install]
|
||||
|
||||
- name: Configure Plasma session and XRDP user setup
|
||||
ansible.builtin.import_tasks: config.yml
|
||||
tags: [plasma, plasma_config]
|
||||
|
||||
- name: Apply Plasma resource-saving tweaks
|
||||
ansible.builtin.import_tasks: optimize.yml
|
||||
tags: [plasma, plasma_optimize]
|
||||
|
||||
- name: Validate XRDP desktop readiness
|
||||
ansible.builtin.import_tasks: validate.yml
|
||||
tags: [plasma, plasma_validate]
|
||||
10
roles/vhosts/plasma_xrdp_minimal/tasks/optimize.yml
Normal file
10
roles/vhosts/plasma_xrdp_minimal/tasks/optimize.yml
Normal file
@ -0,0 +1,10 @@
|
||||
---
|
||||
- name: Ensure Plasma session settings are persisted
|
||||
ansible.builtin.file:
|
||||
path: "{{ plasma_user_home }}/.config"
|
||||
state: directory
|
||||
owner: "{{ plasma_user }}"
|
||||
group: "{{ plasma_user }}"
|
||||
mode: "0755"
|
||||
become: true
|
||||
when: plasma_manage_user | bool
|
||||
33
roles/vhosts/plasma_xrdp_minimal/tasks/validate.yml
Normal file
33
roles/vhosts/plasma_xrdp_minimal/tasks/validate.yml
Normal file
@ -0,0 +1,33 @@
|
||||
---
|
||||
- name: Check XRDP service status
|
||||
ansible.builtin.command: systemctl status xrdp --no-pager --full
|
||||
register: plasma_xrdp_status
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
become: true
|
||||
|
||||
- name: Show XRDP service status
|
||||
ansible.builtin.debug:
|
||||
var: plasma_xrdp_status.stdout_lines
|
||||
|
||||
- name: Check memory usage
|
||||
ansible.builtin.command: free -m
|
||||
register: plasma_memory_usage
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
- name: Show memory usage
|
||||
ansible.builtin.debug:
|
||||
var: plasma_memory_usage.stdout_lines
|
||||
|
||||
- name: Check current session type if available
|
||||
ansible.builtin.shell: 'printf "%s\n" "${XDG_SESSION_TYPE:-unknown}"'
|
||||
args:
|
||||
executable: /bin/bash
|
||||
register: plasma_session_type
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
- name: Show session type hint
|
||||
ansible.builtin.debug:
|
||||
msg: "XDG_SESSION_TYPE={{ plasma_session_type.stdout | default('unknown') }} (expected x11 inside the RDP session)"
|
||||
1
roles/vhosts/plasma_xrdp_minimal/templates/xsession.j2
Normal file
1
roles/vhosts/plasma_xrdp_minimal/templates/xsession.j2
Normal file
@ -0,0 +1 @@
|
||||
exec startplasma-x11
|
||||
6
roles/vhosts/plasma_xrdp_minimal/vars/main.yml
Normal file
6
roles/vhosts/plasma_xrdp_minimal/vars/main.yml
Normal file
@ -0,0 +1,6 @@
|
||||
---
|
||||
plasma_user_home: "/home/{{ plasma_user }}"
|
||||
plasma_xsession_file: "{{ plasma_user_home }}/.xsession"
|
||||
plasma_xrdp_services:
|
||||
- xrdp-sesman
|
||||
- xrdp
|
||||
@ -12,6 +12,7 @@ Minimal XFCE4 + XRDP role for constrained Ubuntu/Debian VPS hosts.
|
||||
- Enables `xrdp` and `xrdp-sesman`
|
||||
- Disables compositor and animations to reduce resource usage
|
||||
- Optionally opens TCP `3389` with UFW if UFW is present
|
||||
- Creates or updates the desktop user and ensures it has a usable local password for XRDP login
|
||||
|
||||
## Variables
|
||||
|
||||
@ -22,6 +23,7 @@ Minimal XFCE4 + XRDP role for constrained Ubuntu/Debian VPS hosts.
|
||||
- `xfce_disable_compositor`: default `true`
|
||||
- `xfce_disable_animations`: default `true`
|
||||
- `xfce_user_groups`: supplemental groups for the desktop user, default `["sudo"]`
|
||||
- `xfce_user_password_plaintext`: required password for the desktop user so XRDP can authenticate
|
||||
|
||||
## Example playbook
|
||||
|
||||
@ -40,6 +42,7 @@ Run these on the server after connecting through RDP:
|
||||
systemctl status xrdp --no-pager --full
|
||||
echo "$XDG_SESSION_TYPE"
|
||||
free -m
|
||||
passwd -S ubuntu
|
||||
```
|
||||
|
||||
Expected:
|
||||
@ -47,3 +50,4 @@ Expected:
|
||||
- `xrdp` is active
|
||||
- `XDG_SESSION_TYPE=x11`
|
||||
- memory stays under the host budget
|
||||
- `ubuntu` is not locked and can authenticate with the password you provided
|
||||
|
||||
@ -27,3 +27,4 @@ xfce_manage_user: true
|
||||
xfce_user_shell: /bin/bash
|
||||
xfce_user_groups:
|
||||
- sudo
|
||||
xfce_user_password_plaintext: ""
|
||||
|
||||
@ -5,9 +5,29 @@
|
||||
shell: "{{ xfce_user_shell }}"
|
||||
create_home: true
|
||||
state: present
|
||||
password_lock: false
|
||||
become: true
|
||||
when: xfce_manage_user | bool
|
||||
|
||||
- name: Fail when the desktop user password is not provided
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- xfce_user_password_plaintext | length > 0
|
||||
fail_msg: >-
|
||||
xfce_user_password_plaintext must be set so XRDP can authenticate the
|
||||
desktop user.
|
||||
when: xfce_manage_user | bool
|
||||
|
||||
- name: Set desktop user password for XRDP login
|
||||
ansible.builtin.user:
|
||||
name: "{{ xfce_user }}"
|
||||
password: "{{ xfce_user_password_plaintext | password_hash('sha512') }}"
|
||||
update_password: always
|
||||
password_lock: false
|
||||
become: true
|
||||
no_log: true
|
||||
when: xfce_manage_user | bool
|
||||
|
||||
- name: Ensure the desktop user can sudo
|
||||
ansible.builtin.user:
|
||||
name: "{{ xfce_user }}"
|
||||
|
||||
@ -3,7 +3,5 @@
|
||||
hosts: localhost
|
||||
connection: local
|
||||
gather_facts: false
|
||||
vars_files:
|
||||
- vars/cloudflare_svc_plus_dns.yml
|
||||
roles:
|
||||
- cloudflare_dns
|
||||
- role: cloudflare_svc_plus_dns
|
||||
|
||||
7
update_cloudflare_svc_plus_dns.yml
Normal file
7
update_cloudflare_svc_plus_dns.yml
Normal file
@ -0,0 +1,7 @@
|
||||
---
|
||||
- name: Update svc.plus Cloudflare DNS records
|
||||
hosts: localhost
|
||||
connection: local
|
||||
gather_facts: false
|
||||
roles:
|
||||
- role: cloudflare_svc_plus_dns
|
||||
@ -42,17 +42,7 @@ cloudflare_dns_records:
|
||||
proxied: false
|
||||
- type: A
|
||||
name: acp-server.svc.plus
|
||||
content: 167.179.110.129
|
||||
ttl: 1
|
||||
proxied: false
|
||||
- type: A
|
||||
name: acp-server-codex.svc.plus
|
||||
content: 167.179.110.129
|
||||
ttl: 1
|
||||
proxied: false
|
||||
- type: A
|
||||
name: acp-server-opencode.svc.plus
|
||||
content: 167.179.110.129
|
||||
content: 46.250.251.132
|
||||
ttl: 1
|
||||
proxied: false
|
||||
- type: CNAME
|
||||
|
||||
Loading…
Reference in New Issue
Block a user