ldap, internal CA, internal webserver, dns, etc.
This commit is contained in:
parent
b62d5f559b
commit
fb0b391408
@ -1,2 +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,7 +1,9 @@
|
||||
order:
|
||||
- common.yml
|
||||
- deploy-common.yml
|
||||
- deploy-nameservers.yml
|
||||
- deploy-webservers.yml
|
||||
- deploy-lldap.yml
|
||||
- deploy-authelia.yml
|
||||
- deploy-pihole.yml
|
||||
- deploy-vpn.yml
|
||||
- deploy-vpn-tags.yml
|
||||
- deploy-vpn-hosts.yml
|
||||
|
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-lldap.yml
Normal file
4
deploy-lldap.yml
Normal file
@ -0,0 +1,4 @@
|
||||
- name: lldap setup
|
||||
hosts: lldap
|
||||
roles:
|
||||
- lldap
|
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
|
@ -1,6 +1,14 @@
|
||||
---
|
||||
johan_ip: '100.64.0.5'
|
||||
|
||||
dns_servers:
|
||||
- 1.1.1.1
|
||||
- 1.0.0.1
|
||||
dns_dnssec: true
|
||||
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') }}"
|
2
group_vars/pihole.yml
Normal file
2
group_vars/pihole.yml
Normal file
@ -0,0 +1,2 @@
|
||||
---
|
||||
pihole_webpwd: "{{ lookup('env', 'PIHOLE_WEBPWD') }}"
|
@ -31,5 +31,14 @@ nijika ansible_user=root ansible_connection=ssh
|
||||
[dnsinternal]
|
||||
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]
|
||||
#ash ansible_user=root ansible_connection=ssh
|
||||
|
@ -7,8 +7,10 @@ services:
|
||||
volumes:
|
||||
- ./authelia:/config
|
||||
ports:
|
||||
- 9091:9091
|
||||
- 127.0.0.1:9091:9091
|
||||
restart: unless-stopped
|
||||
dns:
|
||||
- {{ johan_ip }}
|
||||
redis:
|
||||
image: redis:alpine
|
||||
container_name: redis
|
||||
|
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 }}
|
@ -41,6 +41,16 @@
|
||||
no_extra_spaces: true
|
||||
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
|
||||
ansible.builtin.shell: pgrep systemd-resolve
|
||||
failed_when: false
|
||||
|
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
|
@ -38,8 +38,3 @@ simponic.xyz. 1 IN MX 10 mail.simponic.xyz.
|
||||
;; 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"
|
||||
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
|
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;
|
||||
}
|
||||
}
|
27
roles/private/files/nginx.conf
Normal file
27
roles/private/files/nginx.conf
Normal file
@ -0,0 +1,27 @@
|
||||
user www-data;
|
||||
worker_processes 4;
|
||||
pid /run/nginx.pid;
|
||||
load_module modules/ndk_http_module.so;
|
||||
|
||||
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/*;
|
||||
}
|
95
roles/private/tasks/main.yml
Normal file
95
roles/private/tasks/main.yml
Normal file
@ -0,0 +1,95 @@
|
||||
---
|
||||
- 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 monthly letsencrypt cronjob for cert renewal based on hash of domain name to prevent hitting LE rate limits
|
||||
cron:
|
||||
name: "letsencrypt_renewal_{{ item.stdout }}"
|
||||
day: "{{ '%02d' | format(1 + (item.stdout | hash('md5') | int(0, 16) % 27)) }}"
|
||||
hour: "{{ (item.stdout | hash('md5') | int(0, 16) % 24 ) }}"
|
||||
minute: "{{ (item.stdout | hash('md5') | int(0, 16) % 60 ) }}"
|
||||
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 != ""
|
@ -1,6 +1,7 @@
|
||||
{
|
||||
"groups": {
|
||||
"group:admin": ["elizabeth.hunt"]
|
||||
"group:admin": ["elizabeth.hunt"],
|
||||
"group:sys": ["sys"]
|
||||
},
|
||||
"tagOwners": {
|
||||
"tag:prod": ["group:admin"],
|
||||
@ -14,8 +15,14 @@
|
||||
"dst": [
|
||||
"tag:dev:*",
|
||||
"tag:private:*",
|
||||
"tag:prod:*"
|
||||
"tag:prod:*",
|
||||
"group:sys:*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"action": "accept",
|
||||
"src": ["group:sys"],
|
||||
"dst": ["group:sys:*"]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ services:
|
||||
- ./config:/etc/headscale
|
||||
- ./data:/var/lib/headscale
|
||||
ports:
|
||||
- 27896:8080
|
||||
- 127.0.0.1:27896:8080
|
||||
command: headscale serve
|
||||
restart: unless-stopped
|
||||
headscale-ui:
|
||||
@ -15,4 +15,4 @@ services:
|
||||
restart: unless-stopped
|
||||
container_name: headscale-ui
|
||||
ports:
|
||||
- 9443:443
|
||||
- 127.0.0.1:9443:443
|
||||
|
@ -177,7 +177,7 @@ dns_config:
|
||||
|
||||
# List of DNS servers to expose to clients.
|
||||
nameservers:
|
||||
- 1.1.1.1
|
||||
- {{ johan_ip }}
|
||||
|
||||
# NextDNS (see https://tailscale.com/kb/1218/nextdns/).
|
||||
# "abc123" is example NextDNS ID, replace with yours.
|
||||
@ -202,7 +202,7 @@ dns_config:
|
||||
# - 8.8.8.8
|
||||
|
||||
# Search domains to inject.
|
||||
domains: ['simponic.xyz']
|
||||
domains: ['simponic.xyz', 'internal.simponic.xyz']
|
||||
|
||||
# Extra DNS records
|
||||
# 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.
|
||||
# The FQDN of the hosts will be
|
||||
# `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
|
||||
# Note: for production you will want to set this to something like:
|
||||
|
Loading…
Reference in New Issue
Block a user