feat: refactor, deploy and provisioning
This commit is contained in:
parent
a9639a9340
commit
31bed3964b
13 changed files with 404 additions and 205 deletions
25
install.sh
25
install.sh
|
@ -1,6 +1,21 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
##
|
||||
# Source Code
|
||||
|
||||
# We store all initial configs in the /srv location
|
||||
cd /srv
|
||||
|
||||
# Clone if not yet cloned
|
||||
if [ ! -d .git ]; then
|
||||
git clone https://code.tjo.space/tjo-cloud/ingress.git .
|
||||
else
|
||||
git pull
|
||||
fi
|
||||
|
||||
##
|
||||
# Metadata
|
||||
SERVICE_NAME="ingress.tjo.cloud"
|
||||
SERVICE_VERSION="$(git describe --tags --always --dirty)"
|
||||
CLOUD_REGION="$(hostname -s)"
|
||||
|
@ -26,11 +41,11 @@ mkdir -p /etc/apt/keyrings/
|
|||
wget -q -O - https://apt.grafana.com/gpg.key | gpg --dearmor | tee /etc/apt/keyrings/grafana.gpg >/dev/null
|
||||
echo "deb [signed-by=/etc/apt/keyrings/grafana.gpg] https://apt.grafana.com stable main" | tee /etc/apt/sources.list.d/grafana.list
|
||||
apt update -y
|
||||
apt get install -y alloy
|
||||
apt install -y alloy
|
||||
|
||||
##
|
||||
# Copy Sysmtemd service/units
|
||||
cp -r root/etc/systemd/* /
|
||||
#cp -r root/etc/systemd/* /
|
||||
|
||||
##
|
||||
# Ensure services are enabled
|
||||
|
@ -55,10 +70,10 @@ systemctl reload alloy
|
|||
|
||||
##
|
||||
# Configure NGINX
|
||||
cp -r root/etc/nginx/* /etc/nginx/
|
||||
#cp -r root/etc/nginx/* /etc/nginx/
|
||||
systemctl reload nginx
|
||||
|
||||
##
|
||||
# Configure Webhook
|
||||
cp -r root/etc/webhook/* /etc/webhook/
|
||||
systemctl reload webhook
|
||||
#cp -r root/etc/webhook/* /etc/webhook/
|
||||
systemctl restart webhook
|
||||
|
|
46
justfile
46
justfile
|
@ -10,6 +10,10 @@ lint:
|
|||
@tofu fmt -check -recursive .
|
||||
@tflint --recursive
|
||||
|
||||
format:
|
||||
@tofu fmt -recursive .
|
||||
@tflint --recursive
|
||||
|
||||
deploy:
|
||||
#!/usr/bin/env sh
|
||||
cd {{justfile_directory()}}/terraform
|
||||
|
@ -20,3 +24,45 @@ destroy:
|
|||
#!/usr/bin/env sh
|
||||
cd {{justfile_directory()}}/terraform
|
||||
tofu destroy
|
||||
|
||||
# Create a list of blocked IP ranges. Traffic we don't want.
|
||||
ingress-blocked-list:
|
||||
#!/usr/bin/env bash
|
||||
GOOGLE_BOT_IPV4=$(curl -s https://raw.githubusercontent.com/lord-alfred/ipranges/main/googlebot/ipv4_merged.txt)
|
||||
GOOGLE_BOT_IPV6=$(curl -s https://raw.githubusercontent.com/lord-alfred/ipranges/main/googlebot/ipv6_merged.txt)
|
||||
echo "# GOOGLE_BOT IPV4 $(echo $GOOGLE_BOT_IPV4 | wc -w)"
|
||||
echo "# GOOGLE_BOT IPV6 $(echo $GOOGLE_BOT_IPV6 | wc -w)"
|
||||
|
||||
BING_BOT_IPV4=$(curl -s https://raw.githubusercontent.com/lord-alfred/ipranges/main/bing/ipv4_merged.txt)
|
||||
echo "# BING_BOT IPV4 $(echo $BING_BOT_IPV4 | wc -w)"
|
||||
|
||||
OPENAI_IPV4=$(curl -s https://raw.githubusercontent.com/lord-alfred/ipranges/main/openai/ipv4_merged.txt)
|
||||
echo "# OPENAI IPV4 $(echo $OPENAI_IPV4 | wc -w)"
|
||||
|
||||
FACEBOOK_IPV4=$(curl -s https://raw.githubusercontent.com/lord-alfred/ipranges/main/facebook/ipv4_merged.txt)
|
||||
FACEBOOK_IPV6=$(curl -s https://raw.githubusercontent.com/lord-alfred/ipranges/main/facebook/ipv6_merged.txt)
|
||||
echo "# FACEBOOK IPV4 $(echo $FACEBOOK_IPV4 | wc -w)"
|
||||
echo "# FACEBOOK IPV6 $(echo $FACEBOOK_IPV6 | wc -w)"
|
||||
|
||||
IP_RANGES=$(echo -e "$GOOGLE_BOT_IPV4\n$GOOGLE_BOT_IPV6\n$BING_BOT_IPV4\n$BING_BOT_IPV6\n$OPENAI_IPV4\n$FACEBOOK_IPV4\n$FACEBOOK_IPV6" | sort | uniq)
|
||||
echo "#!!DO NOT EDIT!! Generated by using just ingress-blocked-list command." > root/etc/nginx/partials/blocked.conf
|
||||
for ip in $IP_RANGES; do
|
||||
echo "deny $ip;" >> root/etc/nginx/partials/blocked.conf
|
||||
done
|
||||
|
||||
provision:
|
||||
#!/usr/bin/env sh
|
||||
set -eou pipefail
|
||||
|
||||
pushd {{justfile_directory()}}/terraform > /dev/null
|
||||
NODES=$(tofu output -json | jq -r '.nodes.value[]')
|
||||
popd > /dev/null
|
||||
|
||||
for NODE in $NODES
|
||||
do
|
||||
echo "Provisioning node ${NODE}"
|
||||
|
||||
ssh ubuntu@${NODE} 'sudo rm -rf /srv && sudo mkdir /srv && sudo chown ubuntu:ubuntu /srv'
|
||||
|
||||
cat install.sh | ssh ubuntu@${NODE} 'sudo bash -s'
|
||||
done
|
||||
|
|
91
root/etc/nginx/nginx.conf
Normal file
91
root/etc/nginx/nginx.conf
Normal file
|
@ -0,0 +1,91 @@
|
|||
user www-data;
|
||||
worker_processes auto;
|
||||
pid /run/nginx.pid;
|
||||
error_log /var/log/nginx/error.log;
|
||||
include /etc/nginx/modules-enabled/*.conf;
|
||||
|
||||
events {
|
||||
worker_connections 768;
|
||||
}
|
||||
|
||||
error_log /dev/stderr error;
|
||||
|
||||
stream {
|
||||
# Map of Host -> IP
|
||||
# We will route the traffic to this endpoints.
|
||||
map $ssl_preread_server_name $selected_upstream {
|
||||
hostnames;
|
||||
|
||||
# if not knonw, use some non existing response thingy :shrug:
|
||||
default 255.255.255.255:1;
|
||||
|
||||
## CLOUD
|
||||
proxmox.tjo.cloud batuu.system.tjo.space:4443;
|
||||
postgresql.tjo.cloud batuu.system.tjo.space:4443;
|
||||
monitor.tjo.cloud hetzner.system.tjo.cloud:4443;
|
||||
loki.monitor.tjo.cloud hetzner.system.tjo.cloud:4443;
|
||||
prometheus.monitor.tjo.cloud hetzner.system.tjo.cloud:4443;
|
||||
grpc.otel.monitor.tjo.cloud hetzner.system.tjo.cloud:4443;
|
||||
http.otel.monitor.tjo.cloud hetzner.system.tjo.cloud:4443;
|
||||
vault.tjo.cloud batuu.system.tjo.space:4443;
|
||||
|
||||
## HETZNER
|
||||
tjo.space hetzner.system.tjo.cloud:4443;
|
||||
chat.tjo.space hetzner.system.tjo.cloud:4443;
|
||||
webhook.chat.tjo.space hetzner.system.tjo.cloud:4443;
|
||||
matrix.chat.tjo.space hetzner.system.tjo.cloud:4443;
|
||||
yt.tjo.space hetzner.system.tjo.cloud:4443;
|
||||
search.tjo.space hetzner.system.tjo.cloud:4443;
|
||||
send.tjo.space hetzner.system.tjo.cloud:4443;
|
||||
|
||||
## BATUU
|
||||
cloud.tjo.space batuu.system.tjo.space:4443;
|
||||
collabora.tjo.space batuu.system.tjo.space:4443;
|
||||
code.tjo.space batuu.system.tjo.space:4443;
|
||||
vault.tjo.space batuu.system.tjo.space:4443;
|
||||
rss.tjo.space batuu.system.tjo.space:4443;
|
||||
id.tjo.space batuu.system.tjo.space:4443;
|
||||
ldap.id.tjo.space batuu.system.tjo.space:4443;
|
||||
mnts.dev batuu.system.tjo.space:4443;
|
||||
paperless.tjo.space batuu.system.tjo.space:4443;
|
||||
penpot.tjo.space batuu.system.tjo.space:4443;
|
||||
|
||||
## JAKKU
|
||||
books.tjo.space jakku.system.tjo.space:4443;
|
||||
media.tjo.space jakku.system.tjo.space:4443;
|
||||
next.media.tjo.space jakku.system.tjo.space:4443;
|
||||
request.media.tjo.space jakku.system.tjo.space:4443;
|
||||
tdarr.media.tjo.space jakku.system.tjo.space:4443;
|
||||
stuff.tjo.space jakku.system.tjo.space:4443;
|
||||
auth.media.tjo.space jakku.system.tjo.space:4443;
|
||||
sonarr.media.tjo.space jakku.system.tjo.space:4443;
|
||||
radarr.media.tjo.space jakku.system.tjo.space:4443;
|
||||
lidarr.media.tjo.space jakku.system.tjo.space:4443;
|
||||
prowlarr.media.tjo.space jakku.system.tjo.space:4443;
|
||||
qbittorrent.media.tjo.space jakku.system.tjo.space:4443;
|
||||
bazarr.media.tjo.space jakku.system.tjo.space:4443;
|
||||
readarr.media.tjo.space jakku.system.tjo.space:4443;
|
||||
}
|
||||
|
||||
geoip2 /var/geoip.mmdb {
|
||||
$geoip2_data_country_iso_code country iso_code;
|
||||
$geoip2_data_latitude location latitude;
|
||||
$geoip2_data_longitude location longitude;
|
||||
}
|
||||
|
||||
log_format basic 'country=$geoip2_data_country_iso_code lat=$geoip2_data_latitude long=$geoip2_data_longitude '
|
||||
'ip=$remote_addr '
|
||||
'protocol=$protocol server_name=$ssl_preread_server_name upstream=$selected_upstream status=$status bytes_sent=$bytes_sent bytes_received=$bytes_received '
|
||||
'session_time=$session_time';
|
||||
|
||||
server {
|
||||
listen 0.0.0.0:443 default_server;
|
||||
listen [::]:443 default_server;
|
||||
server_name _;
|
||||
proxy_pass $selected_upstream;
|
||||
|
||||
proxy_protocol on;
|
||||
include /etc/nginx/partials/server.conf;
|
||||
include /etc/nginx/partials/blocked.conf;
|
||||
}
|
||||
}
|
164
root/etc/nginx/partials/blocked.conf
Normal file
164
root/etc/nginx/partials/blocked.conf
Normal file
|
@ -0,0 +1,164 @@
|
|||
#!!DO NOT EDIT!! Generated by using just ingress-blocked-list command.
|
||||
deny 102.132.96.0/19;
|
||||
deny 102.221.188.0/22;
|
||||
deny 103.4.96.0/22;
|
||||
deny 129.134.0.0/16;
|
||||
deny 13.66.139.0/24;
|
||||
deny 13.66.144.0/24;
|
||||
deny 13.67.10.16/28;
|
||||
deny 13.69.66.240/28;
|
||||
deny 13.71.172.224/28;
|
||||
deny 139.217.52.0/28;
|
||||
deny 147.75.208.0/20;
|
||||
deny 157.240.0.0/16;
|
||||
deny 157.55.39.0/24;
|
||||
deny 163.114.128.0/20;
|
||||
deny 163.70.128.0/17;
|
||||
deny 163.77.128.0/17;
|
||||
deny 173.252.64.0/18;
|
||||
deny 179.60.192.0/22;
|
||||
deny 185.60.216.0/22;
|
||||
deny 185.89.216.0/22;
|
||||
deny 191.233.204.224/28;
|
||||
deny 192.178.5.0/27;
|
||||
deny 192.178.6.0/27;
|
||||
deny 196.49.68.0/23;
|
||||
deny 199.201.64.0/22;
|
||||
deny 199.30.24.0/23;
|
||||
deny 2001:4860:4801:10::/60;
|
||||
deny 2001:4860:4801:20::/60;
|
||||
deny 2001:4860:4801:2::/64;
|
||||
deny 2001:4860:4801:31::/64;
|
||||
deny 2001:4860:4801:32::/63;
|
||||
deny 2001:4860:4801:34::/62;
|
||||
deny 2001:4860:4801:38::/62;
|
||||
deny 2001:4860:4801:3c::/63;
|
||||
deny 2001:4860:4801:3e::/64;
|
||||
deny 2001:4860:4801:40::/61;
|
||||
deny 2001:4860:4801:48::/62;
|
||||
deny 2001:4860:4801:50::/63;
|
||||
deny 2001:4860:4801:53::/64;
|
||||
deny 2001:4860:4801:54::/63;
|
||||
deny 2001:4860:4801:60::/60;
|
||||
deny 2001:4860:4801:70::/61;
|
||||
deny 2001:4860:4801:78::/63;
|
||||
deny 2001:4860:4801:80::/61;
|
||||
deny 2001:4860:4801:88::/64;
|
||||
deny 2001:4860:4801:90::/62;
|
||||
deny 2001:4860:4801:94::/64;
|
||||
deny 2001:4860:4801:c::/64;
|
||||
deny 2001:4860:4801:f::/64;
|
||||
deny 20.125.163.80/28;
|
||||
deny 20.15.133.160/27;
|
||||
deny 20.36.108.32/28;
|
||||
deny 204.15.20.0/22;
|
||||
deny 20.43.120.16/28;
|
||||
deny 20.74.197.0/28;
|
||||
deny 207.46.13.0/24;
|
||||
deny 20.79.107.240/28;
|
||||
deny 2401:db00::/32;
|
||||
deny 2620:0:1c00::/40;
|
||||
deny 2620:10d:c090::/44;
|
||||
deny 2803:6080::/29;
|
||||
deny 2a03:2880::/31;
|
||||
deny 2a03:2887:ff02::/47;
|
||||
deny 2a03:2887:ff04::/46;
|
||||
deny 2a03:2887:ff08::/47;
|
||||
deny 2a03:2887:ff18::/47;
|
||||
deny 2a03:2887:ff1b::/48;
|
||||
deny 2a03:2887:ff1c::/46;
|
||||
deny 2a03:2887:ff21::/48;
|
||||
deny 2a03:2887:ff23::/48;
|
||||
deny 2a03:2887:ff24::/47;
|
||||
deny 2a03:2887:ff27::/48;
|
||||
deny 2a03:2887:ff28::/45;
|
||||
deny 2a03:2887:ff30::/48;
|
||||
deny 2a03:2887:ff33::/48;
|
||||
deny 2a03:2887:ff35::/48;
|
||||
deny 2a03:2887:ff36::/47;
|
||||
deny 2a03:2887:ff38::/46;
|
||||
deny 2a03:2887:ff3f::/48;
|
||||
deny 2a03:2887:ff40::/46;
|
||||
deny 2a03:2887:ff44::/47;
|
||||
deny 2a03:2887:ff48::/46;
|
||||
deny 2a03:2887:ff4d::/48;
|
||||
deny 2a03:2887:ff4e::/47;
|
||||
deny 2a03:2887:ff50::/45;
|
||||
deny 2a03:2887:ff58::/47;
|
||||
deny 2a03:2887:ff60::/45;
|
||||
deny 2a03:2887:ff68::/47;
|
||||
deny 2a03:83e0::/32;
|
||||
deny 2a10:f781:10:cee0::/64;
|
||||
deny 2c0f:ef78:10::/47;
|
||||
deny 2c0f:ef78:12::/48;
|
||||
deny 2c0f:ef78:3::/48;
|
||||
deny 2c0f:ef78::/47;
|
||||
deny 2c0f:ef78:5::/48;
|
||||
deny 2c0f:ef78:6::/48;
|
||||
deny 2c0f:ef78:9::/48;
|
||||
deny 2c0f:ef78:c::/46;
|
||||
deny 31.13.24.0/21;
|
||||
deny 31.13.64.0/18;
|
||||
deny 34.100.182.96/28;
|
||||
deny 34.101.50.144/28;
|
||||
deny 34.118.254.0/28;
|
||||
deny 34.118.66.0/28;
|
||||
deny 34.126.178.96/28;
|
||||
deny 34.146.150.144/28;
|
||||
deny 34.147.110.144/28;
|
||||
deny 34.151.74.144/28;
|
||||
deny 34.152.50.64/28;
|
||||
deny 34.154.114.144/28;
|
||||
deny 34.155.98.32/28;
|
||||
deny 34.165.18.176/28;
|
||||
deny 34.175.160.64/28;
|
||||
deny 34.176.130.16/28;
|
||||
deny 34.22.85.0/27;
|
||||
deny 34.64.82.64/28;
|
||||
deny 34.65.242.112/28;
|
||||
deny 34.80.50.80/28;
|
||||
deny 34.88.194.0/28;
|
||||
deny 34.89.10.80/28;
|
||||
deny 34.89.198.80/28;
|
||||
deny 34.96.162.48/28;
|
||||
deny 35.247.243.240/28;
|
||||
deny 40.77.139.0/25;
|
||||
deny 40.77.167.0/24;
|
||||
deny 40.77.177.0/24;
|
||||
deny 40.77.178.0/23;
|
||||
deny 40.77.188.0/22;
|
||||
deny 40.77.202.0/24;
|
||||
deny 40.79.131.208/28;
|
||||
deny 40.79.186.176/28;
|
||||
deny 45.64.40.0/22;
|
||||
deny 51.105.67.0/28;
|
||||
deny 52.167.144.0/24;
|
||||
deny 52.230.152.0/24;
|
||||
deny 52.231.148.0/28;
|
||||
deny 52.233.106.0/24;
|
||||
deny 57.141.0.0/21;
|
||||
deny 57.141.12.0/23;
|
||||
deny 57.141.8.0/22;
|
||||
deny 57.144.0.0/14;
|
||||
deny 65.55.210.0/24;
|
||||
deny 66.220.144.0/20;
|
||||
deny 66.249.64.0/25;
|
||||
deny 66.249.64.128/26;
|
||||
deny 66.249.64.224/27;
|
||||
deny 66.249.65.0/24;
|
||||
deny 66.249.66.0/25;
|
||||
deny 66.249.66.160/27;
|
||||
deny 66.249.66.192/27;
|
||||
deny 66.249.68.0/25;
|
||||
deny 66.249.69.0/24;
|
||||
deny 66.249.70.0/23;
|
||||
deny 66.249.72.0/23;
|
||||
deny 66.249.74.0/25;
|
||||
deny 66.249.74.128/27;
|
||||
deny 66.249.75.0/24;
|
||||
deny 66.249.76.0/23;
|
||||
deny 66.249.78.0/26;
|
||||
deny 66.249.79.0/24;
|
||||
deny 69.171.224.0/19;
|
||||
deny 69.63.176.0/20;
|
||||
deny 74.119.76.0/22;
|
5
root/etc/nginx/partials/server.conf
Normal file
5
root/etc/nginx/partials/server.conf
Normal file
|
@ -0,0 +1,5 @@
|
|||
# Default server configuration
|
||||
access_log /dev/stdout basic;
|
||||
resolver 9.9.9.9 1.1.1.1 8.8.8.8 8.8.4.4;
|
||||
set_real_ip_from 0.0.0.0/0;
|
||||
ssl_preread on;
|
|
@ -24,30 +24,6 @@ provider "registry.opentofu.org/bpg/proxmox" {
|
|||
]
|
||||
}
|
||||
|
||||
provider "registry.opentofu.org/digitalocean/digitalocean" {
|
||||
version = "2.40.0"
|
||||
constraints = "~> 2.0"
|
||||
hashes = [
|
||||
"h1:Y7VkuuqOBgv+1jgL/4Hi247K2BskXwXtR/Uk9ssK/e4=",
|
||||
"zh:00235830abae70642ebefc4d9c00e5eb978e28b74abc6b34f16b078f242aa217",
|
||||
"zh:09d77785f768bd568f85a121d3d79316083befe903ce4ccd5567689a23236fb0",
|
||||
"zh:0c9c4e19b411702d316a6bd044903e2ec506a69d38495ed32cc31e3f3f26acae",
|
||||
"zh:12b34c88faad5b6149e9a3ad1396680588e1bae263b20d6b19835460f111c190",
|
||||
"zh:15f041fc57ea46673a828919efe2ef3f05f7c4b863b7d7881336b93e92bd1159",
|
||||
"zh:45e01972de2fab1687a09ea8fb3e4519be11c93ef93a63f28665630850858a20",
|
||||
"zh:4e18bf5c1d2ec1ec6b6a9f4b58045309006f510edf770168fc18e273e6a09289",
|
||||
"zh:575528b7e36e3489d2309e0c6cb9bd9952595cac5459b914f2d2827de1a1e4fc",
|
||||
"zh:67462192212f810875d556462c79f574a8f5713b7a869ba4fce25953bfcf2dd2",
|
||||
"zh:7024637b31e8276b653265fdf3f479220182edde4b300b034562b4c287faefa5",
|
||||
"zh:a7904721b2680be8330dde98dd826be15c67eb274da7876f042cbcd6592ac970",
|
||||
"zh:b225d4b67037a19392b0ab00d1f5fc9e729db4dfc32d18d4b36225693270ef52",
|
||||
"zh:bd1e8768819d6113b2ec16f939196a1f2ae6d2803824fde463a20d06e071b212",
|
||||
"zh:c5da40dc0749548ee2e1943776fb41b952c994e50bbc404251df20a81f730242",
|
||||
"zh:dabc3387392aaba297739e1e97fadf059258fc3efb4dff2f499dbc407b6e088d",
|
||||
"zh:f42137cf424c3e7c9c935b3f73618e51096bd0367a8d364073e2d70588d2cbf2",
|
||||
]
|
||||
}
|
||||
|
||||
provider "registry.opentofu.org/goauthentik/authentik" {
|
||||
version = "2024.8.3"
|
||||
constraints = "2024.8.3"
|
||||
|
@ -69,43 +45,3 @@ provider "registry.opentofu.org/goauthentik/authentik" {
|
|||
"zh:f6af0fd2e89ea7b7e692ef893cf5fdcc6f53c37fc0c6e066a28d9c834226c539",
|
||||
]
|
||||
}
|
||||
|
||||
provider "registry.opentofu.org/hashicorp/dns" {
|
||||
version = "3.4.1"
|
||||
constraints = "~> 3.4.1"
|
||||
hashes = [
|
||||
"h1:6Tb2wZRxfKunvjLw47ihfkaoARWIQrJd+WCOXkx0hg4=",
|
||||
"zh:53f46f16fc3b25d9bdce61d7cc9a67cea9c67ea5347fcde35833451d5011f1c4",
|
||||
"zh:662669802c99c7e698ca52e7a32afc19acf66d97bbc05f5effacdf0fe471848f",
|
||||
"zh:8289aee49df8a0cb2fcdfded575e68df1721fc3e6ce75555def499d31b7e910d",
|
||||
"zh:90aa9b049d19137ed15ea3f88238824e1fde7d1a806378cb97520391e169a96d",
|
||||
"zh:9e5795e10d65927ba689cfabc06b72085055543342d1db26ef5963ae5ab5d64a",
|
||||
"zh:9f39b6e0ca35cf2405fe4e13af8a405cf9b0b0c34b6b06ad36f319631405a3aa",
|
||||
"zh:c37a2c140c95b3eaa9d0aeb79496b220ba1a0456d01a77fcc68bd565bee7edd5",
|
||||
"zh:cd40d356c5382f0b868df2d8539f95031e3cf0c210053674ec4c7cd20c73b82a",
|
||||
"zh:fde59f09e4e62fc84012fff8493bc64eac287a0245e1c8abf29b0138d3018dfb",
|
||||
"zh:ffee5b54936bd43247e9316de0ecc0dde36556a2cd50f090d7f6443a3f689b95",
|
||||
]
|
||||
}
|
||||
|
||||
provider "registry.opentofu.org/tailscale/tailscale" {
|
||||
version = "0.16.1"
|
||||
constraints = "0.16.1"
|
||||
hashes = [
|
||||
"h1:NDIIkEo0G/leQSvGoh2Mk74ZE2xWrWgHX/S8ZVyBDYU=",
|
||||
"zh:0a9d28e5195e0e29ebf9b12b345cafcb686125008151fa01677c399d8f8f1321",
|
||||
"zh:249bce2fcfd3414211ae9e49e179e31b5d3c23dd9da24dc45acdea34ad308cb0",
|
||||
"zh:3129fb52a2aaa0c8c30aff21e7d4c0601d80898b3ecb9d7604b5933c14f54924",
|
||||
"zh:4ec3e255f34bb4f6362ab41aa9e05a3ce040a791bc07445dec86188dee867f85",
|
||||
"zh:68d3995e5a1722e24f89a385899f56a63542159b884cac989196e9538b53c6ce",
|
||||
"zh:799840b3bfbd14537397f157f4e6a5e54080cd4fee51521bac675aa188e0b33e",
|
||||
"zh:99f1da9fdaddd8a1255dce56edf8eb3e235293c72738cf70f1fb9ee9631b40e6",
|
||||
"zh:9b18fd51e260b2f3100937c34feae5f6fe3515df9b5e27ae23d00af75249a6d4",
|
||||
"zh:a7154cdce28aeb80e822a97c6bc8b8acb7a074304fd198e265ac9cbcbda0ca06",
|
||||
"zh:b0ce2ca42f018e5235a2171cdd8ba9829c90c54a6b2d602bd38e0e90c43d5d5d",
|
||||
"zh:c67609f7018fc6e48b17befd6eeb21197e8f524496185c5e29707efa6967a0a5",
|
||||
"zh:d4c9dc9d2a5a535851fc10049506bad1e7ab88193d5dcd371f91ac1b84f43a0a",
|
||||
"zh:da27f2a9b9d5a4c02ec3893a763874513825c7c4dc2bb870ba741cf7725bcf9f",
|
||||
"zh:e5bc1797b97607ff3d841c6c0d40da89c3843156ad43e15ded7d41fc0ac27717",
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1,70 +0,0 @@
|
|||
locals {
|
||||
nodes_for_dns = { for k, v in var.nodes : k => v if v.public != null && v.internal != null }
|
||||
}
|
||||
|
||||
data "digitalocean_domain" "ingress" {
|
||||
name = "ingress.tjo.cloud"
|
||||
}
|
||||
|
||||
resource "digitalocean_record" "public" {
|
||||
for_each = merge(
|
||||
{
|
||||
for key, node in local.nodes_for_dns : key => {
|
||||
node = node.name,
|
||||
ip = node.public.ipv4,
|
||||
type = "A",
|
||||
}
|
||||
},
|
||||
{
|
||||
for key, node in local.nodes_for_dns : key => {
|
||||
node = node.name,
|
||||
ip = node.public.ipv6,
|
||||
type = "AAAA",
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
domain = data.digitalocean_domain.ingress.id
|
||||
type = each.value.type
|
||||
name = lower(each.value.node)
|
||||
value = each.value.ip
|
||||
ttl = 60
|
||||
}
|
||||
|
||||
resource "digitalocean_record" "internal" {
|
||||
for_each = merge(
|
||||
{
|
||||
for key, node in local.nodes_for_dns : key => {
|
||||
node = node.name,
|
||||
ip = node.internal.ipv4,
|
||||
type = "A",
|
||||
}
|
||||
},
|
||||
{
|
||||
for key, node in local.nodes_for_dns : key => {
|
||||
node = node.name,
|
||||
ip = node.internal.ipv6,
|
||||
type = "AAAA",
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
domain = data.digitalocean_domain.ingress.id
|
||||
type = each.value.type
|
||||
name = "internal.${lower(each.value.node)}"
|
||||
value = each.value.ip
|
||||
ttl = 60
|
||||
}
|
||||
|
||||
resource "digitalocean_record" "srv" {
|
||||
for_each = local.nodes_for_dns
|
||||
|
||||
domain = data.digitalocean_domain.ingress.id
|
||||
type = "SRV"
|
||||
name = digitalocean_record.internal[each.key].fqdn
|
||||
value = "_nginx._tcp"
|
||||
port = 9000
|
||||
priority = 10
|
||||
weight = 100
|
||||
ttl = 60
|
||||
}
|
|
@ -3,12 +3,12 @@ locals {
|
|||
|
||||
nodes = {
|
||||
for k, v in var.nodes : k => merge(v, {
|
||||
id = 700 + index(keys(var.nodes), k)
|
||||
hash = sha1(v.name)
|
||||
mac_address = "AA:BB:07:00:${format("%v:%v", substr(sha1(v.name), 0, 2), substr(sha1(v.name), 2, 2))}"
|
||||
id = 800 + index(keys(var.nodes), k)
|
||||
hash = sha1(v.host)
|
||||
mac_address = "AA:BB:07:00:${format("%v:%v", substr(sha1(v.host), 0, 2), substr(sha1(v.host), 2, 2))}"
|
||||
domain = local.domain
|
||||
meta = {
|
||||
name = v.name
|
||||
name = v.host
|
||||
domain = local.domain
|
||||
service_account = {
|
||||
username = authentik_user.service_account[k].username
|
||||
|
@ -17,12 +17,21 @@ locals {
|
|||
}
|
||||
})
|
||||
}
|
||||
|
||||
ipv4_addresses = {
|
||||
for key, node in local.nodes : key => {
|
||||
for k, v in proxmox_virtual_environment_vm.nodes[key].ipv4_addresses :
|
||||
proxmox_virtual_environment_vm.nodes[key].network_interface_names[k] => v
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resource "proxmox_virtual_environment_download_file" "ubuntu" {
|
||||
for_each = local.nodes
|
||||
|
||||
content_type = "iso"
|
||||
datastore_id = var.common_storage
|
||||
node_name = var.nodes[keys(var.nodes)[0]].host
|
||||
datastore_id = each.value.iso_storage
|
||||
node_name = each.value.host
|
||||
url = "https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.img"
|
||||
overwrite = false
|
||||
}
|
||||
|
@ -32,12 +41,12 @@ resource "proxmox_virtual_environment_file" "userdata" {
|
|||
|
||||
node_name = each.value.host
|
||||
content_type = "snippets"
|
||||
datastore_id = var.common_storage
|
||||
datastore_id = each.value.iso_storage
|
||||
|
||||
source_raw {
|
||||
data = <<-EOF
|
||||
#cloud-config
|
||||
hostname: ${each.value.name}.${each.value.domain}
|
||||
hostname: ${each.value.host}.${each.value.domain}
|
||||
write_files:
|
||||
- path: /etc/tjo.cloud/meta.json
|
||||
encoding: base64
|
||||
|
@ -48,7 +57,7 @@ resource "proxmox_virtual_environment_file" "userdata" {
|
|||
power_state:
|
||||
mode: reboot
|
||||
EOF
|
||||
file_name = "${each.value.name}.ingress.tjo.cloud.userconfig.yaml"
|
||||
file_name = "${each.value.host}.ingress.tjo.cloud.userconfig.yaml"
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -56,11 +65,16 @@ resource "proxmox_virtual_environment_vm" "nodes" {
|
|||
for_each = local.nodes
|
||||
|
||||
vm_id = each.value.id
|
||||
name = "${each.value.name}.${each.value.domain}"
|
||||
name = "${each.value.host}.${each.value.domain}"
|
||||
node_name = each.value.host
|
||||
|
||||
description = "Node ${each.value.name} for ${each.value.domain}."
|
||||
tags = [each.value.domain]
|
||||
description = <<EOT
|
||||
An ingress.tjo.cloud instance for ${each.value.host}.
|
||||
|
||||
Repo: https://code.tjo.space/tjo-cloud/ingress
|
||||
EOT
|
||||
|
||||
tags = [each.value.domain]
|
||||
|
||||
stop_on_destroy = true
|
||||
timeout_start_vm = 60
|
||||
|
@ -79,7 +93,7 @@ resource "proxmox_virtual_environment_vm" "nodes" {
|
|||
|
||||
bios = "ovmf"
|
||||
efi_disk {
|
||||
datastore_id = each.value.storage
|
||||
datastore_id = each.value.boot_storage
|
||||
}
|
||||
|
||||
operating_system {
|
||||
|
@ -91,15 +105,15 @@ resource "proxmox_virtual_environment_vm" "nodes" {
|
|||
}
|
||||
|
||||
network_device {
|
||||
bridge = each.value.bridge
|
||||
bridge = "vmbr1"
|
||||
mac_address = each.value.mac_address
|
||||
}
|
||||
|
||||
scsi_hardware = "virtio-scsi-single"
|
||||
disk {
|
||||
file_id = proxmox_virtual_environment_download_file.ubuntu.id
|
||||
file_id = proxmox_virtual_environment_download_file.ubuntu[each.key].id
|
||||
interface = "virtio0"
|
||||
datastore_id = each.value.storage
|
||||
datastore_id = each.value.boot_storage
|
||||
size = each.value.boot_size
|
||||
backup = true
|
||||
cache = "none"
|
||||
|
@ -108,7 +122,7 @@ resource "proxmox_virtual_environment_vm" "nodes" {
|
|||
|
||||
initialization {
|
||||
interface = "scsi0"
|
||||
datastore_id = each.value.storage
|
||||
datastore_id = each.value.boot_storage
|
||||
user_data_file_id = proxmox_virtual_environment_file.userdata[each.key].id
|
||||
|
||||
ip_config {
|
||||
|
|
5
terraform/outputs.tf
Normal file
5
terraform/outputs.tf
Normal file
|
@ -0,0 +1,5 @@
|
|||
output "nodes" {
|
||||
value = [
|
||||
for key, node in proxmox_virtual_environment_vm.nodes : local.ipv4_addresses[key]["eth0"][0]
|
||||
]
|
||||
}
|
|
@ -6,12 +6,11 @@ data "authentik_group" "monitoring_publisher" {
|
|||
resource "authentik_user" "service_account" {
|
||||
for_each = var.nodes
|
||||
|
||||
username = "${each.value.name}.ingress@svc.tjo.cloud"
|
||||
name = "${each.value.name}.ingress@svc.tjo.cloud"
|
||||
email = "${each.value.name}.ingress@svc.tjo.cloud"
|
||||
username = "${each.value.host}.${local.domain}"
|
||||
name = "${each.value.host}.${local.domain}"
|
||||
|
||||
type = "service_account"
|
||||
path = "svc.tjo.cloud"
|
||||
path = "ingress.tjo.cloud"
|
||||
|
||||
groups = [
|
||||
data.authentik_group.monitoring_publisher.id,
|
||||
|
@ -21,9 +20,9 @@ resource "authentik_user" "service_account" {
|
|||
resource "authentik_token" "service_account" {
|
||||
for_each = var.nodes
|
||||
|
||||
identifier = "svc-tjo-cloud-service-account-${each.value.name}"
|
||||
identifier = replace("service-account-${each.value.host}-${local.domain}", ".", "-")
|
||||
user = authentik_user.service_account[each.key].id
|
||||
description = "Service account for ${each.value.name} node"
|
||||
description = "Service account for ${each.value.host}.${local.domain} node."
|
||||
expiring = false
|
||||
intent = "app_password"
|
||||
retrieve_key = true
|
||||
|
|
|
@ -1,21 +1,9 @@
|
|||
terraform {
|
||||
required_providers {
|
||||
digitalocean = {
|
||||
source = "digitalocean/digitalocean"
|
||||
version = "~> 2.0"
|
||||
}
|
||||
dns = {
|
||||
source = "hashicorp/dns"
|
||||
version = "~> 3.4.1"
|
||||
}
|
||||
proxmox = {
|
||||
source = "bpg/proxmox"
|
||||
version = "0.61.1"
|
||||
}
|
||||
tailscale = {
|
||||
source = "tailscale/tailscale"
|
||||
version = "0.16.1"
|
||||
}
|
||||
authentik = {
|
||||
source = "goauthentik/authentik"
|
||||
version = "2024.8.3"
|
||||
|
@ -30,21 +18,32 @@ provider "authentik" {
|
|||
token = var.authentik_token
|
||||
}
|
||||
|
||||
provider "digitalocean" {
|
||||
token = var.digitalocean_token
|
||||
}
|
||||
|
||||
provider "tailscale" {
|
||||
api_key = var.tailscale_apikey
|
||||
}
|
||||
|
||||
provider "proxmox" {
|
||||
# FIXME: Traefik/NGINX breaks this! 500 ERROR
|
||||
endpoint = "https://178.63.49.225:8006/api2/json"
|
||||
endpoint = "https://batuu.system.tjo.cloud:8006/api2/json"
|
||||
insecure = true
|
||||
api_token = var.proxmox_token
|
||||
|
||||
ssh {
|
||||
agent = true
|
||||
username = "root"
|
||||
|
||||
node {
|
||||
name = "batuu"
|
||||
address = "batuu.system.tjo.cloud"
|
||||
port = 22
|
||||
}
|
||||
|
||||
node {
|
||||
name = "jakku"
|
||||
address = "jakku.system.tjo.cloud"
|
||||
port = 22
|
||||
}
|
||||
|
||||
node {
|
||||
name = "nevaroo"
|
||||
address = "nevaroo.system.tjo.cloud"
|
||||
port = 22
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,20 +1,21 @@
|
|||
nodes = {
|
||||
de_01 = {
|
||||
name = "de-01"
|
||||
host = "hetzner"
|
||||
bridge = "vmprivate0"
|
||||
cloudinit = ""
|
||||
batuu = {
|
||||
host = "batuu"
|
||||
iso_storage = "local"
|
||||
boot_storage = "local-nvme"
|
||||
}
|
||||
de_02 = {
|
||||
name = "de-02"
|
||||
host = "hetzner"
|
||||
bridge = "vmprivate0"
|
||||
cloudinit = ""
|
||||
jakku = {
|
||||
host = "jakku"
|
||||
iso_storage = "local"
|
||||
boot_storage = "local-nvme"
|
||||
}
|
||||
nevaroo = {
|
||||
host = "nevaroo"
|
||||
iso_storage = "local"
|
||||
boot_storage = "local"
|
||||
}
|
||||
}
|
||||
|
||||
ssh_keys = [
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICXAlzwziqfUUb2qmFwNF/nrBYc5MNT1MMOx81ohBmB+ tine@little.sys.tjo.space"
|
||||
]
|
||||
|
||||
common_storage = "proxmox-backup-tjo-cloud"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
variable "nodes" {
|
||||
type = map(object({
|
||||
name = string
|
||||
host = string
|
||||
|
||||
internal = optional(object({
|
||||
ipv4 = string
|
||||
|
@ -11,16 +11,14 @@ variable "nodes" {
|
|||
ipv6 = string
|
||||
}))
|
||||
|
||||
host = string
|
||||
bridge = string
|
||||
|
||||
cores = optional(number, 1)
|
||||
memory = optional(number, 512)
|
||||
|
||||
storage = optional(string, "main")
|
||||
boot_size = optional(number, 8)
|
||||
iso_storage = string
|
||||
|
||||
cloudinit = string
|
||||
boot_storage = string
|
||||
boot_size = optional(number, 8)
|
||||
}))
|
||||
}
|
||||
|
||||
|
@ -28,10 +26,6 @@ variable "ssh_keys" {
|
|||
type = list(string)
|
||||
}
|
||||
|
||||
variable "common_storage" {
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "digitalocean_token" {
|
||||
type = string
|
||||
sensitive = true
|
||||
|
|
Loading…
Reference in a new issue