Add common role, scripts, and documentation
- ansible.cfg: Set remote_user to dlxadmin - inventory: Add infrastructure, application hosts with IPs - group_vars/all.yml: Set ansible_user to dlxadmin - playbooks/site.yml: Enable common role - roles/common: Baseline configuration role - Package installation (Debian/RedHat/Arch) - Timezone and locale setup - User management with SSH keys - SSH hardening - UFW firewall and security settings - scripts/create-user.sh: Create ansible user on servers - USAGE.md: Project usage documentation - HOSTS.md: Infrastructure host inventory Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
35d6965fab
commit
94be59bb26
|
|
@ -0,0 +1,63 @@
|
||||||
|
# Infrastructure Hosts
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
| Host | IP | OS | Group |
|
||||||
|
|------|-----|-----|-------|
|
||||||
|
| ansible-node | 192.168.200.106 | Debian 18.0 | control |
|
||||||
|
| postgres | 192.168.200.103 | Debian 18.1 | dbservers |
|
||||||
|
| mysql | 192.168.200.110 | Debian 18.1 | dbservers |
|
||||||
|
| mongo | 192.168.200.111 | Ubuntu 24.10 | dbservers |
|
||||||
|
| nginx | 192.168.200.65 | Ubuntu 24.04 | webservers |
|
||||||
|
| npm | 192.168.200.71 | Debian 12.12 | webservers |
|
||||||
|
| docker | 192.168.200.200 | Ubuntu 25.04 | infrastructure |
|
||||||
|
| pihole | 192.168.200.100 | Ubuntu 24.04 | infrastructure |
|
||||||
|
| gitea | 192.168.200.102 | Debian 18.0 | infrastructure |
|
||||||
|
| jenkins | 192.168.200.91 | Ubuntu 24.04 | infrastructure |
|
||||||
|
| hiveops | 192.168.200.112 | Ubuntu 24.04 | application |
|
||||||
|
| smartjournal | 192.168.200.114 | Ubuntu 24.04 | application |
|
||||||
|
| odoo | 192.168.200.61 | Debian 18.0 | application |
|
||||||
|
| localhost | - | Pop!_OS 24.04 | local |
|
||||||
|
|
||||||
|
## Groups
|
||||||
|
|
||||||
|
### control
|
||||||
|
- ansible-node (192.168.200.106)
|
||||||
|
|
||||||
|
### dbservers
|
||||||
|
- postgres (192.168.200.103)
|
||||||
|
- mysql (192.168.200.110)
|
||||||
|
- mongo (192.168.200.111)
|
||||||
|
|
||||||
|
### webservers
|
||||||
|
- nginx (192.168.200.65)
|
||||||
|
- npm (192.168.200.71)
|
||||||
|
|
||||||
|
### infrastructure
|
||||||
|
- docker (192.168.200.200)
|
||||||
|
- pihole (192.168.200.100)
|
||||||
|
- gitea (192.168.200.102)
|
||||||
|
- jenkins (192.168.200.91)
|
||||||
|
|
||||||
|
### application
|
||||||
|
- hiveops (192.168.200.112)
|
||||||
|
- smartjournal (192.168.200.114)
|
||||||
|
- odoo (192.168.200.61)
|
||||||
|
|
||||||
|
## Ansible User
|
||||||
|
|
||||||
|
All hosts use `dlxadmin` as the ansible user with passwordless sudo.
|
||||||
|
|
||||||
|
## Quick Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Test all hosts
|
||||||
|
ansible-playbook playbooks/ping.yml
|
||||||
|
|
||||||
|
# Test specific group
|
||||||
|
ansible-playbook playbooks/ping.yml -l dbservers
|
||||||
|
|
||||||
|
# Run ad-hoc command
|
||||||
|
ansible all -a "uptime"
|
||||||
|
ansible dbservers -a "df -h"
|
||||||
|
```
|
||||||
|
|
@ -0,0 +1,175 @@
|
||||||
|
# Ansible Project Usage
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
### 1. Setup SSH Access
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# For existing user
|
||||||
|
./scripts/setup-ssh.sh <ip_address> <username>
|
||||||
|
|
||||||
|
# Create new user via admin account
|
||||||
|
./scripts/setup-ssh.sh <ip_address> <username> <admin_user>
|
||||||
|
|
||||||
|
# Examples
|
||||||
|
./scripts/setup-ssh.sh 192.168.200.103 ansible
|
||||||
|
./scripts/setup-ssh.sh 192.168.200.103 ansible root
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Test Connectivity
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Test all hosts
|
||||||
|
ansible-playbook playbooks/ping.yml
|
||||||
|
|
||||||
|
# Test specific group
|
||||||
|
ansible-playbook playbooks/ping.yml -l dbservers
|
||||||
|
|
||||||
|
# Test single host
|
||||||
|
ansible-playbook playbooks/ping.yml -l postgres
|
||||||
|
|
||||||
|
# Quick ping (no playbook)
|
||||||
|
ansible all -m ping
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Run Playbooks
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Apply common configuration to all hosts
|
||||||
|
ansible-playbook playbooks/site.yml
|
||||||
|
|
||||||
|
# Limit to specific group
|
||||||
|
ansible-playbook playbooks/site.yml -l dbservers
|
||||||
|
|
||||||
|
# Limit to specific host
|
||||||
|
ansible-playbook playbooks/site.yml -l postgres
|
||||||
|
|
||||||
|
# Dry run (check mode)
|
||||||
|
ansible-playbook playbooks/site.yml --check
|
||||||
|
|
||||||
|
# Run specific tags only
|
||||||
|
ansible-playbook playbooks/site.yml --tags packages
|
||||||
|
ansible-playbook playbooks/site.yml --tags security
|
||||||
|
ansible-playbook playbooks/site.yml --tags ssh
|
||||||
|
```
|
||||||
|
|
||||||
|
## Inventory
|
||||||
|
|
||||||
|
Hosts are defined in `inventory/hosts.yml`:
|
||||||
|
|
||||||
|
| Group | Host | IP |
|
||||||
|
|----------------|--------------|-----------------|
|
||||||
|
| control | ansible-node | 192.168.200.106 |
|
||||||
|
| dbservers | postgres | 192.168.200.103 |
|
||||||
|
| dbservers | mysql | 192.168.200.110 |
|
||||||
|
| dbservers | mongo | 192.168.200.111 |
|
||||||
|
| webservers | nginx | 192.168.200.65 |
|
||||||
|
| webservers | npm | 192.168.200.101 |
|
||||||
|
| infrastructure | docker | 192.168.200.200 |
|
||||||
|
| infrastructure | pihole | 192.168.200.100 |
|
||||||
|
|
||||||
|
### Target Hosts
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# All hosts
|
||||||
|
ansible-playbook playbooks/site.yml
|
||||||
|
|
||||||
|
# By group
|
||||||
|
ansible-playbook playbooks/site.yml -l dbservers
|
||||||
|
ansible-playbook playbooks/site.yml -l webservers
|
||||||
|
ansible-playbook playbooks/site.yml -l infrastructure
|
||||||
|
|
||||||
|
# Multiple groups
|
||||||
|
ansible-playbook playbooks/site.yml -l "dbservers:webservers"
|
||||||
|
|
||||||
|
# Single host
|
||||||
|
ansible-playbook playbooks/site.yml -l postgres
|
||||||
|
```
|
||||||
|
|
||||||
|
## Common Role
|
||||||
|
|
||||||
|
The `common` role applies baseline configuration to all hosts.
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- **Packages**: curl, wget, vim, htop, git, unzip, net-tools, tree, jq
|
||||||
|
- **Timezone**: Configurable (default: UTC)
|
||||||
|
- **SSH Hardening**: Disable root login, password auth, limit auth tries
|
||||||
|
- **Firewall**: UFW with configurable allowed ports
|
||||||
|
- **Auto Updates**: Unattended security upgrades
|
||||||
|
- **User Management**: Create users with SSH keys and sudo access
|
||||||
|
|
||||||
|
### Configuration
|
||||||
|
|
||||||
|
Override defaults in `group_vars/` or `host_vars/`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# group_vars/dbservers.yml
|
||||||
|
common_timezone: "America/New_York"
|
||||||
|
common_extra_packages:
|
||||||
|
- postgresql-client
|
||||||
|
|
||||||
|
common_firewall_allowed_ports:
|
||||||
|
- "22/tcp"
|
||||||
|
- "5432/tcp"
|
||||||
|
|
||||||
|
common_users:
|
||||||
|
- name: deploy
|
||||||
|
groups: ['sudo']
|
||||||
|
passwordless_sudo: true
|
||||||
|
ssh_keys:
|
||||||
|
- "ssh-ed25519 AAAA..."
|
||||||
|
```
|
||||||
|
|
||||||
|
### Available Tags
|
||||||
|
|
||||||
|
| Tag | Description |
|
||||||
|
|-----------|--------------------------------|
|
||||||
|
| packages | Install common packages |
|
||||||
|
| timezone | Set timezone and locale |
|
||||||
|
| users | Create users and SSH keys |
|
||||||
|
| ssh | SSH daemon hardening |
|
||||||
|
| security | Firewall, sysctl, auto-updates |
|
||||||
|
|
||||||
|
## Ad-hoc Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Run command on all hosts
|
||||||
|
ansible all -a "uptime"
|
||||||
|
|
||||||
|
# Run command on group
|
||||||
|
ansible dbservers -a "df -h"
|
||||||
|
|
||||||
|
# Run with sudo
|
||||||
|
ansible all -b -a "apt update"
|
||||||
|
|
||||||
|
# Copy file
|
||||||
|
ansible all -m copy -a "src=/local/file dest=/remote/file"
|
||||||
|
|
||||||
|
# Install package
|
||||||
|
ansible dbservers -b -m apt -a "name=htop state=present"
|
||||||
|
|
||||||
|
# Restart service
|
||||||
|
ansible webservers -b -m service -a "name=nginx state=restarted"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Directory Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
dlx-ansible/
|
||||||
|
├── ansible.cfg # Ansible configuration
|
||||||
|
├── inventory/
|
||||||
|
│ └── hosts.yml # Host inventory
|
||||||
|
├── playbooks/
|
||||||
|
│ ├── site.yml # Main playbook
|
||||||
|
│ └── ping.yml # Connectivity test
|
||||||
|
├── roles/
|
||||||
|
│ └── common/ # Common baseline role
|
||||||
|
├── group_vars/
|
||||||
|
│ └── all.yml # Variables for all hosts
|
||||||
|
├── host_vars/ # Per-host variables
|
||||||
|
├── files/ # Static files
|
||||||
|
├── templates/ # Jinja2 templates
|
||||||
|
└── scripts/
|
||||||
|
└── setup-ssh.sh # SSH setup script
|
||||||
|
```
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
[defaults]
|
[defaults]
|
||||||
inventory = inventory/hosts.yml
|
inventory = inventory/hosts.yml
|
||||||
roles_path = roles
|
roles_path = roles
|
||||||
|
remote_user = dlxadmin
|
||||||
host_key_checking = False
|
host_key_checking = False
|
||||||
retry_files_enabled = False
|
retry_files_enabled = False
|
||||||
stdout_callback = yaml
|
stdout_callback = yaml
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
---
|
---
|
||||||
# Variables applied to all hosts
|
# Variables applied to all hosts
|
||||||
# ansible_user: your_ssh_user
|
ansible_user: dlxadmin
|
||||||
# ansible_become: true
|
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ all:
|
||||||
nginx:
|
nginx:
|
||||||
ansible_host: 192.168.200.65
|
ansible_host: 192.168.200.65
|
||||||
npm:
|
npm:
|
||||||
ansible_host: 192.168.200.101
|
ansible_host: 192.168.200.71
|
||||||
|
|
||||||
infrastructure:
|
infrastructure:
|
||||||
hosts:
|
hosts:
|
||||||
|
|
@ -28,8 +28,22 @@ all:
|
||||||
ansible_host: 192.168.200.200
|
ansible_host: 192.168.200.200
|
||||||
pihole:
|
pihole:
|
||||||
ansible_host: 192.168.200.100
|
ansible_host: 192.168.200.100
|
||||||
|
gitea:
|
||||||
|
ansible_host: 192.168.200.102
|
||||||
|
jenkins:
|
||||||
|
ansible_host: 192.168.200.91
|
||||||
|
|
||||||
|
application:
|
||||||
|
hosts:
|
||||||
|
hiveops:
|
||||||
|
ansible_host: 192.168.200.112
|
||||||
|
smartjournal:
|
||||||
|
ansible_host: 192.168.200.114
|
||||||
|
odoo:
|
||||||
|
ansible_host: 192.168.200.61
|
||||||
|
|
||||||
local:
|
local:
|
||||||
hosts:
|
hosts:
|
||||||
localhost:
|
localhost:
|
||||||
ansible_connection: local
|
ansible_connection: local
|
||||||
|
ansible_become: false
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,8 @@
|
||||||
# Main site playbook - orchestrates all plays
|
# Main site playbook - orchestrates all plays
|
||||||
- name: Apply common configuration
|
- name: Apply common configuration
|
||||||
hosts: all
|
hosts: all
|
||||||
roles: []
|
roles:
|
||||||
# - common
|
- common
|
||||||
|
|
||||||
# - name: Configure web servers
|
# - name: Configure web servers
|
||||||
# hosts: webservers
|
# hosts: webservers
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
---
|
||||||
|
# Common role defaults
|
||||||
|
|
||||||
|
# Timezone
|
||||||
|
common_timezone: "UTC"
|
||||||
|
|
||||||
|
# Locale
|
||||||
|
common_locale: "en_US.UTF-8"
|
||||||
|
|
||||||
|
# Packages to install on all hosts
|
||||||
|
common_packages:
|
||||||
|
- curl
|
||||||
|
- wget
|
||||||
|
- vim
|
||||||
|
- htop
|
||||||
|
- git
|
||||||
|
- unzip
|
||||||
|
- net-tools
|
||||||
|
- tree
|
||||||
|
- jq
|
||||||
|
|
||||||
|
# Additional packages (override per host/group)
|
||||||
|
common_extra_packages: []
|
||||||
|
|
||||||
|
# SSH configuration
|
||||||
|
common_ssh_port: 22
|
||||||
|
common_ssh_permit_root_login: "no"
|
||||||
|
common_ssh_password_authentication: "no"
|
||||||
|
common_ssh_pubkey_authentication: "yes"
|
||||||
|
|
||||||
|
# Firewall (ufw for Debian/Ubuntu, firewalld for RHEL)
|
||||||
|
common_firewall_enabled: true
|
||||||
|
common_firewall_allowed_ports:
|
||||||
|
- "22/tcp"
|
||||||
|
|
||||||
|
# Automatic updates
|
||||||
|
common_auto_updates_enabled: true
|
||||||
|
|
||||||
|
# Users to create (override in group_vars/host_vars)
|
||||||
|
common_users: []
|
||||||
|
# Example:
|
||||||
|
# common_users:
|
||||||
|
# - name: deploy
|
||||||
|
# groups: ['sudo']
|
||||||
|
# shell: /bin/bash
|
||||||
|
# ssh_keys:
|
||||||
|
# - "ssh-ed25519 AAAA..."
|
||||||
|
|
||||||
|
# Sysctl settings
|
||||||
|
common_sysctl_settings:
|
||||||
|
net.ipv4.ip_forward: 0
|
||||||
|
net.ipv4.conf.all.send_redirects: 0
|
||||||
|
net.ipv4.conf.default.send_redirects: 0
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
---
|
||||||
|
# Common role handlers
|
||||||
|
|
||||||
|
- name: Restart sshd
|
||||||
|
ansible.builtin.service:
|
||||||
|
name: "{{ 'ssh' if ansible_os_family == 'Debian' else 'sshd' }}"
|
||||||
|
state: restarted
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
---
|
||||||
|
# Common role - main tasks
|
||||||
|
|
||||||
|
- name: Include OS-specific variables
|
||||||
|
ansible.builtin.include_vars: "{{ item }}"
|
||||||
|
with_first_found:
|
||||||
|
- "{{ ansible_distribution | lower }}-{{ ansible_distribution_major_version }}.yml"
|
||||||
|
- "{{ ansible_distribution | lower }}.yml"
|
||||||
|
- "{{ ansible_os_family | lower }}.yml"
|
||||||
|
- "default.yml"
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- name: Run package tasks
|
||||||
|
ansible.builtin.include_tasks: packages.yml
|
||||||
|
tags: [packages]
|
||||||
|
|
||||||
|
- name: Run timezone tasks
|
||||||
|
ansible.builtin.include_tasks: timezone.yml
|
||||||
|
tags: [timezone]
|
||||||
|
|
||||||
|
- name: Run user tasks
|
||||||
|
ansible.builtin.include_tasks: users.yml
|
||||||
|
tags: [users]
|
||||||
|
when: common_users | length > 0
|
||||||
|
|
||||||
|
- name: Run SSH hardening tasks
|
||||||
|
ansible.builtin.include_tasks: ssh.yml
|
||||||
|
tags: [ssh, security]
|
||||||
|
|
||||||
|
- name: Run security tasks
|
||||||
|
ansible.builtin.include_tasks: security.yml
|
||||||
|
tags: [security]
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
---
|
||||||
|
# Package installation tasks
|
||||||
|
|
||||||
|
- name: Update apt cache (Debian/Ubuntu)
|
||||||
|
ansible.builtin.apt:
|
||||||
|
update_cache: true
|
||||||
|
cache_valid_time: 3600
|
||||||
|
when: ansible_os_family == "Debian"
|
||||||
|
|
||||||
|
- name: Install common packages (Debian/Ubuntu)
|
||||||
|
ansible.builtin.apt:
|
||||||
|
name: "{{ common_packages + common_extra_packages }}"
|
||||||
|
state: present
|
||||||
|
when: ansible_os_family == "Debian"
|
||||||
|
|
||||||
|
- name: Install common packages (RedHat/CentOS)
|
||||||
|
ansible.builtin.dnf:
|
||||||
|
name: "{{ common_packages + common_extra_packages }}"
|
||||||
|
state: present
|
||||||
|
when: ansible_os_family == "RedHat"
|
||||||
|
|
||||||
|
- name: Install common packages (Arch)
|
||||||
|
community.general.pacman:
|
||||||
|
name: "{{ common_packages + common_extra_packages }}"
|
||||||
|
state: present
|
||||||
|
when: ansible_os_family == "Archlinux"
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
---
|
||||||
|
# Security hardening tasks
|
||||||
|
|
||||||
|
- name: Apply sysctl settings
|
||||||
|
ansible.posix.sysctl:
|
||||||
|
name: "{{ item.key }}"
|
||||||
|
value: "{{ item.value }}"
|
||||||
|
sysctl_set: true
|
||||||
|
state: present
|
||||||
|
reload: true
|
||||||
|
loop: "{{ common_sysctl_settings | dict2items }}"
|
||||||
|
|
||||||
|
- name: Install UFW (Debian/Ubuntu)
|
||||||
|
ansible.builtin.apt:
|
||||||
|
name: ufw
|
||||||
|
state: present
|
||||||
|
when:
|
||||||
|
- ansible_os_family == "Debian"
|
||||||
|
- common_firewall_enabled
|
||||||
|
|
||||||
|
- name: Configure UFW defaults
|
||||||
|
community.general.ufw:
|
||||||
|
direction: "{{ item.direction }}"
|
||||||
|
policy: "{{ item.policy }}"
|
||||||
|
loop:
|
||||||
|
- { direction: 'incoming', policy: 'deny' }
|
||||||
|
- { direction: 'outgoing', policy: 'allow' }
|
||||||
|
when:
|
||||||
|
- ansible_os_family == "Debian"
|
||||||
|
- common_firewall_enabled
|
||||||
|
|
||||||
|
- name: Allow firewall ports (UFW)
|
||||||
|
community.general.ufw:
|
||||||
|
rule: allow
|
||||||
|
port: "{{ item.split('/')[0] }}"
|
||||||
|
proto: "{{ item.split('/')[1] | default('tcp') }}"
|
||||||
|
loop: "{{ common_firewall_allowed_ports }}"
|
||||||
|
when:
|
||||||
|
- ansible_os_family == "Debian"
|
||||||
|
- common_firewall_enabled
|
||||||
|
|
||||||
|
- name: Enable UFW
|
||||||
|
community.general.ufw:
|
||||||
|
state: enabled
|
||||||
|
when:
|
||||||
|
- ansible_os_family == "Debian"
|
||||||
|
- common_firewall_enabled
|
||||||
|
|
||||||
|
- name: Install automatic security updates (Debian/Ubuntu)
|
||||||
|
ansible.builtin.apt:
|
||||||
|
name: unattended-upgrades
|
||||||
|
state: present
|
||||||
|
when:
|
||||||
|
- ansible_os_family == "Debian"
|
||||||
|
- common_auto_updates_enabled
|
||||||
|
|
||||||
|
- name: Enable automatic security updates (Debian/Ubuntu)
|
||||||
|
ansible.builtin.copy:
|
||||||
|
dest: /etc/apt/apt.conf.d/20auto-upgrades
|
||||||
|
content: |
|
||||||
|
APT::Periodic::Update-Package-Lists "1";
|
||||||
|
APT::Periodic::Unattended-Upgrade "1";
|
||||||
|
mode: '0644'
|
||||||
|
when:
|
||||||
|
- ansible_os_family == "Debian"
|
||||||
|
- common_auto_updates_enabled
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
---
|
||||||
|
# SSH hardening tasks
|
||||||
|
|
||||||
|
- name: Configure SSH daemon
|
||||||
|
ansible.builtin.lineinfile:
|
||||||
|
path: /etc/ssh/sshd_config
|
||||||
|
regexp: "{{ item.regexp }}"
|
||||||
|
line: "{{ item.line }}"
|
||||||
|
state: present
|
||||||
|
validate: 'sshd -t -f %s'
|
||||||
|
loop:
|
||||||
|
- regexp: "^#?Port"
|
||||||
|
line: "Port {{ common_ssh_port }}"
|
||||||
|
- regexp: "^#?PermitRootLogin"
|
||||||
|
line: "PermitRootLogin {{ common_ssh_permit_root_login }}"
|
||||||
|
- regexp: "^#?PasswordAuthentication"
|
||||||
|
line: "PasswordAuthentication {{ common_ssh_password_authentication }}"
|
||||||
|
- regexp: "^#?PubkeyAuthentication"
|
||||||
|
line: "PubkeyAuthentication {{ common_ssh_pubkey_authentication }}"
|
||||||
|
- regexp: "^#?X11Forwarding"
|
||||||
|
line: "X11Forwarding no"
|
||||||
|
- regexp: "^#?MaxAuthTries"
|
||||||
|
line: "MaxAuthTries 3"
|
||||||
|
- regexp: "^#?ClientAliveInterval"
|
||||||
|
line: "ClientAliveInterval 300"
|
||||||
|
- regexp: "^#?ClientAliveCountMax"
|
||||||
|
line: "ClientAliveCountMax 2"
|
||||||
|
notify: Restart sshd
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
---
|
||||||
|
# Timezone and locale configuration
|
||||||
|
|
||||||
|
- name: Set timezone
|
||||||
|
ansible.builtin.timezone:
|
||||||
|
name: "{{ common_timezone }}"
|
||||||
|
|
||||||
|
- name: Generate locale (Debian/Ubuntu)
|
||||||
|
community.general.locale_gen:
|
||||||
|
name: "{{ common_locale }}"
|
||||||
|
state: present
|
||||||
|
when: ansible_os_family == "Debian"
|
||||||
|
|
||||||
|
- name: Set default locale
|
||||||
|
ansible.builtin.lineinfile:
|
||||||
|
path: /etc/default/locale
|
||||||
|
regexp: "^LANG="
|
||||||
|
line: "LANG={{ common_locale }}"
|
||||||
|
create: true
|
||||||
|
mode: '0644'
|
||||||
|
when: ansible_os_family == "Debian"
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
---
|
||||||
|
# User management tasks
|
||||||
|
|
||||||
|
- name: Create user groups
|
||||||
|
ansible.builtin.group:
|
||||||
|
name: "{{ item.name }}"
|
||||||
|
state: present
|
||||||
|
loop: "{{ common_users }}"
|
||||||
|
when: item.create_group | default(true)
|
||||||
|
|
||||||
|
- name: Create users
|
||||||
|
ansible.builtin.user:
|
||||||
|
name: "{{ item.name }}"
|
||||||
|
groups: "{{ item.groups | default([]) }}"
|
||||||
|
shell: "{{ item.shell | default('/bin/bash') }}"
|
||||||
|
create_home: true
|
||||||
|
state: present
|
||||||
|
loop: "{{ common_users }}"
|
||||||
|
|
||||||
|
- name: Set authorized keys for users
|
||||||
|
ansible.posix.authorized_key:
|
||||||
|
user: "{{ item.0.name }}"
|
||||||
|
key: "{{ item.1 }}"
|
||||||
|
state: present
|
||||||
|
loop: "{{ common_users | subelements('ssh_keys', skip_missing=True) }}"
|
||||||
|
|
||||||
|
- name: Configure passwordless sudo for users
|
||||||
|
ansible.builtin.lineinfile:
|
||||||
|
path: "/etc/sudoers.d/{{ item.name }}"
|
||||||
|
line: "{{ item.name }} ALL=(ALL) NOPASSWD:ALL"
|
||||||
|
create: true
|
||||||
|
mode: '0440'
|
||||||
|
validate: 'visudo -cf %s'
|
||||||
|
loop: "{{ common_users }}"
|
||||||
|
when: item.passwordless_sudo | default(false)
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
---
|
||||||
|
# Default variables (fallback)
|
||||||
|
|
@ -0,0 +1,94 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Create a user with sudo privileges
|
||||||
|
# Usage: ./create-user.sh [username]
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Colors
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
NC='\033[0m'
|
||||||
|
|
||||||
|
# Default username
|
||||||
|
USERNAME="${1:-dlxadmin}"
|
||||||
|
|
||||||
|
# Check if running as root
|
||||||
|
if [ "$EUID" -ne 0 ]; then
|
||||||
|
echo -e "${RED}Please run as root or with sudo${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "${GREEN}Creating user: ${USERNAME}${NC}"
|
||||||
|
|
||||||
|
# Check if user already exists
|
||||||
|
if id "$USERNAME" &>/dev/null; then
|
||||||
|
echo -e "${YELLOW}User ${USERNAME} already exists${NC}"
|
||||||
|
else
|
||||||
|
# Create user
|
||||||
|
useradd -m -s /bin/bash "$USERNAME"
|
||||||
|
echo -e "${GREEN}User ${USERNAME} created${NC}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Set password
|
||||||
|
echo -e "${YELLOW}Set password for ${USERNAME}:${NC}"
|
||||||
|
passwd "$USERNAME"
|
||||||
|
|
||||||
|
# Add to sudo group (Debian/Ubuntu) or wheel (RHEL/CentOS)
|
||||||
|
if getent group sudo &>/dev/null; then
|
||||||
|
usermod -aG sudo "$USERNAME"
|
||||||
|
echo -e "${GREEN}Added ${USERNAME} to sudo group${NC}"
|
||||||
|
elif getent group wheel &>/dev/null; then
|
||||||
|
usermod -aG wheel "$USERNAME"
|
||||||
|
echo -e "${GREEN}Added ${USERNAME} to wheel group${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${RED}Neither sudo nor wheel group found${NC}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Configure passwordless sudo
|
||||||
|
if [ -d /etc/sudoers.d ]; then
|
||||||
|
echo "$USERNAME ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/"$USERNAME"
|
||||||
|
chmod 440 /etc/sudoers.d/"$USERNAME"
|
||||||
|
echo -e "${GREEN}Configured passwordless sudo for ${USERNAME}${NC}"
|
||||||
|
else
|
||||||
|
# Fallback: add to sudoers file directly
|
||||||
|
if ! grep -q "^$USERNAME" /etc/sudoers; then
|
||||||
|
echo "$USERNAME ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
|
||||||
|
echo -e "${GREEN}Added ${USERNAME} to /etc/sudoers${NC}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check and install SSH server
|
||||||
|
if ! command -v sshd &>/dev/null && ! systemctl list-unit-files | grep -q sshd; then
|
||||||
|
echo -e "${YELLOW}SSH server not found. Installing...${NC}"
|
||||||
|
if command -v apt-get &>/dev/null; then
|
||||||
|
apt-get update && apt-get install -y openssh-server
|
||||||
|
elif command -v dnf &>/dev/null; then
|
||||||
|
dnf install -y openssh-server
|
||||||
|
elif command -v yum &>/dev/null; then
|
||||||
|
yum install -y openssh-server
|
||||||
|
elif command -v pacman &>/dev/null; then
|
||||||
|
pacman -Sy --noconfirm openssh
|
||||||
|
else
|
||||||
|
echo -e "${RED}Could not install SSH server. Please install manually.${NC}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Enable and start SSH service
|
||||||
|
if command -v systemctl &>/dev/null; then
|
||||||
|
systemctl enable --now sshd 2>/dev/null || systemctl enable --now ssh 2>/dev/null
|
||||||
|
echo -e "${GREEN}SSH service enabled and started${NC}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Setup .ssh directory
|
||||||
|
mkdir -p /home/"$USERNAME"/.ssh
|
||||||
|
chmod 700 /home/"$USERNAME"/.ssh
|
||||||
|
touch /home/"$USERNAME"/.ssh/authorized_keys
|
||||||
|
chmod 600 /home/"$USERNAME"/.ssh/authorized_keys
|
||||||
|
chown -R "$USERNAME":"$USERNAME" /home/"$USERNAME"/.ssh
|
||||||
|
echo -e "${GREEN}Created .ssh directory${NC}"
|
||||||
|
|
||||||
|
echo -e "${GREEN}✓ User ${USERNAME} setup complete!${NC}"
|
||||||
|
echo -e "${YELLOW}Now run from your ansible workstation:${NC}"
|
||||||
|
echo -e " ./scripts/setup-ssh.sh <this-server-ip> ${USERNAME}"
|
||||||
Loading…
Reference in New Issue