Initial commit

This commit is contained in:
Ivan R. 2024-09-29 18:04:34 +05:00
commit 3f72f0e751
No known key found for this signature in database
GPG key ID: 56C7BAAE859B302C
39 changed files with 720 additions and 0 deletions

34
Makefile Normal file
View file

@ -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

13
README.md Normal file
View file

@ -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 | |

6
common.yml Normal file
View file

@ -0,0 +1,6 @@
---
- hosts:
- network
- webservers
roles:
- role: common

4
docker.yml Normal file
View file

@ -0,0 +1,4 @@
---
- hosts: webservers
roles:
- role: docker

4
haproxy.yml Normal file
View file

@ -0,0 +1,4 @@
---
- hosts: webservers
roles:
- role: haproxy

13
inventory.ini Normal file
View file

@ -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

11
mastodon.yml Normal file
View file

@ -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 }}"

5
minio.yml Normal file
View file

@ -0,0 +1,5 @@
---
- hosts: webservers
roles:
- role: minio
minio_root_password: "{{ minio_root_password }}"

8
postgresql.yml Normal file
View file

@ -0,0 +1,8 @@
---
- hosts: webservers
roles:
- role: postgresql
postgres_password: "{{ postgres_password }}"
users:
mastodon: "{{ mastodon_postgresql_password }}"
vaultwarden: "{{ vaultwarden_postgresql_password }}"

3
requirements.yml Normal file
View file

@ -0,0 +1,3 @@
---
collections:
- name: ansible.posix

View file

@ -0,0 +1,5 @@
---
- name: Install vim
become: true
ansible.builtin.apt:
name: vim

View file

@ -0,0 +1,2 @@
---
- import_tasks: editor.yml

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,5 @@
save ""
appendonly no
maxmemory 64mb
maxmemory-policy allkeys-lru

View file

@ -0,0 +1 @@
save 60 1000

View file

@ -0,0 +1,3 @@
---
- import_tasks: redis.yml
- import_tasks: mastodon.yml

View file

@ -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

View file

@ -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

View file

@ -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 }}

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,3 @@
minio_version: RELEASE.2024-09-22T00-33-43Z
minio_root_user: lumin
minio_root_password: change_me

View file

@ -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;

View file

@ -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 }}"

View file

@ -0,0 +1,2 @@
postgres_password: change_me
users: []

13
roles/tls/README.md Normal file
View file

@ -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

41
roles/tls/tasks/main.yml Normal file
View file

@ -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 }}

View file

@ -0,0 +1 @@
dns_cloudflare_api_token = {{ dns_cloudflare_api_token }}

3
roles/tls/vars/main.yml Normal file
View file

@ -0,0 +1,3 @@
email: ordinarydev@protonmail.com
domain: comfycamp.space
dns_cloudflare_api_token: change_me

View file

@ -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

View file

@ -0,0 +1,2 @@
db_url: postgresql://vaultwarden:password@postgresql:5432/vaultwarden
domain: https://vault.comfycamp.space

View file

@ -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

View file

@ -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

5
tls.yml Normal file
View file

@ -0,0 +1,5 @@
---
- hosts: webservers
roles:
- role: tls
dns_cloudflare_api_token: "{{ dns_cloudflare_api_token }}"

52
vaulted_vars.yml Normal file
View file

@ -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

5
vaultwarden.yml Normal file
View file

@ -0,0 +1,5 @@
---
- hosts: webservers
roles:
- role: vaultwarden
db_url: postgresql://vaultwarden:{{ vaultwarden_postgresql_password }}@postgresql:5432/vaultwarden

4
wireguard.yml Normal file
View file

@ -0,0 +1,4 @@
---
- hosts: network
roles:
- role: wireguard