This commit is contained in:
Sam A. 2024-02-10 23:51:41 +01:00
parent 97311b4589
commit f56cebf02e
Signed by: samsapti
GPG key ID: CBBBE7371E81C4EA
37 changed files with 0 additions and 1384 deletions

View file

@ -1,120 +0,0 @@
---
# .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]
- var-naming[no-role-prefix]
# - 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

2
.gitignore vendored
View file

@ -1,2 +0,0 @@
# ---> Ansible
*.retry

View file

@ -1,9 +0,0 @@
# cpx-ansible
This is the Ansible playbook I use to provision my VPS, where I
self-host various stuff. The VPS is a CPX21 from Hetzner Cloud.
### Credits
This project is in large part inspired by the work over on [data.coop's
Ansible setup](https://git.data.coop/data.coop/ansible).

View file

@ -1,6 +0,0 @@
[defaults]
ask_vault_pass = True
remote_user = sysadm
remote_tmp = /tmp/.ansible
inventory = inventory
use_persistent_connections = True

0
decommissioned Normal file
View file

View file

@ -1,55 +0,0 @@
$ANSIBLE_VAULT;1.1;AES256
39343338616331646134303961373936666330613365386436303430343461303038363636316337
6165383039383366653834383338356538356264623565630a633466656662376331396537613661
35343139323632643635336363303961373232353733313064393461336435323136663230346461
6565666162346361610a373134643735376635303039376137633138376463653864356166626564
32323364386139363534343966306464326539356263636461636232633536313635373965373638
66383837383730316563303538343533343437623162383438656131313363303434303063353365
63323262343937656539313765373039306131353161663535663861363838333963343932316231
33323935653261373432353638663462663534653934376661376438363239383362663763376165
37356333356536363535333564633534646136616331653465613934643862653465623035366137
35326562343765376132306133343835323137373232646361376565363934393866656634343561
64313037623133383164663662313362643832373436643133366261343465386533633936356563
66613934653261653239303230666264626461363565316465366331353138383836653561353535
35643233386336356632623939666432376263326231336661313038306164393234653264623231
30343130303738633137616531666365653163373230643535623063376334336632386136303932
30323066656464326261643038303062656562366432323732393162613739363266636438323138
34363636626234653039356437363666346166323834366437633535623230636432663263636632
35306666393733353038616464343431333938326266356464333737636233323564353630356434
32616539336633613132393834376338323536383361343430386538393734623134356634623162
35323066343464346661303963646430336332343631326133333162353638636639346537663232
35316166633638306364613162623934353735383834303234653033646432343835353864636132
39336563646162623566326434613137633531616663386236386333313532326234383433653838
35313066653766393736383631313837353532333833393833643264643932363531356363666165
33616431343733363230656263376539393232386161346331386530323464656464303463393831
34666461636138373666646563316132353766383365303535663033316330663738343265616233
64633734366630643835653236353362386137386636656234396462626565336365346139363239
61373137626631373337373365646362633665316137656335313531316366393730313935383866
66396466386236626134333163393637373030326666313536353764336437326363656563646134
35666330383037383936666137636633633635336366386636373865393331316239666266353365
30633034326262323462626335643637303730626333343638336635613635626633323534393935
33366439323165356164396538363263656466366465666263363637323934623261383833323534
63623862613038366536323761366565653565306430626231366135316532356261383739313930
32343633363664653661333236323931383464346232316136323033376630303733383064663832
33653864393933316133666664653938383336346635336564633937373861666631346432643233
31373262653361633837653764363837366562366530306661373866303166656539323561386161
30353338663430613833313837663636333637363535316339636161383333653562313864633938
65656164363535376366646635643536666233333531646466663863363565383464353639653639
31353438313336663236323035626231383139323762626339323539633439366433623662383864
38643236333539633336636264353863343239663132633939366534343630333238346536303837
30393739353330336539386466633763333863316639396130633061666661666431323636363831
37323533356366623136303665313064363961636231653131356538643138636538386438393962
32346663613836656165373231656562393265653234623032633265373832636464396166643761
37663066633138303332323665303662353630383039353564633233383536336666636161663962
66663066333432306133306431353731646132303239666330383831303937623430666266383939
33366631373264643361323836646462393730323731336164623136613432333134396436356630
31356438343636623133623730663933626335353963386639383830323062666661396534306537
62643137343664383563636633376234343739306362343438313266376331636665646564363165
38616133323864393031383434313863363361626430653537663637303966663437623633343163
31323165353230303733363633316338363164306336383030663433313363323632653564666134
64646631373635316261393632366534323166653061303634316138633066636232303331333730
65376331396665353336373438646336636565643564336133353937353731356437633061663565
35623132366263306664613061373832653363313134326432353737353466663265313833336539
32663330313136393332653262373235653764613435653365346561313062303766373039363765
35626233663333646664646632303338336637623764353963383365396234653833323165363931
3532636438643665326661393164366232353764346634616532

View file

@ -1,31 +0,0 @@
# 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
open_ports:
- { port: '22', proto: 'tcp', comment: 'SSH' }
- { port: '80', proto: 'tcp', comment: 'HTTP' }
- { port: '443', proto: 'tcp', comment: 'HTTPS' }
- { port: '5223', proto: 'tcp', comment: 'SMP server' }
- { port: '5443', proto: 'tcp', comment: 'XFTP server' }
- { port: '10000', proto: 'udp', comment: 'Jitsi Videobridge' }

View file

@ -1,2 +0,0 @@
# CPX21
cpx.servers.sapti.me ansible_python_interface=/usr/bin/python3

View file

@ -1,13 +0,0 @@
# vim: ft=yaml.ansible
---
- name: Deploy self-hosted services
hosts: all
gather_facts: false
become: true
roles:
- role: os_config
tags:
- os
- role: docker_services
tags:
- docker

View file

@ -1,86 +0,0 @@
#!/usr/bin/env sh
set -e
usage() {
printf '%s\n' "Usage:"
printf '$ %s\n' "$0 [--help]"
printf '$ %s\n' "$0 [--dry] os"
printf '$ %s\n' "$0 [--dry] base"
printf '$ %s\n' "$0 [--dry] firewall"
printf '$ %s\n' "$0 [--dry] ssh"
printf '$ %s\n' "$0 [--dry] docker"
printf '$ %s\n' "$0 [--dry] docker_config"
printf '$ %s\n' "$0 [--dry] users [--init]"
printf '$ %s\n' "$0 [--dry] reboot"
printf '$ %s\n' "$0 [--dry] services [--down|--restart|--recreate] [SINGLE_SERVICE]"
}
install_modules() {
if [ -z "$(ansible-galaxy collection list community.general 2>/dev/null)" ]; then
ansible-galaxy collection install community.general
fi
}
BASE_CMD="ansible-playbook playbook.yml --ask-become-pass"
cd "$(dirname "$0")" || exit 255
if [ "$1" = "--dry" ]; then
EXEC="echo"
shift
else
EXEC="eval"
fi
if [ "$#" -gt 0 ]; then
TAG="$1"
shift
fi
case $TAG in
"")
install_modules; $EXEC "$BASE_CMD" ;;
os|base|firewall|ssh|docker|docker_config)
install_modules; $EXEC "$BASE_CMD --tags '$TAG'" ;;
users)
install_modules
if [ "$1" = "--init" ]; then
$EXEC "$BASE_CMD --user root --tags '$TAG'"
else
$EXEC "$BASE_CMD --tags '$TAG'"
fi
;;
reboot)
install_modules; $EXEC "$BASE_CMD --tags '$TAG' --extra-vars 'do_reboot=true'" ;;
services)
install_modules
if [ "$1" = "--down" ]; then
ACTION="down"
shift
elif [ "$1" = "--restart" ]; then
ACTION="restart"
shift
elif [ "$1" = "--recreate" ]; then
ACTION="recreate"
shift
fi
SINGLE_SERVICE="$1"
if [ -z "$ACTION" ] && [ -n "$SINGLE_SERVICE" ]; then
VARS="single_service=$SINGLE_SERVICE"
elif [ -n "$ACTION" ] && [ -z "$SINGLE_SERVICE" ]; then
VARS="$ACTION=true"
elif [ -n "$ACTION" ] && [ -n "$SINGLE_SERVICE" ]; then
VARS='{"'$ACTION'": true, "single_service": "'$SINGLE_SERVICE'"}'
fi
$EXEC "$BASE_CMD --tags '$TAG' $(test -z "$VARS" || echo "--extra-vars '$VARS'")"
;;
--help)
usage ;;
*)
usage >&2; exit 1 ;;
esac

View file

@ -1,51 +0,0 @@
# 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"
username: samsapti
version: stable
samsapti_dev:
domain: samsapti.dev
onion: mldhltdackluvnqso7vk2azcg3ghjxbpw4im6alubymqkonb4kppqcqd.onion
volume: "{{ base_volume }}/samsapti.dev"
version: 1-alpine
simplexmq_smp:
domain: smp01.simplex.{{ base_domain }}
onion: pcexmrs4eod35vdvidq47jce7mnsfm26j27anttoy4zprc25pulkcfyd.onion
volume: "{{ base_volume }}/smp-server"
version: v5
simplexmq_xftp:
domain: xftp01.simplex.{{ base_domain }}
onion: n5vct5tnf4zoaigmfj4ppxzhgrslg3n4a4sp5yjppp6lfwvq7m2vn2id.onion
volume: "{{ base_volume }}/xftp-server"
quota: 50gb
version: v5
searxng:
domain: search.{{ base_domain }}
volume: "{{ base_volume }}/searxng"
version: latest
redis_version: 7-alpine
wkd:
domain: "{{ base_domain }}"
volume: "{{ base_volume }}/wkd"
version: 1-alpine
tor:
version: latest
watchtower:
version: '1.7.1'

View file

@ -1,10 +0,0 @@
{
"default-address-pools": [
{
"base": "172.17.0.0/16",
"size": 24
}
],
"experimental": true,
"ip6tables": true
}

