Initial commit

This commit is contained in:
2026-02-07 07:22:24 +01:00
commit 8c9ad60602
21 changed files with 869 additions and 0 deletions

31
.ansible-lint Normal file
View File

@@ -0,0 +1,31 @@
---
# .ansible-lint
exclude_paths:
- .gitea
# Ansible-lint does not automatically load rules that have the 'opt-in' tag.
# You must enable opt-in rules by listing each rule 'id' below.
enable_list:
- args
- empty-string-compare # opt-in
- no-log-password # opt-in
- no-same-owner # opt-in
- name[prefix] # opt-in
- galaxy-version-incorrect # opt-in
# add yaml here if you want to avoid ignoring yaml checks when yamllint
# library is missing. Normally its absence just skips using that rule.
- yaml
# List of additional kind:pattern to be added at the top of the default
# match list, first match determines the file kind.
kinds:
- playbook: "**/playbooks/*.{yml,yaml}"
- roles: "**/roles/*.{yml,yaml}"
# - galaxy: "**/folder/galaxy.yml"
- tasks: "**/tasks/*.yml"
- vars: "**/vars/*.yml"
- meta: "**/meta/main.yml"
- yaml: "**/*.yaml-too"

View File

@@ -0,0 +1,3 @@
{
"MD041": false
}

127
.continue/rules/ansible.md Normal file
View File

@@ -0,0 +1,127 @@
---
name: Ansible Best Practices
description: Ansible best practices and conventions
alwaysApply: false
globs:
- "**/*.yml"
- "**/*.yaml"
---
You are an expert Ansible automation engineer.
When working with Ansible content, always follow these rules:
## General
- Prefer **idempotent** solutions; tasks must be safe to run multiple times.
- Use **Ansible built-in modules** instead of shell or command whenever possible.
- Do not assume root access; use `become: true` only when required.
- Avoid hard-coded values; prefer variables, defaults, and group/host vars.
- Use clear, descriptive task names.
- Ensure all YAML is valid, properly indented, and ansible-lint compliant.
- Favor clarity and maintainability over cleverness.
- Add README files to complex directories.
- Document complex algorithms and business rules.
- Maintain up-to-date dependencies list.
## Security Hardening
- **Never embed secrets** directly in playbooks, roles, or templates.
- Use **Ansible Vault**, external secret managers, or injected variables for secrets.
- Mark sensitive tasks with:
```yaml
no_log: true
```
- Avoid leaking secrets via debug, register, or error messages.
- Use least privilege:
- Avoid running entire plays as root.
- Scope become to individual tasks where possible.
- Set secure file permissions explicitly:
```yaml
mode: "0640"
owner: root
group: root
```
- Validate downloaded files using checksums.
- Avoid ignore_errors for security-sensitive operations.
- Do not disable SSL/TLS validation unless explicitly required and documented.
- Prefer validate_certs: true for network modules.
- Assume hosts may be compromised—do not trust remote state blindly.
## Playbooks
- Use `hosts`, `gather_facts`, and `become` explicitly.
- Keep playbooks minimal; delegate logic to roles.
- Apply tags consistently for safe partial execution.
- Use serial for rolling updates to reduce blast radius.
- Avoid large monolithic plays.
## Roles
- Follow the standard role structure:
(`tasks/`, `handlers/`, `defaults/`, `vars/`, `templates/`, `files/`).
- Put overridable values in `defaults/main.yml`.
- Put non-overridable or internal values in `vars/main.yml`.
- Namespace all role variables (role_name_variable).
- Use meta/main.yml to define role dependencies.
- Use handlers only when a change requires a follow-up action.
## Tasks
- Always name tasks clearly and descriptively.
- Use `state: present/absent/latest` explicitly.
- Register variables only when they are actually used.
- Use `changed_when` and `failed_when` to ensure correct task status.
- Avoid `ignore_errors` unless absolutely necessary.
- Avoid shell unless absolutely unavoidable; document why if used.
- Prefer creates and removes when using command-like tasks.
- Avoid unnecessary loops; simplify logic where possible.
## Variables & Templates
- Use snake_case for variable names.
- Quote variables in YAML to prevent parsing issues.
- Namespace role variables (e.g., `nginx_port`, not `port`).
- Avoid complex logic in templates—use when instead.
- Use Jinja2 filters safely and defensively (default, bool, int).
- Do not reference undefined variables without defaults.
## Conditionals & Loops
- Use when for conditionals.
- Prefer `loop` over deprecated `with_*`.
- Use `ansible_facts` instead of shell commands for system data.
- Avoid deeply nested conditionals.
## Error Handling & Validation
- Fail fast on critical errors.
- Use assert to validate assumptions.
- Use check_mode compatibility whenever possible.
- Ensure tasks behave correctly in --diff and --check.
## Linting & Compatibility
- Code must comply with ansible-lint.
- Write code compatible with recent Ansible versions.
- Avoid deprecated modules and syntax.
- Do not rely on undefined behavior or undocumented features.
## Performance & Reliability (Tips & Tricks)
- Use gather_facts: false if facts are not needed.
- Use run_once and delegate_to when appropriate.
- Cache facts when operating at scale.
- Avoid repeated expensive operations.
- Prefer block for grouping related tasks and error handling.
## Output Expectations
- Generated YAML must be valid and properly indented.
- Provide minimal but sufficient comments when clarity is needed.
- Do not include explanations unless explicitly requested.
- Assume production usage and security-sensitive environments.

