Added first ubuntu server playbooks
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
- name: Install basic features
|
||||
hosts: ansible_master
|
||||
become: true
|
||||
|
||||
tasks:
|
||||
- name: Update apt
|
||||
ansible.builtin.apt:
|
||||
update_cache: true
|
||||
cache_valid_time: 3600
|
||||
|
||||
- name: Install net-tools
|
||||
ansible.builtin.apt:
|
||||
name: net-tools
|
||||
state: present
|
||||
|
||||
- name: Install neofetch or fastfetch
|
||||
block:
|
||||
- name: Install neofetch
|
||||
ansible.builtin.apt:
|
||||
name: neofetch
|
||||
state: present
|
||||
|
||||
rescue:
|
||||
- name: If neofetch is depricated install fastfetch
|
||||
ansible.builtin.apt:
|
||||
name: fastfetch
|
||||
state: present
|
||||
@@ -0,0 +1,485 @@
|
||||
---
|
||||
# Nextcloud Installation Playbook
|
||||
# Target: Ubuntu 24.04
|
||||
# Stack: Apache2 + PHP 8.3 + MariaDB + Nextcloud 34.0.0
|
||||
# HTTPS via self-signed certificate
|
||||
#
|
||||
# Usage:
|
||||
# ansible-playbook nextcloud.yml -i inventory.ini
|
||||
|
||||
# ================================================================
|
||||
# PLAY 0 — Bootstrap: install acl BEFORE any become_user is used.
|
||||
# ================================================================
|
||||
- name: Bootstrap – ensure acl is installed
|
||||
hosts: nextcloud
|
||||
become: true
|
||||
gather_facts: false
|
||||
|
||||
tasks:
|
||||
- name: Update apt cache
|
||||
ansible.builtin.apt:
|
||||
update_cache: true
|
||||
cache_valid_time: 3600
|
||||
|
||||
- name: Install acl (required for Ansible become_user on Linux)
|
||||
ansible.builtin.apt:
|
||||
name: acl
|
||||
state: present
|
||||
|
||||
# ================================================================
|
||||
# PLAY 1 — Main Nextcloud installation
|
||||
# ================================================================
|
||||
- name: Install and configure Nextcloud
|
||||
hosts: nextcloud
|
||||
become: true
|
||||
|
||||
vars:
|
||||
nextcloud_version: "34.0.0"
|
||||
nextcloud_domain: "192.168.124.80"
|
||||
nextcloud_data_dir: "/etc/nextcloud/data"
|
||||
nextcloud_install_dir: "/etc/nextcloud"
|
||||
|
||||
db_name: "nextcloud"
|
||||
db_user: "nextcloud"
|
||||
db_password: "Start2026!" # ÄNDERN
|
||||
admin_user: "admin"
|
||||
admin_password: "Start2026!" # ÄNDERN
|
||||
php_version: "8.3"
|
||||
|
||||
# TLS certificate paths (self-signed, generated by this playbook)
|
||||
ssl_cert: "/etc/ssl/certs/nextcloud-selfsigned.crt"
|
||||
ssl_key: "/etc/ssl/private/nextcloud-selfsigned.key"
|
||||
|
||||
# Maintenance window (UTC): tasks run between start and start+4h
|
||||
# 1 = 01:00 UTC → adjust to your timezone offset as needed
|
||||
maintenance_window_start: 1
|
||||
|
||||
# ---------------------------------------------------------------
|
||||
# 1. System packages
|
||||
# ---------------------------------------------------------------
|
||||
tasks:
|
||||
- name: Install system packages
|
||||
ansible.builtin.apt:
|
||||
name:
|
||||
- apt-transport-https
|
||||
- ca-certificates
|
||||
- curl
|
||||
- gnupg
|
||||
- lsb-release
|
||||
- python3-pymysql
|
||||
- openssl
|
||||
- unzip
|
||||
- bzip2
|
||||
state: present
|
||||
|
||||
# ---------------------------------------------------------------
|
||||
# 2. Apache
|
||||
# ---------------------------------------------------------------
|
||||
- name: Install Apache2
|
||||
ansible.builtin.apt:
|
||||
name: apache2
|
||||
state: present
|
||||
|
||||
- name: Enable required Apache modules
|
||||
community.general.apache2_module:
|
||||
name: "{{ item }}"
|
||||
state: present
|
||||
loop:
|
||||
- rewrite
|
||||
- headers
|
||||
- env
|
||||
- dir
|
||||
- mime
|
||||
- ssl
|
||||
notify: Restart Apache
|
||||
|
||||
- name: Enable Apache service
|
||||
ansible.builtin.systemd:
|
||||
name: apache2
|
||||
enabled: true
|
||||
state: started
|
||||
|
||||
# ---------------------------------------------------------------
|
||||
# 3. Self-signed TLS certificate
|
||||
# ---------------------------------------------------------------
|
||||
- name: Generate self-signed TLS certificate (10-year validity)
|
||||
ansible.builtin.command:
|
||||
cmd: >
|
||||
openssl req -x509 -nodes -days 3650
|
||||
-newkey rsa:4096
|
||||
-keyout {{ ssl_key }}
|
||||
-out {{ ssl_cert }}
|
||||
-subj "/CN={{ nextcloud_domain }}/O=Nextcloud/C=DE"
|
||||
-addext "subjectAltName=DNS:{{ nextcloud_domain }}"
|
||||
creates: "{{ ssl_cert }}"
|
||||
|
||||
- name: Restrict private key permissions
|
||||
ansible.builtin.file:
|
||||
path: "{{ ssl_key }}"
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0600"
|
||||
|
||||
# ---------------------------------------------------------------
|
||||
# 4. PHP 8.3 + extensions
|
||||
# ---------------------------------------------------------------
|
||||
- name: Install PHP {{ php_version }} and extensions
|
||||
ansible.builtin.apt:
|
||||
name:
|
||||
- "php{{ php_version }}"
|
||||
- "php{{ php_version }}-cli"
|
||||
- "php{{ php_version }}-common"
|
||||
- "php{{ php_version }}-curl"
|
||||
- "php{{ php_version }}-gd"
|
||||
- "php{{ php_version }}-gmp"
|
||||
- "php{{ php_version }}-imagick"
|
||||
- "php{{ php_version }}-intl"
|
||||
- "php{{ php_version }}-mbstring"
|
||||
- "php{{ php_version }}-mysql"
|
||||
- "php{{ php_version }}-opcache"
|
||||
- "php{{ php_version }}-readline"
|
||||
- "php{{ php_version }}-redis"
|
||||
- "php{{ php_version }}-xml"
|
||||
- "php{{ php_version }}-zip"
|
||||
- "php{{ php_version }}-bcmath"
|
||||
- "php{{ php_version }}-apcu"
|
||||
state: present
|
||||
notify: Restart Apache
|
||||
|
||||
- name: Configure PHP for Nextcloud (php.ini tweaks)
|
||||
ansible.builtin.lineinfile:
|
||||
path: "/etc/php/{{ php_version }}/apache2/php.ini"
|
||||
regexp: "{{ item.regexp }}"
|
||||
line: "{{ item.line }}"
|
||||
backup: true
|
||||
loop:
|
||||
- { regexp: '^memory_limit', line: 'memory_limit = 2048M' }
|
||||
- { regexp: '^upload_max_filesize', line: 'upload_max_filesize = 16G' }
|
||||
- { regexp: '^post_max_size', line: 'post_max_size = 16G' }
|
||||
- { regexp: '^max_execution_time', line: 'max_execution_time = 300' }
|
||||
- { regexp: '^max_input_time', line: 'max_input_time = 300' }
|
||||
- { regexp: '^output_buffering', line: 'output_buffering = Off' }
|
||||
notify: Restart Apache
|
||||
|
||||
- name: Enable OPcache settings
|
||||
ansible.builtin.blockinfile:
|
||||
path: "/etc/php/{{ php_version }}/apache2/conf.d/10-opcache.ini"
|
||||
block: |
|
||||
opcache.enable=1
|
||||
opcache.interned_strings_buffer=32
|
||||
opcache.max_accelerated_files=10000
|
||||
opcache.memory_consumption=128
|
||||
opcache.save_comments=1
|
||||
opcache.revalidate_freq=1
|
||||
marker: "; {mark} ANSIBLE MANAGED BLOCK"
|
||||
notify: Restart Apache
|
||||
|
||||
# ---------------------------------------------------------------
|
||||
# 5. MariaDB
|
||||
# ---------------------------------------------------------------
|
||||
- name: Install MariaDB server
|
||||
ansible.builtin.apt:
|
||||
name:
|
||||
- mariadb-server
|
||||
- mariadb-client
|
||||
state: present
|
||||
|
||||
- name: Enable and start MariaDB
|
||||
ansible.builtin.systemd:
|
||||
name: mariadb
|
||||
enabled: true
|
||||
state: started
|
||||
|
||||
- name: Create Nextcloud database
|
||||
community.mysql.mysql_db:
|
||||
name: "{{ db_name }}"
|
||||
collation: utf8mb4_general_ci
|
||||
encoding: utf8mb4
|
||||
state: present
|
||||
login_unix_socket: /var/run/mysqld/mysqld.sock
|
||||
|
||||
- name: Create Nextcloud database user
|
||||
community.mysql.mysql_user:
|
||||
name: "{{ db_user }}"
|
||||
password: "{{ db_password }}"
|
||||
priv: "{{ db_name }}.*:ALL"
|
||||
host: localhost
|
||||
state: present
|
||||
login_unix_socket: /var/run/mysqld/mysqld.sock
|
||||
|
||||
# ---------------------------------------------------------------
|
||||
# 6. Download & extract Nextcloud
|
||||
# ---------------------------------------------------------------
|
||||
- name: Check if Nextcloud is already present
|
||||
ansible.builtin.stat:
|
||||
path: "{{ nextcloud_install_dir }}/index.php"
|
||||
register: nextcloud_stat
|
||||
|
||||
- name: Download Nextcloud {{ nextcloud_version }}
|
||||
ansible.builtin.get_url:
|
||||
url: "https://download.nextcloud.com/server/releases/nextcloud-{{ nextcloud_version }}.zip"
|
||||
dest: "/tmp/nextcloud-{{ nextcloud_version }}.zip"
|
||||
mode: "0644"
|
||||
when: not nextcloud_stat.stat.exists
|
||||
|
||||
- name: Extract Nextcloud archive
|
||||
ansible.builtin.unarchive:
|
||||
src: "/tmp/nextcloud-{{ nextcloud_version }}.zip"
|
||||
dest: /etc/
|
||||
remote_src: true
|
||||
owner: www-data
|
||||
group: www-data
|
||||
when: not nextcloud_stat.stat.exists
|
||||
|
||||
- name: Create Nextcloud data directory
|
||||
ansible.builtin.file:
|
||||
path: "{{ nextcloud_data_dir }}"
|
||||
state: directory
|
||||
owner: www-data
|
||||
group: www-data
|
||||
mode: "0750"
|
||||
|
||||
- name: Set correct ownership on Nextcloud install directory
|
||||
ansible.builtin.file:
|
||||
path: "{{ nextcloud_install_dir }}"
|
||||
recurse: true
|
||||
owner: www-data
|
||||
group: www-data
|
||||
|
||||
# ---------------------------------------------------------------
|
||||
# 7. Apache virtual host — HTTP redirects to HTTPS, HTTPS serves NC
|
||||
# ---------------------------------------------------------------
|
||||
- name: Deploy Nextcloud Apache virtual host (HTTP redirect + HTTPS)
|
||||
ansible.builtin.copy:
|
||||
dest: /etc/apache2/sites-available/nextcloud.conf
|
||||
mode: "0644"
|
||||
content: |
|
||||
# ── HTTP: redirect all traffic to HTTPS ──────────────────────
|
||||
<VirtualHost *:80>
|
||||
ServerName {{ nextcloud_domain }}
|
||||
RewriteEngine On
|
||||
RewriteRule ^(.*)$ https://%{HTTP_HOST}$1 [R=301,L]
|
||||
</VirtualHost>
|
||||
|
||||
# ── HTTPS: serve Nextcloud ────────────────────────────────────
|
||||
<VirtualHost *:443>
|
||||
ServerName {{ nextcloud_domain }}
|
||||
DocumentRoot {{ nextcloud_install_dir }}
|
||||
|
||||
SSLEngine on
|
||||
SSLCertificateFile {{ ssl_cert }}
|
||||
SSLCertificateKeyFile {{ ssl_key }}
|
||||
|
||||
# Recommended TLS hardening
|
||||
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
|
||||
SSLCipherSuite ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:!aNULL:!MD5:!DSS
|
||||
SSLHonorCipherOrder on
|
||||
|
||||
<IfModule mod_headers.c>
|
||||
Header always set Strict-Transport-Security "max-age=15552000; includeSubDomains"
|
||||
</IfModule>
|
||||
|
||||
<Directory {{ nextcloud_install_dir }}>
|
||||
Require all granted
|
||||
AllowOverride All
|
||||
Options FollowSymLinks MultiViews
|
||||
|
||||
<IfModule mod_dav.c>
|
||||
Dav off
|
||||
</IfModule>
|
||||
</Directory>
|
||||
|
||||
# Security headers
|
||||
Header always set Strict-Transport-Security "max-age=15552000; includeSubDomains"
|
||||
Header always set Referrer-Policy "no-referrer"
|
||||
Header always set X-Content-Type-Options "nosniff"
|
||||
Header always set X-Frame-Options "SAMEORIGIN"
|
||||
Header always set X-Permitted-Cross-Domain-Policies "none"
|
||||
Header always set X-Robots-Tag "noindex, nofollow"
|
||||
Header always set X-XSS-Protection "1; mode=block"
|
||||
|
||||
ErrorLog ${APACHE_LOG_DIR}/nextcloud_error.log
|
||||
CustomLog ${APACHE_LOG_DIR}/nextcloud_access.log combined
|
||||
</VirtualHost>
|
||||
notify: Restart Apache
|
||||
|
||||
- name: Disable default Apache site
|
||||
ansible.builtin.command: a2dissite 000-default
|
||||
args:
|
||||
removes: /etc/apache2/sites-enabled/000-default.conf
|
||||
notify: Restart Apache
|
||||
|
||||
- name: Enable Nextcloud Apache site
|
||||
ansible.builtin.command: a2ensite nextcloud
|
||||
args:
|
||||
creates: /etc/apache2/sites-enabled/nextcloud.conf
|
||||
notify: Restart Apache
|
||||
|
||||
# ---------------------------------------------------------------
|
||||
# 8. Nextcloud occ installer
|
||||
# ---------------------------------------------------------------
|
||||
- name: Check if Nextcloud is already installed
|
||||
ansible.builtin.stat:
|
||||
path: "{{ nextcloud_install_dir }}/config/config.php"
|
||||
register: nc_config
|
||||
|
||||
- name: Run Nextcloud installation via occ
|
||||
ansible.builtin.shell: |
|
||||
su -s /bin/bash www-data -c \
|
||||
'php {{ nextcloud_install_dir }}/occ maintenance:install \
|
||||
--database "mysql" \
|
||||
--database-name "{{ db_name }}" \
|
||||
--database-user "{{ db_user }}" \
|
||||
--database-pass "{{ db_password }}" \
|
||||
--admin-user "{{ admin_user }}" \
|
||||
--admin-pass "{{ admin_password }}" \
|
||||
--data-dir "{{ nextcloud_data_dir }}"'
|
||||
args:
|
||||
creates: "{{ nextcloud_install_dir }}/config/config.php"
|
||||
register: occ_install
|
||||
|
||||
- name: Add trusted domain to Nextcloud config
|
||||
ansible.builtin.shell: |
|
||||
su -s /bin/bash www-data -c \
|
||||
'php {{ nextcloud_install_dir }}/occ config:system:set \
|
||||
trusted_domains 0 --value="{{ nextcloud_domain }}"'
|
||||
when: occ_install.changed
|
||||
|
||||
- name: Set overwrite.cli.url to HTTPS
|
||||
ansible.builtin.shell: |
|
||||
su -s /bin/bash www-data -c \
|
||||
'php {{ nextcloud_install_dir }}/occ config:system:set \
|
||||
overwrite.cli.url --value="https://{{ nextcloud_domain }}"'
|
||||
when: occ_install.changed
|
||||
|
||||
- name: Force HTTPS protocol in Nextcloud
|
||||
ansible.builtin.shell: |
|
||||
su -s /bin/bash www-data -c \
|
||||
'php {{ nextcloud_install_dir }}/occ config:system:set \
|
||||
overwriteprotocol --value="https"'
|
||||
when: occ_install.changed
|
||||
|
||||
- name: Set default phone region
|
||||
ansible.builtin.shell: |
|
||||
su -s /bin/bash www-data -c \
|
||||
'php {{ nextcloud_install_dir }}/occ \
|
||||
config:system:set default_phone_region --value=DE'
|
||||
when: occ_install.changed
|
||||
|
||||
- name: Set maintenance window start hour (UTC)
|
||||
ansible.builtin.shell: |
|
||||
su -s /bin/bash www-data -c \
|
||||
'php {{ nextcloud_install_dir }}/occ config:system:set \
|
||||
maintenance_window_start --type=integer --value="{{ maintenance_window_start }}"'
|
||||
when: occ_install.changed
|
||||
|
||||
# ---------------------------------------------------------------
|
||||
# 9. Cron job for background tasks
|
||||
# ---------------------------------------------------------------
|
||||
- name: Configure Nextcloud background job to use cron
|
||||
ansible.builtin.shell: |
|
||||
su -s /bin/bash www-data -c \
|
||||
'php {{ nextcloud_install_dir }}/occ background:cron'
|
||||
|
||||
- name: Add cron job for Nextcloud
|
||||
ansible.builtin.cron:
|
||||
name: "Nextcloud background tasks"
|
||||
user: www-data
|
||||
minute: "*/5"
|
||||
job: "php -f {{ nextcloud_install_dir }}/cron.php > /dev/null 2>&1"
|
||||
|
||||
# ---------------------------------------------------------------
|
||||
# Handlers
|
||||
# ---------------------------------------------------------------
|
||||
handlers:
|
||||
- name: Restart Apache
|
||||
ansible.builtin.systemd:
|
||||
name: apache2
|
||||
state: restarted
|
||||
|
||||
# ---------------------------------------------------------------
|
||||
# Play 3 - Nextcloud: Hardening
|
||||
# ---------------------------------------------------------------
|
||||
|
||||
- name: Harden Nextcloud install
|
||||
hosts: nextcloud
|
||||
become: true
|
||||
|
||||
vars:
|
||||
nextcloud_version: "34.0.0"
|
||||
nextcloud_domain: "cloud.test.local"
|
||||
nextcloud_data_dir: "/etc/nextcloud/data"
|
||||
nextcloud_install_dir: "/etc/nextcloud"
|
||||
|
||||
fail2ban_dir: "/etc/fail2ban"
|
||||
|
||||
php_version: "8.3"
|
||||
|
||||
tasks:
|
||||
- name: Set correct open_basedir restriction
|
||||
ansible.builtin.lineinfile:
|
||||
path: "/etc/php/{{ php_version }}/apache2/php.ini"
|
||||
regexp: '^;?open_basedir'
|
||||
line: "open_basedir = {{ nextcloud_install_dir }}:{{ nextcloud_data_dir }}:/tmp:/dev/urandom"
|
||||
notify: Restart Apache
|
||||
|
||||
# ---------------------------------------------------------------
|
||||
# Setup fail2ban for Nextcloud
|
||||
# ---------------------------------------------------------------
|
||||
- name: Install fail2ban
|
||||
ansible.builtin.apt:
|
||||
name:
|
||||
- fail2ban
|
||||
state: present
|
||||
|
||||
- name: Alter Nextcloud log settings for fail2ban
|
||||
ansible.builtin.lineinfile:
|
||||
path: "{{ nextcloud_install_dir }}/config/config.php"
|
||||
regexp: "{{ item.regexp }}"
|
||||
line: " {{ item.line }}"
|
||||
insertbefore: '^\);'
|
||||
backup: true
|
||||
loop:
|
||||
- { regexp: "^\\s*'log_type'\\s*=>", line: "'log_type' => 'file'," }
|
||||
- { regexp: "^\\s*'logfile'\\s*=>", line: "'logfile' => '{{ nextcloud_data_dir }}/nextcloud.log'," }
|
||||
- { regexp: "^\\s*'loglevel'\\s*=>", line: "'loglevel' => 3," }
|
||||
|
||||
- name: Create fail2ban filter for Nextcloud
|
||||
ansible.builtin.copy:
|
||||
content: |
|
||||
{% raw %}
|
||||
[Definition]
|
||||
_groupsre = (?:(?:,?\s*"\w+":(?:"[^"]+"|\w+))*)
|
||||
failregex = ^\{%(_groupsre)s,?\s*"remoteAddr":"<HOST>"%(_groupsre)s,?\s*"message":"Login failed:
|
||||
^\{%(_groupsre)s,?\s*"remoteAddr":"<HOST>"%(_groupsre)s,?\s*"message":"Two-factor challenge failed:
|
||||
^\{%(_groupsre)s,?\s*"remoteAddr":"<HOST>"%(_groupsre)s,?\s*"message":"Trusted domain error.
|
||||
datepattern = ,?\s*"time"\s*:\s*"%%Y-%%m-%%d[T ]%%H:%%M:%%S(%%z)?"
|
||||
{% endraw %}
|
||||
dest: "{{ fail2ban_dir }}/filter.d/nextcloud.conf"
|
||||
mode: "0644"
|
||||
|
||||
- name: Create fail2ban jail for Nextcloud
|
||||
ansible.builtin.copy:
|
||||
dest: "{{ fail2ban_dir }}/jail.d/nextcloud.local"
|
||||
mode: "0644"
|
||||
content: |
|
||||
[nextcloud]
|
||||
backend = auto
|
||||
enabled = true
|
||||
port = 80,443
|
||||
protocol = tcp
|
||||
filter = nextcloud
|
||||
maxretry = 3
|
||||
bantime = 86400
|
||||
findtime = 43200
|
||||
logpath = {{ nextcloud_data_dir }}/nextcloud.log
|
||||
notify: Restart Apache
|
||||
|
||||
# ---------------------------------------------------------------
|
||||
# Handlers
|
||||
# ---------------------------------------------------------------
|
||||
handlers:
|
||||
- name: Restart Apache
|
||||
ansible.builtin.systemd:
|
||||
name: apache2
|
||||
state: restarted
|
||||
Reference in New Issue
Block a user