View file

@ -1,52 +0,0 @@
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;
}

View file

@ -1,8 +0,0 @@
# vim: ft=yaml.ansible
---
- name: Reload Docker daemon
ansible.builtin.service:
name: docker
enabled: true
state: reloaded
listen: reload-dockerd

View file

@ -1,18 +0,0 @@
# vim: ft=yaml.ansible
---
- 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
notify: reload-dockerd
- name: Configure cron job to prune unused Docker data weekly
ansible.builtin.cron:
name: Prune unused Docker data
cron_file: ansible_docker_prune
job: 'docker system prune -fa && docker volume prune -fa'
special_time: weekly
user: root
state: present

View file

@ -1,52 +0,0 @@
# 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:
- docker_config
- name: Flush handlers
ansible.builtin.meta: flush_handlers
- name: Set up Docker services
ansible.builtin.import_tasks: services.yml
tags:
- services
- reboot

View file

@ -1,43 +0,0 @@
# vim: ft=yaml.ansible
---
- name: Create Docker network for services
community.docker.docker_network:
name: services
enable_ipv6: true
ipam_config:
- subnet: 172.17.2.0/24
- subnet: fd02::/64
state: present
- name: Create Docker network for Tor
community.docker.docker_network:
name: tor
enable_ipv6: true
ipam_config:
- subnet: 172.17.3.0/24
- subnet: fd03::/64
state: present
- 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 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
- 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

View file

@ -1,45 +0,0 @@
# 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: caddy/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 down is defined and down else 'started' }}"
restart: "{{ restart is defined and restart }}"
recreate: "{{ recreate is defined and recreate }}"
image: caddy:{{ services.caddy.version }}
restart_policy: always
default_host_ip: ''
networks:
- name: services
published_ports:
- 80:80/tcp
- 443:443/tcp
- 443:443/udp
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

View file