View File

@@ -0,0 +1,159 @@
---
name: Project README Standards
globs: "**/README.md"
alwaysApply: false
description: Guidelines for creating comprehensive project README files
tags:
- readme
- documentation
- markdown
- project-setup
- best-practices
---
You are an expert in:
- technical documentation
- open source best practices
- developer experience.
## README Structure
A well-structured README should include these sections in order:
1. Project Title and Description
2. Badges (build status, version, license)
3. Key Features
4. Screenshots/Demo (if applicable)
5. Quick Start
6. Installation
7. Usage Examples
8. API Reference (or link to docs)
9. Configuration
10. Contributing
11. License
## Essential Sections
### Project Header
```markdown
# Project Name
> One-line description of what this project does
[![Build Status](https://img.shields.io/github/actions/workflow/status/user/repo/ci.yml)](https://github.com/user/repo/actions)
[![npm version](https://img.shields.io/npm/v/package-name)](https://www.npmjs.com/package/package-name)
[![License](https://img.shields.io/github/license/user/repo)](LICENSE)
Brief paragraph explaining the project's purpose, main features,
and why someone would want to use it.
```
### Quick Start
```markdown
## Quick Start
Get up and running in less than 5 minutes:
\`\`\`bash
npm install package-name
npm run dev
\`\`\`
Visit http://localhost:3000 to see the application.
```
### Installation
```markdown
## Installation
### Prerequisites
- Node.js 18+
- PostgreSQL 14+
- Redis 6.2+
### Install from npm
\`\`\`bash
npm install package-name
\`\`\`
### Install from source
\`\`\`bash
git clone https://github.com/user/repo.git
cd repo
npm install
npm run build
\`\`\`
```
### Usage Examples
```markdown
## Usage
### Basic Example
\`\`\`javascript
import { Widget } from 'package-name';
const widget = new Widget({
apiKey: 'your-api-key',
theme: 'dark'
});
widget.render('#app');
\`\`\`
### Advanced Example
\`\`\`javascript
// Custom configuration with error handling
const widget = new Widget({
apiKey: process.env.API_KEY,
theme: 'dark',
onError: (error) => {
console.error('Widget error:', error);
}
});
// Add custom event handlers
widget.on('ready', () => {
console.log('Widget is ready');
});
widget.render('#app');
\`\`\`
```
## Best Practices
- Keep the README focused and concise
- Use clear, simple language
- Include code examples that actually work
- Add visuals when they help understanding
- Link to more detailed documentation
- Keep examples up-to-date with the code
- Test your installation instructions regularly
## Common Mistakes to Avoid
- Don't assume reader knowledge
- Don't skip the Quick Start section
- Don't use jargon without explanation
- Don't forget to update version numbers
- Don't include sensitive information
## Formatting Tips
- Use consistent heading levels
- Include a table of contents for long READMEs
- Use code blocks with language highlighting
- Add alt text to images
- Use tables for comparing options
- Include emoji sparingly and purposefully

View File

@@ -0,0 +1,42 @@
---
# https://github.com/kekxv/AiReviewPR
name: ai-reviews
on:
pull_request:
types: [opened, synchronize]
jobs:
review:
name: Review PR
runs-on: ubuntu-latest
steps:
- name: Check OLLAMA host
run: |
curl -v ${{ 'http://192.168.2.233:11435' || vars.OLLAMA_HOST }} || exit 1
- name: Checkout code
uses: actions/checkout@v6
with:
# Number of commits to fetch. 0 indicates all history for all
# branches and tags.
# Default: 1
fetch-depth: 0
# The base URL for the GitHub instance that you are trying to clone
# from, will use environment defaults to fetch from the same instance
# that the workflow is running from unless specified.
# Example URLs are https://github.com or
# https://my-ghes-server.example.com
github-server-url: ${{ vars.GIT_SERVER_URL }}
- name: Review code
uses: kekxv/AiReviewPR@v0.1.2
with:
model: ${{ vars.OLLAMA_MODEL }}
host: ${{ 'http://192.168.2.233:11435' || vars.OLLAMA_HOST }}
# host: ${{ vars.OLLAMA_HOST }}
# ai_token: ${{ secrets.AI_TOKEN }}
REVIEW_PULL_REQUEST: true
LANGUAGE: English

View File

@@ -0,0 +1,34 @@
---
# .gitea/workflows/ansible-lint.yml
name: ansible-lint
on: [pull_request, issues, push]
jobs:
build:
name: Ansible Lint
# Naming the build is important to use it as a status check
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v6
with:
github-server-url: ${{ vars.GIT_SERVER_URL }}
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.14"
- name: Install ansible-lint
run: |
python -m pip install --upgrade pip
pip install ansible ansible-lint yamllint
- name: Run yamllint
run: |
yamllint .
- name: Run ansible-lint
run: |
ansible-lint

View File

@@ -0,0 +1,35 @@
---
name: Gitleaks Scan
on:
push:
pull_request:
jobs:
gitleaks:
runs-on: ubuntu-latest
steps:
- name: Install Gitleaks
run: |
curl -sSL https://github.com/gitleaks/gitleaks/releases/download/v8.30.0/gitleaks_8.30.0_linux_x64.tar.gz \
| tar -xz
sudo mv gitleaks /usr/local/bin/
- name: Checkout code
uses: actions/checkout@v6
with:
github-server-url: ${{ vars.GIT_SERVER_URL }}
- name: Run Gitleaks
run: |
gitleaks dir . \
--redact=10 \
--verbose \
--exit-code 1
# gitleaks detect \
# --source . \
# --no-git \
# --redact=20 \
# --verbose \
# --exit-code 1

View File

@@ -0,0 +1,24 @@
---
# .gitea/workflows/markdown-lint.yml
name: Markdown Lint
on: [pull_request, issues, push]
jobs:
build:
name: markdown-lint
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v6
with:
github-server-url: ${{ vars.GIT_SERVER_URL }}
- name: Install Node.js
uses: actions/setup-node@v4
with:
node-version: 20
- name: Run markdownlint
run: npx markdownlint-cli2 "**/*.md" "#node_modules"

View File

@@ -0,0 +1,72 @@
---
# This workflow warns and then closes issues and PRs that have
# had no activity for a specified amount of time.
#
# You can adjust the behavior by modifying this file.
# For more information, see:
# https://github.com/actions/stale
name: Mark stale issues and pull requests
on:
schedule:
- cron: '21 3 * * *'
jobs:
stale:
runs-on: ubuntu-latest
permissions:
issues: write # for actions/stale to close stale issues
pull-requests: write # for actions/stale to close stale PRs
steps:
# - name: Checkout code
# uses: actions/checkout@v4
# with:
# # Number of commits to fetch. 0 indicates all history for all branches
# # and tags.
# # Default: 1
# fetch-depth: 0
# # The base URL for the GitHub instance that you are trying to clone from,
# # will use environment defaults to fetch from the same instance that the
# # workflow is running from unless specified.
# # Example URLs are https://github.com or
# # https://my-ghes-server.example.com
# github-server-url: ${{ vars.GIT_SERVER_URL }}
# The 90 day stale policy
# Used for:
# - Issues & PRs
# - No PRs marked as no-stale or pinned
# - No issues marked as no-stale, help-wanted or pinned
- name: 90 days stale issues & PRs policy
uses: actions/stale@v9.1.0
with:
# repo-token: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
token: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
days-before-stale: 90
days-before-close: 7
operations-per-run: 150
remove-stale-when-updated: true
stale-issue-label: "stale"
exempt-issue-labels: "no-stale,help-wanted,pinned,enhancement"
stale-issue-message: >
There hasn't been any activity on this issue recently. To keep our
backlog manageable we have to clean old issues, as many of them have
already been resolved with the latest updates.
Please make sure to update to the latest version and check if that
solves the issue. Let us know if that works for you by adding a
comment 👍
This issue has now been marked as stale and will be closed if no
further activity occurs. Thank you for your contributions.
stale-pr-label: "stale"
exempt-pr-labels: "no-stale,pinned"
stale-pr-message: >
There hasn't been any activity on this pull request recently. This
pull request has been automatically marked as stale because of that
and will be closed if no further activity occurs within 7 days.
Thank you for your contributions.

