feat: tailscale + dns
This commit is contained in:
parent
b1b8633945
commit
2a2b98f3fe
8 changed files with 110 additions and 74 deletions
|
@ -6,7 +6,7 @@
|
|||
...
|
||||
}:
|
||||
let
|
||||
ngx_http_geoip2_module = pkgs.stdenv.mkDerivation rec {
|
||||
ngx_http_geoip2_module = pkgs.stdenv.mkDerivation {
|
||||
name = "ngx_http_geoip2_module-a28ceff";
|
||||
src = pkgs.fetchgit {
|
||||
url = "https://github.com/leev/ngx_http_geoip2_module";
|
||||
|
@ -28,23 +28,45 @@ in
|
|||
|
||||
# PROXMOX
|
||||
services.qemuGuest.enable = true;
|
||||
services.cloud-init = {
|
||||
enable = true;
|
||||
};
|
||||
|
||||
# USER MANAGEMENT
|
||||
# TODO: Should this be in cloud-init?
|
||||
nix.settings.trusted-users = [ "nixos" ];
|
||||
users.users.nixos = {
|
||||
isNormalUser = true;
|
||||
password = "nixos";
|
||||
extraGroups = [ "wheel" ];
|
||||
openssh.authorizedKeys.keys = [
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICXAlzwziqfUUb2qmFwNF/nrBYc5MNT1MMOx81ohBmB+ tine@little.sys.tjo.space"
|
||||
];
|
||||
};
|
||||
security.sudo.wheelNeedsPassword = false;
|
||||
|
||||
# SSH
|
||||
services.openssh = {
|
||||
enable = true;
|
||||
settings.PasswordAuthentication = false;
|
||||
settings.KbdInteractiveAuthentication = false;
|
||||
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
|
||||
services.nginx = {
|
||||
|
|
4
justfile
4
justfile
|
@ -28,11 +28,13 @@ push:
|
|||
--upload-file $NIXOS_IMAGE \
|
||||
https://code.tjo.space/api/packages/tjo-cloud/generic/ingress/${VERSION}/nixos.qcow2
|
||||
|
||||
deploy:
|
||||
deploy: build
|
||||
#!/usr/bin/env sh
|
||||
export NIXOS_IMAGE=$(nix path-info --quiet .#vm)/nixos.qcow2
|
||||
export TF_VAR_image_path=$NIXOS_IMAGE
|
||||
|
||||
echo "Deploying $NIXOS_IMAGE"
|
||||
|
||||
cd {{justfile_directory()}}/terraform
|
||||
tofu init
|
||||
tofu apply
|
||||
|
|
53
terraform/dns.tf
Normal file
53
terraform/dns.tf
Normal 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
|
||||
}
|
|
@ -2,7 +2,7 @@ locals {
|
|||
nodes_with_names = {
|
||||
for k, v in var.nodes : k => merge(v, {
|
||||
id = 700 + index(keys(var.nodes), k)
|
||||
name = "${v.name}.ingress.tjo.cloud"
|
||||
hostname = "${v.name}.ingress.tjo.cloud"
|
||||
hash = sha1(v.name)
|
||||
})
|
||||
}
|
||||
|
@ -28,12 +28,22 @@ locals {
|
|||
nodes_with_address = {
|
||||
for k, v in local.nodes :
|
||||
k => merge(v, {
|
||||
ipv4 = local.ipv4_addresses[k]["eth0"][0]
|
||||
ipv6 = local.ipv6_addresses[k]["eth0"][0]
|
||||
public_ipv4 = local.ipv4_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" {
|
||||
content_type = "iso"
|
||||
datastore_id = var.common_storage
|
||||
|
@ -54,9 +64,14 @@ resource "proxmox_virtual_environment_file" "cloudinit" {
|
|||
|
||||
source_raw {
|
||||
data = <<-EOF
|
||||
|
||||
#cloud-config
|
||||
bootcmd:
|
||||
- [ 'tailscale', 'up', '--authkey', '${tailscale_tailnet_key.ingress.key}',
|
||||
'--hostname', '${each.value.name}',
|
||||
'--accept-routes', 'true',
|
||||
'--ssh' ]
|
||||
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
|
||||
|
||||
vm_id = each.value.id
|
||||
name = each.value.name
|
||||
name = each.value.hostname
|
||||
node_name = each.value.host
|
||||
|
||||
description = "Node ${each.value.name} for ingress.tjo.cloud."
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -25,6 +25,9 @@ provider "digitalocean" {
|
|||
token = var.digitalocean_token
|
||||
}
|
||||
|
||||
provider "tailscale" {
|
||||
api_key = var.tailscale_apikey
|
||||
}
|
||||
|
||||
provider "proxmox" {
|
||||
# FIXME: Traefik/NGINX breaks this! 500 ERROR
|
||||
|
|
|
@ -27,6 +27,10 @@ variable "proxmox_token" {
|
|||
type = string
|
||||
}
|
||||
|
||||
variable "tailscale_apikey" {
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "image_path" {
|
||||
type = string
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue