Compare commits
18 Commits
main
..
130ad1dba5
| Author | SHA1 | Date | |
|---|---|---|---|
| 130ad1dba5 | |||
| 6649426ca7 | |||
| c7418ad40f | |||
| b3771097c2 | |||
| 2e1f8d4146 | |||
| 14e09c7ee7 | |||
| e59f07fb6d | |||
| 6bef8b28e5 | |||
| eb7fd456e4 | |||
| 5f4f84ea15 | |||
| 8f4fee8b63 | |||
| 1d3bc59a8b | |||
| 49bd2f630b | |||
| 07b33028d1 | |||
| cc68a1f863 | |||
| 4897cdadbd | |||
| e0571783ba | |||
| c633ead7cc |
@@ -1,97 +0,0 @@
|
||||
name: "Bug Report"
|
||||
description: "Report a bug or unexpected behavior to help us improve"
|
||||
title: "[BUG]: "
|
||||
labels: ["bug"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
## ⚠️ Before You Begin
|
||||
Please ensure you have:
|
||||
- [ ] Searched existing issues to avoid duplicates
|
||||
- [ ] Confirmed this is a bug, not a question or configuration problem
|
||||
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: "📋 Description"
|
||||
description: "Provide a clear and concise description of the bug"
|
||||
placeholder: "What happened? What did you expect to happen instead?"
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: reproduction
|
||||
attributes:
|
||||
label: "🔁 Steps to Reproduce"
|
||||
description: "Step-by-step instructions to reproduce the issue"
|
||||
placeholder: |
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: expected
|
||||
attributes:
|
||||
label: "✅ Expected Behavior"
|
||||
description: "What you expected to happen"
|
||||
placeholder: "A clear description of what should happen..."
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: actual
|
||||
attributes:
|
||||
label: "❌ Actual Behavior"
|
||||
description: "What actually happened"
|
||||
placeholder: "Include error messages, stack traces, or unexpected outcomes..."
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: logs
|
||||
attributes:
|
||||
label: "📄 Logs / Screenshots"
|
||||
description: |
|
||||
Provide relevant logs, error messages, or screenshots.
|
||||
For logs, please use a pastebin and share the URL.
|
||||
**Remember to remove any sensitive information (API keys, passwords, etc.).**
|
||||
placeholder: "Paste logs here or provide a Gist URL..."
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
---
|
||||
## 🖥️ Environment Details
|
||||
Please fill out the relevant information below.
|
||||
|
||||
- type: textarea
|
||||
id: additional
|
||||
attributes:
|
||||
label: "📎 Additional Context"
|
||||
description: "Any other information that might be relevant"
|
||||
placeholder: |
|
||||
- Database type and version (e.g., PostgreSQL 15, SQLite)
|
||||
- Reverse proxy/CDN in use (e.g., Nginx, Cloudflare)
|
||||
- Any custom configuration
|
||||
- Related issues or PRs
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: checkboxes
|
||||
id: checklist
|
||||
attributes:
|
||||
label: "✅ Submission Checklist"
|
||||
description: "Please confirm the following before submitting"
|
||||
options:
|
||||
- label: "I have searched for existing issues (open and closed) that report the same problem"
|
||||
required: true
|
||||
- label: "I have provided clear steps to reproduce the issue"
|
||||
required: true
|
||||
- label: "I have included relevant logs or error messages (with sensitive info removed)"
|
||||
required: false
|
||||
@@ -1,118 +0,0 @@
|
||||
name: "Feature Request"
|
||||
description: "Suggest a new feature or enhancement for this project"
|
||||
title: "[FEATURE]: "
|
||||
labels: ["enhancement"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
## ⚠️ Before You Begin
|
||||
Please ensure you have:
|
||||
- [ ] Searched existing issues (open and closed) to avoid duplicates
|
||||
- [ ] Reviewed the [project documentation](https://git.vmn.su/max/vmn-ansible/wiki) for existing functionality
|
||||
- [ ] Confirmed this is a feature request, not a bug or configuration question
|
||||
|
||||
|
||||
- type: textarea
|
||||
id: problem
|
||||
attributes:
|
||||
label: "🎯 Problem Statement"
|
||||
description: "What problem does this feature solve? What can't you do today?"
|
||||
placeholder: |
|
||||
I'm always frustrated when...
|
||||
Currently, it's hard/impossible to...
|
||||
This feature would help me because...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: solution
|
||||
attributes:
|
||||
label: "💡 Proposed Solution"
|
||||
description: "Describe the solution you'd like to see"
|
||||
placeholder: |
|
||||
A clear description of what you want to happen.
|
||||
If you have a specific API, UI, or implementation in mind, describe it here.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: alternatives
|
||||
attributes:
|
||||
label: "🔄 Alternatives Considered"
|
||||
description: "What alternative solutions or workarounds have you considered?"
|
||||
placeholder: |
|
||||
- Alternative A: ...
|
||||
- Workaround B: ...
|
||||
- Why these don't fully solve the problem
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
id: screenshots
|
||||
attributes:
|
||||
label: "📸 Screenshots"
|
||||
description: "If you can, provide screenshots or diagrams of the proposed feature"
|
||||
placeholder: "Drag and drop images or paste links..."
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
---
|
||||
## 🔧 Implementation Details (Optional)
|
||||
The following sections are for contributors who want to implement this feature.
|
||||
|
||||
- type: textarea
|
||||
id: technical
|
||||
attributes:
|
||||
label: "⚙️ Technical Approach"
|
||||
description: "If you have ideas about how to implement this, share them here"
|
||||
placeholder: |
|
||||
- Which components/modules would be affected?
|
||||
- Any database schema changes?
|
||||
- API design considerations?
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
id: acceptance
|
||||
attributes:
|
||||
label: "✅ Acceptance Criteria"
|
||||
description: "What does 'done' look like for this feature?"
|
||||
placeholder: |
|
||||
- [ ] Feature works in the UI
|
||||
- [ ] API endpoints are documented
|
||||
- [ ] Tests are added
|
||||
- [ ] Documentation is updated
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: dropdown
|
||||
id: contribution
|
||||
attributes:
|
||||
label: "🤝 Are you willing to contribute this feature?"
|
||||
description: "Knowing if you can help implement this helps us prioritize"
|
||||
options:
|
||||
- "Yes, I can contribute"
|
||||
- "Yes, but I need guidance"
|
||||
- "No, but I can test/review"
|
||||
- "No, I'm just requesting"
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: checkboxes
|
||||
id: checklist
|
||||
attributes:
|
||||
label: "✅ Submission Checklist"
|
||||
description: "Please confirm the following before submitting"
|
||||
options:
|
||||
- label: "I have searched for existing issues (open and closed) that request the same feature"
|
||||
required: true
|
||||
- label: "I have explained the problem this feature solves"
|
||||
required: true
|
||||
- label: "I have described a concrete solution or direction"
|
||||
required: true
|
||||
- label: "I have considered alternatives and explained why they fall short"
|
||||
required: false
|
||||
@@ -1,145 +0,0 @@
|
||||
name: "Refactor Request"
|
||||
description: "Propose a code restructuring or cleanup with no behavior change"
|
||||
title: "[REFACTOR]: "
|
||||
labels: ["refactoring"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
## ⚠️ Before You Begin
|
||||
Please ensure you have:
|
||||
- [ ] Searched existing issues (open and closed) to avoid duplicates
|
||||
- [ ] Reviewed the [project documentation](https://git.vmn.su/max/vmn-ansible/wiki) for architecture guidelines
|
||||
- [ ] Confirmed this is a refactor (code restructuring with NO behavior change), not a bug fix or new feature
|
||||
|
||||
|
||||
- type: textarea
|
||||
id: problem
|
||||
attributes:
|
||||
label: "🎯 Problem Statement"
|
||||
description: "What pain points does the current code cause? Why is this refactor needed?"
|
||||
placeholder: |
|
||||
The current implementation is difficult to maintain because...
|
||||
This code has accumulated technical debt due to...
|
||||
I'm constantly frustrated when working with this module because...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: scope
|
||||
attributes:
|
||||
label: "📂 Scope"
|
||||
description: "Which files, modules, or components need refactoring? Be specific."
|
||||
placeholder: |
|
||||
- File paths: `src/auth/`, `internal/handler/`
|
||||
- Component: `UserService` class
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: current-state
|
||||
attributes:
|
||||
label: "🔍 Current State"
|
||||
description: "Describe the current code structure, its issues, and why it's problematic"
|
||||
placeholder: |
|
||||
- The function `processUser()` is 500+ lines long
|
||||
- Duplicated logic across 3 different files
|
||||
- Mixed concerns (business logic + HTTP handling)
|
||||
- Poor test coverage makes changes risky
|
||||
- Naming is unclear and inconsistent
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: proposed-changes
|
||||
attributes:
|
||||
label: "💡 Proposed Solution"
|
||||
description: "What should the code look like after the refactor?"
|
||||
placeholder: |
|
||||
- Extract `processUser()` into smaller, focused functions
|
||||
- Consolidate duplicated logic into a shared utility
|
||||
- Separate business logic from HTTP handlers
|
||||
- Introduce interfaces for better testability
|
||||
- Rename variables and functions for clarity
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: constraints
|
||||
attributes:
|
||||
label: "🚫 Constraints"
|
||||
description: "What must NOT change? Public APIs, behavior, backward compatibility, performance characteristics?"
|
||||
placeholder: |
|
||||
- All public APIs must remain identical
|
||||
- Database schema must not change
|
||||
- External behavior must be identical
|
||||
- Response formats must stay the same
|
||||
- Performance must not degrade
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: benefits
|
||||
attributes:
|
||||
label: "📈 Expected Benefits"
|
||||
description: "What improvements will this refactor bring?"
|
||||
placeholder: |
|
||||
- Improved maintainability
|
||||
- Better testability
|
||||
- Reduced code duplication
|
||||
- Clearer separation of concerns
|
||||
- Easier onboarding for new contributors
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
id: risks
|
||||
attributes:
|
||||
label: "⚠️ Risks & Mitigations"
|
||||
description: "What could go wrong, and how will you mitigate it?"
|
||||
placeholder: |
|
||||
- Risk: Regression bugs
|
||||
Mitigation: Comprehensive test coverage before and after
|
||||
- Risk: Large diff making code review difficult
|
||||
Mitigation: Break into smaller, incremental PRs
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
id: alternatives
|
||||
attributes:
|
||||
label: "🔄 Alternatives Considered"
|
||||
description: "What other approaches did you consider, and why did you reject them?"
|
||||
placeholder: |
|
||||
- Alternative A: Complete rewrite — rejected because too risky
|
||||
- Alternative B: Gradual deprecation — rejected because too slow
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: dropdown
|
||||
id: contribution
|
||||
attributes:
|
||||
label: "🤝 Are you willing to contribute this refactor?"
|
||||
description: "Knowing if you can help implement this helps us prioritize"
|
||||
options:
|
||||
- "Yes, I can contribute"
|
||||
- "Yes, but I need guidance"
|
||||
- "No, but I can review"
|
||||
- "No, I'm just suggesting"
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: checkboxes
|
||||
id: checklist
|
||||
attributes:
|
||||
label: "✅ Submission Checklist"
|
||||
description: "Please confirm the following before submitting"
|
||||
options:
|
||||
- label: "I have searched for existing issues (open and closed) that request the same refactor"
|
||||
required: true
|
||||
- label: "I have clearly explained the problem this refactor solves"
|
||||
required: true
|
||||
- label: "I have described the scope of the refactor (specific files/modules)"
|
||||
required: false
|
||||
- label: "I have identified what must NOT change (APIs, behavior, backward compatibility)"
|
||||
required: false
|
||||
@@ -1,3 +1,20 @@
|
||||
# ansible_home
|
||||
|
||||
My own home services automation repository
|
||||
## How to use it?
|
||||
|
||||
It's better to use a virtual environment to avoid incompatibility issues
|
||||
|
||||
```bash
|
||||
git clone https://git.vmn.su/max/vmn-ansible
|
||||
cd vmn-ansible
|
||||
python3 -m venv .venv
|
||||
source .venv/bin/activate
|
||||
pip install -r requirements.txt
|
||||
ansible-galaxy collection install -r requirements.yaml
|
||||
ansible-galaxy role install -r requirements.yaml
|
||||
ansible-playbook playbooks/deploy_and_set_up_lxc_on_proxmox.yaml --vault-pass-file $VAULT_PASS_PATH -i inventory/localhost.yaml --private-key $SSH_KEY
|
||||
```
|
||||
|
||||
**deploy** playbooks must be used with `inventory/localhost.yaml`, they need access to proxmox host only
|
||||
|
||||
There are also a systemd service and timer under `systemd` directory
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
---
|
||||
all:
|
||||
children:
|
||||
this_host:
|
||||
hosts:
|
||||
localhost:
|
||||
ansible_become_password: "{{ ansible_become_passwd }}"
|
||||
ansible_connection: local
|
||||
ansible_python_interpreter: "{{ ansible_playbook_python }}"
|
||||
physical:
|
||||
hosts:
|
||||
proxmox_1:
|
||||
ansible_host: "{{ proxmox_1_host }}"
|
||||
ansible_become_password: "{{ ansible_become_passwd }}"
|
||||
@@ -39,3 +46,11 @@ all:
|
||||
ansible_become_password: "{{ ansible_become_passwd }}"
|
||||
services_to_run:
|
||||
- coder_ai
|
||||
web-servers:
|
||||
hosts:
|
||||
cert-proxy:
|
||||
ansible_host: 192.168.0.47
|
||||
ansible_become_password: "{{ ansible_become_passwd }}"
|
||||
monitoring:
|
||||
ansible_host: 192.168.0.49
|
||||
ansible_become_password: "{{ ansible_become_passwd }}"
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
---
|
||||
physical:
|
||||
hosts:
|
||||
localhost:
|
||||
ansible_become_password: "{{ ansible_become_passwd }}"
|
||||
ansible_connection: local
|
||||
ansible_python_interpreter: "{{ ansible_playbook_python }}"
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
- name: Deploy LXC
|
||||
hosts: all
|
||||
hosts: localhost
|
||||
remote_user: ansible
|
||||
gather_facts: false
|
||||
|
||||
@@ -13,20 +13,29 @@
|
||||
vars_prompt:
|
||||
- name: lxc_hostname
|
||||
prompt: "Hostname for the container (may only contain letters (a-z, A-Z), numbers (0-9), and hyphens)"
|
||||
default: "new-lxc-test"
|
||||
private: false
|
||||
|
||||
- name: lxc_root_password
|
||||
prompt: "Root password"
|
||||
default: "new-lxc-test"
|
||||
private: true
|
||||
confirm: true
|
||||
encrypt: sha512_crypt
|
||||
|
||||
- name: lxc_ip_address
|
||||
prompt: "IP address for the container (in x.x.x.x/x formant)"
|
||||
default: "192.168.0.90/24"
|
||||
private: false
|
||||
|
||||
- name: lxc_is_privileged
|
||||
prompt: "Unprivileged LXC (true/false)?"
|
||||
default: true
|
||||
private: false
|
||||
|
||||
- name: lxc_create_human_admin_user
|
||||
prompt: "Create human admin user? (true/false)?"
|
||||
default: true
|
||||
private: false
|
||||
|
||||
pre_tasks:
|
||||
@@ -38,6 +47,14 @@
|
||||
when: not lxc_hostname is regex('^[a-zA-Z0-9-]+$')
|
||||
run_once: true
|
||||
|
||||
- name: Validate IP address
|
||||
ansible.builtin.fail:
|
||||
msg: |
|
||||
Invalid IP address: "{{ lxc_ip_address }}"
|
||||
IP address must be in x.x.x.x/x format (e.g., 192.168.0.90/24).
|
||||
when: not lxc_ip_address is regex('^((25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.){3}(25[0-5]|2[0-4]\\d|[01]?\\d\\d?)(\\/(3[0-2]|[12]?\\d))?$')
|
||||
run_once: true
|
||||
|
||||
roles:
|
||||
- ../roles/deploy_lxc_on_proxmox
|
||||
|
||||
@@ -48,9 +65,12 @@
|
||||
|
||||
- name: Make the prompted IP available to the whole playbook
|
||||
ansible.builtin.set_fact:
|
||||
#fact_lxc_ip_address: "{{ lxc_ip_address | ansible.utils.ipaddr('address') }}"
|
||||
fact_lxc_ip_address: "{{ lxc_ip_address.split('/') | first }}"
|
||||
|
||||
- name: Make the "human admin user" selection available to the whole playbook
|
||||
ansible.builtin.set_fact:
|
||||
fact_lxc_create_human_admin_user: "{{ lxc_create_human_admin_user }}"
|
||||
|
||||
- name: Add the target host to the inventory
|
||||
ansible.builtin.add_host:
|
||||
name: "{{ fact_lxc_ip_address }}"
|
||||
@@ -73,7 +93,15 @@
|
||||
- ../roles/configure_ansible_user
|
||||
- ../roles/harden_ssh
|
||||
- ../roles/base_system
|
||||
- ../roles/human_admin_user
|
||||
# Update configs - omz, nvim, ranger and so on. Distribute the last version of those configs
|
||||
- ../roles/update_configs
|
||||
|
||||
tasks:
|
||||
- name: Include human admin user role
|
||||
ansible.builtin.include_role:
|
||||
name: ../roles/human_admin_user
|
||||
when: "hostvars['localhost']['fact_lxc_create_human_admin_user'] | bool"
|
||||
|
||||
- name: Include update configs role
|
||||
ansible.builtin.include_role:
|
||||
name: ../roles/update_configs
|
||||
when: "hostvars['localhost']['fact_lxc_create_human_admin_user'] | bool"
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
- name: Deploy VM
|
||||
hosts: all
|
||||
hosts: localhost
|
||||
remote_user: ansible
|
||||
gather_facts: false
|
||||
|
||||
@@ -13,10 +13,27 @@
|
||||
vars_prompt:
|
||||
- name: vm_hostname
|
||||
prompt: "Hostname for the VM (may only contain letters (a-z, A-Z), numbers (0-9), and hyphens)"
|
||||
default: "new-vm-test"
|
||||
private: false
|
||||
|
||||
- name: vm_os_template
|
||||
prompt: "Select OS template. Available: debian-13 | alpine"
|
||||
default: "debian-13"
|
||||
private: false
|
||||
|
||||
- name: vm_become_method
|
||||
prompt: "Select become method. Available: sudo | su | pbrun | pfexec | doas | dzdo | ksu | runas | machinectl"
|
||||
default: "sudo"
|
||||
private: false
|
||||
|
||||
- name: vm_create_human_admin_user
|
||||
prompt: "Create human admin user? (true/false)?"
|
||||
default: true
|
||||
private: false
|
||||
|
||||
- name: vm_ip_address
|
||||
prompt: "IP address for the VM (in x.x.x.x/x formant)"
|
||||
default: "192.168.0.89/24"
|
||||
private: false
|
||||
|
||||
pre_tasks:
|
||||
@@ -28,24 +45,57 @@
|
||||
when: not vm_hostname is regex('^[a-zA-Z0-9-]+$')
|
||||
run_once: true
|
||||
|
||||
- name: Validate IP address
|
||||
ansible.builtin.fail:
|
||||
msg: |
|
||||
Invalid IP address: "{{ vm_ip_address }}"
|
||||
IP address must be in x.x.x.x/x format (e.g., 192.168.0.89/24).
|
||||
when: not vm_ip_address is regex('^((25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.){3}(25[0-5]|2[0-4]\\d|[01]?\\d\\d?)(\\/(3[0-2]|[12]?\\d))?$')
|
||||
run_once: true
|
||||
|
||||
- name: Validate OS template
|
||||
ansible.builtin.fail:
|
||||
msg: |
|
||||
Invalid OS template: "{{ vm_os_template }}"
|
||||
Select from available options: debian-13, alpine
|
||||
when: vm_os_template not in ['debian-13', 'alpine']
|
||||
run_once: true
|
||||
|
||||
- name: Validate become method
|
||||
ansible.builtin.fail:
|
||||
msg: |
|
||||
Invalid become method: "{{ vm_become_method }}"
|
||||
Select from available options: sudo | su | pbrun | pfexec | doas | dzdo | ksu | runas | machinectl
|
||||
when: vm_become_method not in ['sudo', 'su', 'pbrun', 'pfexec', 'doas', 'dzdo', 'ksu', 'runas', 'machinectl']
|
||||
run_once: true
|
||||
|
||||
roles:
|
||||
- ../roles/deploy_vm_on_proxmox
|
||||
|
||||
tasks:
|
||||
- name: Make the prompted hostname available to the whole playbook
|
||||
- name: Make the hostname available to the whole playbook
|
||||
ansible.builtin.set_fact:
|
||||
fact_vm_hostname: "{{ vm_hostname }}"
|
||||
|
||||
- name: Make the prompted IP available to the whole playbook
|
||||
- name: Make the OS template available to the whole playbook
|
||||
ansible.builtin.set_fact:
|
||||
fact_vm_os_template: "{{ vm_os_template }}"
|
||||
|
||||
- name: Make the IP available to the whole playbook
|
||||
ansible.builtin.set_fact:
|
||||
fact_vm_ip_address: "{{ vm_ip_address.split('/') | first }}"
|
||||
|
||||
- name: Make the "human admin user" selection available to the whole playbook
|
||||
ansible.builtin.set_fact:
|
||||
fact_vm_create_human_admin_user: "{{ vm_create_human_admin_user }}"
|
||||
|
||||
- name: Add the target host to the inventory
|
||||
ansible.builtin.add_host:
|
||||
name: "{{ fact_vm_ip_address }}"
|
||||
groups: new_host
|
||||
ansible_user: ansible
|
||||
ansible_become_password: "{{ ansible_become_passwd }}"
|
||||
ansible_become_method: "{{ vm_become_method }}"
|
||||
|
||||
|
||||
- name: Configure VM
|
||||
@@ -62,7 +112,15 @@
|
||||
- ../roles/configure_ansible_user
|
||||
- ../roles/harden_ssh
|
||||
- ../roles/base_system
|
||||
- ../roles/human_admin_user
|
||||
# Update configs - omz, nvim, ranger and so on. Distribute the last version of those configs
|
||||
- ../roles/update_configs
|
||||
|
||||
tasks:
|
||||
- name: Include human admin user role
|
||||
ansible.builtin.include_role:
|
||||
name: ../roles/human_admin_user
|
||||
when: "hostvars['localhost']['fact_vm_create_human_admin_user'] | bool"
|
||||
|
||||
- name: Include update configs role
|
||||
ansible.builtin.include_role:
|
||||
name: ../roles/update_configs
|
||||
when: "hostvars['localhost']['fact_vm_create_human_admin_user'] | bool"
|
||||
|
||||
|
||||
+12
-1
@@ -1,5 +1,5 @@
|
||||
---
|
||||
- name: Deploy and set up an LXC container in Proxmox
|
||||
- name: Perform regular maintenance
|
||||
hosts: virtual
|
||||
remote_user: ansible
|
||||
|
||||
@@ -20,3 +20,14 @@
|
||||
- ../roles/update_configs
|
||||
# Make sure that the services that are supposed to run are running
|
||||
- ../roles/check_services
|
||||
|
||||
- name: Ensure all web-servers have fresh TLS certificates
|
||||
hosts: web-servers
|
||||
remote_user: ansible
|
||||
|
||||
vars_files:
|
||||
../inventory/group_vars/all/secrets.yaml
|
||||
|
||||
roles:
|
||||
# Pull certificates from cert_proxy and distribute them among the servers
|
||||
- ../roles/update_certificates
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
become: true
|
||||
remote_user: ansible
|
||||
|
||||
- name: Install qemu-guest-agent on VM
|
||||
- name: Install qemu-guest-agent on VM with apt-based systems
|
||||
when:
|
||||
- ansible_facts['os_family'] == "Debian"
|
||||
- ansible_facts['virtualization_type'] == "kvm"
|
||||
@@ -29,3 +29,24 @@
|
||||
name: "{{ alpine_packages }}"
|
||||
update_cache: true
|
||||
remote_user: ansible
|
||||
|
||||
- name: Install qemu-guest-agent on VM with Alpine
|
||||
when:
|
||||
- ansible_facts['distribution'] == "Alpine"
|
||||
- ansible_facts['virtualization_type'] == "kvm"
|
||||
community.general.apk:
|
||||
name: qemu-guest-agent
|
||||
update_cache: true
|
||||
become: true
|
||||
remote_user: ansible
|
||||
tags:
|
||||
- kvm-guests
|
||||
- packages
|
||||
|
||||
|
||||
- name: Enable qemu-guest-agent
|
||||
ansible.builtin.service:
|
||||
name: qemu-guest-agent
|
||||
enabled: yes
|
||||
state: started
|
||||
|
||||
|
||||
@@ -1,19 +1,63 @@
|
||||
---
|
||||
- name: Generate locales
|
||||
- name: Generate locales for Debian-based systems
|
||||
community.general.locale_gen:
|
||||
name:
|
||||
- en_US.UTF-8
|
||||
- ru_RU.UTF-8
|
||||
state: present
|
||||
when: (ansible_facts['distribution'] == "Debian") or
|
||||
(ansible_facts['distribution'] == "Ubuntu")
|
||||
|
||||
- name: Set locale
|
||||
- name: Set locale for Debian-based systems
|
||||
ansible.builtin.copy:
|
||||
dest: /etc/locale.conf
|
||||
mode: '0644'
|
||||
content: |
|
||||
LANG=en_US.UTF-8
|
||||
LC_ALL=en_US.UTF-8
|
||||
when: (ansible_facts['distribution'] == "Debian") or
|
||||
(ansible_facts['distribution'] == "Ubuntu")
|
||||
|
||||
# The same for Alpine
|
||||
- name: Install musl-locales package for Alpine
|
||||
community.general.apk:
|
||||
name: musl-locales
|
||||
state: present
|
||||
when: ansible_facts['distribution'] == "Alpine"
|
||||
|
||||
- name: Copy default locale profile to a custom override file for Alpine
|
||||
ansible.builtin.copy:
|
||||
src: /etc/profile.d/20locale.sh
|
||||
dest: /etc/profile.d/locale.sh
|
||||
remote_src: true
|
||||
mode: '0644'
|
||||
owner: root
|
||||
group: root
|
||||
force: false # Do not overwrite if the file already exists
|
||||
when: ansible_facts['distribution'] == "Alpine"
|
||||
|
||||
- name: Set LANG and LC_ALL in the custom locale file for Alpine
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/profile.d/locale.sh
|
||||
regexp: "{{ item.regexp }}"
|
||||
line: "{{ item.line }}"
|
||||
state: present
|
||||
loop:
|
||||
- { regexp: '^export LANG=', line: 'export LANG=en_US.UTF-8' }
|
||||
- { regexp: '^export LC_ALL=', line: 'export LC_ALL=en_US.UTF-8' }
|
||||
when: ansible_facts['distribution'] == "Alpine"
|
||||
|
||||
- name: Ensure Unicode is enabled in /etc/rc.conf for Alpine
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/rc.conf
|
||||
regexp: '^#?unicode='
|
||||
line: 'unicode="YES"'
|
||||
state: present
|
||||
when: ansible_facts['distribution'] == "Alpine"
|
||||
|
||||
|
||||
# Works fine for all
|
||||
- name: Set time
|
||||
community.general.timezone:
|
||||
name: Europe/Samara
|
||||
|
||||
|
||||
@@ -6,8 +6,9 @@ alpine_packages:
|
||||
- git
|
||||
- kitty
|
||||
- neovim
|
||||
- openssh
|
||||
- openssh-server
|
||||
- ranger
|
||||
- rsync
|
||||
- ssh
|
||||
- tzdata
|
||||
- zsh
|
||||
|
||||
@@ -8,6 +8,18 @@
|
||||
- sudo
|
||||
update-cache: true
|
||||
|
||||
- name: Ensure /etc/resolv.conf exists with DNS servers
|
||||
when: (ansible_facts['distribution'] == "Alpine")
|
||||
ansible.builtin.copy:
|
||||
dest: /etc/resolv.conf
|
||||
content: |
|
||||
nameserver 192.168.0.1
|
||||
nameserver 8.8.8.8
|
||||
mode: '0644'
|
||||
owner: root
|
||||
group: root
|
||||
become: true
|
||||
|
||||
# The same commands for Alpine
|
||||
- name: Update and install packages on Alpine
|
||||
when: (ansible_facts['distribution'] == "Alpine")
|
||||
@@ -24,6 +36,12 @@
|
||||
name: sshusers
|
||||
state: present
|
||||
|
||||
- name: Ensure group "sudo" exists
|
||||
ansible.builtin.group:
|
||||
name: sudo
|
||||
state: present
|
||||
|
||||
|
||||
## Add the user to sshusers (for ssh access) and sudo (gain root access)
|
||||
- name: Create a new user with a password for Ansible
|
||||
ansible.builtin.user:
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
api_token_id: ansible
|
||||
api_token_secret: "{{ proxmox_token_secret }}"
|
||||
|
||||
clone: debian-13-cloud-init-template
|
||||
clone: "{{ vm_os_template }}-cloud-init-template"
|
||||
name: "{{ vm_hostname }}"
|
||||
storage: main
|
||||
format: qcow2
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
# PUT NEW BLOCKS STRICTLY BEFORE ANY MATCH BLOCK
|
||||
|
||||
|
||||
# Private keys are NOT distributed via Ansible
|
||||
# They must to be copied manually ONLY to those hosts that need access to others
|
||||
|
||||
# Most of the home major LAN hosts should be accessible with this key
|
||||
Match Host 192.168.0.?
|
||||
User max
|
||||
IdentityFile ~/.ssh/max_regular_key
|
||||
|
||||
# This virtual network has the same hosts range
|
||||
Match Host 10.9.2.?
|
||||
User max
|
||||
IdentityFile ~/.ssh/max_regular_key
|
||||
@@ -48,6 +48,15 @@
|
||||
group: "{{ human_admin_user }}"
|
||||
mode: u=rw,g=r,o-rwx
|
||||
|
||||
- name: Configure ssh client, by pushing the config
|
||||
remote_user: ansible
|
||||
ansible.builtin.copy:
|
||||
src: "{{ role_path }}/files/ssh_config"
|
||||
dest: "/home/{{ human_admin_user }}/.ssh/config"
|
||||
owner: "{{ human_admin_user }}"
|
||||
group: "{{ human_admin_user }}"
|
||||
mode: u=rw,g=r,o-rwx
|
||||
|
||||
|
||||
# WARNING: we've finished with the initial setup, drop ansible key
|
||||
# Push regular user key
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
---
|
||||
- name: Pull directory from remote host to control node
|
||||
ansible.posix.synchronize:
|
||||
mode: pull
|
||||
src: /tmp/letsencrypt
|
||||
dest: /tmp
|
||||
recursive: true
|
||||
delete: true
|
||||
when: "inventory_hostname == 'cert-proxy'"
|
||||
|
||||
- name: Push loki.vmn.su certificate to the target
|
||||
ansible.builtin.copy:
|
||||
src: /tmp/letsencrypt/live/loki.vmn.su/fullchain.pem
|
||||
dest: /etc/nginx/certs/loki_fullchain.pem
|
||||
local_follow: true
|
||||
when: "inventory_hostname == 'monitoring'"
|
||||
|
||||
- name: Push loki.vmn.su key to the target
|
||||
ansible.builtin.copy:
|
||||
src: /tmp/letsencrypt/live/loki.vmn.su/privkey.pem
|
||||
dest: /etc/nginx/certs/loki_privkey.pem
|
||||
local_follow: true
|
||||
when: "inventory_hostname == 'monitoring'"
|
||||
Reference in New Issue
Block a user