39
.gitignore vendored Normal file
View File

@@ -0,0 +1,39 @@
---
# Ansible specific (optional - ignore temporary output or secrets)
*.retry
*.vault
*.vault_pass
*.secret
*.log
# VSCode settings
.vscode/
*.code-workspace
.trunk/
# Windows system files
Thumbs.db
ehthumbs.db
Desktop.ini
$RECYCLE.BIN/
*.lnk
# Backup files
*~
*.bak
*.swp
*.swo
*.tmp
# Python
__pycache__/
*.py[cod]
*$py.class
# Environment files
.env
.env.local
.env.development.local
.env.test
.env.production
.env.production.local

2
.markdownlintignore Normal file
View File

@@ -0,0 +1,2 @@
# ignore files completely
.continue/rules/**/*.md

23
.yamllint Normal file
View File

@@ -0,0 +1,23 @@
---
# This is my first, very own configuration file for yamllint!
# It extends the default conf by adjusting some options.
extends: default
rules:
comments-indentation: disable # don't bother me with this rule
truthy:
allowed-values: ['true', 'false', 'yes', 'no', 'on', 'off']
comments:
min-spaces-from-content: 1
braces:
max-spaces-inside: 1
octal-values:
forbid-implicit-octal: true
forbid-explicit-octal: true
line-length:
max: 120
allow-non-breakable-words: true

21
LICENSE Normal file
View File

@@ -0,0 +1,21 @@
# The MIT License (MIT)
Copyright © 2026 joseraj
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the “Software”), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

88
README.md Normal file
View File

