created major large-scale changes
This commit is contained in:
17
roles/init-server/files/letsencrypt/renewal-hooks/post/up-dependents.sh
Executable file
17
roles/init-server/files/letsencrypt/renewal-hooks/post/up-dependents.sh
Executable file
@@ -0,0 +1,17 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
HTTP_SERVERS=()
|
||||
HTTP_SERVERS_LEN="${#HTTP_SERVERS[@]}"
|
||||
|
||||
if command -v systemctl > /dev/null 2>&1; then
|
||||
if (( HTTP_SERVERS_LEN > 0 )); then
|
||||
for htserv in "${HTTP_SERVERS[@]}"
|
||||
do
|
||||
sudo systemctl start "$htserv"
|
||||
done
|
||||
fi
|
||||
fi
|
||||
if command -v podman > /dev/null 2>&1; then
|
||||
podman start -a
|
||||
fi
|
||||
17
roles/init-server/files/letsencrypt/renewal-hooks/pre/down-dependents.sh
Executable file
17
roles/init-server/files/letsencrypt/renewal-hooks/pre/down-dependents.sh
Executable file
@@ -0,0 +1,17 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
HTTP_SERVERS=()
|
||||
HTTP_SERVERS_LEN="${#HTTP_SERVERS[@]}"
|
||||
|
||||
if command -v systemctl > /dev/null 2>&1; then
|
||||
if (( HTTP_SERVERS_LEN > 0 )); then
|
||||
for htserv in "${HTTP_SERVERS[@]}"
|
||||
do
|
||||
sudo systemctl stop "$htserv"
|
||||
done
|
||||
fi
|
||||
fi
|
||||
if command -v podman > /dev/null 2>&1; then
|
||||
podman stop -a
|
||||
fi
|
||||
13
roles/init-server/files/systemd/system/surge.service
Normal file
13
roles/init-server/files/systemd/system/surge.service
Normal file
@@ -0,0 +1,13 @@
|
||||
[Unit]
|
||||
Description=surge
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=surge service start
|
||||
ExecStop=surge service stop
|
||||
RemainAfterExit=yes
|
||||
|
||||
[Install]
|
||||
WantedBy=default.target
|
||||
@@ -0,0 +1,9 @@
|
||||
# Search these registries when pulling images without full path
|
||||
unqualified-search-registries = ["docker.io", "quay.io", "ghcr.io"]
|
||||
|
||||
# Registry-specific configuration
|
||||
# [[registry]]
|
||||
# location = "docker.io"
|
||||
|
||||
# [[registry.mirror]]
|
||||
# location = "mirror.gcr.io"
|
||||
@@ -0,0 +1,14 @@
|
||||
[Unit]
|
||||
Description=aria2 Daemon
|
||||
Requires=network.target
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=forking
|
||||
ExecStart=/usr/bin/aria2c -D
|
||||
ExecReload=/usr/bin/kill -HUP $MAINPID
|
||||
RestartSec=1min
|
||||
Restart=on-failure
|
||||
|
||||
[Install]
|
||||
WantedBy=default.target
|
||||
BIN
roles/init-server/files/user/journal/mythe-sisyphus-klein.png
Normal file
BIN
roles/init-server/files/user/journal/mythe-sisyphus-klein.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 MiB |
139
roles/init-server/files/user/srv/domain-root/error/503.html
Normal file
139
roles/init-server/files/user/srv/domain-root/error/503.html
Normal file
@@ -0,0 +1,139 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>{{.Host}}: {{ph "http.request.uri.path"}}</title>
|
||||
<style>
|
||||
body {
|
||||
background-image: url(./dark-matter.png);
|
||||
animation: 7s infinite ease-in-out day-cycle-bg;
|
||||
}
|
||||
@keyframes day-cycle-bg {
|
||||
0% {
|
||||
background-color: #000;
|
||||
}
|
||||
15% {
|
||||
background-color: #121212;
|
||||
}
|
||||
75% {
|
||||
background-color: #121212;
|
||||
}
|
||||
100% {
|
||||
background-color: #000;
|
||||
}
|
||||
}
|
||||
|
||||
img {
|
||||
display: block;
|
||||
margin: 3vh auto;
|
||||
max-width: 25vw;
|
||||
animation: 7s infinite alternate day-cycle-filter;
|
||||
}
|
||||
@keyframes day-cycle-filter {
|
||||
0% {
|
||||
filter: brightness(1.00) contrast(0.66) grayscale(0.75);
|
||||
}
|
||||
15% {
|
||||
filter: brightness(1.33) contrast(1.00) grayscale(0.66);
|
||||
}
|
||||
75% {
|
||||
filter: brightness(1.33) contrast(1.10) grayscale(0.66);
|
||||
}
|
||||
100% {
|
||||
filter: brightness(1.00) contrast(0.66) grayscale(0.75);
|
||||
}
|
||||
}
|
||||
|
||||
#sun {
|
||||
display: block;
|
||||
content: "";
|
||||
margin: 0 auto;
|
||||
height: 10vw;
|
||||
max-width: 100vw;
|
||||
background-color: #993333;
|
||||
box-shadow: 0 0 10px 5px #000 inset;
|
||||
position: relative;
|
||||
top: 3vh;
|
||||
transform: rotateX(180deg) rotateY(180deg);
|
||||
animation: 7s infinite linear day-cycle-celestial;
|
||||
}
|
||||
@keyframes day-cycle-celestial {
|
||||
0% {
|
||||
clip-path: circle(33px at 100% 0%);
|
||||
}
|
||||
25% {
|
||||
clip-path: circle(33px at 75% 25%);
|
||||
}
|
||||
50% {
|
||||
clip-path: circle(33px at center 66%);
|
||||
}
|
||||
75% {
|
||||
clip-path: circle(33px at 25% 25%);
|
||||
}
|
||||
100% {
|
||||
clip-path: circle(33px at 0% 0%);
|
||||
}
|
||||
}
|
||||
|
||||
#err-message, #err-trace {
|
||||
display: block;
|
||||
margin: 50px auto;
|
||||
}
|
||||
#err {
|
||||
margin: 2vh auto;
|
||||
max-width: 75vw;
|
||||
color: #fff;
|
||||
background-color: #000;
|
||||
border-radius: 10px;
|
||||
padding: 3%;
|
||||
position: relative;
|
||||
top: -50px;
|
||||
z-index: -1;
|
||||
animation: 7s infinite ease-in-out day-cycle-bxsh;
|
||||
}
|
||||
@keyframes day-cycle-bxsh {
|
||||
0% {
|
||||
box-shadow: 0 0 25px 15px #000 inset;
|
||||
}
|
||||
15% {
|
||||
box-shadow: 0 0 25px 15px #121212 inset;
|
||||
}
|
||||
75% {
|
||||
box-shadow: 0 0 25px 15px #121212 inset;
|
||||
}
|
||||
100% {
|
||||
box-shadow: 0 0 25px 15px #000 inset;
|
||||
}
|
||||
}
|
||||
|
||||
#err-message {
|
||||
max-width: 66%;
|
||||
text-align: justify;
|
||||
}
|
||||
#err-trace {
|
||||
max-width: 50%;
|
||||
}
|
||||
#err-summary {
|
||||
text-align: center;
|
||||
color: #993333;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="sun"></div>
|
||||
<img src="mythe-sisyphus-klein.png" alt="Sisyphus carrying a boulder" srcset="https://kariannekirsten.com/wp-content/uploads/2022/12/mythe-klein.png"/>
|
||||
<main>
|
||||
<article id="err">
|
||||
<section id="err-summary" class="post frontmatter">
|
||||
<h1>Under Construction</h1>
|
||||
<h2>Err. {{ph "http.error.status_code"}}: {{ph "http.error.status_text"}}</h2>
|
||||
</section>
|
||||
<section id="err-body" class="post body">
|
||||
<p id="err-message" class="message">{{ph "http.error.message"}}</p>
|
||||
<code id="err-trace" class="trace http">
|
||||
{{ph "http.error.trace"}}
|
||||
</code>
|
||||
</section>
|
||||
</article>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 121 B |
Binary file not shown.
|
After Width: | Height: | Size: 1.1 MiB |
@@ -1,10 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
if [[ "$1" == "start" ]]; then
|
||||
/usr/sbin/iptables -A FORWARD -i dsnet -p tcp --sport {80,443,465,587,995,110,143,993} -j ACCEPT
|
||||
/usr/sbin/iptables -t nat -A POSTROUTING -o dsnet -j MASQUERADE
|
||||
elif [[ "$1" == "stop" ]]; then
|
||||
/usr/sbin/iptables -D FORWARD -i dsnet -p tcp --sport {80,443,465,587,995,110,143,993} -j ACCEPT
|
||||
/usr/sbin/iptables -t nat -D POSTROUTING -o dsnet -j MASQUERADE
|
||||
fi
|
||||
@@ -5,6 +5,22 @@
|
||||
ansible.builtin.debug:
|
||||
msg: "No post-installaton or additional installation steps needed--continuing..."
|
||||
listen: default
|
||||
- name: Setting up Git
|
||||
ansible.builtin.include_tasks:
|
||||
file: tasks/contingent/pkg/git.yml
|
||||
listen: git
|
||||
- name: Setting up Certbot
|
||||
ansible.builtin.include_tasks:
|
||||
file: tasks/contingent/pkg/certbot.yml
|
||||
listen: certbot
|
||||
- name: Setting up TOR
|
||||
ansible.builtin.include_tasks:
|
||||
file: tasks/contingent/pkg/tor.yml
|
||||
listen: tor
|
||||
- name: Setting up Wireguard
|
||||
ansible.builtin.include_tasks:
|
||||
file: tasks/contingent/pkg/wireguard.yml
|
||||
listen: wireguard
|
||||
- name: Setting up Crowdsec
|
||||
ansible.builtin.include_tasks:
|
||||
file: tasks/contingent/pkg/crowdsec.yml
|
||||
@@ -13,14 +29,6 @@
|
||||
ansible.builtin.include_tasks:
|
||||
file: tasks/contingent/pkg/headscale.yml
|
||||
listen: headscale
|
||||
- name: Setting up Git
|
||||
ansible.builtin.include_tasks:
|
||||
file: tasks/contingent/pkg/git.yml
|
||||
listen: git
|
||||
- name: Setting up TOR
|
||||
ansible.builtin.include_tasks:
|
||||
file: tasks/contingent/pkg/tor.yml
|
||||
listen: tor
|
||||
- name: Setting up DSNet
|
||||
ansible.builtin.include_tasks:
|
||||
file: tasks/contingent/pkg/dsnet.yml
|
||||
|
||||
@@ -37,15 +37,47 @@
|
||||
ansible.builtin.include_tasks:
|
||||
file: tasks/contingent/pkg/uv.yml
|
||||
listen: uv
|
||||
- name: Setting up Radicle
|
||||
- name: Setting up Podman
|
||||
ansible.builtin.include_tasks:
|
||||
file: tasks/contingent/pkg/radicle.yml
|
||||
listen: radicle
|
||||
- name: Setting up Surge
|
||||
file: tasks/contingent/pkg/podman.yml
|
||||
listen: podman
|
||||
- name: Setting up Podman Compose sources
|
||||
ansible.builtin.include_tasks:
|
||||
file: tasks/contingent/pkg/surge.yml
|
||||
listen: surge
|
||||
file: tasks/contingent/pkg/skato_compose.yml
|
||||
listen: skato_compose
|
||||
- name: Setting up Quartz
|
||||
ansible.builtin.include_tasks:
|
||||
file: tasks/contingent/pkg/quartz.yml
|
||||
listen: quartz
|
||||
- name: Setting up native CLI tools sources
|
||||
ansible.builtin.include_tasks:
|
||||
file: tasks/contingent/pkg/skato_cli.yml
|
||||
listen: skato_cli
|
||||
- name: Setting up blog theme
|
||||
ansible.builtin.include_tasks:
|
||||
file: tasks/contingent/pkg/skato_blog_theme.yml
|
||||
listen: skato_blog_theme
|
||||
- name: Setting up blog
|
||||
ansible.builtin.include_tasks:
|
||||
file: tasks/contingent/pkg/skato_blog.yml
|
||||
listen: skato_blog
|
||||
- name: Setting up website sources
|
||||
ansible.builtin.include_tasks:
|
||||
file: tasks/contingent/pkg/sukaato.yml
|
||||
listen: sukaato
|
||||
- name: Setting up Surge
|
||||
ansible.builtin.include_tasks:
|
||||
file: tasks/contingent/pkg/surge.yml
|
||||
listen: surge
|
||||
- name: Setting up Aria2
|
||||
ansible.builtin.include_tasks:
|
||||
file: tasks/contingent/pkg/aria.yml
|
||||
listen: aria
|
||||
- name: Setting up Radicle
|
||||
ansible.builtin.include_tasks:
|
||||
file: tasks/contingent/pkg/radicle.yml
|
||||
listen: radicle
|
||||
- name: Setting up TOTP
|
||||
ansible.builtin.include_tasks:
|
||||
file: tasks/contingent/pkg/libpam-google-authenticator.yml
|
||||
listen: libpam-google-authenticator
|
||||
|
||||
70
roles/init-server/tasks/contingent/pkg/aria.yml
Normal file
70
roles/init-server/tasks/contingent/pkg/aria.yml
Normal file
@@ -0,0 +1,70 @@
|
||||
---
|
||||
- name: Acquiring home of current user
|
||||
when: ansible_facts["system"] == "Linux"
|
||||
ansible.builtin.shell:
|
||||
cmd: "echo ~{{ ansible_user }}"
|
||||
register: ansible_user_home
|
||||
- name: Acquiring current user
|
||||
when: ansible_facts["system"] == "Linux"
|
||||
ansible.builtin.shell:
|
||||
cmd: "echo {{ ansible_user }}"
|
||||
register: current_user
|
||||
- name: Informing user of requirement of two main domains
|
||||
when: (certbot.domains | length) < 2 or (certbot.domains | length) > 2
|
||||
ansible.builtin.fail:
|
||||
msg: Only two domains allowed and required
|
||||
- name: Informing user of requirement at least one wildcard
|
||||
when: (certbot.domains | select("regex", "^\\*\\.") | list | length) == 0
|
||||
ansible.builtin.fail:
|
||||
msg: At least one of the FQDNs must have a wildcard
|
||||
# - name: Setting the FQDN for development
|
||||
# when: compose.mode == "dev"
|
||||
# ansible.builtin.set_fact:
|
||||
# web_fqdn: "{{ (certbot.domains | map('regex_replace', '\\.([^\\.]*)$', '.test') | reject('regex', '^\\*\\.') | list)[0] }}"
|
||||
- name: Setting the FQDN
|
||||
# when: compose.mode == "prod"
|
||||
ansible.builtin.set_fact:
|
||||
web_fqdn: "{{ (certbot.domains | reject('regex', '^\\*\\.') | list)[0] }}"
|
||||
- name: Creating directory to store configuration file
|
||||
ansible.builtin.file:
|
||||
path: "{{ ansible_user_home.stdout }}/.aria2"
|
||||
recurse: true
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
mode: "755"
|
||||
state: directory
|
||||
- name: Configuring Aria2
|
||||
become: true
|
||||
become_user: "{{ current_user.stdout }}"
|
||||
ansible.builtin.template:
|
||||
src: user/aria2/aria2.conf.j2
|
||||
dest: "{{ ansible_user_home.stdout }}/.aria2/aria2.conf"
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
mode: "644"
|
||||
force: true
|
||||
backup: true
|
||||
# validate: "aria2c --check"
|
||||
- name: Setting up Aria2 as a service
|
||||
when: aria.rpc.enabled and not aria.containerized
|
||||
block:
|
||||
- name: Creating a user SystemD service unit for Aria2
|
||||
become: true
|
||||
become_user: "{{ current_user.stdout }}"
|
||||
ansible.builtin.copy:
|
||||
src: user/config/systemd/user/aria2cd.service
|
||||
dest: "{{ ansible_user_home.stdout }}/.config/systemd/user/aria2cd.service"
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
mode: "644"
|
||||
force: true
|
||||
backup: true
|
||||
- name: Starting and enabling user SystemD service unit for Aria2
|
||||
become: true
|
||||
become_user: "{{ current_user.stdout }}"
|
||||
ansible.builtin.systemd_service:
|
||||
name: aria2cd
|
||||
scope: user
|
||||
enabled: true
|
||||
state: started
|
||||
daemon_reload: true
|
||||
166
roles/init-server/tasks/contingent/pkg/certbot.yml
Normal file
166
roles/init-server/tasks/contingent/pkg/certbot.yml
Normal file
@@ -0,0 +1,166 @@
|
||||
---
|
||||
- name: Informing user of requirement of two main domains
|
||||
when: (certbot.domains | length) < 2 or (certbot.domains | length) > 2
|
||||
ansible.builtin.fail:
|
||||
msg: Only two domains allowed and required
|
||||
- name: Informing user of requirement at least one wildcard
|
||||
when: (certbot.domains | select("regex", "^\\*\\.") | list | length) == 0
|
||||
ansible.builtin.fail:
|
||||
msg: At least one of the FQDNs must have a wildcard
|
||||
# - name: Modifying FQDN list for development
|
||||
# when: "certbot.mode == 'dev'"
|
||||
# ansible.builtin.set_fact:
|
||||
# web_fqdns: "{{ certbot.domains | map('regex_replace', '\\.([^\\.]*)$', '.test') | list }}"
|
||||
- name: Modifying FQDN list for development
|
||||
# when: "certbot.mode == 'prod'"
|
||||
ansible.builtin.set_fact:
|
||||
web_fqdns: "{{ certbot.domains }}"
|
||||
- name: Creating domain arguments for certbot
|
||||
ansible.builtin.set_fact:
|
||||
certbot_domains: "{{ ['-d'] | product(web_fqdns) | map('join', '=') | list }}"
|
||||
- name: Getting public IP
|
||||
community.general.ipify_facts:
|
||||
validate_certs: false
|
||||
timeout: 20
|
||||
- name: Starting domain name registration with standalone DNS
|
||||
when: "certbot.auth_method == 'dns' and not certbot.containerized"
|
||||
ignore_errors: true
|
||||
block:
|
||||
- name: Opening port 53
|
||||
become: true
|
||||
ansible.builtin.iptables:
|
||||
chain: INPUT
|
||||
protocol: tcp
|
||||
destination_port: 53
|
||||
jump: ACCEPT
|
||||
comment: Opening up port 53
|
||||
# @NOTE https://github.com/siilike/certbot-dns-standalone
|
||||
- name: Exemplifying needed ACME record
|
||||
ansible.builtin.set_fact:
|
||||
acme_record: |
|
||||
{{ inventory_hostname }} IN A {{ ipify_public_ip }}
|
||||
_acme-challenge.{{ inventory_hostname }} IN CNAME {{ inventory_hostname }}.acme.{{ inventory_hostname }}.
|
||||
acme.{{ inventory_hostname }} IN NS ns.acme.{{ inventory_hostname }}.
|
||||
ns.acme.{{ inventory_hostname }} IN A {{ ipify_public_ip }}
|
||||
- name: Informing user of need to set up ACME record
|
||||
ansible.builtin.debug:
|
||||
msg: "Please set ACME record in domain name provider:\n {{ acme_record }}"
|
||||
- name: Waiting for user to set up ACME records
|
||||
ansible.builtin.pause:
|
||||
- name: Running certbot to authenticate and acquire domain name certificates
|
||||
become: true
|
||||
when: "certbot.mode == 'dev'"
|
||||
ansible.builtin.command:
|
||||
argv:
|
||||
- certbot
|
||||
- certonly
|
||||
- "--staging"
|
||||
- "--debug"
|
||||
- "--authenticator=dns-standalone"
|
||||
- "--email={{ certbot.email }}"
|
||||
- "--agree-tos"
|
||||
- "--non-interactive"
|
||||
- "--dns-standalone-address={{ ipify_public_ip }}"
|
||||
# - "--dns-standalone-ipv6-address={{ ansible_default_ipv6.address | default(ansible_all_ipv6_addresses[0]) }}"
|
||||
- "--dns-standalone-port={{ certbot.port }}"
|
||||
- "{{ certbot_domains[0] }}"
|
||||
- "{{ certbot_domains[1] }}"
|
||||
- name: Running certbot to authenticate and acquire domain name certificates
|
||||
become: true
|
||||
when: "certbot.mode == 'prod'"
|
||||
ansible.builtin.command:
|
||||
argv:
|
||||
- certbot
|
||||
- certonly
|
||||
- "--authenticator=dns-standalone"
|
||||
- "--email={{ certbot.email }}"
|
||||
- "--agree-tos"
|
||||
- "--non-interactive"
|
||||
- "--dns-standalone-address={{ ipify_public_ip }}"
|
||||
# - "--dns-standalone-ipv6-address={{ ansible_default_ipv6.address | default(ansible_all_ipv6_addresses[0]) }}"
|
||||
- "--dns-standalone-port={{ certbot.port }}"
|
||||
- "{{ certbot_domains[0] }}"
|
||||
- "{{ certbot_domains[1] }}"
|
||||
- name: Starting domain name registration with standalone option
|
||||
when: "certbot.auth_method == 'standalone' and not certbot.containerized"
|
||||
ignore_errors: true
|
||||
block:
|
||||
- name: Opening port 80
|
||||
become: true
|
||||
ansible.builtin.iptables:
|
||||
chain: INPUT
|
||||
protocol: tcp
|
||||
destination_port: 80
|
||||
jump: ACCEPT
|
||||
comment: Open up port 80
|
||||
- name: Acquiring domain certificates
|
||||
become: true
|
||||
when: "certbot.mode == 'dev'"
|
||||
ansible.builtin.command:
|
||||
argv:
|
||||
- certbot
|
||||
- certonly
|
||||
- "--staging"
|
||||
- "--debug"
|
||||
- "--standalone"
|
||||
- "--preferred-challenges=http-01"
|
||||
- "--email={{ certbot.email }}"
|
||||
- "--agree-tos"
|
||||
- "--non-interactive"
|
||||
- "{{ certbot_domains[0] }}"
|
||||
- "{{ certbot_domains[1] }}"
|
||||
- name: Acquiring domain certificates
|
||||
become: true
|
||||
when: "certbot.mode == 'dev'"
|
||||
ansible.builtin.command:
|
||||
argv:
|
||||
- certbot
|
||||
- certonly
|
||||
- "--standalone"
|
||||
- "--email {{ certbot.email }}"
|
||||
- "--agree-tos"
|
||||
- "--non-interactive"
|
||||
- "--preferred-challenges http-01"
|
||||
- "{{ certbot_domains[0] }}"
|
||||
- "{{ certbot_domains[1] }}"
|
||||
- name: Creating needed directory for renewal pre- hooks
|
||||
become: true
|
||||
ansible.builtin.file:
|
||||
path: /etc/letsencrypt/renewal-hooks/pre
|
||||
recurse: true
|
||||
owner: root
|
||||
group: root
|
||||
mode: "755"
|
||||
state: directory
|
||||
- name: Copying renewal pre- hook to renewal pre- hook path
|
||||
become: true
|
||||
ansible.builtin.copy:
|
||||
src: letsencrypt/renewal-hooks/pre/down-dependents.sh
|
||||
dest: /etc/letsencrypt/renewal-hooks/pre/
|
||||
owner: root
|
||||
group: root
|
||||
mode: "755"
|
||||
force: true
|
||||
backup: true
|
||||
- name: Creating needed directory for renewal post- hooks
|
||||
become: true
|
||||
ansible.builtin.file:
|
||||
path: /etc/letsencrypt/renewal-hooks/post
|
||||
recurse: true
|
||||
owner: root
|
||||
group: root
|
||||
mode: "755"
|
||||
state: directory
|
||||
- name: Copying renewal post- hook to renewal post- hook path
|
||||
become: true
|
||||
ansible.builtin.copy:
|
||||
src: letsencrypt/renewal-hooks/post/up-dependents.sh
|
||||
dest: /etc/letsencrypt/renewal-hooks/post/
|
||||
owner: root
|
||||
group: root
|
||||
mode: "755"
|
||||
force: true
|
||||
backup: true
|
||||
- name: Starting domain name registration with webroot option
|
||||
when: "certbot.auth_method == 'webroot' and not certbot.containerized"
|
||||
block: []
|
||||
@@ -1,40 +1,65 @@
|
||||
- name: Restarting SystemD service
|
||||
become: true
|
||||
ansible.builtin.systemd_service:
|
||||
name: crowdsec
|
||||
scope: system
|
||||
enabled: true
|
||||
state: started
|
||||
- name: Changing the address and port of the Crowdsec server
|
||||
become: true
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/crowdsec/config.yaml
|
||||
regexp: "^ {4}listen_uri"
|
||||
line: " listen_uri: localhost:{{ crowdsec.port }}"
|
||||
owner: root
|
||||
group: root
|
||||
mode: "644"
|
||||
- name: Changing the address of the Crowdsec Prometheus server
|
||||
become: true
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/crowdsec/config.yaml
|
||||
regexp: "^ {2}listen_addr"
|
||||
line: " listen_addr: localhost"
|
||||
owner: root
|
||||
group: root
|
||||
mode: "644"
|
||||
- name: Changing target or expected address for credentials of the Crowdsec local API
|
||||
become: true
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/crowdsec/local_api_credentials.yaml
|
||||
regexp: "^url"
|
||||
line: "url: http://localhost:{{ crowdsec.port }}"
|
||||
owner: root
|
||||
group: root
|
||||
mode: "644"
|
||||
- name: Restarting SystemD service
|
||||
become: true
|
||||
ansible.builtin.systemd_service:
|
||||
name: crowdsec
|
||||
scope: system
|
||||
state: restarted
|
||||
- name: Preparing non-containerized Crowdsec
|
||||
when: not crowdsec.containerized
|
||||
block:
|
||||
- name: Changing the address and port of the Crowdsec server
|
||||
become: true
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/crowdsec/config.yaml
|
||||
insertafter: EOF
|
||||
regexp: "^ {4}listen_uri"
|
||||
line: " listen_uri: localhost:{{ crowdsec.port }}"
|
||||
owner: root
|
||||
group: root
|
||||
mode: "644"
|
||||
- name: Changing the address of the Crowdsec Prometheus server
|
||||
become: true
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/crowdsec/config.yaml
|
||||
regexp: "^ {2}listen_addr"
|
||||
insertafter: EOF
|
||||
line: " listen_addr: localhost"
|
||||
owner: root
|
||||
group: root
|
||||
mode: "644"
|
||||
- name: Changing target or expected address for credentials of the Crowdsec local API
|
||||
become: true
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/crowdsec/local_api_credentials.yaml
|
||||
insertafter: EOF
|
||||
regexp: "^url"
|
||||
line: "url: http://localhost:{{ crowdsec.port }}"
|
||||
owner: root
|
||||
group: root
|
||||
mode: "644"
|
||||
- name: Restarting SystemD service
|
||||
become: true
|
||||
ansible.builtin.systemd_service:
|
||||
name: crowdsec
|
||||
scope: system
|
||||
state: restarted
|
||||
- name: Adding remediation component or bouncer
|
||||
ansible.builtin.command:
|
||||
cmd: "cscli bouncers add {{ item }}"
|
||||
loop: "{{ crowdsec.bouncers }}"
|
||||
- name: Installing Crowdsec collections
|
||||
ansible.builtin.command:
|
||||
cmd: "cscli collections install {{ item }}"
|
||||
loop: "{{ crowdsec.colls }}"
|
||||
- name: Installing Crowdsec parsers
|
||||
ansible.builtin.command:
|
||||
cmd: "cscli parsers install {{ item }}"
|
||||
loop: "{{ crowdsec.parsers }}"
|
||||
- name: Installing Crowdsec scenarios
|
||||
ansible.builtin.command:
|
||||
cmd: "cscli scenarios install {{ item }}"
|
||||
loop: "{{ crowdsec.scenarios }}"
|
||||
- name: Installing Crowdsec postoverflows
|
||||
ansible.builtin.command:
|
||||
cmd: "cscli postoverflows install {{ item }}"
|
||||
loop: "{{ crowdsec.postoverflows }}"
|
||||
- name: Restarting SystemD service
|
||||
become: true
|
||||
ansible.builtin.systemd_service:
|
||||
name: crowdsec
|
||||
scope: system
|
||||
state: restarted
|
||||
@@ -5,6 +5,7 @@
|
||||
cmd: "echo ~{{ ansible_user }}"
|
||||
register: ansible_user_home
|
||||
- name: Linking binaries to directories already in PATH environment variable
|
||||
ignore_errors: true
|
||||
ansible.builtin.file:
|
||||
src: "{{ ansible_user_home.stdout }}/downloads/archives/released/difftastic/{{ item }}"
|
||||
dest: "{{ ansible_user_home.stdout }}/.local/bin/{{ item }}"
|
||||
@@ -13,6 +14,7 @@
|
||||
- difft
|
||||
- name: Linking binaries to directories already in PATH environment variable
|
||||
become: true
|
||||
ignore_errors: true
|
||||
ansible.builtin.file:
|
||||
src: "{{ ansible_user_home.stdout }}/downloads/archives/released/difftastic/{{ item }}"
|
||||
dest: "/usr/bin/{{ item }}"
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
ansible.builtin.shell:
|
||||
cmd: "dsnet add {{ item.name }}{{ idx }} --owner {{ current_user.stdout }} --description 'For {{ item.name }}--{{ item.desc }}' --confirm > {{ ansible_user_home.stdout }}/.wg/authorized_clients.d/{{ item.name }}{{ (idx | string) }}.conf"
|
||||
creates: "{{ ansible_user_home.stdout }}/.wg/authorized_clients.d/{{ item.name }}{{ idx }}.conf"
|
||||
loop: "{{ vpn_server.clients }}"
|
||||
loop: "{{ vpn.clients }}"
|
||||
loop_control:
|
||||
index_var: idx
|
||||
- name: Changing ownership of consequent DSNet VPN service client configurations
|
||||
@@ -37,8 +37,9 @@
|
||||
path: "{{ ansible_user_home.stdout }}/.wg/authorized_clients.d/{{ item.name }}{{ (idx | string) }}.conf"
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
mode: "600"
|
||||
state: file
|
||||
loop: "{{ vpn_server.clients }}"
|
||||
loop: "{{ vpn.clients }}"
|
||||
loop_control:
|
||||
index_var: idx
|
||||
- name: Pausing to inquire about how to proceed
|
||||
@@ -52,30 +53,47 @@
|
||||
- name: Acquiring contents of DSNet VPN service client configuration files
|
||||
ansible.builtin.slurp:
|
||||
src: "{{ ansible_user_home.stdout }}/.wg/authorized_clients.d/{{ item.name }}{{ (idx | string) }}.conf"
|
||||
loop: "{{ vpn_server.clients }}"
|
||||
loop: "{{ vpn.clients }}"
|
||||
loop_control:
|
||||
index_var: idx
|
||||
register: vpn_client_configs
|
||||
- name: Presenting contents of DSNet VPN service client configurations to control node
|
||||
ansible.builtin.debug:
|
||||
msg: "Copy this client configuration of the DSNet VPN service:\n {{ item.content }}"
|
||||
msg: "Copy this client configuration of the DSNet VPN service:\n {{ item.content | b64decode }}"
|
||||
loop: "{{ vpn_client_configs.results }}"
|
||||
- name: Giving opportunity to manually copy contents of DSNet VPN service client configuration files
|
||||
ansible.builtin.pause:
|
||||
- name: Providing DSNet VPN service client configuration files to control node machine
|
||||
when: data_method.user_input == "fetch"
|
||||
block:
|
||||
- name: Informing user of inventory requirements for VPN clients
|
||||
when: not item.name in groups.homeserver
|
||||
ansible.builtin.fail:
|
||||
msg: The VPN client must be the name of an inventory host in a homeserver group
|
||||
loop: "{{ vpn.clients }}"
|
||||
- name: Dupliciating DSNet VPN service client configuration files to control node
|
||||
when: item.name in groups.homeserver
|
||||
ansible.builtin.fetch:
|
||||
src: "{{ ansible_user_home.stdout }}/.wg/authorized_clients.d/{{ item.name }}{{ (idx | string) }}.conf"
|
||||
dest: "./.tmp/{{ inventory_hostname }}-dsnet/"
|
||||
flat: true
|
||||
loop: "{{ vpn.clients }}"
|
||||
loop_control:
|
||||
index_var: idx
|
||||
- name: Dupliciating DSNet VPN service client configuration files to control node
|
||||
ansible.builtin.fetch:
|
||||
src: "{{ ansible_user_home.stdout }}/.wg/authorized_clients.d/{{ item.name }}{{ (idx | string) }}.conf"
|
||||
dest: "./.tmp/{{ inventory_hostname }}-dsnet/wg/"
|
||||
dest: "./roles/init-server/files/user/wg/containerized/{{ item.name }}{{ (idx | string) }}.conf"
|
||||
flat: true
|
||||
loop: "{{ vpn_server.clients }}"
|
||||
loop: "{{ vpn.clients }}"
|
||||
loop_control:
|
||||
index_var: idx
|
||||
- name: Informing control node of acquired files
|
||||
ansible.builtin.debug:
|
||||
msg: "The DSNet VPS service client configuration files have been duplicated to '/var/tmp/{{ inventory_hostname }}/wg/' at the control node."
|
||||
msg: "The DSNet VPS service client configuration files have been duplicated to \"{{ item }}\" at the control node."
|
||||
loop:
|
||||
- "./.tmp/{{ inventory_hostname }}-dsnet/"
|
||||
- "./roles/init-server/files/user/wg/"
|
||||
- name: Giving control node user time to read the aforementiioned message
|
||||
ansible.builtin.pause:
|
||||
seconds: 30
|
||||
@@ -106,12 +124,12 @@
|
||||
daemon_reload: true
|
||||
- name: Copying script for DSNet iptables rules
|
||||
become: true
|
||||
ansible.builtin.copy:
|
||||
src: usr/local/bin/dsnet-forward.sh
|
||||
dest: /usr/local/bin/
|
||||
ansible.builtin.template:
|
||||
src: usr/local/bin/dsnet-forward.sh.j2
|
||||
dest: /usr/local/bin/dsnet-forward.sh
|
||||
owner: root
|
||||
group: root
|
||||
mode: "744"
|
||||
mode: "755"
|
||||
force: true
|
||||
backup: true
|
||||
- name: Creating SystemD unit for DSNet iptables rules
|
||||
@@ -123,25 +141,19 @@
|
||||
group: root
|
||||
force: true
|
||||
backup: true
|
||||
- name: Reloading SystemD and enabling iptables rules SystemD unit
|
||||
- name: Reloading SystemD
|
||||
become: true
|
||||
ansible.builtin.systemd_service:
|
||||
name: thrunet
|
||||
enabled: true
|
||||
daemon_reload: true
|
||||
- name: Forwarding network traffic on certain ports to Wireguard VPS service interface
|
||||
- name: Opening port 51820
|
||||
become: true
|
||||
ansible.builtin.iptables:
|
||||
chain: FORWARD
|
||||
protocol: "{{ item[0][0] }}"
|
||||
source_port: "{{ item[0][1] }}"
|
||||
in_interface: "{{ item[1] }}"
|
||||
chain: INPUT
|
||||
protocol: "{{ item }}"
|
||||
destination_port: 51820
|
||||
jump: ACCEPT
|
||||
loop: "{{ vpn_server.forwards | product([vpn_server.interface]) }}"
|
||||
- name: Forwarding network traffic on certain ports to Wireguard VPS service interface
|
||||
become: true
|
||||
ansible.builtin.iptables:
|
||||
table: nat
|
||||
chain: POSTROUTING
|
||||
out_interface: "{{ vpn_server.interface }}"
|
||||
jump: MASQUERADE
|
||||
comment: Open up port 51820
|
||||
loop:
|
||||
- udp
|
||||
- tcp
|
||||
|
||||
@@ -8,6 +8,23 @@
|
||||
when: ansible_facts["system"] == "Linux"
|
||||
ansible.builtin.shell:
|
||||
cmd: "echo {{ ansible_user }}"
|
||||
register: current_user
|
||||
- name: Informing user of requirement of two main domains
|
||||
when: (certbot.domains | length) < 2 or (certbot.domains | length) > 2
|
||||
ansible.builtin.fail:
|
||||
msg: Only two domains allowed and required
|
||||
- name: Informing user of requirement at least one wildcard
|
||||
when: (certbot.domains | select("regex", "^\\*\\.") | list | length) == 0
|
||||
ansible.builtin.fail:
|
||||
msg: At least one of the FQDNs must have a wildcard
|
||||
# - name: Setting the FQDN for development
|
||||
# when: compose.mode == "dev"
|
||||
# ansible.builtin.set_fact:
|
||||
# web_fqdn: "{{ (certbot.domains | map('regex_replace', '\\.([^\\.]*)$', '.test') | reject('regex', '^\\*\\.') | list)[0] }}"
|
||||
- name: Setting the FQDN
|
||||
# when: compose.mode == "prod"
|
||||
ansible.builtin.set_fact:
|
||||
web_fqdn: "{{ (certbot.domains | reject('regex', '^\\*\\.') | list)[0] }}"
|
||||
- name: Configuring Headscale
|
||||
become: true
|
||||
ansible.builtin.template:
|
||||
@@ -18,6 +35,7 @@
|
||||
mode: "644"
|
||||
force: true
|
||||
backup: true
|
||||
# validate: "headscale configtest"
|
||||
- name: Starting SystemD service
|
||||
become: true
|
||||
ansible.builtin.systemd_service:
|
||||
@@ -28,12 +46,55 @@
|
||||
- name: Registering a headscale user
|
||||
become: true
|
||||
ansible.builtin.command:
|
||||
# cmd: "headscale users create {{ item.username }} -d '{{ item.dname }}' -e '{{ item.email }}' -p '{{ pfp | default(default_pfp) }}'"
|
||||
cmd: "headscale users create {{ item.username }} -d '{{ item.dname }}' -e '{{ item.email }}'"
|
||||
# vars:
|
||||
# default_pfp: ~
|
||||
loop: "{{ tail.users }}"
|
||||
cmd: "headscale users create {{ headscale.users.admin.username }} -d '{{ headscale.users.admin.dname }}' -e '{{ headscale.users.admin.email }}'"
|
||||
register: headscale_registration
|
||||
changed_when:
|
||||
- "'User created' in headscale_registration.stdout"
|
||||
- headscale_registration.rc == 0
|
||||
- name: Creating an authentication key for this registered headscale user
|
||||
become: true
|
||||
ansible.builtin.command:
|
||||
cmd: "headscale preauthkeys create -e 24h -u 1"
|
||||
register: tailscale_admin_authkey
|
||||
- name: Pausing to inquire about how to proceed
|
||||
ansible.builtin.pause:
|
||||
prompt: "Type \"fetch\" to get the DSNet VPN service client configuration files, or \"show\" to see their contents for manual copying instead"
|
||||
echo: true
|
||||
register: data_method
|
||||
- name: Choosing Headscale authentication key to control node for copying
|
||||
when: data_method.user_input == "show"
|
||||
block:
|
||||
- name: Presenting Headscale authentication key to Control Node
|
||||
ansible.builtin.debug:
|
||||
msg: "Copy this client configuration of the headscale service:\n {{ tailscale_admin_authkey.stdout }}"
|
||||
- name: Giving opportunity to manually copy Headscale authentication key
|
||||
ansible.builtin.pause:
|
||||
- name: Choosing Headscale service client configuration files to control node machine
|
||||
when: data_method.user_input == "fetch"
|
||||
block:
|
||||
- name: Creating temporary file on managed node that stores Headscale authentication key
|
||||
ansible.builtin.copy:
|
||||
content: "{{ tailscale_admin_authkey.stdout }}"
|
||||
dest: "/tmp/headscale.key"
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
mode: "644"
|
||||
register: tailscale_admin_authkey_file
|
||||
- name: Placing Headscale authentication key into file on control node
|
||||
ansible.builtin.fetch:
|
||||
src: "{{ tailscale_admin_authkey_file.dest }}"
|
||||
dest: "./.tmp/{{ inventory_hostname }}-{{ headscale.users.admin.username }}@headscale/headscale.key"
|
||||
flat: true
|
||||
- name: Placing Headscale authentication key into file on control node
|
||||
ansible.builtin.fetch:
|
||||
src: "{{ tailscale_admin_authkey_file.dest }}"
|
||||
dest: "./roles/init-server/files/{{ item.name }}-{{ headscale.users.admin.username }}@headscale/headscale{{ (idx | string) }}.key"
|
||||
flat: true
|
||||
loop: "{{ headscale.clients }}"
|
||||
loop_control:
|
||||
index_var: idx
|
||||
- name: Informing control node of acquired files
|
||||
ansible.builtin.debug:
|
||||
msg: "The Headscale authentication key files have been duplicated to './.tmp/{{ inventory_hostname }}-{{ headscale.users.admin.username }}@headscale/headscale.key' at the control node."
|
||||
- name: Giving control node user time to read the aforementiioned message
|
||||
ansible.builtin.pause:
|
||||
seconds: 30
|
||||
@@ -15,13 +15,14 @@
|
||||
ansible.builtin.shell:
|
||||
cmd: "{{ ansible_user_home.stdout }}/.local/bin/julia-install.sh --yes"
|
||||
creates: "{{ ansible_user_home.stdout }}/.juliaup/bin"
|
||||
async: 900
|
||||
poll: 5
|
||||
- name: Linking binaries to directories already in PATH environment variable
|
||||
become: true
|
||||
ignore_errors: true
|
||||
ansible.builtin.file:
|
||||
src: "{{ ansible_user_home.stdout }}/.juliaup/bin/{{ item }}"
|
||||
dest: "/usr/bin/{{ item }}"
|
||||
owner: root
|
||||
group: root
|
||||
state: link
|
||||
loop:
|
||||
- julia
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
---
|
||||
- name: Acquiring home of current user
|
||||
when: ansible_facts["system"] == "Linux"
|
||||
ansible.builtin.shell:
|
||||
cmd: "echo ~{{ ansible_user }}"
|
||||
register: ansible_user_home
|
||||
- name: Acquiring home of current user
|
||||
when: ansible_facts["system"] == "Linux"
|
||||
ansible.builtin.shell:
|
||||
cmd: "echo {{ ansible_user }}"
|
||||
register: current_user
|
||||
- name: Setting up TOTP using Google Authenticator
|
||||
become: true
|
||||
become_user: "{{ current_user.stdout }}"
|
||||
ansible.builtin.command:
|
||||
argv:
|
||||
- "google-authenticator"
|
||||
- "-t"
|
||||
- "-d"
|
||||
- "-f"
|
||||
- "-C"
|
||||
- "-q"
|
||||
- "-l {{ ansible_user }}@{{ inventory_hostname }}"
|
||||
- "-i {{ inventory_hostname }}"
|
||||
- "--qr-mode=NONE"
|
||||
- "-r 7"
|
||||
- "-R 300"
|
||||
- "-w 9"
|
||||
creates: "{{ ansible_user_home.stdout }}/.google_authenticator"
|
||||
- name: Pausing to inquire about how to proceed
|
||||
ansible.builtin.pause:
|
||||
prompt: "Type \"fetch\" to get the TOTP secret and backup codes, or \"show\" to see it for manual copying instead"
|
||||
echo: true
|
||||
register: data_method
|
||||
- name: Choosing to present TOTP secret and backup codes to Control Node
|
||||
when: data_method.user_input == "show"
|
||||
block:
|
||||
- name: Acquiring contents of file containing TOTP secret and backup codes
|
||||
ansible.builtin.slurp:
|
||||
src: "{{ ansible_user_home.stdout }}/.google_authenticator"
|
||||
register: totp_token
|
||||
- name: Presenting TOTP secret and backup codes to Control Node
|
||||
ansible.builtin.debug:
|
||||
msg: "Make sure to store the following TOTP secret and backup codes for Google Authenticator:\n {{ totp_token.content | b64decode }}"
|
||||
- name: Giving opportunity to manually copy TOTP secret and backup codes
|
||||
ansible.builtin.pause:
|
||||
- name: Choosing to provide file on control node containing TOTP secret and backup codes
|
||||
when: data_method.user_input == "fetch"
|
||||
block:
|
||||
- name: Placing TOTP secret and backup codes into file on control node
|
||||
ansible.builtin.fetch:
|
||||
src: "{{ ansible_user_home.stdout }}/.google_authenticator"
|
||||
dest: "./.tmp/{{ inventory_hostname }}-google-auth/google_auth.secret"
|
||||
flat: true
|
||||
- name: Informing control node of acquired files
|
||||
ansible.builtin.debug:
|
||||
msg: "The TOTP secret and backup codes file has been duplicated to './.tmp/{{ inventory_hostname }}-google-auth/google-auth.secret' at the control node."
|
||||
- name: Giving control node user time to read the aforementiioned message
|
||||
ansible.builtin.pause:
|
||||
seconds: 30
|
||||
- name: Adding Google Authenticator OTP module PAM authentication line for SSH
|
||||
become: true
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/pam.d/sshd
|
||||
line: "auth sufficient pam_google_authenticator.so nullok"
|
||||
insertafter: "include common-auth$"
|
||||
owner: root
|
||||
group: root
|
||||
mode: "644"
|
||||
- name: Prioritizing authentication methods in SSH
|
||||
become: true
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/ssh/sshd_config.d/auth.conf
|
||||
line: "KbdInteractiveAuthentication yes # enable if implementing TOTP 2FA"
|
||||
regexp: "^KbdInteractiveAuthentication"
|
||||
owner: root
|
||||
group: root
|
||||
mode: "644"
|
||||
- name: Prioritizing authentication methods in SSH
|
||||
become: true
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/ssh/sshd_config.d/auth.conf
|
||||
line: "AuthenticationMethods publickey keyboard-interactive:pam"
|
||||
insertafter: "^KbdInteractiveAuthentication"
|
||||
owner: root
|
||||
group: root
|
||||
mode: "644"
|
||||
# - name: Adding Google Authenticator OTP module PAM authentication line for SSH
|
||||
# become: true
|
||||
# ansible.builtin.lineinfile:
|
||||
# path: /etc/pam.d/sudo
|
||||
# line: "auth required pam_google_authenticator.so nullok"
|
||||
# insertafter: "include common-auth$"
|
||||
# owner: root
|
||||
# group: root
|
||||
# mode: "644"
|
||||
# - name: Adding Google Authenticator OTP module PAM authentication line for SSH
|
||||
# become: true
|
||||
# ansible.builtin.lineinfile:
|
||||
# path: /etc/pam.d/su
|
||||
# line: "auth required pam_google_authenticator.so nullok"
|
||||
# insertafter: "include common-auth$"
|
||||
# owner: root
|
||||
# group: root
|
||||
# mode: "644"
|
||||
- name: Restarting SystemD SSH service
|
||||
become: true
|
||||
ansible.builtin.systemd_service:
|
||||
name: sshd
|
||||
state: restarted
|
||||
@@ -18,43 +18,38 @@
|
||||
ansible.builtin.set_fact:
|
||||
prebuilt_nodepaths: "{{ prebuilt_nodes.files | map(attribute='path') }}"
|
||||
- name: Linking binaries to directories already in PATH environment variable
|
||||
ignore_errors: true
|
||||
ansible.builtin.file:
|
||||
src: "{{ item[0] }}/bin/{{ item[1] }}"
|
||||
dest: "/usr/bin/{{ item[1] }}"
|
||||
owner: root
|
||||
group: root
|
||||
state: link
|
||||
loop: "{{ prebuilt_nodepaths | product(['node']) }}"
|
||||
- name: Linking binaries to directories already in PATH environment variable
|
||||
ignore_errors: true
|
||||
ansible.builtin.file:
|
||||
src: "{{ item[0] }}/lib/node_modules/corepack/dist/{{ item[1] }}.js"
|
||||
dest: "/usr/bin/{{ item[1] }}"
|
||||
owner: root
|
||||
group: root
|
||||
state: link
|
||||
loop: "{{ prebuilt_nodepaths | product(['corepack']) }}"
|
||||
- name: Linking binaries to directories already in PATH environment variable
|
||||
ignore_errors: true
|
||||
ansible.builtin.file:
|
||||
src: "{{ item[0] }}/lib/node_modules/npm/bin/{{ item[1] }}-cli.js"
|
||||
dest: "/usr/bin/{{ item[1] }}"
|
||||
owner: root
|
||||
group: root
|
||||
state: link
|
||||
loop: "{{ prebuilt_nodepaths | product(['npm','npx']) }}"
|
||||
- name: Link includes to directories already recognized by system
|
||||
ignore_errors: true
|
||||
ansible.builtin.file:
|
||||
src: "{{ item[0] }}/include/{{ item[1] }}"
|
||||
dest: "/usr/include/{{ item[1] }}"
|
||||
owner: root
|
||||
group: root
|
||||
state: link
|
||||
loop: "{{ prebuilt_nodepaths | product(['node']) }}"
|
||||
- name: Link requisite libraries to directories already recognized by system
|
||||
ignore_errors: true
|
||||
ansible.builtin.file:
|
||||
src: "{{ item[0] }}/lib/{{ item[1] }}"
|
||||
dest: "/usr/lib/{{ item[1] }}"
|
||||
owner: root
|
||||
group: root
|
||||
state: link
|
||||
loop: "{{ prebuilt_nodepaths | product(['node_modules']) }}"
|
||||
- name: Create man1 subdirectory for man pages
|
||||
@@ -66,11 +61,10 @@
|
||||
mode: "644"
|
||||
state: directory
|
||||
- name: Link shared resources to directories already recognized by system
|
||||
ignore_errors: true
|
||||
ansible.builtin.file:
|
||||
src: "{{ item[0] }}/share/man/man1/{{ item[1] }}.1"
|
||||
dest: "/usr/share/man/man1/{{ item[1] }}.1"
|
||||
owner: root
|
||||
group: root
|
||||
state: link
|
||||
loop: "{{ prebuilt_nodepaths | product(['node']) }}"
|
||||
- name: Create man1 subdirectory for man pages
|
||||
@@ -82,11 +76,10 @@
|
||||
mode: "644"
|
||||
state: directory
|
||||
- name: Link shared resources to directories already recognized by system
|
||||
ignore_errors: true
|
||||
ansible.builtin.file:
|
||||
src: "{{ item[0] }}/share/doc/{{ item[1] }}"
|
||||
dest: "/usr/share/doc/{{ item[1] }}"
|
||||
owner: root
|
||||
group: root
|
||||
state: link
|
||||
loop: "{{ prebuilt_nodepaths | product(['node']) }}"
|
||||
# - name: Reboot machine for shell environment change
|
||||
|
||||
65
roles/init-server/tasks/contingent/pkg/podman.yml
Normal file
65
roles/init-server/tasks/contingent/pkg/podman.yml
Normal file
@@ -0,0 +1,65 @@
|
||||
---
|
||||
- name: Acquiring home of current user
|
||||
when: ansible_facts["system"] == "Linux"
|
||||
ansible.builtin.shell:
|
||||
cmd: "echo ~{{ ansible_user }}"
|
||||
register: ansible_user_home
|
||||
- name: Acquiring current user
|
||||
when: ansible_facts["system"] == "Linux"
|
||||
ansible.builtin.shell:
|
||||
cmd: "echo {{ ansible_user }}"
|
||||
register: current_user
|
||||
- name: Ensuring user namespace support is enabled
|
||||
become: true
|
||||
ansible.posix.sysctl:
|
||||
name: kernel.unprivileged_userns_clone
|
||||
value: "1"
|
||||
sysctl_set: true
|
||||
state: present
|
||||
- name: Ensuring user namespace support is enabled
|
||||
become: true
|
||||
ansible.posix.sysctl:
|
||||
name: net.ipv4.ip_unprivileged_port_start
|
||||
value: "0"
|
||||
sysctl_set: true
|
||||
state: present
|
||||
- name: Creating container directory
|
||||
ansible.builtin.file:
|
||||
path: "{{ ansible_user_home.stdout }}/.config/containers"
|
||||
recurse: true
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
mode: "755"
|
||||
state: directory
|
||||
- name: Configuring container storage
|
||||
become: true
|
||||
become_user: "{{ current_user.stdout }}"
|
||||
ansible.builtin.template:
|
||||
src: user/config/containers/storage.conf.j2
|
||||
dest: "{{ ansible_user_home.stdout }}/.config/containers/storage.conf"
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
mode: "644"
|
||||
force: true
|
||||
backup: true
|
||||
- name: Configuring container image registries
|
||||
become: true
|
||||
become_user: "{{ current_user.stdout }}"
|
||||
ansible.builtin.copy:
|
||||
src: user/config/containers/registries.conf
|
||||
dest: "{{ ansible_user_home.stdout }}/.config/containers/"
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
mode: "644"
|
||||
force: true
|
||||
backup: true
|
||||
# @NOTE https://oneuptime.com/blog/post/2026-01-27-podman-rootless/view#configuring-registries
|
||||
# @NOTE https://github.com/podman-container-tools/podman/blob/main/docs/tutorials/rootless_tutorial.md#using-volumes
|
||||
# @NOTE https://github.com/containers/podman-compose/issues/166#issuecomment-1550515230
|
||||
- name: Enabling and starting SystemD unit service for automatic restart of containers/pods
|
||||
become: true
|
||||
ansible.builtin.systemd_service:
|
||||
name: podman-restart
|
||||
scope: system
|
||||
enabled: true
|
||||
state: started
|
||||
@@ -4,23 +4,180 @@
|
||||
ansible.builtin.shell:
|
||||
cmd: "echo ~{{ ansible_user }}"
|
||||
register: ansible_user_home
|
||||
- name: Acquiring home of current user
|
||||
when: ansible_facts["system"] == "Linux"
|
||||
ansible.builtin.shell:
|
||||
cmd: "echo {{ ansible_user }}"
|
||||
register: current_user
|
||||
- name: Informing user of requirement of two main domains
|
||||
when: (certbot.domains | length) < 2 or (certbot.domains | length) > 2
|
||||
ansible.builtin.fail:
|
||||
msg: Only two domains allowed and required
|
||||
- name: Informing user of requirement at least one wildcard
|
||||
when: (certbot.domains | select("regex", "^\\*\\.") | list | length) == 0
|
||||
ansible.builtin.fail:
|
||||
msg: At least one of the FQDNs must have a wildcard
|
||||
# - name: Setting the FQDN for development
|
||||
# when: compose.mode == "dev"
|
||||
# ansible.builtin.set_fact:
|
||||
# web_fqdn: "{{ (certbot.domains | map('regex_replace', '\\.([^\\.]*)$', '.test') | reject('regex', '^\\*\\.') | list)[0] }}"
|
||||
- name: Setting the FQDN for production
|
||||
# when: compose.mode == "prod"
|
||||
ansible.builtin.set_fact:
|
||||
web_fqdn: "{{ (certbot.domains | reject('regex', '^\\*\\.') | list)[0] }}"
|
||||
- name: Linking repository to another path
|
||||
ignore_errors: true
|
||||
ansible.builtin.file:
|
||||
src: "{{ ansible_user_home.stdout }}/repos/.foreign/quartz"
|
||||
dest: "{{ ansible_user_home.stdout }}/repos/skato-quartz"
|
||||
state: link
|
||||
- name: Installing NodeJS dependencies of quartz software
|
||||
become: true
|
||||
become_user: "{{ current_user.stdout }}"
|
||||
community.general.npm:
|
||||
path: "{{ ansible_user_home.stdout }}/repos/.foreign/quartz"
|
||||
state: latest
|
||||
- name: Configuring quartz software
|
||||
block:
|
||||
- name: Creating path for Quartz content files (path for Obsidian vaults)
|
||||
ansible.builtin.file:
|
||||
path: "{{ ansible_user_home.stdout }}/journal/notes"
|
||||
recurse: true
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
mode: "755"
|
||||
state: directory
|
||||
- name: Creating some initial text content for Quartz
|
||||
become: true
|
||||
become_user: "{{ current_user.stdout }}"
|
||||
ansible.builtin.template:
|
||||
src: "user/journal/notes/index.md.j2"
|
||||
dest: "{{ ansible_user_home.stdout }}/journal/notes/index.md"
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
mode: "644"
|
||||
backup: true
|
||||
- name: Creating some initial image content for Quartz
|
||||
become: true
|
||||
become_user: "{{ current_user.stdout }}"
|
||||
ansible.builtin.copy:
|
||||
src: user/journal/mythe-sisyphus-klein.png
|
||||
dest: "{{ ansible_user_home.stdout }}/journal/notes/mythe-sisyphus-klein.png"
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
mode: "644"
|
||||
backup: true
|
||||
- name: Initializing quartz website
|
||||
become: true
|
||||
become_user: "{{ current_user.stdout }}"
|
||||
ansible.builtin.command:
|
||||
argv:
|
||||
- npx
|
||||
- "-y"
|
||||
- quartz
|
||||
- create
|
||||
- "-b"
|
||||
- notes.{{ web_fqdn }}"
|
||||
- "-t"
|
||||
- obsidian
|
||||
- "-s"
|
||||
- "{{ ansible_user_home.stdout }}/journal/notes"
|
||||
- "-X"
|
||||
- symlink
|
||||
chdir: "{{ ansible_user_home.stdout }}/repos/.foreign/quartz"
|
||||
cmd: npx quartz create
|
||||
creates: "{{ ansible_user_home.stdout }}/repos/.foreign/quartz/content/index.md"
|
||||
- name: Installing quartz plugins referenced in website template
|
||||
become: true
|
||||
become_user: "{{ current_user.stdout }}"
|
||||
ansible.builtin.command:
|
||||
argv:
|
||||
- npx
|
||||
- "-y"
|
||||
- quartz
|
||||
- plugin
|
||||
- install
|
||||
chdir: "{{ ansible_user_home.stdout }}/repos/.foreign/quartz"
|
||||
cmd: npx quartz plugin install --from-config
|
||||
# - name: Starting quartz site web server
|
||||
# ansible.builtin.command:
|
||||
# chdir: "{{ ansible_user_home.stdout }}/repos/.foreign/quartz"
|
||||
# cmd: npx quartz build --serve
|
||||
# register: stdout
|
||||
# changed_when: stdout
|
||||
- name: Starting quartz site web server
|
||||
become: true
|
||||
become_user: "{{ current_user.stdout }}"
|
||||
ansible.builtin.command:
|
||||
argv:
|
||||
- npx
|
||||
- "-y"
|
||||
- quartz
|
||||
- build
|
||||
- "-o"
|
||||
- "{{ ansible_user_home.stdout }}/srv/notes.{{ web_fqdn }}"
|
||||
- "--concurrency"
|
||||
- "3"
|
||||
chdir: "{{ ansible_user_home.stdout }}/repos/.foreign/quartz"
|
||||
creates: "{{ ansible_user_home.stdout }}/srv/notes.{{ web_fqdn }}/index.html"
|
||||
- name: Creating directory for caddy configuration
|
||||
ansible.builtin.file:
|
||||
path: "{{ ansible_user_home.stdout }}/.config/caddy"
|
||||
recurse: true
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
state: directory
|
||||
- name: Adding Caddyfile subdomain entry
|
||||
when: "(caddy is defined and caddy != None) and caddy.containerized and mode == 'prod'"
|
||||
ansible.builtin.blockinfile:
|
||||
path: "{{ ansible_user_home.stdout }}/.config/caddy/Caddyfile"
|
||||
block: |
|
||||
notes.{{ web_fqdn }} {
|
||||
respond 503
|
||||
# root /srv/notes.{{ web_fqdn }}
|
||||
file_server
|
||||
encode gzip
|
||||
|
||||
handle_errors {
|
||||
root /srv/{{ web_fqdn }}
|
||||
rewrite /error/{err.status_code}.html
|
||||
templates
|
||||
}
|
||||
}
|
||||
prepend_newline: true
|
||||
marker: "# <-- {mark} ANSIBLE MANAGED NOTES DOMAIN -->"
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
mode: "644"
|
||||
create: true
|
||||
state: present
|
||||
- name: Adding Caddyfile subdomain entry
|
||||
when: "(caddy is defined and caddy != None) and caddy.containerized and (mode == 'dev' or caddy.scheme == 'http')"
|
||||
ansible.builtin.blockinfile:
|
||||
path: "{{ ansible_user_home.stdout }}/.config/caddy/Caddyfile"
|
||||
block: |
|
||||
http://notes.{{ web_fqdn }} {
|
||||
respond 503
|
||||
# root /srv/notes.{{ web_fqdn }}
|
||||
file_server
|
||||
encode gzip
|
||||
|
||||
handle_errors {
|
||||
root /srv/{{ web_fqdn }}
|
||||
rewrite /error/{err.status_code}.html
|
||||
templates
|
||||
}
|
||||
}
|
||||
prepend_newline: true
|
||||
marker: "# <-- {mark} ANSIBLE MANAGED NOTES DOMAIN -->"
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
mode: "644"
|
||||
create: true
|
||||
state: present
|
||||
- name: Checking the status of podman containers
|
||||
ansible.builtin.command:
|
||||
argv:
|
||||
- podman
|
||||
- ps
|
||||
register: podman_status
|
||||
- name: Restarting webserver / reverse proxy container
|
||||
become: true
|
||||
become_user: "{{ current_user.stdout }}"
|
||||
when: "'revproxy0' in podman_status.stdout and (caddy is defined and caddy != None) and caddy.containerized"
|
||||
containers.podman.podman_container:
|
||||
name: "{{ compose.containers.webserver.name }}"
|
||||
state: started
|
||||
force_restart: true
|
||||
@@ -15,10 +15,13 @@
|
||||
ansible.builtin.shell:
|
||||
cmd: "{{ ansible_user_home.stdout }}/.local/bin/radicle-install.sh"
|
||||
creates: "{{ ansible_user_home.stdout }}/.radicle"
|
||||
async: 600
|
||||
poll: 5
|
||||
- name: Bootstrapping Radicle
|
||||
become: true
|
||||
block:
|
||||
- name: Linking binaries to directories already in PATH environment variable
|
||||
ignore_errors: true
|
||||
ansible.builtin.file:
|
||||
src: "{{ ansible_user_home.stdout }}/.radicle/bin/{{ item }}"
|
||||
dest: "/usr/bin/{{ item }}"
|
||||
@@ -36,6 +39,7 @@
|
||||
mode: "644"
|
||||
state: directory
|
||||
- name: Link manpages to Linux manpage directories
|
||||
ignore_errors: true
|
||||
ansible.builtin.file:
|
||||
src: "{{ ansible_user_home.stdout }}/.radicle/man/man1/{{ item }}.1"
|
||||
dest: "/usr/share/man/man1/{{ item }}.1"
|
||||
|
||||
@@ -15,8 +15,11 @@
|
||||
ansible.builtin.shell:
|
||||
cmd: "{{ ansible_user_home.stdout }}/.local/bin/rustup-install.sh -yq"
|
||||
creates: "{{ ansible_user_home.stdout }}/.cargo/bin"
|
||||
async: 600
|
||||
poll: 5
|
||||
- name: Linking binaries to directories already in PATH environment variable
|
||||
become: true
|
||||
ignore_errors: true
|
||||
ansible.builtin.file:
|
||||
src: "{{ ansible_user_home.stdout }}/.cargo/bin/{{ item }}"
|
||||
dest: "/usr/bin/{{ item }}"
|
||||
|
||||
171
roles/init-server/tasks/contingent/pkg/skato_blog.yml
Normal file
171
roles/init-server/tasks/contingent/pkg/skato_blog.yml
Normal file
@@ -0,0 +1,171 @@
|
||||
---
|
||||
- name: Acquiring home of current user
|
||||
when: ansible_facts["system"] == "Linux"
|
||||
ansible.builtin.shell:
|
||||
cmd: "echo ~{{ ansible_user }}"
|
||||
register: ansible_user_home
|
||||
- name: Acquiring home of current user
|
||||
when: ansible_facts["system"] == "Linux"
|
||||
ansible.builtin.shell:
|
||||
cmd: "echo {{ ansible_user }}"
|
||||
register: current_user
|
||||
- name: Informing user of requirement of two main domains
|
||||
when: (certbot.domains | length) < 2 or (certbot.domains | length) > 2
|
||||
ansible.builtin.fail:
|
||||
msg: Only two domains allowed and required
|
||||
- name: Informing user of requirement at least one wildcard
|
||||
when: (certbot.domains | select("regex", "^\\*\\.") | list | length) == 0
|
||||
ansible.builtin.fail:
|
||||
msg: At least one of the FQDNs must have a wildcard
|
||||
# - name: Setting the FQDN for development
|
||||
# when: compose.mode == "dev"
|
||||
# ansible.builtin.set_fact:
|
||||
# web_fqdn: "{{ (certbot.domains | map('regex_replace', '\\.([^\\.]*)$', '.test') | reject('regex', '^\\*\\.') | list)[0] }}"
|
||||
- name: Setting the FQDN
|
||||
# when: compose.mode == "prod"
|
||||
ansible.builtin.set_fact:
|
||||
web_fqdn: "{{ (certbot.domains | reject('regex', '^\\*\\.') | list)[0] }}"
|
||||
- name: Moving git repository from initial path
|
||||
block:
|
||||
- name: Recursively copying directory and its contents to elsewhere
|
||||
ansible.builtin.copy:
|
||||
src: "{{ ansible_user_home.stdout }}/repos/.foreign/{{ source_code.repos.blog.name }}"
|
||||
remote_src: true
|
||||
dest: "{{ ansible_user_home.stdout }}/repos/"
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
register: new_blog_path
|
||||
- name: Deleting directory at previous path
|
||||
ansible.builtin.file:
|
||||
path: "{{ ansible_user_home.stdout }}/repos/.foreign/{{ source_code.repos.blog.name }}"
|
||||
state: absent
|
||||
- name: Creating directory for new bare repository
|
||||
ansible.builtin.file:
|
||||
path: "{{ ansible_user_home.stdout }}/src"
|
||||
recurse: true
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
state: directory
|
||||
- name: Creating bare repository
|
||||
ansible.builtin.command:
|
||||
cmd: "git init --bare {{ source_code.repos.blog.name }}.git"
|
||||
chdir: "{{ ansible_user_home.stdout }}/src"
|
||||
creates: "{{ ansible_user_home.stdout }}/src/{{ source_code.repos.blog.name }}.git"
|
||||
- name: Running Hugo blog
|
||||
when: source_code.repos.blog.run
|
||||
block:
|
||||
- name: Creating path for Hugo content files
|
||||
when: caddy.containerized and (compose.containers.webserver is defined or compose.containers.webserver != None)
|
||||
ansible.builtin.file:
|
||||
path: "{{ ansible_user_home.stdout }}/journal/blog"
|
||||
recurse: true
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
mode: "755"
|
||||
state: directory
|
||||
- name: Creating some initial text content for Hugo
|
||||
become: true
|
||||
become_user: "{{ current_user.stdout }}"
|
||||
when: caddy.containerized and (compose.containers.webserver is defined or compose.containers.webserver != None)
|
||||
ansible.builtin.template:
|
||||
src: "user/journal/blog/_index.md.j2"
|
||||
dest: "{{ ansible_user_home.stdout }}/journal/blog/index.md"
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
mode: "644"
|
||||
backup: true
|
||||
- name: Creating some initial image content for Hugo
|
||||
become: true
|
||||
become_user: "{{ current_user.stdout }}"
|
||||
when: caddy.containerized and (compose.containers.webserver is defined or compose.containers.webserver != None)
|
||||
ansible.builtin.copy:
|
||||
src: "user/journal/mythe-sisyphus-klein.png"
|
||||
dest: "{{ ansible_user_home.stdout }}/journal/blog/mythe-sisyphus-klein.png"
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
mode: "644"
|
||||
backup: true
|
||||
- name: Creating subdirectory for blog website root
|
||||
when: caddy.containerized and (compose.containers.webserver is defined or compose.containers.webserver != None)
|
||||
ansible.builtin.file:
|
||||
path: "{{ ansible_user_home.stdout }}/srv/blog.{{ web_fqdn }}"
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
mode: "755"
|
||||
state: directory
|
||||
- name: Build Hugo blog at additional webroot
|
||||
when: caddy.containerized and (compose.containers.webserver is defined or compose.containers.webserver != None)
|
||||
ansible.builtin.command:
|
||||
argv:
|
||||
- hugo
|
||||
- "--quiet"
|
||||
- "-b"
|
||||
- "https://blog.{{ web_fqdn }}/"
|
||||
- "-c"
|
||||
- "{{ ansible_user_home.stdout }}/journal/blog"
|
||||
- "-d"
|
||||
- "{{ ansible_user_home.stdout }}/srv/blog.{{ web_fqdn }}"
|
||||
- "--cleanDestinationDir"
|
||||
chdir: "{{ new_blog_path.dest }}"
|
||||
creates: "{{ ansible_user_home.stdout }}/srv/blog.{{ web_fqdn }}/index.html"
|
||||
# @TODO write error Caddy template HTML file at the blog's web root
|
||||
- name: Adding Caddyfile subdomain entry
|
||||
when: caddy.containerized and mode == 'prod' and (compose.containers.webserver is defined or compose.containers.webserver != None)
|
||||
ansible.builtin.blockinfile:
|
||||
path: "{{ ansible_user_home.stdout }}/.config/caddy/Caddyfile"
|
||||
block: |
|
||||
blog.{{ web_fqdn }} {
|
||||
respond 503
|
||||
# root /srv/blog.{{ web_fqdn }}
|
||||
file_server
|
||||
encode gzip
|
||||
|
||||
handle_errors {
|
||||
root /srv/{{ web_fqdn }}
|
||||
rewrite /error/{err.status_code}.html
|
||||
templates
|
||||
}
|
||||
}
|
||||
prepend_newline: true
|
||||
marker: "# <-- {mark} ANSIBLE MANAGED BLOG DOMAIN -->"
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
mode: "644"
|
||||
state: present
|
||||
- name: Adding Caddyfile subdomain entry
|
||||
when: caddy.containerized and (mode == 'dev' or caddy.scheme == 'http') and (compose.containers.webserver is defined or compose.containers.webserver != None)
|
||||
ansible.builtin.blockinfile:
|
||||
path: "{{ ansible_user_home.stdout }}/.config/caddy/Caddyfile"
|
||||
block: |
|
||||
http://blog.{{ web_fqdn }} {
|
||||
respond 503
|
||||
# root /srv/blog.{{ web_fqdn }}
|
||||
file_server
|
||||
encode gzip
|
||||
|
||||
handle_errors {
|
||||
root /srv/{{ web_fqdn }}
|
||||
rewrite /error/{err.status_code}.html
|
||||
templates
|
||||
}
|
||||
}
|
||||
prepend_newline: true
|
||||
marker: "# <-- {mark} ANSIBLE MANAGED BLOG DOMAIN -->"
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
mode: "644"
|
||||
state: present
|
||||
- name: Checking the status of podman containers
|
||||
ansible.builtin.command:
|
||||
argv:
|
||||
- podman
|
||||
- ps
|
||||
register: podman_status
|
||||
- name: Restarting webserver / reverse proxy container
|
||||
become: true
|
||||
become_user: "{{ current_user.stdout }}"
|
||||
when: "'revproxy0' in podman_status.stdout and (caddy is defined and caddy != None) and caddy.containerized"
|
||||
containers.podman.podman_container:
|
||||
name: "{{ compose.containers.webserver.name }}"
|
||||
state: started
|
||||
force_restart: true
|
||||
45
roles/init-server/tasks/contingent/pkg/skato_blog_theme.yml
Normal file
45
roles/init-server/tasks/contingent/pkg/skato_blog_theme.yml
Normal file
@@ -0,0 +1,45 @@
|
||||
---
|
||||
- name: Acquiring home of current user
|
||||
when: ansible_facts["system"] == "Linux"
|
||||
ansible.builtin.shell:
|
||||
cmd: "echo ~{{ ansible_user }}"
|
||||
register: ansible_user_home
|
||||
- name: Acquiring home of current user
|
||||
when: ansible_facts["system"] == "Linux"
|
||||
ansible.builtin.shell:
|
||||
cmd: "echo {{ ansible_user }}"
|
||||
register: current_user
|
||||
- name: Moving git repository from initial path
|
||||
block:
|
||||
- name: Recursively copying directory and its contents to elsewhere
|
||||
ansible.builtin.copy:
|
||||
src: "{{ ansible_user_home.stdout }}/repos/.foreign/{{ source_code.repos.blog_theme.name }}"
|
||||
remote_src: true
|
||||
dest: "{{ ansible_user_home.stdout }}/repos/"
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
register: new_compose_path
|
||||
- name: Deleting directory at previous path
|
||||
ansible.builtin.file:
|
||||
path: "{{ ansible_user_home.stdout }}/repos/.foreign/{{ source_code.repos.blog_theme.name }}"
|
||||
state: absent
|
||||
- name: Creating directory for new bare repository
|
||||
ansible.builtin.file:
|
||||
path: "{{ ansible_user_home.stdout }}/src"
|
||||
recurse: true
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
state: directory
|
||||
- name: Creating bare repository
|
||||
ansible.builtin.command:
|
||||
cmd: "git init --bare {{ source_code.repos.blog_theme.name }}.git"
|
||||
chdir: "{{ ansible_user_home.stdout }}/src"
|
||||
creates: "{{ ansible_user_home.stdout }}/src/{{ source_code.repos.blog_theme.name }}.git"
|
||||
- name: Running Hugo blog theme
|
||||
when: source_code.repos.blog_theme.run
|
||||
# become: true
|
||||
# become_user: "{{ current_user.stdout }}"
|
||||
block:
|
||||
- name: Warning about lack of implementation
|
||||
ansible.builtin.debug:
|
||||
msg: Not yet implemented
|
||||
45
roles/init-server/tasks/contingent/pkg/skato_cli.yml
Normal file
45
roles/init-server/tasks/contingent/pkg/skato_cli.yml
Normal file
@@ -0,0 +1,45 @@
|
||||
---
|
||||
- name: Acquiring home of current user
|
||||
when: ansible_facts["system"] == "Linux"
|
||||
ansible.builtin.shell:
|
||||
cmd: "echo ~{{ ansible_user }}"
|
||||
register: ansible_user_home
|
||||
- name: Acquiring home of current user
|
||||
when: ansible_facts["system"] == "Linux"
|
||||
ansible.builtin.shell:
|
||||
cmd: "echo {{ ansible_user }}"
|
||||
register: current_user
|
||||
- name: Moving git repository from initial path
|
||||
block:
|
||||
- name: Recursively copying directory and its contents to elsewhere
|
||||
ansible.builtin.copy:
|
||||
src: "{{ ansible_user_home.stdout }}/repos/.foreign/{{ source_code.repos.cli.name }}"
|
||||
remote_src: true
|
||||
dest: "{{ ansible_user_home.stdout }}/repos/"
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
register: new_compose_path
|
||||
- name: Deleting directory at previous path
|
||||
ansible.builtin.file:
|
||||
path: "{{ ansible_user_home.stdout }}/repos/.foreign/{{ source_code.repos.cli.name }}"
|
||||
state: absent
|
||||
- name: Creating directory for new bare repository
|
||||
ansible.builtin.file:
|
||||
path: "{{ ansible_user_home.stdout }}/src"
|
||||
recurse: true
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
state: directory
|
||||
- name: Creating bare repository
|
||||
ansible.builtin.command:
|
||||
cmd: "git init --bare {{ source_code.repos.cli.name }}.git"
|
||||
chdir: "{{ ansible_user_home.stdout }}/src"
|
||||
creates: "{{ ansible_user_home.stdout }}/src/{{ source_code.repos.cli.name }}.git"
|
||||
- name: Running CLI utility
|
||||
when: source_code.repos.cli.run
|
||||
# become: true
|
||||
# become_user: "{{ current_user.stdout }}"
|
||||
block:
|
||||
- name: Warning about lack of implementation
|
||||
ansible.builtin.debug:
|
||||
msg: Not yet implemented
|
||||
836
roles/init-server/tasks/contingent/pkg/skato_compose.yml
Normal file
836
roles/init-server/tasks/contingent/pkg/skato_compose.yml
Normal file
@@ -0,0 +1,836 @@
|
||||
---
|
||||
- name: Acquiring home of current user
|
||||
when: ansible_facts["system"] == "Linux"
|
||||
ansible.builtin.shell:
|
||||
cmd: "echo ~{{ ansible_user }}"
|
||||
register: ansible_user_home
|
||||
- name: Acquiring home of current user
|
||||
when: ansible_facts["system"] == "Linux"
|
||||
ansible.builtin.shell:
|
||||
cmd: "echo {{ ansible_user }}"
|
||||
register: current_user
|
||||
- name: Informing user of requirement of two main domains
|
||||
when: (certbot.domains | length) < 2 or (certbot.domains | length) > 2
|
||||
ansible.builtin.fail:
|
||||
msg: Only two domains allowed and required
|
||||
- name: Informing user of requirement at least one wildcard
|
||||
when: (certbot.domains | select("regex", "^\\*\\.") | list | length) == 0
|
||||
ansible.builtin.fail:
|
||||
msg: At least one of the FQDNs must have a wildcard
|
||||
# - name: Setting the FQDN for development
|
||||
# when: compose.mode == "dev"
|
||||
# ansible.builtin.set_fact:
|
||||
# web_fqdn: "{{ (certbot.domains | map('regex_replace', '\\.([^\\.]*)$', '.test') | reject('regex', '^\\*\\.') | list)[0] }}"
|
||||
- name: Setting the FQDN for production
|
||||
# when: compose.mode == "prod"
|
||||
ansible.builtin.set_fact:
|
||||
web_fqdn: "{{ (certbot.domains | reject('regex', '^\\*\\.') | list)[0] }}"
|
||||
- name: Moving git repository from initial path
|
||||
block:
|
||||
- name: Recursively copying directory and its contents to elsewhere
|
||||
become: true
|
||||
become_user: "{{ current_user.stdout }}"
|
||||
ansible.builtin.copy:
|
||||
src: "{{ ansible_user_home.stdout }}/repos/.foreign/{{ source_code.repos.compose.name }}"
|
||||
remote_src: true
|
||||
dest: "{{ ansible_user_home.stdout }}/repos/"
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
register: new_compose_path
|
||||
- name: Deleting directory at previous path
|
||||
ansible.builtin.file:
|
||||
path: "{{ ansible_user_home.stdout }}/repos/.foreign/{{ source_code.repos.compose.name }}"
|
||||
state: absent
|
||||
- name: Creating directory for new bare repository
|
||||
ansible.builtin.file:
|
||||
path: "{{ ansible_user_home.stdout }}/src"
|
||||
recurse: true
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
state: directory
|
||||
- name: Creating bare repository
|
||||
ansible.builtin.command:
|
||||
cmd: "git init --bare {{ source_code.repos.compose.name }}.git"
|
||||
chdir: "{{ ansible_user_home.stdout }}/src"
|
||||
creates: "{{ ansible_user_home.stdout }}/src/{{ source_code.repos.compose.name }}.git"
|
||||
- name: Creating required SMTP-related container secret
|
||||
become: true
|
||||
# become_user: "{{ current_user.stdout }}"
|
||||
ansible.builtin.lineinfile:
|
||||
line: "{{ email.smtp.password }}"
|
||||
path: "{{ ansible_user_home.stdout }}/.podsecrets/email.pass"
|
||||
insertafter: EOF
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
mode: "644"
|
||||
create: true
|
||||
backup: true
|
||||
- name: Creating environment file
|
||||
become: true
|
||||
become_user: "{{ current_user.stdout }}"
|
||||
ansible.builtin.template:
|
||||
src: user/all.env.j2
|
||||
dest: "{{ ansible_user_home.stdout }}/.all.env"
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
mode: "644"
|
||||
force: true
|
||||
backup: true
|
||||
register: environ
|
||||
- name: Creating environment file for email
|
||||
become: true
|
||||
become_user: "{{ current_user.stdout }}"
|
||||
ansible.builtin.template:
|
||||
src: user/email.env.j2
|
||||
dest: "{{ ansible_user_home.stdout }}/.email.env"
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
mode: "644"
|
||||
force: true
|
||||
backup: true
|
||||
register: email_environ
|
||||
- name: Creating a directory for container secrets
|
||||
ansible.builtin.file:
|
||||
path: "{{ ansible_user_home.stdout }}/.podsecrets"
|
||||
recurse: true
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
mode: "644"
|
||||
state: directory
|
||||
- name: Creating directory for DBMS server configuration
|
||||
ansible.builtin.file:
|
||||
path: "{{ ansible_user_home.stdout }}/.config/{{ item }}"
|
||||
recurse: true
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
mode: "755"
|
||||
state: directory
|
||||
loop:
|
||||
- caddy
|
||||
- letsencrypt
|
||||
- mysql
|
||||
- redis
|
||||
- gitea
|
||||
- opengist
|
||||
- tailscale
|
||||
- glance
|
||||
- name: Creating directory for main website root
|
||||
ansible.builtin.file:
|
||||
path: "{{ ansible_user_home.stdout }}/srv/{{ web_fqdn }}"
|
||||
recurse: true
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
mode: "755"
|
||||
state: directory
|
||||
- name: Creating directory for caddy configuration
|
||||
ansible.builtin.file:
|
||||
path: "{{ ansible_user_home.stdout }}/.config/caddy"
|
||||
recurse: true
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
state: directory
|
||||
# - name: Pulling all needed container images for Compose services
|
||||
# become: true
|
||||
# become_user: "{{ current_user.stdout }}"
|
||||
# ansible.builtin.command:
|
||||
# cmd: podman-compose pull
|
||||
# chdir: "{{ new_compose_path.dest }}{{ source_code.repos.compose.rpath | default('/independent') }}"
|
||||
- name: Calculating desired container states
|
||||
block:
|
||||
- name: Calculating desired container state for VPN client
|
||||
ansible.builtin.set_fact:
|
||||
# @TODO write case of at least one vpn client having a boolean attribute declaring whether it is a container
|
||||
vpn_run: "{{ source_code.repos.compose.run and (vpn.clients | selectattr('name', 'in', web_fqdn) | length) == 1 and (compose.containers.vpn is defined and compose.containers.vpn != None) }}"
|
||||
- name: Calculating desired container state for web server or reverse proxy server
|
||||
ansible.builtin.set_fact:
|
||||
server_run: "{{ source_code.repos.compose.run and caddy.containerized and (compose.containers.webserver is defined and compose.containers.webserver != None) }}"
|
||||
- name: Calculatng desired container state for ACME challenge
|
||||
ansible.builtin.set_fact:
|
||||
ssl_run: "{{ server_run and certbot.containerized and (compose.containers.ssl is defined and compose.containers.ssl != None) }}"
|
||||
- name: Calculating desired container state for database management
|
||||
ansible.builtin.set_fact:
|
||||
dbms_run: "{{ source_code.repos.compose.run and mysql.containerized and (compose.containers.db is defined and compose.containers.db != None) }}"
|
||||
- name: Calculating desired container state for caching server
|
||||
ansible.builtin.set_fact:
|
||||
cache_run: "{{ source_code.repos.compose.run and redis.containerized and (compose.containers.cache is defined and compose.containers.cache != None) }}"
|
||||
- name: Calculating desired container state for cloud server
|
||||
ansible.builtin.set_fact:
|
||||
cloud_run: "{{ source_code.repos.compose.run and nextcloud.containerized and (compose.containers.cloud is defined and compose.containers.cloud != None) }}"
|
||||
- name: Calculating desired container state for forge server
|
||||
ansible.builtin.set_fact:
|
||||
forge_run: "{{ source_code.repos.compose.run and gitea.containerized and (compose.containers.forge is defined and compose.containers.forge != None ) }}"
|
||||
- name: Calculating desired container state for pastebin server
|
||||
ansible.builtin.set_fact:
|
||||
pbin_run: "{{ source_code.repos.compose.run and gist.containerized and (compose.containers.pastebin is defined and compose.containers.pastebin != None) }}"
|
||||
- name: Calculating desired container state for tailnet client
|
||||
ansible.builtin.set_fact:
|
||||
tail_run: "{{ source_code.repos.compose.run and tailscale.containerized and (compose.containers.tail is defined and compose.containers.tail != None) }}"
|
||||
- name: Calculating desired container state for tailnet dashboard
|
||||
ansible.builtin.set_fact:
|
||||
dash_run: "{{ source_code.repos.compose.run and glance.containerized and (compose.containers.dash is defined and compose.containers.dash != None) }}"
|
||||
- name: Running VPN client Compose files
|
||||
when: vpn_run
|
||||
block:
|
||||
- name: Creating subdirectory for VPN client container specified by Compose file
|
||||
ansible.builtin.file:
|
||||
path: "{{ ansible_user_home.stdout }}/.wg/containerized"
|
||||
recurse: true
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
state: directory
|
||||
- name: Copying VPN client configuration files
|
||||
become: true
|
||||
become_user: "{{ current_user.stdout }}"
|
||||
when: item.name == inventory_hostname
|
||||
ansible.builtin.copy:
|
||||
src: "user/wg/containerized/{{ item.name }}{{ (idx | string) }}.conf"
|
||||
dest: "{{ ansible_user_home.stdout }}/.wg/containerized/"
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
mode: "644"
|
||||
force: true
|
||||
backup: true
|
||||
loop: "{{ vpn.clients }}"
|
||||
loop_control:
|
||||
index_var: idx
|
||||
- name: Creating and deploying VPN client container specified by Compose file
|
||||
become: true
|
||||
become_user: "{{ current_user.stdout }}"
|
||||
when: source_code.repos.compose.run and (vpn.clients | selectattr("name", "in", web_fqdn) | length) == 1 and (compose.containers.vpn is defined and compose.containers.vpn != None)
|
||||
ansible.builtin.command:
|
||||
cmd: "podman-compose up -d {{ compose.containers.vpn.name }}"
|
||||
chdir: "{{ new_compose_path.dest }}{{ source_code.repos.compose.rpath | default('/independent') }}"
|
||||
- name: Opening port 51820
|
||||
become: true
|
||||
ansible.builtin.iptables:
|
||||
chain: INPUT
|
||||
protocol: "{{ item }}"
|
||||
destination_port: 51820
|
||||
jump: ACCEPT
|
||||
comment: Open up port 51820
|
||||
loop:
|
||||
- udp
|
||||
- tcp
|
||||
- name: Spinning up database management container specified by Compose file
|
||||
when: dbms_run
|
||||
block:
|
||||
- name: Creating required container secret for DBMS server container's root account
|
||||
become: true
|
||||
# become_user: "{{ current_user.stdout }}"
|
||||
ansible.builtin.lineinfile:
|
||||
line: "{{ mysql.password }}"
|
||||
path: "{{ ansible_user_home.stdout }}/.podsecrets/root-mysql.pass"
|
||||
insertafter: EOF
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
mode: "644"
|
||||
create: true
|
||||
backup: true
|
||||
- name: Creatng required container secret for DBMS server container's primary non-root account
|
||||
become: true
|
||||
# become_user: "{{ current_user.stdout }}"
|
||||
ansible.builtin.lineinfile:
|
||||
line: "{{ mysql.users.admin.password }}"
|
||||
path: "{{ ansible_user_home.stdout }}/.podsecrets/user-mysql.pass"
|
||||
insertafter: EOF
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
mode: "644"
|
||||
create: true
|
||||
backup: true
|
||||
- name: Creating environment file for DBMS server container specified in Compose file
|
||||
become: true
|
||||
become_user: "{{ current_user.stdout }}"
|
||||
ansible.builtin.template:
|
||||
src: user/mysql.env.j2
|
||||
dest: "{{ ansible_user_home.stdout }}/.mysql.env"
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
mode: "644"
|
||||
force: true
|
||||
backup: true
|
||||
register: mysql_environ
|
||||
- name: Creating and deploying DBMS server container specified by Compose file
|
||||
become: true
|
||||
become_user: "{{ current_user.stdout }}"
|
||||
ansible.builtin.command:
|
||||
cmd: "podman-compose --env-file {{ mysql_environ.dest }} --env-file {{ environ.dest }} up -d {{ compose.containers.db.name }}"
|
||||
chdir: "{{ new_compose_path.dest }}{{ source_code.repos.compose.rpath | default('/independent') }}"
|
||||
# @TODO see if manual creation of additional databases is necessary for the DBMS server container
|
||||
# REDIS
|
||||
- name: Spinning up caching container specified by Compose file
|
||||
when: cache_run
|
||||
block:
|
||||
- name: Creating environment file for DBMS server container specified in Compose file
|
||||
become: true
|
||||
become_user: "{{ current_user.stdout }}"
|
||||
ansible.builtin.template:
|
||||
src: user/redis.env.j2
|
||||
dest: "{{ ansible_user_home.stdout }}/.redis.env"
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
mode: "644"
|
||||
force: true
|
||||
backup: true
|
||||
register: redis_environ
|
||||
- name: Creating and deploying cache server container specified by Compose file
|
||||
become: true
|
||||
become_user: "{{ current_user.stdout }}"
|
||||
ansible.builtin.command:
|
||||
cmd: "podman-compose --env-file {{ environ.dest }} up -d {{ compose.containers.cache.name }}"
|
||||
chdir: "{{ new_compose_path.dest }}{{ source_code.repos.compose.rpath | default('/independent') }}"
|
||||
- name: Spinning up cloud container specified by Compose file
|
||||
when: cloud_run
|
||||
block:
|
||||
- name: Creating database necessary for cloud server container specified by Compose file
|
||||
become: true
|
||||
become_user: "{{ current_user.stdout }}"
|
||||
when: dbms_run
|
||||
containers.podman.podman_container_exec:
|
||||
name: "{{ compose.containers.db.name }}"
|
||||
argv:
|
||||
- mysql
|
||||
- "-u"
|
||||
- "{{ mysql.users.admin.username }}"
|
||||
- "-p{{ mysql.users.admin.password }}"
|
||||
- "-e"
|
||||
- "'CREATE DATABASE IF NOT EXISTS {{ mysql.users.admin.databases.nextcloud.name }};'"
|
||||
detach: true
|
||||
- name: Creating required cache-related container secret for cloud server container specified by Compose file
|
||||
become: true
|
||||
# become_user: "{{ current_user.stdout }}"
|
||||
when: cache_run
|
||||
ansible.builtin.lineinfile:
|
||||
line: "{{ redis.password }}"
|
||||
dest: "{{ ansible_user_home.stdout }}/.podsecrets/redis.pass"
|
||||
insertafter: EOF
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
mode: "644"
|
||||
create: true
|
||||
backup: true
|
||||
- name: Creating environment file for cloud server container specified by Compose file
|
||||
become: true
|
||||
become_user: "{{ current_user.stdout }}"
|
||||
ansible.builtin.template:
|
||||
src: user/nextcloud.env.j2
|
||||
dest: "{{ ansible_user_home.stdout }}/.nextcloud.env"
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
mode: "644"
|
||||
force: true
|
||||
backup: true
|
||||
register: nextcloud_environ
|
||||
- name: Creating and deploying DBMS server container specified by Compose file
|
||||
become: true
|
||||
become_user: "{{ current_user.stdout }}"
|
||||
ansible.builtin.command:
|
||||
cmd: "podman-compose --env-file {{ mysql_environ.dest }} --env-file {{ email_environ.dest }} --env-file {{ nextcloud_environ.dest }} --env-file {{ environ.dest }} up -d {{ compose.containers.cloud.name }}"
|
||||
chdir: "{{ new_compose_path.dest }}{{ source_code.repos.compose.rpath | default('/independent') }}"
|
||||
- name: Adding Caddyfile subdomain entry
|
||||
when: "server_run and mode == 'prod'"
|
||||
ansible.builtin.blockinfile:
|
||||
path: "{{ ansible_user_home.stdout }}/.config/caddy/Caddyfile"
|
||||
block: |
|
||||
{{ nextcloud.subdomain }}.{{ web_fqdn }} {
|
||||
root /srv/{{ nextcloud.subdomain }}.{{ web_fqdn }}
|
||||
file_server
|
||||
php_fastcgi localhost:9000
|
||||
|
||||
handle_errors {
|
||||
root /srv/{{ web_fqdn }}
|
||||
rewrite /error/{err.status_code}.html
|
||||
templates
|
||||
encode gzip
|
||||
}
|
||||
}
|
||||
prepend_newline: true
|
||||
marker: "# <-- {mark} ANSIBLE MANAGED CLOUD DOMAIN -->"
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
create: true
|
||||
mode: "644"
|
||||
state: present
|
||||
- name: Adding Caddyfile subdomain entry
|
||||
when: "server_run and (mode == 'dev' or caddy.scheme == 'http')"
|
||||
ansible.builtin.blockinfile:
|
||||
path: "{{ ansible_user_home.stdout }}/.config/caddy/Caddyfile"
|
||||
block: |
|
||||
http://{{ nextcloud.subdomain }}.{{ web_fqdn }} {
|
||||
root /srv/{{ nextcloud.subdomain }}.{{ web_fqdn }}
|
||||
file_server
|
||||
php_fastcgi localhost:9000
|
||||
|
||||
handle_errors {
|
||||
root /srv/{{ web_fqdn }}
|
||||
rewrite /error/{err.status_code}.html
|
||||
templates
|
||||
encode gzip
|
||||
}
|
||||
}
|
||||
prepend_newline: true
|
||||
marker: "# <-- {mark} ANSIBLE MANAGED CLOUD DOMAIN -->"
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
create: true
|
||||
mode: "644"
|
||||
state: present
|
||||
# - name: Restarting webserver / reverse proxy container
|
||||
# become: true
|
||||
# become_user: "{{ current_user.stdout }}"
|
||||
# when: server_run
|
||||
# containers.podman.podman_container:
|
||||
# name: "{{ compose.containers.webserver.name }}"
|
||||
# state: started
|
||||
# force_restart: true
|
||||
- name: Spinning up forge container specified by Compose file
|
||||
when: forge_run
|
||||
block:
|
||||
- name: Creating database necessary for forge server container specified by Compose file
|
||||
become: true
|
||||
become_user: "{{ current_user.stdout }}"
|
||||
when: dbms_run
|
||||
containers.podman.podman_container_exec:
|
||||
name: "{{ compose.containers.db.name }}"
|
||||
argv:
|
||||
- mysql
|
||||
- "-u"
|
||||
- "{{ mysql.users.admin.username }}"
|
||||
- "-p{{ mysql.users.admin.password }}"
|
||||
- "-e"
|
||||
- "'CREATE DATABASE IF NOT EXISTS {{ mysql.users.admin.databases.gitea.name }};'"
|
||||
detach: true
|
||||
- name: Creating environment file for forge server container specified by Compose file
|
||||
become: true
|
||||
become_user: "{{ current_user.stdout }}"
|
||||
ansible.builtin.template:
|
||||
src: user/gitea.env.j2
|
||||
dest: "{{ ansible_user_home.stdout }}/.gitea.env"
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
mode: "644"
|
||||
force: true
|
||||
backup: true
|
||||
register: gitea_environ
|
||||
- name: Creating and deploying forge server container specified by Compose file
|
||||
become: true
|
||||
become_user: "{{ current_user.stdout }}"
|
||||
ansible.builtin.command:
|
||||
cmd: "podman-compose --env-file {{ mysql_environ.dest }} --env-file {{ email_environ.dest }} --env-file {{ gitea_environ.dest }} --env-file {{ environ.dest }} up -d {{ compose.containers.forge.name }}"
|
||||
chdir: "{{ new_compose_path.dest }}{{ source_code.repos.compose.rpath | default('/independent') }}"
|
||||
- name: Adding Caddyfile subdomain entry
|
||||
when: "server_run and mode == 'prod'"
|
||||
ansible.builtin.blockinfile:
|
||||
path: "{{ ansible_user_home.stdout }}/.config/caddy/Caddyfile"
|
||||
block: |
|
||||
{{ gitea.subdomain }}.{{ web_fqdn }} {
|
||||
reverse_proxy localhost:3000
|
||||
|
||||
handle_errors {
|
||||
root /srv/{{ web_fqdn }}
|
||||
rewrite /error/{err.status_code}.html
|
||||
file_server
|
||||
templates
|
||||
encode gzip
|
||||
}
|
||||
}
|
||||
prepend_newline: true
|
||||
marker: "# <-- {mark} ANSIBLE MANAGED CLOUD DOMAIN -->"
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
create: true
|
||||
mode: "644"
|
||||
state: present
|
||||
- name: Adding Caddyfile subdomain entry
|
||||
when: "server_run and (mode == 'dev' or caddy.scheme == 'http')"
|
||||
ansible.builtin.blockinfile:
|
||||
path: "{{ ansible_user_home.stdout }}/.config/caddy/Caddyfile"
|
||||
block: |
|
||||
http://{{ gitea.subdomain }}.{{ web_fqdn }} {
|
||||
reverse_proxy localhost:3000
|
||||
|
||||
handle_errors {
|
||||
root /srv/{{ web_fqdn }}
|
||||
rewrite /error/{err.status_code}.html
|
||||
file_server
|
||||
templates
|
||||
encode gzip
|
||||
}
|
||||
}
|
||||
prepend_newline: true
|
||||
marker: "# <-- {mark} ANSIBLE MANAGED CLOUD DOMAIN -->"
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
create: true
|
||||
mode: "644"
|
||||
state: present
|
||||
# - name: Restarting webserver / reverse proxy container
|
||||
# become: true
|
||||
# become_user: "{{ current_user.stdout }}"
|
||||
# when: server_run
|
||||
# containers.podman.podman_container:
|
||||
# name: "{{ compose.containers.webserver.name }}"
|
||||
# state: started
|
||||
# force_restart: true
|
||||
- name: Spinning up pastebin container specified by Compose file
|
||||
when: pbin_run
|
||||
block:
|
||||
- name: Creating database necessary for pastebin server container specified by Compose file
|
||||
become: true
|
||||
become_user: "{{ current_user.stdout }}"
|
||||
when: dbms_run
|
||||
containers.podman.podman_container_exec:
|
||||
name: "{{ compose.containers.db.name }}"
|
||||
argv:
|
||||
- mysql
|
||||
- "-u"
|
||||
- "{{ mysql.users.admin.username }}"
|
||||
- "-p{{ mysql.users.admin.password }}"
|
||||
- "-e"
|
||||
- "'CREATE DATABASE IF NOT EXISTS {{ mysql.users.admin.databases.opengist.name }};'"
|
||||
detach: true
|
||||
- name: Creating environment file for pastebin server container specified by Compose file
|
||||
become: true
|
||||
become_user: "{{ current_user.stdout }}"
|
||||
when: pbin_run
|
||||
ansible.builtin.template:
|
||||
src: user/opengist.env.j2
|
||||
dest: "{{ ansible_user_home.stdout }}/.opengist.env"
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
mode: "644"
|
||||
force: true
|
||||
backup: true
|
||||
register: opengist_environ
|
||||
- name: Creating gist configuration file
|
||||
become: true
|
||||
become_user: "{{ current_user.stdout }}"
|
||||
when: pbin_run
|
||||
ansible.builtin.template:
|
||||
src: user/config/opengist/config.yml.j2
|
||||
dest: "{{ ansible_user_home.stdout }}/.config/opengist/config.yml"
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
mode: "644"
|
||||
force: true
|
||||
backup: true
|
||||
- name: Creating and deploying pastebin server container specified by Compose file
|
||||
become: true
|
||||
become_user: "{{ current_user.stdout }}"
|
||||
when: pbin_run
|
||||
ansible.builtin.command:
|
||||
cmd: "podman-compose --env-file {{ opengist_environ.dest }} --env-file {{ mysql_environ.dest }} --env-file {{ environ.dest }} up -d {{ compose.containers.pastebin.name }}"
|
||||
chdir: "{{ new_compose_path.dest }}{{ source_code.repos.compose.rpath | default('/independent') }}"
|
||||
- name: Adding Caddyfile subdomain entry
|
||||
when: "server_run and mode == 'prod'"
|
||||
ansible.builtin.blockinfile:
|
||||
path: "{{ ansible_user_home.stdout }}/.config/caddy/Caddyfile"
|
||||
block: |
|
||||
{{ gist.subdomain }}.{{ web_fqdn }} {
|
||||
reverse_proxy localhost:6157
|
||||
|
||||
handle_errors {
|
||||
root /srv/{{ web_fqdn }}
|
||||
rewrite /error/{err.status_code}.html
|
||||
file_server
|
||||
templates
|
||||
encode gzip
|
||||
}
|
||||
}
|
||||
prepend_newline: true
|
||||
marker: "# <-- {mark} ANSIBLE MANAGED CLOUD DOMAIN -->"
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
create: true
|
||||
mode: "644"
|
||||
state: present
|
||||
- name: Adding Caddyfile subdomain entry
|
||||
when: "server_run and (mode == 'dev' or caddy.scheme == 'http')"
|
||||
ansible.builtin.blockinfile:
|
||||
path: "{{ ansible_user_home.stdout }}/.config/caddy/Caddyfile"
|
||||
block: |
|
||||
http://{{ gist.subdomain }}.{{ web_fqdn }} {
|
||||
reverse_proxy localhost:6157
|
||||
|
||||
handle_errors {
|
||||
root /srv/{{ web_fqdn }}
|
||||
rewrite /error/{err.status_code}.html
|
||||
file_server
|
||||
templates
|
||||
encode gzip
|
||||
}
|
||||
}
|
||||
prepend_newline: true
|
||||
marker: "# <-- {mark} ANSIBLE MANAGED CLOUD DOMAIN -->"
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
create: true
|
||||
mode: "644"
|
||||
state: present
|
||||
# - name: Restarting webserver / reverse proxy container
|
||||
# become: true
|
||||
# become_user: "{{ current_user.stdout }}"
|
||||
# when: server_run
|
||||
# containers.podman.podman_container:
|
||||
# name: "{{ compose.containers.webserver.name }}"
|
||||
# state: started
|
||||
# force_restart: true
|
||||
- name: Spinning up web or reverse proxy server container specified by Compose file
|
||||
when: server_run
|
||||
block:
|
||||
- name: Creating directory for website subdomains
|
||||
ansible.builtin.file:
|
||||
path: "{{ ansible_user_home.stdout }}/srv/{{ item }}.{{ web_fqdn }}"
|
||||
recurse: true
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
state: directory
|
||||
loop:
|
||||
- certbot
|
||||
- notes
|
||||
- blog
|
||||
- name: Creating directory for Caddy configuration
|
||||
ansible.builtin.file:
|
||||
path: "{{ ansible_user_home.stdout }}/.caddy"
|
||||
recurse: true
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
state: directory
|
||||
- name: Creating and deploying webserver / reverse proxy server container specified by Compose file
|
||||
become: true
|
||||
become_user: "{{ current_user.stdout }}"
|
||||
ansible.builtin.command:
|
||||
cmd: "podman-compose --env-file {{ environ.dest }} up -d {{ compose.containers.webserver.name }}"
|
||||
chdir: "{{ new_compose_path.dest }}{{ source_code.repos.compose.rpath | default('/independent') }}"
|
||||
- name: Creating volume subdirectory for main website root's error pages
|
||||
ansible.builtin.file:
|
||||
path: "{{ ansible_user_home.stdout }}/srv/{{ web_fqdn }}/error"
|
||||
recurse: true
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
state: directory
|
||||
- name: Creating image files for main website root's error path
|
||||
become: true
|
||||
become_user: "{{ current_user.stdout }}"
|
||||
ansible.builtin.copy:
|
||||
src: "user/srv/domain-root/error/{{ item }}"
|
||||
dest: "{{ ansible_user_home.stdout }}/srv/{{ web_fqdn }}/error/"
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
backup: true
|
||||
mode: "644"
|
||||
loop:
|
||||
- 503.html
|
||||
- "mythe-sisyphus-klein.png"
|
||||
- "dark-matter.png"
|
||||
- name: Creating or updating Caddyfile at directory
|
||||
when: "mode == 'prod' and ssl_run"
|
||||
ansible.builtin.blockinfile:
|
||||
path: "{{ ansible_user_home.stdout }}/.config/caddy/Caddyfile"
|
||||
block: |
|
||||
http://{{ web_fqdn }} {
|
||||
handle /.well-known/acme-challenge/* {
|
||||
reverse_proxy localhost:80
|
||||
}
|
||||
handle {
|
||||
redir https://{host}{uri} 308
|
||||
}
|
||||
}
|
||||
:80 {
|
||||
root /srv/certbot.{{ web_fqdn }}
|
||||
browse
|
||||
}
|
||||
{{ web_fqdn }} {
|
||||
respond 503
|
||||
# root /srv/{{ web_fqdn }}
|
||||
file_server
|
||||
|
||||
header /.well-known/openpgpkey/* {
|
||||
Content-Type application/octet-stream
|
||||
Access-Control-Allow-Origin *
|
||||
}
|
||||
|
||||
handle_errors {
|
||||
rewrite /error/{err.status_code}.html
|
||||
templates
|
||||
}
|
||||
}
|
||||
prepend_newline: true
|
||||
marker: "# <-- {mark} ANSIBLE MANAGED ROOT DOMAIN -->"
|
||||
create: true
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
mode: "644"
|
||||
state: present
|
||||
- name: Creating or updating Caddyfile at directory
|
||||
when: "mode == 'prod' and not ssl_run"
|
||||
ansible.builtin.blockinfile:
|
||||
path: "{{ ansible_user_home.stdout }}/.config/caddy/Caddyfile"
|
||||
block: |
|
||||
{{ web_fqdn }} {
|
||||
respond 503
|
||||
# root /srv/{{ web_fqdn }}
|
||||
file_server
|
||||
|
||||
header /.well-known/openpgpkey/* {
|
||||
Content-Type application/octet-stream
|
||||
Access-Control-Allow-Origin *
|
||||
}
|
||||
|
||||
handle_errors {
|
||||
rewrite /error/{err.status_code}.html
|
||||
templates
|
||||
}
|
||||
}
|
||||
prepend_newline: true
|
||||
marker: "# <-- {mark} ANSIBLE MANAGED ROOT DOMAIN -->"
|
||||
create: true
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
mode: "644"
|
||||
state: present
|
||||
- name: Creating or updating Caddyfile at directory
|
||||
when: "mode == 'dev' or caddy.scheme == 'http'"
|
||||
ansible.builtin.blockinfile:
|
||||
path: "{{ ansible_user_home.stdout }}/.config/caddy/Caddyfile"
|
||||
block: |
|
||||
http://{{ web_fqdn }} {
|
||||
respond 503
|
||||
# root /srv/{{ web_fqdn }}
|
||||
file_server
|
||||
|
||||
header /.well-known/openpgpkey/* {
|
||||
Content-Type application/octet-stream
|
||||
Access-Control-Allow-Origin *
|
||||
}
|
||||
|
||||
handle_errors {
|
||||
rewrite /error/{err.status_code}.html
|
||||
templates
|
||||
}
|
||||
}
|
||||
prepend_newline: true
|
||||
marker: "# <-- {mark} ANSIBLE MANAGED ROOT DOMAIN -->"
|
||||
create: true
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
mode: "644"
|
||||
state: present
|
||||
- name: Opening port 443
|
||||
become: true
|
||||
ansible.builtin.iptables:
|
||||
chain: INPUT
|
||||
protocol: "{{ item }}"
|
||||
destination_port: 443
|
||||
jump: ACCEPT
|
||||
comment: Open up port 443
|
||||
loop:
|
||||
- udp
|
||||
- tcp
|
||||
- name: Opening ports
|
||||
become: true
|
||||
ansible.builtin.iptables:
|
||||
chain: INPUT
|
||||
protocol: tcp
|
||||
destination_port: "{{ item }}"
|
||||
jump: ACCEPT
|
||||
comment: "Open up port {{ (item | string) }}"
|
||||
loop:
|
||||
- 80
|
||||
# - name: Restarting webserver / reverse proxy container
|
||||
# become: true
|
||||
# become_user: "{{ current_user.stdout }}"
|
||||
# containers.podman.podman_container:
|
||||
# name: "{{ compose.containers.webserver.name }}"
|
||||
# state: started
|
||||
# force_restart: true
|
||||
- name: Spinning up ACME challenge container specified by Compose file
|
||||
when: ssl_run
|
||||
ignore_errors: true
|
||||
block:
|
||||
- name: Creating environment file for SSL/TLS certificate acquisition container specified in Compose file
|
||||
become: true
|
||||
become_user: "{{ current_user.stdout }}"
|
||||
ansible.builtin.template:
|
||||
src: user/certbot.env.j2
|
||||
dest: "{{ ansible_user_home.stdout }}/.certbot.env"
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
mode: "644"
|
||||
force: true
|
||||
backup: true
|
||||
register: certbot_environ
|
||||
- name: Creating and deploying SSL/TLS certificate acquisition container specified by Compose file
|
||||
become: true
|
||||
become_user: "{{ current_user.stdout }}"
|
||||
ansible.builtin.command:
|
||||
cmd: "podman-compose --env-file {{ certbot_environ.dest }} --env-file {{ environ.dest }} up -d {{ compose.containers.ssl.name }}"
|
||||
chdir: "{{ new_compose_path.dest }}{{ source_code.repos.compose.rpath | default('/independent') }}"
|
||||
- name: Spinning up tailnet container specified by Compose file
|
||||
when: tail_run
|
||||
block:
|
||||
- name: Creating required tailnet container secret for tailnet container specified by Compose file
|
||||
become: true
|
||||
# become_user: "{{ current_user.stdout }}"
|
||||
when: item.name == inventory_hostname
|
||||
ansible.builtin.copy:
|
||||
src: "{{ item.name }}-{{ headscale.users.admin.username }}@headscale/headscale{{ (idx | string) }}.key"
|
||||
dest: "{{ ansible_user_home.stdout }}/.podsecrets/headscale.key"
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
mode: "644"
|
||||
force: true
|
||||
backup: true
|
||||
loop: "{{ headscale.clients }}"
|
||||
loop_control:
|
||||
index_var: idx
|
||||
- name: Creating tailnet configuration file
|
||||
become: true
|
||||
become_user: "{{ current_user.stdout }}"
|
||||
ansible.builtin.template:
|
||||
src: user/config/tailscale/conf.json.j2
|
||||
dest: "{{ ansible_user_home.stdout }}/.config/tailscale/conf.json"
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
mode: "644"
|
||||
force: true
|
||||
backup: true
|
||||
- name: Creating and deploying tailnet container specified by Compose file
|
||||
become: true
|
||||
become_user: "{{ current_user.stdout }}"
|
||||
ansible.builtin.command:
|
||||
cmd: "podman-compose --env-file {{ environ.dest }} up -d {{ compose.containers.tail.name }}"
|
||||
chdir: "{{ new_compose_path.dest }}{{ source_code.repos.compose.rpath | default('/independent') }}"
|
||||
- name: Spinning up dashboard container specified by Compose file
|
||||
when: tail_run and dash_run
|
||||
block:
|
||||
- name: Creating glance configuration file
|
||||
become: true
|
||||
become_user: "{{ current_user.stdout }}"
|
||||
ansible.builtin.template:
|
||||
src: user/config/glance/glance.yml.j2
|
||||
dest: "{{ ansible_user_home.stdout }}/.config/glance/glance.yml"
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
mode: "644"
|
||||
force: true
|
||||
backup: true
|
||||
- name: Creating and deploying dashboard container specified by Compose file
|
||||
become: true
|
||||
become_user: "{{ current_user.stdout }}"
|
||||
ansible.builtin.command:
|
||||
cmd: "podman-compose up -d {{ compose.containers.dash.name }}"
|
||||
chdir: "{{ new_compose_path.dest }}{{ source_code.repos.compose.rpath | default('/independent') }}"
|
||||
- name: Restarting webserver / reverse proxy container
|
||||
become: true
|
||||
become_user: "{{ current_user.stdout }}"
|
||||
when: server_run
|
||||
containers.podman.podman_container:
|
||||
name: "{{ compose.containers.webserver.name }}"
|
||||
state: started
|
||||
force_restart: true
|
||||
- name: Making running containers persist on user logout
|
||||
become: true
|
||||
ansible.builtin.shell:
|
||||
cmd: loginctl enable-linger $(whoami)
|
||||
|
||||
45
roles/init-server/tasks/contingent/pkg/sukaato.yml
Normal file
45
roles/init-server/tasks/contingent/pkg/sukaato.yml
Normal file
@@ -0,0 +1,45 @@
|
||||
---
|
||||
- name: Acquiring home of current user
|
||||
when: ansible_facts["system"] == "Linux"
|
||||
ansible.builtin.shell:
|
||||
cmd: "echo ~{{ ansible_user }}"
|
||||
register: ansible_user_home
|
||||
- name: Acquiring home of current user
|
||||
when: ansible_facts["system"] == "Linux"
|
||||
ansible.builtin.shell:
|
||||
cmd: "echo {{ ansible_user }}"
|
||||
register: current_user
|
||||
- name: Moving git repository from initial path
|
||||
block:
|
||||
- name: Recursively copying directory and its contents to elsewhere
|
||||
ansible.builtin.copy:
|
||||
src: "{{ ansible_user_home.stdout }}/repos/.foreign/{{ source_code.repos.site.name }}"
|
||||
remote_src: true
|
||||
dest: "{{ ansible_user_home.stdout }}/repos/"
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
register: new_compose_path
|
||||
- name: Deleting directory at previous path
|
||||
ansible.builtin.file:
|
||||
path: "{{ ansible_user_home.stdout }}/repos/.foreign/{{ source_code.repos.site.name }}"
|
||||
state: absent
|
||||
- name: Creating directory for new bare repository
|
||||
ansible.builtin.file:
|
||||
path: "{{ ansible_user_home.stdout }}/src"
|
||||
recurse: true
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
state: directory
|
||||
- name: Creating bare repository
|
||||
ansible.builtin.command:
|
||||
cmd: "git init --bare {{ source_code.repos.site.name }}.git"
|
||||
chdir: "{{ ansible_user_home.stdout }}/src"
|
||||
creates: "{{ ansible_user_home.stdout }}/src/{{ source_code.repos.site.name }}.git"
|
||||
- name: Running website
|
||||
when: source_code.repos.site.run
|
||||
# become: true
|
||||
# become_user: "{{ current_user.stdout }}"
|
||||
block:
|
||||
- name: Warning about lack of implementation
|
||||
ansible.builtin.debug:
|
||||
msg: Not yet implemented
|
||||
@@ -6,52 +6,81 @@
|
||||
register: ansible_user_home
|
||||
- name: Linking binaries to directories already in PATH environment variable
|
||||
become: true
|
||||
ignore_errors: true
|
||||
ansible.builtin.file:
|
||||
src: "{{ ansible_user_home.stdout }}/downloads/archives/released/surge/{{ item }}"
|
||||
dest: "/usr/bin/{{ item }}"
|
||||
state: link
|
||||
loop:
|
||||
- surge
|
||||
- name: Installing accompanying complementary Surge system service
|
||||
ansible.builtin.command:
|
||||
cmd: surge service install
|
||||
- name: Acquiring API token for remote Surge service control
|
||||
ansible.builtin.command:
|
||||
cmd: surge token
|
||||
register: surge_token
|
||||
- name: Pausing to inquire about how to proceed
|
||||
ansible.builtin.pause:
|
||||
prompt: "Type \"fetch\" to get the Surge API token, or \"show\" to see it for manual copying instead"
|
||||
echo: true
|
||||
register: data_method
|
||||
- name: Choosing to present Surge API token to Control Node
|
||||
when: data_method.user_input == "show"
|
||||
- name: Starting to spin up the Surge service
|
||||
when: surge.service.enabled and not surge.containerized
|
||||
block:
|
||||
- name: Installing accompanying complementary Surge system service
|
||||
become: true
|
||||
ansible.builtin.command:
|
||||
cmd: surge service install
|
||||
- name: Creating corresponding SystemD service unit
|
||||
become: true
|
||||
ansible.builtin.copy:
|
||||
src: systemd/system/surge.service
|
||||
dest: /etc/systemd/system/surge.service
|
||||
owner: root
|
||||
group: root
|
||||
force: true
|
||||
backup: true
|
||||
- name: Acquiring API token for remote Surge service control
|
||||
become: true
|
||||
ansible.builtin.command:
|
||||
cmd: surge token
|
||||
register: surge_token
|
||||
- name: Pausing to inquire about how to proceed
|
||||
ansible.builtin.pause:
|
||||
prompt: "Type \"fetch\" to get the Surge API token, or \"show\" to see it for manual copying instead"
|
||||
echo: true
|
||||
register: data_method
|
||||
- name: Presenting Surge API token to Control Node
|
||||
when: data_method.user_input == "show"
|
||||
ansible.builtin.debug:
|
||||
msg: "Make sure to store the following API token for Surge:\n {{ surge_token.stdout }}"
|
||||
- name: Giving opportunity to manually copy Surge API token
|
||||
when: data_method.user_input == "show"
|
||||
ansible.builtin.pause:
|
||||
- name: Choosing to provide file on control node containing Surge's API token
|
||||
when: data_method.user_input == "fetch"
|
||||
block:
|
||||
- name: Creating temporary file on managed node that stores Surge API token
|
||||
become: true
|
||||
when: data_method.user_input == "fetch"
|
||||
ansible.builtin.copy:
|
||||
content: "{{ surge_token.stdout }}"
|
||||
dest: /tmp/surge.token
|
||||
dest: /tmp/surge.secret
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
mode: "644"
|
||||
register: surge_token
|
||||
- name: Placing Surge API token into file on control node
|
||||
when: data_method.user_input == "fetch"
|
||||
ansible.builtin.fetch:
|
||||
src: "{{ surge_token.dest }}"
|
||||
dest: "./.tmp/{{ inventory_hostname }}-surge/surge.secret"
|
||||
flat: true
|
||||
- name: Placing Surge API token into file on control node
|
||||
when: data_method.user_input == "fetch"
|
||||
ansible.builtin.fetch:
|
||||
src: "{{ surge_token.dest }}"
|
||||
dest: "./roles/init-server/files/{{ inventory_hostname }}-surge/surge.secret"
|
||||
flat: true
|
||||
- name: Informing control node of acquired files
|
||||
when: data_method.user_input == "fetch"
|
||||
ansible.builtin.debug:
|
||||
msg: "The Surge API token file have been duplicated to '/var/tmp/{{ inventory_hostname }}/surge.token' at the control node."
|
||||
msg: "The Surge API token file have been duplicated to './.tmp/{{ inventory_hostname }}-surge/surge.secret' at the control node."
|
||||
- name: Giving control node user time to read the aforementiioned message
|
||||
when: data_method.user_input == "fetch"
|
||||
ansible.builtin.pause:
|
||||
seconds: 30
|
||||
seconds: 30
|
||||
- name: Starting and enabling Surge SystemD service unit
|
||||
become: true
|
||||
ansible.builtin.systemd_service:
|
||||
name: surge
|
||||
scope: system
|
||||
state: started
|
||||
enabled: true
|
||||
daemon_reload: true
|
||||
@@ -15,8 +15,11 @@
|
||||
ansible.builtin.shell:
|
||||
cmd: "{{ ansible_user_home.stdout }}/.local/bin/uv-install.sh"
|
||||
creates: "{{ ansible_user_home.stdout }}/.local/bin/uv"
|
||||
async: 600
|
||||
poll: 5
|
||||
- name: Linking binaries to directories already in PATH environment variable
|
||||
become: true
|
||||
ignore_errors: true
|
||||
ansible.builtin.file:
|
||||
src: "{{ ansible_user_home.stdout }}/.local/bin/{{ item }}"
|
||||
dest: "/usr/bin/{{ item }}"
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
force: true
|
||||
mode: "644"
|
||||
follow_redirects: safe
|
||||
timeout: 300
|
||||
- name: Configuring ViM
|
||||
become: true
|
||||
become_user: "{{ current_user.stdout }}"
|
||||
|
||||
57
roles/init-server/tasks/contingent/pkg/wireguard.yml
Normal file
57
roles/init-server/tasks/contingent/pkg/wireguard.yml
Normal file
@@ -0,0 +1,57 @@
|
||||
---
|
||||
- name: Enabling Wireguard kernel module
|
||||
become: true
|
||||
community.general.modprobe:
|
||||
name: wireguard
|
||||
persistent: present
|
||||
state: present
|
||||
- name: Enable IP forwarding
|
||||
become: true
|
||||
when: wireguard.ip_forward
|
||||
block:
|
||||
- name: Enabling IPv4 forwarding
|
||||
ansible.posix.sysctl:
|
||||
name: net.ipv4.ip_forward
|
||||
value: "1"
|
||||
sysctl_set: true
|
||||
state: present
|
||||
- name: Marking IPv4 forwarded traffic as valid
|
||||
ansible.posix.sysctl:
|
||||
name: net.ipv4.conf.all.src_valid_mark
|
||||
value: "1"
|
||||
sysctl_set: true
|
||||
state: present
|
||||
- name: Enabling IPv6 forwarding
|
||||
ansible.posix.sysctl:
|
||||
name: net.ipv6.conf.all.forwarding
|
||||
value: "1"
|
||||
sysctl_set: true
|
||||
state: present
|
||||
- name: Marking IPv6 traffic as valid
|
||||
ansible.posix.sysctl:
|
||||
name: net.ipv6.conf.all.src_valid_mark
|
||||
value: "1"
|
||||
sysctl_set: true
|
||||
state: present
|
||||
- name: Preparing to allow Wireguard logging
|
||||
when: "wireguard.debug"
|
||||
block:
|
||||
- name: Creating subdirectory for system kernel debugging
|
||||
become: true
|
||||
ansible.builtin.file:
|
||||
path: /sys/kernel/debug/dynamic_debug
|
||||
recurse: true
|
||||
owner: root
|
||||
group: root
|
||||
mode: "755"
|
||||
state: directory
|
||||
- name: Enabling Wireguard system logging
|
||||
become: true
|
||||
ansible.builtin.copy:
|
||||
content: "module wireguard +p"
|
||||
dest: /sys/kernel/debug/dynamic_debug/control
|
||||
owner: root
|
||||
group: root
|
||||
mode: "644"
|
||||
force: true
|
||||
|
||||
@@ -87,13 +87,6 @@
|
||||
# @TODO uncomment below before continuing with testing previous task
|
||||
# - name: Premature end of play
|
||||
# ansible.builtin.meta: end_play
|
||||
- name: Updating package cache
|
||||
ansible.builtin.apt:
|
||||
update_cache: true
|
||||
- name: Updating package cache
|
||||
ansible.builtin.apt:
|
||||
upgrade: dist
|
||||
autoremove: true
|
||||
- name: Registering a package source
|
||||
when: item.sources != None
|
||||
ansible.builtin.deb822_repository:
|
||||
@@ -108,6 +101,10 @@
|
||||
- name: Updating package cache
|
||||
ansible.builtin.apt:
|
||||
update_cache: true
|
||||
- name: Upgrading
|
||||
ansible.builtin.apt:
|
||||
upgrade: dist
|
||||
autoremove: true
|
||||
- name: Installing a local package in managed node
|
||||
when: item.uri != None
|
||||
ansible.builtin.apt:
|
||||
@@ -121,6 +118,8 @@
|
||||
name: "{{ item.name }}"
|
||||
state: present
|
||||
notify: "{{ item.handler | default('default') }}"
|
||||
async: 600
|
||||
poll: 5
|
||||
loop: "{{ ((pkgs.mngr.core | default([]))) | rejectattr('uri', 'search', '\\.deb$') }}"
|
||||
tags:
|
||||
- get_mngr_pkgs
|
||||
@@ -137,7 +136,8 @@
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
force: true
|
||||
mode: "744"
|
||||
mode: "755"
|
||||
timeout: 300
|
||||
notify: "{{ ((pkgs.script.core | default([])))[idx].handler | default('default') }}"
|
||||
loop: "{{ (pkgs.script.core | default([])) }}"
|
||||
loop_control:
|
||||
@@ -206,7 +206,6 @@
|
||||
dest: "{{ ansible_user_home.stdout }}/repos/.foreign/{{ item.name }}"
|
||||
version: "{{ item.branch }}"
|
||||
clone: true
|
||||
single_branch: true
|
||||
notify: "{{ item.handler | default('default') }}"
|
||||
loop: "{{ (pkgs.git_repos.core | default([])) }}"
|
||||
register: installation_repos
|
||||
@@ -225,9 +224,10 @@
|
||||
dest: "/usr/bin/{{ item.name }}"
|
||||
owner: root
|
||||
group: root
|
||||
mode: "744"
|
||||
mode: "755"
|
||||
force: true
|
||||
backup: true
|
||||
notify: "{{ item.handler }}"
|
||||
timeout: 300
|
||||
loop: "{{ (pkgs.binaries.core | default([])) }}"
|
||||
|
||||
|
||||
20
roles/init-server/tasks/netrc.yml
Normal file
20
roles/init-server/tasks/netrc.yml
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
- name: Acquiring home of current user
|
||||
when: ansible_facts["system"] == "Linux"
|
||||
ansible.builtin.shell:
|
||||
cmd: "echo ~{{ ansible_user }}"
|
||||
register: ansible_user_home
|
||||
- name: Acquiring current user
|
||||
when: ansible_facts["system"] == "Linux"
|
||||
ansible.builtin.shell:
|
||||
cmd: "echo {{ ansible_user }}"
|
||||
register: current_user
|
||||
- name: Copying NetRC file
|
||||
become: true
|
||||
become_user: "{{ current_user.stdout }}"
|
||||
ansible.builtin.template:
|
||||
src: user/netrc.j2
|
||||
dest: "{{ ansible_user_home.stdout }}/.netrc"
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
mode: "600"
|
||||
@@ -2,6 +2,22 @@
|
||||
---
|
||||
# tasks file for roles/init-vps
|
||||
# @NOTE server deployment method is based on task tags compiled herein
|
||||
- name: Informing user of requirement of two main domains
|
||||
when: (certbot.domains | length) < 2 or (certbot.domains | length) > 2
|
||||
ansible.builtin.fail:
|
||||
msg: Only two domains allowed and required
|
||||
- name: Informing user of requirement at least one wildcard
|
||||
when: (certbot.domains | select("regex", "^\\*\\.") | list | length) == 0
|
||||
ansible.builtin.fail:
|
||||
msg: At least one of the FQDNs must have a wildcard
|
||||
# - name: Setting the FQDN for development
|
||||
# when: mode == "dev"
|
||||
# ansible.builtin.set_fact:
|
||||
# fqdn: "{{ (certbot.domains | map('regex_replace', '\\.([^\\.]*)$', '.test') | reject('regex', '^\\*\\.') | list)[0] }}"
|
||||
- name: Setting the FQDN
|
||||
# when: mode == "prod"
|
||||
ansible.builtin.set_fact:
|
||||
fqdn: "{{ (certbot.domains | reject('regex', '^\\*\\.') | list)[0] }}"
|
||||
- name: Finding SSH public keys for root
|
||||
delegate_facts: true
|
||||
delegate_to: localhost
|
||||
@@ -44,7 +60,7 @@
|
||||
- name: Creating the VPS
|
||||
linode.cloud.instance:
|
||||
api_token: "{{ token | prompted_token.user_input }}"
|
||||
label: "{{ instance }}"
|
||||
label: "{{ fqdn }}"
|
||||
type: g6-standard-2
|
||||
image: "{{ operating_system }}"
|
||||
disk_encryption: enabled
|
||||
@@ -86,7 +102,7 @@
|
||||
ansible.builtin.wait_for_connection:
|
||||
delay: 20
|
||||
timeout: 300
|
||||
loop: "{{ groups[instance] | default(hostvars[instance]) }}"
|
||||
loop: "{{ groups[fqdn] | default(hostvars[fqdn]) }}"
|
||||
- name: Checking if that server has required operating system
|
||||
delegate_to: "{{ item }}"
|
||||
delegate_facts: true
|
||||
@@ -94,7 +110,7 @@
|
||||
when: ansible_facts["system"] != "Linux" and item is ansible.utils['ip_pref']
|
||||
ansible.builtin.fail:
|
||||
msg: Unsupported operating system found
|
||||
loop: "{{ groups[instance] | default(hostvars[instance]) }}"
|
||||
loop: "{{ groups[fqdn] | default(hostvars[fqdn]) }}"
|
||||
- name: Checking if that server has required Linux distro
|
||||
delegate_to: "{{ item }}"
|
||||
delegate_facts: true
|
||||
@@ -102,7 +118,7 @@
|
||||
when: ansible_facts["system"] == "Linux" and ansible_facts["os_family"] != "Debian" and item is ansible.utils['ip_pref']
|
||||
ansible.builtin.fail:
|
||||
msg: Unsupported Linux distro found
|
||||
loop: "{{ groups[instance] | default(hostvars[instance]) }}"
|
||||
loop: "{{ groups[fqdn] | default(hostvars[fqdn]) }}"
|
||||
- name: Providing authorized keys for server root account
|
||||
delegate_to: "{{ item[0] }}"
|
||||
delegate_facts: true
|
||||
@@ -112,6 +128,6 @@
|
||||
user: "{{ ansible_user }}"
|
||||
key: "{{ lookup('file', item[1]) }}"
|
||||
state: present
|
||||
loop: "{{ (groups[instance] | default(hostvars[instance])) | product(root_pubkey_paths) }}"
|
||||
loop: "{{ (groups[fqdn] | default(hostvars[fqdn])) | product(root_pubkey_paths) }}"
|
||||
tags:
|
||||
- lan
|
||||
|
||||
@@ -88,13 +88,6 @@
|
||||
# @TODO uncomment below before continuing with testing previous task
|
||||
# - name: Premature end of play
|
||||
# ansible.builtin.meta: end_play
|
||||
- name: Updating package cache
|
||||
ansible.builtin.apt:
|
||||
update_cache: true
|
||||
- name: Updating package cache
|
||||
ansible.builtin.apt:
|
||||
upgrade: dist
|
||||
autoremove: true
|
||||
- name: Registering a package source
|
||||
when: item.sources != None
|
||||
ansible.builtin.deb822_repository:
|
||||
@@ -109,6 +102,10 @@
|
||||
- name: Updating package cache
|
||||
ansible.builtin.apt:
|
||||
update_cache: true
|
||||
- name: Upgrading
|
||||
ansible.builtin.apt:
|
||||
upgrade: dist
|
||||
autoremove: true
|
||||
- name: Installing a local package in managed node
|
||||
when: item.uri != None
|
||||
ansible.builtin.apt:
|
||||
@@ -122,6 +119,8 @@
|
||||
name: "{{ item.name }}"
|
||||
state: latest
|
||||
notify: "{{ item.handler | default('default') }}" # @TODO create corresponding roles/init-vps handlers
|
||||
async: 600
|
||||
poll: 5
|
||||
loop: "{{ (pkgs.mngr.userspace | default([])) | rejectattr('uri', 'search', '\\.deb$') }}"
|
||||
tags:
|
||||
- get_mngr_pkgs
|
||||
@@ -138,7 +137,8 @@
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
force: true
|
||||
mode: "744"
|
||||
mode: "755"
|
||||
timeout: 300
|
||||
notify: "{{ (pkgs.script.userspace | default([]))[idx].handler | default('default') }}"
|
||||
loop: "{{ (pkgs.script.userspace | default([])) }}"
|
||||
loop_control:
|
||||
@@ -206,7 +206,6 @@
|
||||
dest: "{{ ansible_user_home.stdout }}/repos/.foreign/{{ item.name }}"
|
||||
version: "{{ item.branch }}"
|
||||
clone: true
|
||||
single_branch: true
|
||||
notify: "{{ item.handler | default('default') }}"
|
||||
loop: "{{ (pkgs.git_repos.userspace | default([])) }}"
|
||||
register: installation_repos
|
||||
@@ -225,8 +224,9 @@
|
||||
dest: "/usr/bin/{{ item.name }}"
|
||||
owner: root
|
||||
group: root
|
||||
mode: "744"
|
||||
mode: "755"
|
||||
force: true
|
||||
backup: true
|
||||
notify: "{{ item.handler }}"
|
||||
timeout: 300
|
||||
loop: "{{ (pkgs.binaries.userspace | default([])) }}"
|
||||
@@ -10,13 +10,29 @@
|
||||
#
|
||||
# https://myheadscale.example.com:443
|
||||
#
|
||||
server_url: {{ tail.scheme + '://' + tail.domain + tail.port }}
|
||||
{% if mode == 'prod' %}
|
||||
{% if headscale.port is defined and headscale.port != None %}
|
||||
server_url: {{ headscale.scheme + '://' + web_fqdn + ':' + (headscale.port | string) }}
|
||||
{% else %}
|
||||
server_url: {{ headscale.scheme + '://' + web_fqdn + ':80' }}
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{% if headscale.port is defined and headscale.port != None %}
|
||||
server_url: {{ 'http://' + web_fqdn + ':' + (headscale.port | string) }}
|
||||
{% else %}
|
||||
server_url: {{ 'http://' + web_fqdn + ':443' }}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
# Address to listen to / bind to on the server
|
||||
#
|
||||
# For production:
|
||||
# listen_addr: 0.0.0.0:8080
|
||||
listen_addr: {{ '0.0.0.0' + tail.port }}
|
||||
{% if headscale.port is defined and headscale.port != None %}
|
||||
listen_addr: {{ '0.0.0.0' + ':' + (headscale.port | string) }}
|
||||
{% else %}
|
||||
listen_addr: 0.0.0.0:80
|
||||
{% endif %}
|
||||
|
||||
# Address to listen to /metrics and /debug, you may want
|
||||
# to keep this endpoint private to your internal network
|
||||
@@ -31,8 +47,8 @@ metrics_listen_addr: 127.0.0.1:9090
|
||||
#
|
||||
# For production:
|
||||
# grpc_listen_addr: 0.0.0.0:50443
|
||||
{% if tail.grpc.expose %}
|
||||
grpc_listen_addr: {{ '0.0.0.0' + tail.grpc.port }}
|
||||
{% if headscale.grpc.expose %}
|
||||
grpc_listen_addr: {{ '0.0.0.0' + ':' + (headscale.grpc.port | string) }}
|
||||
{% else %}
|
||||
grpc_listen_addr: 127.0.0.1:50443
|
||||
{% endif %}
|
||||
@@ -41,7 +57,7 @@ grpc_listen_addr: 127.0.0.1:50443
|
||||
# mode. This is not recommended as the traffic will
|
||||
# be unencrypted. Only enable if you know what you
|
||||
# are doing.
|
||||
{% if tail.grpc.secure %}
|
||||
{% if headscale.grpc.secure %}
|
||||
grpc_allow_insecure: false
|
||||
{% else %}
|
||||
grpc_allow_insecure: true
|
||||
@@ -253,6 +269,7 @@ database:
|
||||
# # in the 'ssl' field. Refers to https://www.postgresql.org/docs/current/libpq-ssl.html Table 34.1.
|
||||
# ssl: false
|
||||
|
||||
{% if mode == 'prod' or headscale.scheme == 'https' %}
|
||||
### TLS configuration
|
||||
#
|
||||
## Let's encrypt / ACME
|
||||
@@ -260,32 +277,42 @@ database:
|
||||
# headscale supports automatically requesting and setting up
|
||||
# TLS for a domain with Let's Encrypt.
|
||||
#
|
||||
|
||||
{% if certbot is undefined or certbot == None %}
|
||||
# URL to ACME directory
|
||||
acme_url: https://acme-v02.api.letsencrypt.org/directory
|
||||
# acme_url: https://acme-v02.api.letsencrypt.org/directory
|
||||
|
||||
# Email to register with ACME provider
|
||||
acme_email: ""
|
||||
# acme_email: ""
|
||||
|
||||
# Domain name to request a TLS certificate for:
|
||||
tls_letsencrypt_hostname: ""
|
||||
# tls_letsencrypt_hostname: ""
|
||||
|
||||
# Path to store certificates and metadata needed by
|
||||
# letsencrypt
|
||||
# For production:
|
||||
tls_letsencrypt_cache_dir: /var/lib/headscale/cache
|
||||
# tls_letsencrypt_cache_dir: /var/lib/headscale/cache
|
||||
|
||||
# Type of ACME challenge to use, currently supported types:
|
||||
# HTTP-01 or TLS-ALPN-01
|
||||
# See: https://headscale.net/stable/ref/tls/
|
||||
tls_letsencrypt_challenge_type: HTTP-01
|
||||
# tls_letsencrypt_challenge_type: HTTP-01
|
||||
# When HTTP-01 challenge is chosen, letsencrypt must set up a
|
||||
# verification endpoint, and it will be listening on:
|
||||
# :http = port 80
|
||||
tls_letsencrypt_listen: ":http"
|
||||
|
||||
# tls_letsencrypt_listen: ":http"
|
||||
{% else %}
|
||||
{% if not certbot.containerized %}
|
||||
## Use already defined certificates:
|
||||
tls_cert_path: ""
|
||||
tls_key_path: ""
|
||||
tls_cert_path: {{ '/etc/letsencrypt/live/' + web_fqdn + '/fullchain.pem' }}
|
||||
tls_key_path: {{ '/etc/letsencrypt/live/' + web_fqdn + '/privkey.pem' }}
|
||||
{% else %}
|
||||
tls_cert_path: {{ ansible_user_home.stdout + '/.config/letsencrypt/live/' + web_fqdn + '/fullchain.pem' }}
|
||||
tls_key_path: {{ ansible_user_home.stdout + '/.config/letsencrypt/live/' + web_fqdn + '/privkey.pem' }}
|
||||
## Use already defined certificates:
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
log:
|
||||
# Valid log levels: panic, fatal, error, warn, info, debug, trace
|
||||
@@ -335,7 +362,7 @@ dns:
|
||||
# `base_domain` must be a FQDN, without the trailing dot.
|
||||
# The FQDN of the hosts will be
|
||||
# `hostname.base_domain` (e.g., _myhost.example.com_).
|
||||
base_domain: {{ tail.magic_dns.domain }}
|
||||
base_domain: {{ headscale.magic_dns.domain }}
|
||||
|
||||
# Whether to use the local DNS settings of a node or override the local DNS
|
||||
# settings (default) and force the use of Headscale's DNS configuration.
|
||||
@@ -343,7 +370,7 @@ dns:
|
||||
|
||||
# List of DNS servers to expose to clients.
|
||||
nameservers:
|
||||
global: {{ tail.magic_dns.nameservers }}
|
||||
global: {{ headscale.magic_dns.nameservers }}
|
||||
|
||||
# NextDNS (see https://tailscale.com/docs/integrations/nextdns).
|
||||
# "abc123" is example NextDNS ID, replace with yours.
|
||||
|
||||
17
roles/init-server/templates/user/all.env.j2
Normal file
17
roles/init-server/templates/user/all.env.j2
Normal file
@@ -0,0 +1,17 @@
|
||||
{% if compose.mode == "dev" %}
|
||||
SERVER_FQDN_SCHEME=http
|
||||
SERVER_FQDN={{ (certbot.domains | map("regex_replace", "\\.([^\\.]*)$", ".test") | reject("regex", "^\\*\\.") | list)[0] }}
|
||||
{% elif compose.mode == "prod" %}
|
||||
SERVER_FQDN_SCHEME=https
|
||||
SERVER_FQDN={{ (certbot.domains | reject("regex", "^\\*\\.") | list)[0] }}
|
||||
{% endif %}
|
||||
|
||||
{% if nextcloud.subdomain is defined and nextcloud != None %}
|
||||
NEXTCLOUD_SUBDOMAIN={{ nextcloud.subdomain }}
|
||||
{% endif %}
|
||||
{% if gitea is defined and gitea != None %}
|
||||
GITEA_SUBDOMAIN={{ gitea.subdomain }}
|
||||
{% endif %}
|
||||
{% if gist is defined and gist != None %}
|
||||
OG_SUBDOMAIN={{ gist.subdomain }}
|
||||
{% endif %}
|
||||
196
roles/init-server/templates/user/aria2/aria2.conf.j2
Normal file
196
roles/init-server/templates/user/aria2/aria2.conf.j2
Normal file
@@ -0,0 +1,196 @@
|
||||
# GENERAL
|
||||
max-concurrent-downloads={{ aria.dl.max.concurrent | string }}
|
||||
dir={{ ansible_user_home.stdout + "/downloads/aria2" }}
|
||||
log={{ ansible_user_home.stdout + "/.aria2/aria2.log" }}
|
||||
log-level={{ aria.log }}
|
||||
console-log-level=notice
|
||||
continue=true
|
||||
|
||||
{% if aria.dl.resume %}
|
||||
always-resume=true
|
||||
{% else %}
|
||||
always-resume=false
|
||||
{% endif %}
|
||||
|
||||
{% if aria.dl.overwriting %}
|
||||
allow-overwrite=true
|
||||
{% else %}
|
||||
allow-overwrite=false
|
||||
{% endif %}
|
||||
|
||||
{% if aria.dl.autorenaming %}
|
||||
auto-file-renaming=true
|
||||
{% else %}
|
||||
auto-file-renaming=false
|
||||
{% endif %}
|
||||
|
||||
file-allocation={{ aria.alloc }}
|
||||
disk-cache={{ aria.dcache | string }}
|
||||
enable-mmap=true
|
||||
enable-color=true
|
||||
human-readable=true
|
||||
keep-unfinished-download-result=true
|
||||
max-download-result=500
|
||||
max-resume-failure-tries=0
|
||||
|
||||
# RPC
|
||||
{% if aria.rpc.enabled %}
|
||||
enable-rpc=true
|
||||
|
||||
{% if mode == "prod" or aria.rpc.scheme == "https" %}
|
||||
rpc-secure=true
|
||||
|
||||
{% if not certbot.containerized %}
|
||||
rpc-certificate={{ "/etc/letsencrypt/live/" + web_fqdn + "/fullchain.pem" }}
|
||||
rpc-private-key={{ "/etc/letsencrypt/live/" + web_fqdn + "/privkey.pem" }}
|
||||
{% else %}
|
||||
rpc-certificate={{ ansible_user_home.stdout + "/.config/letsencrypt/live/" + web_fqdn + "/fullchain.pem" }}
|
||||
rpc-private-key={{ ansible_user_home.stdout + "/.config/letsencrypt/live/" + web_fqdn + "/privkey.pem" }}
|
||||
{% endif %}
|
||||
|
||||
{% endif %}
|
||||
|
||||
{% if aria.rpc.listen_all %}
|
||||
rpc-listen-all=true
|
||||
{% else %}
|
||||
rpc-listen-all=false
|
||||
{% endif %}
|
||||
|
||||
rpc-listen-port={{ aria.rpc.port | string }}
|
||||
|
||||
{% if aria.rpc.credentials is undefined or aria.rpc.credentials == None %}
|
||||
rpc-secret={{ aria.rpc.secret | default(lookup('password', './.tmp/' + inventory_hostname + '-aria/aria.secret', chars=['ascii_lowercase', 'digits'], length=32)) }}
|
||||
{% else %}
|
||||
rpc-user={{ aria.rpc.credentials.username }}
|
||||
rpc-password={{ aria.rpc.credentials.password }}
|
||||
{% endif %}
|
||||
|
||||
{% else %}
|
||||
enable-rpc=false
|
||||
{% endif %}
|
||||
|
||||
|
||||
# (HT/SF/F)TP
|
||||
{% if aria.conn.proxy.enabled %}
|
||||
all-proxy={{ aria.conn.proxy.uri }}
|
||||
no-proxy={{ aria.conn.proxy.excluded | join(",") }}
|
||||
{% endif %}
|
||||
|
||||
max-connection-per-server={{ aria.conn.max.per_server | string }}
|
||||
split={{ aria.conn.split | string }}
|
||||
max-tries={{ aria.conn.max.attempts | string }}
|
||||
retry-wait=15
|
||||
netrc-path={{ ansible_user_home.stdout + "/.netrc" }}
|
||||
server-stat-if={{ ansible_user_home.stdout + "/.aria2/dl.log" }}
|
||||
server-stat-of={{ ansible_user_home.stdout + "/.aria2/dl.log" }}
|
||||
uri-selector={{ aria.dl.algorithm }}
|
||||
|
||||
|
||||
# HTTP
|
||||
{% if aria.http.gzip %}
|
||||
http-accept-gzip=true
|
||||
{% else %}
|
||||
http-accept-gzip=false
|
||||
{% endif %}
|
||||
|
||||
{% if aria.http.cache %}
|
||||
http-no-cache=true
|
||||
{% else %}
|
||||
http-no-cache=false
|
||||
{% endif %}
|
||||
|
||||
{% if aria.http.sustain %}
|
||||
enable-http-keep-alive=true
|
||||
{% else %}
|
||||
enable-http-keep-alive=false
|
||||
{% endif %}
|
||||
|
||||
{% if aria.http.agent is defined and aria.http.agent != None %}
|
||||
user-agent={{ aria.http.agent }}
|
||||
{% endif %}
|
||||
|
||||
|
||||
# (S)FTP
|
||||
{% if aria.ftp.mode == "passive" %}
|
||||
ftp-pasv=true
|
||||
{% elif aria.ftp.mode == "active" %}
|
||||
ftp-pasv=false
|
||||
{% endif %}
|
||||
|
||||
ftp-type={{ aria.ftp.data_type }}
|
||||
|
||||
|
||||
# METALINKS/TORRENTS
|
||||
|
||||
|
||||
# TORRENTS
|
||||
bt-detach-seed-only=true
|
||||
|
||||
{% if aria.trnt.local_discovery %}
|
||||
bt-enable-lpd=true
|
||||
{% else %}
|
||||
bt-enable-lpd=false
|
||||
{% endif %}
|
||||
|
||||
{% if aria.trnt.encrypt %}
|
||||
bt-force-encryption=true
|
||||
{% else %}
|
||||
bt-force-encryption=false
|
||||
{% endif %}
|
||||
|
||||
bt-max-peers={{ aria.trnt.peers.max }}
|
||||
|
||||
{% if aria.trnt.trackers is defined and aria.trnt.trackers != None and (aria.trnt.trackers | length) > 0 %}
|
||||
bt-tracker={{ aria.trnt.trackers | join(",") }}
|
||||
{% endif %}
|
||||
|
||||
{% if aria.trnt.dht.enabled %}
|
||||
enable-dht=true
|
||||
enable-dht6=true
|
||||
dht-file-path={{ ansible_user_home.stdout + "/.aria2/dht.dat" }}
|
||||
dht-file-path6={{ ansible_user_home.stdout + "/.aria2/dht6.dat" }}
|
||||
|
||||
{% if aria.trnt.dht.entrypoint is defined and aria.trnt.dht.entrypoint != None %}
|
||||
dht-entry-point={{ aria.trnt.dht.entrypoint }}
|
||||
dht-entry-point6={{ aria.trnt.dht.entrypoint }}
|
||||
{% endif %}
|
||||
|
||||
dht-listen-port={{ aria.trnt.dht.port | string }}
|
||||
{% endif %}
|
||||
|
||||
{% if aria.trnt.peers.agent is defined and aria.trnt.peers.agent != None %}
|
||||
peer-agent={{ aria.trnt.peers.agent }}
|
||||
{% endif %}
|
||||
|
||||
{% if aria.trnt.peers.prefix is defined and aria.trnt.peers.prefix != None %}
|
||||
peer-id-prefix={{ aria.trnt.peers.prefix }}
|
||||
{% endif %}
|
||||
|
||||
{% if aria.trnt.peers.exchange %}
|
||||
enable-peer-exchange=true
|
||||
{% else %}
|
||||
enable-peer-exchange=false
|
||||
{% endif %}
|
||||
|
||||
seed-ratio={{ aria.trnt.seeding.ratio | string }}
|
||||
seed-time={{ aria.trnt.seeding.time | string }}
|
||||
|
||||
max-overall-upload-limit={{ aria.ul.max.overall | string }}
|
||||
max-upload-limit={{ aria.ul.max.per_entry | string }}
|
||||
|
||||
# METALINK
|
||||
{% if aria.meta.follow == "mem" %}
|
||||
follow-metalink={{ aria.meta.follow }}
|
||||
{% elif aria.meta.follow %}
|
||||
follow-metalink=true
|
||||
{% else %}
|
||||
follow-metalink=false
|
||||
{% endif %}
|
||||
|
||||
metalink-language={{ aria.meta.lang }}
|
||||
|
||||
{% if aria.meta.locs is defined and aria.meta.locs != None and (aria.meta.locs | length) > 0 %}
|
||||
metalink-location={{ aria.meta.locs | join(",") }}
|
||||
{% endif %}
|
||||
|
||||
metalink-preferred-protocol={{ aria.meta.protocol_pref }}
|
||||
14
roles/init-server/templates/user/certbot.env.j2
Normal file
14
roles/init-server/templates/user/certbot.env.j2
Normal file
@@ -0,0 +1,14 @@
|
||||
CERTBOT_EMAIL="{{ certbot.email }}"
|
||||
CERTBOT_AUTHENTICATOR={{ certbot.auth_method }}
|
||||
SERVER_WEBROOT_PATH={{ ansible_user_home.stdout + "/srv/acme." + inventory_hostname }}
|
||||
{% if compose.mode == "dev" %}
|
||||
# @TODO find a better way to have processed the below in Ansible
|
||||
CERTBOT_CHALLENGE_DOMAINS={{ certbot.domains | map("regex_replace", "\\.([^\\.]*)$", ".test") | list | join(",") }}
|
||||
STAGING=1
|
||||
DEBUG=1
|
||||
VERBOSE=1
|
||||
RUN_ONCE=1
|
||||
{% elif compose.mode == "prod" %}
|
||||
CERTBOT_CHALLENGE_DOMAINS={{ certbot.domains | join(",") }}
|
||||
CRON={{ certbot.cron }}
|
||||
{% endif %}
|
||||
11
roles/init-server/templates/user/config/caddy/Caddyfile.j2
Normal file
11
roles/init-server/templates/user/config/caddy/Caddyfile.j2
Normal file
@@ -0,0 +1,11 @@
|
||||
http://<< inventory_hostname >> {
|
||||
handle /.well-known/acme-challenge/* {
|
||||
reverse_proxy localhost:80
|
||||
}
|
||||
}
|
||||
|
||||
:80 {
|
||||
root * /srv/<< inventory_hostname >>
|
||||
file_server
|
||||
encode gzip
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
[storage]
|
||||
# Storage driver - use overlay with fuse-overlayfs for rootless
|
||||
driver = "overlay"
|
||||
|
||||
# Root directory for storage (default: $HOME/.local/share/containers/storage)
|
||||
# Uncomment to customize:
|
||||
graphroot = "{{ ansible_user_home.stdout }}/volumes"
|
||||
|
||||
# Run directory for transient data
|
||||
runroot = "/run/user/1000/containers"
|
||||
|
||||
[storage.options]
|
||||
[storage.options.overlay]
|
||||
# Use fuse-overlayfs for rootless overlay support on older kernels
|
||||
mount_program = "/usr/bin/fuse-overlayfs"
|
||||
339
roles/init-server/templates/user/config/glance/glance.yml.j2
Normal file
339
roles/init-server/templates/user/config/glance/glance.yml.j2
Normal file
@@ -0,0 +1,339 @@
|
||||
server:
|
||||
port: {{ glance.port }}
|
||||
{% if glance.proxied %}
|
||||
proxied: true
|
||||
{% endif %}
|
||||
base-url: /
|
||||
pages:
|
||||
- name: home
|
||||
head-widgets:
|
||||
- type: search
|
||||
search-engine: {{ glance.search.engine }}
|
||||
bangs:
|
||||
- title: Linux Kernel
|
||||
shortcut: "@linuxkernel"
|
||||
url: "https://www.kernel.org/doc/html/latest/search.html?q={QUERY}"
|
||||
- title: Linux
|
||||
shortcut: "@linux"
|
||||
url: https://cse.google.com/cse?cx=017644269519104757279%3Agm62gtzaoky&q={QUERY}&sa=go
|
||||
- title: Debian
|
||||
shortcut: "@deb"
|
||||
url: https://search.debian.org/cgi-bin/omega?DB=en&P={QUERY}
|
||||
- title: C++
|
||||
shortcut: "@cpp"
|
||||
url: https://learn.microsoft.com/en-us/search/?scope=C%2B%2B&view=msvc-170&terms={QUERY}
|
||||
- title: Rust
|
||||
shortcut: "@rust"
|
||||
url: https://doc.rust-lang.org/book/?search={QUERY}
|
||||
- title: Python
|
||||
shortcut: "@python"
|
||||
url: https://docs.python.org/3/search.html?check_keywords=yes&area=default&q={QUERY}
|
||||
- title: Python Click
|
||||
shortcut: "@pyclick"
|
||||
url: https://click.palletsprojects.com/en/stable/search/?q={QUERY}
|
||||
- title: Ansible
|
||||
shortcut: "@ansible"
|
||||
url: https://docs.ansible.com/projects/ansible/latest/search.html?q={QUERY}&check_keywords=yes&area=default
|
||||
- title: Podman
|
||||
shortcut: "@podman"
|
||||
url: https://docs.podman.io/en/latest/search.html?q={QUERY}
|
||||
- title: Podman Compose
|
||||
shortcut: "@podcompose"
|
||||
url: https://docs.podman.io/en/latest/search.html?q={QUERY}
|
||||
- title: Elixir
|
||||
shortcut: "@elixir"
|
||||
url: https://hexdocs.pm/?packages=elixir%3A1.20.2%2Ceex%3A1.20.2%2Cex_unit%3A1.20.2%2Ciex%3A1.20.2%2Clogger%3A1.20.2%2Cmix%3A1.20.2&q={QUERY}
|
||||
- title: Elixir Phoenix
|
||||
shortcut: "@exphoenix"
|
||||
url: https://hexdocs.pm/?q={QUERY}&packages=plug%3Alatest%2Cphoenix%3Alatest%2Cphoenix_html%3Alatest%2Cphoenix_live_view%3Alatest%2Cphoenix_pubsub%3Alatest%2Cphoenix_template%3Alatest
|
||||
- title: Javascript
|
||||
shortcut: "@js"
|
||||
shortcut: https://javascript.info/search?query={QUERY}
|
||||
- title: MDN
|
||||
shortcut: "@mdn"
|
||||
url: https://developer.mozilla.org/en-US/search?q={QUERY}
|
||||
- title: PHP
|
||||
shortcut: "@php"
|
||||
url: https://www.php.net/search.php#gsc.tab=0&gsc.q={QUERY}&gsc.sort=
|
||||
- title: PostgreSQL
|
||||
shortcut: "@pgsql"
|
||||
url: https://www.postgresql.org/search/?q={QUERY}
|
||||
- title: MySQL
|
||||
shortcut: "@mysql"
|
||||
url: https://dev.mysql.com/doc/search/?q={QUERY}
|
||||
- title: Julia
|
||||
shortcut: "@julia"
|
||||
url: https://docs.julialang.org/en/v1/?q={QUERY}
|
||||
- title: Gitea
|
||||
shortcut: "@gitea"
|
||||
url: https://docs.gitea.com/search/?q={QUERY}
|
||||
- title: Git
|
||||
shortcut: "@git"
|
||||
url: https://git-scm.com/search/results?search={QUERY}&language=en
|
||||
- title: Elixir Phoenix
|
||||
shortcut: "@exphoenix"
|
||||
url: https://hexdocs.pm/?q={QUERY}&packages=plug%3Alatest%2Cphoenix%3Alatest%2Cphoenix_html%3Alatest%2Cphoenix_live_view%3Alatest%2Cphoenix_pubsub%3Alatest%2Cphoenix_template%3Alatest
|
||||
# @TODO add more documentation searches
|
||||
- type: group
|
||||
widgets:
|
||||
- type: clock
|
||||
hour-format: 24h
|
||||
timezones:
|
||||
- timezone: {{ glance.timezone.id}}
|
||||
label: {{ glance.timezone.name }}
|
||||
- type: weather
|
||||
units: metric
|
||||
hour-format: 24h
|
||||
location: {{ glance.weather_loc }}
|
||||
columns:
|
||||
- size: small
|
||||
widgets:
|
||||
- type: calendar
|
||||
first-day-of-week: sunday
|
||||
- type: bookmarks
|
||||
groups:
|
||||
- title: strat
|
||||
links:
|
||||
- title: The New Oil
|
||||
url: https://thenewoil.org/en/
|
||||
- title: Resilient by Design
|
||||
url: https://theanarchistlibrary.org/library/the-techno-anarchist-resilient-by-design
|
||||
- title: complang dox
|
||||
links:
|
||||
- name: Raspberry Pi
|
||||
url: https://www.raspberrypi.com/documentation/
|
||||
- name: Arduino
|
||||
url: https://docs.arduino.cc/
|
||||
- name: NASM x86 Assembly
|
||||
url: https://www.tutorialspoint.com/assembly_programming/index.htm
|
||||
- name: WASM
|
||||
url: https://webassembly.org/docs/faq/
|
||||
- name: Linux Kernel
|
||||
url: https://www.kernel.org/doc/html/latest/index.html
|
||||
- name: Linux
|
||||
url: https://tldp.org/guides.html
|
||||
- name: Debian
|
||||
url: https://www.debian.org/doc/
|
||||
- name: Zig
|
||||
url: https://ziglang.org/documentation/
|
||||
- name: Rust
|
||||
url: https://doc.rust-lang.org/
|
||||
- name: Cargo
|
||||
url: https://doc.rust-lang.org/cargo/
|
||||
- name: C++
|
||||
url: https://learn.microsoft.com/en-us/cpp/
|
||||
- name: vcpkg
|
||||
url: https://learn.microsoft.com/en-us/vcpkg/
|
||||
- name: C#
|
||||
url: https://learn.microsoft.com/en-us/dotnet/csharp/
|
||||
- name: nuget
|
||||
url: https://learn.microsoft.com/en-us/nuget/
|
||||
- name: Python
|
||||
url: https://docs.python.org/
|
||||
- name: Python uv
|
||||
url: https://docs.astral.sh/uv/
|
||||
- name: Ansible
|
||||
url: https://docs.ansible.com/projects/ansible/latest/
|
||||
- name: Podman
|
||||
url: https://docs.podman.io/en/latest/
|
||||
- name: Podman Compose
|
||||
url: https://docs.podman.io/en/latest/markdown/podman-compose.1.html
|
||||
- name: Erlang
|
||||
url: https://www.erlang.org/docs.html
|
||||
- name: Elixir
|
||||
url: https://elixir-lang.org/docs.html
|
||||
- name: Hex
|
||||
url: https://hex.pm/docs/usage
|
||||
- name: Lua
|
||||
url: https://www.lua.org/docs.html
|
||||
- name: LuaRocks
|
||||
url: https://luarocks.org/docs
|
||||
- name: GDScript
|
||||
url: https://docs.godotengine.org/en/latest/tutorials/scripting/gdscript/index.html
|
||||
- name: Julia
|
||||
url: https://docs.julialang.org/
|
||||
- name: NodeJS
|
||||
url: https://nodejs.org/docs/latest/api/
|
||||
- name: NPMJS
|
||||
url: https://docs.npmjs.com/
|
||||
- name: Go
|
||||
url: https://go.dev/doc/
|
||||
- name: CSS
|
||||
url: https://www.w3.org/Style/CSS/Overview.en.html
|
||||
- name: HTML
|
||||
url: https://html.spec.whatwg.org/multipage/
|
||||
- name: Javascript
|
||||
url: https://javascript.info/
|
||||
- name: Javascript DOM
|
||||
url: https://dom.spec.whatwg.org/
|
||||
- name: JSON
|
||||
url: https://www.json.org/json-en.html
|
||||
- name: Client-Side Web Languages
|
||||
url: https://developer.mozilla.org/en-US/
|
||||
- name: PHP
|
||||
url: https://www.php.net/docs.php
|
||||
- name: PHP Composer
|
||||
url: https://getcomposer.org/doc/
|
||||
- name: SQL
|
||||
url: https://www.postgresql.org/docs/current/sql.html
|
||||
- name: SASS
|
||||
url: https://sass-lang.com/documentation/
|
||||
- name: YAML
|
||||
url: https://www.yaml.info/
|
||||
- name: TOML
|
||||
url: https://toml.io/en/
|
||||
- name: ActivityPub
|
||||
url: https://activitypub.rocks/
|
||||
- name: SuperCollider
|
||||
url: https://doc.sccode.org/
|
||||
- name: CSound
|
||||
url: https://csound.com/docs/manual/index.html
|
||||
- name: FAUST
|
||||
url: https://faustdoc.grame.fr/
|
||||
- name: regexp
|
||||
url: https://regexbox.com/cheatsheet
|
||||
- title: warez dox
|
||||
links:
|
||||
- name: glance
|
||||
url: https://github.com/glanceapp/glance/tree/main/docs
|
||||
- name: Nextcloud
|
||||
url: https://docs.nextcloud.com/
|
||||
- name: Wireguard
|
||||
url: https://www.wireguard.com/#conceptual-overview
|
||||
- name: Headscale
|
||||
url: https://docs.headscale.org/
|
||||
- name: Tailscale
|
||||
url: https://tailscale.com/docs
|
||||
- name: Gitea
|
||||
url: https://docs.gitea.com/
|
||||
- name: OpenGist
|
||||
url: https://opengist.io/docs/
|
||||
- name: Caddy
|
||||
url: https://caddyserver.com/docs/
|
||||
- name: MySQL
|
||||
url: https://dev.mysql.com/doc/
|
||||
- name: Certbot
|
||||
url: https://eff-certbot.readthedocs.io/en/stable/
|
||||
- name: git
|
||||
url: https://git-scm.dev/doc
|
||||
# - title: api
|
||||
# - title: src
|
||||
# - title: warez
|
||||
- size: full
|
||||
widgets:
|
||||
- type: split-column
|
||||
widgets:
|
||||
- type: rss
|
||||
title: technoscience
|
||||
style: detailed-list
|
||||
collapse-after: 5
|
||||
feeds:
|
||||
- url: https://feeds.arstechnica.com/arstechnica/features
|
||||
title: arstechnica
|
||||
- url: https://rss.slashdot.org/Slashdot/slashdotMain
|
||||
title: slashdot
|
||||
- url: https://torrentfreak.com/feed/
|
||||
title: torrentfreak
|
||||
- url: https://blog.p2pfoundation.net/feed/
|
||||
title: p2p foundation
|
||||
- url: https://www.wired.com/feed/category/backchannel/latest/rss
|
||||
title: wired
|
||||
- url: https://www.quantamagazine.org/feed/
|
||||
title: quanta
|
||||
- url: https://www.sciencedaily.com/rss/matter_energy/telecommunications.xml
|
||||
title: scidaily - telecomms
|
||||
- url: https://www.sciencedaily.com/rss/computers_math/quantum_computers.xml
|
||||
title: scidaily - quancomp
|
||||
- url: https://www.sciencedaily.com/rss/matter_energy/engineering_and_construction.xml
|
||||
title: scidaily - engi
|
||||
- url: https://www.sciencedaily.com/rss/matter_energy/energy_and_resources.xml
|
||||
title: scidaily - energy & fuel
|
||||
- url: https://www.sciencedaily.com/rss/earth_climate/energy.xml
|
||||
title: scidaily - climate change
|
||||
- url: https://www.sciencedaily.com/rss/earth_climate/global_warming.xml
|
||||
title: scidaily - global warming
|
||||
- url: https://www.sciencedaily.com/rss/earth_climate/sustainability.xml
|
||||
title: scidaily - sustainability
|
||||
- url: https://www.sciencedaily.com/rss/computers_math/computer_programming.xml
|
||||
title: scidaily - compprog
|
||||
- url: https://www.sciencedaily.com/rss/computers_math/information_technology.xml
|
||||
title: scidaily - infotech
|
||||
- url: https://phys.org/rss-feed/biology-news/ecology/
|
||||
title: phys - ecology
|
||||
- type: rss
|
||||
title: politics
|
||||
style: detailed-list
|
||||
collapse-after: 5
|
||||
feeds:
|
||||
- url: https://www.democracynow.org/democracynow.rss
|
||||
title: democracy now
|
||||
- url: https://www.nakedcapitalism.com/feed
|
||||
title: naked capitalism
|
||||
- url: https://www.thenews.coop/feed/
|
||||
title: co-operative news
|
||||
- url: http://feeds.propublica.org/propublica/main
|
||||
title: propublica
|
||||
- url: https://unicornriot.ninja/feed/rss/
|
||||
title: unicorn riot
|
||||
- url: https://crimethinc.com/feed
|
||||
title: crimethinc
|
||||
- url: https://anarchistnews.org/rss.xml
|
||||
title: anarchist news
|
||||
- type: rss
|
||||
title: misc
|
||||
style: detailed-list
|
||||
collapse-after: 5
|
||||
feeds:
|
||||
- url: https://www.radicalphilosophy.com/feed
|
||||
title: radical philosophy
|
||||
- url: http://spectrejournal.com/feed/rss
|
||||
title: spectre
|
||||
- url: https://nautil.us/feed
|
||||
title: nautilus
|
||||
- url: https://theconversation.com/us/home-page/articles.atom
|
||||
title: the conversation
|
||||
- url: https://thebaffler.com/latest/feed
|
||||
title: the baffler
|
||||
- type: videos
|
||||
style: horizontal-cards
|
||||
channels:
|
||||
- UCjEDZ_R_ypSc-MUBRkiW1lw
|
||||
- UCIZ5ZOeiXYbmKTl_85ghNPw
|
||||
- UCdcemy56JtVTrsFIOoqvV8g
|
||||
- UCSkzHxIcfoEr69MWBdo0ppg
|
||||
- UCW6TXMZ5Pq6yL6_k5NZ2e0Q
|
||||
- UC4a-Gbdw7vOaccHmFo40b9g
|
||||
- UCwbyKKmjVdCpWzZZY-WnajA
|
||||
- UCMMBpWfWUd3xlcOxrot_neA
|
||||
- UCJXa3_WNNmIpewOtCHf3B0g
|
||||
- UCmfF7JZv26UUKyRedViGIlw
|
||||
- UCEmQRq5bxIUNGvAWj41AoaA
|
||||
- UCHkYOD-3fZbuGhwsADBd9ZQ
|
||||
- UCHa8J-xnRYOg5VuudfWpBgg
|
||||
- UCJZv4d5rbIKd4QHMPkcABCw
|
||||
- UCZUyPT9DkJWmS_DzdOi7RIA
|
||||
- UChbS_z6KHQiIu9et38O37eQ
|
||||
- UCxX9wt5FWQUAAz4UrysqK9A
|
||||
- UCX6b17PVsYBQ0ip5gyeme-Q
|
||||
- UCk0fGHsCEzGig-rSzkfCjMw
|
||||
- UCYO_jab_esuFRV4b17AJtAw
|
||||
- UChKIQpndVpX1ung-7IkGhzA
|
||||
- UCaM7SQvF5q9sz4NgL16PNRA
|
||||
- UC7pdnrWVj8eDfCI0bRe_0kQ
|
||||
- UCtuXekfqj-paqsxtqVNCC2A
|
||||
- UCgkjg1UbcQZHW40IO1BEt5A
|
||||
- UCGKEMK3s-ZPbjVOIuAV8clQ
|
||||
- UCbiGcwDWZjz05njNPrJU7jA
|
||||
- UC6biysICWOJ-C3P4Tyeggzg
|
||||
- UCbi3ei431gvBpgZ3R-_Wk5Q
|
||||
- UCA5yXa0rDsGaJFOuj6pxw1w
|
||||
- UCDG73pGqESS1XcEVY_0xwWw
|
||||
- UCR2uRTQ53V_egXKFflMMaaw
|
||||
- UCzGUT9PjV3SMBwjWXUYh4HA
|
||||
- name: services
|
||||
columns:
|
||||
- size: full
|
||||
widgets:
|
||||
- type: docker-containers
|
||||
title: status
|
||||
hide-by-default: false
|
||||
@@ -0,0 +1,9 @@
|
||||
db-uri: {{ gist.db.type + "://" + mysql.users.admin.username + ":" + mysql.users.admin.password + "@localhost:3306/" + mysql.users.admin.databases.opengist.name }}
|
||||
{% if mode == "dev" %}
|
||||
log-level: debug
|
||||
{% else %}
|
||||
log-level: info
|
||||
{% endif %}
|
||||
custom.static-links:
|
||||
- name: Playbooks
|
||||
path: {{ "https://" + gitea.subdomain + "." + web_fqdn + "/admin/skato-ansible" }}
|
||||
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"TCP": {
|
||||
<% if mode == "prod" %>
|
||||
"443": {
|
||||
"HTTPS": true
|
||||
}
|
||||
<% elif mode == "dev" or tailscale.scheme == "http" %>
|
||||
"80": {
|
||||
"HTTPS": false
|
||||
}
|
||||
<% endif %>
|
||||
},
|
||||
"Web": {
|
||||
<% if mode == "prod" %>
|
||||
"${TS_CERT_DOMAIN}:443": {
|
||||
"Handlers": {
|
||||
"/": {
|
||||
"Proxy": "http://localhost:8080"
|
||||
}
|
||||
}
|
||||
}
|
||||
<% elif mode == "dev" or tailscale.scheme == "http" %>
|
||||
"${TS_CERT_DOMAIN}:80": {
|
||||
"Handlers": {
|
||||
"/": {
|
||||
"Proxy": "http://localhost:8080"
|
||||
}
|
||||
}
|
||||
}
|
||||
<% endif %>
|
||||
},
|
||||
"AllowFunnel": {
|
||||
<% if mode == "prod" %>
|
||||
"${TS_CERT_DOMAIN}:443": false
|
||||
<% elif mode == "dev" or tailscale.scheme == "http" %>
|
||||
"${TS_CERT_DOMAIN}:80": false
|
||||
<% endif %>
|
||||
}
|
||||
}
|
||||
10
roles/init-server/templates/user/email.env.j2
Normal file
10
roles/init-server/templates/user/email.env.j2
Normal file
@@ -0,0 +1,10 @@
|
||||
{% if email.smtp is defined or email.smtp != None %}
|
||||
EMAIL_SEND_PROTOCOL=smtp
|
||||
EMAIL_SMTP_HOST={{ email.smtp.host }}
|
||||
EMAIL_SMTP_PORT={{ email.smtp.port }}
|
||||
EMAIL_SMTP_SECURE={{ email.smtp.conn_mode }}
|
||||
EMAIL_SMTP_USERNAME={{ email.smtp.username }}
|
||||
EMAIL_SMTP_AUTHTYPE={{ email.smtp.auth_meth.upper() }}
|
||||
EMAIL_SMTP_USER_ALIAS={{ (email.smtp.alias | split("@"))[0] }}
|
||||
EMAIL_SMTP_EMAIL_ALIAS={{ (email.smtp.alias | split("@"))[1] }}
|
||||
{% endif %}
|
||||
@@ -38,7 +38,7 @@ tasks:
|
||||
populate_folders:
|
||||
{% if download_mode == 'direct' %}
|
||||
proxy:
|
||||
https: 'socks5://<< sox.hostname >>:<< sox.port >>'
|
||||
https: 'socks5://<< tor.proxy.hostname >>:<< tor.proxy.port >>'
|
||||
{% endif %}
|
||||
if:
|
||||
- "'batch' in title.lower()": reject
|
||||
@@ -63,16 +63,19 @@ tasks:
|
||||
template: limited_series
|
||||
{% if flexget.download_mode == 'aria2' %}
|
||||
aria2:
|
||||
server: << aria.hostname >>
|
||||
port: << aria.port >>
|
||||
{% if aria.secret != None or aria.secret is defined %}
|
||||
secret: << aria.secret >>
|
||||
server: << aria.rpc.hostname >>
|
||||
port: << aria.rpc.port >>
|
||||
{% if aria.rpc.secret != None and aria.rpc.secret is defined %}
|
||||
secret: << aria.rpc.secret >>
|
||||
{% elif aria.rpc.credentials != None and aria.rpc.credentials is defined %}
|
||||
username: << aria.rpc.credentials.username >>
|
||||
password: << aria.rpc.credentials.password >>
|
||||
{% endif %}
|
||||
{% if aria.credentials != None or aria.credentials is defined %}
|
||||
username: << aria.credentials.username >>
|
||||
password: << aria.credentials.password >>
|
||||
{% if mode == 'prod' %}
|
||||
scheme: << aria.rpc.scheme >>
|
||||
{% else %}
|
||||
scheme: http
|
||||
{% endif %}
|
||||
scheme: << aria.scheme >>
|
||||
rpc_mode: json
|
||||
rpc_path: jsonrpc
|
||||
path: '~/downloads/media/vids/{{ series_name }}'
|
||||
@@ -85,21 +88,25 @@ tasks:
|
||||
fap_queue:
|
||||
{% if download_mode == 'direct' %}
|
||||
proxy:
|
||||
https: 'socks5://<< sox.hostname >>:<< sox.port >>'
|
||||
https: 'socks5://<< tor.proxy.hostname >>:<< tor.proxy.port >>'
|
||||
{% endif %}
|
||||
template: porn_vids
|
||||
{% if flexget.download_mode == 'aria2' %}
|
||||
aria2:
|
||||
server: << aria.hostname >>
|
||||
port: << aria.port >>
|
||||
{% if aria.secret != None or aria.secret is defined %}
|
||||
secret: << aria.secret >>
|
||||
server: << aria.rpc.hostname >>
|
||||
port: << aria.rpc.port >>
|
||||
{% if aria.rpc.secret != None and aria.rpc.secret is defined %}
|
||||
secret: << aria.rpc.secret >>
|
||||
{% endif %}
|
||||
{% if aria.credentials != None or aria.credentials is defined %}
|
||||
username: << aria.credentials.username >>
|
||||
password: << aria.credentials.password >>
|
||||
{% if aria.rpc.credentials != None and aria.rpc.credentials is defined %}
|
||||
username: << aria.rpc.credentials.username >>
|
||||
password: << aria.rpc.credentials.password >>
|
||||
{% endif %}
|
||||
{% if mode == 'prod' %}
|
||||
scheme: << aria.rpc.scheme >>
|
||||
{% else %}
|
||||
scheme: http
|
||||
{% endif %}
|
||||
scheme: << aria.scheme >>
|
||||
rpc_mode: json
|
||||
rpc_path: jsonrpc
|
||||
path: ~/downloads/.xxx/media/vids
|
||||
@@ -112,21 +119,25 @@ tasks:
|
||||
film_queue:
|
||||
{% if download_mode == 'direct' %}
|
||||
proxy:
|
||||
https: 'socks5://<< sox.hostname >>:<< sox.port >>'
|
||||
https: 'socks5://<< tor.proxy.hostname >>:<< tor.proxy.port >>'
|
||||
{% endif %}
|
||||
template: feature_films
|
||||
{% if flexget.download_mode == 'aria2' %}
|
||||
aria2:
|
||||
server: << aria.hostname >>
|
||||
port: << aria.port >>
|
||||
{% if aria.secret != None or aria.secret is defined %}
|
||||
secret: << aria.secret >>
|
||||
server: << aria.rpc.hostname >>
|
||||
port: << aria.rpc.port >>
|
||||
{% if aria.rpc.secret != None or aria.rpc.secret is defined %}
|
||||
secret: << aria.rpc.secret >>
|
||||
{% endif %}
|
||||
{% if aria.credentials != None or aria.credentials is defined %}
|
||||
username: << aria.credentials.username >>
|
||||
password: << aria.credentials.password >>
|
||||
{% if aria.rpc.credentials != None or aria.rpc.credentials is defined %}
|
||||
username: << aria.rpc.credentials.username >>
|
||||
password: << aria.rpc.credentials.password >>
|
||||
{% endif %}
|
||||
{% if mode == 'prod' %}
|
||||
scheme: << aria.rpc.scheme >>
|
||||
{% else %}
|
||||
scheme: http
|
||||
{% endif %}
|
||||
scheme: << aria.scheme >>
|
||||
rpc_mode: json
|
||||
rpc_path: jsonrpc
|
||||
path: ~/downloads/media/vids
|
||||
|
||||
17
roles/init-server/templates/user/gitea.env.j2
Normal file
17
roles/init-server/templates/user/gitea.env.j2
Normal file
@@ -0,0 +1,17 @@
|
||||
GITEA_MODE={{ mode | default("dev") }}
|
||||
GITEA_NAME={{ (web_fqdn | split("."))[0].upper() + " Nous" }}
|
||||
GITEA_SSH_PORT={{ gitea.ssh.port }}
|
||||
GITEA_LANDING={{ gitea.site.landing }}
|
||||
GITEA_TRUSTED_PROXIES={{ gitea.trusted.proxies | join(",") }}
|
||||
|
||||
{% if gitea.site.registration.enabled %}
|
||||
GITEA_PROHIBIT_REGISTRATION=false
|
||||
{% else %}
|
||||
GITEA_PROHIBIT_REGISTRATION=true
|
||||
{% endif %}
|
||||
|
||||
GITEA_DB_TYPE={{ gitea.db.type }}
|
||||
|
||||
{% if gitea.db.type == "mysql" %}
|
||||
GITEA_DB_NAME={{ gitea.db.name }}
|
||||
{% endif %}
|
||||
12
roles/init-server/templates/user/journal/blog/_index.md.j2
Normal file
12
roles/init-server/templates/user/journal/blog/_index.md.j2
Normal file
@@ -0,0 +1,12 @@
|
||||
+++
|
||||
title = '{{ web_fqdn }}'
|
||||
draft = false
|
||||
+++
|
||||
|
||||

|
||||
|
||||
## Under Construction
|
||||
|
||||
### Err. 503: Service Unavailable
|
||||
|
||||
Working on building or migrating the content, layout or theme for this blog.
|
||||
11
roles/init-server/templates/user/journal/notes/index.md.j2
Normal file
11
roles/init-server/templates/user/journal/notes/index.md.j2
Normal file
@@ -0,0 +1,11 @@
|
||||
---
|
||||
title: {{ web_fqdn }}
|
||||
---
|
||||
|
||||

|
||||
|
||||
## Under Construction
|
||||
|
||||
### Err. 503: Service Unavailable
|
||||
|
||||
Working on building or migrating Obsidian vault entries for this server.
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.1 MiB |
3
roles/init-server/templates/user/mysql.env.j2
Normal file
3
roles/init-server/templates/user/mysql.env.j2
Normal file
@@ -0,0 +1,3 @@
|
||||
MYSQL_DB_HOST=localhost
|
||||
MYSQL_DB_USER={{ mysql.users.admin.username }}
|
||||
MYSQL_DB_NAME={{ mysql.users.admin.databases.init.name }}
|
||||
3
roles/init-server/templates/user/netrc.j2
Normal file
3
roles/init-server/templates/user/netrc.j2
Normal file
@@ -0,0 +1,3 @@
|
||||
machine {{ source_code.host }}
|
||||
login {{ source_code.user }}
|
||||
password {{ source_code.http_password }}
|
||||
19
roles/init-server/templates/user/nextcloud.env.j2
Normal file
19
roles/init-server/templates/user/nextcloud.env.j2
Normal file
@@ -0,0 +1,19 @@
|
||||
{% if nextcloud.db.type == "mysql" or nextcloud.db.type == "mariadb" %}
|
||||
NEXTCLOUD_DB_NAME={{ nextcloud.db.name | default("nextcloud") }}
|
||||
{% elif nextcloud.db.type == "sqlite" %}
|
||||
SQLITE_DATABASE={{ nextcloud.db.name + ".db" }}
|
||||
{% endif %}
|
||||
|
||||
{% if not nextcloud.rewrite_ip %}
|
||||
NEXTCLOUD_APACHE_DISABLE_REWRITE_IP=1
|
||||
{% endif %}
|
||||
|
||||
NEXTCLOUD_TRUSTED_PROXIES={{ nextcloud.trusted.proxies | join(" ") }}
|
||||
NEXTCLOUD_TRUSTED_FQDNS={{ "cloud." + web_fqdn }}
|
||||
{% if compose.mode == "prod" %}
|
||||
NEXTCLOUD_URL_REWRITE={{ "https://cloud." + web_fqdn }}
|
||||
NEXTCLOUD_PROTOCOL_REWRITE=https
|
||||
{% elif compose.mode == "dev" %}
|
||||
NEXTCLOUD_URL_REWRITE={{ "http://cloud." + web_fqdn }}
|
||||
NEXTCLOUD_PROTOCOL_REWRITE=http
|
||||
{% endif %}
|
||||
18
roles/init-server/templates/user/opengist.env.j2
Normal file
18
roles/init-server/templates/user/opengist.env.j2
Normal file
@@ -0,0 +1,18 @@
|
||||
OG_DB_TYPE={{ gist.db.type }}
|
||||
|
||||
{% if gist.db.type == "mysql" %}
|
||||
OG_DB_NAME={{ gist.db.name }}
|
||||
{% endif %}
|
||||
|
||||
OG_SEARCH_DEFAULT={{ gist.search.priority | join(",") }}
|
||||
|
||||
{% if ssh is defined and ssh != None %}
|
||||
OG_SSH_PORT={{ gist.ssh.port }}
|
||||
OG_SSH_GIT_ENABLED=true
|
||||
{% else %}
|
||||
OG_SSH_GIT_ENABLED=false
|
||||
{% endif %}
|
||||
|
||||
OG_NAME={{ (web_fqdn | split("."))[0].upper() + " Grimoire" }}
|
||||
OG_LOGO=logo.svg
|
||||
OG_FAVICON=logo.ico
|
||||
1
roles/init-server/templates/user/redis.env.j2
Normal file
1
roles/init-server/templates/user/redis.env.j2
Normal file
@@ -0,0 +1 @@
|
||||
REDIS_PARAMS={{ "--requirepass " + redis.password + " --appendonly yes" }}
|
||||
@@ -56,7 +56,7 @@ set wildmenu
|
||||
|
||||
" Make wildmenu behave like similar to Bash completion.
|
||||
set wildmode=list:longest
|
||||
{% if vimrc.typed_paths.ignore is defined or vimrc.typed_paths.ignore != None %}
|
||||
{% if vimrc.typed_paths.ignore is defined and vimrc.typed_paths.ignore != None %}
|
||||
|
||||
" There are certain files that we would never want to edit with Vim.
|
||||
" Wildmenu will ignore files with these extensions.
|
||||
|
||||
22
roles/init-server/templates/usr/local/bin/dsnet-forward.sh.j2
Executable file
22
roles/init-server/templates/usr/local/bin/dsnet-forward.sh.j2
Executable file
@@ -0,0 +1,22 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
if [[ "$1" == "start" ]]; then
|
||||
/usr/sbin/iptables -A FORWARD -i dsnet -p tcp --sport 80 -j ACCEPT # HTTP
|
||||
/usr/sbin/iptables -A FORWARD -i dsnet -p tcp --sport 443 -j ACCEPT # HTTPS (HTTP + SSL/TLS)
|
||||
/usr/sbin/iptables -A FORWARD -i dsnet -p udp --sport 443 -j ACCEPT # HTTPS (HTTP + SSL/TLS)
|
||||
/usr/sbin/iptables -A FORWARD -i dsnet -p tcp --sport 465 -j ACCEPT # SMTP (send)
|
||||
/usr/sbin/iptables -A FORWARD -i dsnet -p tcp --sport 587 -j ACCEPT # SMTP (send)
|
||||
/usr/sbin/iptables -A FORWARD -i dsnet -p tcp --sport 995 -j ACCEPT # POP3 (receive)
|
||||
/usr/sbin/iptables -A FORWARD -i dsnet -p tcp --sport 993 -j ACCEPT # IMAP (receive)
|
||||
/usr/sbin/iptables -t nat -A POSTROUTING -o dsnet -j MASQUERADE
|
||||
elif [[ "$1" == "stop" ]]; then
|
||||
/usr/sbin/iptables -D FORWARD -i dsnet -p tcp --sport 80 -j ACCEPT # HTTP
|
||||
/usr/sbin/iptables -D FORWARD -i dsnet -p tcp --sport 443 -j ACCEPT # HTTPS (HTTP + SSL/TLS)
|
||||
/usr/sbin/iptables -D FORWARD -i dsnet -p udp --sport 443 -j ACCEPT # HTTPS (HTTP + SSL/TLS)
|
||||
/usr/sbin/iptables -D FORWARD -i dsnet -p tcp --sport 465 -j ACCEPT # SMTP (send)
|
||||
/usr/sbin/iptables -D FORWARD -i dsnet -p tcp --sport 587 -j ACCEPT # SMTP (send)
|
||||
/usr/sbin/iptables -D FORWARD -i dsnet -p tcp --sport 995 -j ACCEPT # POP3 (receive)
|
||||
/usr/sbin/iptables -D FORWARD -i dsnet -p tcp --sport 993 -j ACCEPT # IMAP (receive)
|
||||
/usr/sbin/iptables -t nat -D POSTROUTING -o dsnet -j MASQUERADE
|
||||
fi
|
||||
Reference in New Issue
Block a user