From 3f72f0e75187589f53d3fc754dbe2a4330665d99 Mon Sep 17 00:00:00 2001 From: Ivan Reshetnikov Date: Sun, 29 Sep 2024 18:04:34 +0500 Subject: [PATCH] Initial commit --- Makefile | 34 +++++++++ README.md | 13 ++++ common.yml | 6 ++ docker.yml | 4 ++ haproxy.yml | 4 ++ inventory.ini | 13 ++++ mastodon.yml | 11 +++ minio.yml | 5 ++ postgresql.yml | 8 +++ requirements.yml | 3 + roles/common/tasks/editor.yml | 5 ++ roles/common/tasks/main.yml | 2 + roles/docker/tasks/main.yml | 30 ++++++++ roles/haproxy/files/haproxy.cfg | 88 ++++++++++++++++++++++++ roles/haproxy/tasks/main.yml | 18 +++++ roles/mastodon/files/redis-cache.conf | 5 ++ roles/mastodon/files/redis.conf | 1 + roles/mastodon/tasks/main.yml | 3 + roles/mastodon/tasks/mastodon.yml | 64 +++++++++++++++++ roles/mastodon/tasks/redis.yml | 48 +++++++++++++ roles/mastodon/templates/mastodon.env.j2 | 34 +++++++++ roles/mastodon/vars/main.yml | 24 +++++++ roles/minio/tasks/main.yml | 31 +++++++++ roles/minio/vars/main.yml | 3 + roles/postgresql/files/create-user.sql | 10 +++ roles/postgresql/tasks/main.yml | 42 +++++++++++ roles/postgresql/vars/main.yml | 2 + roles/tls/README.md | 13 ++++ roles/tls/tasks/main.yml | 41 +++++++++++ roles/tls/templates/cloudflare.ini.j2 | 1 + roles/tls/vars/main.yml | 3 + roles/vaultwarden/tasks/main.yml | 21 ++++++ roles/vaultwarden/vars/main.yml | 2 + roles/wireguard/tasks/main.yml | 52 ++++++++++++++ roles/wireguard/templates/wg0.conf.j2 | 10 +++ tls.yml | 5 ++ vaulted_vars.yml | 52 ++++++++++++++ vaultwarden.yml | 5 ++ wireguard.yml | 4 ++ 39 files changed, 720 insertions(+) create mode 100644 Makefile create mode 100644 README.md create mode 100644 common.yml create mode 100644 docker.yml create mode 100644 haproxy.yml create mode 100644 inventory.ini create mode 100644 mastodon.yml create mode 100644 minio.yml create mode 100644 postgresql.yml create mode 100644 requirements.yml create mode 100644 roles/common/tasks/editor.yml create mode 100644 roles/common/tasks/main.yml create mode 100644 roles/docker/tasks/main.yml create mode 100644 roles/haproxy/files/haproxy.cfg create mode 100644 roles/haproxy/tasks/main.yml create mode 100644 roles/mastodon/files/redis-cache.conf create mode 100644 roles/mastodon/files/redis.conf create mode 100644 roles/mastodon/tasks/main.yml create mode 100644 roles/mastodon/tasks/mastodon.yml create mode 100644 roles/mastodon/tasks/redis.yml create mode 100644 roles/mastodon/templates/mastodon.env.j2 create mode 100644 roles/mastodon/vars/main.yml create mode 100644 roles/minio/tasks/main.yml create mode 100644 roles/minio/vars/main.yml create mode 100644 roles/postgresql/files/create-user.sql create mode 100644 roles/postgresql/tasks/main.yml create mode 100644 roles/postgresql/vars/main.yml create mode 100644 roles/tls/README.md create mode 100644 roles/tls/tasks/main.yml create mode 100644 roles/tls/templates/cloudflare.ini.j2 create mode 100644 roles/tls/vars/main.yml create mode 100644 roles/vaultwarden/tasks/main.yml create mode 100644 roles/vaultwarden/vars/main.yml create mode 100644 roles/wireguard/tasks/main.yml create mode 100644 roles/wireguard/templates/wg0.conf.j2 create mode 100644 tls.yml create mode 100644 vaulted_vars.yml create mode 100644 vaultwarden.yml create mode 100644 wireguard.yml diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..bb7835e --- /dev/null +++ b/Makefile @@ -0,0 +1,34 @@ +all: networkvm webserver + +common_args := -i inventory.ini --ask-vault-pass -e@vaulted_vars.yml + +common: + ansible-playbook $(common_args) common.yml + +networkvm: wireguard + +webserver: tls haproxy docker minio postgresql mastodon vaultwarden + +wireguard: + ansible-playbook $(common_args) wireguard.yml + +tls: + ansible-playbook $(common_args) tls.yml + +haproxy: + ansible-playbook $(common_args) haproxy.yml + +docker: + ansible-playbook $(common_args) docker.yml + +minio: + ansible-playbook $(common_args) minio.yml + +postgresql: + ansible-playbook $(common_args) postgresql.yml + +mastodon: + ansible-playbook $(common_args) mastodon.yml + +vaultwarden: + ansible-playbook $(common_args) vaultwarden.yml diff --git a/README.md b/README.md new file mode 100644 index 0000000..4ed6383 --- /dev/null +++ b/README.md @@ -0,0 +1,13 @@ +# Home server configuration + +Available at [comfycamp.space](https://comfycamp.space). + +## Ports + +| Number | Service | Public URL | +| --- | --- | --- | +| 3000 | Mastodon | [m.comfycamp.space](https://m.comfycamp.space) | +| 3001 | Mastodon streaming | | +| 3002 | Vaultwarden | | +| 3003 | Minio console | | +| 9000 | Minio | | diff --git a/common.yml b/common.yml new file mode 100644 index 0000000..6c50a4d --- /dev/null +++ b/common.yml @@ -0,0 +1,6 @@ +--- +- hosts: + - network + - webservers + roles: + - role: common diff --git a/docker.yml b/docker.yml new file mode 100644 index 0000000..7aa8131 --- /dev/null +++ b/docker.yml @@ -0,0 +1,4 @@ +--- +- hosts: webservers + roles: + - role: docker diff --git a/haproxy.yml b/haproxy.yml new file mode 100644 index 0000000..b24bd8e --- /dev/null +++ b/haproxy.yml @@ -0,0 +1,4 @@ +--- +- hosts: webservers + roles: + - role: haproxy diff --git a/inventory.ini b/inventory.ini new file mode 100644 index 0000000..94c973c --- /dev/null +++ b/inventory.ini @@ -0,0 +1,13 @@ +[webservers] +192.168.0.39 ansible_ssh_private_key_file=~/.ssh/root_server ansible_become_pass='{{ webserver_become_pass }}' + +[webservers:vars] +ansible_become_method=su +ansible_become_user=root + +[network] +192.168.0.42 ansible_ssh_private_key_file=~/.ssh/network_vm ansible_become_pass='{{ network_vm_become_pass }}' + +[network:vars] +ansible_become_method=su +ansible_become_user=root diff --git a/mastodon.yml b/mastodon.yml new file mode 100644 index 0000000..36ecbd2 --- /dev/null +++ b/mastodon.yml @@ -0,0 +1,11 @@ +--- +- hosts: webservers + roles: + - role: mastodon + vapid_public_key: "{{ mastodon_vapid_public_key }}" + vapid_private_key: "{{ mastodon_vapid_private_key }}" + db_pass: "{{ mastodon_postgresql_password }}" + otp_secret: "{{ mastodon_otp_secret }}" + secret_key_base: "{{ mastodon_secret_key_base }}" + smtp_password: "{{ mastodon_smtp_password }}" + aws_secret_access_key: "{{ mastodon_aws_secret_access_key }}" diff --git a/minio.yml b/minio.yml new file mode 100644 index 0000000..09563fb --- /dev/null +++ b/minio.yml @@ -0,0 +1,5 @@ +--- +- hosts: webservers + roles: + - role: minio + minio_root_password: "{{ minio_root_password }}" diff --git a/postgresql.yml b/postgresql.yml new file mode 100644 index 0000000..040a789 --- /dev/null +++ b/postgresql.yml @@ -0,0 +1,8 @@ +--- +- hosts: webservers + roles: + - role: postgresql + postgres_password: "{{ postgres_password }}" + users: + mastodon: "{{ mastodon_postgresql_password }}" + vaultwarden: "{{ vaultwarden_postgresql_password }}" diff --git a/requirements.yml b/requirements.yml new file mode 100644 index 0000000..a0cd255 --- /dev/null +++ b/requirements.yml @@ -0,0 +1,3 @@ +--- +collections: + - name: ansible.posix diff --git a/roles/common/tasks/editor.yml b/roles/common/tasks/editor.yml new file mode 100644 index 0000000..2d231ad --- /dev/null +++ b/roles/common/tasks/editor.yml @@ -0,0 +1,5 @@ +--- +- name: Install vim + become: true + ansible.builtin.apt: + name: vim diff --git a/roles/common/tasks/main.yml b/roles/common/tasks/main.yml new file mode 100644 index 0000000..0ce9bab --- /dev/null +++ b/roles/common/tasks/main.yml @@ -0,0 +1,2 @@ +--- +- import_tasks: editor.yml diff --git a/roles/docker/tasks/main.yml b/roles/docker/tasks/main.yml new file mode 100644 index 0000000..eaf59d0 --- /dev/null +++ b/roles/docker/tasks/main.yml @@ -0,0 +1,30 @@ +--- +- name: Install dependencies + become: true + ansible.builtin.apt: + pkg: + - curl + - ca-certificates + - python3-pip + - python3-docker + - python3-requests +- name: Download docker keyring + become: true + ansible.builtin.get_url: + url: https://download.docker.com/linux/debian/gpg + dest: /etc/apt/keyrings/docker.asc + mode: '0644' +- name: Add docker source + become: true + ansible.builtin.apt_repository: + repo: deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian bookworm stable + state: present + filename: docker +- name: Install docker engine + become: true + ansible.builtin.apt: + pkg: + - docker-ce + - docker-ce-cli + - containerd.io + update_cache: yes diff --git a/roles/haproxy/files/haproxy.cfg b/roles/haproxy/files/haproxy.cfg new file mode 100644 index 0000000..12823a3 --- /dev/null +++ b/roles/haproxy/files/haproxy.cfg @@ -0,0 +1,88 @@ +global + log /dev/log local0 + log /dev/log local1 notice + chroot /var/lib/haproxy + stats socket /run/haproxy/admin.sock mode 660 level admin + stats timeout 30s + user haproxy + group haproxy + daemon + + # Default SSL material locations + ca-base /etc/ssl/certs + crt-base /etc/ssl/private + + # See: https://ssl-config.mozilla.org/#server=haproxy&server-version=2.0.3&config=intermediate + ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384 + ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256 + ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets + +defaults + log global + mode http + option httplog + option dontlognull + timeout connect 5000 + timeout client 50000 + timeout server 50000 + errorfile 400 /etc/haproxy/errors/400.http + errorfile 403 /etc/haproxy/errors/403.http + errorfile 408 /etc/haproxy/errors/408.http + errorfile 500 /etc/haproxy/errors/500.http + errorfile 502 /etc/haproxy/errors/502.http + errorfile 503 /etc/haproxy/errors/503.http + errorfile 504 /etc/haproxy/errors/504.http + +frontend www + mode http + bind :80 + bind :443 ssl crt /etc/haproxy/certs + http-request redirect scheme https unless { ssl_fc } + http-request set-header X-Forwarded-Proto https if { ssl_fc } + http-request set-header X-Forwarded-Proto http if !{ ssl_fc } + + acl acl_mastodon hdr(host) -i m.comfycamp.space + acl acl_s3 hdr(host) -i s3.comfycamp.space + acl acl_comfycamp hdr(host) -i comfycamp.space + acl acl_vaultwarden hdr(host) -i vault.comfycamp.space + acl acl_minio hdr(host) -i minio.comfycamp.space + + use_backend mastodon_streaming if acl_mastodon { path_beg /api/v1/streaming } + use_backend mastodon if acl_mastodon + use_backend minio if acl_s3 + use_backend minio_console if acl_minio + use_backend vaultwarden if acl_vaultwarden + use_backend comfycamp if acl_comfycamp + + +backend comfycamp + mode http + server green 127.0.0.1:8080 check + +backend mastodon + mode http + option forwardfor + server green 127.0.0.1:3000 check + +backend mastodon_streaming + mode http + option forwardfor + option http-server-close + timeout tunnel 1h + server green 127.0.0.1:3001 check + +backend vaultwarden + mode http + option forwardfor + server green 127.0.0.1:3002 check + +backend minio_console + mode http + option forwardfor + server green 127.0.0.1:3003 check + +backend minio + mode http + http-response set-header Access-Control-Allow-Origin https://m.comfycamp.space + option forwardfor + server green 127.0.0.1:9000 check diff --git a/roles/haproxy/tasks/main.yml b/roles/haproxy/tasks/main.yml new file mode 100644 index 0000000..19812b2 --- /dev/null +++ b/roles/haproxy/tasks/main.yml @@ -0,0 +1,18 @@ +--- +- name: Install haproxy + become: true + ansible.builtin.apt: + name: haproxy +- name: Copy haproxy config + become: true + ansible.builtin.copy: + src: haproxy.cfg + dest: /etc/haproxy/haproxy.cfg + validate: /usr/sbin/haproxy -f %s -c + register: haproxy +- name: Reload haproxy + become: true + when: haproxy.changed + ansible.builtin.systemd_service: + name: haproxy + state: reloaded diff --git a/roles/mastodon/files/redis-cache.conf b/roles/mastodon/files/redis-cache.conf new file mode 100644 index 0000000..d258a4d --- /dev/null +++ b/roles/mastodon/files/redis-cache.conf @@ -0,0 +1,5 @@ +save "" +appendonly no + +maxmemory 64mb +maxmemory-policy allkeys-lru diff --git a/roles/mastodon/files/redis.conf b/roles/mastodon/files/redis.conf new file mode 100644 index 0000000..3628768 --- /dev/null +++ b/roles/mastodon/files/redis.conf @@ -0,0 +1 @@ +save 60 1000 diff --git a/roles/mastodon/tasks/main.yml b/roles/mastodon/tasks/main.yml new file mode 100644 index 0000000..1a950c2 --- /dev/null +++ b/roles/mastodon/tasks/main.yml @@ -0,0 +1,3 @@ +--- +- import_tasks: redis.yml +- import_tasks: mastodon.yml diff --git a/roles/mastodon/tasks/mastodon.yml b/roles/mastodon/tasks/mastodon.yml new file mode 100644 index 0000000..9b8e1a3 --- /dev/null +++ b/roles/mastodon/tasks/mastodon.yml @@ -0,0 +1,64 @@ +--- +- name: Create mastodon's public volume + become: true + community.docker.docker_volume: + name: mastodon-public-system +- name: Create mastodon config directory + become: true + ansible.builtin.file: + path: /etc/mastodon + state: directory + mode: '1750' + owner: root + group: root +- name: Copy env file + become: true + ansible.builtin.template: + src: mastodon.env.j2 + dest: /etc/mastodon/.env + mode: '0660' + owner: root + group: root +- name: Create web container + become: true + community.docker.docker_container: + name: mastodon-web + image: ghcr.io/mastodon/mastodon:v4.2.12 + env_file: /etc/mastodon/.env + command: ["bundle", "exec", "puma", "-C", "config/puma.rb"] + networks: + - name: redis-mastodon + - name: postgresql + - name: minio + ports: + - 127.0.0.1:3000:3000 + volumes: + - mastodon-public-system:/mastodon/public/system + restart_policy: unless-stopped +- name: Create streaming container + become: true + community.docker.docker_container: + name: mastodon-streaming + image: ghcr.io/mastodon/mastodon-streaming:nightly.2024-08-19 + env_file: /etc/mastodon/.env + command: ["node", "./streaming/index.js"] + networks: + - name: redis-mastodon + - name: postgresql + ports: + - 127.0.0.1:3001:4000 + restart_policy: unless-stopped +- name: Create sidekiq container + become: true + community.docker.docker_container: + name: mastodon-sidekiq + image: ghcr.io/mastodon/mastodon:v4.2.12 + env_file: /etc/mastodon/.env + command: ["bundle", "exec", "sidekiq"] + networks: + - name: redis-mastodon + - name: postgresql + - name: minio + volumes: + - mastodon-public-system:/mastodon/public/system + restart_policy: unless-stopped diff --git a/roles/mastodon/tasks/redis.yml b/roles/mastodon/tasks/redis.yml new file mode 100644 index 0000000..1f45fdb --- /dev/null +++ b/roles/mastodon/tasks/redis.yml @@ -0,0 +1,48 @@ +--- +- name: Create docker network + become: true + community.docker.docker_network: + name: redis-mastodon + +- name: Create redis docker volume + become: true + community.docker.docker_volume: + name: redis-mastodon +- name: Create redis cache docker volume + become: true + community.docker.docker_volume: + name: redis-mastodon-cache + +- name: Copy redis config + become: true + ansible.builtin.copy: + src: redis.conf + dest: /var/lib/docker/volumes/redis-mastodon/_data/redis.conf +- name: Copy redis cache config + become: true + ansible.builtin.copy: + src: redis-cache.conf + dest: /var/lib/docker/volumes/redis-mastodon-cache/_data/redis.conf + +- name: Create redis container + become: true + community.docker.docker_container: + name: redis-mastodon + image: redis:7.4-bookworm + command: ["redis-server", "/data/redis.conf"] + networks: + - name: redis-mastodon + volumes: + - redis-mastodon:/data + restart_policy: unless-stopped +- name: Create redis cache container + become: true + community.docker.docker_container: + name: redis-mastodon-cache + image: redis:7.4-bookworm + command: ["redis-server", "/data/redis.conf"] + networks: + - name: redis-mastodon + volumes: + - redis-mastodon-cache:/data + restart_policy: unless-stopped diff --git a/roles/mastodon/templates/mastodon.env.j2 b/roles/mastodon/templates/mastodon.env.j2 new file mode 100644 index 0000000..33276c1 --- /dev/null +++ b/roles/mastodon/templates/mastodon.env.j2 @@ -0,0 +1,34 @@ +LOCAL_DOMAIN={{ local_domain }} + +REDIS_HOST=redis-mastodon +REDIS_PORT=6379 + +CACHE_REDIS_HOST=redis-mastodon-cache +CACHE_REDIS_PORT=6379 + +DB_HOST={{ db_host }} +DB_USER={{ db_user }} +DB_NAME={{ db_name }} +DB_PASS={{ db_pass }} +DB_PORT={{ db_port }} + +SECRET_KEY_BASE={{ secret_key_base }} +OTP_SECRET={{ otp_secret }} + +VAPID_PRIVATE_KEY={{ vapid_private_key }} +VAPID_PUBLIC_KEY={{ vapid_public_key }} + +SMTP_SERVER={{ smtp_server }} +SMTP_PORT={{ smtp_port }} +SMTP_LOGIN={{ smtp_login }} +SMTP_PASSWORD={{ smtp_password }} +SMTP_FROM_ADDRESS={{ smtp_from_address }} + +S3_ENABLED=true +S3_ENDPOINT={{ s3_endpoint }} +S3_BUCKET={{ s3_bucket }} +AWS_ACCESS_KEY_ID={{ aws_access_key_id }} +AWS_SECRET_ACCESS_KEY={{ aws_secret_access_key }} + +S3_PROTOCOL=https +S3_HOSTNAME={{ s3_hostname }} diff --git a/roles/mastodon/vars/main.yml b/roles/mastodon/vars/main.yml new file mode 100644 index 0000000..eede2c7 --- /dev/null +++ b/roles/mastodon/vars/main.yml @@ -0,0 +1,24 @@ +local_domain: m.comfycamp.space + +vapid_public_key: change_me +vapid_private_key: change_me +otp_secret: change_me +secret_key_base: change_me + +db_host: postgresql +db_user: mastodon +db_name: mastodon +db_pass: change_me +db_port: "5432" + +smtp_server: comfycamp.space +smtp_port: "465" +smtp_login: mastodon@comfycamp.space +smtp_password: change_me +smtp_from_address: mastodon@comfycamp.space + +s3_endpoint: http://minio:9000 +s3_hostname: s3.comfycamp.space +s3_bucket: mastodon +aws_access_key_id: WfSoEsOL1Glg9GXc3sRN +aws_secret_access_key: change_me diff --git a/roles/minio/tasks/main.yml b/roles/minio/tasks/main.yml new file mode 100644 index 0000000..bc16b14 --- /dev/null +++ b/roles/minio/tasks/main.yml @@ -0,0 +1,31 @@ +--- +- name: Create minio volume + become: true + community.docker.docker_volume: + name: minio +- name: Create minio network + become: true + community.docker.docker_network: + name: minio +- name: Run minio container + become: true + community.docker.docker_container: + name: minio + image: minio/minio:{{ minio_version }} + command: ["minio", "server", "--console-address", ":9001"] + networks: + - name: minio + volumes: + - minio:/data + ports: + - 127.0.0.1:3003:9001 + - 127.0.0.1:9000:9000 + env: + MINIO_ROOT_USER: "{{ minio_root_user }}" + MINIO_ROOT_PASSWORD: "{{ minio_root_password }}" + MINIO_VOLUMES: /data + restart_policy: unless-stopped +- name: Install rclone + become: true + ansible.builtin.apt: + name: rclone diff --git a/roles/minio/vars/main.yml b/roles/minio/vars/main.yml new file mode 100644 index 0000000..3682dcb --- /dev/null +++ b/roles/minio/vars/main.yml @@ -0,0 +1,3 @@ +minio_version: RELEASE.2024-09-22T00-33-43Z +minio_root_user: lumin +minio_root_password: change_me diff --git a/roles/postgresql/files/create-user.sql b/roles/postgresql/files/create-user.sql new file mode 100644 index 0000000..1ecb3f2 --- /dev/null +++ b/roles/postgresql/files/create-user.sql @@ -0,0 +1,10 @@ +CREATE OR REPLACE FUNCTION create_user_if_not_exists(username TEXT, passwd TEXT) +RETURNS VOID AS \$\$ +BEGIN + IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = username) THEN + EXECUTE format('CREATE ROLE %I LOGIN PASSWORD %L', username, passwd); + ELSE + RAISE NOTICE 'User % already exists.', username; + END IF; +END; +\$\$ LANGUAGE plpgsql; diff --git a/roles/postgresql/tasks/main.yml b/roles/postgresql/tasks/main.yml new file mode 100644 index 0000000..56232ec --- /dev/null +++ b/roles/postgresql/tasks/main.yml @@ -0,0 +1,42 @@ +--- +- name: Create docker network + become: true + community.docker.docker_network: + name: postgresql +- name: Create docker volume + become: true + community.docker.docker_volume: + name: postgresql +- name: Create postgresql container + become: true + community.docker.docker_container: + name: postgresql + image: postgres:16.4-bookworm + networks: + - name: postgresql + volumes: + - postgresql:/var/lib/postgresql/data + env: + POSTGRES_USER: postgres + POSTGRES_DB: postgres + POSTGRES_PASSWORD: "{{ postgres_password }}" + restart_policy: unless-stopped +- name: Create a function to manage users + become: true + community.docker.docker_container_exec: + container: postgresql + argv: + - /bin/bash + - "-c" + - echo "{{ lookup('file', 'create-user.sql') }}" | psql -U postgres +- name: Create roles + become: true + community.docker.docker_container_exec: + container: postgresql + argv: + - /bin/bash + - "-c" + - echo "SELECT create_user_if_not_exists('{{ item.key }}', '{{ item.value }}')" | psql -U postgres + no_log: True + loop: + "{{ users | dict2items }}" diff --git a/roles/postgresql/vars/main.yml b/roles/postgresql/vars/main.yml new file mode 100644 index 0000000..ae4b0af --- /dev/null +++ b/roles/postgresql/vars/main.yml @@ -0,0 +1,2 @@ +postgres_password: change_me +users: [] diff --git a/roles/tls/README.md b/roles/tls/README.md new file mode 100644 index 0000000..7ddc306 --- /dev/null +++ b/roles/tls/README.md @@ -0,0 +1,13 @@ +# TLS + +This role will install certbot with cloudflare plugin, +issue a wildcard certificate for your domain, and prepare it for use in haproxy. + +Certbot should automatically set a systemd timer to renew certificates. + +## Created files + +- `/etc/certbot/cloudflare.ini` +- `/etc/letsencrypt/live/{{ domain }}/fullchain.pem` +- `/etc/letsencrypt/live/{{ domain }}/privkey.pem` +- `/etc/haproxy/certs/{{ domain }}.pem` - fullchain + privkey diff --git a/roles/tls/tasks/main.yml b/roles/tls/tasks/main.yml new file mode 100644 index 0000000..fe5d333 --- /dev/null +++ b/roles/tls/tasks/main.yml @@ -0,0 +1,41 @@ +--- +- name: Install certbot + become: true + ansible.builtin.apt: + pkg: + - certbot + - python3-certbot-dns-cloudflare +- name: Create certbot directory + become: true + ansible.builtin.file: + path: /etc/certbot + state: directory + owner: root + group: root + mode: '1750' +- name: Copy cloudflare credentials + become: true + ansible.builtin.template: + src: cloudflare.ini.j2 + dest: /etc/certbot/cloudflare.ini + owner: root + group: root + mode: '0660' +- name: Issue certificates + become: true + ansible.builtin.shell: + certbot certonly -n --agree-tos --expand --email {{ email }} --dns-cloudflare --dns-cloudflare-credentials /etc/certbot/cloudflare.ini -d {{ domain }} -d '*.{{ domain }}' + args: + creates: /etc/letsencrypt/live/{{ domain }}/fullchain.pem +- name: Create a directory to store combined files + become: true + ansible.builtin.file: + path: /etc/haproxy/certs + state: directory + mode: '1750' +- name: Combine certificate and private key + become: true + ansible.builtin.shell: + cat fullchain.pem privkey.pem > /etc/haproxy/certs/{{ domain }}.pem + args: + chdir: /etc/letsencrypt/live/{{ domain }} diff --git a/roles/tls/templates/cloudflare.ini.j2 b/roles/tls/templates/cloudflare.ini.j2 new file mode 100644 index 0000000..2073297 --- /dev/null +++ b/roles/tls/templates/cloudflare.ini.j2 @@ -0,0 +1 @@ +dns_cloudflare_api_token = {{ dns_cloudflare_api_token }} diff --git a/roles/tls/vars/main.yml b/roles/tls/vars/main.yml new file mode 100644 index 0000000..18e594a --- /dev/null +++ b/roles/tls/vars/main.yml @@ -0,0 +1,3 @@ +email: ordinarydev@protonmail.com +domain: comfycamp.space +dns_cloudflare_api_token: change_me diff --git a/roles/vaultwarden/tasks/main.yml b/roles/vaultwarden/tasks/main.yml new file mode 100644 index 0000000..a289b05 --- /dev/null +++ b/roles/vaultwarden/tasks/main.yml @@ -0,0 +1,21 @@ +--- +- name: Create vaultwarden docker volume + become: true + community.docker.docker_volume: + name: vaultwarden +- name: Create vaultwarden container + become: true + community.docker.docker_container: + name: vaultwarden + image: vaultwarden/server:1.32.0 + env: + DOMAIN: "{{ domain }}" + LOG_LEVEL: warn + DATABASE_URL: "{{ db_url }}" + networks: + - name: postgresql + ports: + - 127.0.0.1:3002:80 + volumes: + - vaultwarden:/data + restart_policy: unless-stopped diff --git a/roles/vaultwarden/vars/main.yml b/roles/vaultwarden/vars/main.yml new file mode 100644 index 0000000..af8fe12 --- /dev/null +++ b/roles/vaultwarden/vars/main.yml @@ -0,0 +1,2 @@ +db_url: postgresql://vaultwarden:password@postgresql:5432/vaultwarden +domain: https://vault.comfycamp.space diff --git a/roles/wireguard/tasks/main.yml b/roles/wireguard/tasks/main.yml new file mode 100644 index 0000000..5d7357a --- /dev/null +++ b/roles/wireguard/tasks/main.yml @@ -0,0 +1,52 @@ +--- +- name: Install wireguard and iptables + become: true + ansible.builtin.apt: + pkg: + - wireguard + - iptables +- name: Create wireguard directory + become: true + ansible.builtin.file: + path: /etc/wireguard + state: directory + mode: '1750' +- name: Generate private key + become: true + ansible.builtin.shell: | + umask 077 + wg genkey > private_key + args: + chdir: /etc/wireguard + creates: private_key +- name: Generate public key + become: true + ansible.builtin.shell: | + umask 077 + cat private_key | wg pubkey > public_key + args: + chdir: /etc/wireguard + creates: public_key +- name: Enable packet forwarding + become: true + ansible.posix.sysctl: + name: net.ipv4.ip_forward + value: '1' + state: present + reload: true +- name: Read private key + become: true + ansible.builtin.slurp: + path: /etc/wireguard/private_key + register: private_key +- name: Copy wireguard config + become: true + ansible.builtin.template: + src: wg0.conf.j2 + dest: /etc/wireguard/wg0.conf +- name: Enable wireguard service + become: true + ansible.builtin.systemd_service: + name: wg-quick@wg0 + state: restarted + enabled: true diff --git a/roles/wireguard/templates/wg0.conf.j2 b/roles/wireguard/templates/wg0.conf.j2 new file mode 100644 index 0000000..785b3c6 --- /dev/null +++ b/roles/wireguard/templates/wg0.conf.j2 @@ -0,0 +1,10 @@ +[Interface] +PrivateKey = {{ private_key.content | b64decode }} +Address = 10.110.0.1/24 +ListenPort = 51840 +PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o ens18 -j MASQUERADE +PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -o ens18 -j MASQUERADE + +[Peer] +PublicKey = awAVP/tkl0Z9PKEMTABjIXhblWSGHhIvYjBFp3C7YUk= +AllowedIPs = 10.110.0.2/32 diff --git a/tls.yml b/tls.yml new file mode 100644 index 0000000..7148a20 --- /dev/null +++ b/tls.yml @@ -0,0 +1,5 @@ +--- +- hosts: webservers + roles: + - role: tls + dns_cloudflare_api_token: "{{ dns_cloudflare_api_token }}" diff --git a/vaulted_vars.yml b/vaulted_vars.yml new file mode 100644 index 0000000..4aa6ccb --- /dev/null +++ b/vaulted_vars.yml @@ -0,0 +1,52 @@ +$ANSIBLE_VAULT;1.1;AES256 +36316363396534613033333531386165353335363961316133363862333864656435396137333335 +3431376131663962656632333563373162313066323835620a313961653764303462343563353064 +65393361356530373764396264636235353435363162663865396232333861323064633538306563 +3830356338353433340a383165643938333938623434633839613835313736646633326238363636 +30613838303933333161393236363531613662616638326138613262626631613061346132306663 +38323336363930313834323131303430663866613264356630303133323964353635386635383165 +64386432643930643935343731383131653662353166376434373635343962343139666134613161 +36663261343234396533313662386330363465653164633162386339363461313163316237643566 +39386537656165356330386533643164616633326264313961326166323964316336386662393830 +61616130373466363861623137393530326164383663303237633631303930653633666235396435 +65666535366133333365353233656464663338363763643363656562376131353230333763656462 +34376431656563613964623739623735613931396439343432386131663032386161336461343232 +61336462393931633065393330626230383237666235303266333736333863356630653139313134 +65343463356137363633373839323461626139393163646531613465313037353466636566373839 +62656234386663616461616430353865653834623933333438313463656439316465643762396262 +33363834313938336135323064393331383132613234643837393934616262346536623532666635 +39303337313964666665336562643065653861623866326232323438363164346639613433316235 +39303633383038326661313031613536313265353333653239613138666439343533333934336638 +39656235316662363862326664323035306666646434383539366563643532393762636233653832 +63336131363931386432333764306464303866653064346233613338333636346536626436636438 +33633431386135666138363661353866623966343638316261396132303866383161643538393663 +31343833343462363530633065636561363466333334303730643333316437613963623536623438 +32646530653838653332353635613066613761643161643639383331636332616138623936363139 +34386661303233316439656239356463366130356665366639613031383130626330363531633238 +63343532356635666233393665663832666161353735326337666637303032396434633135323832 +38373563333637386264633430346638376433323234623562643230623564616432653431623135 +32376363353065323230363564353461623162326635323539626237376239643061363035343436 +62333261326131303333643537316162316662303432353162653933373530656432373266326135 +61343235626238353864643630353630303532613031356239353532396338306539333538336639 +66366533666364383837343236333130396265366230376333383231383464383364616233366136 +33316134383430623662363163373538323161333061313562363363663865336131343832666134 +35656563366438363565613439663161323565363330316661353764393533316238323332386364 +30653336616664643565363261613936353831343364393562663933323731313334623038363539 +36333133633035643433396339353931626433363036303135323864323465316565323730343832 +36336362343634656436346131333137613035626434323434663539313131626363373266323236 +31373963663736353833356237643630353837386534306362306138363834633863386434363731 +31366666633661323638613136396133646666643436613232633439346565323036313238663863 +31333231616462396133623839383961623039306363653532303262363532313063396235356362 +33306661313464323738663132663666333630353039656366303534613364376639366563343161 +36333535383532363966323439396666646162313562633462643837643363623137366232383065 +63633265366135613963316536663538346661353832383364653935313236353131653664396663 +64306234663438353233646539343439643462363238323539396136343232303531313837653235 +34343536633430383565356263643730343539346139343935323333636535666461663764373434 +35376239643833343233663933656464623861373961363363616537313861353238396665353366 +63363331663630353966306264386138396434646335386564646233303735323062363135343931 +35393339653934363138646463393034613561333063313235346135386532356331373162366433 +65396330326662653237336431393861613932646233313061373532363364616438626433336463 +33333530303130326361343663613030623262353137366536323062333636393463356434346638 +33383132336431356631303638393964646231626361383638393838623334636338313661316232 +61383131623133376331383239393765346335373530346231353161616433633064316633343533 +376235356632396563306361653663336366 diff --git a/vaultwarden.yml b/vaultwarden.yml new file mode 100644 index 0000000..f621c6b --- /dev/null +++ b/vaultwarden.yml @@ -0,0 +1,5 @@ +--- +- hosts: webservers + roles: + - role: vaultwarden + db_url: postgresql://vaultwarden:{{ vaultwarden_postgresql_password }}@postgresql:5432/vaultwarden diff --git a/wireguard.yml b/wireguard.yml new file mode 100644 index 0000000..58139e5 --- /dev/null +++ b/wireguard.yml @@ -0,0 +1,4 @@ +--- +- hosts: network + roles: + - role: wireguard