@ -1,118 +0,0 @@
# 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:
- web/transcripts
- prosody
loop_control:
loop_var: dir
- name: Create Jitsi Meet volume directories for Prosody
ansible.builtin.file:
path: "{{ services.jitsi_meet.volume }}/{{ dir }}"
owner: '101'
group: root
mode: u=rwx,g=rx,o=rx
state: directory
loop:
- prosody/plugins
- prosody/config
loop_control:
loop_var: dir
- name: Deploy Jitsi Meet with Docker Compose
community.docker.docker_compose:
project_name: jitsi_meet
state: "{{ 'absent' if down is defined and down else 'present' }}"
restarted: "{{ restart is defined and restart }}"
recreate: "{{ 'always' if recreate is defined and recreate else 'smart' }}"
remove_orphans: true
pull: true
definition:
version: '3.8'
services:
web:
image: jitsi/web:{{ services.jitsi_meet.version }}
restart: always
environment:
DISABLE_HTTPS: 1
PUBLIC_URL: "{{ services.jitsi_meet.domain }}"
ENABLE_AUTH: '1'
ENABLE_GUESTS: '1'
networks:
meet.jitsi:
services:
aliases:
- jitsi_meet
volumes:
- "{{ services.jitsi_meet.volume }}/web/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 }}"
ENABLE_AUTH: '1'
ENABLE_GUESTS: '1'
AUTH_TYPE: internal
networks:
meet.jitsi:
aliases:
- xmpp.meet.jitsi
volumes:
- "{{ services.jitsi_meet.volume }}/prosody/plugins:/prosody-plugins-custom:rw"
- "{{ services.jitsi_meet.volume }}/prosody/config:/config: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 }}"
ENABLE_AUTH: '1'
AUTH_TYPE: internal
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
- name: Check if Jitsi Meet user is registered
ansible.builtin.stat:
path: "{{ services.jitsi_meet.volume }}/prosody/config/data/meet%2ejitsi/accounts/{{ services.jitsi_meet.username }}.dat"
register: jitsi_meet_user
- name: Register Jitsi Meet user
community.docker.docker_container_exec:
container: jitsi_meet_prosody_1
command: |
/usr/bin/prosodyctl --config /config/prosody.cfg.lua register {{ services.jitsi_meet.username }} meet.jitsi {{ secrets.jitsi_meet.password }}
when: (down is undefined or not down) and
not jitsi_meet_user.stat.exists

View file

@ -1,27 +0,0 @@
# 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 down is defined and down else 'started' }}"
restart: "{{ restart is defined and restart }}"
recreate: "{{ recreate is defined and recreate }}"
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"

View file

@ -1,79 +0,0 @@
# vim: ft=yaml.ansible
---
- name: Create SearXNG volume directory
ansible.builtin.file:
path: "{{ services.searxng.volume }}/searxng"
owner: root
mode: u=rwx,g=rx,o=rx
state: directory
- name: Create SearXNG volume directory for Redis
ansible.builtin.file:
path: "{{ services.searxng.volume }}/redis"
owner: '999'
group: '1000'
mode: u=rwx,g=rx,o=rx
state: directory
- name: Copy SearXNG settings.yml file
ansible.builtin.template:
src: searxng/settings.yml.j2
dest: "{{ services.searxng.volume }}/searxng/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 down is defined and down else 'present' }}"
restarted: "{{ restart is defined and restart }}"
recreate: "{{ 'always' if recreate is defined and recreate else 'smart' }}"
remove_orphans: true
pull: true
definition:
version: '3.8'
services:
app:
image: searxng/searxng:{{ services.searxng.version }}
restart: always
environment:
SEARXNG_BASE_URL: https://{{ services.searxng.domain }}
networks:
default:
services:
aliases:
- searxng
volumes:
- "{{ services.searxng.volume }}/searxng/settings.yml:/etc/searxng/settings.yml:ro"
cap_add:
- chown
- dac_override
- setuid
- setgid
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 60 1 --appendonly no
volumes:
- "{{ services.searxng.volume }}/redis:/data:rw"
cap_add:
- dac_override
- setuid
- setgid
cap_drop:
- all
networks:
services:
external: true
tor:
external: true

View file

@ -1,36 +0,0 @@
# vim: ft=yaml.ansible
---
- name: Create SMP server volume directories
ansible.builtin.file:
name: "{{ services.simplexmq_smp.volume }}/{{ dir }}"
owner: root
mode: u=rwx,g=rx,o=rx
state: directory
loop:
- config
- logs
loop_control:
loop_var: dir
- name: Deploy SMP server Docker container
community.docker.docker_container:
name: smp-server
state: "{{ 'absent' if down is defined and down else 'started' }}"
restart: "{{ restart is defined and restart }}"
recreate: "{{ recreate is defined and recreate }}"
image: simplexchat/smp-server:{{ services.simplexmq_smp.version }}
restart_policy: always
default_host_ip: ''
networks:
- name: tor
aliases:
- smp-server
env:
ADDR: "{{ services.simplexmq_smp.domain }}"
volumes:
- "{{ services.simplexmq_smp.volume }}/config:/etc/opt/simplex:rw"
- "{{ services.simplexmq_smp.volume }}/logs:/var/opt/simplex:rw"
published_ports:
- 5223:5223/tcp
labels:
com.centurylinklabs.watchtower.stop-signal: SIGINT

View file

@ -1,39 +0,0 @@
# vim: ft=yaml.ansible
---
- name: Create XFTP server volume directories
ansible.builtin.file:
name: "{{ services.simplexmq_xftp.volume }}/{{ dir }}"
owner: root
mode: u=rwx,g=rx,o=rx
state: directory
loop:
- config
- logs
- files
loop_control:
loop_var: dir
- name: Deploy XFTP server Docker container
community.docker.docker_container:
name: xftp-server
state: "{{ 'absent' if down is defined and down else 'started' }}"
restart: "{{ restart is defined and restart }}"
recreate: "{{ recreate is defined and recreate }}"
image: simplexchat/xftp-server:{{ services.simplexmq_xftp.version }}
restart_policy: always
default_host_ip: ''
networks:
- name: tor
aliases:
- xftp-server
env:
ADDR: "{{ services.simplexmq_xftp.domain }}"
QUOTA: "{{ services.simplexmq_xftp.quota }}"
volumes:
- "{{ services.simplexmq_xftp.volume }}/config:/etc/opt/simplex-xftp:rw"
- "{{ services.simplexmq_xftp.volume }}/logs:/var/opt/simplex-xftp:rw"
- "{{ services.simplexmq_xftp.volume }}/files:/srv/xftp:rw"
published_ports:
- 5443:443/tcp
labels:
com.centurylinklabs.watchtower.stop-signal: SIGINT

View file

@ -1,29 +0,0 @@
# vim: ft=yaml.ansible
---
- name: Deploy Tor Docker container
community.docker.docker_container:
name: tor
state: "{{ 'absent' if down is defined and down else 'started' }}"
restart: "{{ restart is defined and restart }}"
recreate: "{{ recreate is defined and recreate }}"
image: goldy/tor-hidden-service:{{ services.tor.version }}
restart_policy: always
env:
# Required by SMP/XFTP server (we're not hosting anonymous services anyway)
TOR_EXTRA_OPTIONS: |
HiddenServiceNonAnonymousMode 1
HiddenServiceSingleHopMode 1
SAMSAPTIDEV_TOR_SERVICE_HOSTS: 80:samsapti:80
SAMSAPTIDEV_TOR_SERVICE_VERSION: '3'
SAMSAPTIDEV_TOR_SERVICE_KEY: "{{ secrets.tor.samsapti_dev_key }}"
SMPSERVER_TOR_SERVICE_HOSTS: 5223:smp-server:5223
SMPSERVER_TOR_SERVICE_VERSION: '3'
SMPSERVER_TOR_SERVICE_KEY: "{{ secrets.tor.simplexmq_smp_key }}"
XFTPSERVER_TOR_SERVICE_HOSTS: 5443:xftp-server:443
XFTPSERVER_TOR_SERVICE_VERSION: '3'
XFTPSERVER_TOR_SERVICE_KEY: "{{ secrets.tor.simplexmq_xftp_key }}"
networks:
- name: tor