@@ -0,0 +1,88 @@
# ansible-role-template
> A reusable Ansible role template for deploying and managing
> applications/services with security best practices.
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Ansible Version](https://img.shields.io/badge/Ansible-2.12+-blue)](https://www.ansible.com/)
[![Platforms](https://img.shields.io/badge/Platforms-Debian-blue)](https://www.debian.org/)
## 📌 Key Features
**Idempotent** - Safe to run multiple times
**Security Hardened** - Follows Ansible security best practices
**Modular** - Clear separation of concerns
**Documented** - Comprehensive README and variable documentation
**Tested** - Includes example playbook for validation
## 📂 Directory Structure
```text
ansible-role-template/
├── README.md # This file
├── defaults/ # Default role variables
│ └── main.yml
├── handlers/ # Role handlers
│ └── main.yml
├── files/ # Static files to deploy
├── meta/ # Role metadata
│ └── main.yml
├── tasks/ # Main role tasks
│ ├── backup.yml # Backup-related tasks
│ ├── main.yml # Core tasks
│ └── monitoring.yml # Monitoring setup
├── templates/ # Jinja2 templates
└── vars/ # Non-overridable variables
└── main.yml
```
## 🛠️ Development
### Prerequisites
- Ansible 2.12+
- Python 3.8+
## 🔧 Configuration
## Default Variables (`defaults/main.yml`)
```yaml
# Default values for role variables
role_template_service_name: "default_service"
role_template_service_port: 80
role_template_backup_enabled: false
role_template_service_backup_dir: "/var/backups/{{ role_template_service_name }}"
role_template_monitoring_enabled: false
```
## Example usage
### Example Playbook (`example-playbook.yml`)
```yaml
---
- hosts: all
roles:
- role: yourorg.ansible-role-template
vars:
role_template_service_name: "myapp"
role_template_service_port: 8080
```
### 3. Run the Playbook
```bash
ansible-playbook -i inventory.ini example-playbook.yml
```
## 📄 License
This project is licensed under the MIT License
See the [LICENSE](LICENSE) file for details.
## TODO
☐ refactor
☐ debug
☐ docs

38
defaults/main.yml Normal file
View File

@@ -0,0 +1,38 @@
---
# ansible-role-template/defaults/main.yml
# Default values for role variables
# ===================================
# Service configuration
role_template_service_name: "default_service"
role_template_service_port: 80
# User and permissions
role_template_service_user: "nobody"
role_template_service_group: "nogroup"
role_template_service_uid: 65534
role_template_service_gid: 65534
role_template_service_mode: "0755"
# Directory structure
role_template_service_dir: "/opt/{{ role_template_service_name }}"
role_template_service_backup_dir: "/var/backups/{{ role_template_service_name }}"
# Systemd configuration (if applicable)
role_template_systemd_enabled: false
role_template_systemd_override_dir: "/etc/systemd/system/{{ role_template_service_name }}.d"
# Security
role_template_validate_certs: true
role_template_ssl_ciphers: "HIGH:!aNULL:!MD5"
role_template_ssl_protocols: "TLSv1.2:TLSv1.3"
# Backup
role_template_backup_enabled: false
role_template_backup_retention: 7
role_template_backup_archive_path: "/var/backups/{{ role_template_service_name }}/archive"
# Monitoring (optional)
role_template_monitoring_enabled: false
role_template_monitoring_interval: 60
role_template_monitoring_notify_email: "admin@example.com"

45
handlers/main.yml Normal file
View File

@@ -0,0 +1,45 @@
---
# ansible-role-template/handlers/main.yml
# Handlers for role
# ==================
# Service handlers
- name: Restart {{ role_template_service_name }}
ansible.builtin.service:
name: "{{ role_template_service_name }}"
state: restarted
listen: "restart {{ role_template_service_name }}"
when: role_template_service_enabled
- name: Reload systemd
ansible.builtin.systemd:
daemon_reload: true
listen: "restart {{ role_template_service_name }}"
when: role_template_systemd_enabled
# Configuration handlers
- name: Reload nginx
ansible.builtin.service:
name: nginx
state: reloaded
listen: "reload nginx"
when: "'nginx' in role_template_service_name"
# Backup handlers
- name: Rotate logs
ansible.builtin.command: logger -p local0.info "Rotating logs for {{ role_template_service_name }}"
changed_when: true
listen: "rotate logs"
# Monitoring handlers
- name: Notify monitoring
ansible.builtin.uri:
url: "{{ role_template_monitoring_webhook_url }}"
method: POST
body_format: json
body: "{{ lookup('template', 'monitoring_notification.json.j2') }}"
status_code: 200
delegate_to: localhost
run_once: true
listen: "notify monitoring"
when: role_template_monitoring_enabled

20
meta/main.yml Normal file
View File

@@ -0,0 +1,20 @@
---
# ansible-role-template/meta/main.yml
galaxy_info:
role_name: ansible_role_template # if absent directory name hosting role is used instead
namespace: joseraj # if absent, author is used instead
author: joseraj
description: >
A reusable Ansible role template for deploying and managing applications/services
with security best practices, modularity, and idempotency.
license: MIT
min_ansible_version: "2.12"
platforms:
- name: Debian
versions:
- buster
- bullseye
- bookworm
- trixie
galaxy_tags:
- automation

28
tasks/backup.yml Normal file
View File

@@ -0,0 +1,28 @@
---
# # ansible-role-template/tasks/backup.yml
# Backup tasks
# ============
- name: backup | Ensure backup directory exists
ansible.builtin.file:
path: "{{ role_template_backup_dir }}"
state: directory
mode: "0750"
owner: root
group: root
- name: backup | Create backup script
ansible.builtin.template:
src: templates/backup_script.sh.j2
dest: /usr/local/bin/backup_{{ role_template_service_name }}
mode: "0755"
owner: root
group: root
- name: backup | Create cron job for backups
ansible.builtin.cron:
name: "Backup {{ role_template_service_name }}"
user: root
minute: "0"
hour: "3"
job: "/usr/local/bin/backup_{{ role_template_service_name }}"

14
tasks/main.yml Normal file
View File

@@ -0,0 +1,14 @@
---
# ansible-role-template/tasks/main.yml
# Main tasks for role
# ===================
# Import backup tasks
- name: Import backup tasks
ansible.builtin.import_tasks: backup.yml
when: role_template_backup_enabled
# Import monitoring tasks
- name: Import monitoring tasks
ansible.builtin.import_tasks: monitoring.yml
when: role_template_monitoring_enabled

22
tasks/monitoring.yml Normal file
View File

@@ -0,0 +1,22 @@
---
# # ansible-role-template/tasks/monitoring.yml
# Monitoring tasks
# ================
- name: monitoring | Ensure monitoring directory exists
ansible.builtin.file:
path: "/var/log/monitoring/{{ role_template_service_name }}"
state: directory
mode: "0755"
- name: monitoring | Create monitoring configuration
ansible.builtin.template:
src: templates/monitoring_config.yml.j2
dest: "/etc/monitoring/{{ role_template_service_name }}.yml"
mode: "0640"
- name: monitoring | Ensure monitoring service is running
ansible.builtin.service:
name: monitoring-service
state: started
enabled: yes

2
vars/main.yml Normal file
View File

@@ -0,0 +1,2 @@
---
# ansible-role-template/vars/main.yml