feat: Integrate Authentik OIDC into Semaphore and enhance Proxmox VM template creation with image list selection and SSH key management.
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
ansible/hosts.ini
|
||||||
@@ -1,84 +1,119 @@
|
|||||||
# Home Server Ansible Configuration
|
# Proxmox VM Management Suite
|
||||||
|
|
||||||
This directory contains Ansible playbooks for managing the Proxmox home server environment.
|
A comprehensive Ansible automation suite for managing Proxmox Virtual Machines. This suite allows you to easily create Cloud-Init templates, provision new VMs, manage backups, and decommission resources across multiple Proxmox hosts.
|
||||||
|
|
||||||
## Directory Structure
|
## Features
|
||||||
|
|
||||||
- `inventory/`: Contains the inventory file `hosts.ini` where you define your servers.
|
- **Template Management**:
|
||||||
- `playbooks/`: Contains the actual Ansible playbooks.
|
- Automatically download Cloud Images (Ubuntu, Debian, etc.).
|
||||||
- `ansible.cfg`: Local Ansible configuration.
|
- Pre-configured with Cloud-Init (SSH keys, IP Config).
|
||||||
- `requirements.yml`: List of Ansible collections required.
|
- Support for selecting images from a curated list or custom URLs.
|
||||||
|
- **VM Provisioning**:
|
||||||
|
- Clone from templates (Full or Linked clones).
|
||||||
|
- Auto-start option.
|
||||||
|
- **Lifecycle Management**:
|
||||||
|
- Backup VMs (Snapshot mode).
|
||||||
|
- Delete/Purge VMs.
|
||||||
|
- **Security**:
|
||||||
|
- **Automatic SSH Key Injection**: Automatically adds a defined Admin SSH key to every template.
|
||||||
|
- Support for injecting additional SSH keys per deployment.
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
1. **Install Requirements**:
|
### 1. Requirements
|
||||||
```bash
|
|
||||||
ansible-galaxy install -r requirements.yml
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Configure Inventory**:
|
|
||||||
Edit `inventory/hosts.ini` and update the following:
|
|
||||||
- `ansible_host`: The IP address of your Proxmox node.
|
|
||||||
- `ansible_user`: The SSH user (usually root).
|
|
||||||
- `proxmox_api_*`: Variables if you plan to use API-based modules in the future.
|
|
||||||
|
|
||||||
*Note: Ensure you have SSH key access to your Proxmox node for passwordless login, or uncomment `ansible_ssh_pass`.*
|
|
||||||
|
|
||||||
## Available Playbooks
|
|
||||||
|
|
||||||
### Create Ubuntu Cloud Template (`playbooks/create_ubuntu_template.yml`)
|
|
||||||
|
|
||||||
This playbook downloads a generic Ubuntu 22.04 Cloud Image and converts it into a Proxmox VM Template.
|
|
||||||
|
|
||||||
**Usage:**
|
|
||||||
|
|
||||||
|
Install the required Ansible collections:
|
||||||
```bash
|
```bash
|
||||||
# Run the playbook
|
ansible-galaxy install -r requirements.yml
|
||||||
ansible-playbook playbooks/create_ubuntu_template.yml
|
|
||||||
```
|
```
|
||||||
|
|
||||||
**Variables:**
|
### 2. Configuration
|
||||||
You can override variables at runtime or by editing the playbook:
|
|
||||||
|
|
||||||
- `template_id`: Default `9000`
|
Edit `roles/proxmox_vm/defaults/main.yml` to set your global defaults, specifically the **Admin SSH Key**.
|
||||||
- `template_name`: Default `ubuntu-2204-cloud`
|
|
||||||
- `storage_pool`: Default `local-lvm`
|
|
||||||
|
|
||||||
Example overriding variables:
|
**Important Variable to Change:**
|
||||||
```bash
|
```yaml
|
||||||
ansible-playbook playbooks/create_ubuntu_template.yml -e "template_id=9001 template_name=my-custom-template"
|
# ansible/roles/proxmox_vm/defaults/main.yml
|
||||||
|
admin_ssh_key: "ssh-ed25519 AAAAC3... your-actual-public-key"
|
||||||
```
|
```
|
||||||
|
|
||||||
### Manage VM Playbook (`playbooks/manage_vm.yml`)
|
## Usage
|
||||||
|
|
||||||
This unified playbook allows you to manage VMs (create from template, delete, backup, create template) across your Proxmox hosts.
|
The main entry point is the playbook `playbooks/manage_vm.yml`. You control the behavior using the `proxmox_action` variable.
|
||||||
|
|
||||||
**Usage:**
|
### 1. Create a Cloud-Init Template
|
||||||
|
|
||||||
The playbook target defaults to the `proxmox` group, but you should usually specify a specific host using `target_host` variable or `-l` limit.
|
You can create a template by selecting a predefined alias (e.g., `ubuntu-22.04`) or providing a custom URL.
|
||||||
|
|
||||||
1. **Create a New Template**:
|
**Option A: Select from List (Default)**
|
||||||
```bash
|
Current aliases: `ubuntu-22.04`, `ubuntu-24.04`, `debian-12`.
|
||||||
ansible-playbook playbooks/manage_vm.yml -e "proxmox_action=create_template vmid=9003 template_name=my-ubuntu-template"
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Create a VM from Template**:
|
```bash
|
||||||
```bash
|
# Create Ubuntu 22.04 Template (ID: 9000)
|
||||||
ansible-playbook playbooks/manage_vm.yml -e "proxmox_action=create_vm vmid=9002 new_vmid=105 new_vm_name=my-new-vm"
|
ansible-playbook playbooks/manage_vm.yml \
|
||||||
```
|
-e "proxmox_action=create_template vmid=9000 template_name=ubuntu-22-template image_alias=ubuntu-22.04"
|
||||||
|
```
|
||||||
|
|
||||||
3. **Delete a VM**:
|
**Option B: Custom URL**
|
||||||
```bash
|
```bash
|
||||||
ansible-playbook playbooks/manage_vm.yml -e "proxmox_action=delete_vm vmid=105"
|
ansible-playbook playbooks/manage_vm.yml \
|
||||||
```
|
-e "proxmox_action=create_template \
|
||||||
|
vmid=9001 \
|
||||||
|
template_name=custom-linux \
|
||||||
|
image_source_type=url \
|
||||||
|
custom_image_url='https://example.com/image.qcow2'"
|
||||||
|
```
|
||||||
|
|
||||||
4. **Backup a VM**:
|
### 2. Create a VM from Template
|
||||||
```bash
|
|
||||||
ansible-playbook playbooks/manage_vm.yml -e "proxmox_action=backup_vm vmid=105"
|
|
||||||
```
|
|
||||||
|
|
||||||
**Variables:**
|
Clone a valid template to a new VM.
|
||||||
- `proxmox_action`: One of `create_template`, `create_vm`, `delete_vm`, `backup_vm` (Default: `create_vm`)
|
|
||||||
- `target_host`: The host to run on (Default: `proxmox` group). Example: `-e "target_host=mercury"`
|
|
||||||
|
|
||||||
*See `roles/proxmox_vm/defaults/main.yml` for all available configuration options.*
|
```bash
|
||||||
|
ansible-playbook playbooks/manage_vm.yml \
|
||||||
|
-e "proxmox_action=create_vm \
|
||||||
|
vmid=9000 \
|
||||||
|
new_vmid=105 \
|
||||||
|
new_vm_name=web-server-01"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Backup a VM
|
||||||
|
|
||||||
|
Create a snapshot backup of a specific VM.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ansible-playbook playbooks/manage_vm.yml \
|
||||||
|
-e "proxmox_action=backup_vm vmid=105"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Delete a VM
|
||||||
|
|
||||||
|
Stop and purge a VM.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ansible-playbook playbooks/manage_vm.yml \
|
||||||
|
-e "proxmox_action=delete_vm vmid=105"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Advanced Usage
|
||||||
|
|
||||||
|
### Handling Multiple Hosts
|
||||||
|
You can target a specific Proxmox node using the `target_host` variable.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ansible-playbook playbooks/manage_vm.yml -e "proxmox_action=create_vm ... target_host=mercury"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Injecting Additional SSH Keys
|
||||||
|
You can add extra SSH keys for a specific run (or add them to the defaults file).
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ansible-playbook playbooks/manage_vm.yml \
|
||||||
|
-e "proxmox_action=create_template ... additional_ssh_keys=['ssh-rsa AAAAB3... key1', 'ssh-ed25519 AAAA... key2']"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Directory Structure
|
||||||
|
|
||||||
|
- `roles/proxmox_vm/`: Core logic role.
|
||||||
|
- `defaults/main.yml`: Configuration variables (Images, Keys, Defaults).
|
||||||
|
- `tasks/`: Action modules (`create_template.yml`, `create_vm.yml`, etc.).
|
||||||
|
- `inventory/`: Host definitions.
|
||||||
|
|||||||
@@ -5,22 +5,54 @@
|
|||||||
proxmox_action: create_vm
|
proxmox_action: create_vm
|
||||||
|
|
||||||
# Common settings
|
# Common settings
|
||||||
storage_pool: local-lvm
|
storage_pool: Lithium
|
||||||
vmid: 9000
|
vmid: 9000
|
||||||
|
target_node: "{{ inventory_hostname }}"
|
||||||
|
|
||||||
# Template Creation settings
|
# --- Template Creation Settings ---
|
||||||
|
|
||||||
|
# Image Source Selection
|
||||||
|
# Options: 'list' (use image_alias) or 'url' (use custom_image_url)
|
||||||
|
image_source_type: list
|
||||||
|
|
||||||
|
# Predefined Image List
|
||||||
|
# You can select these by setting image_alias
|
||||||
|
image_list:
|
||||||
|
ubuntu-22.04:
|
||||||
|
url: "https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img"
|
||||||
|
filename: "ubuntu-22.04-server-cloudimg-amd64.img"
|
||||||
|
ubuntu-24.04:
|
||||||
|
url: "https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.img"
|
||||||
|
filename: "ubuntu-24.04-server-cloudimg-amd64.img"
|
||||||
|
debian-12:
|
||||||
|
url: "https://cloud.debian.org/images/cloud/bookworm/latest/debian-12-generic-amd64.qcow2"
|
||||||
|
filename: "debian-12-generic-amd64.qcow2"
|
||||||
|
|
||||||
|
# Selection (Default)
|
||||||
|
image_alias: ubuntu-22.04
|
||||||
|
|
||||||
|
# Custom URL (Used if image_source_type is 'url')
|
||||||
|
custom_image_url: ""
|
||||||
|
custom_image_name: "custom-image.img"
|
||||||
|
|
||||||
|
# Template Config
|
||||||
template_name: ubuntu-cloud-template
|
template_name: ubuntu-cloud-template
|
||||||
image_url: "https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img"
|
|
||||||
image_name: "ubuntu-22.04-server-cloudimg-amd64.img"
|
|
||||||
memory: 2048
|
memory: 2048
|
||||||
cores: 2
|
cores: 2
|
||||||
|
|
||||||
# Create VM settings (cloning)
|
# --- SSH Key Configuration ---
|
||||||
new_vm_name: new-vm
|
# The Admin Key is always added
|
||||||
target_node: "{{ inventory_hostname }}" # For cloning, usually same node
|
admin_ssh_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI..." # REPLACE THIS with your actual public key
|
||||||
clone_full: true # Full clone (independent) vs Linked clone
|
|
||||||
|
|
||||||
# Backup settings
|
# Additional keys (list of strings)
|
||||||
|
additional_ssh_keys: []
|
||||||
|
|
||||||
|
# --- Create VM Settings (Cloning) ---
|
||||||
|
new_vm_name: new-vm
|
||||||
|
clone_full: true # Full clone (independent) vs Linked clone
|
||||||
|
start_after_create: true
|
||||||
|
|
||||||
|
# --- Backup Settings ---
|
||||||
backup_mode: snapshot # snapshot, suspend, stop
|
backup_mode: snapshot # snapshot, suspend, stop
|
||||||
backup_compress: zstd
|
backup_compress: zstd
|
||||||
backup_storage: local
|
backup_storage: Lithium
|
||||||
|
|||||||
@@ -1,4 +1,16 @@
|
|||||||
---
|
---
|
||||||
|
- name: Resolve Image Variables (List)
|
||||||
|
set_fact:
|
||||||
|
_image_url: "{{ image_list[image_alias].url }}"
|
||||||
|
_image_name: "{{ image_list[image_alias].filename }}"
|
||||||
|
when: image_source_type == 'list'
|
||||||
|
|
||||||
|
- name: Resolve Image Variables (URL)
|
||||||
|
set_fact:
|
||||||
|
_image_url: "{{ custom_image_url }}"
|
||||||
|
_image_name: "{{ custom_image_name }}"
|
||||||
|
when: image_source_type == 'url'
|
||||||
|
|
||||||
- name: Check if template already exists
|
- name: Check if template already exists
|
||||||
command: "qm status {{ vmid }}"
|
command: "qm status {{ vmid }}"
|
||||||
register: vm_status
|
register: vm_status
|
||||||
@@ -12,8 +24,8 @@
|
|||||||
|
|
||||||
- name: Download Cloud Image
|
- name: Download Cloud Image
|
||||||
get_url:
|
get_url:
|
||||||
url: "{{ image_url }}"
|
url: "{{ _image_url }}"
|
||||||
dest: "/tmp/{{ image_name }}"
|
dest: "/tmp/{{ _image_name }}"
|
||||||
mode: '0644'
|
mode: '0644'
|
||||||
|
|
||||||
- name: Install libguestfs-tools
|
- name: Install libguestfs-tools
|
||||||
@@ -34,7 +46,7 @@
|
|||||||
--serial0 socket --vga serial0
|
--serial0 socket --vga serial0
|
||||||
|
|
||||||
- name: Import Disk
|
- name: Import Disk
|
||||||
command: "qm importdisk {{ vmid }} /tmp/{{ image_name }} {{ storage_pool }}"
|
command: "qm importdisk {{ vmid }} /tmp/{{ _image_name }} {{ storage_pool }}"
|
||||||
|
|
||||||
- name: Attach Disk to SCSI
|
- name: Attach Disk to SCSI
|
||||||
command: "qm set {{ vmid }} --scsi0 {{ storage_pool }}:vm-{{ vmid }}-disk-0"
|
command: "qm set {{ vmid }} --scsi0 {{ storage_pool }}:vm-{{ vmid }}-disk-0"
|
||||||
@@ -45,6 +57,22 @@
|
|||||||
- name: Set Boot Order
|
- name: Set Boot Order
|
||||||
command: "qm set {{ vmid }} --boot c --bootdisk scsi0"
|
command: "qm set {{ vmid }} --boot c --bootdisk scsi0"
|
||||||
|
|
||||||
|
- name: Prepare SSH Keys File
|
||||||
|
copy:
|
||||||
|
content: |
|
||||||
|
{{ admin_ssh_key }}
|
||||||
|
{% for key in additional_ssh_keys %}
|
||||||
|
{{ key }}
|
||||||
|
{% endfor %}
|
||||||
|
dest: "/tmp/ssh_keys_{{ vmid }}.pub"
|
||||||
|
mode: '0600'
|
||||||
|
|
||||||
|
- name: Configure Cloud-Init (SSH Keys, User, IP)
|
||||||
|
command: >
|
||||||
|
qm set {{ vmid }}
|
||||||
|
--sshkeys /tmp/ssh_keys_{{ vmid }}.pub
|
||||||
|
--ipconfig0 ip=dhcp
|
||||||
|
|
||||||
- name: Resize Disk (Default 10G)
|
- name: Resize Disk (Default 10G)
|
||||||
command: "qm resize {{ vmid }} scsi0 10G"
|
command: "qm resize {{ vmid }} scsi0 10G"
|
||||||
ignore_errors: yes
|
ignore_errors: yes
|
||||||
@@ -54,5 +82,10 @@
|
|||||||
|
|
||||||
- name: Remove Downloaded Image
|
- name: Remove Downloaded Image
|
||||||
file:
|
file:
|
||||||
path: "/tmp/{{ image_name }}"
|
path: "/tmp/{{ _image_name }}"
|
||||||
|
state: absent
|
||||||
|
|
||||||
|
- name: Remove Temporary SSH Keys File
|
||||||
|
file:
|
||||||
|
path: "/tmp/ssh_keys_{{ vmid }}.pub"
|
||||||
state: absent
|
state: absent
|
||||||
|
|||||||
@@ -17,3 +17,7 @@ SEMAPHORE_EMAIL_PASSWORD=smtp_password
|
|||||||
SEMAPHORE_EMAIL_SECURE=false
|
SEMAPHORE_EMAIL_SECURE=false
|
||||||
|
|
||||||
|
|
||||||
|
AUTHENTIK_URL=https://authentik.example.com/application/o/<slug>/
|
||||||
|
AUTHENTIK_CLIENT_ID=your_client_id
|
||||||
|
AUTHENTIK_CLIENT_SECRET=your_client_secret
|
||||||
|
AUTHENTIK_REDIRECT_URI=https://semaphore.example.com/api/auth/oidc/authentik/redirect/
|
||||||
|
|||||||
@@ -34,6 +34,18 @@ services:
|
|||||||
SEMAPHORE_EMAIL_USERNAME: ${SEMAPHORE_EMAIL_USERNAME}
|
SEMAPHORE_EMAIL_USERNAME: ${SEMAPHORE_EMAIL_USERNAME}
|
||||||
SEMAPHORE_EMAIL_PASSWORD: ${SEMAPHORE_EMAIL_PASSWORD}
|
SEMAPHORE_EMAIL_PASSWORD: ${SEMAPHORE_EMAIL_PASSWORD}
|
||||||
SEMAPHORE_EMAIL_SECURE: ${SEMAPHORE_EMAIL_SECURE}
|
SEMAPHORE_EMAIL_SECURE: ${SEMAPHORE_EMAIL_SECURE}
|
||||||
|
SEMAPHORE_OIDC_PROVIDERS: '{
|
||||||
|
"authentik": {
|
||||||
|
"display_name": "Sign in with Authentik",
|
||||||
|
"provider_url": ${AUTHENTIK_URL},
|
||||||
|
"client_id": ${AUTHENTIK_CLIENT_ID},
|
||||||
|
"client_secret": ${AUTHENTIK_CLIENT_SECRET},
|
||||||
|
"redirect_uri": ${AUTHENTIK_REDIRECT_URI},
|
||||||
|
"scopes": ["openid", "profile", "email"],
|
||||||
|
"username_claim": "preferred_username",
|
||||||
|
"name_claim": "preferred_username"
|
||||||
|
}
|
||||||
|
}'
|
||||||
volumes:
|
volumes:
|
||||||
- semaphore_data:/var/lib/semaphore
|
- semaphore_data:/var/lib/semaphore
|
||||||
- semaphore_config:/etc/semaphore
|
- semaphore_config:/etc/semaphore
|
||||||
|
|||||||
Reference in New Issue
Block a user