Compare commits
10 Commits
4fd1ae556e
...
37350776bf
Author | SHA1 | Date | |
---|---|---|---|
37350776bf | |||
f761f69683 | |||
a5ddb4f7f6 | |||
2227a2c0aa | |||
ce4c85dd6f | |||
ae64628958 | |||
fb0b391408 | |||
b62d5f559b | |||
fdd85fb735 | |||
e67eff6acc |
7
.env.sample
Normal file
7
.env.sample
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
HEADSCALE_PREAUTH_KEY=
|
||||||
|
HEADSCALE_OIDC_SECRET=
|
||||||
|
LLDAP_USER_PASS=
|
||||||
|
LLDAP_JWT_SECRET=
|
||||||
|
PIHOLE_WEBPWD=
|
||||||
|
STEP_CA_ROOT_PASSWORD=
|
||||||
|
STEP_CA_INTERMEDIATE_PASSWORD=
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,2 +1,3 @@
|
|||||||
**/*.swp
|
**/*.swp
|
||||||
*.swp
|
*.swp
|
||||||
|
.env
|
||||||
|
9
README.md
Normal file
9
README.md
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
order:
|
||||||
|
- deploy-common.yml
|
||||||
|
- deploy-nameservers.yml
|
||||||
|
- deploy-webservers.yml
|
||||||
|
- deploy-lldap.yml
|
||||||
|
- deploy-authelia.yml
|
||||||
|
- deploy-pihole.yml
|
||||||
|
- deploy-vpn.yml
|
||||||
|
- deploy-vpn-hosts.yml
|
4
deploy-authelia.yml
Normal file
4
deploy-authelia.yml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
- name: authelia setup
|
||||||
|
hosts: authelia
|
||||||
|
roles:
|
||||||
|
- authelia
|
31
deploy-ca.yml
Normal file
31
deploy-ca.yml
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
- name: add acme CA
|
||||||
|
hosts: ca
|
||||||
|
become: yes
|
||||||
|
roles:
|
||||||
|
- role: maxhoesel.smallstep.step_ca
|
||||||
|
tasks:
|
||||||
|
- name: add an acme provisioner to the ca
|
||||||
|
maxhoesel.smallstep.step_ca_provisioner:
|
||||||
|
name: ACME
|
||||||
|
type: ACME
|
||||||
|
become_user: step-ca
|
||||||
|
- name: restart step-ca
|
||||||
|
ansible.builtin.systemd_service:
|
||||||
|
name: step-ca
|
||||||
|
state: restarted
|
||||||
|
enabled: true
|
||||||
|
- name: allow step-ca port traffic on vpn
|
||||||
|
ufw:
|
||||||
|
rule: allow
|
||||||
|
from: 100.64.0.0/10
|
||||||
|
port: "{{ step_ca_port }}"
|
||||||
|
- name: restart ufw
|
||||||
|
ansible.builtin.systemd_service:
|
||||||
|
name: ufw
|
||||||
|
state: restarted
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
- name: configure trust to internal ca on all hosts
|
||||||
|
hosts: all
|
||||||
|
roles:
|
||||||
|
- ca
|
4
deploy-gitea.yml
Normal file
4
deploy-gitea.yml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
- name: gitea setup
|
||||||
|
hosts: gitea
|
||||||
|
roles:
|
||||||
|
- gitea
|
4
deploy-lldap.yml
Normal file
4
deploy-lldap.yml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
- name: lldap setup
|
||||||
|
hosts: lldap
|
||||||
|
roles:
|
||||||
|
- lldap
|
8
deploy-mail.yml
Normal file
8
deploy-mail.yml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
- name: mail setup
|
||||||
|
hosts: mail
|
||||||
|
roles:
|
||||||
|
- mail
|
||||||
|
- name: roundcube setup
|
||||||
|
hosts: roundcube
|
||||||
|
roles:
|
||||||
|
- roundcube
|
4
deploy-pihole.yml
Normal file
4
deploy-pihole.yml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
- name: pihole setup
|
||||||
|
hosts: pihole
|
||||||
|
roles:
|
||||||
|
- pihole
|
4
deploy-private.yml
Normal file
4
deploy-private.yml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
- name: private setup
|
||||||
|
hosts: private
|
||||||
|
roles:
|
||||||
|
- private
|
4
deploy-roundcube.yml
Normal file
4
deploy-roundcube.yml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
- name: roundcube setup
|
||||||
|
hosts: roundcube
|
||||||
|
roles:
|
||||||
|
- roundcube
|
4
deploy-scurvy.yml
Normal file
4
deploy-scurvy.yml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
- name: scurvy setup
|
||||||
|
hosts: scurvy
|
||||||
|
roles:
|
||||||
|
- scurvy
|
23
deploy-vpn-hosts.yml
Normal file
23
deploy-vpn-hosts.yml
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
- name: prod headscale tags
|
||||||
|
hosts: prod
|
||||||
|
tasks:
|
||||||
|
- name: add prod tags to prod servers
|
||||||
|
include_role:
|
||||||
|
name: artis3n.tailscale
|
||||||
|
vars:
|
||||||
|
tailscale_args: "--login-server='https://headscale.simponic.xyz'"
|
||||||
|
tailscale_authkey: "{{ lookup('env', 'HEADSCALE_PREAUTH_KEY') }}"
|
||||||
|
tailscale_tags:
|
||||||
|
- "prod"
|
||||||
|
|
||||||
|
- name: private headscale tags
|
||||||
|
hosts: private
|
||||||
|
tasks:
|
||||||
|
- name: add private tags to private servers
|
||||||
|
include_role:
|
||||||
|
name: artis3n.tailscale
|
||||||
|
vars:
|
||||||
|
tailscale_args: "--login-server='https://headscale.simponic.xyz'"
|
||||||
|
tailscale_authkey: "{{ lookup('env', 'HEADSCALE_PREAUTH_KEY') }}"
|
||||||
|
tailscale_tags:
|
||||||
|
- "private"
|
@ -1,6 +1,15 @@
|
|||||||
---
|
---
|
||||||
|
johan_ip: '100.64.0.5'
|
||||||
|
nijika_ip: '100.64.0.2'
|
||||||
|
|
||||||
dns_servers:
|
dns_servers:
|
||||||
- 1.1.1.1
|
- 1.1.1.1
|
||||||
- 1.0.0.1
|
- 1.0.0.1
|
||||||
dns_dnssec: true
|
dns_dnssec: true
|
||||||
dns_domains: ["simponic.xyz"]
|
dns_domains: ["simponic.xyz"]
|
||||||
|
dns_stub_listener: false
|
||||||
|
|
||||||
|
step_bootstrap_fingerprint: '2de0c420e3b6f9f8e47f325de908b2b2d395d3bc7e49ed9b672ce9be89bea1bf'
|
||||||
|
step_bootstrap_ca_url: 'ca.internal.simponic.xyz'
|
||||||
|
step_acme_cert_contact: 'elizabeth.hunt@simponic.xyz'
|
||||||
|
step_ca_port: 5239
|
||||||
|
6
group_vars/ca.yml
Normal file
6
group_vars/ca.yml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
step_ca_root_password: "{{ lookup('env', 'STEP_CA_ROOT_PASSWORD') }}"
|
||||||
|
step_ca_intermediate_password: "{{ lookup('env', 'STEP_CA_INTERMEDIATE_PASSWORD') }}"
|
||||||
|
step_ca_dns: "{{ step_bootstrap_ca_url }}, {{ johan_ip }}"
|
||||||
|
step_ca_name: Simponic Internal CA
|
||||||
|
step_ca_address: ":{{ step_ca_port }}"
|
3
group_vars/lldap.yml
Normal file
3
group_vars/lldap.yml
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
---
|
||||||
|
lldap_jwt_secret: "{{ lookup('env', 'LLDAP_JWT_SECRET') }}"
|
||||||
|
lldap_user_pass: "{{ lookup('env', 'LLDAP_USER_PASS') }}"
|
5
group_vars/mail.yml
Normal file
5
group_vars/mail.yml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
domain: mail.simponic.xyz
|
||||||
|
certbot_email: elizabeth.hunt@simponic.xyz
|
||||||
|
postmaster_email: postmaster@simponic.xyz
|
||||||
|
lldap_admin_pass: "{{ lookup('env', 'LLDAP_USER_PASS') }}"
|
2
group_vars/pihole.yml
Normal file
2
group_vars/pihole.yml
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
---
|
||||||
|
pihole_webpwd: "{{ lookup('env', 'PIHOLE_WEBPWD') }}"
|
0
group_vars/roundcube.yml
Normal file
0
group_vars/roundcube.yml
Normal file
2
group_vars/scurvy.yml
Normal file
2
group_vars/scurvy.yml
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
---
|
||||||
|
openvpn_user: "{{ lookup('env', 'OPENVPN_USER') }}"
|
@ -1,2 +1,5 @@
|
|||||||
---
|
---
|
||||||
headscale_users: ['simponic']
|
headscale_oidc_secret: "{{ lookup('env', 'HEADSCALE_OIDC_SECRET') }}"
|
||||||
|
headscale_allowed_users:
|
||||||
|
- "elizabeth.hunt@simponic.xyz"
|
||||||
|
- "riley.ferguson@simponic.xyz"
|
||||||
|
34
inventory
34
inventory
@ -1,13 +1,16 @@
|
|||||||
[private]
|
[prod]
|
||||||
johan ansible_user=root ansible_connection=ssh
|
|
||||||
nijika ansible_user=root ansible_connection=ssh
|
nijika ansible_user=root ansible_connection=ssh
|
||||||
ryo ansible_user=root ansible_connection=ssh
|
ryo ansible_user=root ansible_connection=ssh
|
||||||
#ash ansible_user=root ansible_connection=ssh
|
levi ansible_user=root ansible_connection=ssh
|
||||||
|
mail.simponic.xyz ansible_user=root ansible_connection=ssh
|
||||||
|
|
||||||
|
[private]
|
||||||
|
johan ansible_user=root ansible_connection=ssh
|
||||||
|
europa ansible_user=root ansible_connection=ssh
|
||||||
|
|
||||||
[webservers]
|
[webservers]
|
||||||
levi ansible_user=root ansible_connection=ssh
|
levi ansible_user=root ansible_connection=ssh
|
||||||
nijika ansible_user=root ansible_connection=ssh
|
nijika ansible_user=root ansible_connection=ssh
|
||||||
#ash.internal.simponic.xyz ansible_user=root ansible_connection=ssh
|
|
||||||
|
|
||||||
[nameservers]
|
[nameservers]
|
||||||
ryo ansible_user=root ansible_connection=ssh
|
ryo ansible_user=root ansible_connection=ssh
|
||||||
@ -22,8 +25,29 @@ nijika ansible_user=root ansible_connection=ssh
|
|||||||
[vpn]
|
[vpn]
|
||||||
nijika ansible_user=root ansible_connection=ssh
|
nijika ansible_user=root ansible_connection=ssh
|
||||||
|
|
||||||
|
[authelia]
|
||||||
|
nijika ansible_user=root ansible_connection=ssh
|
||||||
|
|
||||||
[dnsinternal]
|
[dnsinternal]
|
||||||
johan ansible_user=root ansible_connection=ssh
|
johan ansible_user=root ansible_connection=ssh
|
||||||
|
|
||||||
|
[pihole]
|
||||||
|
johan ansible_user=root ansible_connection=ssh
|
||||||
|
|
||||||
|
[lldap]
|
||||||
|
johan ansible_user=root ansible_connection=ssh
|
||||||
|
|
||||||
|
[ca]
|
||||||
|
johan ansible_user=root ansible_connection=ssh
|
||||||
|
|
||||||
[mail]
|
[mail]
|
||||||
#ash ansible_user=root ansible_connection=ssh
|
mail.simponic.xyz ansible_user=root ansible_connection=ssh
|
||||||
|
|
||||||
|
[roundcube]
|
||||||
|
europa ansible_user=root ansible_connection=ssh
|
||||||
|
|
||||||
|
[scurvy]
|
||||||
|
europa ansible_user=root ansible_connection=ssh
|
||||||
|
|
||||||
|
[gitea]
|
||||||
|
nijika ansible_user=root ansible_connection=ssh
|
||||||
|
2
roles/authelia/files/authelia/.gitignore
vendored
Normal file
2
roles/authelia/files/authelia/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
users_database.yml
|
||||||
|
configuration.yml
|
30
roles/authelia/tasks/main.yml
Normal file
30
roles/authelia/tasks/main.yml
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
---
|
||||||
|
- name: ensure authelia docker/compose exist
|
||||||
|
file:
|
||||||
|
path: /etc/docker/compose/authelia
|
||||||
|
state: directory
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: 0700
|
||||||
|
|
||||||
|
- name: copy authelia config
|
||||||
|
copy:
|
||||||
|
src: ../files/authelia
|
||||||
|
dest: /etc/docker/compose/authelia/
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: u=rw,g=r,o=r
|
||||||
|
|
||||||
|
- name: build authelia docker-compose.yml.j2
|
||||||
|
template:
|
||||||
|
src: ../templates/docker-compose.yml.j2
|
||||||
|
dest: /etc/docker/compose/authelia/docker-compose.yml
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: u=rw,g=r,o=r
|
||||||
|
|
||||||
|
- name: daemon-reload and enable authelia
|
||||||
|
ansible.builtin.systemd_service:
|
||||||
|
state: restarted
|
||||||
|
enabled: true
|
||||||
|
name: docker-compose@authelia
|
19
roles/authelia/templates/docker-compose.yml.j2
Normal file
19
roles/authelia/templates/docker-compose.yml.j2
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
version: '3.3'
|
||||||
|
|
||||||
|
services:
|
||||||
|
authelia:
|
||||||
|
image: authelia/authelia
|
||||||
|
container_name: authelia
|
||||||
|
volumes:
|
||||||
|
- ./authelia:/config
|
||||||
|
ports:
|
||||||
|
- 127.0.0.1:9091:9091
|
||||||
|
restart: unless-stopped
|
||||||
|
dns:
|
||||||
|
- {{ johan_ip }}
|
||||||
|
redis:
|
||||||
|
image: redis:alpine
|
||||||
|
container_name: redis
|
||||||
|
volumes:
|
||||||
|
- ./redis:/data
|
||||||
|
restart: unless-stopped
|
15
roles/ca/tasks/main.yml
Normal file
15
roles/ca/tasks/main.yml
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
---
|
||||||
|
|
||||||
|
- name: get root CA certificate
|
||||||
|
command: >
|
||||||
|
curl -k -X GET -H "Content-Type:application/json" \
|
||||||
|
"https://{{ step_bootstrap_ca_url }}:{{ step_ca_port }}/root/{{ step_bootstrap_fingerprint }}"
|
||||||
|
register: root_ca_fp
|
||||||
|
|
||||||
|
- name: copy to os certificates
|
||||||
|
template:
|
||||||
|
src: "../templates/crt.j2"
|
||||||
|
dest: "/usr/local/share/ca-certificates/{{ step_bootstrap_ca_url }}.crt"
|
||||||
|
|
||||||
|
- name: update trusted certs
|
||||||
|
command: "update-ca-certificates"
|
1
roles/ca/templates/crt.j2
Normal file
1
roles/ca/templates/crt.j2
Normal file
@ -0,0 +1 @@
|
|||||||
|
{{ (root_ca_fp.stdout | from_json).ca }}
|
@ -1,5 +1,11 @@
|
|||||||
---
|
---
|
||||||
|
|
||||||
|
# set hostname
|
||||||
|
- name: Set a hostname specifying strategy
|
||||||
|
ansible.builtin.hostname:
|
||||||
|
name: "{{ inventory_hostname }}"
|
||||||
|
use: systemd
|
||||||
|
|
||||||
# docker
|
# docker
|
||||||
- name: install dependencies
|
- name: install dependencies
|
||||||
apt:
|
apt:
|
||||||
|
@ -41,6 +41,16 @@
|
|||||||
no_extra_spaces: true
|
no_extra_spaces: true
|
||||||
register: conf_domains
|
register: conf_domains
|
||||||
|
|
||||||
|
- name: stub listener
|
||||||
|
community.general.ini_file:
|
||||||
|
path: /etc/systemd/resolved.conf
|
||||||
|
section: Resolve
|
||||||
|
option: DNSStubListener
|
||||||
|
value: '{{ "yes" if dns_stub_listener else "no" }}'
|
||||||
|
mode: '0644'
|
||||||
|
no_extra_spaces: true
|
||||||
|
register: conf_domains
|
||||||
|
|
||||||
- name: Check if systemd-resolve runs
|
- name: Check if systemd-resolve runs
|
||||||
ansible.builtin.shell: pgrep systemd-resolve
|
ansible.builtin.shell: pgrep systemd-resolve
|
||||||
failed_when: false
|
failed_when: false
|
||||||
|
1
roles/gitea/files/.gitignore
vendored
Normal file
1
roles/gitea/files/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
app.ini
|
46
roles/gitea/tasks/main.yml
Normal file
46
roles/gitea/tasks/main.yml
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
---
|
||||||
|
- name: ensure gitea docker/compose exist
|
||||||
|
file:
|
||||||
|
path: /etc/docker/compose/gitea
|
||||||
|
state: directory
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: 0700
|
||||||
|
|
||||||
|
- name: create gitea docker/compose/data/gitea with set uid/gid
|
||||||
|
file:
|
||||||
|
path: /etc/docker/compose/gitea/data
|
||||||
|
state: directory
|
||||||
|
owner: 1000
|
||||||
|
group: 1000
|
||||||
|
mode: 0700
|
||||||
|
|
||||||
|
- name: ensure gitea docker/compose/data/gitea exist
|
||||||
|
file:
|
||||||
|
path: /etc/docker/compose/gitea/data/gitea/conf
|
||||||
|
state: directory
|
||||||
|
owner: 1000
|
||||||
|
group: 1000
|
||||||
|
mode: 0700
|
||||||
|
|
||||||
|
- name: copy app.ini
|
||||||
|
copy:
|
||||||
|
src: ../files/app.ini
|
||||||
|
dest: /etc/docker/compose/gitea/data/gitea/conf/app.ini
|
||||||
|
owner: 1000
|
||||||
|
group: 1000
|
||||||
|
mode: 0700
|
||||||
|
|
||||||
|
- name: build gitea docker-compose.yml.j2
|
||||||
|
template:
|
||||||
|
src: ../templates/docker-compose.yml.j2
|
||||||
|
dest: /etc/docker/compose/gitea/docker-compose.yml
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: u=rw,g=r,o=r
|
||||||
|
|
||||||
|
- name: daemon-reload and enable gitea
|
||||||
|
ansible.builtin.systemd_service:
|
||||||
|
state: restarted
|
||||||
|
enabled: true
|
||||||
|
name: docker-compose@gitea
|
20
roles/gitea/templates/docker-compose.yml.j2
Normal file
20
roles/gitea/templates/docker-compose.yml.j2
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
version: "3"
|
||||||
|
|
||||||
|
networks:
|
||||||
|
gitea:
|
||||||
|
external: false
|
||||||
|
|
||||||
|
services:
|
||||||
|
server:
|
||||||
|
image: gitea/gitea:1.21.3
|
||||||
|
container_name: gitea
|
||||||
|
restart: always
|
||||||
|
networks:
|
||||||
|
- gitea
|
||||||
|
volumes:
|
||||||
|
- ./data:/data
|
||||||
|
- /etc/timezone:/etc/timezone:ro
|
||||||
|
- /etc/localtime:/etc/localtime:ro
|
||||||
|
ports:
|
||||||
|
- "127.0.0.1:9966:3000"
|
||||||
|
- "{{ nijika_ip }}:222:22"
|
28
roles/lldap/tasks/main.yml
Normal file
28
roles/lldap/tasks/main.yml
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
---
|
||||||
|
- name: ensure lldap docker/compose exist
|
||||||
|
file:
|
||||||
|
path: /etc/docker/compose/lldap
|
||||||
|
state: directory
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: 0700
|
||||||
|
|
||||||
|
- name: build lldap docker-compose.yml.j2
|
||||||
|
template:
|
||||||
|
src: ../templates/docker-compose.yml.j2
|
||||||
|
dest: /etc/docker/compose/lldap/docker-compose.yml
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: u=rw,g=r,o=r
|
||||||
|
|
||||||
|
- name: daemon-reload and enable lldap
|
||||||
|
ansible.builtin.systemd_service:
|
||||||
|
state: restarted
|
||||||
|
enabled: true
|
||||||
|
name: docker-compose@lldap
|
||||||
|
|
||||||
|
- name: allow ldap on vpn
|
||||||
|
ufw:
|
||||||
|
rule: allow
|
||||||
|
port: '3890'
|
||||||
|
from: '100.64.0.0/10'
|
18
roles/lldap/templates/docker-compose.yml.j2
Normal file
18
roles/lldap/templates/docker-compose.yml.j2
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
version: "3"
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
lldap_data:
|
||||||
|
driver: local
|
||||||
|
|
||||||
|
services:
|
||||||
|
lldap:
|
||||||
|
image: lldap/lldap:stable
|
||||||
|
ports:
|
||||||
|
- "{{ johan_ip }}:3890:3890"
|
||||||
|
- "127.0.0.1:17170:17170"
|
||||||
|
volumes:
|
||||||
|
- "lldap_data:/data"
|
||||||
|
environment:
|
||||||
|
- LLDAP_JWT_SECRET="{{ lldap_jwt_secret }}"
|
||||||
|
- LLDAP_LDAP_USER_PASS="{{ lldap_user_pass }}"
|
||||||
|
- LLDAP_LDAP_BASE_DN=dc=simponic,dc=xyz
|
3
roles/mail/files/postmaster-main.cf
Normal file
3
roles/mail/files/postmaster-main.cf
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
virtual_mailbox_domains = /etc/postfix/vhost
|
||||||
|
virtual_mailbox_maps = ldap:/etc/postfix/ldap-users.cf
|
||||||
|
virtual_alias_maps =
|
71
roles/mail/tasks/main.yml
Normal file
71
roles/mail/tasks/main.yml
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
---
|
||||||
|
- name: install letsencrypt
|
||||||
|
apt:
|
||||||
|
name: letsencrypt
|
||||||
|
state: latest
|
||||||
|
|
||||||
|
- name: allow 80/tcp ufw
|
||||||
|
ufw:
|
||||||
|
rule: allow
|
||||||
|
port: '80'
|
||||||
|
proto: 'tcp'
|
||||||
|
|
||||||
|
- name: allow 443/tcp ufw
|
||||||
|
ufw:
|
||||||
|
rule: allow
|
||||||
|
port: '443'
|
||||||
|
proto: 'tcp'
|
||||||
|
|
||||||
|
- name: restart ufw
|
||||||
|
service: name=ufw state=restarted enabled=yes
|
||||||
|
|
||||||
|
- name: request certificate
|
||||||
|
shell: >
|
||||||
|
letsencrypt certonly -n --standalone -d "{{ domain }}" \
|
||||||
|
-m "{{ certbot_email }}" --agree-tos
|
||||||
|
args:
|
||||||
|
creates: "/etc/letsencrypt/live/{{ domain }}"
|
||||||
|
|
||||||
|
- name: add monthly letsencrypt cronjob for cert renewal
|
||||||
|
cron:
|
||||||
|
name: "letsencrypt_renewal_mail"
|
||||||
|
day: "18"
|
||||||
|
hour: "2"
|
||||||
|
minute: "1"
|
||||||
|
job: "letsencrypt renew --cert-name {{ domain }} -n --standalone --agree-tos -m {{ certbot_email }}"
|
||||||
|
|
||||||
|
- name: ensure mail docker/compose exist
|
||||||
|
file:
|
||||||
|
path: /etc/docker/compose/mail
|
||||||
|
state: directory
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: 0700
|
||||||
|
|
||||||
|
- name: ensure mail docker/compose volume exist
|
||||||
|
file:
|
||||||
|
path: /etc/docker/compose/mail/docker-data/dms/config
|
||||||
|
state: directory
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: 0700
|
||||||
|
|
||||||
|
# https://github.com/docker-mailserver/docker-mailserver/issues/1562
|
||||||
|
- name: ensure mail docker/compose ldap overrides exist
|
||||||
|
copy:
|
||||||
|
src: ../files/postmaster-main.cf
|
||||||
|
dest: /etc/docker/compose/mail/docker-data/dms/config/postfix-main.cf
|
||||||
|
|
||||||
|
- name: build mail docker-compose.yml.j2
|
||||||
|
template:
|
||||||
|
src: ../templates/docker-compose.yml.j2
|
||||||
|
dest: /etc/docker/compose/mail/docker-compose.yml
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: u=rw,g=r,o=r
|
||||||
|
|
||||||
|
- name: daemon-reload and enable mail
|
||||||
|
ansible.builtin.systemd_service:
|
||||||
|
state: restarted
|
||||||
|
enabled: true
|
||||||
|
name: docker-compose@mail
|
46
roles/mail/templates/docker-compose.yml.j2
Normal file
46
roles/mail/templates/docker-compose.yml.j2
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
services:
|
||||||
|
mailserver:
|
||||||
|
image: ghcr.io/docker-mailserver/docker-mailserver:latest
|
||||||
|
container_name: mailserver
|
||||||
|
# Provide the FQDN of your mail server here (Your DNS MX record should point to this value)
|
||||||
|
hostname: {{ domain }}
|
||||||
|
ports:
|
||||||
|
- "25:25"
|
||||||
|
- "465:465"
|
||||||
|
- "587:587"
|
||||||
|
- "993:993"
|
||||||
|
volumes:
|
||||||
|
- ./docker-data/dms/mail-data/:/var/mail/
|
||||||
|
- ./docker-data/dms/mail-state/:/var/mail-state/
|
||||||
|
- ./docker-data/dms/mail-logs/:/var/log/mail/
|
||||||
|
- ./docker-data/dms/config/:/tmp/docker-mailserver/
|
||||||
|
- /etc/letsencrypt:/etc/letsencrypt
|
||||||
|
- /etc/localtime:/etc/localtime:ro
|
||||||
|
environment:
|
||||||
|
- SSL_TYPE=letsencrypt
|
||||||
|
- ENABLE_CLAMAV=0
|
||||||
|
- ENABLE_AMAVIS=0
|
||||||
|
- ENABLE_FAIL2BAN=0
|
||||||
|
- SPOOF_PROTECTION=1
|
||||||
|
- ACCOUNT_PROVISIONER=LDAP
|
||||||
|
- LDAP_SERVER_HOST=ldap://lldap.internal.simponic.xyz:3890
|
||||||
|
- LDAP_SEARCH_BASE=dc=simponic,dc=xyz
|
||||||
|
- LDAP_BIND_DN=uid=admin,ou=people,dc=simponic,dc=xyz
|
||||||
|
- LDAP_BIND_PW={{ lldap_admin_pass }}
|
||||||
|
|
||||||
|
- LDAP_QUERY_FILTER_USER=(&(objectClass=mailAccount)(|(uid=%u)))
|
||||||
|
- LDAP_QUERY_FILTER_GROUP=(&(cn=mail)(uniquemember=uid=%u,ou=people,dc=simponic,dc=xyz))
|
||||||
|
- LDAP_QUERY_FILTER_ALIAS=(&(objectClass=inetOrgPerson)(|(uid=%u)(mail=%u)))
|
||||||
|
- LDAP_QUERY_FILTER_DOMAIN=(mail=*@%s)
|
||||||
|
|
||||||
|
- DOVECOT_AUTH_BIND=yes
|
||||||
|
- DOVECOT_USER_FILTER=(&(objectClass=inetOrgPerson)(|(uid=%u)(mail=%u)))
|
||||||
|
- DOVECOT_USER_ATTRS==uid=5000,=gid=5000,=home=/var/mail/%Ln,=mail=maildir:~/Maildir
|
||||||
|
|
||||||
|
- ENABLE_SASLAUTHD=1
|
||||||
|
- SASLAUTHD_MECHANISMS=rimap
|
||||||
|
- SASLAUTHD_MECH_OPTIONS=127.0.0.1
|
||||||
|
- POSTMASTER_ADDRESS={{ postmaster_email }}
|
||||||
|
dns:
|
||||||
|
- {{ johan_ip }}
|
||||||
|
restart: always
|
@ -39,7 +39,8 @@
|
|||||||
|
|
||||||
- name: flush dns cache on replicas
|
- name: flush dns cache on replicas
|
||||||
file: path={{ item }} state=absent
|
file: path={{ item }} state=absent
|
||||||
with_fileglob: /var/cache/bind/db.*
|
with_fileglob: "/var/cache/bind/db.*"
|
||||||
|
when: inventory_hostname in groups['dnsreplica']
|
||||||
|
|
||||||
- name: restart bind9
|
- name: restart bind9
|
||||||
service:
|
service:
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
$TTL 604800
|
$TTL 604800
|
||||||
@ IN SOA {{ dns_primary_hostname }}.simponic.xyz. admin.simponic.xyz. (
|
@ IN SOA {{ dns_primary_hostname }}.simponic.xyz. admin.simponic.xyz. (
|
||||||
{{ ansible_date_time.epoch }} ; Serial
|
{{ ansible_date_time.epoch }} ; Serial
|
||||||
86400 ; Refresh
|
86400 ; Refresh
|
||||||
86400 ; Retry
|
86400 ; Retry
|
||||||
2419200 ; Expire
|
2419200 ; Expire
|
||||||
@ -19,27 +19,27 @@ johan.simponic.xyz. 1 IN A 23.95.20.192
|
|||||||
osaka.simponic.xyz. 1 IN A 129.123.76.14
|
osaka.simponic.xyz. 1 IN A 129.123.76.14
|
||||||
|
|
||||||
mail.simponic.xyz. 1 IN A 192.3.248.205
|
mail.simponic.xyz. 1 IN A 192.3.248.205
|
||||||
ash.simponic.xyz. 1 IN A 192.3.248.205
|
|
||||||
|
|
||||||
levi.simponic.xyz. 1 IN A 23.95.214.176
|
levi.simponic.xyz. 1 IN A 23.95.214.176
|
||||||
simponic.xyz. 1 IN A 23.95.214.176
|
simponic.xyz. 1 IN A 23.95.214.176
|
||||||
|
|
||||||
|
chesshbot.simponic.xyz. 1 IN A 129.123.76.14
|
||||||
|
|
||||||
;; CNAME Records
|
;; CNAME Records
|
||||||
static.simponic.xyz. 1 IN CNAME simponic.xyz.
|
static.simponic.xyz. 1 IN CNAME simponic.xyz.
|
||||||
www.simponic.xyz. 1 IN CNAME simponic.xyz.
|
www.simponic.xyz. 1 IN CNAME simponic.xyz.
|
||||||
s1._domainkey.simponic.xyz. 1 IN CNAME s1.domainkey.u25709709.wl210.sendgrid.net.
|
s1._domainkey.simponic.xyz. 1 IN CNAME s1.domainkey.u25709709.wl210.sendgrid.net.
|
||||||
s2._domainkey.simponic.xyz. 1 IN CNAME s2.domainkey.u25709709.wl210.sendgrid.net.
|
s2._domainkey.simponic.xyz. 1 IN CNAME s2.domainkey.u25709709.wl210.sendgrid.net.
|
||||||
headscale.simponic.xyz. 1 IN CNAME nijika.simponic.xyz.
|
headscale.simponic.xyz. 1 IN CNAME nijika.simponic.xyz.
|
||||||
authentik.simponic.xyz. 1 IN CNAME nijika.simponic.xyz.
|
authelia.simponic.xyz. 1 IN CNAME nijika.simponic.xyz.
|
||||||
|
git.simponic.xyz. 1 IN CNAME simponic.xyz.
|
||||||
|
|
||||||
;; MX Records
|
;; MX Records
|
||||||
simponic.xyz. 1 IN MX 10 mail.simponic.xyz.
|
simponic.xyz. 1 IN MX 10 mail.simponic.xyz.
|
||||||
|
|
||||||
;; TXT Records
|
;; TXT Records
|
||||||
dkim._domainkey.simponic.xyz. 1 IN TXT "v=DKIM1; p= MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoNWLcbrcGq0z8f0fSmxLbfK/Q/ZwmnPyJEfljS2VuDIm7DUXahHIFtB8hfZ/WAocoirb8kUHTvTAgmUOXPpNxTDve3tV9S+CBBYHH2c9XBsuaZn/Vi0TR5vbBDuISmlXT6k+2cdq0LO+PYRwJI65t/JWTR5fQlCmVgxbI5gwDYFRZC0Nl5gEwuKw7pdEJg4Pymyox" "i" "zcikaGk/plXj6BDvv9pK1q8Wa+QPIkuBPFvsEh3KSApMP1p5thzHFaeNyCn5PuYEvbgkal0722px6GvYfR2W/APNRztbmWVewXH6kEWCgOYMkmWiYYLgEwz62rq2SzszP1rrl3WjVi26916wIDAQAB"
|
mail._domainkey.simponic.xyz. 1 IN TXT ( "v=DKIM1; h=sha256; k=rsa; "
|
||||||
|
"p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2ktysbZaewsAo1Uk+FfLvVeL9ii6ejTDxxYE1RoGTxFDulFYXdpvO+MErDq62IvaQ6E4TYTc0RULoqp3BjuVVG6IG85SmhWME9XYSrxLm1pq7yRN1s1b6pBqNC6+yiyxwSjThS7RzH3sxwBL7R8AHRuEV+2UKsvT2wOCyRXAth+lrB7t9S9niWNOB3lvDqe0/oPf9JDrKjpuO6"
|
||||||
|
"lKZ3nglGzPfdJEpfLyXBP4l5UlxqWYUIrCzqHY9bNmyPepb1CJT97AD5jGGngCrnMCmllAdyOKa1ds5uoPjjGaLO8bOoBWXQuacn++hDsdyQ78Y673T2935CN/uGgrLBs9UiA0BQIDAQAB" ) ; ----- DKIM key mail for simponic.xyz
|
||||||
|
_dmarc.simponic.xyz. 1 IN TXT "v=DMARC1; p=quarantine; sp=quarantine; fo=0; adkim=r; aspf=r; pct=100; rf=afrf; ri=86400; rua=mailto:dmarc.report@simponic.xyz; ruf=mailto:dmarc.report@simponic.xyz"
|
||||||
simponic.xyz. 1 IN TXT "v=spf1 mx ip4:192.3.248.205 ~all"
|
simponic.xyz. 1 IN TXT "v=spf1 mx ip4:192.3.248.205 ~all"
|
||||||
|
|
||||||
_acme-challenge.simponic.xyz. 1 IN TXT "6GcrSuBAj8pNKqiCBWUIONRJjbDVtOizadBDGngW4-U"
|
|
||||||
_acme-challenge.simponic.xyz. 1 IN TXT "IErMxNBY3v1Wc3RV06khZXKDC1f9EObYHSXETK5ZKYE"
|
|
||||||
_acme-challenge.simponic.xyz. 1 IN TXT "3jWQSVbU-SdebeymX58bir5kEHG1dVHRXYE-P_4Qao8"
|
|
||||||
_acme-challenge.simponic.xyz. 1 IN TXT "LXaVBwQCanWKF4cNxzPHHPM9N-kkjhn8_4r6RsveBqs"
|
|
||||||
|
36
roles/pihole/tasks/main.yml
Normal file
36
roles/pihole/tasks/main.yml
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
---
|
||||||
|
- name: ensure pihole docker/compose exist
|
||||||
|
file:
|
||||||
|
path: /etc/docker/compose/pihole
|
||||||
|
state: directory
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: 0700
|
||||||
|
|
||||||
|
- name: build pihole docker-compose.yml.j2
|
||||||
|
template:
|
||||||
|
src: ../templates/docker-compose.yml.j2
|
||||||
|
dest: /etc/docker/compose/pihole/docker-compose.yml
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: u=rw,g=r,o=r
|
||||||
|
|
||||||
|
- name: daemon-reload and enable pihole
|
||||||
|
ansible.builtin.systemd_service:
|
||||||
|
state: restarted
|
||||||
|
enabled: true
|
||||||
|
name: docker-compose@pihole
|
||||||
|
|
||||||
|
- name: allow dns queries in vpn/tcp
|
||||||
|
ufw:
|
||||||
|
rule: allow
|
||||||
|
from: '100.64.0.0/10'
|
||||||
|
port: '53'
|
||||||
|
proto: 'tcp'
|
||||||
|
|
||||||
|
- name: allow dns queries in vpn/udp
|
||||||
|
ufw:
|
||||||
|
rule: allow
|
||||||
|
from: '100.64.0.0/10'
|
||||||
|
port: '53'
|
||||||
|
proto: 'udp'
|
18
roles/pihole/templates/docker-compose.yml.j2
Normal file
18
roles/pihole/templates/docker-compose.yml.j2
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
version: "3"
|
||||||
|
|
||||||
|
services:
|
||||||
|
pihole:
|
||||||
|
container_name: pihole
|
||||||
|
image: pihole/pihole:latest
|
||||||
|
ports:
|
||||||
|
- "{{ johan_ip }}:53:53/tcp"
|
||||||
|
- "{{ johan_ip }}:53:53/udp"
|
||||||
|
- "127.0.0.1:53:53/tcp"
|
||||||
|
- "127.0.0.1:53:53/udp"
|
||||||
|
- "127.0.0.1:9135:80/tcp"
|
||||||
|
environment:
|
||||||
|
WEBPASSWORD: '{{ pihole_webpwd }}'
|
||||||
|
volumes:
|
||||||
|
- './etc-pihole:/etc/pihole'
|
||||||
|
- './etc-dnsmasq.d:/etc/dnsmasq.d'
|
||||||
|
restart: unless-stopped
|
@ -0,0 +1,13 @@
|
|||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name jellyfin.internal.simponic.xyz;
|
||||||
|
|
||||||
|
location /.well-known/acme-challenge {
|
||||||
|
root /var/www/letsencrypt;
|
||||||
|
try_files $uri $uri/ =404;
|
||||||
|
}
|
||||||
|
|
||||||
|
location / {
|
||||||
|
rewrite ^ https://jellyfin.internal.simponic.xyz$request_uri? permanent;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name roundcube.internal.simponic.xyz;
|
||||||
|
|
||||||
|
location /.well-known/acme-challenge {
|
||||||
|
root /var/www/letsencrypt;
|
||||||
|
try_files $uri $uri/ =404;
|
||||||
|
}
|
||||||
|
|
||||||
|
location / {
|
||||||
|
rewrite ^ https://roundcube.internal.simponic.xyz$request_uri? permanent;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name scurvy.internal.simponic.xyz;
|
||||||
|
|
||||||
|
location /.well-known/acme-challenge {
|
||||||
|
root /var/www/letsencrypt;
|
||||||
|
try_files $uri $uri/ =404;
|
||||||
|
}
|
||||||
|
|
||||||
|
location / {
|
||||||
|
rewrite ^ https://scurvy.internal.simponic.xyz$request_uri? permanent;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
server {
|
||||||
|
listen 443 ssl;
|
||||||
|
server_name jellyfin.internal.simponic.xyz;
|
||||||
|
|
||||||
|
ssl_certificate /etc/letsencrypt/live/jellyfin.internal.simponic.xyz/fullchain.pem;
|
||||||
|
ssl_certificate_key /etc/letsencrypt/live/jellyfin.internal.simponic.xyz/privkey.pem;
|
||||||
|
ssl_trusted_certificate /etc/letsencrypt/live/jellyfin.internal.simponic.xyz/fullchain.pem;
|
||||||
|
|
||||||
|
ssl_session_cache shared:SSL:50m;
|
||||||
|
ssl_session_timeout 5m;
|
||||||
|
ssl_stapling on;
|
||||||
|
ssl_stapling_verify on;
|
||||||
|
|
||||||
|
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
|
||||||
|
ssl_ciphers "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4";
|
||||||
|
|
||||||
|
ssl_dhparam /etc/nginx/dhparams.pem;
|
||||||
|
ssl_prefer_server_ciphers on;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://127.0.0.1:8096;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection "upgrade";
|
||||||
|
proxy_set_header Host $server_name;
|
||||||
|
proxy_buffering off;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
|
||||||
|
add_header Strict-Transport-Security "max-age=15552000; includeSubDomains" always;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
server {
|
||||||
|
listen 443 ssl;
|
||||||
|
server_name roundcube.internal.simponic.xyz;
|
||||||
|
|
||||||
|
ssl_certificate /etc/letsencrypt/live/roundcube.internal.simponic.xyz/fullchain.pem;
|
||||||
|
ssl_certificate_key /etc/letsencrypt/live/roundcube.internal.simponic.xyz/privkey.pem;
|
||||||
|
ssl_trusted_certificate /etc/letsencrypt/live/roundcube.internal.simponic.xyz/fullchain.pem;
|
||||||
|
|
||||||
|
ssl_session_cache shared:SSL:50m;
|
||||||
|
ssl_session_timeout 5m;
|
||||||
|
ssl_stapling on;
|
||||||
|
ssl_stapling_verify on;
|
||||||
|
|
||||||
|
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
|
||||||
|
ssl_ciphers "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4";
|
||||||
|
|
||||||
|
ssl_dhparam /etc/nginx/dhparams.pem;
|
||||||
|
ssl_prefer_server_ciphers on;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://127.0.0.1:9002;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection "upgrade";
|
||||||
|
proxy_set_header Host $server_name;
|
||||||
|
proxy_buffering off;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
|
||||||
|
add_header Strict-Transport-Security "max-age=15552000; includeSubDomains" always;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
server {
|
||||||
|
listen 443 ssl;
|
||||||
|
server_name scurvy.internal.simponic.xyz;
|
||||||
|
|
||||||
|
ssl_certificate /etc/letsencrypt/live/scurvy.internal.simponic.xyz/fullchain.pem;
|
||||||
|
ssl_certificate_key /etc/letsencrypt/live/scurvy.internal.simponic.xyz/privkey.pem;
|
||||||
|
ssl_trusted_certificate /etc/letsencrypt/live/scurvy.internal.simponic.xyz/fullchain.pem;
|
||||||
|
|
||||||
|
ssl_session_cache shared:SSL:50m;
|
||||||
|
ssl_session_timeout 5m;
|
||||||
|
ssl_stapling on;
|
||||||
|
ssl_stapling_verify on;
|
||||||
|
|
||||||
|
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
|
||||||
|
ssl_ciphers "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4";
|
||||||
|
|
||||||
|
ssl_dhparam /etc/nginx/dhparams.pem;
|
||||||
|
ssl_prefer_server_ciphers on;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://127.0.0.1:9000;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection "upgrade";
|
||||||
|
proxy_set_header Host $server_name;
|
||||||
|
proxy_buffering off;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
|
||||||
|
add_header Strict-Transport-Security "max-age=15552000; includeSubDomains" always;
|
||||||
|
}
|
||||||
|
}
|
13
roles/private/files/johan/http.ca.internal.simponic.xyz.conf
Normal file
13
roles/private/files/johan/http.ca.internal.simponic.xyz.conf
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name ca.internal.simponic.xyz;
|
||||||
|
|
||||||
|
location /.well-known/acme-challenge {
|
||||||
|
root /var/www/letsencrypt;
|
||||||
|
try_files $uri $uri/ =404;
|
||||||
|
}
|
||||||
|
|
||||||
|
location / {
|
||||||
|
rewrite ^ https://ca.internal.simponic.xyz$request_uri? permanent;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name lldap.internal.simponic.xyz;
|
||||||
|
|
||||||
|
location /.well-known/acme-challenge {
|
||||||
|
root /var/www/letsencrypt;
|
||||||
|
try_files $uri $uri/ =404;
|
||||||
|
}
|
||||||
|
|
||||||
|
location / {
|
||||||
|
rewrite ^ https://lldap.internal.simponic.xyz$request_uri? permanent;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name pihole.internal.simponic.xyz;
|
||||||
|
|
||||||
|
location /.well-known/acme-challenge {
|
||||||
|
root /var/www/letsencrypt;
|
||||||
|
try_files $uri $uri/ =404;
|
||||||
|
}
|
||||||
|
|
||||||
|
location / {
|
||||||
|
rewrite ^ https://pihole.internal.simponic.xyz$request_uri? permanent;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
server {
|
||||||
|
listen 443 ssl;
|
||||||
|
server_name ca.internal.simponic.xyz;
|
||||||
|
|
||||||
|
ssl_certificate /etc/letsencrypt/live/ca.internal.simponic.xyz/fullchain.pem;
|
||||||
|
ssl_certificate_key /etc/letsencrypt/live/ca.internal.simponic.xyz/privkey.pem;
|
||||||
|
ssl_trusted_certificate /etc/letsencrypt/live/ca.internal.simponic.xyz/fullchain.pem;
|
||||||
|
|
||||||
|
ssl_session_cache shared:SSL:50m;
|
||||||
|
ssl_session_timeout 5m;
|
||||||
|
ssl_stapling on;
|
||||||
|
ssl_stapling_verify on;
|
||||||
|
|
||||||
|
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
|
||||||
|
ssl_ciphers "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4";
|
||||||
|
|
||||||
|
ssl_dhparam /etc/nginx/dhparams.pem;
|
||||||
|
ssl_prefer_server_ciphers on;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass https://ca.internal.simponic.xyz:5239;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection "upgrade";
|
||||||
|
proxy_set_header Host $server_name;
|
||||||
|
proxy_buffering off;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
|
||||||
|
add_header Strict-Transport-Security "max-age=15552000; includeSubDomains" always;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
server {
|
||||||
|
listen 443 ssl;
|
||||||
|
server_name lldap.internal.simponic.xyz;
|
||||||
|
|
||||||
|
ssl_certificate /etc/letsencrypt/live/lldap.internal.simponic.xyz/fullchain.pem;
|
||||||
|
ssl_certificate_key /etc/letsencrypt/live/lldap.internal.simponic.xyz/privkey.pem;
|
||||||
|
ssl_trusted_certificate /etc/letsencrypt/live/lldap.internal.simponic.xyz/fullchain.pem;
|
||||||
|
|
||||||
|
ssl_session_cache shared:SSL:50m;
|
||||||
|
ssl_session_timeout 5m;
|
||||||
|
ssl_stapling on;
|
||||||
|
ssl_stapling_verify on;
|
||||||
|
|
||||||
|
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
|
||||||
|
ssl_ciphers "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4";
|
||||||
|
|
||||||
|
ssl_dhparam /etc/nginx/dhparams.pem;
|
||||||
|
ssl_prefer_server_ciphers on;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://127.0.0.1:17170;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection "upgrade";
|
||||||
|
proxy_set_header Host $server_name;
|
||||||
|
proxy_buffering off;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
|
||||||
|
add_header Strict-Transport-Security "max-age=15552000; includeSubDomains" always;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
server {
|
||||||
|
listen 443 ssl;
|
||||||
|
server_name pihole.internal.simponic.xyz;
|
||||||
|
|
||||||
|
ssl_certificate /etc/letsencrypt/live/pihole.internal.simponic.xyz/fullchain.pem;
|
||||||
|
ssl_certificate_key /etc/letsencrypt/live/pihole.internal.simponic.xyz/privkey.pem;
|
||||||
|
ssl_trusted_certificate /etc/letsencrypt/live/pihole.internal.simponic.xyz/fullchain.pem;
|
||||||
|
|
||||||
|
ssl_session_cache shared:SSL:50m;
|
||||||
|
ssl_session_timeout 5m;
|
||||||
|
ssl_stapling on;
|
||||||
|
ssl_stapling_verify on;
|
||||||
|
|
||||||
|
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
|
||||||
|
ssl_ciphers "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4";
|
||||||
|
|
||||||
|
ssl_dhparam /etc/nginx/dhparams.pem;
|
||||||
|
ssl_prefer_server_ciphers on;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://127.0.0.1:9135;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection "upgrade";
|
||||||
|
proxy_set_header Host $server_name;
|
||||||
|
proxy_buffering off;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
|
||||||
|
add_header Strict-Transport-Security "max-age=15552000; includeSubDomains" always;
|
||||||
|
}
|
||||||
|
}
|
26
roles/private/files/nginx.conf
Normal file
26
roles/private/files/nginx.conf
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
user www-data;
|
||||||
|
worker_processes 4;
|
||||||
|
pid /run/nginx.pid;
|
||||||
|
|
||||||
|
events {
|
||||||
|
worker_connections 768;
|
||||||
|
}
|
||||||
|
|
||||||
|
http {
|
||||||
|
sendfile on;
|
||||||
|
tcp_nopush on;
|
||||||
|
tcp_nodelay on;
|
||||||
|
keepalive_timeout 65;
|
||||||
|
types_hash_max_size 2048;
|
||||||
|
include /etc/nginx/mime.types;
|
||||||
|
default_type application/octet-stream;
|
||||||
|
|
||||||
|
access_log /var/log/nginx/access.log;
|
||||||
|
error_log /var/log/nginx/error.log;
|
||||||
|
|
||||||
|
gzip on;
|
||||||
|
gzip_disable "msie6";
|
||||||
|
|
||||||
|
include /etc/nginx/conf.d/*.conf;
|
||||||
|
include /etc/nginx/sites-enabled/*;
|
||||||
|
}
|
94
roles/private/tasks/main.yml
Normal file
94
roles/private/tasks/main.yml
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
---
|
||||||
|
- name: allow http from vpn
|
||||||
|
ufw:
|
||||||
|
rule: allow
|
||||||
|
port: '80'
|
||||||
|
proto: tcp
|
||||||
|
from: 100.64.0.0/10
|
||||||
|
|
||||||
|
- name: allow https from vpn
|
||||||
|
ufw:
|
||||||
|
rule: allow
|
||||||
|
port: '443'
|
||||||
|
proto: tcp
|
||||||
|
from: 100.64.0.0/10
|
||||||
|
|
||||||
|
- name: restart ufw
|
||||||
|
service: name=ufw state=restarted enabled=yes
|
||||||
|
|
||||||
|
- name: install letsencrypt
|
||||||
|
apt: name=letsencrypt state=latest
|
||||||
|
|
||||||
|
- name: create letsencrypt directory
|
||||||
|
file: name=/var/www/letsencrypt state=directory
|
||||||
|
|
||||||
|
- name: install nginx
|
||||||
|
apt: name=nginx state=latest
|
||||||
|
|
||||||
|
- name: remove default nginx
|
||||||
|
file: name=/etc/nginx/sites-enabled/default state=absent
|
||||||
|
|
||||||
|
- name: generate dhparams
|
||||||
|
shell: openssl dhparam -out /etc/nginx/dhparams.pem 2048
|
||||||
|
args:
|
||||||
|
creates: /etc/nginx/dhparams.pem
|
||||||
|
|
||||||
|
- name: add system nginx config
|
||||||
|
template:
|
||||||
|
src: ../files/nginx.conf
|
||||||
|
dest: /etc/nginx/nginx.conf
|
||||||
|
|
||||||
|
- name: copy http nginx configuration for each domain
|
||||||
|
copy:
|
||||||
|
src: "{{ item }}"
|
||||||
|
dest: "/etc/nginx/sites-enabled/"
|
||||||
|
with_fileglob:
|
||||||
|
- "files/{{ inventory_hostname }}/http.*.conf"
|
||||||
|
|
||||||
|
- name: restart nginx to get letsencrypt certificate
|
||||||
|
service: name=nginx state=restarted enabled=yes
|
||||||
|
|
||||||
|
- name: find deployed domains
|
||||||
|
ansible.builtin.find:
|
||||||
|
paths: "/etc/nginx/sites-enabled/"
|
||||||
|
patterns: "http.*.conf"
|
||||||
|
register: nginx_conf_files
|
||||||
|
delegate_to: "{{ inventory_hostname }}"
|
||||||
|
|
||||||
|
- name: extract domains from deployed nginx configurations
|
||||||
|
shell: |
|
||||||
|
grep -oP 'server_name\s+\K[^;]+' "{{ item.path }}"
|
||||||
|
loop: "{{ nginx_conf_files.files }}"
|
||||||
|
register: extracted_domains
|
||||||
|
|
||||||
|
# crt is given from the "ca" role to all hosts; that needs to run first
|
||||||
|
- name: request letsencrypt certificate
|
||||||
|
shell: >
|
||||||
|
REQUESTS_CA_BUNDLE="/usr/local/share/ca-certificates/{{ step_bootstrap_ca_url }}.crt" \
|
||||||
|
letsencrypt certonly -n -d {{ item.stdout }} \
|
||||||
|
--server https://{{ step_bootstrap_ca_url }}:{{ step_ca_port }}/acme/ACME/directory \
|
||||||
|
--webroot -w /var/www/letsencrypt \
|
||||||
|
--agree-tos --email {{ step_acme_cert_contact }}
|
||||||
|
args:
|
||||||
|
creates: "/etc/letsencrypt/live/{{ item.stdout }}"
|
||||||
|
loop: "{{ extracted_domains.results }}"
|
||||||
|
when: item.stdout != ""
|
||||||
|
|
||||||
|
- name: copy https nginx configuration for each domain
|
||||||
|
copy:
|
||||||
|
src: "{{ item }}"
|
||||||
|
dest: "/etc/nginx/sites-enabled/"
|
||||||
|
with_fileglob:
|
||||||
|
- "files/{{ inventory_hostname }}/https.*.conf"
|
||||||
|
|
||||||
|
- name: reload nginx to activate sites
|
||||||
|
service: name=nginx state=restarted
|
||||||
|
|
||||||
|
- name: add daily letsencrypt cronjob for cert renewal based on hash of domain name to prevent hitting LE rate limits
|
||||||
|
cron:
|
||||||
|
name: "letsencrypt_renewal_{{ item.stdout }}"
|
||||||
|
minute: "0"
|
||||||
|
hour: "5,17"
|
||||||
|
job: "REQUESTS_CA_BUNDLE=/usr/local/share/ca-certificates/{{ step_bootstrap_ca_url }}.crt letsencrypt renew --server https://{{ step_bootstrap_ca_url }}:{{ step_ca_port }}/acme/ACME/directory --cert-name {{ item.stdout }} -n --webroot -w /var/www/letsencrypt --agree-tos --email {{ step_acme_cert_contact }} && service nginx reload"
|
||||||
|
loop: "{{ extracted_domains.results }}"
|
||||||
|
when: item.stdout != ""
|
22
roles/roundcube/tasks/main.yml
Normal file
22
roles/roundcube/tasks/main.yml
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
---
|
||||||
|
- name: ensure rouncube docker/compose exist
|
||||||
|
file:
|
||||||
|
path: /etc/docker/compose/roundcube
|
||||||
|
state: directory
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: 0700
|
||||||
|
|
||||||
|
- name: build roundcube docker-compose.yml.j2
|
||||||
|
template:
|
||||||
|
src: ../templates/docker-compose.yml.j2
|
||||||
|
dest: /etc/docker/compose/roundcube/docker-compose.yml
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: u=rw,g=r,o=r
|
||||||
|
|
||||||
|
- name: daemon-reload and enable roundcube
|
||||||
|
ansible.builtin.systemd_service:
|
||||||
|
state: restarted
|
||||||
|
enabled: true
|
||||||
|
name: docker-compose@roundcube
|
22
roles/roundcube/templates/docker-compose.yml.j2
Normal file
22
roles/roundcube/templates/docker-compose.yml.j2
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
version: '3'
|
||||||
|
|
||||||
|
services:
|
||||||
|
roundcube:
|
||||||
|
image: roundcube/roundcubemail:latest
|
||||||
|
container_name: roundcubemail
|
||||||
|
restart: unless-stopped
|
||||||
|
hostname: roundcube.internal.simponic.xyz
|
||||||
|
volumes:
|
||||||
|
- ./www:/var/www/html
|
||||||
|
- ./db/sqlite:/var/roundcube/db
|
||||||
|
ports:
|
||||||
|
- 127.0.0.1:9002:80
|
||||||
|
dns:
|
||||||
|
- {{ johan_ip }}
|
||||||
|
environment:
|
||||||
|
- ROUNDCUBEMAIL_DB_TYPE=sqlite
|
||||||
|
- ROUNDCUBEMAIL_SKIN=elastic
|
||||||
|
- ROUNDCUBEMAIL_DEFAULT_HOST=ssl://mail.simponic.xyz
|
||||||
|
- ROUNDCUBEMAIL_DEFAULT_PORT=993
|
||||||
|
- ROUNDCUBEMAIL_SMTP_SERVER=tls://mail.simponic.xyz
|
||||||
|
- ROUNDCUBEMAIL_SMTP_PORT=587
|
22
roles/scurvy/tasks/main.yml
Normal file
22
roles/scurvy/tasks/main.yml
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
---
|
||||||
|
- name: ensure scurvy docker/compose exist
|
||||||
|
file:
|
||||||
|
path: /etc/docker/compose/scurvy
|
||||||
|
state: directory
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: 0700
|
||||||
|
|
||||||
|
- name: build scurvy docker-compose.yml.j2
|
||||||
|
template:
|
||||||
|
src: ../templates/docker-compose.yml.j2
|
||||||
|
dest: /etc/docker/compose/scurvy/docker-compose.yml
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: u=rw,g=r,o=r
|
||||||
|
|
||||||
|
- name: daemon-reload and enable scurvy
|
||||||
|
ansible.builtin.systemd_service:
|
||||||
|
state: restarted
|
||||||
|
enabled: true
|
||||||
|
name: docker-compose@scurvy
|
61
roles/scurvy/templates/docker-compose.yml.j2
Normal file
61
roles/scurvy/templates/docker-compose.yml.j2
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
version: '3'
|
||||||
|
services:
|
||||||
|
gluetun:
|
||||||
|
image: qmcgaw/gluetun
|
||||||
|
container_name: gluetun
|
||||||
|
cap_add:
|
||||||
|
- NET_ADMIN
|
||||||
|
devices:
|
||||||
|
- /dev/net/tun:/dev/net/tun
|
||||||
|
ports:
|
||||||
|
- 127.0.0.1:9000:8080/tcp
|
||||||
|
- 127.0.0.1:6881:6881
|
||||||
|
- 127.0.0.1:6881:6881/udp
|
||||||
|
volumes:
|
||||||
|
- /gluetun
|
||||||
|
environment:
|
||||||
|
- VPN_SERVICE_PROVIDER=mullvad
|
||||||
|
- VPN_TYPE=openvpn
|
||||||
|
- OPENVPN_USER={{ openvpn_user }}
|
||||||
|
- SERVER_CITIES=Salt Lake City UT
|
||||||
|
|
||||||
|
qbittorrent:
|
||||||
|
image: hotio/qbittorrent:latest
|
||||||
|
container_name: qbittorrent
|
||||||
|
environment:
|
||||||
|
- PUID=1000
|
||||||
|
- PGID=1000
|
||||||
|
volumes:
|
||||||
|
- qbittorrent_config:/config:rw
|
||||||
|
- type: bind
|
||||||
|
source: /mnt/hdd-01
|
||||||
|
target: /hdd-01
|
||||||
|
- type: bind
|
||||||
|
source: /mnt/ssd-01
|
||||||
|
target: /ssd-01
|
||||||
|
restart: unless-stopped
|
||||||
|
network_mode: "container:gluetun"
|
||||||
|
|
||||||
|
jellyfin:
|
||||||
|
image: lscr.io/linuxserver/jellyfin:latest
|
||||||
|
container_name: jellyfin
|
||||||
|
environment:
|
||||||
|
- JELLYFIN_PublishedServerUrl=https://jellyfin.internal.simponic.xyz
|
||||||
|
ports:
|
||||||
|
- 127.0.0.1:8096:8096
|
||||||
|
devices:
|
||||||
|
- /dev/dri:/dev/dri
|
||||||
|
volumes:
|
||||||
|
- type: bind
|
||||||
|
source: /mnt/hdd-01
|
||||||
|
target: /hdd-01
|
||||||
|
- type: bind
|
||||||
|
source: /mnt/ssd-01
|
||||||
|
target: /ssd-01
|
||||||
|
- jellyfin_config:/config:rw
|
||||||
|
- jellyfin_cache:/cache:rw
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
jellyfin_config:
|
||||||
|
jellyfin_cache:
|
||||||
|
qbittorrent_config:
|
45
roles/vpn/files/config/acl.json
Normal file
45
roles/vpn/files/config/acl.json
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
{
|
||||||
|
"groups": {
|
||||||
|
"group:admin": ["elizabeth.hunt"],
|
||||||
|
"group:roomates": ["riley.ferguson"],
|
||||||
|
"group:friends": ["riley.ferguson"],
|
||||||
|
"group:sys": ["sys"]
|
||||||
|
},
|
||||||
|
"tagOwners": {
|
||||||
|
"tag:prod": ["group:admin"],
|
||||||
|
"tag:private": ["group:admin"],
|
||||||
|
"tag:dev": ["group:admin"]
|
||||||
|
},
|
||||||
|
"acls": [
|
||||||
|
{
|
||||||
|
"action": "accept",
|
||||||
|
"src": ["group:admin"],
|
||||||
|
"dst": [
|
||||||
|
"tag:dev:*",
|
||||||
|
"tag:private:*",
|
||||||
|
"tag:prod:*",
|
||||||
|
"group:sys:*"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"action": "accept",
|
||||||
|
"src": ["group:sys"],
|
||||||
|
"dst": ["group:sys:*"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"action": "accept",
|
||||||
|
"src": ["group:admin"],
|
||||||
|
"dst": ["10.0.0.0/24:*"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"action": "accept",
|
||||||
|
"src": ["group:roomates"],
|
||||||
|
"dst": ["10.0.0.0/24:*", "tag:router:*"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"action": "accept",
|
||||||
|
"src": ["group:friends"],
|
||||||
|
"dst": ["group:sys:*"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -1,4 +0,0 @@
|
|||||||
---
|
|
||||||
groups:
|
|
||||||
admin:
|
|
||||||
- "lizzy"
|
|
@ -7,7 +7,7 @@ services:
|
|||||||
- ./config:/etc/headscale
|
- ./config:/etc/headscale
|
||||||
- ./data:/var/lib/headscale
|
- ./data:/var/lib/headscale
|
||||||
ports:
|
ports:
|
||||||
- 27896:8080
|
- 127.0.0.1:27896:8080
|
||||||
command: headscale serve
|
command: headscale serve
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
headscale-ui:
|
headscale-ui:
|
||||||
@ -15,4 +15,4 @@ services:
|
|||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
container_name: headscale-ui
|
container_name: headscale-ui
|
||||||
ports:
|
ports:
|
||||||
- 9443:443
|
- 127.0.0.1:9443:443
|
||||||
|
@ -23,6 +23,14 @@
|
|||||||
group: root
|
group: root
|
||||||
mode: u=rw,g=r,o=r
|
mode: u=rw,g=r,o=r
|
||||||
|
|
||||||
|
- name: build headscale config template
|
||||||
|
template:
|
||||||
|
src: ../templates/config.yml.j2
|
||||||
|
dest: /etc/docker/compose/headscale/config/config.yml
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: u=rw,g=r,o=r
|
||||||
|
|
||||||
- name: ensure headscale data volume exist
|
- name: ensure headscale data volume exist
|
||||||
file:
|
file:
|
||||||
path: /etc/docker/compose/headscale/data
|
path: /etc/docker/compose/headscale/data
|
||||||
@ -31,12 +39,6 @@
|
|||||||
group: root
|
group: root
|
||||||
mode: 0700
|
mode: 0700
|
||||||
|
|
||||||
- name: ensure headscale users
|
|
||||||
shell: |
|
|
||||||
docker exec headscale headscale user create "{{ item }}"
|
|
||||||
with_items:
|
|
||||||
- "{{ headscale_users }}"
|
|
||||||
|
|
||||||
- name: daemon-reload and enable headscale
|
- name: daemon-reload and enable headscale
|
||||||
ansible.builtin.systemd_service:
|
ansible.builtin.systemd_service:
|
||||||
state: restarted
|
state: restarted
|
||||||
|
@ -160,7 +160,7 @@ log:
|
|||||||
# Path to a file containg ACL policies.
|
# Path to a file containg ACL policies.
|
||||||
# ACLs can be defined as YAML or HUJSON.
|
# ACLs can be defined as YAML or HUJSON.
|
||||||
# https://tailscale.com/kb/1018/acls/
|
# https://tailscale.com/kb/1018/acls/
|
||||||
acl_policy_path: "/etc/headscale/acl.yml"
|
acl_policy_path: "/etc/headscale/acl.json"
|
||||||
|
|
||||||
## DNS
|
## DNS
|
||||||
#
|
#
|
||||||
@ -177,7 +177,7 @@ dns_config:
|
|||||||
|
|
||||||
# List of DNS servers to expose to clients.
|
# List of DNS servers to expose to clients.
|
||||||
nameservers:
|
nameservers:
|
||||||
- 1.1.1.1
|
- {{ johan_ip }}
|
||||||
|
|
||||||
# NextDNS (see https://tailscale.com/kb/1218/nextdns/).
|
# NextDNS (see https://tailscale.com/kb/1218/nextdns/).
|
||||||
# "abc123" is example NextDNS ID, replace with yours.
|
# "abc123" is example NextDNS ID, replace with yours.
|
||||||
@ -202,7 +202,7 @@ dns_config:
|
|||||||
# - 8.8.8.8
|
# - 8.8.8.8
|
||||||
|
|
||||||
# Search domains to inject.
|
# Search domains to inject.
|
||||||
domains: ['simponic.xyz']
|
domains: ['simponic.xyz', 'internal.simponic.xyz']
|
||||||
|
|
||||||
# Extra DNS records
|
# Extra DNS records
|
||||||
# so far only A-records are supported (on the tailscale side)
|
# so far only A-records are supported (on the tailscale side)
|
||||||
@ -223,7 +223,7 @@ dns_config:
|
|||||||
# `base_domain` must be a FQDNs, without the trailing dot.
|
# `base_domain` must be a FQDNs, without the trailing dot.
|
||||||
# The FQDN of the hosts will be
|
# The FQDN of the hosts will be
|
||||||
# `hostname.user.base_domain` (e.g., _myhost.myuser.example.com_).
|
# `hostname.user.base_domain` (e.g., _myhost.myuser.example.com_).
|
||||||
base_domain: headscale.simponic.xyz
|
base_domain: internal.simponic.xyz
|
||||||
|
|
||||||
# Unix socket used for the CLI to connect without authentication
|
# Unix socket used for the CLI to connect without authentication
|
||||||
# Note: for production you will want to set this to something like:
|
# Note: for production you will want to set this to something like:
|
||||||
@ -234,52 +234,43 @@ unix_socket_permission: "0770"
|
|||||||
# it is still being tested and might have some bugs, please
|
# it is still being tested and might have some bugs, please
|
||||||
# help us test it.
|
# help us test it.
|
||||||
# OpenID Connect
|
# OpenID Connect
|
||||||
# oidc:
|
oidc:
|
||||||
# only_start_if_oidc_is_available: true
|
# Block further startup until the OIDC provider is healthy and available
|
||||||
# issuer: "https://your-oidc.issuer.com/path"
|
only_start_if_oidc_is_available: false
|
||||||
# client_id: "your-oidc-client-id"
|
# Specified by your OIDC provider
|
||||||
# client_secret: "your-oidc-client-secret"
|
issuer: "https://authelia.simponic.xyz"
|
||||||
# # Alternatively, set `client_secret_path` to read the secret from the file.
|
# Specified/generated by your OIDC provider
|
||||||
# # It resolves environment variables, making integration to systemd's
|
client_id: "simponicheadscale"
|
||||||
# # `LoadCredential` straightforward:
|
client_secret: "{{ headscale_oidc_secret }}"
|
||||||
# client_secret_path: "${CREDENTIALS_DIRECTORY}/oidc_client_secret"
|
# alternatively, set `client_secret_path` to read the secret from the file.
|
||||||
# # client_secret and client_secret_path are mutually exclusive.
|
# It resolves environment variables, making integration to systemd's
|
||||||
#
|
# `LoadCredential` straightforward:
|
||||||
# # The amount of time from a node is authenticated with OpenID until it
|
#client_secret_path: "${CREDENTIALS_DIRECTORY}/oidc_client_secret"
|
||||||
# # expires and needs to reauthenticate.
|
|
||||||
# # Setting the value to "0" will mean no expiry.
|
# Customize the scopes used in the OIDC flow, defaults to "openid", "profile" and "email" and add custom query
|
||||||
# expiry: 180d
|
# parameters to the Authorize Endpoint request. Scopes default to "openid", "profile" and "email".
|
||||||
#
|
scope: ["openid", "profile", "email"]
|
||||||
# # Use the expiry from the token received from OpenID when the user logged
|
# Optional: Passed on to the browser login request – used to tweak behaviour for the OIDC provider
|
||||||
# # in, this will typically lead to frequent need to reauthenticate and should
|
extra_params:
|
||||||
# # only been enabled if you know what you are doing.
|
domain_hint: simponic.xyz
|
||||||
# # Note: enabling this will cause `oidc.expiry` to be ignored.
|
|
||||||
# use_expiry_from_token: false
|
# Optional: List allowed principal domains and/or users. If an authenticated user's domain is not in this list,
|
||||||
#
|
# the authentication request will be rejected.
|
||||||
# # Customize the scopes used in the OIDC flow, defaults to "openid", "profile" and "email" and add custom query
|
allowed_domains:
|
||||||
# # parameters to the Authorize Endpoint request. Scopes default to "openid", "profile" and "email".
|
- simponic.xyz
|
||||||
#
|
# Optional. Note that groups from Keycloak have a leading '/'.
|
||||||
# scope: ["openid", "profile", "email", "custom"]
|
# allowed_groups:
|
||||||
# extra_params:
|
# - /admins
|
||||||
# domain_hint: example.com
|
# - admins
|
||||||
#
|
# - people
|
||||||
# # List allowed principal domains and/or users. If an authenticated user's domain is not in this list, the
|
# Optional.
|
||||||
# # authentication request will be rejected.
|
allowed_users: {{ headscale_allowed_users }}
|
||||||
#
|
|
||||||
# allowed_domains:
|
# If `strip_email_domain` is set to `true`, the domain part of the username email address will be removed.
|
||||||
# - example.com
|
# This will transform `first-name.last-name@example.com` to the user `first-name.last-name`
|
||||||
# # Note: Groups from keycloak have a leading '/'
|
# If `strip_email_domain` is set to `false` the domain part will NOT be removed resulting to the following
|
||||||
# allowed_groups:
|
# user: `first-name.last-name.example.com`
|
||||||
# - /headscale
|
strip_email_domain: true
|
||||||
# allowed_users:
|
|
||||||
# - alice@example.com
|
|
||||||
#
|
|
||||||
# # If `strip_email_domain` is set to `true`, the domain part of the username email address will be removed.
|
|
||||||
# # This will transform `first-name.last-name@example.com` to the user `first-name.last-name`
|
|
||||||
# # If `strip_email_domain` is set to `false` the domain part will NOT be removed resulting to the following
|
|
||||||
# user: `first-name.last-name.example.com`
|
|
||||||
#
|
|
||||||
# strip_email_domain: true
|
|
||||||
|
|
||||||
# Logtail configuration
|
# Logtail configuration
|
||||||
# Logtail is Tailscales logging and auditing infrastructure, it allows the control panel
|
# Logtail is Tailscales logging and auditing infrastructure, it allows the control panel
|
@ -1,6 +1,8 @@
|
|||||||
user www-data;
|
user www-data;
|
||||||
worker_processes 4;
|
worker_processes 4;
|
||||||
pid /run/nginx.pid;
|
pid /run/nginx.pid;
|
||||||
|
load_module modules/ndk_http_module.so;
|
||||||
|
load_module modules/ngx_http_set_misc_module.so;
|
||||||
|
|
||||||
events {
|
events {
|
||||||
worker_connections 768;
|
worker_connections 768;
|
||||||
|
@ -0,0 +1,13 @@
|
|||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name authelia.simponic.xyz;
|
||||||
|
|
||||||
|
location /.well-known/acme-challenge {
|
||||||
|
root /var/www/letsencrypt;
|
||||||
|
try_files $uri $uri/ =404;
|
||||||
|
}
|
||||||
|
|
||||||
|
location / {
|
||||||
|
rewrite ^ https://authelia.simponic.xyz$request_uri? permanent;
|
||||||
|
}
|
||||||
|
}
|
13
roles/webservers/files/nijika/http.git.simponic.xyz.conf
Normal file
13
roles/webservers/files/nijika/http.git.simponic.xyz.conf
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name git.simponic.xyz;
|
||||||
|
|
||||||
|
location /.well-known/acme-challenge {
|
||||||
|
root /var/www/letsencrypt;
|
||||||
|
try_files $uri $uri/ =404;
|
||||||
|
}
|
||||||
|
|
||||||
|
location / {
|
||||||
|
rewrite ^ https://git.simponic.xyz$request_uri? permanent;
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,5 @@
|
|||||||
server_tokens off;
|
|
||||||
|
|
||||||
server {
|
server {
|
||||||
listen 80 default_server;
|
listen 80;
|
||||||
server_name headscale.simponic.xyz;
|
server_name headscale.simponic.xyz;
|
||||||
|
|
||||||
location /.well-known/acme-challenge {
|
location /.well-known/acme-challenge {
|
||||||
|
@ -0,0 +1,57 @@
|
|||||||
|
server {
|
||||||
|
listen 443 ssl;
|
||||||
|
server_name authelia.simponic.xyz;
|
||||||
|
|
||||||
|
ssl_certificate /etc/letsencrypt/live/authelia.simponic.xyz/fullchain.pem;
|
||||||
|
ssl_certificate_key /etc/letsencrypt/live/authelia.simponic.xyz/privkey.pem;
|
||||||
|
ssl_trusted_certificate /etc/letsencrypt/live/authelia.simponic.xyz/fullchain.pem;
|
||||||
|
|
||||||
|
ssl_session_cache shared:SSL:50m;
|
||||||
|
ssl_session_timeout 5m;
|
||||||
|
ssl_stapling on;
|
||||||
|
ssl_stapling_verify on;
|
||||||
|
|
||||||
|
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
|
||||||
|
ssl_ciphers "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4";
|
||||||
|
|
||||||
|
ssl_dhparam /etc/nginx/dhparams.pem;
|
||||||
|
ssl_prefer_server_ciphers on;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://127.0.0.1:9091;
|
||||||
|
|
||||||
|
client_body_buffer_size 128k;
|
||||||
|
|
||||||
|
#Timeout if the real server is dead
|
||||||
|
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503;
|
||||||
|
|
||||||
|
# Advanced Proxy Config
|
||||||
|
send_timeout 5m;
|
||||||
|
proxy_read_timeout 360;
|
||||||
|
proxy_send_timeout 360;
|
||||||
|
proxy_connect_timeout 360;
|
||||||
|
|
||||||
|
# Basic Proxy Config
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
proxy_set_header X-Forwarded-Host $http_host;
|
||||||
|
proxy_set_header X-Forwarded-Uri $request_uri;
|
||||||
|
proxy_set_header X-Forwarded-Ssl on;
|
||||||
|
proxy_redirect http:// $scheme://;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Connection "";
|
||||||
|
proxy_cache_bypass $cookie_session;
|
||||||
|
proxy_no_cache $cookie_session;
|
||||||
|
proxy_buffers 64 256k;
|
||||||
|
|
||||||
|
# If behind reverse proxy, forwards the correct IP
|
||||||
|
set_real_ip_from 10.0.0.0/8;
|
||||||
|
set_real_ip_from 172.0.0.0/8;
|
||||||
|
set_real_ip_from 192.168.0.0/16;
|
||||||
|
set_real_ip_from fc00::/7;
|
||||||
|
real_ip_header X-Forwarded-For;
|
||||||
|
real_ip_recursive on;
|
||||||
|
}
|
||||||
|
}
|
39
roles/webservers/files/nijika/https.git.simponic.xyz.conf
Normal file
39
roles/webservers/files/nijika/https.git.simponic.xyz.conf
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
server {
|
||||||
|
listen 443 ssl;
|
||||||
|
server_name git.simponic.xyz;
|
||||||
|
|
||||||
|
ssl_certificate /etc/letsencrypt/live/git.simponic.xyz/fullchain.pem;
|
||||||
|
ssl_certificate_key /etc/letsencrypt/live/git.simponic.xyz/privkey.pem;
|
||||||
|
ssl_trusted_certificate /etc/letsencrypt/live/git.simponic.xyz/fullchain.pem;
|
||||||
|
|
||||||
|
ssl_session_cache shared:SSL:50m;
|
||||||
|
ssl_session_timeout 5m;
|
||||||
|
ssl_stapling on;
|
||||||
|
ssl_stapling_verify on;
|
||||||
|
|
||||||
|
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
|
||||||
|
ssl_ciphers "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4";
|
||||||
|
|
||||||
|
ssl_dhparam /etc/nginx/dhparams.pem;
|
||||||
|
ssl_prefer_server_ciphers on;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://127.0.0.1:9966;
|
||||||
|
|
||||||
|
client_body_buffer_size 128k;
|
||||||
|
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
proxy_set_header X-Forwarded-Host $http_host;
|
||||||
|
proxy_set_header X-Forwarded-Uri $request_uri;
|
||||||
|
proxy_set_header X-Forwarded-Ssl on;
|
||||||
|
proxy_redirect http:// $scheme://;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Connection "";
|
||||||
|
proxy_cache_bypass $cookie_session;
|
||||||
|
proxy_no_cache $cookie_session;
|
||||||
|
proxy_buffers 64 256k;
|
||||||
|
}
|
||||||
|
}
|
@ -17,6 +17,9 @@
|
|||||||
- name: install nginx
|
- name: install nginx
|
||||||
apt: name=nginx state=latest
|
apt: name=nginx state=latest
|
||||||
|
|
||||||
|
- name: install libnginx-mod-http-set-misc
|
||||||
|
apt: name=libnginx-mod-http-set-misc state=latest
|
||||||
|
|
||||||
- name: install letsencrypt
|
- name: install letsencrypt
|
||||||
apt: name=letsencrypt state=latest
|
apt: name=letsencrypt state=latest
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user