This commit is contained in:
viktorbarzin 2021-02-07 23:45:55 +00:00
commit 4caa987213
No known key found for this signature in database
GPG key ID: 0EB088298288D958
35 changed files with 32889 additions and 0 deletions

35
.gitignore vendored Normal file
View file

@ -0,0 +1,35 @@
# Created by https://www.toptal.com/developers/gitignore/api/terraform
# Edit at https://www.toptal.com/developers/gitignore?templates=terraform
### Terraform ###
# Local .terraform directories
**/.terraform/*
# .tfstate files
*.tfstate
*.tfstate.*
# Crash log files
crash.log
# Ignore any .tfvars files that are generated automatically for each Terraform run. Most
# .tfvars files are managed as part of configuration and so should be included in
# version control.
#
# example.tfvars
*.tfvars
# Ignore override files as they are usually used to override resources locally and so
# are not checked in
override.tf
override.tf.json
*_override.tf
*_override.tf.json
# Include override files you do wish to add to version control using negated pattern
# !example_override.tf
# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan
# example: *tfplan*

11
idrac-power-cycle.sh Normal file
View file

@ -0,0 +1,11 @@
#!/bin/bash
# Get power supply on outside system voltage
curl -s -k -u root:calvin -H"Content-type: application/json" -X GET https://idrac/redfish/v1/Chassis/System.Embedded.1/Power/PowerSupplies/PSU.Slot.2 |jq .LineInputVoltage
# Power off
curl -s -k -u root:calvin -X POST -d '{"Action": "Reset", "ResetType": "GracefulShutdown"}' -H"Content-type: application/json" https://idrac/redfish/v1/Systems/System.Embedded.1/Actions/ComputerSystem.Reset
# Power on
curl -s -k -u root:calvin -X POST -d '{"Action": "Reset", "ResetType": "On"}' -H"Content-type: application/json" https://idrac/redfish/v1/Systems/System.Embedded.1/Actions/ComputerSystem.Reset

164
main.tf Normal file
View file

@ -0,0 +1,164 @@
variable "vsphere_password" {}
variable "vsphere_user" {}
variable "vsphere_server" {}
variable "tls_secret_name" {}
variable "tls_crt" {}
variable "tls_key" {}
variable "client_certificate_secret_name" {}
variable "mailserver_accounts" {}
variable "mailserver_aliases" {}
variable "pihole_web_password" {}
variable "webhook_handler_secret" {}
variable "wireguard_wg_0_conf" {}
variable "wireguard_firewall_sh" {}
variable "hackmd_db_password" {}
variable "bind_db_viktorbarzin_me" {}
variable "bind_db_viktorbarzin_lan" {}
variable "bind_named_conf_options" {}
variable "alertmanager_account_password" {}
variable "wireguard_wg_0_key" {}
variable "ansible_prefix" {
default = "ANSIBLE_VAULT_PASSWORD_FILE=~/.ansible/vault_pass.txt ansible-playbook -i playbook/hosts.yaml playbook/linux.yml -t linux/initial_setup"
description = "Provisioner command"
}
provider "kubernetes" {
config_path = "~/.kube/config"
}
provider "helm" {
kubernetes {
config_path = "~/.kube/config"
}
}
# Main module to init infra from
module "pxe_server" {
source = "./modules/create-vm"
vm_name = "pxe-server"
network = "dManagementVMs"
# provisioner_command = "${var.ansible_prefix} -t linux/pxe-server/add-distro"
provisioner_command = "# no provisioner needed #" # Noop until ubuntu autoinstall is setup
vsphere_password = var.vsphere_password
vsphere_user = var.vsphere_user
vsphere_server = var.vsphere_server
cdrom_path = "ISO/ubuntu-server-20.04.1.iso"
vm_disk_size = 50
vm_mac_address = "00:50:56:87:4a:2d"
}
module "k8s_master" {
source = "./modules/create-vm"
vm_name = "k8s-master"
vm_mac_address = "00:50:56:b0:a1:39"
network = "dKubernetes"
provisioner_command = "${var.ansible_prefix} -t linux/k8s/master -e hostname=k8s-master"
vsphere_password = var.vsphere_password
vsphere_user = var.vsphere_user
vsphere_server = var.vsphere_server
vsphere_datastore = "r730-datastore"
vsphere_resource_pool = "R730"
}
module "k8s_node1" {
source = "./modules/create-vm"
vm_name = "k8s-node1"
vm_mac_address = "00:50:56:b0:e0:c9"
network = "dKubernetes"
provisioner_command = "${var.ansible_prefix} -t linux/k8s/node -e hostname=k8s-node1 -e k8s_master='wizard@${module.k8s_master.guest_ip}'"
vsphere_password = var.vsphere_password
vsphere_user = var.vsphere_user
vsphere_server = var.vsphere_server
vsphere_datastore = "r730-datastore"
vsphere_resource_pool = "R730"
}
module "k8s_node2" {
source = "./modules/create-vm"
vm_name = "k8s-node2"
vm_mac_address = "00:50:56:b0:a1:36"
network = "dKubernetes"
provisioner_command = "${var.ansible_prefix} -t linux/k8s/node -e hostname=k8s-node2 -e k8s_master='wizard@${module.k8s_master.guest_ip}'"
vsphere_password = var.vsphere_password
vsphere_user = var.vsphere_user
vsphere_server = var.vsphere_server
vsphere_datastore = "r730-datastore"
vsphere_resource_pool = "R730"
}
module "k8s_node3" {
source = "./modules/create-vm"
vm_name = "k8s-node3"
vm_mac_address = "00:50:56:b0:a1:37"
network = "dKubernetes"
provisioner_command = "${var.ansible_prefix} -t linux/k8s/node -e hostname=k8s-node3 -e k8s_master='wizard@${module.k8s_master.guest_ip}'"
vsphere_password = var.vsphere_password
vsphere_user = var.vsphere_user
vsphere_server = var.vsphere_server
vsphere_datastore = "r730-datastore"
vsphere_resource_pool = "R730"
}
module "k8s_node4" {
source = "./modules/create-vm"
vm_name = "k8s-node4"
vm_mac_address = "00:50:56:b0:a1:38"
network = "dKubernetes"
provisioner_command = "${var.ansible_prefix} -t linux/k8s/node -e hostname=k8s-node4 -e k8s_master='wizard@${module.k8s_master.guest_ip}'"
vsphere_password = var.vsphere_password
vsphere_user = var.vsphere_user
vsphere_server = var.vsphere_server
vsphere_datastore = "r730-datastore"
vsphere_resource_pool = "R730"
}
module "k8s_node5" {
source = "./modules/create-vm"
vm_name = "k8s-node5"
vm_mac_address = "00:50:56:b0:a1:40"
network = "dKubernetes"
provisioner_command = "${var.ansible_prefix} -t linux/k8s/node -e hostname=k8s-node5 -e k8s_master='wizard@${module.k8s_master.guest_ip}'"
vsphere_password = var.vsphere_password
vsphere_user = var.vsphere_user
vsphere_server = var.vsphere_server
vsphere_datastore = "r730-datastore"
vsphere_resource_pool = "R730"
}
# resource "null_resource" "test" {
# provisioner "local-exec" {
# working_dir = "/home/viktor/"
# command = "ANSIBLE_VAULT_PASSWORD_FILE=~/.ansible/vault_pass.txt ansible-playbook -i playbook/hosts.yaml playbook/linux.yml -t linux/k8s/node -e host='10.0.40.126'"
# }
# }
module "kubernetes_cluster" {
source = "./modules/kubernetes"
tls_secret_name = var.tls_secret_name
tls_crt = var.tls_crt
tls_key = var.tls_key
client_certificate_secret_name = var.client_certificate_secret_name
mailserver_accounts = var.mailserver_accounts
mailserver_aliases = var.mailserver_aliases
pihole_web_password = var.pihole_web_password
webhook_handler_secret = var.webhook_handler_secret
wireguard_wg_0_conf = var.wireguard_wg_0_conf
wireguard_wg_0_key = var.wireguard_wg_0_key
wireguard_firewall_sh = var.wireguard_firewall_sh
hackmd_db_password = var.hackmd_db_password
bind_db_viktorbarzin_me = var.bind_db_viktorbarzin_me
bind_db_viktorbarzin_lan = var.bind_db_viktorbarzin_lan
bind_named_conf_options = var.bind_named_conf_options
alertmanager_account_password = var.alertmanager_account_password
}

4
migrate_tfstate.txt Normal file
View file

@ -0,0 +1,4 @@
# Steps to migrate 1 .tfstate into another
# Inside the dir to be migrated out from do:
for s in $(tf state list); do tf state mv -state-out=../../terraform.tfstate $s "module.UPPER_WORKSPACE_MODULE_NAME.$s"; done

153
modules/create-vm/main.tf Normal file
View file

@ -0,0 +1,153 @@
variable "vsphere_user" {
default = "Administrator@viktorbarzin.lan"
}
variable "vsphere_password" {}
variable "vsphere_server" {
default = "vcenter"
}
variable "vm_name" {
default = "terraform-test"
}
variable "vm_cpus" {
type = number
default = 4
}
variable "vm_mem" {
type = number
default = 4096
}
variable "vm_guest_id" {
default = "ubuntu64Guest"
}
variable "vm_disk_size" {
type = number
default = 64
}
variable "provisioner_command" {
description = "Additional provisioning commands to run"
# default = "#"
type = string
}
variable "network" {
description = "Network to attach the vm guest to"
}
variable "ceph_disk_size" {
type = number
default = 0
}
variable "cdrom_path" {
type = string
default = ""
}
variable "vsphere_datastore" {
type = string
default = "r730-datastore"
}
variable "vsphere_resource_pool" {
type = string
default = "R730"
}
variable "vm_mac_address" {
type = string
default = ""
}
provider "vsphere" {
user = var.vsphere_user
password = var.vsphere_password
vsphere_server = var.vsphere_server
# If you have a self-signed cert
allow_unverified_ssl = true
}
data "vsphere_datacenter" "dc" {
name = "Home"
}
data "vsphere_datastore" "datastore" {
name = var.vsphere_datastore
datacenter_id = data.vsphere_datacenter.dc.id
}
data "vsphere_resource_pool" "pool" {
name = var.vsphere_resource_pool
datacenter_id = data.vsphere_datacenter.dc.id
}
data "vsphere_network" "network" {
name = var.network
datacenter_id = data.vsphere_datacenter.dc.id
}
resource "vsphere_virtual_machine" "vm" {
name = var.vm_name
resource_pool_id = data.vsphere_resource_pool.pool.id
datastore_id = data.vsphere_datastore.datastore.id
num_cpus = var.vm_cpus
memory = var.vm_mem
guest_id = var.vm_guest_id
# If mac address is set create NIC with that MAC
dynamic "network_interface" {
for_each = var.vm_mac_address != "" ? [1] : []
content {
network_id = data.vsphere_network.network.id
use_static_mac = true
mac_address = var.vm_mac_address
}
}
# Else create a NIC with random MAC
dynamic "network_interface" {
for_each = var.vm_mac_address == "" ? [1] : []
content {
network_id = data.vsphere_network.network.id
}
}
disk {
label = "disk0"
size = var.vm_disk_size
}
dynamic "disk" {
for_each = var.ceph_disk_size > 0 ? [1] : []
content {
label = "ceph-disk0"
size = var.ceph_disk_size
unit_number = 1
}
}
dynamic "cdrom" {
for_each = var.cdrom_path != "" ? [1] : []
content {
datastore_id = data.vsphere_datastore.datastore.id
path = var.cdrom_path
}
}
wait_for_guest_net_timeout = 600
provisioner "local-exec" {
# for_each = var.provisioner_command != "" ? [1] : []
# content {
command = "${var.provisioner_command} -e 'host=${vsphere_virtual_machine.vm.default_ip_address}'"
# }
}
}
output "guest_ip" {
value = vsphere_virtual_machine.vm.default_ip_address
}

View file

@ -0,0 +1,85 @@
variable "named_conf_mounts" {}
variable "deployment_name" {}
resource "kubernetes_deployment" "bind" {
metadata {
name = var.deployment_name
namespace = "bind"
labels = {
"app" = "bind"
"kubernetes.io/cluster-service" : "true"
}
}
spec {
replicas = "3"
selector {
match_labels = {
"app" = var.deployment_name
}
}
template {
metadata {
labels = {
"app" = var.deployment_name
"kubernetes.io/cluster-service" : "true"
}
}
spec {
container {
name = "bind"
image = "resystit/bind9:latest"
image_pull_policy = "IfNotPresent"
port {
container_port = 53
protocol = "UDP"
}
volume_mount {
mount_path = "/etc/bind/named.conf"
sub_path = "named.conf"
name = "bindconf"
}
dynamic "volume_mount" {
for_each = [for m in var.named_conf_mounts :
{
name = m.name
mount_path = m.mount_path
sub_path = m.sub_path
}]
content {
name = volume_mount.value.name
mount_path = volume_mount.value.mount_path
sub_path = volume_mount.value.sub_path
}
}
volume_mount {
mount_path = "/etc/bind/db.viktorbarzin.me"
sub_path = "db.viktorbarzin.me"
name = "bindconf"
}
volume_mount {
mount_path = "/etc/bind/db.viktorbarzin.lan"
sub_path = "db.viktorbarzin.lan"
name = "bindconf"
}
}
container {
name = "bind-exporter"
image = "prometheuscommunity/bind-exporter:latest"
image_pull_policy = "IfNotPresent"
port {
container_port = 9119
}
}
volume {
name = "bindconf"
config_map {
name = "bind-configmap"
}
}
}
}
}
}

View file

@ -0,0 +1,72 @@
variable "db_viktorbarzin_me" {}
variable "db_viktorbarzin_lan" {}
variable "named_conf_options" {}
resource "kubernetes_namespace" "bind" {
metadata {
name = "bind"
}
}
resource "kubernetes_config_map" "bind_configmap" {
metadata {
name = "bind-configmap"
namespace = "bind"
}
data = {
"db.viktorbarzin.lan" = var.db_viktorbarzin_lan
"db.viktorbarzin.me" = var.db_viktorbarzin_me
"named.conf" = var.named_conf
"named.conf.local" = var.named_conf_local
"named.conf.options" = var.named_conf_options
"public-named.conf.local" = var.public_named_conf_local
"public-named.conf.options" = var.public_named_conf_options
}
}
module "bind-local-deployment" {
source = "./deployment-factory"
deployment_name = "bind"
named_conf_mounts = [
{
"mount_path" = "/etc/bind/named.conf.local"
"sub_path" = "named.conf.local"
"name" = "bindconf"
},
{
mount_path = "/etc/bind/named.conf.options"
sub_path = "named.conf.options"
name = "bindconf"
}
]
}
module "bind-local-service" {
source = "./service-factory"
service_name = "bind"
port = 5354
}
module "bind-public-deployment" {
source = "./deployment-factory"
deployment_name = "bind-public"
named_conf_mounts = [
{
"mount_path" = "/etc/bind/named.conf.local"
"sub_path" = "public-named.conf.local"
"name" = "bindconf"
},
{
mount_path = "/etc/bind/named.conf.options"
sub_path = "public-named.conf.options"
name = "bindconf"
}
]
}
module "bind-public-service" {
source = "./service-factory"
service_name = "bind-public"
port = 10053
}

View file

@ -0,0 +1,28 @@
variable "service_name" {}
variable "port" {}
resource "kubernetes_service" "bind" {
metadata {
name = var.service_name
namespace = "bind"
annotations = {
"metallb.universe.tf/allow-shared-ip" = "shared"
}
labels = {
"app" = var.service_name
}
}
spec {
type = "LoadBalancer"
external_traffic_policy = "Cluster"
selector = {
"app" = var.service_name
}
port {
name = "dns"
protocol = "UDP"
port = var.port
target_port = "53"
}
}
}

View file

@ -0,0 +1,71 @@
variable "named_conf" {
default = <<EOT
// This is the primary configuration file for the BIND DNS server named.
//
// Please read /usr/share/doc/bind9/README.Debian.gz for information on the
// structure of BIND configuration files in Debian, *BEFORE* you customize
// this configuration file.
//
// If you are just adding zones, please do that in /etc/bind/named.conf.local
include "/etc/bind/named.conf.options";
include "/etc/bind/named.conf.local";
//include "/etc/bind/named.conf.default-zones";
EOT
}
variable "named_conf_local" {
default = <<EOT
//
// Do any local configuration here
//
// Consider adding the 1918 zones here, if they are not used in your
// organization
//include "/etc/bind/zones.rfc1918";
zone "viktorbarzin.me" {
type master;
file "/etc/bind/db.viktorbarzin.me";
};
zone "viktorbarzin.lan" {
type master;
file "/etc/bind/db.viktorbarzin.lan";
};
EOT
}
variable "public_named_conf_local" {
default = <<EOT
//
// Do any local configuration here
//
// Consider adding the 1918 zones here, if they are not used in your
// organization
//include "/etc/bind/zones.rfc1918";
zone "viktorbarzin.me" {
type master;
file "/etc/bind/db.viktorbarzin.me";
};
EOT
}
variable "public_named_conf_options" {
default = <<EOT
options {
querylog yes;
directory "/tmp/";
listen-on {
any;
};
dnssec-validation auto;
allow-recursion {
none;
};
};
EOT
}

View file

@ -0,0 +1,130 @@
variable "tls_secret_name" {}
variable "tls_crt" {}
variable "tls_key" {}
resource "kubernetes_namespace" "website" {
metadata {
name = "website"
}
}
module "tls_secret" {
source = "../setup_tls_secret"
namespace = "website"
tls_secret_name = var.tls_secret_name
tls_crt = var.tls_crt
tls_key = var.tls_key
}
resource "kubernetes_deployment" "blog" {
metadata {
name = "blog"
namespace = "website"
labels = {
run = "blog"
}
}
spec {
replicas = 3
selector {
match_labels = {
run = "blog"
}
}
template {
metadata {
labels = {
run = "blog"
}
}
spec {
container {
image = "viktorbarzin/blog:latest"
name = "blog"
resources {
limits = {
cpu = "0.5"
memory = "512Mi"
}
requests = {
cpu = "250m"
memory = "50Mi"
}
}
port {
container_port = 80
}
}
container {
image = "nginx/nginx-prometheus-exporter"
name = "nginx-exporter"
args = ["-nginx.scrape-uri", "http://127.0.0.1:8080/nginx_status"]
port {
container_port = 9113
}
}
}
}
}
}
resource "kubernetes_service" "blog" {
metadata {
name = "blog"
namespace = "website"
labels = {
"run" = "blog"
}
annotations = {
"prometheus.io/scrape" = "true"
"prometheus.io/path" = "/metrics"
"prometheus.io/port" = "9113"
}
}
spec {
selector = {
run = "blog"
}
port {
name = "http"
port = "80"
target_port = "80"
}
port {
name = "prometheus"
port = "9113"
target_port = "9113"
}
}
}
resource "kubernetes_ingress" "blog" {
metadata {
name = "blog-ingress"
namespace = "website"
annotations = {
"kubernetes.io/ingress.class" = "nginx"
}
}
spec {
tls {
hosts = ["viktorbarzin.me"]
secret_name = var.tls_secret_name
}
rule {
host = "viktorbarzin.me"
http {
path {
path = "/"
backend {
service_name = "blog"
service_port = "80"
}
}
}
}
}
}

View file

@ -0,0 +1,92 @@
resource "kubernetes_namespace" "dnscrypt" {
metadata {
name = "dnscrypt"
}
}
resource "kubernetes_config_map" "dnscrypt" {
metadata {
name = "dnscrypt-proxy-configmap"
namespace = "dnscrypt"
}
data = {
"dnscrypt-proxy.toml" = var.dnscrypt_proxy_toml
}
}
resource "kubernetes_deployment" "dnscrypt" {
metadata {
name = "dnscrypt-proxy"
namespace = "dnscrypt"
labels = {
app = "dnscrypt-proxy"
"kubernetes.io/cluster-service" = "true"
}
}
spec {
replicas = 3
selector {
match_labels = {
app = "dnscrypt-proxy"
}
}
template {
metadata {
labels = {
app = "dnscrypt-proxy"
"kubernetes.io/cluster-service" = "true"
}
}
spec {
container {
image = "gists/dnscrypt-proxy:latest"
name = "dnscrypt-proxy"
image_pull_policy = "IfNotPresent"
port {
container_port = 53
protocol = "UDP"
}
volume_mount {
name = "config"
mount_path = "/etc/dnscrypt-proxy/"
}
}
volume {
name = "config"
config_map {
name = "dnscrypt-proxy-configmap"
items {
key = "dnscrypt-proxy.toml"
path = "dnscrypt-proxy.toml"
}
}
}
}
}
}
}
resource "kubernetes_service" "dnscrypt" {
metadata {
name = "dnscrypt-proxy"
namespace = "dnscrypt"
labels = {
"app" = "dnscrypt-proxy"
}
annotations = {
"metallb.universe.tf/allow-shared-ip" = "shared"
}
}
spec {
type = "LoadBalancer"
selector = {
app = "dnscrypt-proxy"
}
port {
name = "dns"
protocol = "UDP"
port = "5353"
target_port = "53"
}
}
}

View file

@ -0,0 +1,707 @@
variable "dnscrypt_proxy_toml" {
default = <<EOT
##############################################
# #
# dnscrypt-proxy configuration #
# #
##############################################
## This is an example configuration file.
## You should adjust it to your needs, and save it as "dnscrypt-proxy.toml"
##
## Online documentation is available here: https://dnscrypt.info/doc
##################################
# Global settings #
##################################
## List of servers to use
##
## Servers from the "public-resolvers" source (see down below) can
## be viewed here: https://dnscrypt.info/public-servers
##
## The proxy will automatically pick working servers from this list.
## Note that the require_* filters do NOT apply when using this setting.
##
## By default, this list is empty and all registered servers matching the
## require_* filters will be used instead.
##
## Remove the leading # first to enable this; lines starting with # are ignored.
# server_names = ['scaleway-fr', 'google', 'yandex', 'cloudflare']
## List of local addresses and ports to listen to. Can be IPv4 and/or IPv6.
## Example with both IPv4 and IPv6:
## listen_addresses = ['127.0.0.1:53', '[::1]:53']
listen_addresses = ['0.0.0.0:53']
## Maximum number of simultaneous client connections to accept
max_clients = 250
## Switch to a different system user after listening sockets have been created.
## Note (1): this feature is currently unsupported on Windows.
## Note (2): this feature is not compatible with systemd socket activation.
## Note (3): when using -pidfile, the PID file directory must be writable by the new user
# user_name = 'nobody'
## Require servers (from static + remote sources) to satisfy specific properties
# Use servers reachable over IPv4
ipv4_servers = true
# Use servers reachable over IPv6 -- Do not enable if you don't have IPv6 connectivity
ipv6_servers = false
# Use servers implementing the DNSCrypt protocol
dnscrypt_servers = true
# Use servers implementing the DNS-over-HTTPS protocol
doh_servers = true
## Require servers defined by remote sources to satisfy specific properties
# Server must support DNS security extensions (DNSSEC)
require_dnssec = false
# Server must not log user queries (declarative)
require_nolog = true
# Server must not enforce its own blacklist (for parental control, ads blocking...)
require_nofilter = true
# Server names to avoid even if they match all criteria
disabled_server_names = []
## Always use TCP to connect to upstream servers.
## This can be useful if you need to route everything through Tor.
## Otherwise, leave this to `false`, as it doesn't improve security
## (dnscrypt-proxy will always encrypt everything even using UDP), and can
## only increase latency.
force_tcp = false
## SOCKS proxy
## Uncomment the following line to route all TCP connections to a local Tor node
## Tor doesn't support UDP, so set `force_tcp` to `true` as well.
# proxy = 'socks5://127.0.0.1:9050'
## HTTP/HTTPS proxy
## Only for DoH servers
# http_proxy = 'http://127.0.0.1:8888'
## How long a DNS query will wait for a response, in milliseconds.
## If you have a network with *a lot* of latency, you may need to
## increase this. Startup may be slower if you do so.
## Don't increase it too much. 10000 is the highest reasonable value.
timeout = 5000
## Keepalive for HTTP (HTTPS, HTTP/2) queries, in seconds
keepalive = 30
## Response for blocked queries. Options are `refused`, `hinfo` (default) or
## an IP response. To give an IP response, use the format `a:<IPv4>,aaaa:<IPv6>`.
## Using the `hinfo` option means that some responses will be lies.
## Unfortunately, the `hinfo` option appears to be required for Android 8+
# blocked_query_response = 'refused'
## Load-balancing strategy: 'p2' (default), 'ph', 'first' or 'random'
# lb_strategy = 'p2'
## Set to `true` to constantly try to estimate the latency of all the resolvers
## and adjust the load-balancing parameters accordingly, or to `false` to disable.
# lb_estimator = true
## Log level (0-6, default: 2 - 0 is very verbose, 6 only contains fatal errors)
# log_level = 2
## log file for the application
# log_file = 'dnscrypt-proxy.log'
## Use the system logger (syslog on Unix, Event Log on Windows)
use_syslog = true
## Delay, in minutes, after which certificates are reloaded
cert_refresh_delay = 240
## DNSCrypt: Create a new, unique key for every single DNS query
## This may improve privacy but can also have a significant impact on CPU usage
## Only enable if you don't have a lot of network load
# dnscrypt_ephemeral_keys = false
## DoH: Disable TLS session tickets - increases privacy but also latency
# tls_disable_session_tickets = false
## DoH: Use a specific cipher suite instead of the server preference
## 49199 = TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
## 49195 = TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
## 52392 = TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
## 52393 = TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305
## 4865 = TLS_AES_128_GCM_SHA256
## 4867 = TLS_CHACHA20_POLY1305_SHA256
##
## On non-Intel CPUs such as MIPS routers and ARM systems (Android, Raspberry Pi...),
## the following suite improves performance.
## This may also help on Intel CPUs running 32-bit operating systems.
##
## Keep tls_cipher_suite empty if you have issues fetching sources or
## connecting to some DoH servers. Google and Cloudflare are fine with it.
# tls_cipher_suite = [52392, 49199]
## Fallback resolvers
## These are normal, non-encrypted DNS resolvers, that will be only used
## for one-shot queries when retrieving the initial resolvers list, and
## only if the system DNS configuration doesn't work.
## No user application queries will ever be leaked through these resolvers,
## and they will not be used after IP addresses of resolvers URLs have been found.
## They will never be used if lists have already been cached, and if stamps
## don't include host names without IP addresses.
## They will not be used if the configured system DNS works.
## Resolvers supporting DNSSEC are recommended.
##
## People in China may need to use 114.114.114.114:53 here.
## Other popular options include 8.8.8.8 and 1.1.1.1.
##
## If more than one resolver is specified, they will be tried in sequence.
# fallback_resolvers = ['9.9.9.9:53', '8.8.8.8:53']
## Always use the fallback resolver before the system DNS settings.
ignore_system_dns = true
## Maximum time (in seconds) to wait for network connectivity before
## initializing the proxy.
## Useful if the proxy is automatically started at boot, and network
## connectivity is not guaranteed to be immediately available.
## Use 0 to not test for connectivity at all (not recommended),
## and -1 to wait as much as possible.
netprobe_timeout = 60
## Address and port to try initializing a connection to, just to check
## if the network is up. It can be any address and any port, even if
## there is nothing answering these on the other side. Just don't use
## a local address, as the goal is to check for Internet connectivity.
## On Windows, a datagram with a single, nul byte will be sent, only
## when the system starts.
## On other operating systems, the connection will be initialized
## but nothing will be sent at all.
netprobe_address = '9.9.9.9:53'
## Offline mode - Do not use any remote encrypted servers.
## The proxy will remain fully functional to respond to queries that
## plugins can handle directly (forwarding, cloaking, ...)
# offline_mode = false
## Additional data to attach to outgoing queries.
## These strings will be added as TXT records to queries.
## Do not use, except on servers explicitly asking for extra data
## to be present.
## encrypted-dns-server can be configured to use this for access control
## in the [access_control] section
# query_meta = ["key1:value1", "key2:value2", "token:MySecretToken"]
## Automatic log files rotation
# Maximum log files size in MB - Set to 0 for unlimited.
log_files_max_size = 10
# How long to keep backup files, in days
log_files_max_age = 7
# Maximum log files backups to keep (or 0 to keep all backups)
log_files_max_backups = 1
#########################
# Filters #
#########################
## Note: if you are using dnsmasq, disable the `dnssec` option in dnsmasq if you
## configure dnscrypt-proxy to do any kind of filtering (including the filters
## below and blacklists).
## You can still choose resolvers that do DNSSEC validation.
## Immediately respond to IPv6-related queries with an empty response
## This makes things faster when there is no IPv6 connectivity, but can
## also cause reliability issues with some stub resolvers.
block_ipv6 = false
## Immediately respond to A and AAAA queries for host names without a domain name
block_unqualified = true
## Immediately respond to queries for local zones instead of leaking them to
## upstream resolvers (always causing errors or timeouts).
# block_undelegated = true
## TTL for synthetic responses sent when a request has been blocked (due to
## IPv6 or blacklists).
reject_ttl = 600
##################################################################################
# Route queries for specific domains to a dedicated set of servers #
##################################################################################
## See the `example-forwarding-rules.txt` file for an example
# forwarding_rules = 'forwarding-rules.txt'
###############################
# Cloaking rules #
###############################
## Cloaking returns a predefined address for a specific name.
## In addition to acting as a HOSTS file, it can also return the IP address
## of a different name. It will also do CNAME flattening.
##
## See the `example-cloaking-rules.txt` file for an example
# cloaking_rules = 'cloaking-rules.txt'
## TTL used when serving entries in cloaking-rules.txt
# cloak_ttl = 600
###########################
# DNS cache #
###########################
## Enable a DNS cache to reduce latency and outgoing traffic
cache = true
## Cache size
cache_size = 4096
## Minimum TTL for cached entries
cache_min_ttl = 2400
## Maximum TTL for cached entries
cache_max_ttl = 86400
## Minimum TTL for negatively cached entries
cache_neg_min_ttl = 60
## Maximum TTL for negatively cached entries
cache_neg_max_ttl = 600
##################################
# Local DoH server #
##################################
[local_doh]
## dnscrypt-proxy can act as a local DoH server. By doing so, web browsers
## requiring a direct connection to a DoH server in order to enable some
## features will enable these, without bypassing your DNS proxy.
## Addresses that the local DoH server should listen to
# listen_addresses = ['127.0.0.1:3000']
## Path of the DoH URL. This is not a file, but the part after the hostname
## in the URL. By convention, `/dns-query` is frequently chosen.
## For each `listen_address` the complete URL to access the server will be:
## `https://<listen_address><path>` (ex: `https://127.0.0.1/dns-query`)
# path = "/dns-query"
## Certificate file and key - Note that the certificate has to be trusted.
## See the documentation (wiki) for more information.
# cert_file = "localhost.pem"
# cert_key_file = "localhost.pem"
###############################
# Query logging #
###############################
## Log client queries to a file
[query_log]
## Path to the query log file (absolute, or relative to the same directory as the config file)
## On non-Windows systems, can be /dev/stdout to log to the standard output (also set log_files_max_size to 0)
# file = 'query.log'
file = '/dev/stdout'
## Query log format (currently supported: tsv and ltsv)
format = 'tsv'
## Do not log these query types, to reduce verbosity. Keep empty to log everything.
# ignored_qtypes = ['DNSKEY', 'NS']
############################################
# Suspicious queries logging #
############################################
## Log queries for nonexistent zones
## These queries can reveal the presence of malware, broken/obsolete applications,
## and devices signaling their presence to 3rd parties.
[nx_log]
## Path to the query log file (absolute, or relative to the same directory as the config file)
# file = 'nx.log'
## Query log format (currently supported: tsv and ltsv)
format = 'tsv'
######################################################
# Pattern-based blocking (blacklists) #
######################################################
## Blacklists are made of one pattern per line. Example of valid patterns:
##
## example.com
## =example.com
## *sex*
## ads.*
## ads*.example.*
## ads*.example[0-9]*.com
##
## Example blacklist files can be found at https://download.dnscrypt.info/blacklists/
## A script to build blacklists from public feeds can be found in the
## `utils/generate-domains-blacklists` directory of the dnscrypt-proxy source code.
[blacklist]
## Path to the file of blocking rules (absolute, or relative to the same directory as the config file)
# blacklist_file = 'blacklist.txt'
## Optional path to a file logging blocked queries
# log_file = 'blocked.log'
## Optional log format: tsv or ltsv (default: tsv)
# log_format = 'tsv'
###########################################################
# Pattern-based IP blocking (IP blacklists) #
###########################################################
## IP blacklists are made of one pattern per line. Example of valid patterns:
##
## 127.*
## fe80:abcd:*
## 192.168.1.4
[ip_blacklist]
## Path to the file of blocking rules (absolute, or relative to the same directory as the config file)
# blacklist_file = 'ip-blacklist.txt'
## Optional path to a file logging blocked queries
# log_file = 'ip-blocked.log'
## Optional log format: tsv or ltsv (default: tsv)
# log_format = 'tsv'
######################################################
# Pattern-based whitelisting (blacklists bypass) #
######################################################
## Whitelists support the same patterns as blacklists
## If a name matches a whitelist entry, the corresponding session
## will bypass names and IP filters.
##
## Time-based rules are also supported to make some websites only accessible at specific times of the day.
[whitelist]
## Path to the file of whitelisting rules (absolute, or relative to the same directory as the config file)
# whitelist_file = 'whitelist.txt'
## Optional path to a file logging whitelisted queries
# log_file = 'whitelisted.log'
## Optional log format: tsv or ltsv (default: tsv)
# log_format = 'tsv'
##########################################
# Time access restrictions #
##########################################
## One or more weekly schedules can be defined here.
## Patterns in the name-based blocklist can optionally be followed with @schedule_name
## to apply the pattern 'schedule_name' only when it matches a time range of that schedule.
##
## For example, the following rule in a blacklist file:
## *.youtube.* @time-to-sleep
## would block access to YouTube during the times defined by the 'time-to-sleep' schedule.
##
## {after='21:00', before= '7:00'} matches 0:00-7:00 and 21:00-0:00
## {after= '9:00', before='18:00'} matches 9:00-18:00
[schedules]
# [schedules.'time-to-sleep']
# mon = [{after='21:00', before='7:00'}]
# tue = [{after='21:00', before='7:00'}]
# wed = [{after='21:00', before='7:00'}]
# thu = [{after='21:00', before='7:00'}]
# fri = [{after='23:00', before='7:00'}]
# sat = [{after='23:00', before='7:00'}]
# sun = [{after='21:00', before='7:00'}]
# [schedules.'work']
# mon = [{after='9:00', before='18:00'}]
# tue = [{after='9:00', before='18:00'}]
# wed = [{after='9:00', before='18:00'}]
# thu = [{after='9:00', before='18:00'}]
# fri = [{after='9:00', before='17:00'}]
#########################
# Servers #
#########################
## Remote lists of available servers
## Multiple sources can be used simultaneously, but every source
## requires a dedicated cache file.
##
## Refer to the documentation for URLs of public sources.
##
## A prefix can be prepended to server names in order to
## avoid collisions if different sources share the same for
## different servers. In that case, names listed in `server_names`
## must include the prefixes.
##
## If the `urls` property is missing, cache files and valid signatures
## must already be present. This doesn't prevent these cache files from
## expiring after `refresh_delay` hours.
[sources]
## An example of a remote source from https://github.com/DNSCrypt/dnscrypt-resolvers
[sources.'public-resolvers']
urls = ['https://raw.githubusercontent.com/DNSCrypt/dnscrypt-resolvers/master/v2/public-resolvers.md', 'https://download.dnscrypt.info/resolvers-list/v2/public-resolvers.md']
cache_file = 'public-resolvers.md'
minisign_key = 'RWQf6LRCGA9i53mlYecO4IzT51TGPpvWucNSCh1CBM0QTaLn73Y7GFO3'
prefix = ''
## Anonymized DNS relays
[sources.'relays']
urls = ['https://raw.githubusercontent.com/DNSCrypt/dnscrypt-resolvers/master/v2/relays.md', 'https://download.dnscrypt.info/resolvers-list/v2/relays.md']
cache_file = 'relays.md'
minisign_key = 'RWQf6LRCGA9i53mlYecO4IzT51TGPpvWucNSCh1CBM0QTaLn73Y7GFO3'
refresh_delay = 72
prefix = ''
## Quad9 over DNSCrypt - https://quad9.net/
# [sources.quad9-resolvers]
# urls = ['https://www.quad9.net/quad9-resolvers.md']
# minisign_key = 'RWQBphd2+f6eiAqBsvDZEBXBGHQBJfeG6G+wJPPKxCZMoEQYpmoysKUN'
# cache_file = 'quad9-resolvers.md'
# prefix = 'quad9-'
## Another example source, with resolvers censoring some websites not appropriate for children
## This is a subset of the `public-resolvers` list, so enabling both is useless
# [sources.'parental-control']
# urls = ['https://raw.githubusercontent.com/DNSCrypt/dnscrypt-resolvers/master/v2/parental-control.md', 'https://download.dnscrypt.info/resolvers-list/v2/parental-control.md']
# cache_file = 'parental-control.md'
# minisign_key = 'RWQf6LRCGA9i53mlYecO4IzT51TGPpvWucNSCh1CBM0QTaLn73Y7GFO3'
#########################################
# Servers with known bugs #
#########################################
[broken_implementations]
# Cisco servers currently cannot handle queries larger than 1472 bytes, and don't
# truncate reponses larger than questions as expected by the DNSCrypt protocol.
# This prevents large responses from being received over UDP and over relays.
#
# The `dnsdist` server software drops client queries larger than 1500 bytes.
# They are aware of it and are working on a fix.
#
# The list below enables workarounds to make non-relayed usage more reliable
# until the servers are fixed.
# fragments_blocked = ['cisco', 'cisco-ipv6', 'cisco-familyshield', 'cisco-familyshield-ipv6', 'quad9-dnscrypt-ip4-filter-alt', 'quad9-dnscrypt-ip4-filter-pri', 'quad9-dnscrypt-ip4-nofilter-alt', 'quad9-dnscrypt-ip4-nofilter-pri', 'quad9-dnscrypt-ip6-filter-alt', 'quad9-dnscrypt-ip6-filter-pri', 'quad9-dnscrypt-ip6-nofilter-alt', 'quad9-dnscrypt-ip6-nofilter-pri', 'cleanbrowsing-adult', 'cleanbrowsing-family-ipv6', 'cleanbrowsing-family', 'cleanbrowsing-security']
#################################################################
# Certificate-based client authentication for DoH #
#################################################################
# Use a X509 certificate to authenticate yourself when connecting to DoH servers.
# This is only useful if you are operating your own, private DoH server(s).
# (for DNSCrypt, see the `query_meta` feature instead)
# [doh_client_x509_auth]
# creds = [
# { server_name='myserver', client_cert='client.crt', client_key='client.key' }
# ]
################################
# Anonymized DNS #
################################
[anonymized_dns]
## Routes are indirect ways to reach DNSCrypt servers.
##
## A route maps a server name ("server_name") to one or more relays that will be
## used to connect to that server.
##
## A relay can be specified as a DNS Stamp (either a relay stamp, or a
## DNSCrypt stamp), an IP:port, a hostname:port, or a server name.
##
## The following example routes "example-server-1" via `anon-example-1` or `anon-example-2`,
## and "example-server-2" via the relay whose relay DNS stamp
## is "sdns://gRIxMzcuNzQuMjIzLjIzNDo0NDM".
##
## !!! THESE ARE JUST EXAMPLES !!!
##
## Review the list of available relays from the "relays.md" file, and, for each
## server you want to use, define the relays you want connections to go through.
##
## Carefully choose relays and servers so that they are run by different entities.
##
## "server_name" can also be set to "*" to define a default route, but this is not
## recommended. If you do so, keep "server_names" short and distinct from relays.
# routes = [
# { server_name='example-server-1', via=['anon-example-1', 'anon-example-2'] },
# { server_name='example-server-2', via=['sdns://gRIxMzcuNzQuMjIzLjIzNDo0NDM'] }
# ]
# skip resolvers incompatible with anonymization instead of using them directly
# skip_incompatible = false
## Optional, local, static list of additional servers
## Mostly useful for testing your own servers.
[static]
# [static.'myserver']
# stamp = 'sdns:AQcAAAAAAAAAAAAQMi5kbnNjcnlwdC1jZXJ0Lg'
EOT
}

View file

@ -0,0 +1,113 @@
variable tls_secret_name {}
variable "tls_crt" {}
variable "tls_key" {}
resource "kubernetes_namespace" "f1-stream" {
metadata {
name = "f1-stream"
}
}
resource "kubernetes_deployment" "f1-stream" {
metadata {
name = "f1-stream"
namespace = "f1-stream"
labels = {
app = "f1-stream"
}
}
spec {
replicas = 3
selector {
match_labels = {
app = "f1-stream"
}
}
template {
metadata {
labels = {
app = "f1-stream"
}
}
spec {
container {
image = "viktorbarzin/f1-stream:latest"
name = "f1-stream"
resources {
limits = {
cpu = "0.5"
memory = "512Mi"
}
requests = {
cpu = "250m"
memory = "512Mi"
}
}
port {
container_port = 80
}
}
}
}
}
}
resource "kubernetes_service" "f1-stream" {
metadata {
name = "f1-stream"
namespace = "f1-stream"
labels = {
"app" = "f1-stream"
}
}
spec {
selector = {
app = "f1-stream"
}
port {
port = "80"
}
}
}
module "tls_secret" {
source = "../setup_tls_secret"
namespace = "f1-stream"
tls_secret_name = var.tls_secret_name
tls_crt = var.tls_crt
tls_key = var.tls_key
}
resource "kubernetes_ingress" "f1-stream" {
metadata {
name = "f1-ingress"
namespace = "f1-stream"
annotations = {
"kubernetes.io/ingress.class" = "nginx"
"nginx.ingress.kubernetes.io/force-ssl-redirect" : "false"
"nginx.ingress.kubernetes.io/ssl-redirect" : "false"
}
}
spec {
tls {
hosts = ["f1.viktorbarzin.me"]
secret_name = var.tls_secret_name
}
rule {
host = "f1.viktorbarzin.me"
http {
path {
path = "/"
backend {
service_name = "f1-stream"
service_port = "80"
}
}
}
}
}
}

View file

@ -0,0 +1,168 @@
variable "tls_secret_name" {}
variable "tls_crt" {}
variable "tls_key" {}
variable "hackmd_db_password" {}
resource "kubernetes_namespace" "hackmd" {
metadata {
name = "hackmd"
}
}
module "tls_secret" {
source = "../setup_tls_secret"
namespace = "hackmd"
tls_secret_name = var.tls_secret_name
tls_crt = var.tls_crt
tls_key = var.tls_key
}
resource "kubernetes_deployment" "hackmd" {
metadata {
name = "hackmd"
namespace = "hackmd"
labels = {
app = "hackmd"
"kubernetes.io/cluster-service" = "true"
}
}
spec {
replicas = 1
strategy {
type = "Recreate"
}
selector {
match_labels = {
app = "hackmd"
}
}
template {
metadata {
labels = {
app = "hackmd"
"kubernetes.io/cluster-service" = "true"
}
}
spec {
container {
image = "postgres:11.6-alpine"
name = "postgres"
image_pull_policy = "IfNotPresent"
env {
name = "POSTGRES_USER"
value = "codimd"
}
env {
name = "POSTGRES_PASSWORD"
value = var.hackmd_db_password
}
env {
name = "POSTGRES_DB"
value = "codimd"
}
resources {
limits = {
cpu = "1"
memory = "1Gi"
}
requests = {
cpu = "1"
memory = "1Gi"
}
}
port {
container_port = 80
}
volume_mount {
name = "data"
mount_path = "/var/lib/postgresql/data"
sub_path = "postgres"
}
}
container {
name = "codumd"
image = "nabo.codimd.dev/hackmdio/hackmd:2.0.1"
image_pull_policy = "IfNotPresent"
env {
name = "CMD_DB_URL"
value = format("%s%s%s", "postgres://codimd:", var.hackmd_db_password, "@localhost/codimd")
}
env {
name = "CMD_USECDN"
value = "false"
}
volume_mount {
name = "data"
mount_path = "/home/hackmd/app/public/uploads"
sub_path = "hackmd"
}
port {
name = "http"
container_port = 3000
protocol = "TCP"
}
}
volume {
name = "data"
iscsi {
target_portal = "iscsi.viktorbarzin.lan:3260"
fs_type = "ext4"
iqn = "iqn.2020-12.lan.viktorbarzin:storage:hackmd"
lun = 0
read_only = false
}
}
}
}
}
}
resource "kubernetes_service" "hackmd" {
metadata {
name = "hackmd"
namespace = "hackmd"
labels = {
"app" = "hackmd"
}
}
spec {
selector = {
app = "hackmd"
}
port {
port = "80"
target_port = "3000"
}
}
}
resource "kubernetes_ingress" "hackmd" {
metadata {
name = "hackmd-ingress"
namespace = "hackmd"
annotations = {
"kubernetes.io/ingress.class" = "nginx"
}
}
spec {
tls {
hosts = ["hackmd.viktorbarzin.me"]
secret_name = var.tls_secret_name
}
rule {
host = "hackmd.viktorbarzin.me"
http {
path {
path = "/"
backend {
service_name = "hackmd"
service_port = "80"
}
}
}
}
}
}

View file

@ -0,0 +1,12 @@
#!/bin/bash
user="user"
pass="pass"
# Get power supply on outside system voltage
curl -s -k -u $user:$pass -H"Content-type: application/json" -X GET https://idrac/redfish/v1/Chassis/System.Embedded.1/Power/PowerSupplies/PSU.Slot.2 |jq .LineInputVoltage
# Power off
curl -s -k -u $user:$pass -X POST -d '{"Action": "Reset", "ResetType": "GracefulShutdown"}' -H"Content-type: application/json" https://idrac/redfish/v1/Systems/System.Embedded.1/Actions/ComputerSystem.Reset
# Power on
curl -s -k -u $user:$pass -X POST -d '{"Action": "Reset", "ResetType": "On"}' -H"Content-type: application/json" https://idrac/redfish/v1/Systems/System.Embedded.1/Actions/ComputerSystem.Reset

View file

@ -0,0 +1,95 @@
variable "tls_secret_name" {}
variable "tls_crt" {}
variable "tls_key" {}
variable "client_certificate_secret_name" {}
module "dashboard" {
# source = "cookielab/dashboard/kubernetes"
# source = "ViktorBarzin/dashboard/kubernetes"
# version = "0.13.0"
# TODO: update this once merged
source = "/opt/terraform-kubernetes-dashboard"
# insert the 1 required variable here
kubernetes_dashboard_csrf = "kekerino"
kubernetes_dashboard_deployment_args = list(
"--auto-generate-certificates",
"--token-ttl=0"
)
}
module "tls_secret" {
source = "../setup_tls_secret"
namespace = "kubernetes-dashboard"
tls_secret_name = var.tls_secret_name
tls_crt = var.tls_crt
tls_key = var.tls_key
}
# # locals {
# # resources = split("---\n", file("${path.module}/recommended.yaml"))
# # }
# # resource "k8s_manifest" "kubernetes-dashboard-manifests" {
# # count = length(local.resources) - 1
# # # count = 2
# # # content = local.resources[1 + count.index]
# # # content = file("${path.module}/recommended.yaml")
# # content = local.resources[1]
# # depends_on = [kubernetes_namespace.kubernetes-dashboard]
# # }
# resource "kubectl_manifest" "kubernetes-dashboard-manifests" {
# yaml_body = file("${path.module}/recommended.yaml")
# force_new = true
# depends_on = [kubernetes_namespace.kubernetes-dashboard]
# }
resource "kubernetes_ingress" "kubernetes-dashboard" {
metadata {
name = "kubernetes-dashboard"
namespace = "kubernetes-dashboard"
annotations = {
"kubernetes.io/ingress.class" = "nginx"
"nginx.ingress.kubernetes.io/backend-protocol" = "HTTPS"
"nginx.ingress.kubernetes.io/force-ssl-redirect" = "true"
"nginx.ingress.kubernetes.io/auth-tls-verify-client" = "on"
"nginx.ingress.kubernetes.io/auth-tls-secret" = var.client_certificate_secret_name
}
}
spec {
tls {
hosts = ["k8s.viktorbarzin.me"]
secret_name = var.tls_secret_name
}
rule {
host = "k8s.viktorbarzin.me"
http {
path {
path = "/"
backend {
service_name = "kubernetes-dashboard"
service_port = "443"
}
}
}
}
}
depends_on = [module.dashboard]
}
# Give cluster-admin permissions to dashboard
resource "kubernetes_cluster_role_binding" "kubernetes-dashboard" {
metadata {
name = "admin-user"
}
role_ref {
api_group = "rbac.authorization.k8s.io"
kind = "ClusterRole"
name = "cluster-admin"
}
subject {
kind = "ServiceAccount"
name = "kubernetes-dashboard"
namespace = "kubernetes-dashboard"
}
depends_on = [module.dashboard]
}

View file

@ -0,0 +1,209 @@
variable "tls_secret_name" {}
variable "tls_crt" {}
variable "tls_key" {}
resource "kubernetes_namespace" "kms" {
metadata {
name = "kms"
}
}
module "tls_secret" {
source = "../setup_tls_secret"
namespace = "kms"
tls_secret_name = var.tls_secret_name
tls_crt = var.tls_crt
tls_key = var.tls_key
}
resource "kubernetes_config_map" "kms-web-page" {
metadata {
name = "kms-web-page-config"
namespace = "kms"
}
data = {
"index.html" = var.index_html
}
}
resource "kubernetes_deployment" "kms-web-page" {
metadata {
name = "kms-web-page"
namespace = "kms"
labels = {
"app" = "kms-web-page"
"kubernetes.io/cluster-service" = "true"
}
}
spec {
replicas = 3
selector {
match_labels = {
"app" = "kms-web-page"
}
}
template {
metadata {
labels = {
"app" = "kms-web-page"
"kubernetes.io/cluster-service" = "true"
}
}
spec {
container {
image = "nginx"
name = "kms-web-page"
image_pull_policy = "IfNotPresent"
resources {
limits = {
cpu = "0.5"
memory = "512Mi"
}
requests = {
cpu = "0.5"
memory = "512Mi"
}
}
port {
container_port = 80
protocol = "TCP"
}
volume_mount {
name = "config"
mount_path = "/usr/share/nginx/html/"
}
}
volume {
name = "config"
config_map {
name = "kms-web-page-config"
items {
key = "index.html"
path = "index.html"
}
}
}
}
}
}
depends_on = [kubernetes_config_map.kms-web-page]
}
resource "kubernetes_service" "kms-web-page" {
metadata {
name = "kms-web-page"
namespace = "kms"
labels = {
"app" = "kms-web-page"
}
}
spec {
selector = {
"app" = "kms-web-page"
}
port {
port = "80"
protocol = "TCP"
}
}
}
resource "kubernetes_ingress" "kms-web-page" {
metadata {
name = "kms-web-page"
namespace = "kms"
annotations = {
"kubernetes.io/ingress.class" = "nginx"
}
}
spec {
tls {
hosts = ["kms.viktorbarzin.me"]
secret_name = var.tls_secret_name
}
rule {
host = "kms.viktorbarzin.me"
http {
path {
path = "/"
backend {
service_name = "kms-web-page"
service_port = "80"
}
}
}
}
}
}
resource "kubernetes_deployment" "windows_kms" {
metadata {
name = "kms"
namespace = "kms"
labels = {
app = "kms-service"
}
}
spec {
replicas = 1
selector {
match_labels = {
app = "kms-service"
}
}
template {
metadata {
labels = {
app = "kms-service"
}
}
spec {
container {
image = "kebe/vlmcsd:latest"
name = "windows-kms"
resources {
limits = {
cpu = "1"
memory = "512Mi"
}
requests = {
cpu = "1"
memory = "50Mi"
}
}
port {
container_port = 1688
}
}
}
}
}
}
resource "kubernetes_service" "windows_kms" {
metadata {
name = "windows-kms"
namespace = "kms"
labels = {
"app" = "windows-kms"
}
annotations = {
"metallb.universe.tf/allow-shared-ip" = "shared"
}
}
spec {
type = "LoadBalancer"
external_traffic_policy = "Cluster"
selector = {
"app" = "windows-kms"
}
port {
port = "1688"
}
}
}

View file

@ -0,0 +1,68 @@
variable "index_html" {
default = <<EOT
<h1>How to activate windows</h1>
Open the following link and find a key for you version of windows: </br>
<b><a href="https://goo.gl/BcrPjW" target="_blank">https://goo.gl/BcrPjW</a></b>
</br>
</br>
Open cmd as <b>Administrator</b> and run the following: </br>
</br>
<b>slmgr.vbs /ipk key_for_your_windows</b>
</br>
<b>slmgr.vbs /skms kms.viktorbarzin.me </b>
<br>
<b>
slmgr /ato
</b>
<br>
<p>
<h3> If you have an evaluation windows, you need to change it to retail one. This is how:</h3>
<br>
From an elevated command prompt, determine the current edition name with the command <br>
<strong>DISM /online /Get-CurrentEdition</strong>.
<br>Make note of the edition ID, an abbreviated form of the edition name. Then run
<br>
<strong>DISM /online /Set-Edition:<edition ID> /ProductKey:XXXXX-XXXXX-XXXXX-XXXXX-XXXXX /AcceptEula</strong>
<br> providing the edition ID and a retail product key. The server will restart
</p>
<hr>
<h1>How to activate Microsoft Office</h1>
<br>
<b>
CD \Program Files\Microsoft Office\Office16 </b> OR <b>CD \Program Files (x86)\Microsoft Office\Office16
</b>
<br>
<b>
cscript ospp.vbs /sethst:kms.viktorbarzin.me
</b>
<br>
<b>
cscript ospp.vbs /inpkey:xxxxx-xxxxx-xxxxx-xxxxx-xxxxx
</b>
<br>
where 'xxxx' is a key for your office. Some examples for office 2016 - <a
href="https://www.techdee.com/microsoft-office-2016-product-key/">https://www.techdee.com/microsoft-office-2016-product-key/</a>
<br>
<b>
cscript ospp.vbs /act
</b>
<br>
<br>
If you messed up activation settings reset them using
<br>
slmgr /upk
<br>
slmgr /cpky
<br>
and
<br>
slmgr /rearm
<h3>Buy me a beer :P</h3>
EOT
}

View file

@ -0,0 +1,65 @@
variable "mailserver_accounts" {}
variable postfix_account_aliases {}
resource "kubernetes_namespace" "mailserver" {
metadata {
name = "mailserver"
}
}
resource "kubernetes_config_map" "mailserver_env_config" {
metadata {
name = "mailserver.env.config"
namespace = "mailserver"
labels = {
app = "mailserver"
}
}
data = {
DMS_DEBUG = "0"
ENABLE_CLAMAV = "0"
ENABLE_FAIL2BAN = "1"
ENABLE_FETCHMAIL = "0"
ENABLE_POSTGREY = "0"
ENABLE_SPAMASSASSIN = "0"
ENABLE_SRS = "1"
FETCHMAIL_POLL = "120"
ONE_DIR = "1"
OVERRIDE_HOSTNAME = "mail.viktorbarzin.me"
TLS_LEVEL = "intermediate"
}
}
locals {
postfix_accounts_cf = join("\n", [for user, pass in var.mailserver_accounts : "${user}|${bcrypt(pass, 6)}"])
# postfix_accounts_cf = join("\n", [for user, pass in var.mailserver_accounts : format("%s%s%s", user, "|{SHA512-CRYPT}$6$$", sha512(pass))]) # Does not work :/
}
resource "kubernetes_config_map" "mailserver_config" {
metadata {
name = "mailserver.config"
namespace = "mailserver"
labels = {
app = "mailserver"
}
}
data = {
# Actual mail settings
"postfix-accounts.cf" = local.postfix_accounts_cf
"postfix-main.cf" = var.postfix_cf
"postfix-virtual.cf" = var.postfix_account_aliases
KeyTable = "mail._domainkey.viktorbarzin.me viktorbarzin.me:mail:/etc/opendkim/keys/viktorbarzin.me-mail.key\n"
SigningTable = "*@viktorbarzin.me mail._domainkey.viktorbarzin.me\n"
TrustedHosts = "127.0.0.1\nlocalhost\n"
}
# Password hashes are different each time and avoid changing secret constantly.
# Either 1.Create consistent hashes or 2.Find a way to ignore_changes on per password
lifecycle {
ignore_changes = [data["postfix-accounts.cf"]]
}
}

View file

@ -0,0 +1,118 @@
variable "postfix_cf" {
default = <<EOT
# See /usr/share/postfix/main.cf.dist for a commented, more complete version
smtpd_banner = $myhostname ESMTP $mail_name (Debian)
biff = no
append_dot_mydomain = no
readme_directory = no
# Basic configuration
# myhostname =
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
mydestination = $myhostname, localhost.$mydomain, localhost
relayhost =
mynetworks = 127.0.0.0/8 [::1]/128 [fe80::]/64 10.47.0.11/32
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all
inet_protocols = ipv4
# TLS parameters
smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
#smtpd_tls_CAfile=
#smtp_tls_CAfile=
smtpd_tls_security_level = may
smtpd_use_tls=yes
smtpd_tls_loglevel = 1
smtp_tls_security_level = may
smtp_tls_loglevel = 1
tls_ssl_options = NO_COMPRESSION
tls_high_cipherlist = ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS
tls_preempt_cipherlist = yes
smtpd_tls_protocols = !SSLv2,!SSLv3
smtp_tls_protocols = !SSLv2,!SSLv3
smtpd_tls_mandatory_ciphers = high
smtpd_tls_mandatory_protocols = !SSLv2,!SSLv3
smtpd_tls_exclude_ciphers = aNULL, LOW, EXP, MEDIUM, ADH, AECDH, MD5, DSS, ECDSA, CAMELLIA128, 3DES, CAMELLIA256, RSA+AES, eNULL
smtpd_tls_dh1024_param_file = /etc/postfix/dhparams.pem
smtpd_tls_CApath = /etc/ssl/certs
smtp_tls_CApath = /etc/ssl/certs
# Settings to prevent SPAM early
smtpd_helo_required = yes
smtpd_delay_reject = yes
smtpd_helo_restrictions = permit_mynetworks, reject_invalid_helo_hostname, permit
smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_unauth_destination
smtpd_recipient_restrictions = permit_sasl_authenticated, permit_mynetworks, reject_unauth_destination, reject_unauth_pipelining, reject_invalid_helo_hostname, reject_non_fqdn_helo_hostname, reject_unknown_recipient_domain, reject_rbl_client zen.spamhaus.org, reject_rbl_client bl.spamcop.net
smtpd_client_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination, reject_unauth_pipelining
smtpd_sender_restrictions = permit_sasl_authenticated, permit_mynetworks, reject_unknown_sender_domain
disable_vrfy_command = yes
# Postscreen settings to drop zombies/open relays/spam early
postscreen_dnsbl_action = enforce
postscreen_dnsbl_sites = zen.spamhaus.org*3
bl.mailspike.net
b.barracudacentral.org*2
bl.spameatingmonkey.net
bl.spamcop.net
dnsbl.sorbs.net
psbl.surriel.com
list.dnswl.org=127.0.[0..255].0*-2
list.dnswl.org=127.0.[0..255].1*-3
list.dnswl.org=127.0.[0..255].[2..3]*-4
postscreen_dnsbl_threshold = 3
postscreen_dnsbl_whitelist_threshold = -1
postscreen_greet_action = enforce
postscreen_bare_newline_action = enforce
# SASL
smtpd_sasl_auth_enable = yes
smtpd_sasl_path = /var/spool/postfix/private/auth
smtpd_sasl_type = dovecot
smtpd_sasl_security_options = noanonymous
smtpd_sasl_local_domain = $mydomain
broken_sasl_auth_clients = yes
# Mail directory
virtual_transport = lmtp:unix:/var/run/dovecot/lmtp
virtual_mailbox_domains = /etc/postfix/vhost
virtual_mailbox_maps = texthash:/etc/postfix/vmailbox
virtual_alias_maps = texthash:/etc/postfix/virtual
# Additional option for filtering
content_filter = smtp-amavis:[127.0.0.1]:10024
# Milters used by DKIM
milter_protocol = 6
milter_default_action = accept
dkim_milter = inet:localhost:8891
dmarc_milter = inet:localhost:8893
smtpd_milters = $dkim_milter,$dmarc_milter
non_smtpd_milters = $dkim_milter
# SPF policy settings
policyd-spf_time_limit = 3600
# Header checks for content inspection on receiving
header_checks = pcre:/etc/postfix/maps/header_checks.pcre
# Remove unwanted headers that reveail our privacy
smtp_header_checks = pcre:/etc/postfix/maps/sender_header_filter.pcre
myhostname = mail.viktorbarzin.me
mydomain = viktorbarzin.me
smtputf8_enable = no
message_size_limit = 10240000
sender_canonical_maps = tcp:localhost:10001
sender_canonical_classes = envelope_sender
recipient_canonical_maps = tcp:localhost:10002
recipient_canonical_classes = envelope_recipient,header_recipient
compatibility_level = 2
always_add_missing_headers = yes
EOT
}

133
modules/kubernetes/main.tf Normal file
View file

@ -0,0 +1,133 @@
variable "tls_secret_name" {}
variable "tls_crt" {}
variable "tls_key" {}
variable "client_certificate_secret_name" {}
variable "hackmd_db_password" {}
variable "mailserver_accounts" {}
variable "mailserver_aliases" {}
variable "pihole_web_password" {}
variable "webhook_handler_secret" {}
variable "wireguard_wg_0_conf" {}
variable "wireguard_wg_0_key" {}
variable "wireguard_firewall_sh" {}
variable "bind_db_viktorbarzin_me" {}
variable "bind_db_viktorbarzin_lan" {}
variable "bind_named_conf_options" {}
variable "alertmanager_account_password" {}
module "blog" {
source = "./blog"
tls_secret_name = var.tls_secret_name
tls_crt = var.tls_crt
tls_key = var.tls_key
}
module "bind" {
source = "./bind"
db_viktorbarzin_me = var.bind_db_viktorbarzin_me
db_viktorbarzin_lan = var.bind_db_viktorbarzin_lan
named_conf_options = var.bind_named_conf_options
}
module "dnscrypt" {
source = "./dnscrypt"
}
module "f1-stream" {
source = "./f1-stream"
tls_secret_name = var.tls_secret_name
tls_crt = var.tls_crt
tls_key = var.tls_key
}
module "hackmd" {
source = "./hackmd"
hackmd_db_password = var.hackmd_db_password
tls_secret_name = var.tls_secret_name
tls_crt = var.tls_crt
tls_key = var.tls_key
}
# TODO
# module "ingress-nginx" {
# source = "./ingress-nginx"
# }
module "kms" {
source = "./kms"
tls_secret_name = var.tls_secret_name
tls_crt = var.tls_crt
tls_key = var.tls_key
}
# TODO
# module "kube-system"{}
module "k8s-dashboard" {
source = "./k8s-dashboard"
tls_secret_name = var.tls_secret_name
tls_crt = var.tls_crt
tls_key = var.tls_key
client_certificate_secret_name = var.client_certificate_secret_name
}
module "mailserver" {
source = "./mailserver"
mailserver_accounts = var.mailserver_accounts
postfix_account_aliases = var.mailserver_aliases
}
module "metallb" {
source = "./metallb"
}
module monitoring {
source = "./monitoring"
tls_secret_name = var.tls_secret_name
tls_crt = var.tls_crt
tls_key = var.tls_key
alertmanager_account_password = var.alertmanager_account_password
}
module openid_help_page {
source = "./openid_help_page"
tls_secret_name = var.tls_secret_name
tls_crt = var.tls_crt
tls_key = var.tls_key
}
module pihole {
source = "./pihole"
web_password = var.pihole_web_password
tls_secret_name = var.tls_secret_name
tls_crt = var.tls_crt
tls_key = var.tls_key
depends_on = [module.bind] # DNS goes like pihole -> bind -> dnscrypt
}
module privatebin {
source = "./privatebin"
tls_secret_name = var.tls_secret_name
tls_crt = var.tls_crt
tls_key = var.tls_key
}
module webhook_handler {
source = "./webhook_handler"
tls_secret_name = var.tls_secret_name
tls_crt = var.tls_crt
tls_key = var.tls_key
webhook_secret = var.webhook_handler_secret
}
module wireguard {
source = "./wireguard"
tls_secret_name = var.tls_secret_name
tls_crt = var.tls_crt
tls_key = var.tls_key
wg_0_conf = var.wireguard_wg_0_conf
wg_0_key = var.wireguard_wg_0_key
firewall_sh = var.wireguard_firewall_sh
}

View file

@ -0,0 +1,21 @@
# Creates namespace and everythin needed
module "metallb" {
source = "colinwilson/metallb/kubernetes"
version = "0.1.5"
}
resource "kubernetes_config_map" "config" {
metadata {
name = "config"
namespace = "metallb-system"
}
data = {
config = <<EOT
address-pools:
- name: default
protocol: layer2
addresses:
- 10.0.20.200-10.0.20.220
EOT
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,148 @@
variable "tls_secret_name" {}
variable "tls_crt" {}
variable "tls_key" {}
variable "alertmanager_account_password" {}
module "tls_secret" {
source = "../setup_tls_secret"
namespace = "monitoring"
tls_secret_name = var.tls_secret_name
tls_crt = var.tls_crt
tls_key = var.tls_key
}
resource "helm_release" "prometheus" {
namespace = "monitoring"
create_namespace = true
name = "prometheus"
repository = "https://prometheus-community.github.io/helm-charts"
chart = "prometheus"
values = [templatefile("${path.module}/prometheus_chart_values.tpl", { alertmanager_mail_pass = var.alertmanager_account_password })]
}
# Terraform get angry with the 30k values file :/ use ansible until solved
# resource "helm_release" "prometheus_snmp_exporter" {
# namespace = "monitoring"
# create_namespace = true
# name = "prometheus_exporter"
# repository = "https://prometheus-community.github.io/helm-charts"
# chart = "prometheus-snmp-exporter"
# values = [file("${path.module}/prometheus_snmp_chart_values.yaml")]
# }
resource "kubernetes_secret" "prometheus_grafana_datasource" {
metadata {
name = "prometheus-grafana-datasource"
namespace = "monitoring"
labels = {
grafana_datasource = "1"
}
}
data = {
"datasource.yaml" = <<EOT
# config file version
apiVersion: 1
# list of datasources that should be deleted from the database
#deleteDatasources:
# - name: Prometheus
# orgId: 1
# list of datasources to insert/update depending
# whats available in the database
datasources:
# <string, required> name of the datasource. Required
- name: Prometheus
# <string, required> datasource type. Required
type: prometheus
# <string, required> access mode. proxy or direct (Server or Browser in the UI). Required
access: proxy
# <int> org id. will default to orgId 1 if not specified
orgId: 1
# <string> url
url: http://prometheus-server
# <string> database password, if used
password:
# <string> database user, if used
user:
# <string> database name, if used
database:
# <bool> enable/disable basic auth
basicAuth:
# <string> basic auth username
basicAuthUser:
# <string> basic auth password
basicAuthPassword:
# <bool> enable/disable with credentials headers
withCredentials:
# <bool> mark as default datasource. Max one per org
isDefault:
# <map> fields that will be converted to json and stored in json_data
#jsonData:
# graphiteVersion: \"1.1\"
# tlsAuth: true
# tlsAuthWithCACert: true
# <string> json object of data that will be encrypted.
#secureJsonData:
# tlsCACert: \"...\"
# tlsClientCert: \"...\"
# tlsClientKey: \"...\"
version: 1
# <bool> allow users to edit datasources from the UI.
editable: false
EOT
}
type = "Opaque"
}
resource "kubernetes_persistent_volume" "prometheus_grafana_pv" {
metadata {
name = "grafana-iscsi-pv"
}
spec {
capacity = {
"storage" = "2Gi"
}
access_modes = ["ReadWriteOnce"]
persistent_volume_source {
iscsi {
target_portal = "iscsi.viktorbarzin.lan:3260"
iqn = "iqn.2020-12.lan.viktorbarzin:storage:monitoring:grafana"
lun = 0
fs_type = "ext4"
}
}
}
}
resource "kubernetes_persistent_volume_claim" "prometheus_grafana_pvc" {
metadata {
name = "grafana-iscsi-pvc"
namespace = "monitoring"
}
spec {
access_modes = ["ReadWriteOnce"]
resources {
requests = {
"storage" = "2Gi"
}
}
}
}
resource "helm_release" "grafana" {
namespace = "monitoring"
create_namespace = true
name = "grafana"
repository = "https://grafana.github.io/helm-charts"
chart = "grafana"
values = [file("${path.module}/grafana_chart_values.yaml")]
}

View file

@ -0,0 +1,176 @@
# Helm values
# all values - https://github.com/prometheus-community/helm-charts/blob/main/charts/prometheus/values.yaml
alertmanager:
persistentVolume:
# enabled: false
existingClaim: alertmanager-iscsi-pvc
# storageClass: rook-cephfs
strategy:
type: Recreate
ingress:
enabled: "true"
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
# Enable client certificate authentication
nginx.ingress.kubernetes.io/auth-tls-verify-client: "on"
# Create the secret containing the trusted ca certificates
nginx.ingress.kubernetes.io/auth-tls-secret: "default/ca-secret"
tls:
- secretName: "tls-secret"
hosts:
- "alertmanager.viktorbarzin.me"
hosts:
- "alertmanager.viktorbarzin.me"
alertmanagerFiles:
alertmanager.yml:
global:
smtp_from: "alertmanager@viktorbarzin.me"
# smtp_smarthost: "smtp.viktorbarzin.me:587"
smtp_smarthost: "mailserver.mailserver.svc.cluster.local:587"
smtp_auth_username: "alertmanager@viktorbarzin.me"
smtp_auth_password: "${alertmanager_mail_pass}"
smtp_require_tls: true
templates:
- "/etc/alertmanager/template/*.tmpl"
route:
group_by: ["alertname"]
group_wait: 3s
group_interval: 5s
repeat_interval: 1h
receiver: SMTP_STARTTLS
receivers:
- name: 'SMTP_STARTTLS'
email_configs:
- to: "me@viktorbarzin.me"
send_resolved: true
tls_config:
insecure_skip_verify: true
server:
# Enable me to delete metrics
# extraFlags:
# - "web.enable-admin-api"
persistentVolume:
# enabled: false
existingClaim: prometheus-iscsi-pvc
# storageClass: rook-cephfs
retention: "12w" # ~100GB storage
strategy:
type: Recreate
ingress:
enabled: "true"
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
# Enable client certificate authentication
nginx.ingress.kubernetes.io/auth-tls-verify-client: "on"
# Create the secret containing the trusted ca certificates
nginx.ingress.kubernetes.io/auth-tls-secret: "default/ca-secret"
tls:
- secretName: "tls-secret"
hosts:
- "prometheus.viktorbarzin.me"
hosts:
- "prometheus.viktorbarzin.me"
alertmanagers:
- static_configs:
- targets:
- "prometheus-alertmanager.monitoring.svc.cluster.local"
# - "alertmanager.viktorbarzin.me"
tls_config:
insecure_skip_verify: true
serverFiles:
# prometheus.yml:
# alertingaaa:
# alertmanagers:
# - static_configs:
# targets: "alertmanager.viktorbarzin.lan"
alerting_rules.yml:
groups:
- name: NodeDown
rules:
- alert: NodeDown
expr: up{job="kubernetes-nodes"} == 0
for: 1m
labels:
severity: page
annotations:
summary: Node down.
- name: NodeHighCPUUsage
rules:
- alert: NodeHighCPUUsage
expr: node_load1 > 2
# for: 10m
for: 1m # DEBUG
labels:
severity: page
annotations:
summary: High CPU usage on node.
# - name: PodStuckNotReady
# rules:
# - alert: PodStuckNotReady
# expr: kube_pod_status_ready{condition="true"} == 0
# for: 5m
# labels:
# severity: page
# annotations:
# summary: Pod stuck not ready.
- name: ReadyPodsInDeploymentLessThanSpec
rules:
- alert: ReadyPodsInDeploymentLessThanSpec
expr: kube_deployment_status_replicas_available - on(namespace, deployment) kube_deployment_spec_replicas < 0
for: 10m
labels:
severity: page
annotations:
summary: Number of ready pods in deployment is less than what is defined in spec.
- name: PowerOutage
rules:
- alert: PowerOutage
expr: r730_idrac_powerSupplyCurrentInputVoltage < 200
labels:
severity: page
annotations:
summary: Power voltage on a power supply is critically low indicating power outage.
extraScrapeConfigs: |
- job_name: 'snmp-idrac'
static_configs:
- targets:
- "idrac.viktorbarzin.lan:161"
metrics_path: '/snmp'
params:
module: [dell_idrac]
relabel_configs:
- source_labels: [__address__]
target_label: __param_target
- source_labels: [__param_target]
target_label: instance
- target_label: __address__
replacement: 'prometheus-snmp-exporter.monitoring.svc.cluster.local:9116'
metric_relabel_configs:
- source_labels: [ __name__ ]
target_label: '__name__'
action: replace
regex: '(.*)'
replacement: 'r730_idrac_${1}'
- job_name: 'openwrt'
static_configs:
- targets:
- "home.viktorbarzin.lan:9100"
metrics_path: '/metrics'
relabel_configs:
- source_labels: [__address__]
target_label: __param_target
- source_labels: [__param_target]
target_label: instance
- target_label: __address__
replacement: 'home.viktorbarzin.lan:9100'
metric_relabel_configs:
- source_labels: [ __name__ ]
target_label: '__name__'
action: replace
regex: '(.*)'
replacement: 'openwrt_${1}'

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,112 @@
variable "tls_secret_name" {}
variable "tls_crt" {}
variable "tls_key" {}
resource "kubernetes_namespace" "openid_help_page" {
metadata {
name = "openid-help-page"
}
}
module "tls_secret" {
source = "../setup_tls_secret"
namespace = "openid-help-page"
tls_secret_name = var.tls_secret_name
tls_crt = var.tls_crt
tls_key = var.tls_key
}
resource "kubernetes_deployment" "openid_help_page" {
metadata {
name = "openid-help-page"
namespace = "openid-help-page"
labels = {
app = "openid-help-page"
}
}
spec {
replicas = 3
selector {
match_labels = {
app = "openid-help-page"
}
}
template {
metadata {
labels = {
app = "openid-help-page"
}
}
spec {
container {
image = "viktorbarzin/openid-create-account-help-webpage:latest"
name = "openid-help-page"
resources {
limits = {
cpu = "0.5"
memory = "512Mi"
}
requests = {
cpu = "250m"
memory = "50Mi"
}
}
port {
container_port = 80
}
}
}
}
}
}
resource "kubernetes_service" "openid_help_page" {
metadata {
name = "openid-help-page"
namespace = "openid-help-page"
}
spec {
port {
name = "service-port"
protocol = "TCP"
port = 80
target_port = "80"
}
selector = {
app = "openid-help-page"
}
type = "ClusterIP"
session_affinity = "None"
}
}
resource "kubernetes_ingress" "openid_help_page" {
metadata {
name = "openid-help-page"
namespace = "openid-help-page"
annotations = {
"kubernetes.io/ingress.class" = "nginx"
}
}
spec {
tls {
hosts = ["kubectl.viktorbarzin.me"]
secret_name = var.tls_secret_name
}
rule {
host = "kubectl.viktorbarzin.me"
http {
path {
path = "/"
backend {
service_name = "openid-help-page"
service_port = "80"
}
}
}
}
}
}

View file

@ -0,0 +1,200 @@
variable "tls_secret_name" {}
variable "tls_crt" {}
variable "tls_key" {}
variable "web_password" {}
resource "kubernetes_namespace" "pihole" {
metadata {
name = "pihole"
}
}
module "tls_secret" {
source = "../setup_tls_secret"
namespace = "pihole"
tls_secret_name = var.tls_secret_name
tls_crt = var.tls_crt
tls_key = var.tls_key
}
resource "kubernetes_config_map" "external_conf" {
metadata {
name = "external-conf"
namespace = "pihole"
labels = {
app = "pihole"
}
}
data = {
"external.conf" = "$HTTP[\"host\"] == \"pihole.viktorbarzin.me\" {\n server.document-root = \"/var/www/html/admin/\"\n}\n"
}
}
resource "kubernetes_deployment" "pihole" {
metadata {
name = "pihole"
namespace = "pihole"
labels = {
app = "pihole"
}
}
spec {
replicas = 1
selector {
match_labels = {
app = "pihole"
}
}
template {
metadata {
labels = {
app = "pihole"
}
}
spec {
container {
image = "pihole/pihole:latest"
name = "pihole"
resources {
limits = {
cpu = "1"
memory = "1Gi"
}
requests = {
cpu = "1"
memory = "1Gi"
}
}
port {
container_port = 80
}
env {
name = "DNS1"
value = "10.0.20.200#5354" # bind
}
env {
name = "VIRTUAL_HOST"
value = "pihole.viktorbarzin.me"
}
env {
name = "WEBPASSWORD"
value = var.web_password
}
env {
name = "TZ"
value = "Europe/Sofia"
}
volume_mount {
name = "external-conf"
mount_path = "/tmp/external.conf"
sub_path = "external.conf"
}
volume_mount {
name = "pihole-local-etc-volume"
mount_path = "/etc/pihole"
}
volume_mount {
name = "pihole-local-dnsmasq-volume"
mount_path = "/etc/dnsmasq.d"
}
}
volume {
name = "external-conf"
config_map {
name = "external-conf"
}
}
volume {
name = "pihole-local-etc-volume"
empty_dir {} # no hard dependencies on truenas which needs dns
}
volume {
name = "pihole-local-dnsmasq-volume"
empty_dir {} # no hard dependencies on truenas which needs dns
}
}
}
}
}
resource "kubernetes_service" "pihole-dns" {
metadata {
name = "pihole-dns"
namespace = "pihole"
labels = {
"app" = "pihole"
}
annotations = {
"metallb.universe.tf/allow-shared-ip" : "shared"
}
}
spec {
type = "LoadBalancer"
external_traffic_policy = "Cluster"
selector = {
app = "pihole"
}
port {
name = "dns-udp"
port = "53"
protocol = "UDP"
}
}
}
resource "kubernetes_service" "pihole-web" {
metadata {
name = "pihole-web"
namespace = "pihole"
labels = {
"app" = "pihole"
}
annotations = {
"metallb.universe.tf/allow-shared-ip" : "shared"
}
}
spec {
selector = {
app = "pihole"
}
port {
name = "dns-web"
port = "80"
}
}
}
resource "kubernetes_ingress" "pihole" {
metadata {
name = "pihole-ingress"
namespace = "pihole"
annotations = {
"kubernetes.io/ingress.class" = "nginx"
"nginx.ingress.kubernetes.io/auth-tls-verify-client" = "on"
"nginx.ingress.kubernetes.io/auth-tls-secret" = "default/ca-secret"
}
}
spec {
tls {
hosts = ["pihole.viktorbarzin.me"]
secret_name = var.tls_secret_name
}
rule {
host = "pihole.viktorbarzin.me"
http {
path {
path = "/"
backend {
service_name = "pihole-web"
service_port = "80"
}
}
}
}
}
}

View file

@ -0,0 +1,144 @@
variable "tls_secret_name" {}
variable "tls_crt" {}
variable "tls_key" {}
resource "kubernetes_namespace" "privatebin" {
metadata {
name = "privatebin"
}
}
module "tls_secret" {
source = "../setup_tls_secret"
namespace = "privatebin"
tls_secret_name = var.tls_secret_name
tls_crt = var.tls_crt
tls_key = var.tls_key
}
resource "kubernetes_deployment" "privatebin" {
metadata {
name = "privatebin"
namespace = "privatebin"
labels = {
app = "privatebin"
"kubernetes.io/cluster-service" = "true"
}
}
spec {
replicas = 1
strategy {
type = "Recreate"
}
selector {
match_labels = {
app = "privatebin"
}
}
template {
metadata {
labels = {
app = "privatebin"
"kubernetes.io/cluster-service" = "true"
}
}
spec {
container {
image = "privatebin/nginx-fpm-alpine"
name = "privatebin"
image_pull_policy = "IfNotPresent"
resources {
limits = {
cpu = "1"
memory = "1Gi"
}
requests = {
cpu = "1"
memory = "1Gi"
}
}
port {
container_port = 8080
}
volume_mount {
name = "data"
mount_path = "/srv/data"
sub_path = "data"
}
}
volume {
name = "data"
iscsi {
target_portal = "iscsi.viktorbarzin.lan:3260"
fs_type = "ext4"
iqn = "iqn.2020-12.lan.viktorbarzin:storage:privatebin"
lun = 0
read_only = false
}
}
}
}
}
}
resource "kubernetes_service" "privatebin" {
metadata {
name = "privatebin"
namespace = "privatebin"
labels = {
"app" = "privatebin"
}
}
spec {
selector = {
app = "privatebin"
}
port {
port = "80"
target_port = "8080"
}
}
}
resource "kubernetes_ingress" "privatebin" {
metadata {
name = "privatebin-ingress"
namespace = "privatebin"
annotations = {
"kubernetes.io/ingress.class" = "nginx"
}
}
spec {
tls {
hosts = ["privatebin.viktorbarzin.me", "pb.viktorbarzin.me"]
secret_name = var.tls_secret_name
}
rule {
host = "privatebin.viktorbarzin.me"
http {
path {
path = "/"
backend {
service_name = "privatebin"
service_port = "80"
}
}
}
}
rule {
host = "pb.viktorbarzin.me"
http {
path {
path = "/"
backend {
service_name = "privatebin"
service_port = "80"
}
}
}
}
}
}

View file

@ -0,0 +1,16 @@
variable namespace {}
variable tls_secret_name {}
variable tls_crt {}
variable tls_key {}
resource "kubernetes_secret" "tls_secret" {
metadata {
name = var.tls_secret_name
namespace = var.namespace
}
data = {
"tls.crt" = var.tls_crt
"tls.key" = var.tls_key
}
type = "kubernetes.io/tls"
}

View file

@ -0,0 +1,8 @@
terraform {
required_providers {
kubernetes = {
source = "hashicorp/kubernetes"
}
}
required_version = ">= 0.13"
}

View file

@ -0,0 +1,146 @@
variable "tls_secret_name" {}
variable "tls_crt" {}
variable "tls_key" {}
variable "webhook_secret" {}
resource "kubernetes_namespace" "webhook-handler" {
metadata {
name = "webhook-handler"
}
}
module "tls_secret" {
source = "../setup_tls_secret"
namespace = "webhook-handler"
tls_secret_name = var.tls_secret_name
tls_crt = var.tls_crt
tls_key = var.tls_key
}
resource "kubernetes_cluster_role" "deployment_updater" {
metadata {
name = "deployment-updater"
}
rule {
verbs = ["create", "update", "get", "patch", "list"]
api_groups = ["extensions", "apps", ""]
resources = ["deployments", "namespaces", "pods", "services"]
}
}
resource "kubernetes_cluster_role_binding" "update_deployment_binding" {
metadata {
name = "update-deployment-binding"
}
subject {
kind = "ServiceAccount"
name = "default"
namespace = "webhook-handler"
}
role_ref {
api_group = "rbac.authorization.k8s.io"
kind = "ClusterRole"
name = "deployment-updater"
}
}
resource "kubernetes_deployment" "webhook_handler" {
metadata {
name = "webhook-handler"
namespace = "webhook-handler"
labels = {
app = "webhook-handler"
}
}
spec {
replicas = 1
selector {
match_labels = {
app = "webhook-handler"
}
}
template {
metadata {
labels = {
app = "webhook-handler"
}
}
spec {
container {
image = "viktorbarzin/webhook-handler:latest"
name = "webhook-handler"
resources {
limits = {
cpu = "0.5"
memory = "512Mi"
}
requests = {
cpu = "250m"
memory = "50Mi"
}
}
port {
container_port = 80
}
env {
name = "WEBHOOKSECRET"
value = var.webhook_secret
}
}
}
}
}
}
resource "kubernetes_service" "webhook_handler" {
metadata {
name = "webhook-handler"
namespace = "webhook-handler"
labels = {
"app" = "webhook-handler"
}
}
spec {
selector = {
app = "webhook-handler"
}
port {
port = "80"
target_port = "3000"
}
}
}
resource "kubernetes_ingress" "webhook_handler" {
metadata {
name = "webhook-handler-ingress"
namespace = "webhook-handler"
annotations = {
"kubernetes.io/ingress.class" = "nginx"
}
}
spec {
tls {
hosts = ["webhook.viktorbarzin.me"]
secret_name = var.tls_secret_name
}
rule {
host = "webhook.viktorbarzin.me"
http {
path {
path = "/"
backend {
service_name = "webhook-handler"
service_port = "80"
}
}
}
}
}
}

View file

@ -0,0 +1,196 @@
variable "tls_secret_name" {}
variable "tls_crt" {}
variable "tls_key" {}
variable "wg_0_conf" {}
variable "firewall_sh" {}
variable "wg_0_key" {}
resource "kubernetes_namespace" "wireguard" {
metadata {
name = "wireguard"
}
}
resource "kubernetes_config_map" "wg_0_conf" {
metadata {
name = "wg0-conf"
namespace = "wireguard"
labels = {
app = "wireguard"
}
}
data = {
"setup-firewall.sh" = var.firewall_sh
"wg0.conf" = var.wg_0_conf
}
}
resource "kubernetes_secret" "wg_0_key" {
metadata {
name = "wg0-key"
namespace = "wireguard"
}
data = {
"wg0.key" = var.wg_0_key
}
type = "generic"
}
resource "kubernetes_deployment" "wireguard" {
metadata {
name = "wireguard"
namespace = "wireguard"
labels = {
app = "wireguard"
}
}
spec {
replicas = 1
strategy {
rolling_update {
max_surge = "2"
max_unavailable = "0"
}
}
selector {
match_labels = {
app = "wireguard"
}
}
template {
metadata {
labels = {
app = "wireguard"
}
annotations = {
"prometheus.io/scrape" = "true"
}
}
spec {
container {
image = "sclevine/wg:latest"
name = "wireguard"
image_pull_policy = "IfNotPresent"
lifecycle {
post_start {
exec {
command = ["wg-quick", "up", "wg0"]
}
}
pre_stop {
exec {
command = ["wg-quick", "down", "wg0"]
}
}
}
command = ["tail", "-f", "/dev/null"]
port {
container_port = 51820
protocol = "UDP"
}
volume_mount {
name = "wg0-key"
mount_path = "/etc/wireguard/wg0.key"
sub_path = "wg0.key"
}
volume_mount {
name = "wg0-conf"
mount_path = "/etc/wireguard/wg0.conf"
sub_path = "wg0.conf"
}
volume_mount {
name = "wg0-conf"
mount_path = "/etc/wireguard/setup-firewall.sh"
sub_path = "setup-firewall.sh"
}
security_context {
capabilities {
add = ["NET_ADMIN", "SYS_MODULE"]
}
}
}
container {
name = "prometheus-exporter"
image = "mindflavor/prometheus-wireguard-exporter"
image_pull_policy = "IfNotPresent"
command = ["prometheus_wireguard_exporter", "-a", "-v", "-n", "/etc/wireguard/wg0.conf"]
volume_mount {
name = "wg0-conf"
mount_path = "/etc/wireguard/wg0.conf"
sub_path = "wg0.conf"
}
security_context {
capabilities {
add = ["NET_ADMIN"]
}
}
port {
container_port = 9586
protocol = "TCP"
}
}
volume {
name = "wg0-key"
secret {
secret_name = "wg0-key"
}
}
volume {
name = "wg0-conf"
config_map {
name = "wg0-conf"
}
}
}
}
}
}
resource "kubernetes_service" "wireguard" {
metadata {
name = "wireguard"
namespace = "wireguard"
annotations = {
"metallb.universe.tf/allow-shared-ip" = "shared"
}
labels = {
"app" = "wireguard"
}
}
spec {
type = "LoadBalancer"
external_traffic_policy = "Cluster"
selector = {
app = "wireguard"
}
port {
port = "51820"
protocol = "UDP"
}
}
}
resource "kubernetes_service" "wireguard_exporter" {
metadata {
name = "wireguard-exporter"
namespace = "wireguard"
labels = {
"app" = "wireguard-exporter"
}
}
spec {
selector = {
app = "wireguard"
}
port {
port = "9102"
target_port = "9586"
}
}
}

1
playbook Symbolic link
View file

@ -0,0 +1 @@
../playbook

8
versions.tf Normal file
View file

@ -0,0 +1,8 @@
terraform {
required_providers {
kubernetes = {
source = "hashicorp/kubernetes"
}
}
required_version = ">= 0.13"
}