Ansiblify my VPS setup
This commit is contained in:
parent
c9fe87cd0e
commit
9c9ef9f4c7
119
.ansible-lint
Normal file
119
.ansible-lint
Normal file
|
@ -0,0 +1,119 @@
|
|||
---
|
||||
# .ansible-lint
|
||||
|
||||
profile: null # min, basic, moderate,safety, shared, production
|
||||
|
||||
# exclude_paths included in this file are parsed relative to this file's location
|
||||
# and not relative to the CWD of execution. CLI arguments passed to the --exclude
|
||||
# option are parsed relative to the CWD of execution.
|
||||
exclude_paths:
|
||||
- .cache/ # implicit unless exclude_paths is defined in config
|
||||
- .github/
|
||||
- test/fixtures/formatting-before/
|
||||
- test/fixtures/formatting-prettier/
|
||||
# parseable: true
|
||||
# quiet: true
|
||||
# strict: true
|
||||
# verbosity: 1
|
||||
|
||||
# Mock modules or roles in order to pass ansible-playbook --syntax-check
|
||||
mock_modules:
|
||||
- zuul_return
|
||||
# note the foo.bar is invalid as being neither a module or a collection
|
||||
- fake_namespace.fake_collection.fake_module
|
||||
- fake_namespace.fake_collection.fake_module.fake_submodule
|
||||
mock_roles:
|
||||
- mocked_role
|
||||
- author.role_name # old standalone galaxy role
|
||||
- fake_namespace.fake_collection.fake_role # role within a collection
|
||||
|
||||
# Enable checking of loop variable prefixes in roles
|
||||
# loop_var_prefix: "{role}_"
|
||||
|
||||
# Enforce variable names to follow pattern below, in addition to Ansible own
|
||||
# requirements, like avoiding python identifiers. To disable add `var-naming`
|
||||
# to skip_list.
|
||||
# var_naming_pattern: "^[a-z_][a-z0-9_]*$"
|
||||
|
||||
use_default_rules: true
|
||||
# Load custom rules from this specific folder
|
||||
# rulesdir:
|
||||
# - ./rule/directory/
|
||||
|
||||
# Ansible-lint completely ignores rules or tags listed below
|
||||
# skip_list:
|
||||
# - skip_this_tag
|
||||
|
||||
# Ansible-lint does not automatically load rules that have the 'opt-in' tag.
|
||||
# You must enable opt-in rules by listing each rule 'id' below.
|
||||
enable_list:
|
||||
- empty-string-compare # opt-in
|
||||
- no-log-password # opt-in
|
||||
- no-same-owner # opt-in
|
||||
# add yaml here if you want to avoid ignoring yaml checks when yamllint
|
||||
# library is missing. Normally its absence just skips using that rule.
|
||||
- yaml
|
||||
# Report only a subset of tags and fully ignore any others
|
||||
# tags:
|
||||
# - jinja[spacing]
|
||||
|
||||
# Ansible-lint does not fail on warnings from the rules or tags listed below
|
||||
warn_list:
|
||||
- skip_this_tag
|
||||
- experimental # experimental is included in the implicit list
|
||||
- no-changed-when
|
||||
- latest[git]
|
||||
# - role-name
|
||||
# - yaml[document-start] # you can also use sub-rule matches
|
||||
|
||||
# skip_list:
|
||||
# - fqcn[action-core]
|
||||
# - fqcn[action]
|
||||
|
||||
# Some rules can transform files to fix (or make it easier to fix) identified
|
||||
# errors. `ansible-lint --write` will reformat YAML files and run these transforms.
|
||||
# By default it will run all transforms (effectively `write_list: ["all"]`).
|
||||
# You can disable running transforms by setting `write_list: ["none"]`.
|
||||
# Or only enable a subset of rule transforms by listing rules/tags here.
|
||||
# write_list:
|
||||
# - all
|
||||
|
||||
# Offline mode disables installation of requirements.yml
|
||||
offline: false
|
||||
|
||||
# Return success if number of violations compared with previous git
|
||||
# commit has not increased. This feature works only in git
|
||||
# repositories.
|
||||
progressive: false
|
||||
|
||||
# Define required Ansible's variables to satisfy syntax check
|
||||
extra_vars:
|
||||
foo: bar
|
||||
multiline_string_variable: |
|
||||
line1
|
||||
line2
|
||||
complex_variable: ":{;\t$()"
|
||||
|
||||
# Uncomment to enforce action validation with tasks, usually is not
|
||||
# needed as Ansible syntax check also covers it.
|
||||
# skip_action_validation: false
|
||||
|
||||
# List of additional kind:pattern to be added at the top of the default
|
||||
# match list, first match determines the file kind.
|
||||
kinds:
|
||||
# - playbook: "**/examples/*.{yml,yaml}"
|
||||
# - galaxy: "**/folder/galaxy.yml"
|
||||
# - tasks: "**/tasks/*.yml"
|
||||
# - vars: "**/vars/*.yml"
|
||||
# - meta: "**/meta/main.yml"
|
||||
- yaml: "**/*.yaml-too"
|
||||
|
||||
# List of additional collections to allow in only-builtins rule.
|
||||
# only_builtins_allow_collections:
|
||||
# - example_ns.example_collection
|
||||
|
||||
# List of additions modules to allow in only-builtins rule.
|
||||
# only_builtins_allow_modules:
|
||||
# - example_module
|
||||
|
||||
# vim:ft=yaml
|
5
ansible.cfg
Normal file
5
ansible.cfg
Normal file
|
@ -0,0 +1,5 @@
|
|||
[defaults]
|
||||
remote_user = sysadm
|
||||
remote_tmp = /tmp/.ansible
|
||||
inventory = inventory
|
||||
use_persistent_connections = True
|
47
group_vars/all/secrets.yml
Normal file
47
group_vars/all/secrets.yml
Normal file
|
@ -0,0 +1,47 @@
|
|||
$ANSIBLE_VAULT;1.1;AES256
|
||||
30376133336133396666636131316435356262663762386235616334333965633165326338363065
|
||||
6334346230333564663066353962643833613634663833630a383831393035343730653564373266
|
||||
63363266653965626363656139316632326233623038333139343838326366663333623464666663
|
||||
6131363263653164320a663930323534613661623965656164613431626266363834646665326434
|
||||
66633538623733386335376432326462666265353864373734323833396132663539636363613765
|
||||
32303535663436626464336636313964633764303163666135303333616261316438326462666261
|
||||
31643736376561313865393838636433376232653666366631363866326432303231373838393262
|
||||
61376137393861346231313735626235366337306633653961613330323364333164633835333639
|
||||
39653161636132663661613838343861303364666537383237306632636131316334666263613934
|
||||
64373630396232613436643235626262656630343130363866313334633466316266356231373035
|
||||
36636161633233313661303162333165306331313633666131643333373765336637643562373833
|
||||
34626261353161656135653033623036633231656362653537323361323763333937353631373032
|
||||
66613939643161666535356139353139303734393237333135623166323331663137343737616630
|
||||
65643962356466616261383638616337383932653066303836643738646237666138643566333263
|
||||
62653335643436333161643562613837343166393732373262323362346162353164353230663730
|
||||
30303730306235333039623839366466663565386266386262326333643536643334613665633266
|
||||
63656666633137386235626531396535623030333834623337343862653432373035376630633264
|
||||
39323263353864376537666565636631396563626266396131383265653262343664636463396565
|
||||
31343437313731613130623131636234343263323836316232316362396636313931326531383266
|
||||
36323133646365636635363264646232363233343366636563353163326361336531376438303163
|
||||
37383234323765633039393164623035363935383333383537396639626636633262653561633734
|
||||
64653766336439343963646264616362396264393765656632363233376437373864323837323466
|
||||
65326532623033346331643130376632643538643939313961326465623636343332396533326565
|
||||
31336665613431366439663765326239336365316539303164633333613965643162643362666363
|
||||
65353339663436393462646338646535613166303833346330613265316266343935333339323865
|
||||
37356164623632376532623635616239313735663337613139633332346634386535353036656136
|
||||
38313262653366363933383632623831636566363765663737653637316661343061646238613062
|
||||
36646630393164323363373635343762393334626232363864373266653031346435663033616564
|
||||
66313534633236306533373832343136393334303364396130653763353530323936663263636239
|
||||
34623664643061353362346535373965626133613737303632656336633639373338353837643233
|
||||
36366233623837383461336365343136376134333433373037656533313431336136333234373134
|
||||
33356362633665643337353339643632633439616663313564616165333761316262353933303235
|
||||
37393738386165333362326535626336393339353863663831663363366137643638643938636362
|
||||
31623165323561376665393965613332616365393732333365376566316364653837656238383565
|
||||
61666238626564303239383036373437613630663366383931616661303338336363393264323566
|
||||
61396639383735326532343139316134616636663939626463376639336434343238653333336337
|
||||
32643331616537663362383932343735623861623534346235623337393535343761316463373234
|
||||
39356363343730633437363131623538346534653839313031363936363131653937346131396136
|
||||
30326331326261646664303530346133323134613466323536323935646164353162663836643166
|
||||
31393761333838363834663832636335356138663064313431333836613735343064333262306239
|
||||
62333365356134346433633335396565323136303435656132396434653937303032383938643466
|
||||
62353563323036346431643663623938333333353665646361313237643861303562663062353362
|
||||
61303539306164333935626561393963633631306265313665373262303636383664363034383639
|
||||
64313832623038653266353432353662326433363033373466356461323330623139393632653933
|
||||
36383865343933393531306638376635666337653234363437313962373938333139383637323837
|
||||
6364356630343237313161353266323864616365336631353062
|
23
group_vars/all/vars.yml
Normal file
23
group_vars/all/vars.yml
Normal file
|
@ -0,0 +1,23 @@
|
|||
# vim: ft=yaml.ansible
|
||||
---
|
||||
hostname: cpx
|
||||
timezone: Europe/Berlin
|
||||
|
||||
users:
|
||||
- name: sysadm
|
||||
comment: System Administration
|
||||
password: $6$Q2WHaFPAPgndQSz4$F6py94HemVpE/cgtTU0cRKkI/Si5Vjl/aSCniVr8WtbkViBOtt.dpDDWwhjbOOX/o6R22w1tFiciBmF.UA9HH0
|
||||
groups:
|
||||
- sudo
|
||||
ssh_keys:
|
||||
- sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIFWZGLov8wPBNxuvnaPK+8vv6wK5hHUVEFzXKsN9QeuBAAAADHNzaDpzYW1zYXB0aQ== ssh:samsapti
|
||||
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPd/4fQV7CL8/KVwbo/phiV5UdXFBIDlkZ+ps8C7FeRf cardno:14 336 332
|
||||
|
||||
- name: cicd
|
||||
comment: CI/CD user
|
||||
password: '!'
|
||||
groups: []
|
||||
ssh_keys:
|
||||
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBN7XhL364LZ4rnEnmpV59Qehw3ldqEb7XX5DWTAb/XH cicd
|
||||
- sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIFWZGLov8wPBNxuvnaPK+8vv6wK5hHUVEFzXKsN9QeuBAAAADHNzaDpzYW1zYXB0aQ== ssh:samsapti
|
||||
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPd/4fQV7CL8/KVwbo/phiV5UdXFBIDlkZ+ps8C7FeRf cardno:14 336 332
|
2
inventory
Normal file
2
inventory
Normal file
|
@ -0,0 +1,2 @@
|
|||
# CPX21
|
||||
cpx.servers.sapti.me ansible_python_interface=/usr/bin/python3
|
13
playbook.yml
Normal file
13
playbook.yml
Normal file
|
@ -0,0 +1,13 @@
|
|||
# vim: ft=yaml.ansible
|
||||
---
|
||||
- name: Deploy self-hosted services
|
||||
hosts: all
|
||||
gather_facts: true
|
||||
become: true
|
||||
roles:
|
||||
- role: os_config
|
||||
tags:
|
||||
- os
|
||||
- role: docker_services
|
||||
tags:
|
||||
- docker
|
57
provision.sh
Executable file
57
provision.sh
Executable file
|
@ -0,0 +1,57 @@
|
|||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
usage() {
|
||||
printf '%s\n' "Usage:"
|
||||
printf '$ %s\n' "$0 [-h|--help]"
|
||||
printf '$ %s\n' "$0 os"
|
||||
printf '$ %s\n' "$0 docker"
|
||||
printf '$ %s\n' "$0 users [-i|--init]"
|
||||
printf '$ %s\n' "$0 reboot [-f|--force]"
|
||||
printf '$ %s\n' "$0 services [SINGLE_SERVICE]"
|
||||
}
|
||||
|
||||
install_modules() {
|
||||
if [ -z "$(ansible-galaxy collection list community.general 2>/dev/null)" ]; then
|
||||
ansible-galaxy collection install community.general
|
||||
fi
|
||||
}
|
||||
|
||||
cd "$(dirname "$0")" || exit 255
|
||||
BASE_CMD="ansible-playbook playbook.yml --ask-vault-pass --ask-become-pass"
|
||||
|
||||
case $1 in
|
||||
"")
|
||||
install_modules; $BASE_CMD ;;
|
||||
os|docker)
|
||||
install_modules; $BASE_CMD --tags "$1" ;;
|
||||
users)
|
||||
install_modules
|
||||
if [ "$2" = "-i" ] || [ "$2" = "--init" ]; then
|
||||
$BASE_CMD --user root --tags "$1"
|
||||
else
|
||||
$BASE_CMD --tags "$1"
|
||||
fi
|
||||
;;
|
||||
reboot)
|
||||
install_modules
|
||||
if [ "$2" = "-f" ] || [ "$2" = "--force" ]; then
|
||||
$BASE_CMD --tags "$1" --extra-vars "force_reboot=true"
|
||||
else
|
||||
$BASE_CMD --tags "$1" --extra-vars "reboot=true"
|
||||
fi
|
||||
;;
|
||||
services)
|
||||
install_modules
|
||||
if [ -z "$2" ]; then
|
||||
$BASE_CMD --tags "$1"
|
||||
else
|
||||
$BASE_CMD --tags "$1" --extra-vars "single_service=$2"
|
||||
fi
|
||||
;;
|
||||
-h|--help)
|
||||
usage ;;
|
||||
*)
|
||||
usage >&2; exit 1 ;;
|
||||
esac
|
44
roles/docker_services/defaults/main.yml
Normal file
44
roles/docker_services/defaults/main.yml
Normal file
|
@ -0,0 +1,44 @@
|
|||
# vim: ft=yaml.ansible
|
||||
---
|
||||
base_domain: sapti.me
|
||||
base_volume: /opt/docker
|
||||
|
||||
services:
|
||||
caddy:
|
||||
volume: "{{ base_volume }}/caddy"
|
||||
version: 2-alpine
|
||||
|
||||
jitsi_meet:
|
||||
domain: meet.{{ base_domain }}
|
||||
volume: "{{ base_volume }}/jitsi-meet"
|
||||
version: stable
|
||||
|
||||
lingva:
|
||||
domain: translate.{{ base_domain }}
|
||||
onion: 22qfd63ax4zt5arctpfh62kvjekap7yrdfzwq5kv5jvhew5hcpq6vgyd.onion
|
||||
version: latest
|
||||
|
||||
samsapti_dev:
|
||||
domain: samsapti.dev
|
||||
onion: mldhltdackluvnqso7vk2azcg3ghjxbpw4im6alubymqkonb4kppqcqd.onion
|
||||
volume: "{{ base_volume }}/samsapti.dev"
|
||||
version: 1-alpine
|
||||
|
||||
searxng:
|
||||
domain: search.{{ base_domain }}
|
||||
onion: gbat2pbpg7ys3fi3pbp64667tt5x66mg45xok35bxdw7v55brm7a27yd.onion
|
||||
volume: "{{ base_volume }}/searxng"
|
||||
version: latest
|
||||
redis_version: 7-alpine
|
||||
|
||||
wkd:
|
||||
domain: "{{ base_domain }}"
|
||||
volume: "{{ base_volume }}/wkd"
|
||||
version: 1-alpine
|
||||
|
||||
tor:
|
||||
volume: "{{ base_volume }}/tor"
|
||||
version: latest
|
||||
|
||||
watchtower:
|
||||
version: amd64-1.5.3
|
8
roles/docker_services/files/dockerd/daemon.json
Normal file
8
roles/docker_services/files/dockerd/daemon.json
Normal file
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"default-address-pools": [
|
||||
{
|
||||
"base": "172.17.0.0/16",
|
||||
"size": 24
|
||||
}
|
||||
]
|
||||
}
|
52
roles/docker_services/files/shared/nginx.conf
Normal file
52
roles/docker_services/files/shared/nginx.conf
Normal file
|
@ -0,0 +1,52 @@
|
|||
user nginx;
|
||||
worker_processes auto;
|
||||
|
||||
error_log /dev/null crit;
|
||||
pid /var/run/nginx.pid;
|
||||
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
|
||||
http {
|
||||
include /etc/nginx/mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
access_log off;
|
||||
|
||||
sendfile on;
|
||||
tcp_nopush on;
|
||||
gzip on;
|
||||
server_tokens off;
|
||||
|
||||
include /etc/nginx/conf.d/*.conf;
|
||||
|
||||
keepalive_timeout 65;
|
||||
|
||||
|
||||
### HTTP headers
|
||||
|
||||
# TCP Keep-Alive
|
||||
add_header Connection "Keep-Alive" always;
|
||||
|
||||
# CSP
|
||||
add_header Content-Security-Policy "default-src 'none'; child-src 'none'; script-src 'self'; style-src 'self' 'unsafe-inline'; form-action 'self'; font-src 'self'; frame-ancestors 'self'; base-uri 'self'; connect-src 'self'; img-src 'self'; manifest-src 'self'" always;
|
||||
|
||||
# Enable cross-site filter (XSS) and tell browser to block detected attacks
|
||||
add_header X-XSS-Protection "1; mode=block" always;
|
||||
|
||||
# Prevent some browsers from MIME-sniffing a response away from the declared Content-Type
|
||||
add_header X-Content-Type-Options "nosniff" always;
|
||||
|
||||
# Disallow the site to be rendered within a frame (clickjacking protection)
|
||||
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||
|
||||
# Disable some features
|
||||
add_header Permissions-Policy "accelerometer=(),ambient-light-sensor=(),autoplay=(),camera=(),encrypted-media=(),focus-without-user-activation=(),geolocation=(),gyroscope=(),magnetometer=(),microphone=(),midi=(),payment=(),picture-in-picture=(),speaker=(),sync-xhr=(),usb=(),vr=(),interest-cohort=()" always;
|
||||
|
||||
# Disable referrer
|
||||
add_header Referrer-Policy "no-referrer" always;
|
||||
|
||||
# Cache control policy
|
||||
add_header Cache-Control "max-age=15552000" always;
|
||||
}
|
BIN
roles/docker_services/files/wkd/6fi64ioaua1j93gkt5eow8skha8e34sy
Normal file
BIN
roles/docker_services/files/wkd/6fi64ioaua1j93gkt5eow8skha8e34sy
Normal file
Binary file not shown.
45
roles/docker_services/tasks/config.yml
Normal file
45
roles/docker_services/tasks/config.yml
Normal file
|
@ -0,0 +1,45 @@
|
|||
# vim: ft=yaml.ansible
|
||||
---
|
||||
- name: Create base directory for Docker volumes
|
||||
ansible.builtin.file:
|
||||
path: "{{ base_volume }}"
|
||||
owner: root
|
||||
mode: u=rwx,g=rx,o=rx
|
||||
state: directory
|
||||
|
||||
- name: Copy Docker daemon config file
|
||||
ansible.builtin.copy:
|
||||
src: dockerd/daemon.json
|
||||
dest: /etc/docker/daemon.json
|
||||
owner: root
|
||||
mode: u=rw,g=r,o=r
|
||||
register: daemon_config
|
||||
|
||||
- name: (Re)start Docker daemon
|
||||
ansible.builtin.service:
|
||||
name: "{{ item }}"
|
||||
enabled: true
|
||||
state: "{{ 'restarted' if daemon_config.changed else 'started' }}"
|
||||
loop:
|
||||
- docker.socket
|
||||
- docker.service
|
||||
|
||||
- name: Create Docker network for services
|
||||
community.docker.docker_network:
|
||||
name: services
|
||||
ipam_config:
|
||||
- subnet: 172.16.0.0/16
|
||||
gateway: 172.16.0.1
|
||||
state: present
|
||||
|
||||
- name: Create Docker network for Tor
|
||||
community.docker.docker_network:
|
||||
name: tor
|
||||
state: present
|
||||
|
||||
- name: Copy nginx.conf to shared location
|
||||
ansible.builtin.copy:
|
||||
src: shared/nginx.conf
|
||||
dest: "{{ base_volume }}/nginx.conf"
|
||||
owner: root
|
||||
mode: u=rw,g=r,o=r
|
50
roles/docker_services/tasks/main.yml
Normal file
50
roles/docker_services/tasks/main.yml
Normal file
|
@ -0,0 +1,50 @@
|
|||
# vim: ft=yaml.ansible
|
||||
---
|
||||
- name: Add Docker PGP key
|
||||
ansible.builtin.apt_key:
|
||||
keyserver: keyserver.ubuntu.com
|
||||
id: '0x8D81803C0EBFCD88'
|
||||
state: present
|
||||
|
||||
- name: Add Docker apt repository
|
||||
ansible.builtin.apt_repository:
|
||||
repo: deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian bullseye stable
|
||||
state: present
|
||||
update_cache: true
|
||||
|
||||
- name: Install Docker
|
||||
ansible.builtin.apt:
|
||||
name: "{{ pkgs }}"
|
||||
state: present
|
||||
vars:
|
||||
pkgs:
|
||||
- docker-ce
|
||||
- docker-compose-plugin
|
||||
|
||||
- name: Create docker-compose symlink
|
||||
ansible.builtin.file:
|
||||
path: /usr/local/bin/docker-compose
|
||||
src: /usr/libexec/docker/cli-plugins/docker-compose
|
||||
state: link
|
||||
|
||||
- name: Install Python bindings for Docker
|
||||
ansible.builtin.pip:
|
||||
name: "{{ pkgs }}"
|
||||
state: present
|
||||
executable: pip3
|
||||
vars:
|
||||
pkgs:
|
||||
- docker
|
||||
- docker-compose
|
||||
|
||||
- name: Configure Docker
|
||||
ansible.builtin.import_tasks: config.yml
|
||||
tags:
|
||||
- services
|
||||
- reboot
|
||||
|
||||
- name: Set up Docker services
|
||||
ansible.builtin.import_tasks: services.yml
|
||||
tags:
|
||||
- services
|
||||
- reboot
|
11
roles/docker_services/tasks/services.yml
Normal file
11
roles/docker_services/tasks/services.yml
Normal file
|
@ -0,0 +1,11 @@
|
|||
# vim: ft=yaml.ansible
|
||||
---
|
||||
- name: Deploy services
|
||||
ansible.builtin.include_tasks: services/{{ item.key }}.yml
|
||||
loop: "{{ services | dict2items }}"
|
||||
when: single_service is not defined
|
||||
|
||||
- name: Deploy single service
|
||||
ansible.builtin.include_tasks: services/{{ single_service }}.yml
|
||||
when: single_service is defined and
|
||||
single_service in services
|
43
roles/docker_services/tasks/services/caddy.yml
Normal file
43
roles/docker_services/tasks/services/caddy.yml
Normal file
|
@ -0,0 +1,43 @@
|
|||
# vim: ft=yaml.ansible
|
||||
---
|
||||
- name: Create Caddy volume directories
|
||||
ansible.builtin.file:
|
||||
path: "{{ services.caddy.volume }}/{{ dir }}"
|
||||
owner: root
|
||||
mode: u=rwx,g=rx,o=rx
|
||||
state: directory
|
||||
loop:
|
||||
- config
|
||||
- data
|
||||
loop_control:
|
||||
loop_var: dir
|
||||
|
||||
- name: Copy Caddyfile
|
||||
ansible.builtin.template:
|
||||
src: Caddyfile.j2
|
||||
dest: "{{ services.caddy.volume }}/Caddyfile"
|
||||
owner: root
|
||||
mode: u=rw,g=r,o=r
|
||||
|
||||
- name: Deploy Caddy Docker container
|
||||
community.docker.docker_container:
|
||||
name: caddy
|
||||
state: "{{ 'absent' if stop is defined and stop else 'started' }}"
|
||||
restart: "{{ stop is undefined or not stop }}"
|
||||
image: caddy:{{ services.caddy.version }}
|
||||
restart_policy: always
|
||||
networks:
|
||||
- name: services
|
||||
ipv4_address: 172.16.3.2
|
||||
published_ports:
|
||||
- 80:80/tcp
|
||||
- 443:443/tcp
|
||||
volumes:
|
||||
- "{{ services.caddy.volume }}/Caddyfile:/etc/caddy/Caddyfile:ro"
|
||||
- "{{ services.caddy.volume }}/config:/config:rw"
|
||||
- "{{ services.caddy.volume }}/data:/data:rw"
|
||||
capabilities:
|
||||
- net_bind_service
|
||||
- dac_override
|
||||
cap_drop:
|
||||
- all
|
82
roles/docker_services/tasks/services/jitsi_meet.yml
Normal file
82
roles/docker_services/tasks/services/jitsi_meet.yml
Normal file
|
@ -0,0 +1,82 @@
|
|||
# vim: ft=yaml.ansible
|
||||
---
|
||||
- name: Create Jitsi Meet volume directories
|
||||
ansible.builtin.file:
|
||||
path: "{{ services.jitsi_meet.volume }}/{{ dir }}"
|
||||
owner: root
|
||||
mode: u=rwx,g=rx,o=rx
|
||||
state: directory
|
||||
loop:
|
||||
- prosody/plugins
|
||||
- transcripts
|
||||
loop_control:
|
||||
loop_var: dir
|
||||
|
||||
- name: Deploy Jitsi Meet with Docker Compose
|
||||
community.docker.docker_compose:
|
||||
project_name: searxng
|
||||
state: "{{ 'absent' if stop is defined and stop else 'present' }}"
|
||||
restarted: "{{ stop is undefined or not stop }}"
|
||||
pull: true
|
||||
definition:
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
frontend:
|
||||
image: jitsi/web:{{ services.jitsi_meet.version }}
|
||||
restart: always
|
||||
environment:
|
||||
DISABLE_HTTPS: 1
|
||||
PUBLIC_URL: "{{ services.jitsi_meet.domain }}"
|
||||
networks:
|
||||
meet.jitsi:
|
||||
services:
|
||||
aliases:
|
||||
- jitsi_meet
|
||||
volumes:
|
||||
- "{{ services.jitsi_meet.volume }}/transcripts:/usr/share/jitsi-meet/transcripts:rw"
|
||||
|
||||
prosody:
|
||||
image: jitsi/prosody:{{ services.jitsi_meet.version }}
|
||||
restart: always
|
||||
environment:
|
||||
JICOFO_AUTH_PASSWORD: "{{ secrets.jitsi_meet.jicofo_auth_password }}"
|
||||
JVB_AUTH_PASSWORD: "{{ secrets.jitsi_meet.jvb_auth_password }}"
|
||||
networks:
|
||||
meet.jitsi:
|
||||
aliases:
|
||||
- xmpp.meet.jitsi
|
||||
volumes:
|
||||
- "{{ services.jitsi_meet.volume }}/prosody/plugins:/prosody-plugins-custom:rw"
|
||||
expose:
|
||||
- 5222
|
||||
- 5280
|
||||
- 5347
|
||||
|
||||
jicofo:
|
||||
image: jitsi/jicofo:{{ services.jitsi_meet.version }}
|
||||
restart: always
|
||||
environment:
|
||||
JICOFO_AUTH_PASSWORD: "{{ secrets.jitsi_meet.jicofo_auth_password }}"
|
||||
networks:
|
||||
meet.jitsi:
|
||||
depends_on:
|
||||
- prosody
|
||||
|
||||
jvb:
|
||||
image: jitsi/jvb:{{ services.jitsi_meet.version }}
|
||||
restart: always
|
||||
environment:
|
||||
JVB_AUTH_PASSWORD: "{{ secrets.jitsi_meet.jvb_auth_password }}"
|
||||
JVB_WS_DOMAIN: "{{ services.jitsi_meet.domain }}"
|
||||
networks:
|
||||
meet.jitsi:
|
||||
ports:
|
||||
- 10000:10000/udp
|
||||
depends_on:
|
||||
- prosody
|
||||
|
||||
networks:
|
||||
meet.jitsi:
|
||||
services:
|
||||
external: true
|
18
roles/docker_services/tasks/services/lingva.yml
Normal file
18
roles/docker_services/tasks/services/lingva.yml
Normal file
|
@ -0,0 +1,18 @@
|
|||
# vim: ft=yaml.ansible
|
||||
---
|
||||
- name: Deploy Lingva Docker container
|
||||
community.docker.docker_container:
|
||||
name: lingva
|
||||
state: "{{ 'absent' if stop is defined and stop else 'started' }}"
|
||||
restart: "{{ stop is undefined or not stop }}"
|
||||
image: thedaviddelta/lingva-translate:{{ services.lingva.version }}
|
||||
restart_policy: always
|
||||
env:
|
||||
site_domain: "{{ services.lingva.domain }}"
|
||||
networks:
|
||||
- name: services
|
||||
aliases:
|
||||
- lingva
|
||||
- name: tor
|
||||
aliases:
|
||||
- lingva
|
26
roles/docker_services/tasks/services/samsapti_dev.yml
Normal file
26
roles/docker_services/tasks/services/samsapti_dev.yml
Normal file
|
@ -0,0 +1,26 @@
|
|||
# vim: ft=yaml.ansible
|
||||
---
|
||||
- name: Create samsapti.dev volume directories
|
||||
ansible.builtin.file:
|
||||
path: "{{ services.samsapti_dev.volume }}/public"
|
||||
owner: cicd
|
||||
mode: u=rwx,g=rx,o=rx
|
||||
state: directory
|
||||
|
||||
- name: Deploy samsapti.dev Docker container
|
||||
community.docker.docker_container:
|
||||
name: samsapti.dev
|
||||
state: "{{ 'absent' if stop is defined and stop else 'started' }}"
|
||||
restart: "{{ stop is undefined or not stop }}"
|
||||
image: nginx:{{ services.samsapti_dev.version }}
|
||||
restart_policy: always
|
||||
networks:
|
||||
- name: services
|
||||
aliases:
|
||||
- samsapti
|
||||
- name: tor
|
||||
aliases:
|
||||
- samsapti
|
||||
volumes:
|
||||
- "{{ services.samsapti_dev.volume }}/public:/usr/share/nginx/html:ro"
|
||||
- "{{ base_volume }}/nginx.conf:/etc/nginx/nginx.conf:ro"
|
72
roles/docker_services/tasks/services/searxng.yml
Normal file
72
roles/docker_services/tasks/services/searxng.yml
Normal file
|
@ -0,0 +1,72 @@
|
|||
# vim: ft=yaml.ansible
|
||||
---
|
||||
- name: Create SearXNG volume directory
|
||||
ansible.builtin.file:
|
||||
path: "{{ services.searxng.volume }}"
|
||||
owner: root
|
||||
mode: u=rwx,g=rx,o=rx
|
||||
state: directory
|
||||
|
||||
- name: Copy SearXNG settings.yml file
|
||||
ansible.builtin.template:
|
||||
src: settings.yml.j2
|
||||
dest: "{{ services.searxng.volume }}/settings.yml"
|
||||
owner: root
|
||||
mode: u=rw,g=r,o=r
|
||||
|
||||
- name: Deploy SearXNG with Docker Compose
|
||||
community.docker.docker_compose:
|
||||
project_name: searxng
|
||||
state: "{{ 'absent' if stop is defined and stop else 'present' }}"
|
||||
restarted: "{{ stop is undefined or not stop }}"
|
||||
pull: true
|
||||
definition:
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
searxng:
|
||||
image: searxng/searxng:{{ services.searxng.version }}
|
||||
restart: always
|
||||
environment:
|
||||
SEARXNG_BASE_URL: https://{{ services.searxng.domain }}
|
||||
networks:
|
||||
default:
|
||||
services:
|
||||
aliases:
|
||||
- searxng
|
||||
tor:
|
||||
aliases:
|
||||
- searxng
|
||||
volumes:
|
||||
- "{{ services.searxng.volume }}:/etc/searxng:rw"
|
||||
cap_add:
|
||||
- chown
|
||||
- setuid
|
||||
- setgid
|
||||
- dac_override
|
||||
cap_drop:
|
||||
- all
|
||||
logging:
|
||||
driver: json-file
|
||||
options:
|
||||
max-size: 1m
|
||||
max-file: '1'
|
||||
|
||||
redis:
|
||||
image: redis:{{ services.searxng.redis_version }}
|
||||
restart: always
|
||||
command: redis-server --save "" --appendonly "no"
|
||||
tmpfs:
|
||||
- /var/lib/redis
|
||||
cap_add:
|
||||
- setuid
|
||||
- setgid
|
||||
- dac_override
|
||||
cap_drop:
|
||||
- all
|
||||
|
||||
networks:
|
||||
services:
|
||||
external: true
|
||||
tor:
|
||||
external: true
|
33
roles/docker_services/tasks/services/tor.yml
Normal file
33
roles/docker_services/tasks/services/tor.yml
Normal file
|
@ -0,0 +1,33 @@
|
|||
# vim: ft=yaml.ansible
|
||||
---
|
||||
- name: Create Tor volume directory
|
||||
ansible.builtin.file:
|
||||
path: "{{ services.tor.volume }}"
|
||||
owner: '104'
|
||||
group: '107'
|
||||
mode: u=rwx,go=
|
||||
state: directory
|
||||
|
||||
- name: Deploy Tor Docker container
|
||||
community.docker.docker_container:
|
||||
name: tor
|
||||
state: "{{ 'absent' if stop is defined and stop else 'started' }}"
|
||||
restart: "{{ stop is undefined or not stop }}"
|
||||
image: goldy/tor-hidden-service:{{ services.tor.version }}
|
||||
restart_policy: always
|
||||
env:
|
||||
LINGVA_TOR_SERVICE_HOSTS: 80:lingva:3000
|
||||
LINGVA_TOR_SERVICE_VERSION: '3'
|
||||
LINGVA_TOR_SERVICE_KEY: "{{ secrets.tor.lingva_key }}"
|
||||
|
||||
SAMSAPTI_TOR_SERVICE_HOSTS: 80:samsapti:80
|
||||
SAMSAPTI_TOR_SERVICE_VERSION: '3'
|
||||
SAMSAPTI_TOR_SERVICE_KEY: "{{ secrets.tor.samsapti_key }}"
|
||||
|
||||
SEARXNG_TOR_SERVICE_HOSTS: 80:searxng:8080
|
||||
SEARXNG_TOR_SERVICE_VERSION: '3'
|
||||
SEARXNG_TOR_SERVICE_KEY: "{{ secrets.tor.searxng_key }}"
|
||||
networks:
|
||||
- name: tor
|
||||
volumes:
|
||||
- "{{ services.tor.volume }}:/var/lib/tor/hidden_service:rw"
|
20
roles/docker_services/tasks/services/watchtower.yml
Normal file
20
roles/docker_services/tasks/services/watchtower.yml
Normal file
|
@ -0,0 +1,20 @@
|
|||
# vim: ft=yaml.ansible
|
||||
---
|
||||
- name: Create Docker network for Watchtower
|
||||
community.docker.docker_network:
|
||||
name: watchtower
|
||||
state: present
|
||||
|
||||
- name: Deploy Watchtower Docker container
|
||||
community.docker.docker_container:
|
||||
name: watchtower
|
||||
state: "{{ 'absent' if stop is defined and stop else 'started' }}"
|
||||
restart: "{{ stop is undefined or not stop }}"
|
||||
image: containrrr/watchtower:{{ services.watchtower.version }}
|
||||
restart_policy: always
|
||||
networks:
|
||||
- name: watchtower
|
||||
env:
|
||||
WATCHTOWER_POLL_INTERVAL: '3600'
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock:rw
|
30
roles/docker_services/tasks/services/wkd.yml
Normal file
30
roles/docker_services/tasks/services/wkd.yml
Normal file
|
@ -0,0 +1,30 @@
|
|||
# vim: ft=yaml.ansible
|
||||
---
|
||||
- name: Create WKD volume directories
|
||||
ansible.builtin.file:
|
||||
path: "{{ services.wkd.volume }}/.well-known/openpgpkey/hu"
|
||||
owner: root
|
||||
mode: u=rwx,g=rx,o=rx
|
||||
state: directory
|
||||
|
||||
- name: Copy PGP key to WKD volume directory
|
||||
ansible.builtin.copy:
|
||||
src: wkd/6fi64ioaua1j93gkt5eow8skha8e34sy
|
||||
dest: "{{ services.wkd.volume }}/.well-known/openpgpkey/hu/6fi64ioaua1j93gkt5eow8skha8e34sy"
|
||||
owner: root
|
||||
mode: u=rw,g=r,o=r
|
||||
|
||||
- name: Deploy WKD Docker container
|
||||
community.docker.docker_container:
|
||||
name: wkd
|
||||
state: "{{ 'absent' if stop is defined and stop else 'started' }}"
|
||||
restart: "{{ stop is undefined or not stop }}"
|
||||
image: nginx:{{ services.wkd.version }}
|
||||
restart_policy: always
|
||||
networks:
|
||||
- name: services
|
||||
aliases:
|
||||
- wkd
|
||||
volumes:
|
||||
- "{{ services.wkd.volume }}:/usr/share/nginx/html:ro"
|
||||
- "{{ base_volume }}/nginx.conf:/etc/nginx/nginx.conf:ro"
|
154
roles/docker_services/templates/Caddyfile.j2
Normal file
154
roles/docker_services/templates/Caddyfile.j2
Normal file
|
@ -0,0 +1,154 @@
|
|||
{
|
||||
admin off
|
||||
}
|
||||
|
||||
www.{{ services.samsapti_dev.domain }} {
|
||||
tls {{ secrets.tls_email }}
|
||||
|
||||
log {
|
||||
output discard
|
||||
}
|
||||
|
||||
redir https://{{ services.samsapti_dev.domain }}{uri}
|
||||
}
|
||||
|
||||
{{ services.samsapti_dev.domain }} {
|
||||
tls {{ secrets.tls_email }}
|
||||
|
||||
log {
|
||||
output discard
|
||||
}
|
||||
|
||||
header {
|
||||
Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
|
||||
Onion-Location "http://{{ services.samsapti_dev.onion }}{uri}"
|
||||
-Server
|
||||
}
|
||||
|
||||
reverse_proxy samsapti:80
|
||||
}
|
||||
|
||||
{{ services.wkd.domain }} {
|
||||
tls {{ secrets.tls_email }}
|
||||
|
||||
log {
|
||||
output discard
|
||||
}
|
||||
|
||||
header {
|
||||
Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
|
||||
-Server
|
||||
}
|
||||
|
||||
reverse_proxy wkd:80
|
||||
}
|
||||
|
||||
{{ services.jitsi_meet.domain }} {
|
||||
tls {{ secrets.tls_email }}
|
||||
|
||||
log {
|
||||
output discard
|
||||
}
|
||||
|
||||
header {
|
||||
Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
|
||||
-Server
|
||||
}
|
||||
|
||||
reverse_proxy jitsi_meet:80
|
||||
}
|
||||
|
||||
{{ services.lingva.domain }} {
|
||||
tls {{ secrets.tls_email }}
|
||||
|
||||
log {
|
||||
output discard
|
||||
}
|
||||
|
||||
header {
|
||||
Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
|
||||
Onion-Location "http://{{ services.lingva.onion }}{uri]"
|
||||
-Server
|
||||
}
|
||||
|
||||
reverse_proxy lingva:3000
|
||||
}
|
||||
|
||||
{{ services.searxng.domain }} {
|
||||
tls {{ secrets.tls_email }}
|
||||
|
||||
log {
|
||||
output discard
|
||||
}
|
||||
|
||||
@api {
|
||||
path /config
|
||||
path /healthz
|
||||
path /stats/errors
|
||||
path /stats/checker
|
||||
}
|
||||
|
||||
@static {
|
||||
path /static/*
|
||||
}
|
||||
|
||||
@notstatic {
|
||||
not path /static/*
|
||||
}
|
||||
|
||||
@imageproxy {
|
||||
path /image_proxy
|
||||
}
|
||||
|
||||
@notimageproxy {
|
||||
not path /image_proxy
|
||||
}
|
||||
|
||||
header {
|
||||
Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
|
||||
X-XSS-Protection "1; mode=block"
|
||||
X-Content-Type-Options "nosniff"
|
||||
Permissions-Policy "accelerometer=(),ambient-light-sensor=(),autoplay=(),camera=(),encrypted-media=(),focus-without-user-activation=(),geolocation=(),gyroscope=(),magnetometer=(),microphone=(),midi=(),payment=(),picture-in-picture=(),speaker=(),sync-xhr=(),usb=(),vr=(),interest-cohort=()"
|
||||
Referrer-Policy "no-referrer"
|
||||
X-Robots-Tag "noindex, noarchive, nofollow"
|
||||
Onion-Location "http://{{ services.searxng.onion }}{uri}"
|
||||
-Server
|
||||
}
|
||||
|
||||
header @api {
|
||||
Access-Control-Allow-Methods "GET, OPTIONS"
|
||||
Access-Control-Allow-Origin "*"
|
||||
}
|
||||
|
||||
# Cache
|
||||
header @static {
|
||||
# Cache
|
||||
Cache-Control "public, max-age=31536000"
|
||||
defer
|
||||
}
|
||||
|
||||
header @notstatic {
|
||||
# No Cache
|
||||
Cache-Control "no-cache, no-store"
|
||||
Pragma "no-cache"
|
||||
}
|
||||
|
||||
# CSP (see http://content-security-policy.com/ )
|
||||
header @imageproxy {
|
||||
Content-Security-Policy "default-src 'none'; img-src 'self' data:"
|
||||
}
|
||||
|
||||
header @notimageproxy {
|
||||
Content-Security-Policy "upgrade-insecure-requests; default-src 'none'; script-src 'self'; style-src 'self' 'unsafe-inline'; form-action 'self' https://github.com/searxng/searxng/issues/new; font-src 'self'; frame-ancestors 'self'; base-uri 'self'; connect-src 'self' https://overpass-api.de; img-src 'self' data: https://*.tile.openstreetmap.org; frame-src https://www.youtube-nocookie.com https://player.vimeo.com https://www.dailymotion.com https://www.deezer.com https://www.mixcloud.com https://w.soundcloud.com https://embed.spotify.com"
|
||||
}
|
||||
|
||||
# SearXNG
|
||||
handle {
|
||||
encode zstd gzip
|
||||
|
||||
reverse_proxy searxng:8080 {
|
||||
header_up X-Forwarded-Port {http.request.port}
|
||||
header_up X-Forwarded-Proto {http.request.scheme}
|
||||
}
|
||||
}
|
||||
}
|
85
roles/docker_services/templates/settings.yml.j2
Normal file
85
roles/docker_services/templates/settings.yml.j2
Normal file
|
@ -0,0 +1,85 @@
|
|||
use_default_settings: true
|
||||
|
||||
general:
|
||||
debug: false
|
||||
instance_name: "Sam's SearXNG"
|
||||
privacypolicy_url: "https://{{ services.samsapti_dev.domain }}/privacy/"
|
||||
contact_url: "https://{{ services.samsapti_dev.domain }}/contact/"
|
||||
enable_metrics: true
|
||||
|
||||
server:
|
||||
secret_key: "{{ secrets.searxng.secret_key }}"
|
||||
limiter: true
|
||||
image_proxy: true
|
||||
http_protocol_version: "1.1"
|
||||
method: "GET"
|
||||
|
||||
ui:
|
||||
results_on_new_tab: false
|
||||
center_alignment: true
|
||||
theme_args:
|
||||
simple_style: auto
|
||||
|
||||
redis:
|
||||
url: redis://redis:6379/0
|
||||
|
||||
search:
|
||||
formats:
|
||||
- html
|
||||
- csv
|
||||
- json
|
||||
- rss
|
||||
safe_search: 2
|
||||
|
||||
outgoing:
|
||||
enable_http2: true
|
||||
|
||||
enabled_plugins:
|
||||
- 'Hash plugin'
|
||||
- 'Hostname replace'
|
||||
- 'Search on category select'
|
||||
- 'Self Informations'
|
||||
- 'Tracker URL remover'
|
||||
- 'Vim-like hotkeys'
|
||||
|
||||
hostname_replace:
|
||||
'^(.*\.)?youtube\.com$': 'yewtu.be'
|
||||
'^(.*\.)?youtu\.be$': 'yewtu.be'
|
||||
'^(.*\.)?youtube-noocookie\.com$': 'yewtu.be'
|
||||
'^(.*\.)?reddit\.com$': 'libreddit.de'
|
||||
'^(.*\.)?redd\.it$': 'libreddit.de'
|
||||
'^(www\.)?twitter\.com$': 'nitter.net'
|
||||
'^(.*\.)?(m\.)?wiktionary\.org$': '\1m.wiktionary.org'
|
||||
|
||||
engines:
|
||||
- name: bing
|
||||
disabled: false
|
||||
|
||||
- name: yahoo
|
||||
disabled: false
|
||||
|
||||
- name: ddg definitions
|
||||
disabled: false
|
||||
|
||||
- name: duckduckgo images
|
||||
disabled: false
|
||||
|
||||
- name: google
|
||||
use_mobile_ui: true
|
||||
disabled: false
|
||||
|
||||
- name: wikidata
|
||||
disabled: true
|
||||
|
||||
- name: wikinews
|
||||
disabled: true
|
||||
|
||||
- name: qwant
|
||||
disabled: true
|
||||
|
||||
- name: qwant images
|
||||
disabled: true
|
||||
|
||||
- name: lingva
|
||||
url: https://translate.sapti.me
|
||||
disabled: true
|
19
roles/os_config/handlers/main.yml
Normal file
19
roles/os_config/handlers/main.yml
Normal file
|
@ -0,0 +1,19 @@
|
|||
# vim: ft=yaml.ansible
|
||||
---
|
||||
- name: Create .env for apt-update-push
|
||||
ansible.builtin.template:
|
||||
src: env.j2
|
||||
dest: /home/{{ ansible_user }}/apt-update-push/.env
|
||||
owner: root
|
||||
mode: u=rw,go=
|
||||
listen: apt-update-push
|
||||
|
||||
- name: Install apt-update-push
|
||||
ansible.builtin.command: /home/{{ ansible_user }}/apt-update-push/install.sh
|
||||
listen: apt-update-push
|
||||
|
||||
- name: Restart sshd
|
||||
ansible.builtin.service:
|
||||
name: sshd
|
||||
state: restarted
|
||||
listen: sshd
|
40
roles/os_config/tasks/base.yml
Normal file
40
roles/os_config/tasks/base.yml
Normal file
|
@ -0,0 +1,40 @@
|
|||
# vim: ft=yaml.ansible
|
||||
---
|
||||
- name: Set hostname
|
||||
ansible.builtin.hostname:
|
||||
name: "{{ hostname }}"
|
||||
|
||||
- name: Set timezone
|
||||
community.general.timezone:
|
||||
name: "{{ timezone }}"
|
||||
|
||||
- name: Upgrade system packages
|
||||
ansible.builtin.apt:
|
||||
update_cache: true
|
||||
upgrade: full
|
||||
|
||||
- name: Install packages via apt
|
||||
ansible.builtin.apt:
|
||||
name: "{{ pkgs }}"
|
||||
state: present
|
||||
vars:
|
||||
pkgs:
|
||||
- apparmor
|
||||
- curl
|
||||
- git
|
||||
- haveged
|
||||
- needrestart
|
||||
- python3-pip
|
||||
- ufw
|
||||
- unattended-upgrades
|
||||
|
||||
- name: Clone apt-update-push
|
||||
ansible.builtin.git:
|
||||
dest: /home/{{ ansible_user }}/apt-update-push
|
||||
repo: https://github.com/samsapti/apt-update-push.git
|
||||
clone: true
|
||||
update: true
|
||||
single_branch: true
|
||||
depth: 1
|
||||
become: false
|
||||
notify: apt-update-push
|
18
roles/os_config/tasks/firewall.yml
Normal file
18
roles/os_config/tasks/firewall.yml
Normal file
|
@ -0,0 +1,18 @@
|
|||
# vim: ft=yaml.ansible
|
||||
---
|
||||
- name: Allow necessary ports in UFW
|
||||
community.general.ufw:
|
||||
rule: allow
|
||||
port: "{{ item.port }}"
|
||||
proto: "{{ item.proto | default('tcp') }}"
|
||||
loop:
|
||||
- port: '22' # SSH
|
||||
- port: '80' # HTTP
|
||||
- port: '443' # HTTPS
|
||||
- port: '10000' # Jitsi Videobridge
|
||||
proto: udp
|
||||
|
||||
- name: Enable UFW
|
||||
community.general.ufw:
|
||||
state: enabled
|
||||
policy: deny
|
20
roles/os_config/tasks/main.yml
Normal file
20
roles/os_config/tasks/main.yml
Normal file
|
@ -0,0 +1,20 @@
|
|||
# vim: ft=yaml.ansible
|
||||
---
|
||||
- name: Configure user accounts
|
||||
ansible.builtin.import_tasks: users.yml
|
||||
tags:
|
||||
- users
|
||||
|
||||
- name: Configure system base
|
||||
ansible.builtin.import_tasks: base.yml
|
||||
|
||||
- name: Reboot if needed
|
||||
ansible.builtin.import_tasks: reboot.yml
|
||||
tags:
|
||||
- reboot
|
||||
|
||||
- name: Configure firewall
|
||||
ansible.builtin.import_tasks: firewall.yml
|
||||
|
||||
- name: Configure SSH
|
||||
ansible.builtin.import_tasks: ssh.yml
|
28
roles/os_config/tasks/reboot.yml
Normal file
28
roles/os_config/tasks/reboot.yml
Normal file
|
@ -0,0 +1,28 @@
|
|||
# vim: ft=yaml.ansible
|
||||
---
|
||||
- name: Check if a reboot is needed
|
||||
ansible.builtin.stat:
|
||||
path: /var/run/reboot-required
|
||||
register: needs_reboot
|
||||
|
||||
- name: Include docker_services role for service shutdown
|
||||
ansible.builtin.include_role:
|
||||
name: docker_services
|
||||
tasks_from: services.yml
|
||||
apply:
|
||||
ignore_errors: true
|
||||
vars:
|
||||
stop: true
|
||||
when: needs_reboot.stat.exists or
|
||||
(force_reboot is defined and force_reboot)
|
||||
|
||||
- name: Reboot host
|
||||
ansible.builtin.reboot:
|
||||
when: needs_reboot.stat.exists or
|
||||
(force_reboot is defined and force_reboot)
|
||||
register: rebooted
|
||||
|
||||
- name: End play if reboot is not needed
|
||||
ansible.builtin.meta: end_play
|
||||
when: reboot is defined and reboot and
|
||||
(rebooted.rebooted is undefined or not rebooted.rebooted)
|
25
roles/os_config/tasks/ssh.yml
Normal file
25
roles/os_config/tasks/ssh.yml
Normal file
|
@ -0,0 +1,25 @@
|
|||
# vim: ft=yaml.ansible
|
||||
---
|
||||
- name: Allow SSH login with public keys
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/ssh/sshd_config
|
||||
regexp: '^#?PubkeyAuthentication '
|
||||
line: PubkeyAuthentication yes
|
||||
state: present
|
||||
notify: sshd
|
||||
|
||||
- name: Disallow SSH login with password
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/ssh/sshd_config
|
||||
regexp: '^#?PasswordAuthentication '
|
||||
line: PasswordAuthentication no
|
||||
state: present
|
||||
notify: sshd
|
||||
|
||||
- name: Disallow root login over SSH
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/ssh/sshd_config
|
||||
regexp: '^#?PermitRootLogin '
|
||||
line: PermitRootLogin no
|
||||
state: present
|
||||
notify: sshd
|
17
roles/os_config/tasks/users.yml
Normal file
17
roles/os_config/tasks/users.yml
Normal file
|
@ -0,0 +1,17 @@
|
|||
# vim: ft=yaml.ansible
|
||||
---
|
||||
- name: Add users
|
||||
ansible.builtin.user:
|
||||
name: "{{ item.name }}"
|
||||
comment: "{{ item.comment }}"
|
||||
password: "{{ item.password }}"
|
||||
groups: "{{ item.groups }}"
|
||||
update_password: always
|
||||
loop: "{{ users }}"
|
||||
|
||||
- name: Add ssh authorized_keys
|
||||
ansible.posix.authorized_key:
|
||||
user: "{{ item.name }}"
|
||||
key: "{{ item.ssh_keys | join('\n') }}"
|
||||
exclusive: true
|
||||
loop: "{{ users }}"
|
2
roles/os_config/templates/env.j2
Normal file
2
roles/os_config/templates/env.j2
Normal file
|
@ -0,0 +1,2 @@
|
|||
topic={{ secrets.ntfy_topic }}
|
||||
hour=20
|
Reference in a new issue