feat: tailscale + dns

This commit is contained in:
Tine 2024-08-23 22:03:47 +02:00
parent b1b8633945
commit 2a2b98f3fe
Signed by: mentos1386
SSH key fingerprint: SHA256:MNtTsLbihYaWF8j1fkOHfkKNlnN1JQfxEU/rBU8nCGw
8 changed files with 110 additions and 74 deletions

View file

@ -6,7 +6,7 @@
... ...
}: }:
let let
ngx_http_geoip2_module = pkgs.stdenv.mkDerivation rec { ngx_http_geoip2_module = pkgs.stdenv.mkDerivation {
name = "ngx_http_geoip2_module-a28ceff"; name = "ngx_http_geoip2_module-a28ceff";
src = pkgs.fetchgit { src = pkgs.fetchgit {
url = "https://github.com/leev/ngx_http_geoip2_module"; url = "https://github.com/leev/ngx_http_geoip2_module";
@ -28,23 +28,45 @@ in
# PROXMOX # PROXMOX
services.qemuGuest.enable = true; services.qemuGuest.enable = true;
services.cloud-init = {
enable = true;
};
# USER MANAGEMENT # USER MANAGEMENT
# TODO: Should this be in cloud-init?
nix.settings.trusted-users = [ "nixos" ]; nix.settings.trusted-users = [ "nixos" ];
users.users.nixos = { users.users.nixos = {
isNormalUser = true; isNormalUser = true;
password = "nixos";
extraGroups = [ "wheel" ]; extraGroups = [ "wheel" ];
openssh.authorizedKeys.keys = [ openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICXAlzwziqfUUb2qmFwNF/nrBYc5MNT1MMOx81ohBmB+ tine@little.sys.tjo.space" "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICXAlzwziqfUUb2qmFwNF/nrBYc5MNT1MMOx81ohBmB+ tine@little.sys.tjo.space"
]; ];
}; };
security.sudo.wheelNeedsPassword = false;
# SSH
services.openssh = { services.openssh = {
enable = true; enable = true;
settings.PasswordAuthentication = false; settings.PasswordAuthentication = false;
settings.KbdInteractiveAuthentication = false; settings.KbdInteractiveAuthentication = false;
settings.PermitRootLogin = "no"; settings.PermitRootLogin = "no";
}; };
security.sudo.wheelNeedsPassword = false;
# TAILSCALE
services.tailscale = {
enable = true;
};
# FIREWALL
networking.firewall = {
enable = true;
trustedInterfaces = [ "tailscale0" ];
allowedUDPPorts = [ config.services.tailscale.port ];
allowedTCPPorts = [ 22 ];
};
# NGINX # NGINX
services.nginx = { services.nginx = {

View file

@ -28,11 +28,13 @@ push:
--upload-file $NIXOS_IMAGE \ --upload-file $NIXOS_IMAGE \
https://code.tjo.space/api/packages/tjo-cloud/generic/ingress/${VERSION}/nixos.qcow2 https://code.tjo.space/api/packages/tjo-cloud/generic/ingress/${VERSION}/nixos.qcow2
deploy: deploy: build
#!/usr/bin/env sh #!/usr/bin/env sh
export NIXOS_IMAGE=$(nix path-info --quiet .#vm)/nixos.qcow2 export NIXOS_IMAGE=$(nix path-info --quiet .#vm)/nixos.qcow2
export TF_VAR_image_path=$NIXOS_IMAGE export TF_VAR_image_path=$NIXOS_IMAGE
echo "Deploying $NIXOS_IMAGE"
cd {{justfile_directory()}}/terraform cd {{justfile_directory()}}/terraform
tofu init tofu init
tofu apply tofu apply

53
terraform/dns.tf Normal file
View file

@ -0,0 +1,53 @@
data "digitalocean_domain" "ingress" {
name = "ingress.tjo.cloud"
}
resource "digitalocean_record" "public" {
for_each = merge(
{
for key, node in local.nodes_with_address : key => {
node = node.name,
ip = node.public_ipv4,
type = "A",
}
},
{
for key, node in local.nodes_with_address : 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_with_address : key => {
node = node.name,
ip = node.internal_ipv4,
type = "A",
}
},
{
for key, node in local.nodes_with_address : key => {
node = node.name,
ip = node.internal_ipv6,
type = "AAAA",
}
}
)
domain = data.digitalocean_domain.ingress.id
type = each.value.type
name = lower(each.value.node)
value = each.value.ip
ttl = 60
}

View file

@ -1,9 +1,9 @@
locals { locals {
nodes_with_names = { nodes_with_names = {
for k, v in var.nodes : k => merge(v, { for k, v in var.nodes : k => merge(v, {
id = 700 + index(keys(var.nodes), k) id = 700 + index(keys(var.nodes), k)
name = "${v.name}.ingress.tjo.cloud" hostname = "${v.name}.ingress.tjo.cloud"
hash = sha1(v.name) hash = sha1(v.name)
}) })
} }
nodes = { nodes = {
@ -28,12 +28,22 @@ locals {
nodes_with_address = { nodes_with_address = {
for k, v in local.nodes : for k, v in local.nodes :
k => merge(v, { k => merge(v, {
ipv4 = local.ipv4_addresses[k]["eth0"][0] public_ipv4 = local.ipv4_addresses[k]["eth0"][0]
ipv6 = local.ipv6_addresses[k]["eth0"][0] public_ipv6 = local.ipv6_addresses[k]["eth0"][0]
internal_ipv4 = local.ipv4_addresses[k]["tailscale0"][0]
internal_ipv6 = local.ipv6_addresses[k]["tailscale0"][0]
}) })
} }
} }
resource "tailscale_tailnet_key" "ingress" {
reusable = true
ephemeral = true
preauthorized = true
tags = ["tag:ingress-tjo-cloud"]
description = "tailscale key for ingress-tjo-cloud nodes"
}
resource "proxmox_virtual_environment_file" "ingress" { resource "proxmox_virtual_environment_file" "ingress" {
content_type = "iso" content_type = "iso"
datastore_id = var.common_storage datastore_id = var.common_storage
@ -54,9 +64,14 @@ resource "proxmox_virtual_environment_file" "cloudinit" {
source_raw { source_raw {
data = <<-EOF data = <<-EOF
#cloud-config
bootcmd:
- [ 'tailscale', 'up', '--authkey', '${tailscale_tailnet_key.ingress.key}',
'--hostname', '${each.value.name}',
'--accept-routes', 'true',
'--ssh' ]
EOF EOF
file_name = "${each.value.name}.cloudinit.yaml" file_name = "${each.value.hostname}.cloudinit.yaml"
} }
} }
@ -64,7 +79,7 @@ resource "proxmox_virtual_environment_vm" "nodes" {
for_each = local.nodes for_each = local.nodes
vm_id = each.value.id vm_id = each.value.id
name = each.value.name name = each.value.hostname
node_name = each.value.host node_name = each.value.host
description = "Node ${each.value.name} for ingress.tjo.cloud." description = "Node ${each.value.name} for ingress.tjo.cloud."

View file

@ -1,28 +0,0 @@
locals {
locations = {
DE = ["46.4.88.62", "2a01:4f8:202:2395::"]
SI = ["93.103.125.118", "2a01:261:455:6c00:21e:6ff:fe45:c34"]
}
}
data "digitalocean_domain" "ingress" {
name = "ingress.tjo.cloud"
}
resource "digitalocean_record" "locations" {
for_each = merge([
for location, ips in local.locations : {
for ip in ips : "${location} at ${ip}" => {
location = location,
ip = ip,
}
}
]...)
domain = data.digitalocean_domain.ingress.id
type = strcontains(each.value.ip, ":") ? "AAAA" : "A"
name = lower(each.value.location)
value = each.value.ip
ttl = 60
}

View file

@ -1,35 +0,0 @@
locals {
listeners = [
{
domain = "k8s.tjo.cloud"
name = "api"
locations = ["SI", "DE"]
},
{
domain = "k8s.tjo.cloud"
name = "dashboard"
locations = ["SI", "DE"]
}
]
}
resource "digitalocean_record" "listeners" {
for_each = merge(flatten([
for listener in local.listeners :
[
for location in listener.locations : {
for ip in local.locations[location] : "${ip} for ${listener.name}.${listener.domain} at ${location}" => {
ip = ip
domain = listener.domain
name = listener.name
}
}
]
])...)
domain = each.value.domain
type = strcontains(each.value.ip, ":") ? "AAAA" : "A"
name = each.value.name
value = each.value.ip
ttl = 60
}

View file

@ -25,6 +25,9 @@ provider "digitalocean" {
token = var.digitalocean_token token = var.digitalocean_token
} }
provider "tailscale" {
api_key = var.tailscale_apikey
}
provider "proxmox" { provider "proxmox" {
# FIXME: Traefik/NGINX breaks this! 500 ERROR # FIXME: Traefik/NGINX breaks this! 500 ERROR

View file

@ -27,6 +27,10 @@ variable "proxmox_token" {
type = string type = string
} }
variable "tailscale_apikey" {
type = string
}
variable "image_path" { variable "image_path" {
type = string type = string
} }