View file

@ -1,21 +0,0 @@
# 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 down is defined and down else 'started' }}"
restart: "{{ restart is defined and restart }}"
recreate: "{{ recreate is defined and recreate }}"
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

View file

@ -1,31 +0,0 @@
# 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 down is defined and down else 'started' }}"
restart: "{{ restart is defined and restart }}"
recreate: "{{ recreate is defined and recreate }}"
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"

View file

@ -1,137 +0,0 @@
{
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.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"
-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}
}
}
}

View file

@ -1,97 +0,0 @@
# vim: ft=yaml
---
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 }}"
image_proxy: true
http_protocol_version: '1.1'
method: GET
limiter: true
public_instance: true
ui:
results_on_new_tab: false
center_alignment: true
theme_args:
simple_style: auto
redis:
url: redis://redis:6379/0
search:
formats:
- html
safe_search: 2
suspended_times:
SearxEngineAccessDenied: 0
SearxEngineCaptcha: 600
SearxEngineTooManyRequests: 600
cf_SearxEngineCaptcha: 600
cf_SearxEngineAccessDenied: 1200
recaptcha_SearxEngineCaptcha: 600
outgoing:
enable_http2: true
source_ips:
- 0.0.0.0
enabled_plugins:
- 'Hash plugin'
- 'Self Informations'
- 'Tracker URL remover'
- 'Hostname replace'
hostname_replace:
'^(.*\.)?youtube\.com$': 'yewtu.be'
'^(.*\.)?youtu\.be$': 'yewtu.be'
'^(.*\.)?youtube-noocookie\.com$': 'yewtu.be'
'^(www\.)?twitter\.com$': 'nitter.net'
'^(.*\.)?(m\.)?wiktionary\.org$': '\1m.wiktionary.org'
engines:
- name: bing
disabled: false
- name: brave
disabled: true
- name: ddg definitions
disabled: false
- name: duckduckgo
disabled: false
- name: duckduckgo images
disabled: false
- name: google
disabled: false
- name: mojeek
disabled: true
- name: qwant
disabled: true
- name: qwant images
disabled: false
- name: startpage
disabled: true
- name: wikidata
disabled: true
- name: wikinews
disabled: true
- name: yahoo
disabled: false

View file

@ -1,19 +0,0 @@
# 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

View file

@ -1,40 +0,0 @@
# 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

View file

@ -1,14 +0,0 @@
# vim: ft=yaml.ansible
---
- name: Allow necessary ports in UFW
community.general.ufw:
rule: allow
port: "{{ item.port }}"
proto: "{{ item.proto }}"
comment: "{{ item.comment }}"
loop: "{{ open_ports }}"
- name: Enable UFW
community.general.ufw:
state: enabled
policy: deny

View file

@ -1,26 +0,0 @@
# 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
tags:
- base
- name: Reboot if needed
ansible.builtin.import_tasks: reboot.yml
tags:
- reboot
- name: Configure firewall
ansible.builtin.import_tasks: firewall.yml
tags:
- firewall
- name: Configure SSH
ansible.builtin.import_tasks: ssh.yml
tags:
- ssh

View file

@ -1,23 +0,0 @@
# 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:
down: true
when: needs_reboot.stat.exists or
(do_reboot is defined and do_reboot)
- name: Reboot host
ansible.builtin.reboot:
when: needs_reboot.stat.exists or
(do_reboot is defined and do_reboot)
register: rebooted

View file

@ -1,25 +0,0 @@
# 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

View file

@ -1,18 +0,0 @@
# vim: ft=yaml.ansible
---
- name: Add users
ansible.builtin.user:
name: "{{ item.name }}"
comment: "{{ item.comment }}"
password: "{{ item.password }}"
groups: "{{ item.groups }}"
shell: /bin/bash
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 }}"

View file

@ -1,2 +0,0 @@
topic={{ secrets.ntfy_topic }}
hour=20