Initial commit

This commit is contained in:
2026-03-24 08:19:29 +01:00
commit 2b1ca2d5be
95 changed files with 1993 additions and 0 deletions
+60
View File
@@ -0,0 +1,60 @@
# About This Repo #
This is a skeleton of an Ansible home directory. You can control all of your application environments from this directory. If you work with multiple customers, you probably want to create a separate copy of this repo for each customer.
This repo was designed to help new Ansible users to get up and running quickly. Feel free to add to it and add additional tips and tricks. Pull requests welcome.
# Ansible Tips #
In your roles directory, type ansible-galaxy init <em>role_name</em> in order to generate an empty skeleton for a new role you are working on.
Example:
<pre>
ansible-galaxy init nginx
</pre>
Check out [Ansible Examples](https://github.com/ansible/ansible-examples) for example playbooks.
# Best Practices Directory Layout #
Based on [Ansible Best Practices](https://docs.ansible.com/ansible/playbooks_best_practices.html#directory-layout)
<pre>
production # inventory file for production servers
staging # inventory file for staging environment
group_vars/
group1 # here we assign variables to particular groups
group2 # ""
host_vars/
hostname1 # if systems need specific variables, put them here
hostname2 # ""
library/ # if any custom modules, put them here (optional)
filter_plugins/ # if any custom filter plugins, put them here (optional)
site.yml # master playbook
webservers.yml # playbook for webserver tier
dbservers.yml # playbook for dbserver tier
roles/
common/ # this hierarchy represents a "role"
tasks/ #
main.yml # <-- tasks file can include smaller files if warranted
handlers/ #
main.yml # <-- handlers file
templates/ # <-- files for use with the template resource
ntp.conf.j2 # <------- templates end in .j2
files/ #
bar.txt # <-- files for use with the copy resource
foo.sh # <-- script files for use with the script resource
vars/ #
main.yml # <-- variables associated with this role
defaults/ #
main.yml # <-- default lower priority variables for this role
meta/ #
main.yml # <-- role dependencies
webtier/ # same kind of structure as "common" was above, done for the webtier role
monitoring/ # ""
fooapp/ # ""
</pre>
+3
View File
@@ -0,0 +1,3 @@
# A place to put variables that apply to all groups
# Create a file in this directory called "webservers" to set variables
# for the "webservers" group.
+2
View File
@@ -0,0 +1,2 @@
docker_apps_dir: "/opt/docker-apps/"
docker_socket_path: "/var/run/docker.sock"
+3
View File
@@ -0,0 +1,3 @@
docker_apps_dir: "/home/matzman/tmp/ansible-test/docker-apps-dir"
docker_socket_path: "/var/run/docker.sock"
+1
View File
@@ -0,0 +1 @@
+1
View File
@@ -0,0 +1 @@
+10
View File
@@ -0,0 +1,10 @@
localhost ansible_connection=local ansible_python_interpreter="{{ansible_playbook_python}}" host_ip_addr="10.61.1.20" host_base_domain="localhost"
[vhosts]
vhost0.homelan host_ip_addr="10.61.0.100" host_base_domain="vhost0.homelan"
vhost1.homelan host_ip_addr="10.61.0.110" host_base_domain="vhost1.homelan"
[vservers]
vserver0.homelan
vserver1.homelan
+30
View File
@@ -0,0 +1,30 @@
---
- hosts: vhost0.homelan
roles:
- role: docker-host
- role: docker-traefik-proxy
vars:
app_name: "traefik-vhost0"
- role: docker-arcane
vars:
app_name: "arcane-vhost0"
- role: docker-socket-proxy
- hosts: vhost1.homelan
roles:
- role: docker-host
- role: docker-traefik-proxy
vars:
app_name: "traefik-vhost1"
- role: docker-arcane
vars:
app_name: "arcane-vhost1"
- role: docker-socket-proxy
- role: docker-comic-utils
vars:
comicutils_data_extramounts:
Comics: "/storage/files/Multimedia/Comics"
Comics_Staging: "/storage/files/Multimedia/Comics_Staging"
tmp3x: "/storage/files/Sonstiges/tmp/tmp3x"
+38
View File
@@ -0,0 +1,38 @@
Role Name
========
A brief description of the role goes here.
Requirements
------------
Any pre-requisites that may not be covered by Ansible itself or the role should be mentioned here. For instance, if the role uses the EC2 module, it may be a good idea to mention in this section that the boto package is required.
Role Variables
--------------
A description of the settable variables for this role should go here, including any variables that are in defaults/main.yml, vars/main.yml, and any variables that can/should be set via parameters to the role. Any variables that are read from other roles and/or the global scope (ie. hostvars, group vars, etc.) should be mentioned here as well.
Dependencies
------------
A list of other roles hosted on Galaxy should go here, plus any details in regards to parameters that may need to be set for other roles, or variables that are used from other roles.
Example Playbook
-------------------------
Including an example of how to use your role (for instance, with variables passed in as parameters) is always nice for users too:
- hosts: servers
roles:
- { role: username.rolename, x: 42 }
License
-------
BSD
Author Information
------------------
An optional section for the role authors to include contact information, or a website (HTML is not allowed).
+2
View File
@@ -0,0 +1,2 @@
---
# defaults file for common
+2
View File
@@ -0,0 +1,2 @@
---
# handlers file for common
+122
View File
@@ -0,0 +1,122 @@
---
galaxy_info:
author: your name
description:
company: your company (optional)
# Some suggested licenses:
# - BSD (default)
# - MIT
# - GPLv2
# - GPLv3
# - Apache
# - CC-BY
license: license (GPLv2, CC-BY, etc)
min_ansible_version: 1.2
#
# Below are all platforms currently available. Just uncomment
# the ones that apply to your role. If you don't see your
# platform on this list, let us know and we'll get it added!
#
#platforms:
#- name: EL
# versions:
# - all
# - 5
# - 6
#- name: GenericUNIX
# versions:
# - all
# - any
#- name: Fedora
# versions:
# - all
# - 16
# - 17
# - 18
# - 19
# - 20
#- name: opensuse
# versions:
# - all
# - 12.1
# - 12.2
# - 12.3
# - 13.1
# - 13.2
#- name: Amazon
# versions:
# - all
# - 2013.03
# - 2013.09
#- name: GenericBSD
# versions:
# - all
# - any
#- name: FreeBSD
# versions:
# - all
# - 8.0
# - 8.1
# - 8.2
# - 8.3
# - 8.4
# - 9.0
# - 9.1
# - 9.1
# - 9.2
#- name: Ubuntu
# versions:
# - all
# - lucid
# - maverick
# - natty
# - oneiric
# - precise
# - quantal
# - raring
# - saucy
# - trusty
#- name: SLES
# versions:
# - all
# - 10SP3
# - 10SP4
# - 11
# - 11SP1
# - 11SP2
# - 11SP3
#- name: GenericLinux
# versions:
# - all
# - any
#- name: Debian
# versions:
# - all
# - etch
# - lenny
# - squeeze
# - wheezy
#
# Below are all categories currently available. Just as with
# the platforms above, uncomment those that apply to your role.
#
#categories:
#- cloud
#- cloud:ec2
#- cloud:gce
#- cloud:rax
#- database
#- database:nosql
#- database:sql
#- development
#- monitoring
#- networking
#- packaging
#- system
#- web
dependencies: []
# List your role dependencies here, one per line. Only
# dependencies available via galaxy should be listed here.
# Be sure to remove the '[]' above if you add dependencies
# to this list.
+2
View File
@@ -0,0 +1,2 @@
---
# tasks file for common
+2
View File
@@ -0,0 +1,2 @@
---
# vars file for common
+38
View File
@@ -0,0 +1,38 @@
Role Name
=========
A brief description of the role goes here.
Requirements
------------
Any pre-requisites that may not be covered by Ansible itself or the role should be mentioned here. For instance, if the role uses the EC2 module, it may be a good idea to mention in this section that the boto package is required.
Role Variables
--------------
A description of the settable variables for this role should go here, including any variables that are in defaults/main.yml, vars/main.yml, and any variables that can/should be set via parameters to the role. Any variables that are read from other roles and/or the global scope (ie. hostvars, group vars, etc.) should be mentioned here as well.
Dependencies
------------
A list of other roles hosted on Galaxy should go here, plus any details in regards to parameters that may need to be set for other roles, or variables that are used from other roles.
Example Playbook
----------------
Including an example of how to use your role (for instance, with variables passed in as parameters) is always nice for users too:
- hosts: servers
roles:
- { role: username.rolename, x: 42 }
License
-------
BSD
Author Information
------------------
An optional section for the role authors to include contact information, or a website (HTML is not allowed).
+14
View File
@@ -0,0 +1,14 @@
#SPDX-License-Identifier: MIT-0
---
# defaults file for docker-arcane
app_name: "arcane"
app_dns_name: "arcane"
app_base_dir: "{{ (docker_apps_dir, app_name) | path_join }}"
app_base_domain: "{{ app_dns_name ~ '.' ~ host_base_domain }}"
app_proxy_network: "traefik-proxy-net"
arcane_image_name: "ghcr.io/getarcaneapp/arcane"
arcane_webui_port: 3552
arcane_data_dir: "arcane-data"
arcane_encrypt_key: "513862f9ece8e28e27cbe78773f0ea6fafe8f8d168f58302c29e611796238780"
arcane_swt_key: "526bd35af00be1f3fe8547482c0eefe2180dd59a1add6244efce5fe7e7e4f256"
+3
View File
@@ -0,0 +1,3 @@
#SPDX-License-Identifier: MIT-0
---
# handlers file for docker-arcane
+35
View File
@@ -0,0 +1,35 @@
#SPDX-License-Identifier: MIT-0
galaxy_info:
author: your name
description: your role description
company: your company (optional)
# If the issue tracker for your role is not on github, uncomment the
# next line and provide a value
# issue_tracker_url: http://example.com/issue/tracker
# Choose a valid license ID from https://spdx.org - some suggested licenses:
# - BSD-3-Clause (default)
# - MIT
# - GPL-2.0-or-later
# - GPL-3.0-only
# - Apache-2.0
# - CC-BY-4.0
license: license (GPL-2.0-or-later, MIT, etc)
min_ansible_version: 2.2
# If this a Container Enabled role, provide the minimum Ansible Container version.
# min_ansible_container_version:
galaxy_tags: []
# List tags for your role here, one per line. A tag is a keyword that describes
# and categorizes the role. Users find roles by searching for tags. Be sure to
# remove the '[]' above, if you add tags to this list.
#
# NOTE: A tag is limited to a single word comprised of alphanumeric characters.
# Maximum 20 tags per role.
dependencies: []
# List your role dependencies here, one per line. Be sure to remove the '[]' above,
# if you add dependencies to this list.
+20
View File
@@ -0,0 +1,20 @@
#SPDX-License-Identifier: MIT-0
---
- name: Run Compose App Init
ansible.builtin.import_role:
name: docker-common
tasks_from: compose-app-init
tags: [create, docker-arcane]
- name: Run Compose App Start
ansible.builtin.import_role:
name: docker-common
tasks_from: compose-app-start
tags: [create, docker-arcane]
- name: Run Compose App Stop
ansible.builtin.import_role:
name: docker-common
tasks_from: compose-app-stop
tags: [never, stop-docker-arcane]
@@ -0,0 +1,40 @@
services:
{{ app_name }}:
image: {{ arcane_image_name }}
container_name: {{ app_name }}
ports:
- {{ arcane_webui_port }}:3552
networks:
{% if app_proxy_network is not none %}
{{ app_proxy_network }}:
{% else %}
{{ app_name ~ "-net" }}:
{% endif %}
volumes:
- {{ docker_socket_path }}:/var/run/docker.sock
- ./{{ arcane_data_dir }}:/app/data
- {{ docker_apps_dir }}:/app/data/projects
environment:
- APP_URL=http://{{ app_base_domain }}:{{ arcane_webui_port }}
- PUID=1000
- PGID=1000
- ENCRYPTION_KEY={{ arcane_encrypt_key }}
- JWT_SECRET={{ arcane_swt_key }}
restart: unless-stopped
{% if app_proxy_network is not none %}
labels:
traefik.enable: true
traefik.docker.network: "{{ app_proxy_network }}"
traefik.http.routers.{{ app_name }}-http.rule: "Host(`{{ app_base_domain }}`)"
traefik.http.routers.{{ app_name }}-http.entryPoints: web
traefik.http.services.{{ app_name }}.loadbalancer.server.port: 3552
{% endif %}
networks:
{% if app_proxy_network is not none %}
{{ app_proxy_network }}:
external: true
{% else %}
{{ app_name ~ "-net" }}:
{% endif %}
+3
View File
@@ -0,0 +1,3 @@
#SPDX-License-Identifier: MIT-0
localhost
+6
View File
@@ -0,0 +1,6 @@
#SPDX-License-Identifier: MIT-0
---
- hosts: localhost
remote_user: root
roles:
- docker-arcane
+3
View File
@@ -0,0 +1,3 @@
#SPDX-License-Identifier: MIT-0
---
# vars file for docker-arcane
+38
View File
@@ -0,0 +1,38 @@
Role Name
=========
A brief description of the role goes here.
Requirements
------------
Any pre-requisites that may not be covered by Ansible itself or the role should be mentioned here. For instance, if the role uses the EC2 module, it may be a good idea to mention in this section that the boto package is required.
Role Variables
--------------
A description of the settable variables for this role should go here, including any variables that are in defaults/main.yml, vars/main.yml, and any variables that can/should be set via parameters to the role. Any variables that are read from other roles and/or the global scope (ie. hostvars, group vars, etc.) should be mentioned here as well.
Dependencies
------------
A list of other roles hosted on Galaxy should go here, plus any details in regards to parameters that may need to be set for other roles, or variables that are used from other roles.
Example Playbook
----------------
Including an example of how to use your role (for instance, with variables passed in as parameters) is always nice for users too:
- hosts: servers
roles:
- { role: username.rolename, x: 42 }
License
-------
BSD
Author Information
------------------
An optional section for the role authors to include contact information, or a website (HTML is not allowed).
@@ -0,0 +1,18 @@
#SPDX-License-Identifier: MIT-0
---
# defaults file for docker-comic-utils
app_name: "comic-utils"
app_dns_name: "comic-utils"
app_base_dir: "{{ (docker_apps_dir, app_name) | path_join }}"
app_base_domain: "{{ app_dns_name ~ '.' ~ host_base_domain }}"
app_extra_domains: ["comic-utils.homelan"]
app_proxy_network: "traefik-proxy-net"
comicutils_image_name: "allaboutduncan/comic-utils-web:latest"
comicutils_config_dir: "config"
comicutils_data_dir: "data"
comicutils_cache_dir: "cache"
comicutils_downloads_dir: "downloads"
comicutils_data_extramounts:
Comics: "./data/Comics"
Comics_Staging: "./data/Comics_Staging"
@@ -0,0 +1,3 @@
#SPDX-License-Identifier: MIT-0
---
# handlers file for docker-comic-utils
+35
View File
@@ -0,0 +1,35 @@
#SPDX-License-Identifier: MIT-0
galaxy_info:
author: your name
description: your role description
company: your company (optional)
# If the issue tracker for your role is not on github, uncomment the
# next line and provide a value
# issue_tracker_url: http://example.com/issue/tracker
# Choose a valid license ID from https://spdx.org - some suggested licenses:
# - BSD-3-Clause (default)
# - MIT
# - GPL-2.0-or-later
# - GPL-3.0-only
# - Apache-2.0
# - CC-BY-4.0
license: license (GPL-2.0-or-later, MIT, etc)
min_ansible_version: 2.2
# If this a Container Enabled role, provide the minimum Ansible Container version.
# min_ansible_container_version:
galaxy_tags: []
# List tags for your role here, one per line. A tag is a keyword that describes
# and categorizes the role. Users find roles by searching for tags. Be sure to
# remove the '[]' above, if you add tags to this list.
#
# NOTE: A tag is limited to a single word comprised of alphanumeric characters.
# Maximum 20 tags per role.
dependencies: []
# List your role dependencies here, one per line. Be sure to remove the '[]' above,
# if you add dependencies to this list.
+22
View File
@@ -0,0 +1,22 @@
#SPDX-License-Identifier: MIT-0
---
# tasks file for docker-comic-utils
- name: Run Compose App Init
ansible.builtin.import_role:
name: docker-common
tasks_from: compose-app-init
tags: [create, docker-comic-utils]
- name: Run Compose App Start
ansible.builtin.import_role:
name: docker-common
tasks_from: compose-app-start
tags: [create, docker-comic-utils]
- name: Run Compose App Stop
ansible.builtin.import_role:
name: docker-common
tasks_from: compose-app-stop
tags: [never, stop-docker-comic-utils]
@@ -0,0 +1,60 @@
services:
{{ app_name }}:
image: {{ comicutils_image_name }}
container_name: {{ app_name }}
logging:
options:
max-size: 20m # Reduce log size to 20MB
max-file: "3" # Keep only 3 rotated files
restart: unless-stopped
{% if app_proxy_network is none %}
ports:
- 5577:5577
{% endif %}
networks:
{% if app_proxy_network is not none %}
{{ app_proxy_network }}:
{% else %}
{{ app_name ~ "-net" }}:
{% endif %}
volumes:
- {{ docker_socket_path }}:/tmp/docker.sock:ro
- ./{{ comicutils_config_dir }}:/config
- ./{{ comicutils_cache_dir }}:/cache
## Additional folder is you want to use Folder Monitoring.
- ./{{ comicutils_downloads_dir }}:/downloads
- ./{{ comicutils_data_dir }}:/data
{% for m in comicutils_data_extramounts %}
{{ "- " ~ comicutils_data_extramounts[m] ~ ":/data/" ~ m}}
{% endfor %}
environment:
- FLASK_ENV=development
## Set to 'yes' if you want to use folder monitoring.
- MONITOR=no
## Set the User ID (PUID) and Group ID (PGID) for the container.
## This is often needed to resolve permission issues, especially on systems like Unraid
## where a specific user/group owns the files.
## For Unraid, PUID is typically 99 (user 'nobody') and PGID is typically 100 (group 'users').
## For Windows/WSL, you need to set these to match your Windows user ID (see WINDOWS_WSL_SETUP.md)
- PUID=1000
- PGID=1000
## Set the file creation mask (UMASK). 022 is a common value.
# - UMASK=022
{% if app_proxy_network is not none %}
labels:
traefik.enable: true
traefik.docker.network: "{{ app_proxy_network }}"
traefik.http.routers.{{ app_name }}-http.rule: "Host(`{{ app_base_domain }}`){%- for d in app_extra_domains %}{{ "||Host(`" ~ d ~ "`)" }}{% endfor %}"
traefik.http.routers.{{ app_name }}-http.entryPoints: web
traefik.http.services.{{ app_name }}.loadbalancer.server.port: 5577
{% endif %}
networks:
{% if app_proxy_network is not none %}
{{ app_proxy_network }}:
external: true
{% else %}
{{ app_name ~ "-net" }}:
{% endif %}
+3
View File
@@ -0,0 +1,3 @@
#SPDX-License-Identifier: MIT-0
localhost
+6
View File
@@ -0,0 +1,6 @@
#SPDX-License-Identifier: MIT-0
---
- hosts: localhost
remote_user: root
roles:
- docker-comic-utils
+3
View File
@@ -0,0 +1,3 @@
#SPDX-License-Identifier: MIT-0
---
# vars file for docker-comic-utils
+3
View File
@@ -0,0 +1,3 @@
#SPDX-License-Identifier: MIT-0
---
# defaults file for docker-common
+3
View File
@@ -0,0 +1,3 @@
#SPDX-License-Identifier: MIT-0
---
# handlers file for docker-common
@@ -0,0 +1,14 @@
---
- name: Create app dir {{ app_base_dir }}
ansible.builtin.file:
path: "{{ app_base_dir }}"
state: directory
- name: Write the docker compose file to {{ app_base_dir }}
ansible.builtin.template:
src: docker-compose.j2
dest: "{{ (app_base_dir, 'docker-compose.yaml') | path_join }}"
mode: 0644
owner: matzman
group: matzman
@@ -0,0 +1,10 @@
---
- name: Pull images for {{ app_name }}
community.docker.docker_compose_v2_pull:
project_src: "{{ app_base_dir }}"
- name: create and start docker compose services for {{ app_name }}
community.docker.docker_compose_v2:
project_src: "{{ app_base_dir }}"
@@ -0,0 +1,7 @@
---
- name: stop and remove docker compose services for {{ app_name }}
community.docker.docker_compose_v2:
project_src: "{{ app_base_dir }}"
state: absent
+3
View File
@@ -0,0 +1,3 @@
#SPDX-License-Identifier: MIT-0
---
# tasks file for docker-common
+38
View File
@@ -0,0 +1,38 @@
Role Name
=========
A brief description of the role goes here.
Requirements
------------
Any pre-requisites that may not be covered by Ansible itself or the role should be mentioned here. For instance, if the role uses the EC2 module, it may be a good idea to mention in this section that the boto package is required.
Role Variables
--------------
A description of the settable variables for this role should go here, including any variables that are in defaults/main.yml, vars/main.yml, and any variables that can/should be set via parameters to the role. Any variables that are read from other roles and/or the global scope (ie. hostvars, group vars, etc.) should be mentioned here as well.
Dependencies
------------
A list of other roles hosted on Galaxy should go here, plus any details in regards to parameters that may need to be set for other roles, or variables that are used from other roles.
Example Playbook
----------------
Including an example of how to use your role (for instance, with variables passed in as parameters) is always nice for users too:
- hosts: servers
roles:
- { role: username.rolename, x: 42 }
License
-------
BSD
Author Information
------------------
An optional section for the role authors to include contact information, or a website (HTML is not allowed).
+3
View File
@@ -0,0 +1,3 @@
#SPDX-License-Identifier: MIT-0
---
# defaults file for docker-host
+7
View File
@@ -0,0 +1,7 @@
#SPDX-License-Identifier: MIT-0
---
# handlers file for docker-host
- name: restart docker
ansible.builtin.service:
name: docker
state: restarted
+35
View File
@@ -0,0 +1,35 @@
#SPDX-License-Identifier: MIT-0
galaxy_info:
author: your name
description: your role description
company: your company (optional)
# If the issue tracker for your role is not on github, uncomment the
# next line and provide a value
# issue_tracker_url: http://example.com/issue/tracker
# Choose a valid license ID from https://spdx.org - some suggested licenses:
# - BSD-3-Clause (default)
# - MIT
# - GPL-2.0-or-later
# - GPL-3.0-only
# - Apache-2.0
# - CC-BY-4.0
license: license (GPL-2.0-or-later, MIT, etc)
min_ansible_version: 2.2
# If this a Container Enabled role, provide the minimum Ansible Container version.
# min_ansible_container_version:
galaxy_tags: []
# List tags for your role here, one per line. A tag is a keyword that describes
# and categorizes the role. Users find roles by searching for tags. Be sure to
# remove the '[]' above, if you add tags to this list.
#
# NOTE: A tag is limited to a single word comprised of alphanumeric characters.
# Maximum 20 tags per role.
dependencies: []
# List your role dependencies here, one per line. Be sure to remove the '[]' above,
# if you add dependencies to this list.
@@ -0,0 +1,16 @@
---
- name: Create Docker config directory
ansible.builtin.file:
path: /etc/docker
state: directory
mode: 0755
- name: Write daemon.json
ansible.builtin.template:
src: daemon.j2
dest: /etc/docker/daemon.json
mode: 0644
backup: true
notify: restart docker
+8
View File
@@ -0,0 +1,8 @@
#SPDX-License-Identifier: MIT-0
---
# tasks file for docker-host
- name: Configure Docker Daemon
ansible.builtin.import_tasks: configure-daemon.yml
tags: [create, docker-host]
become: true
+12
View File
@@ -0,0 +1,12 @@
{
"ipv6":true,"fixed-cidr-v6":"fc30:0882:4321:10::/64","ip6tables":true,
"default-address-pools":[
{"base":"172.16.0.0/16","size":24},
{"base":"172.17.0.0/16","size":24},
{"base":"172.18.0.0/16","size":24},
{"base":"172.19.0.0/16","size":24},
{"base":"172.20.0.0/16","size":24},
{"base":"fc30:882:4322::/48","size":64},
{"base":"fc30:882:4323::/48","size":64}
]
}
+3
View File
@@ -0,0 +1,3 @@
#SPDX-License-Identifier: MIT-0
localhost
+6
View File
@@ -0,0 +1,6 @@
#SPDX-License-Identifier: MIT-0
---
- hosts: localhost
remote_user: root
roles:
- docker-host
+3
View File
@@ -0,0 +1,3 @@
#SPDX-License-Identifier: MIT-0
---
# vars file for docker-host
+38
View File
@@ -0,0 +1,38 @@
Role Name
=========
A brief description of the role goes here.
Requirements
------------
Any pre-requisites that may not be covered by Ansible itself or the role should be mentioned here. For instance, if the role uses the EC2 module, it may be a good idea to mention in this section that the boto package is required.
Role Variables
--------------
A description of the settable variables for this role should go here, including any variables that are in defaults/main.yml, vars/main.yml, and any variables that can/should be set via parameters to the role. Any variables that are read from other roles and/or the global scope (ie. hostvars, group vars, etc.) should be mentioned here as well.
Dependencies
------------
A list of other roles hosted on Galaxy should go here, plus any details in regards to parameters that may need to be set for other roles, or variables that are used from other roles.
Example Playbook
----------------
Including an example of how to use your role (for instance, with variables passed in as parameters) is always nice for users too:
- hosts: servers
roles:
- { role: username.rolename, x: 42 }
License
-------
BSD
Author Information
------------------
An optional section for the role authors to include contact information, or a website (HTML is not allowed).
+13
View File
@@ -0,0 +1,13 @@
#SPDX-License-Identifier: MIT-0
---
# defaults file for docker-pihole
app_name: "pihole"
app_dns_name: "pihole"
app_base_dir: "{{ (docker_apps_dir, app_name) | path_join }}"
app_base_domain: "{{ app_dns_name ~ '.' ~ host_base_domain }}"
app_proxy_network: "traefik-proxy-net"
pihole_image_name: "pihole/pihole:latest"
pihole_timezone: "Europe/Vienna"
pihole_webapi_password: "letmein123"
pihole_etc_dir: "pihole-etc"
+3
View File
@@ -0,0 +1,3 @@
#SPDX-License-Identifier: MIT-0
---
# handlers file for docker-pihole
+35
View File
@@ -0,0 +1,35 @@
#SPDX-License-Identifier: MIT-0
galaxy_info:
author: your name
description: your role description
company: your company (optional)
# If the issue tracker for your role is not on github, uncomment the
# next line and provide a value
# issue_tracker_url: http://example.com/issue/tracker
# Choose a valid license ID from https://spdx.org - some suggested licenses:
# - BSD-3-Clause (default)
# - MIT
# - GPL-2.0-or-later
# - GPL-3.0-only
# - Apache-2.0
# - CC-BY-4.0
license: license (GPL-2.0-or-later, MIT, etc)
min_ansible_version: 2.2
# If this a Container Enabled role, provide the minimum Ansible Container version.
# min_ansible_container_version:
galaxy_tags: []
# List tags for your role here, one per line. A tag is a keyword that describes
# and categorizes the role. Users find roles by searching for tags. Be sure to
# remove the '[]' above, if you add tags to this list.
#
# NOTE: A tag is limited to a single word comprised of alphanumeric characters.
# Maximum 20 tags per role.
dependencies: []
# List your role dependencies here, one per line. Be sure to remove the '[]' above,
# if you add dependencies to this list.
+26
View File
@@ -0,0 +1,26 @@
#SPDX-License-Identifier: MIT-0
---
# tasks file for docker-pihole
- name: Run Compose App Init
ansible.builtin.import_role:
name: docker-common
tasks_from: compose-app-init
tags: [create, docker-pihole]
- name: Run Compose App Start
ansible.builtin.import_role:
name: docker-common
tasks_from: compose-app-start
tags: [create, docker-pihole]
- name: "Print API Password"
debug:
msg: "PiHole Web API Password: {{ pihole_webapi_password }}"
tags: [create, docker-pihole]
- name: Run Compose App Stop
ansible.builtin.import_role:
name: docker-common
tasks_from: compose-app-stop
tags: [never, stop-docker-pihole]
@@ -0,0 +1,44 @@
# More info at https://github.com/pi-hole/docker-pi-hole/ and https://docs.pi-hole.net/
services:
{{ app_name }}:
container_name: {{ app_name }}
image: {{ pihole_image_name }}
ports:
# DNS Ports
- "{{ host_ip_addr | ansible.utils.ipaddr }}:53:53/tcp"
- "{{ host_ip_addr | ansible.utils.ipaddr }}:53:53/udp"
{% if app_proxy_network is none %}
- "{{ host_ip_addr | ansible.utils.ipaddr }}:83:80/tcp"
{% endif %}
networks:
{% if app_proxy_network is not none %}
{{ app_proxy_network }}:
{% else %}
{{ app_name ~ "-net" }}:
{% endif %}
environment:
TZ: '{{ pihole_timezone }}'
FTLCONF_webserver_api_password: '{{ pihole_webapi_password }}'
volumes:
- './{{ pihole_etc_dir }}:/etc/pihole'
cap_add:
- CAP_SYS_NICE
restart: unless-stopped
{% if app_proxy_network is not none %}
labels:
traefik.enable: true
traefik.docker.network: "{{ app_proxy_network }}"
traefik.http.routers.{{ app_name }}-http.rule: "Host(`{{ app_base_domain }}`)"
traefik.http.routers.{{ app_name }}-http.entryPoints: web
traefik.http.services.{{ app_name }}.loadbalancer.server.port: 80
{% endif %}
networks:
{% if app_proxy_network is not none %}
{{ app_proxy_network }}:
external: true
{% else %}
{{ app_name ~ "-net" }}:
{% endif %}
+3
View File
@@ -0,0 +1,3 @@
#SPDX-License-Identifier: MIT-0
localhost
+6
View File
@@ -0,0 +1,6 @@
#SPDX-License-Identifier: MIT-0
---
- hosts: localhost
remote_user: root
roles:
- docker-pihole
+3
View File
@@ -0,0 +1,3 @@
#SPDX-License-Identifier: MIT-0
---
# vars file for docker-pihole
+38
View File
@@ -0,0 +1,38 @@
Role Name
=========
A brief description of the role goes here.
Requirements
------------
Any pre-requisites that may not be covered by Ansible itself or the role should be mentioned here. For instance, if the role uses the EC2 module, it may be a good idea to mention in this section that the boto package is required.
Role Variables
--------------
A description of the settable variables for this role should go here, including any variables that are in defaults/main.yml, vars/main.yml, and any variables that can/should be set via parameters to the role. Any variables that are read from other roles and/or the global scope (ie. hostvars, group vars, etc.) should be mentioned here as well.
Dependencies
------------
A list of other roles hosted on Galaxy should go here, plus any details in regards to parameters that may need to be set for other roles, or variables that are used from other roles.
Example Playbook
----------------
Including an example of how to use your role (for instance, with variables passed in as parameters) is always nice for users too:
- hosts: servers
roles:
- { role: username.rolename, x: 42 }
License
-------
BSD
Author Information
------------------
An optional section for the role authors to include contact information, or a website (HTML is not allowed).
@@ -0,0 +1,10 @@
#SPDX-License-Identifier: MIT-0
---
# defaults file for docker-pihole
app_name: "docker-socket-proxy"
app_dns_name: "docker-socket-proxy"
app_base_dir: "{{ (docker_apps_dir, app_name) | path_join }}"
app_base_domain: "{{ app_dns_name ~ '.' ~ host_base_domain }}"
app_proxy_network: "traefik-proxy-net"
dsp_image_name: "ghcr.io/tecnativa/docker-socket-proxy:latest"
@@ -0,0 +1,3 @@
#SPDX-License-Identifier: MIT-0
---
# handlers file for docker-socket-proxy
+35
View File
@@ -0,0 +1,35 @@
#SPDX-License-Identifier: MIT-0
galaxy_info:
author: your name
description: your role description
company: your company (optional)
# If the issue tracker for your role is not on github, uncomment the
# next line and provide a value
# issue_tracker_url: http://example.com/issue/tracker
# Choose a valid license ID from https://spdx.org - some suggested licenses:
# - BSD-3-Clause (default)
# - MIT
# - GPL-2.0-or-later
# - GPL-3.0-only
# - Apache-2.0
# - CC-BY-4.0
license: license (GPL-2.0-or-later, MIT, etc)
min_ansible_version: 2.2
# If this a Container Enabled role, provide the minimum Ansible Container version.
# min_ansible_container_version:
galaxy_tags: []
# List tags for your role here, one per line. A tag is a keyword that describes
# and categorizes the role. Users find roles by searching for tags. Be sure to
# remove the '[]' above, if you add tags to this list.
#
# NOTE: A tag is limited to a single word comprised of alphanumeric characters.
# Maximum 20 tags per role.
dependencies: []
# List your role dependencies here, one per line. Be sure to remove the '[]' above,
# if you add dependencies to this list.
+20
View File
@@ -0,0 +1,20 @@
#SPDX-License-Identifier: MIT-0
---
- name: Run Compose App Init
ansible.builtin.import_role:
name: docker-common
tasks_from: compose-app-init
tags: [create, docker-socket-proxy]
- name: Run Compose App Start
ansible.builtin.import_role:
name: docker-common
tasks_from: compose-app-start
tags: [create, docker-socket-proxy]
- name: Run Compose App Stop
ansible.builtin.import_role:
name: docker-common
tasks_from: compose-app-stop
tags: [never, stop-docker-socket-proxy]
@@ -0,0 +1,40 @@
services:
{{ app_name }}:
image: {{ dsp_image_name }}
container_name: {{ app_name }}
environment:
- CONTAINERS=1 # Allow access to viewing containers
- SERVICES=1 # Allow access to viewing services (necessary when using Docker Swarm)
- TASKS=1 # Allow access to viewing tasks (necessary when using Docker Swarm)
- POST=0 # Disallow any POST operations (effectively read-only)
{% if app_proxy_network is none %}
ports:
- "{{ host_ip_addr}}:2375:2375/tcp"
{% endif %}
networks:
{% if app_proxy_network is not none %}
{{ app_proxy_network }}:
{% else %}
{{ app_name ~ "-net" }}:
{% endif %}
volumes:
- {{ docker_socket_path }}:/var/run/docker.sock:ro # Mounted as read-only
restart: unless-stopped
{% if app_proxy_network is not none %}
labels:
traefik.enable: true
traefik.docker.network: "{{ app_proxy_network }}"
traefik.http.routers.{{ app_name }}-http.rule: "Host(`{{ app_base_domain }}`)"
traefik.http.routers.{{ app_name }}-http.entryPoints: web
traefik.http.services.{{ app_name }}.loadbalancer.server.port: 2375
{% endif %}
networks:
{% if app_proxy_network is not none %}
{{ app_proxy_network }}:
external: true
{% else %}
{{ app_name ~ "-net" }}:
{% endif %}
@@ -0,0 +1,3 @@
#SPDX-License-Identifier: MIT-0
localhost
+6
View File
@@ -0,0 +1,6 @@
#SPDX-License-Identifier: MIT-0
---
- hosts: localhost
remote_user: root
roles:
- docker-socket-proxy
+3
View File
@@ -0,0 +1,3 @@
#SPDX-License-Identifier: MIT-0
---
# vars file for docker-socket-proxy
+38
View File
@@ -0,0 +1,38 @@
Role Name
=========
A brief description of the role goes here.
Requirements
------------
Any pre-requisites that may not be covered by Ansible itself or the role should be mentioned here. For instance, if the role uses the EC2 module, it may be a good idea to mention in this section that the boto package is required.
Role Variables
--------------
A description of the settable variables for this role should go here, including any variables that are in defaults/main.yml, vars/main.yml, and any variables that can/should be set via parameters to the role. Any variables that are read from other roles and/or the global scope (ie. hostvars, group vars, etc.) should be mentioned here as well.
Dependencies
------------
A list of other roles hosted on Galaxy should go here, plus any details in regards to parameters that may need to be set for other roles, or variables that are used from other roles.
Example Playbook
----------------
Including an example of how to use your role (for instance, with variables passed in as parameters) is always nice for users too:
- hosts: servers
roles:
- { role: username.rolename, x: 42 }
License
-------
BSD
Author Information
------------------
An optional section for the role authors to include contact information, or a website (HTML is not allowed).
@@ -0,0 +1,14 @@
#SPDX-License-Identifier: MIT-0
---
app_name: "traefik"
app_dns_name: "traefik"
app_base_dir: "{{ (docker_apps_dir, app_name) | path_join }}"
app_base_domain: "{{ app_dns_name ~ '.' ~ host_base_domain }}"
traefik_image_name: "ghcr.io/traefik/traefik"
traefik_proxy_net: "traefik-proxy-net"
traefik_config_dir: "traefik_config"
traefik_log_dir: "traefik_logs"
traefik_net_ip_addr: "172.31.0.2"
@@ -0,0 +1,3 @@
#SPDX-License-Identifier: MIT-0
---
# handlers file for docker-traefik-proxy
+35
View File
@@ -0,0 +1,35 @@
#SPDX-License-Identifier: MIT-0
galaxy_info:
author: your name
description: your role description
company: your company (optional)
# If the issue tracker for your role is not on github, uncomment the
# next line and provide a value
# issue_tracker_url: http://example.com/issue/tracker
# Choose a valid license ID from https://spdx.org - some suggested licenses:
# - BSD-3-Clause (default)
# - MIT
# - GPL-2.0-or-later
# - GPL-3.0-only
# - Apache-2.0
# - CC-BY-4.0
license: license (GPL-2.0-or-later, MIT, etc)
min_ansible_version: 2.2
# If this a Container Enabled role, provide the minimum Ansible Container version.
# min_ansible_container_version:
galaxy_tags: []
# List tags for your role here, one per line. A tag is a keyword that describes
# and categorizes the role. Users find roles by searching for tags. Be sure to
# remove the '[]' above, if you add tags to this list.
#
# NOTE: A tag is limited to a single word comprised of alphanumeric characters.
# Maximum 20 tags per role.
dependencies: []
# List your role dependencies here, one per line. Be sure to remove the '[]' above,
# if you add dependencies to this list.
@@ -0,0 +1,41 @@
---
- name: Create traefik config dir
ansible.builtin.file:
path: "{{ item }}"
state: directory
loop:
- "{{ (app_base_dir, traefik_config_dir, 'certs') | path_join }}"
- "{{ (app_base_dir, traefik_config_dir, 'letsencrypt') | path_join }}"
- "{{ (app_base_dir, traefik_config_dir, 'plugins') | path_join }}"
- "{{ (app_base_dir, traefik_config_dir, 'rules') | path_join }}"
- "{{ (app_base_dir, traefik_config_dir, 'static') | path_join }}"
- name: Write traefik config files
ansible.builtin.template:
src: "{{ item.src }}"
dest: "{{ item.dest }}"
mode: 0644
owner: matzman
group: matzman
loop:
- { src: "static_traefik.j2", dest: "{{ (app_base_dir, traefik_config_dir, 'static', 'traefik.yml') | path_join }}" }
- { src: "rules_dashboard.j2", dest: "{{ (app_base_dir, traefik_config_dir, 'rules', 'dashboard.yml') | path_join }}" }
- { src: "rules_middleware.j2", dest: "{{ (app_base_dir, traefik_config_dir, 'rules', 'middleware.yml') | path_join }}" }
- name: Create traefik-proxy net
community.docker.docker_network:
name: "{{ traefik_proxy_net }}"
driver: bridge
enable_ipv6: true
ipam_config:
- subnet: 172.31.0.0/16
gateway: 172.31.0.1
iprange: 172.31.128.0/17
- subnet: fc30:0882:4324:1::/64
gateway: fc30:0882:4324:1::1
iprange: fc30:0882:4324:1:8000::/65
driver_options:
com.docker.network.bridge.name: br-traefik0
+25
View File
@@ -0,0 +1,25 @@
#SPDX-License-Identifier: MIT-0
---
- name: Run Compose App Init
ansible.builtin.import_role:
name: docker-common
tasks_from: compose-app-init
tags: [create, docker-traefik-proxy]
- name: Create Docker App
ansible.builtin.import_tasks: create-app.yml
tags: [create, docker-traefik-proxy]
become: true
- name: Run Compose App Start
ansible.builtin.import_role:
name: docker-common
tasks_from: compose-app-start
tags: [create, docker-traefik-proxy]
- name: Run Compose App Stop
ansible.builtin.import_role:
name: docker-common
tasks_from: compose-app-stop
tags: [never, stop-docker-traefik-proxy]
@@ -0,0 +1,26 @@
services:
{{ app_name }}:
image: {{ traefik_image_name }}
container_name: {{ app_name }}
restart: unless-stopped
ports:
- 80:80
- 443:443
command:
- --configFile=/etc/traefik/traefik.yml
volumes:
- {{ docker_socket_path }}:/var/run/docker.sock:ro
- ./{{ traefik_config_dir }}/static:/etc/traefik # For traefik.yml
- ./{{ traefik_config_dir }}/rules:/rules # For dynamic configurations
- ./{{ traefik_config_dir }}/letsencrypt:/letsencrypt
- ./{{ traefik_config_dir }}/plugins:/plugins-storage # For Traefik v2 plugins
- ./{{ traefik_log_dir }}:/logfiles
networks:
{{ traefik_proxy_net }}:
ipv4_address: {{ traefik_net_ip_addr }}
networks:
{{ traefik_proxy_net }}:
external: true
@@ -0,0 +1,16 @@
http:
routers:
traefik-dashboard:
rule: Host(`{{ app_base_domain }}`)&&PathPrefix(`/`)
entrypoints:
- web
- websecure
service: dashboard@internal
priority: 10
traefik-api:
rule: Host(`{{ app_base_domain }}`)&&PathPrefix(`/api`)
entrypoints:
- web
- websecure
service: api@internal
priority: 15
@@ -0,0 +1,6 @@
http:
middlewares:
httpsredirect:
redirectScheme:
scheme: https
permanent: true
@@ -0,0 +1,49 @@
global:
sendanonymoususage: false
api:
dashboard: true
disabledashboardad: false
insecure: false
log:
level: INFO
filePath: "/logfiles/traefik.log"
format: common
accesslog:
filePath: "/logfiles/access-log.json"
format: json
fields:
headers:
defaultMode: keep
#tracing:
# otlp:
# http:
# endpoint: http://opentelemetry-collector:4318/v1/traces
entryPoints:
web:
address: ":80"
observability:
accessLogs: false
websecure:
address: ":443"
http:
tls: true
observability:
accessLogs: false
providers:
docker:
exposedByDefault: false
network: "{{ traefik_proxy_net }}"
file:
directory: /rules
watch: true
experimental:
plugins:
rewriteHeaders:
modulename: "github.com/vincentinttsh/rewriteheaders"
version: "v1.0.0"
@@ -0,0 +1,3 @@
#SPDX-License-Identifier: MIT-0
localhost
@@ -0,0 +1,6 @@
#SPDX-License-Identifier: MIT-0
---
- hosts: localhost
remote_user: root
roles:
- docker-traefik-proxy
+3
View File
@@ -0,0 +1,3 @@
#SPDX-License-Identifier: MIT-0
---
# vars file for docker-traefik-proxy
@@ -0,0 +1,16 @@
#SPDX-License-Identifier: MIT-0
---
# SSH port allowed through INPUT chain
firewall_ssh_port: 22
# Additional host-level ports to allow through INPUT chain
firewall_allowed_tcp_ports: []
firewall_allowed_udp_ports: []
# Ports to allow through to Docker containers via DOCKER-USER chain
docker_user_allowed_tcp_ports: []
docker_user_allowed_udp_ports: []
wg_if: wg0
@@ -0,0 +1,28 @@
#SPDX-License-Identifier: MIT-0
---
- name: Reload iptables
ansible.builtin.service:
name: netfilter-persistent
state: restarted
- name: Reload ip6tables
ansible.builtin.service:
name: netfilter-persistent
state: restarted
- name: Restart wg0
ansible.builtin.systemd:
name: wg-quick@wg0
state: restarted
become: true
- name: Restart SSH
ansible.builtin.service:
name: ssh
state: restarted
- name: Restart Docker
ansible.builtin.service:
name: docker
state: restarted
@@ -0,0 +1,52 @@
---
- name: Ensure dependencies are installed
ansible.builtin.package:
name:
- curl
- ca-certificates
- python3-requests
state: present
- name: Create Docker GPG key directory
ansible.builtin.file:
path: /etc/apt/keyrings
state: directory
mode: "0755"
- name: Download Docker's official GPG key
ansible.builtin.get_url:
url: https://download.docker.com/linux/ubuntu/gpg
dest: /etc/apt/keyrings/docker.asc
mode: "0644"
- name: Add Docker repository to Apt sources
ansible.builtin.apt_repository:
repo: "deb [signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu {{ ansible_facts['distribution_release'] }} stable"
state: present
filename: docker
- name: Update apt cache after adding Docker repository
ansible.builtin.apt:
update_cache: yes
- name: Install Docker and Docker Compose
ansible.builtin.package:
name:
- docker-ce
- docker-ce-cli
- containerd.io
- docker-buildx-plugin
- docker-compose-plugin
state: present
- name: Ensure Docker service is enabled and started
ansible.builtin.service:
name: docker
state: started
enabled: yes
- name: Add matzman user to docker group
ansible.builtin.user:
name: matzman
groups: docker
append: yes
+13
View File
@@ -0,0 +1,13 @@
#SPDX-License-Identifier: MIT-0
---
# tasks file for ubuntu-docker-base
- name: Setup Ubuntu for Docker host
ansible.builtin.import_tasks: setup-ubuntu.yml
tags: [ setup-ubuntu ]
become: true
- name: Install Docker on Ubuntu
ansible.builtin.import_tasks: install-ubuntu-docker.yml
tags: [ install-ubuntu-docker-base ]
become: true
@@ -0,0 +1,209 @@
---
- name: Show host IP
ansible.builtin.debug:
msg: "{{ ansible_facts['default_ipv4'] }}"
# --- Users & group ---
- name: Add group matzman
ansible.builtin.group:
name: matzman
state: present
gid: 1000
- name: Add user matzman
ansible.builtin.user:
name: matzman
uid: 1000
group: matzman
create_home: yes
# --- Install required packages ---
- name: Update apt cache
ansible.builtin.apt:
update_cache: yes
become: true
- name: Upgrade all packages
ansible.builtin.apt:
upgrade: dist
update_cache: yes
- name: Check if reboot is required
ansible.builtin.stat:
path: /var/run/reboot-required
register: reboot_required
- name: Reboot if required
ansible.builtin.reboot:
reboot_timeout: 300
when: reboot_required.stat.exists
- name: Install custom packages
ansible.builtin.package:
name:
# Required by an ansible task later
- python3-requests
state: present
# --- Unattended upgrades ---
- name: Install unattended-upgrades
ansible.builtin.package:
name:
- unattended-upgrades
- apt-listchanges
state: present
- name: Enable automatic security upgrades
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"
# --- SSH setup ---
- name: Set authorized key for matzman
ansible.posix.authorized_key:
user: matzman
state: present
key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINBi8TS/s2X7W7gb+rGm7A2PG9hRDLa3kYdNM9hLNY0w matzman+2025@matzman.net"
- name: Set authorized key for root
ansible.posix.authorized_key:
user: root
state: present
key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINBi8TS/s2X7W7gb+rGm7A2PG9hRDLa3kYdNM9hLNY0w matzman+2025@matzman.net"
# --- SSH hardening ---
- name: Disable SSH password authentication
ansible.builtin.lineinfile:
path: /etc/ssh/sshd_config
regexp: '^#?PasswordAuthentication'
line: 'PasswordAuthentication no'
notify: Restart SSH
#- name: Disable SSH root login
# ansible.builtin.lineinfile:
# path: /etc/ssh/sshd_config
# regexp: '^#?PermitRootLogin'
# line: 'PermitRootLogin no'
# notify: Restart SSH
# --- fail2ban ---
- name: Install fail2ban
ansible.builtin.package:
name: fail2ban
state: present
- name: Enable and start fail2ban
ansible.builtin.service:
name: fail2ban
state: started
enabled: yes
# --- Wireguard ---
- name: Install wireguard packages
ansible.builtin.package:
name:
- wireguard-tools
state: present
- name: Ensure /etc/wireguard directory exists
ansible.builtin.file:
path: /etc/wireguard
state: directory
owner: root
group: root
mode: "0700"
tags: wireguard
- name: "Deploy {{ wg_if }} config"
ansible.builtin.template:
src: "{{ wg_if }}.conf.j2"
dest: "/etc/wireguard/{{ wg_if }}.conf"
owner: root
group: root
mode: "0600"
notify: Restart wg0
tags: wireguard
- name: "Enable and start wg-quick@{{ wg_if }}"
ansible.builtin.systemd:
name: "wg-quick@{{ wg_if }}"
enabled: yes
state: started
tags: wireguard
# --- Firewall ---
- name: Install iptables-persistent
ansible.builtin.package:
name:
- iptables-persistent
- netfilter-persistent
state: present
- name: Deploy iptables rules (IPv4)
ansible.builtin.template:
src: rules.v4.j2
dest: /etc/iptables/rules.v4
mode: "0640"
notify:
- Reload iptables
- Restart Docker
- name: Deploy iptables rules (IPv6)
ansible.builtin.template:
src: rules.v6.j2
dest: /etc/iptables/rules.v6
mode: "0640"
notify:
- Reload ip6tables
- Restart Docker
# --- sysctl hardening ---
- name: Configure sysctl security settings
ansible.posix.sysctl:
name: "{{ item.name }}"
value: "{{ item.value }}"
state: present
reload: yes
loop:
- { name: 'net.ipv4.conf.all.rp_filter', value: '1' }
- { name: 'net.ipv4.conf.default.rp_filter', value: '1' }
- { name: 'net.ipv4.conf.all.accept_redirects', value: '0' }
- { name: 'net.ipv4.conf.default.accept_redirects', value: '0' }
- { name: 'net.ipv4.conf.all.send_redirects', value: '0' }
- { name: 'net.ipv4.conf.default.send_redirects', value: '0' }
# --- Audit logging ---
- name: Install auditd
ansible.builtin.package:
name: auditd
state: present
- name: Enable and start auditd
ansible.builtin.service:
name: auditd
state: started
enabled: yes
@@ -0,0 +1,55 @@
# Managed by Ansible — do not edit manually
*filter
:INPUT DROP [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:DOCKER-USER - [0:0]
# --- INPUT ---
# Allow loopback
-A INPUT -i lo -j ACCEPT
# Allow established/related connections
-A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# Allow SSH
-A INPUT -p tcp --dport {{ firewall_ssh_port }} -j ACCEPT
# Allow additional host ports
{% for port in firewall_allowed_tcp_ports %}
-A INPUT -p tcp --dport {{ port }} -j ACCEPT
{% endfor %}
{% for port in firewall_allowed_udp_ports %}
-A INPUT -p udp --dport {{ port }} -j ACCEPT
{% endfor %}
# --- DOCKER-USER ---
# Allow loopback
-A DOCKER-USER -i lo -j RETURN
# Allow outgoing from Docker IP range
-A DOCKER-USER -s 172.16.0.0/12 -j RETURN
# Whitelist specific TCP ports to containers
{% for port in docker_user_allowed_tcp_ports %}
-A DOCKER-USER -p tcp --dport {{ port }} -j RETURN
{% endfor %}
# Whitelist specific UDP ports to containers
{% for port in docker_user_allowed_udp_ports %}
-A DOCKER-USER -p udp --dport {{ port }} -j RETURN
{% endfor %}
# Allow all already established connections
-A DOCKER-USER -m conntrack --ctstate RELATED,ESTABLISHED -j RETURN
# Drop everything else to containers
-A DOCKER-USER -j DROP
COMMIT
@@ -0,0 +1,55 @@
# Managed by Ansible — do not edit manually
*filter
:INPUT DROP [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:DOCKER-USER - [0:0]
# --- INPUT ---
# Allow loopback
-A INPUT -i lo -j ACCEPT
# Allow established/related connections
-A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# Allow SSH
-A INPUT -p tcp --dport {{ firewall_ssh_port }} -j ACCEPT
# Allow additional host ports
{% for port in firewall_allowed_tcp_ports %}
-A INPUT -p tcp --dport {{ port }} -j ACCEPT
{% endfor %}
{% for port in firewall_allowed_udp_ports %}
-A INPUT -p udp --dport {{ port }} -j ACCEPT
{% endfor %}
# --- DOCKER-USER ---
# Allow loopback
-A DOCKER-USER -i lo -j RETURN
# Allow outgoing from Docker IP range
-A DOCKER-USER -s 172.16.0.0/12 -j RETURN
# Whitelist specific TCP ports to containers
{% for port in docker_user_allowed_tcp_ports %}
-A DOCKER-USER -p tcp --dport {{ port }} -j RETURN
{% endfor %}
# Whitelist specific UDP ports to containers
{% for port in docker_user_allowed_udp_ports %}
-A DOCKER-USER -p udp --dport {{ port }} -j RETURN
{% endfor %}
# Allow all already established connections
-A DOCKER-USER -m conntrack --ctstate RELATED,ESTABLISHED -j RETURN
# Drop everything else to containers
-A DOCKER-USER -j DROP
COMMIT
@@ -0,0 +1,23 @@
# Managed by Ansible — do not edit manually
[Interface]
Address = {{ wg_nets[wg_if].hosts[inventory_hostname].address }}
ListenPort = {{ wg_nets[wg_if].hosts[inventory_hostname].port }}
PrivateKey = {{ wg_nets[wg_if].secrect[inventory_hostname].private_key }}
{% if wg_nets[wg_if].hosts[inventory_hostname].dnsserver is defined %}
DNS = {{ wg_nets[wg_if].hosts[inventory_hostname].dnsserver }}
{% endif %}
{% for peer, data in wg_nets[wg_if].hosts[inventory_hostname].peers.items() %}
# {{ peer }}
[Peer]
PublicKey = {{ wg_nets[wg_if].hosts[peer].public_key }}
AllowedIPs = {{ data.allowed_ips }}
{% if data.preshared_key is defined %}
PresharedKey = {{ data.preshared_key }}
{% endif %}
{% if data.keepalive is defined %}
PersistentKeepalive = {{ data.keepalive }}
{% endif %}
{% endfor %}
+23
View File
@@ -0,0 +1,23 @@
#SPDX-License-Identifier: MIT-0
---
wireguard_port: 51820
wireguard_interface: wg0
# Server private key — store in Ansible Vault in host_vars
# wireguard_private_key: "YOUR_PRIVATE_KEY"
# Server address in the WireGuard subnet, e.g. "10.0.0.1/24"
# wireguard_address: "10.0.0.1/24"
# Optional: DNS server pushed to clients
# wireguard_dns: "1.1.1.1"
# Peers — defined per host in host_vars
# wireguard_peers:
# - name: client1
# public_key: "CLIENT_PUBLIC_KEY"
# allowed_ips: "10.0.0.2/32"
# - name: client2
# public_key: "CLIENT_PUBLIC_KEY"
# allowed_ips: "10.0.0.3/32"
wireguard_peers: []
+7
View File
@@ -0,0 +1,7 @@
#SPDX-License-Identifier: MIT-0
---
- name: Restart wg0
ansible.builtin.systemd:
name: wg-quick@wg0
state: restarted
become: true
+33
View File
@@ -0,0 +1,33 @@
#SPDX-License-Identifier: MIT-0
---
- name: Install wireguard-tools
ansible.builtin.package:
name: wireguard-tools
state: present
become: true
- name: Ensure /etc/wireguard directory exists
ansible.builtin.file:
path: /etc/wireguard
state: directory
owner: root
group: root
mode: "0700"
become: true
- name: Deploy wg0 config
ansible.builtin.template:
src: wg0.conf.j2
dest: /etc/wireguard/wg0.conf
owner: root
group: root
mode: "0600"
become: true
notify: Restart wg0
- name: Enable and start wg-quick@wg0
ansible.builtin.systemd:
name: wg-quick@wg0
enabled: yes
state: started
become: true
+22
View File
@@ -0,0 +1,22 @@
# Managed by Ansible — do not edit manually
[Interface]
Address = {{ wireguard_address }}
ListenPort = {{ wireguard_port }}
PrivateKey = {{ wireguard_private_key }}
{% if wireguard_dns is defined %}
DNS = {{ wireguard_dns }}
{% endif %}
{% for peer in wireguard_peers %}
# {{ peer.name }}
[Peer]
PublicKey = {{ peer.public_key }}
AllowedIPs = {{ peer.allowed_ips }}
{% if peer.preshared_key is defined %}
PresharedKey = {{ peer.preshared_key }}
{% endif %}
{% if peer.keepalive is defined %}
PersistentKeepalive = {{ peer.keepalive }}
{% endif %}
{% endfor %}
+13
View File
@@ -0,0 +1,13 @@
# This is your main playbook you will run with:
# ansible-playbook site.yml
# You can kick off everything from this playbook.
# Or, you can create separate playbooks in this directory for specific orchestration events.
---
- name: apply common configuration to all nodes
hosts: all
user: root
roles:
- common
+46
View File
@@ -0,0 +1,46 @@
---
- hosts: vserver1.matzman.net
roles:
- role: ubuntu-docker-host
vars:
firewall_allowed_tcp_ports:
- 80
- 443
firewall_allowed_udp_ports: []
docker_user_allowed_tcp_ports:
- 80
- 443
docker_user_allowed_udp_ports: []
wg_nets:
wg0:
secrect:
vserver1.matzman.net:
private_key: "oJOaTfNDU5dxj3aUpTOHE98FCg/Dx4agwV6pXg8OTWc="
hosts:
vserver1.matzman.net:
address: "10.0.0.1/24"
port: 51432
public_key: "IGo70n2CfouTLUSrzqRiCfU9iU++sJ1cJSuPO6tsoGw="
endpoint: "vserver.matzman.net"
peers:
client1:
allowed_ips: "10.0.0.2/32"
client1:
address: "10.0.0.2/24"
public_key: "IGo70n2CfouTLUSrzqRiCfU9iU++sJ1cJSuPO6tsoGw="
peers:
vserver1.matzman.net:
allowed_ips: "0.0.0.0/0"
- role: docker-host
- role: docker-traefik-proxy
vars:
app_name: "traefik-vserver1"
- role: docker-arcane
vars:
app_name: "arcane-vserver1"
- role: docker-socket-proxy
+5
View File
@@ -0,0 +1,5 @@
localhost ansible_connection=local ansible_python_interpreter="{{ansible_playbook_python}}" host_ip_addr="10.61.1.20" host_base_domain="localhost"
[vhosts]
vserver1.matzman.net ansible_connection=ssh ansible_user=root host_ip_addr="185.242.113.24" host_base_domain="vserver1.matzman.net"