Compare commits

...

1 Commits

Author SHA1 Message Date
Nemo 853d77e0bf Terraform Upgrade WIP 2021-03-20 13:09:19 +05:30
107 changed files with 922 additions and 685 deletions

View File

@ -1 +1 @@
0.11.13 0.12.30

View File

@ -4,18 +4,18 @@
*/ */
resource "cloudflare_record" "home" { resource "cloudflare_record" "home" {
domain = "${var.domain}" zone_id = var.zone_id
name = "in" name = "in"
value = "${var.ips["eth0"]}" value = var.ips["eth0"]
type = "A" type = "A"
} }
resource "cloudflare_record" "home-wildcard" { resource "cloudflare_record" "home-wildcard" {
domain = "${var.domain}" zone_id = var.zone_id
name = "*.in" name = "*.in"
value = "${cloudflare_record.home.hostname}" value = cloudflare_record.home.hostname
type = "CNAME" type = "CNAME"
ttl = 3600 ttl = 3600
} }
/** /**
@ -23,42 +23,42 @@ resource "cloudflare_record" "home-wildcard" {
* *.bb8.fun -> bb8.fun * *.bb8.fun -> bb8.fun
*/ */
resource "cloudflare_record" "internet" { resource "cloudflare_record" "internet" {
domain = "${var.domain}" zone_id = var.zone_id
name = "@" name = "@"
value = "${var.droplet_ip}" value = var.droplet_ip
type = "A" type = "A"
} }
resource "cloudflare_record" "internet-wildcard" { resource "cloudflare_record" "internet-wildcard" {
domain = "${var.domain}" zone_id = var.zone_id
name = "*.${var.domain}" name = var.domain
value = "${cloudflare_record.internet.hostname}" value = cloudflare_record.internet.hostname
type = "CNAME" type = "CNAME"
ttl = 3600 ttl = 3600
} }
resource "cloudflare_record" "dns" { resource "cloudflare_record" "dns" {
domain = "${var.domain}" zone_id = var.zone_id
name = "dns" name = "dns"
value = "${var.ips["static"]}" value = var.ips["static"]
type = "A" type = "A"
} }
resource "cloudflare_record" "doh" { resource "cloudflare_record" "doh" {
domain = "${var.domain}" zone_id = var.zone_id
name = "doh" name = "doh"
value = "${var.ips["static"]}" value = var.ips["static"]
type = "A" type = "A"
} }
// This ensures that _acme-challenge is not a CNAME // This ensures that _acme-challenge is not a CNAME
// alongside the above wildcard CNAME entry. // alongside the above wildcard CNAME entry.
resource "cloudflare_record" "acme-no-cname-1" { resource "cloudflare_record" "acme-no-cname-1" {
domain = "${var.domain}" zone_id = var.zone_id
name = "_acme-challenge.${var.domain}" name = "_acme-challenge.${var.domain}"
type = "A" type = "A"
value = "127.0.0.1" value = "127.0.0.1"
ttl = "300" ttl = "300"
} }
/** /**
@ -66,18 +66,18 @@ resource "cloudflare_record" "acme-no-cname-1" {
* *.vpn.bb8.fun * *.vpn.bb8.fun
*/ */
resource "cloudflare_record" "vpn" { resource "cloudflare_record" "vpn" {
domain = "${var.domain}" zone_id = var.zone_id
name = "vpn" name = "vpn"
value = "${var.ips["tun0"]}" value = var.ips["tun0"]
type = "A" type = "A"
} }
resource "cloudflare_record" "vpn_wildcard" { resource "cloudflare_record" "vpn_wildcard" {
domain = "${var.domain}" zone_id = var.zone_id
name = "*.vpn.${var.domain}" name = "*.vpn.${var.domain}"
value = "${cloudflare_record.vpn.hostname}" value = cloudflare_record.vpn.hostname
type = "CNAME" type = "CNAME"
ttl = 3600 ttl = 3600
} }
/** /**
@ -85,25 +85,25 @@ resource "cloudflare_record" "vpn_wildcard" {
* *.vpn.bb8.fun * *.vpn.bb8.fun
*/ */
resource "cloudflare_record" "dovpn" { resource "cloudflare_record" "dovpn" {
domain = "${var.domain}" zone_id = var.zone_id
name = "dovpn" name = "dovpn"
value = "${var.ips["dovpn"]}" value = var.ips["dovpn"]
type = "A" type = "A"
} }
resource "cloudflare_record" "dovpn_wildcard" { resource "cloudflare_record" "dovpn_wildcard" {
domain = "${var.domain}" zone_id = var.zone_id
name = "*.dovpn.${var.domain}" name = "*.dovpn.${var.domain}"
value = "${cloudflare_record.dovpn.hostname}" value = cloudflare_record.dovpn.hostname
type = "CNAME" type = "CNAME"
ttl = 3600 ttl = 3600
} }
resource "cloudflare_record" "etcd" { resource "cloudflare_record" "etcd" {
domain = "${var.domain}" zone_id = var.zone_id
name = "etcd" name = "etcd"
value = "${var.ips["dovpn"]}" value = var.ips["dovpn"]
type = "A" type = "A"
} }
######################## ########################
@ -111,21 +111,21 @@ resource "cloudflare_record" "etcd" {
######################## ########################
resource "cloudflare_record" "mailgun-spf" { resource "cloudflare_record" "mailgun-spf" {
domain = "${var.domain}" zone_id = var.zone_id
name = "l" name = "l"
value = "v=spf1 include:mailgun.org ~all" value = "v=spf1 include:mailgun.org ~all"
type = "TXT" type = "TXT"
} }
resource "cloudflare_record" "mailgun-dkim" { resource "cloudflare_record" "mailgun-dkim" {
domain = "${var.domain}" zone_id = var.zone_id
name = "k1._domainkey.l" name = "k1._domainkey.l"
value = "k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCnbP+IQkuPkgmUhpqCKzIdDSZ0HazaMp+cdBH++LBed8oY8/jmV8BhxMp5JwyePzRTxneT8ASsRtcp7CQ3z4nMC7aFX0kH6Bnu2v+u2JWudxs8x0I02OrPbSaQ5QVQdbAaCUCEfCQ06LJsn8aqPNrRIOWEMnxln+ebFJ0wKGscFQIDAQAB" value = "k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCnbP+IQkuPkgmUhpqCKzIdDSZ0HazaMp+cdBH++LBed8oY8/jmV8BhxMp5JwyePzRTxneT8ASsRtcp7CQ3z4nMC7aFX0kH6Bnu2v+u2JWudxs8x0I02OrPbSaQ5QVQdbAaCUCEfCQ06LJsn8aqPNrRIOWEMnxln+ebFJ0wKGscFQIDAQAB"
type = "TXT" type = "TXT"
} }
resource "cloudflare_record" "mailgun-mxa" { resource "cloudflare_record" "mailgun-mxa" {
domain = "${var.domain}" zone_id = var.zone_id
name = "l" name = "l"
value = "mxa.mailgun.org" value = "mxa.mailgun.org"
type = "MX" type = "MX"
@ -133,7 +133,7 @@ resource "cloudflare_record" "mailgun-mxa" {
} }
resource "cloudflare_record" "mailgun-mxb" { resource "cloudflare_record" "mailgun-mxb" {
domain = "${var.domain}" zone_id = var.zone_id
name = "l" name = "l"
value = "mxb.mailgun.org" value = "mxb.mailgun.org"
type = "MX" type = "MX"
@ -141,9 +141,9 @@ resource "cloudflare_record" "mailgun-mxb" {
} }
resource "cloudflare_record" "k8s" { resource "cloudflare_record" "k8s" {
domain = "${var.domain}" zone_id = var.zone_id
name = "k8s" name = "k8s"
value = "10.8.0.1" value = "10.8.0.1"
type = "A" type = "A"
ttl = 3600 ttl = 3600
} }

View File

@ -1,9 +1,10 @@
variable "domain" { variable "domain" {
type = "string" type = string
} }
variable "ips" { variable "ips" {
type = "map" type = map
} }
variable "droplet_ip" {} variable "droplet_ip" {}
variable "zone_id" {}

View File

@ -1,3 +1,11 @@
data "docker_network" "bridge" { data "docker_network" "bridge" {
name = "bridge" name = "bridge"
} }
data "cloudflare_zones" "bb8" {
filter {
name = "bb8"
lookup_type = "exact"
match = "bb8.fun"
}
}

View File

@ -8,3 +8,4 @@ resource "docker_network" "postgres" {
gateway = "172.20.0.9" gateway = "172.20.0.9"
} }
} }

View File

@ -1,3 +1,4 @@
output "postgres-network-id" { output "postgres-network-id" {
value = "${docker_network.postgres.name}" value = docker_network.postgres.name
} }

View File

@ -1,18 +1,18 @@
resource "docker_container" "postgres" { resource "docker_container" "postgres" {
name = "postgres" name = "postgres"
image = "${docker_image.postgres.latest}" image = docker_image.postgres.latest
volumes { volumes {
volume_name = "${docker_volume.postgres_volume.name}" volume_name = docker_volume.postgres_volume.name
container_path = "/var/lib/postgresql/data" container_path = "/var/lib/postgresql/data"
host_path = "${docker_volume.postgres_volume.mountpoint}" host_path = docker_volume.postgres_volume.mountpoint
} }
// This is so that other host-only services can share this // This is so that other host-only services can share this
ports { ports {
internal = 5432 internal = 5432
external = 5432 external = 5432
ip = "${var.ips["eth0"]}" ip = var.ips["eth0"]
} }
// This is a not-so-great idea // This is a not-so-great idea
@ -20,7 +20,7 @@ resource "docker_container" "postgres" {
ports { ports {
internal = 5432 internal = 5432
external = 5432 external = 5432
ip = "${var.ips["tun0"]}" ip = var.ips["tun0"]
} }
memory = 256 memory = 256
@ -32,12 +32,12 @@ resource "docker_container" "postgres" {
"POSTGRES_PASSWORD=${var.postgres-root-password}", "POSTGRES_PASSWORD=${var.postgres-root-password}",
] ]
networks = ["${docker_network.postgres.id}", "${data.docker_network.bridge.id}"] networks = [docker_network.postgres.id, data.docker_network.bridge.id]
} }
resource "docker_image" "postgres" { resource "docker_image" "postgres" {
name = "${data.docker_registry_image.postgres.name}" name = data.docker_registry_image.postgres.name
pull_triggers = ["${data.docker_registry_image.postgres.sha256_digest}"] pull_triggers = [data.docker_registry_image.postgres.sha256_digest]
} }
data "docker_registry_image" "postgres" { data "docker_registry_image" "postgres" {
@ -47,3 +47,4 @@ data "docker_registry_image" "postgres" {
data "docker_network" "bridge" { data "docker_network" "bridge" {
name = "bridge" name = "bridge"
} }

View File

@ -4,7 +4,9 @@ variable "postgres-version" {
} }
variable "ips" { variable "ips" {
type = "map" type = map(string)
}
variable "postgres-root-password" {
} }
variable "postgres-root-password" {}

3
db/versions.tf Normal file
View File

@ -0,0 +1,3 @@
terraform {
required_version = ">= 0.12"
}

View File

@ -1,3 +1,4 @@
resource "docker_volume" "postgres_volume" { resource "docker_volume" "postgres_volume" {
name = "postgres_volume" name = "postgres_volume"
} }

View File

@ -18,5 +18,6 @@ resource "digitalocean_droplet" "sydney" {
} }
output "droplet_ipv4" { output "droplet_ipv4" {
value = "${digitalocean_droplet.sydney.ipv4_address}" value = digitalocean_droplet.sydney.ipv4_address
} }

View File

@ -1,38 +1,35 @@
resource "digitalocean_firewall" "web" { resource "digitalocean_firewall" "web" {
name = "web-inbound" name = "web-inbound"
inbound_rule = [ inbound_rule {
{ protocol = "tcp"
protocol = "tcp" port_range = "80"
port_range = "80" source_addresses = ["0.0.0.0/0", "::/0"]
source_addresses = ["0.0.0.0/0", "::/0"] }
}, inbound_rule {
{ protocol = "tcp"
protocol = "tcp" port_range = "443"
port_range = "443" source_addresses = ["0.0.0.0/0", "::/0"]
source_addresses = ["0.0.0.0/0", "::/0"] }
},
]
} }
resource "digitalocean_firewall" "ssh" { resource "digitalocean_firewall" "ssh" {
name = "ssh-inbound" name = "ssh-inbound"
inbound_rule = [ inbound_rule {
{ protocol = "tcp"
protocol = "tcp" port_range = "22"
port_range = "22" source_addresses = ["0.0.0.0/0", "::/0"]
source_addresses = ["0.0.0.0/0", "::/0"] }
}, inbound_rule {
{ protocol = "tcp"
protocol = "tcp" port_range = "222"
port_range = "222" source_addresses = ["0.0.0.0/0", "::/0"]
source_addresses = ["0.0.0.0/0", "::/0"] }
}, inbound_rule {
{ protocol = "tcp"
protocol = "tcp" port_range = "24"
port_range = "24" source_addresses = ["0.0.0.0/0", "::/0"]
source_addresses = ["0.0.0.0/0", "::/0"] }
},
]
} }

View File

@ -1,4 +1,5 @@
resource "digitalocean_floating_ip" "sydney" { resource "digitalocean_floating_ip" "sydney" {
droplet_id = "${digitalocean_droplet.sydney.id}" droplet_id = digitalocean_droplet.sydney.id
region = "${digitalocean_droplet.sydney.region}" region = digitalocean_droplet.sydney.region
} }

4
digitalocean/versions.tf Normal file
View File

@ -0,0 +1,4 @@
terraform {
required_version = ">= 0.12"
}

View File

@ -9,3 +9,4 @@ data "docker_registry_image" "ubooquity" {
data "docker_registry_image" "lychee" { data "docker_registry_image" "lychee" {
name = "linuxserver/lychee:latest" name = "linuxserver/lychee:latest"
} }

View File

@ -6,22 +6,15 @@ data "docker_registry_image" "gotviz" {
# name = "${data.docker_registry_image.gotviz.name}" # name = "${data.docker_registry_image.gotviz.name}"
# pull_triggers = ["${data.docker_registry_image.gotviz.sha256_digest}"] # pull_triggers = ["${data.docker_registry_image.gotviz.sha256_digest}"]
# } # }
# resource "docker_container" "gotviz" { # resource "docker_container" "gotviz" {
# name = "gotviz" # name = "gotviz"
# image = "${docker_image.gotviz.latest}" # image = "${docker_image.gotviz.latest}"
# labels = "${merge( # labels = "${merge(
# local.traefik_common_labels, map( # local.traefik_common_labels, map(
# "traefik.port", 8080, # "traefik.port", 8080,
# "traefik.frontend.rule","Host:got-relationships.${var.domain}" # "traefik.frontend.rule","Host:got-relationships.${var.domain}"
# ))}" # ))}"
# restart = "unless-stopped" # restart = "unless-stopped"
# destroy_grace_seconds = 60 # destroy_grace_seconds = 60
# must_run = true # must_run = true
# } # }

View File

@ -1,11 +1,11 @@
resource "docker_image" "traefik17" { resource "docker_image" "traefik17" {
name = "${data.docker_registry_image.traefik.name}" name = data.docker_registry_image.traefik.name
pull_triggers = ["${data.docker_registry_image.traefik.sha256_digest}"] pull_triggers = [data.docker_registry_image.traefik.sha256_digest]
} }
resource "docker_image" "ubooquity" { resource "docker_image" "ubooquity" {
name = "${data.docker_registry_image.ubooquity.name}" name = data.docker_registry_image.ubooquity.name
pull_triggers = ["${data.docker_registry_image.ubooquity.sha256_digest}"] pull_triggers = [data.docker_registry_image.ubooquity.sha256_digest]
} }
# resource "docker_image" "lychee" { # resource "docker_image" "lychee" {

View File

@ -1,20 +1,17 @@
locals { locals {
traefik_common_labels { traefik_common_labels = {
"traefik.enable" = "true" "traefik.enable" = "true"
// HSTS // HSTS
"traefik.frontend.headers.SSLTemporaryRedirect" = "true" "traefik.frontend.headers.SSLTemporaryRedirect" = "true"
"traefik.frontend.headers.STSSeconds" = "2592000" "traefik.frontend.headers.STSSeconds" = "2592000"
"traefik.frontend.headers.STSIncludeSubdomains" = "false" "traefik.frontend.headers.STSIncludeSubdomains" = "false"
// X-Powered-By, Server headers // X-Powered-By, Server headers
"traefik.frontend.headers.customResponseHeaders" = "${var.xpoweredby}" "traefik.frontend.headers.customResponseHeaders" = var.xpoweredby
// X-Frame-Options // X-Frame-Options
"traefik.frontend.headers.customFrameOptionsValue" = "${var.xfo_allow}" "traefik.frontend.headers.customFrameOptionsValue" = var.xfo_allow
"traefik.frontend.headers.contentTypeNosniff" = "true" "traefik.frontend.headers.contentTypeNosniff" = "true"
"traefik.frontend.headers.browserXSSFilter" = "true" "traefik.frontend.headers.browserXSSFilter" = "true"
"traefik.docker.network" = "traefik"
"traefik.docker.network" = "traefik"
} }
} }

View File

@ -28,4 +28,3 @@
# ] # ]
# # links = ["${var.links-mariadb}"] # # links = ["${var.links-mariadb}"]
# } # }

View File

@ -1 +0,0 @@

View File

@ -3,3 +3,4 @@ resource "docker_network" "traefik" {
driver = "bridge" driver = "bridge"
internal = true internal = true
} }

View File

@ -3,13 +3,14 @@
# } # }
output "names-traefik" { output "names-traefik" {
value = "${docker_container.traefik.name}" value = docker_container.traefik.name
} }
output "traefik-network-id" { output "traefik-network-id" {
value = "${docker_network.traefik.id}" value = docker_network.traefik.id
} }
output "auth-header" { output "auth-header" {
value = "${var.basic_auth}" value = var.basic_auth
} }

View File

@ -1,70 +1,78 @@
resource "docker_container" "traefik" { resource "docker_container" "traefik" {
name = "traefik" name = "traefik"
image = "${docker_image.traefik17.latest}" image = docker_image.traefik17.latest
# Admin Backend # Admin Backend
ports { ports {
internal = 1111 internal = 1111
external = 1111 external = 1111
ip = "${var.ips["eth0"]}" ip = var.ips["eth0"]
} }
ports { ports {
internal = 1111 internal = 1111
external = 1111 external = 1111
ip = "${var.ips["tun0"]}" ip = var.ips["tun0"]
} }
# Local Web Server # Local Web Server
ports { ports {
internal = 80 internal = 80
external = 80 external = 80
ip = "${var.ips["eth0"]}" ip = var.ips["eth0"]
} }
# Local Web Server (HTTPS) # Local Web Server (HTTPS)
ports { ports {
internal = 443 internal = 443
external = 443 external = 443
ip = "${var.ips["eth0"]}" ip = var.ips["eth0"]
} }
# Proxied via sydney.captnemo.in # Proxied via sydney.captnemo.in
ports { ports {
internal = 443 internal = 443
external = 443 external = 443
ip = "${var.ips["tun0"]}" ip = var.ips["tun0"]
} }
ports { ports {
internal = 80 internal = 80
external = 80 external = 80
ip = "${var.ips["tun0"]}" ip = var.ips["tun0"]
} }
upload { upload {
content = "${file("${path.module}/conf/traefik.toml")}" content = file("${path.module}/conf/traefik.toml")
file = "/etc/traefik/traefik.toml" file = "/etc/traefik/traefik.toml"
} }
upload { upload {
content = "${file("/home/nemo/projects/personal/certs/git.captnemo.in/fullchain.pem")}" content = file(
file = "/etc/traefik/git.captnemo.in.crt" "/home/nemo/projects/personal/certs/git.captnemo.in/fullchain.pem",
)
file = "/etc/traefik/git.captnemo.in.crt"
} }
upload { upload {
content = "${file("/home/nemo/projects/personal/certs/git.captnemo.in/privkey.pem")}" content = file(
file = "/etc/traefik/git.captnemo.in.key" "/home/nemo/projects/personal/certs/git.captnemo.in/privkey.pem",
)
file = "/etc/traefik/git.captnemo.in.key"
} }
upload { upload {
content = "${file("/home/nemo/projects/personal/certs/rss.captnemo.in/fullchain.pem")}" content = file(
file = "/etc/traefik/rss.captnemo.in.crt" "/home/nemo/projects/personal/certs/rss.captnemo.in/fullchain.pem",
)
file = "/etc/traefik/rss.captnemo.in.crt"
} }
upload { upload {
content = "${file("/home/nemo/projects/personal/certs/rss.captnemo.in/privkey.pem")}" content = file(
file = "/etc/traefik/rss.captnemo.in.key" "/home/nemo/projects/personal/certs/rss.captnemo.in/privkey.pem",
)
file = "/etc/traefik/rss.captnemo.in.key"
} }
volumes { volumes {
@ -86,8 +94,8 @@ resource "docker_container" "traefik" {
// `bridge` is auto-connected for now // `bridge` is auto-connected for now
// https://github.com/terraform-providers/terraform-provider-docker/issues/10 // https://github.com/terraform-providers/terraform-provider-docker/issues/10
networks = [ networks = [
"${docker_network.traefik.id}", docker_network.traefik.id,
"${data.docker_network.bridge.id}", data.docker_network.bridge.id,
] ]
env = [ env = [
@ -99,3 +107,4 @@ resource "docker_container" "traefik" {
data "docker_network" "bridge" { data "docker_network" "bridge" {
name = "bridge" name = "bridge"
} }

View File

@ -1,6 +1,6 @@
resource "docker_container" "ubooquity" { resource "docker_container" "ubooquity" {
name = "ubooquity" name = "ubooquity"
image = "${docker_image.ubooquity.latest}" image = docker_image.ubooquity.latest
restart = "unless-stopped" restart = "unless-stopped"
destroy_grace_seconds = 30 destroy_grace_seconds = 30
@ -26,31 +26,27 @@ resource "docker_container" "ubooquity" {
container_path = "/comics" container_path = "/comics"
} }
labels { labels = {
"traefik.enable" = "true" "traefik.enable" = "true"
"traefik.admin.port" = 2203 "traefik.admin.port" = 2203
"traefik.admin.frontend.rule" = "Host:library.${var.domain}" "traefik.admin.frontend.rule" = "Host:library.${var.domain}"
# I do not trust the Ubooquity authentication # I do not trust the Ubooquity authentication
# it does some shady JS encryption # it does some shady JS encryption
"traefik.admin.frontend.auth.basic" = "${var.basic_auth}" "traefik.admin.frontend.auth.basic" = var.basic_auth
"traefik.read.port" = 2202
"traefik.read.port" = 2202 "traefik.read.frontend.rule" = "Host:read.${var.domain},comics.${var.domain},books.${var.domain}"
"traefik.read.frontend.rule" = "Host:read.${var.domain},comics.${var.domain},books.${var.domain}"
"traefik.read.frontend.headers.SSLTemporaryRedirect" = "true" "traefik.read.frontend.headers.SSLTemporaryRedirect" = "true"
"traefik.read.frontend.headers.STSSeconds" = "2592000" "traefik.read.frontend.headers.STSSeconds" = "2592000"
"traefik.read.frontend.headers.STSIncludeSubdomains" = "false" "traefik.read.frontend.headers.STSIncludeSubdomains" = "false"
"traefik.read.frontend.headers.contentTypeNosniff" = "true" "traefik.read.frontend.headers.contentTypeNosniff" = "true"
"traefik.read.frontend.headers.browserXSSFilter" = "true" "traefik.read.frontend.headers.browserXSSFilter" = "true"
"traefik.read.frontend.headers.customResponseHeaders" = "${var.xpoweredby}" "traefik.read.frontend.headers.customResponseHeaders" = var.xpoweredby
"traefik.frontend.headers.customFrameOptionsValue" = "${var.xfo_allow}" "traefik.frontend.headers.customFrameOptionsValue" = var.xfo_allow
"traefik.docker.network" = "traefik" "traefik.docker.network" = "traefik"
} }
upload { upload {
content = "${file("${path.module}/conf/ubooquity.json")}" content = file("${path.module}/conf/ubooquity.json")
file = "/config/preferences.json" file = "/config/preferences.json"
} }
@ -61,3 +57,4 @@ resource "docker_container" "ubooquity" {
"MAXMEM=800", "MAXMEM=800",
] ]
} }

View File

@ -1,18 +1,18 @@
variable "web_username" { variable "web_username" {
type = "string" type = string
} }
variable "web_password" { variable "web_password" {
type = "string" type = string
} }
variable "cloudflare_key" { variable "cloudflare_key" {
type = "string" type = string
description = "cloudflare API Key" description = "cloudflare API Key"
} }
variable "cloudflare_email" { variable "cloudflare_email" {
type = "string" type = string
description = "cloudflare email address" description = "cloudflare email address"
} }
@ -39,15 +39,15 @@ variable "refpolicy" {
} }
variable "wiki_session_secret" { variable "wiki_session_secret" {
type = "string" type = string
} }
variable "domain" { variable "domain" {
type = "string" type = string
} }
variable "ips" { variable "ips" {
type = "map" type = map(string)
} }
# variable "links-mariadb" {} # variable "links-mariadb" {}

4
docker/versions.tf Normal file
View File

@ -0,0 +1,4 @@
terraform {
required_version = ">= 0.12"
}

View File

@ -1 +0,0 @@

View File

@ -1,11 +1,12 @@
module "echo-server" { module "echo-server" {
source = "modules/container" source = "./modules/container"
name = "echo-server" name = "echo-server"
image = "jmalloc/echo-server:latest" image = "jmalloc/echo-server:latest"
web { web = {
expose = "true" expose = "true"
port = 8080 port = 8080
host = "debug.${var.root-domain},debug.in.${var.root-domain}" host = "debug.${var.root-domain},debug.in.${var.root-domain}"
} }
} }

View File

@ -1,14 +1,14 @@
module "elibsrv" { module "elibsrv" {
name = "elibsrv" name = "./elibsrv"
source = "./modules/container" source = "./modules/container"
image = "captn3m0/elibsrv" image = "captn3m0/elibsrv"
resource { resource = {
memory = 512 memory = 512
memory_swap = 512 memory_swap = 512
} }
web { web = {
expose = true expose = true
host = "ebooks.${var.root-domain}" host = "ebooks.${var.root-domain}"
auth = true auth = true
@ -49,3 +49,4 @@ module "elibsrv" {
}, },
] ]
} }

View File

@ -4,21 +4,23 @@ module "firefox-sync" {
image = "mozilla/syncserver:latest" image = "mozilla/syncserver:latest"
// Default is port 80 // Default is port 80
web { web = {
expose = true expose = true
port = "5000" port = "5000"
host = "firesync.${var.root-domain}" host = "firesync.${var.root-domain}"
} }
resource { resource = {
memory = "400" memory = "400"
memory_swap = "400" memory_swap = "400"
} }
volumes = [{ volumes = [
host_path = "/mnt/xwing/data/firefox-sync" {
container_path = "/data" host_path = "/mnt/xwing/data/firefox-sync"
}] container_path = "/data"
},
]
env = [ env = [
"SYNCSERVER_PUBLIC_URL=https://firesync.${var.root-domain}", "SYNCSERVER_PUBLIC_URL=https://firesync.${var.root-domain}",
@ -38,3 +40,4 @@ module "firefox-sync" {
}, },
] ]
} }

View File

@ -8,14 +8,15 @@ data "docker_registry_image" "redis" {
} }
data "template_file" "gitea-config-file" { data "template_file" "gitea-config-file" {
template = "${file("${path.module}/conf/conf.ini.tpl")}" template = file("${path.module}/conf/conf.ini.tpl")
vars { vars = {
secret_key = "${var.secret-key}" secret_key = var.secret-key
internal_token = "${var.internal-token}" internal_token = var.internal-token
smtp_password = "${var.smtp-password}" smtp_password = var.smtp-password
lfs-jwt-secret = "${var.lfs-jwt-secret}" lfs-jwt-secret = var.lfs-jwt-secret
mysql-password = "${var.mysql-password}" mysql-password = var.mysql-password
oauth2-jwt-secret = "${var.oauth2-jwt-secret}" oauth2-jwt-secret = var.oauth2-jwt-secret
} }
} }

View File

@ -1,59 +1,62 @@
resource "docker_container" "gitea" { resource "docker_container" "gitea" {
name = "gitea" name = "gitea"
image = "${docker_image.gitea.latest}" image = docker_image.gitea.latest
labels = "${merge( labels = merge(
var.traefik-labels, map( var.traefik-labels,
"traefik.port", 3000, {
"traefik.frontend.rule", "Host:${var.domain}" "traefik.port" = 3000
))}" "traefik.frontend.rule" = "Host:${var.domain}"
},
)
volumes { volumes {
volume_name = "${docker_volume.gitea_volume.name}" volume_name = docker_volume.gitea_volume.name
container_path = "/data" container_path = "/data"
host_path = "${docker_volume.gitea_volume.mountpoint}" host_path = docker_volume.gitea_volume.mountpoint
} }
# Logos # Logos
# TODO: Add svg # TODO: Add svg
upload { upload {
content = "${file("${path.module}/conf/public/img/gitea-lg.png")}" content = file("${path.module}/conf/public/img/gitea-lg.png")
file = "/data/gitea/public/img/gitea-lg.png" file = "/data/gitea/public/img/gitea-lg.png"
} }
upload { upload {
content = "${file("${path.module}/conf/public/img/gitea-sm.png")}" content = file("${path.module}/conf/public/img/gitea-sm.png")
file = "/data/gitea/public/img/gitea-sm.png" file = "/data/gitea/public/img/gitea-sm.png"
} }
upload { upload {
content = "${file("${path.module}/conf/public/img/gitea-sm.png")}" content = file("${path.module}/conf/public/img/gitea-sm.png")
file = "/data/gitea/public/img/favicon.png" file = "/data/gitea/public/img/favicon.png"
executable = false executable = false
} }
upload { upload {
content = "${file("${path.module}/../docker/conf/humans.txt")}" content = file("${path.module}/../docker/conf/humans.txt")
file = "/data/gitea/public/humans.txt" file = "/data/gitea/public/humans.txt"
} }
upload { upload {
content = "${file("${path.module}/conf/public/robots.txt")}" content = file("${path.module}/conf/public/robots.txt")
file = "/data/gitea/public/robots.txt" file = "/data/gitea/public/robots.txt"
} }
# Extra Links in header # Extra Links in header
upload { upload {
content = "${file("${path.module}/conf/extra_links.tmpl")}" content = file("${path.module}/conf/extra_links.tmpl")
file = "/data/gitea/templates/custom/extra_links.tmpl" file = "/data/gitea/templates/custom/extra_links.tmpl"
} }
# This is the main configuration file # This is the main configuration file
upload { upload {
content = "${data.template_file.gitea-config-file.rendered}" content = data.template_file.gitea-config-file.rendered
file = "/data/gitea/conf/app.ini" file = "/data/gitea/conf/app.ini"
} }
memory = 512 memory = 512
restart = "always" restart = "always"
destroy_grace_seconds = 10 destroy_grace_seconds = 10
must_run = true must_run = true
networks = ["${docker_network.gitea.id}", "${var.traefik-network-id}"] networks = [docker_network.gitea.id, var.traefik-network-id]
# This doesn't work. # This doesn't work.
# See https://github.com/terraform-providers/terraform-provider-docker/issues/48 # See https://github.com/terraform-providers/terraform-provider-docker/issues/48
# lifecycle { # lifecycle {
@ -66,6 +69,7 @@ resource "docker_container" "gitea" {
} }
resource "docker_image" "gitea" { resource "docker_image" "gitea" {
name = "${data.docker_registry_image.gitea.name}" name = data.docker_registry_image.gitea.name
pull_triggers = ["${data.docker_registry_image.gitea.sha256_digest}"] pull_triggers = [data.docker_registry_image.gitea.sha256_digest]
} }

View File

@ -1 +0,0 @@

View File

@ -2,3 +2,4 @@ resource "docker_network" "gitea" {
name = "gitea" name = "gitea"
driver = "bridge" driver = "bridge"
} }

View File

@ -1,6 +1,6 @@
resource "docker_container" "redis" { resource "docker_container" "redis" {
name = "gitea-redis" name = "gitea-redis"
image = "${docker_image.redis.latest}" image = docker_image.redis.latest
volumes { volumes {
host_path = "/mnt/xwing/cache/gitea" host_path = "/mnt/xwing/cache/gitea"
@ -12,11 +12,12 @@ resource "docker_container" "redis" {
destroy_grace_seconds = 10 destroy_grace_seconds = 10
must_run = true must_run = true
networks = ["${docker_network.gitea.id}"] networks = [docker_network.gitea.id]
} }
resource "docker_image" "redis" { resource "docker_image" "redis" {
name = "${data.docker_registry_image.redis.name}" name = data.docker_registry_image.redis.name
pull_triggers = ["${data.docker_registry_image.redis.sha256_digest}"] pull_triggers = [data.docker_registry_image.redis.sha256_digest]
keep_locally = true keep_locally = true
} }

View File

@ -1,18 +1,32 @@
variable "traefik-labels" { variable "traefik-labels" {
type = "map" type = map(string)
} }
variable "domain" {} variable "domain" {
}
variable "ips" { variable "ips" {
type = "map" type = map(string)
} }
variable "secret-key" {} variable "secret-key" {
variable "internal-token" {} }
variable "smtp-password" {}
variable "lfs-jwt-secret" {} variable "internal-token" {
variable "oauth2-jwt-secret" {} }
variable "mysql-password" {}
variable "smtp-password" {
}
variable "lfs-jwt-secret" {
}
variable "oauth2-jwt-secret" {
}
variable "mysql-password" {
}
variable "traefik-network-id" {
}
variable "traefik-network-id" {}

4
gitea/versions.tf Normal file
View File

@ -0,0 +1,4 @@
terraform {
required_version = ">= 0.12"
}

View File

@ -1,3 +1,4 @@
resource "docker_volume" "gitea_volume" { resource "docker_volume" "gitea_volume" {
name = "gitea_volume" name = "gitea_volume"
} }

View File

@ -10,4 +10,3 @@
# }, # },
# ] # ]
# } # }

View File

@ -3,11 +3,11 @@
module "kaarana" { module "kaarana" {
source = "./kaarana" source = "./kaarana"
root_db_password = "${data.pass_password.kaarana-root-db-password.password}" root_db_password = data.pass_password.kaarana-root-db-password.password
db_password = "${data.pass_password.kaarana-db-password.password}" db_password = data.pass_password.kaarana-db-password.password
providers = { providers = {
docker = "docker.sydney" docker = docker.sydney
} }
} }
@ -18,3 +18,4 @@ data "pass_password" "kaarana-root-db-password" {
data "pass_password" "kaarana-db-password" { data "pass_password" "kaarana-db-password" {
path = "KAARANA_DB_PASSWORD" path = "KAARANA_DB_PASSWORD"
} }

View File

@ -18,7 +18,7 @@ resource "docker_network" "kaarana-db" {
// Run a small mySQL container in this subnet // Run a small mySQL container in this subnet
resource "docker_container" "mysql" { resource "docker_container" "mysql" {
image = "${docker_image.db.latest}" image = docker_image.db.latest
name = "kaarana-mariadb" name = "kaarana-mariadb"
restart = "always" restart = "always"
must_run = true must_run = true
@ -36,7 +36,16 @@ resource "docker_container" "mysql" {
} }
networks_advanced { networks_advanced {
name = "kaarana-db" name = "kaarana-db"
aliases = ["${local.db_hostname}"] # TF-UPGRADE-TODO: In Terraform v0.10 and earlier, it was sometimes necessary to
# force an interpolation expression to be interpreted as a list by wrapping it
# in an extra set of list brackets. That form was supported for compatibility in
# v0.11, but is no longer supported in Terraform v0.12.
#
# If the expression in the following list itself returns a list, remove the
# brackets to avoid interpretation as a list of lists. If the expression
# returns a single list item then leave it as-is and remove this TODO comment.
aliases = [local.db_hostname]
} }
} }

View File

@ -4,7 +4,7 @@ data "docker_registry_image" "wp" {
resource "docker_image" "wp" { resource "docker_image" "wp" {
name = "wordpress" name = "wordpress"
pull_triggers = ["${data.docker_registry_image.wp.sha256_digest}"] pull_triggers = [data.docker_registry_image.wp.sha256_digest]
} }
data "docker_registry_image" "db" { data "docker_registry_image" "db" {
@ -13,7 +13,7 @@ data "docker_registry_image" "db" {
resource "docker_image" "db" { resource "docker_image" "db" {
name = "mariadb" name = "mariadb"
pull_triggers = ["${data.docker_registry_image.db.sha256_digest}"] pull_triggers = [data.docker_registry_image.db.sha256_digest]
} }
data "docker_registry_image" "traefik" { data "docker_registry_image" "traefik" {
@ -22,5 +22,6 @@ data "docker_registry_image" "traefik" {
resource "docker_image" "traefik" { resource "docker_image" "traefik" {
name = "traefik" name = "traefik"
pull_triggers = ["${data.docker_registry_image.db.sha256_digest}"] pull_triggers = [data.docker_registry_image.db.sha256_digest]
} }

View File

@ -12,7 +12,7 @@ resource "docker_network" "traefik" {
resource "docker_container" "traefik" { resource "docker_container" "traefik" {
name = "traefik" name = "traefik"
image = "${docker_image.traefik.latest}" image = docker_image.traefik.latest
# Do not offer HTTP2 # Do not offer HTTP2
# https://community.containo.us/t/traefikv2-http-2-0/1199 # https://community.containo.us/t/traefikv2-http-2-0/1199
@ -21,7 +21,7 @@ resource "docker_container" "traefik" {
] ]
upload { upload {
content = "${file("${path.module}/traefik.toml")}" content = file("${path.module}/traefik.toml")
file = "/etc/traefik/traefik.toml" file = "/etc/traefik/traefik.toml"
} }
@ -53,12 +53,11 @@ resource "docker_container" "traefik" {
destroy_grace_seconds = 10 destroy_grace_seconds = 10
must_run = true must_run = true
networks_advanced = [ networks_advanced {
{ name = "bridge"
name = "bridge" }
}, networks_advanced {
{ name = "traefik"
name = "traefik" }
},
]
} }

View File

@ -1,8 +1,12 @@
variable "root_db_password" {} variable "root_db_password" {
variable "db_password" {} }
variable "db_password" {
}
locals { locals {
username = "wordpress" username = "wordpress"
database = "wordpress" database = "wordpress"
db_hostname = "kaarana.db" db_hostname = "kaarana.db"
} }

4
kaarana/versions.tf Normal file
View File

@ -0,0 +1,4 @@
terraform {
required_version = ">= 0.12"
}

View File

@ -1,18 +1,16 @@
resource "docker_container" "wp" { resource "docker_container" "wp" {
image = "${docker_image.wp.latest}" image = docker_image.wp.latest
name = "kaarana-wordpress" name = "kaarana-wordpress"
restart = "always" restart = "always"
must_run = true must_run = true
labels { labels = {
"traefik.enable" = "true" "traefik.enable" = "true"
"traefik.tcp.routers.kaarana.rule" = "HostSNI(`kaarana.captnemo.in`)" "traefik.tcp.routers.kaarana.rule" = "HostSNI(`kaarana.captnemo.in`)"
"traefik.tcp.routers.kaarana.tls" = "true" "traefik.tcp.routers.kaarana.tls" = "true"
# "traefik.tcp.routers.kaarana.tls.options" = "foo" # "traefik.tcp.routers.kaarana.tls.options" = "foo"
"traefik.tcp.services.wordpress.loadbalancer.server.port" = "80" "traefik.tcp.services.wordpress.loadbalancer.server.port" = "80"
# "traefik.tcp.routers.kaarana.entrypoints" = "web-secure" # "traefik.tcp.routers.kaarana.entrypoints" = "web-secure"
"traefik.tcp.routers.kaarana.tls.certResolver" = "default" "traefik.tcp.routers.kaarana.tls.certResolver" = "default"
"traefik.tcp.routers.kaarana.tls.domains[0].main" = "kaarana.captnemo.in" "traefik.tcp.routers.kaarana.tls.domains[0].main" = "kaarana.captnemo.in"
@ -37,17 +35,16 @@ resource "docker_container" "wp" {
ip = "10.8.0.1" ip = "10.8.0.1"
} }
networks_advanced = [ networks_advanced {
{ name = "kaarana-db"
name = "kaarana-db" }
}, networks_advanced {
{ // TODO: Once configuration/plugins have stabilized
// TODO: Once configuration/plugins have stabilized // remove internet access from wordpress
// remove internet access from wordpress name = "bridge"
name = "bridge" }
}, networks_advanced {
{ name = "traefik"
name = "traefik" }
},
]
} }

View File

@ -39,4 +39,3 @@
# type = "A" # type = "A"
# ttl = 120 # ttl = 120
# } # }

View File

@ -1,20 +1,20 @@
module "klaxon-db" { module "klaxon-db" {
source = "modules/postgres" source = "./modules/postgres"
name = "klaxon" name = "klaxon"
password = "${data.pass_password.klaxon-db-password.password}" password = data.pass_password.klaxon-db-password.password
} }
module "klaxon" { module "klaxon" {
name = "klaxon" name = "klaxon"
source = "modules/container" source = "./modules/container"
web { web = {
expose = true expose = true
port = "3000" port = "3000"
host = "klaxon.${var.root-domain}" host = "klaxon.${var.root-domain}"
} }
resource { resource = {
memory = 1024 memory = 1024
memory_swap = 1024 memory_swap = 1024
} }
@ -29,7 +29,7 @@ module "klaxon" {
"KLAXON_FORCE_SSL=false", "KLAXON_FORCE_SSL=false",
"KLAXON_COMPILE_ASSETS=true", "KLAXON_COMPILE_ASSETS=true",
"ADMIN_EMAILS=klaxon@captnemo.in", "ADMIN_EMAILS=klaxon@captnemo.in",
"MAILER_FROM_ADDRESS=klaxon@sendgrid.captnemo.in" "MAILER_FROM_ADDRESS=klaxon@sendgrid.captnemo.in",
] ]
restart = "always" restart = "always"
@ -38,9 +38,13 @@ module "klaxon" {
networks_advanced = [ networks_advanced = [
{ {
name = "traefik" name = "traefik"
}, { },
{
name = "postgres" name = "postgres"
}, { },
{
name = "external" name = "external"
}] },
]
} }

View File

@ -17,4 +17,3 @@
# } # }
# } # }
# } # }

97
main.tf
View File

@ -1,96 +1,97 @@
module "cloudflare" { module "cloudflare" {
source = "cloudflare" source = "./cloudflare"
domain = "bb8.fun" domain = "bb8.fun"
ips = "${var.ips}" zone_id = lookup(data.cloudflare_zones.bb8.zones[0], "id")
ips = var.ips
droplet_ip = "${module.digitalocean.droplet_ipv4}" droplet_ip = module.digitalocean.droplet_ipv4
} }
module "docker" { module "docker" {
source = "docker" source = "./docker"
web_username = "${data.pass_password.web_username.password}" web_username = data.pass_password.web_username.password
web_password = "${data.pass_password.web_password.password}" web_password = data.pass_password.web_password.password
cloudflare_key = "${data.pass_password.cloudflare_key.password}" cloudflare_key = data.pass_password.cloudflare_key.password
cloudflare_email = "bb8@captnemo.in" cloudflare_email = "bb8@captnemo.in"
wiki_session_secret = "${data.pass_password.wiki_session_secret.password}" wiki_session_secret = data.pass_password.wiki_session_secret.password
ips = "${var.ips}" ips = var.ips
domain = "bb8.fun" domain = "bb8.fun"
} }
module "db" { module "db" {
source = "db" source = "./db"
postgres-root-password = "${data.pass_password.postgres-root-password.password}" postgres-root-password = data.pass_password.postgres-root-password.password
ips = "${var.ips}" ips = var.ips
} }
module "timemachine" { module "timemachine" {
source = "timemachine" source = "./timemachine"
ips = "${var.ips}" ips = var.ips
username-1 = "vikalp" username-1 = "vikalp"
username-2 = "rishav" username-2 = "rishav"
password-1 = "${data.pass_password.timemachine-password-1.password}" password-1 = data.pass_password.timemachine-password-1.password
password-2 = "${data.pass_password.timemachine-password-2.password}" password-2 = data.pass_password.timemachine-password-2.password
} }
module "gitea" { module "gitea" {
source = "gitea" source = "./gitea"
domain = "git.captnemo.in" domain = "git.captnemo.in"
traefik-labels = "${var.traefik-common-labels}" traefik-labels = var.traefik-common-labels
ips = "${var.ips}" ips = var.ips
secret-key = "${data.pass_password.gitea-secret-key.password}" secret-key = data.pass_password.gitea-secret-key.password
internal-token = "${data.pass_password.gitea-internal-token.password}" internal-token = data.pass_password.gitea-internal-token.password
smtp-password = "${data.pass_password.gitea-smtp-password.password}" smtp-password = data.pass_password.gitea-smtp-password.password
lfs-jwt-secret = "${data.pass_password.gitea-lfs-jwt-secret.password}" lfs-jwt-secret = data.pass_password.gitea-lfs-jwt-secret.password
oauth2-jwt-secret = "${data.pass_password.gitea-oauth2-jwt-secret.password}" oauth2-jwt-secret = data.pass_password.gitea-oauth2-jwt-secret.password
//passed, but not used //passed, but not used
mysql-password = "" mysql-password = ""
traefik-network-id = "${module.docker.traefik-network-id}" traefik-network-id = module.docker.traefik-network-id
} }
module "opml" { module "opml" {
source = "opml" source = "./opml"
domain = "opml.bb8.fun" domain = "opml.bb8.fun"
client-id = "${data.pass_password.opml-github-client-id.password}" client-id = data.pass_password.opml-github-client-id.password
client-secret = "${data.pass_password.opml-github-client-secret.password}" client-secret = data.pass_password.opml-github-client-secret.password
traefik-network-id = "${module.docker.traefik-network-id}" traefik-network-id = module.docker.traefik-network-id
} }
module "radicale" { module "radicale" {
source = "radicale" source = "./radicale"
domain = "radicale.bb8.fun" domain = "radicale.bb8.fun"
} }
module "media" { module "media" {
source = "media" source = "./media"
domain = "bb8.fun" domain = "bb8.fun"
traefik-labels = "${var.traefik-common-labels}" traefik-labels = var.traefik-common-labels
ips = "${var.ips}" ips = var.ips
traefik-network-id = "${module.docker.traefik-network-id}" traefik-network-id = module.docker.traefik-network-id
lastfm_api_key = "${data.pass_password.navidrome-lastfm-api-key.password}" lastfm_api_key = data.pass_password.navidrome-lastfm-api-key.password
lastfm_secret = "${data.pass_password.navidrome-lastfm-secret.password}" lastfm_secret = data.pass_password.navidrome-lastfm-secret.password
spotify_id = "${data.pass_password.navidrome-spotify-id.password}" spotify_id = data.pass_password.navidrome-spotify-id.password
spotify_secret = "${data.pass_password.navidrome-spotify-secret.password}" spotify_secret = data.pass_password.navidrome-spotify-secret.password
} }
module "monitoring" { module "monitoring" {
source = "monitoring" source = "./monitoring"
gf-security-admin-password = "${data.pass_password.gf-security-admin-password.password}" gf-security-admin-password = data.pass_password.gf-security-admin-password.password
domain = "bb8.fun" domain = "bb8.fun"
transmission = "${module.media.names-transmission}" transmission = module.media.names-transmission
traefik-labels = "${var.traefik-common-labels}" traefik-labels = var.traefik-common-labels
ips = "${var.ips}" ips = var.ips
links-traefik = "${module.docker.names-traefik}" links-traefik = module.docker.names-traefik
traefik-network-id = "${module.docker.traefik-network-id}" traefik-network-id = module.docker.traefik-network-id
} }
module "digitalocean" { module "digitalocean" {
source = "digitalocean" source = "./digitalocean"
} }
// Used to force access to ISP related resources // Used to force access to ISP related resources
# module "tinyproxy" { # module "tinyproxy" {
# source = "tinyproxy" # source = "./tinyproxy"
# ips = "${var.ips}" # ips = "${var.ips}"
# } # }

View File

@ -2,43 +2,34 @@
# source = "../modules/container" # source = "../modules/container"
# image = "linuxserver/airsonic:latest" # image = "linuxserver/airsonic:latest"
# name = "airsonic" # name = "airsonic"
# resource { # resource {
# memory = "1024" # memory = "1024"
# memory_swap = "1024" # memory_swap = "1024"
# } # }
# web { # web {
# port = 4040 # port = 4040
# host = "airsonic.bb8.fun" # host = "airsonic.bb8.fun"
# expose = true # expose = true
# } # }
# networks = "${list(docker_network.media.id, data.docker_network.bridge.id)}" # networks = "${list(docker_network.media.id, data.docker_network.bridge.id)}"
# env = [ # env = [
# "PUID=1004", # "PUID=1004",
# "PGID=1003", # "PGID=1003",
# "TZ=Asia/Kolkata", # "TZ=Asia/Kolkata",
# "JAVA_OPTS=-Xmx512m -Dserver.use-forward-headers=true -Dserver.context-path=/", # "JAVA_OPTS=-Xmx512m -Dserver.use-forward-headers=true -Dserver.context-path=/",
# ] # ]
# devices = [{ # devices = [{
# host_path = "/dev/snd" # host_path = "/dev/snd"
# container_path = "/dev/snd" # container_path = "/dev/snd"
# }] # }]
# # files = [ # # files = [
# # "/usr/lib/jvm/java-1.8-openjdk/jre/lib/airsonic.properties", # # "/usr/lib/jvm/java-1.8-openjdk/jre/lib/airsonic.properties",
# # "/usr/lib/jvm/java-1.8-openjdk/jre/lib/sound.properties", # # "/usr/lib/jvm/java-1.8-openjdk/jre/lib/sound.properties",
# # ] # # ]
# # contents = [ # # contents = [
# # "${data.template_file.airsonic-properties-file.rendered}", # # "${data.template_file.airsonic-properties-file.rendered}",
# # "${file("${path.module}/conf/airsonic.sound.properties")}", # # "${file("${path.module}/conf/airsonic.sound.properties")}",
# # ] # # ]
# volumes = [ # volumes = [
# { # {
# host_path = "/mnt/xwing/config/airsonic2" # host_path = "/mnt/xwing/config/airsonic2"
@ -62,16 +53,10 @@
# }, # },
# ] # ]
# } # }
# data "template_file" "airsonic-properties-file" { # data "template_file" "airsonic-properties-file" {
# template = "${file("${path.module}/conf/airsonic.properties.tpl")}" # template = "${file("${path.module}/conf/airsonic.properties.tpl")}"
# vars { # vars {
# smtp-password = "${var.airsonic-smtp-password}" # smtp-password = "${var.airsonic-smtp-password}"
# # db-password = "${var.airsonic-db-password}" # # db-password = "${var.airsonic-db-password}"
# } # }
# } # }

View File

@ -1,3 +1,4 @@
data "docker_network" "bridge" { data "docker_network" "bridge" {
name = "bridge" name = "bridge"
} }

View File

@ -1,6 +1,6 @@
resource "docker_container" "emby" { resource "docker_container" "emby" {
name = "emby" name = "emby"
image = "${docker_image.emby.latest}" image = docker_image.emby.latest
volumes { volumes {
host_path = "/mnt/xwing/config/emby" host_path = "/mnt/xwing/config/emby"
@ -12,15 +12,16 @@ resource "docker_container" "emby" {
container_path = "/media" container_path = "/media"
} }
labels = "${merge( labels = merge(
var.traefik-labels, var.traefik-labels,
map( {
"traefik.frontend.rule", "Host:emby.in.${var.domain},emby.${var.domain}", "traefik.frontend.rule" = "Host:emby.in.${var.domain},emby.${var.domain}"
"traefik.frontend.passHostHeader", "true", "traefik.frontend.passHostHeader" = "true"
"traefik.port", 8096, "traefik.port" = 8096
))}" },
)
networks = ["${docker_network.media.id}", "${var.traefik-network-id}"] networks = [docker_network.media.id, var.traefik-network-id]
memory = 2048 memory = 2048
restart = "unless-stopped" restart = "unless-stopped"
@ -38,10 +39,11 @@ resource "docker_container" "emby" {
} }
resource "docker_image" "emby" { resource "docker_image" "emby" {
name = "${data.docker_registry_image.emby.name}" name = data.docker_registry_image.emby.name
pull_triggers = ["${data.docker_registry_image.emby.sha256_digest}"] pull_triggers = [data.docker_registry_image.emby.sha256_digest]
} }
data "docker_registry_image" "emby" { data "docker_registry_image" "emby" {
name = "emby/embyserver:latest" name = "emby/embyserver:latest"
} }

View File

@ -2,21 +2,23 @@ module "jackett" {
name = "jackett" name = "jackett"
source = "../modules/container" source = "../modules/container"
image = "linuxserver/jackett:latest" image = "linuxserver/jackett:latest"
# TODO FIXME
# networks = [data.docker_network.bridge.id]
networks = "${list(data.docker_network.bridge.id)}" web = {
web {
expose = true expose = true
port = 9117 port = 9117
host = "jackett.${var.domain}" host = "jackett.${var.domain}"
} }
volumes = [{ volumes = [
host_path = "/mnt/xwing/config/jackett" {
container_path = "/config" host_path = "/mnt/xwing/config/jackett"
}] container_path = "/config"
},
]
resource { resource = {
memory = "256" memory = "256"
memory_swap = "512" memory_swap = "512"
} }
@ -27,3 +29,4 @@ module "jackett" {
"TZ=Asia/Kolkata", "TZ=Asia/Kolkata",
] ]
} }

View File

@ -3,19 +3,21 @@ data "docker_registry_image" "lidarr" {
} }
resource "docker_image" "lidarr" { resource "docker_image" "lidarr" {
name = "${data.docker_registry_image.lidarr.name}" name = data.docker_registry_image.lidarr.name
pull_triggers = ["${data.docker_registry_image.lidarr.sha256_digest}"] pull_triggers = [data.docker_registry_image.lidarr.sha256_digest]
} }
resource "docker_container" "lidarr" { resource "docker_container" "lidarr" {
name = "lidarr" name = "lidarr"
image = "${docker_image.lidarr.latest}" image = docker_image.lidarr.latest
labels = "${merge( labels = merge(
var.traefik-labels, map( var.traefik-labels,
"traefik.port", 8686, {
"traefik.frontend.rule","Host:lidarr.${var.domain}" "traefik.port" = 8686
))}" "traefik.frontend.rule" = "Host:lidarr.${var.domain}"
},
)
memory = 512 memory = 512
restart = "unless-stopped" restart = "unless-stopped"
@ -43,5 +45,6 @@ resource "docker_container" "lidarr" {
"TZ=Asia/Kolkata", "TZ=Asia/Kolkata",
] ]
networks = ["${docker_network.media.id}", "${var.traefik-network-id}"] networks = [docker_network.media.id, var.traefik-network-id]
} }

View File

@ -5,12 +5,12 @@ module "navidrome" {
user = 1004 user = 1004
resource { resource = {
memory = "1024" memory = "1024"
memory_swap = "1024" memory_swap = "1024"
} }
web { web = {
port = 4533 port = 4533
host = "music.bb8.fun" host = "music.bb8.fun"
expose = true expose = true
@ -22,14 +22,14 @@ module "navidrome" {
"ND_SESSIONTIMEOUT=300h", "ND_SESSIONTIMEOUT=300h",
"ND_BASEURL=", "ND_BASEURL=",
"ND_AUTOIMPORTPLAYLISTS=false", "ND_AUTOIMPORTPLAYLISTS=false",
# "ND_UIWELCOMEMESSAGE=Welcome to Scarif Music Archives",
"ND_LASTFM_APIKEY=${var.lastfm_api_key}", "ND_LASTFM_APIKEY=${var.lastfm_api_key}",
"ND_LASTFM_SECRET=${var.lastfm_secret}", "ND_LASTFM_SECRET=${var.lastfm_secret}",
"ND_SPOTIFY_ID=${var.spotify_id}", "ND_SPOTIFY_ID=${var.spotify_id}",
"ND_SPOTIFY_SECRET=${var.spotify_secret}" "ND_SPOTIFY_SECRET=${var.spotify_secret}",
] ]
networks = "${list(docker_network.media.id, data.docker_network.bridge.id)}" # TODO FIXME
# networks = [docker_network.media.id, data.docker_network.bridge.id]
volumes = [ volumes = [
{ {
@ -40,6 +40,7 @@ module "navidrome" {
host_path = "/mnt/xwing/media/Music" host_path = "/mnt/xwing/media/Music"
container_path = "/music" container_path = "/music"
read_only = true read_only = true
} },
] ]
} }

View File

@ -7,3 +7,4 @@ resource "docker_network" "media" {
gateway = "172.18.0.1" gateway = "172.18.0.1"
} }
} }

View File

@ -1,7 +1,8 @@
output "names-transmission" { output "names-transmission" {
value = "${docker_container.transmission.name}" value = docker_container.transmission.name
} }
output "names-emby" { output "names-emby" {
value = "${docker_container.emby.name}" value = docker_container.emby.name
} }

View File

@ -3,15 +3,16 @@ module "radarr" {
source = "../modules/container" source = "../modules/container"
image = "linuxserver/radarr:latest" image = "linuxserver/radarr:latest"
networks = "${list(docker_network.media.id, data.docker_network.bridge.id)}" # TODO FIXME
# networks = [docker_network.media.id, data.docker_network.bridge.id]
web { web = {
expose = true expose = true
port = 7878 port = 7878
host = "radarr.${var.domain}" host = "radarr.${var.domain}"
} }
resource { resource = {
memory = 512 memory = 512
memory_swap = 1024 memory_swap = 1024
} }
@ -37,3 +38,4 @@ module "radarr" {
"TZ=Asia/Kolkata", "TZ=Asia/Kolkata",
] ]
} }

View File

@ -3,13 +3,13 @@ module "requestrr" {
source = "../modules/container" source = "../modules/container"
image = "darkalfx/requestrr:latest" image = "darkalfx/requestrr:latest"
web { web = {
expose = true expose = true
port = 4545 port = 4545
host = "requestrr.${var.domain}" host = "requestrr.${var.domain}"
} }
resource { resource = {
memory = 256 memory = 256
memory_swap = 256 memory_swap = 256
} }
@ -18,8 +18,10 @@ module "requestrr" {
{ {
host_path = "/mnt/xwing/config/requestrr" host_path = "/mnt/xwing/config/requestrr"
container_path = "/root/config" container_path = "/root/config"
} },
] ]
networks = "${list(docker_network.media.id, data.docker_network.bridge.id)}" # TODO FIXME
# networks = [docker_network.media.id, data.docker_network.bridge.id]
} }

View File

@ -3,13 +3,13 @@ module "sonarr-container" {
source = "../modules/container" source = "../modules/container"
image = "linuxserver/sonarr:latest" image = "linuxserver/sonarr:latest"
web { web = {
expose = true expose = true
port = 8989 port = 8989
host = "sonarr.${var.domain}" host = "sonarr.${var.domain}"
} }
resource { resource = {
memory = 512 memory = 512
memory_swap = 1024 memory_swap = 1024
} }
@ -35,5 +35,6 @@ module "sonarr-container" {
"TZ=Asia/Kolkata", "TZ=Asia/Kolkata",
] ]
networks = "${list(docker_network.media.id, data.docker_network.bridge.id)}" networks = [docker_network.media.id, data.docker_network.bridge.id]
} }

View File

@ -1,18 +1,19 @@
resource "docker_container" "transmission" { resource "docker_container" "transmission" {
name = "transmission" name = "transmission"
image = "${docker_image.transmission.latest}" image = docker_image.transmission.latest
labels = "${merge( labels = merge(
var.traefik-labels, var.traefik-labels,
map( {
"traefik.frontend.auth.basic", "${var.basic_auth}", "traefik.frontend.auth.basic" = var.basic_auth
"traefik.port", 9091, "traefik.port" = 9091
))}" },
)
ports { ports {
internal = 51413 internal = 51413
external = 51413 external = 51413
ip = "${var.ips["eth0"]}" ip = var.ips["eth0"]
protocol = "udp" protocol = "udp"
} }
@ -32,7 +33,7 @@ resource "docker_container" "transmission" {
} }
upload { upload {
content = "${file("${path.module}/conf/transmission.json")}" content = file("${path.module}/conf/transmission.json")
file = "/config/settings.json" file = "/config/settings.json"
} }
@ -42,7 +43,7 @@ resource "docker_container" "transmission" {
"TZ=Asia/Kolkata", "TZ=Asia/Kolkata",
] ]
networks = ["${docker_network.media.id}", "${var.traefik-network-id}"] networks = [docker_network.media.id, var.traefik-network-id]
memory = 1024 memory = 1024
restart = "unless-stopped" restart = "unless-stopped"
@ -51,10 +52,11 @@ resource "docker_container" "transmission" {
} }
resource "docker_image" "transmission" { resource "docker_image" "transmission" {
name = "${data.docker_registry_image.transmission.name}" name = data.docker_registry_image.transmission.name
pull_triggers = ["${data.docker_registry_image.transmission.sha256_digest}"] pull_triggers = [data.docker_registry_image.transmission.sha256_digest]
} }
data "docker_registry_image" "transmission" { data "docker_registry_image" "transmission" {
name = "linuxserver/transmission:latest" name = "linuxserver/transmission:latest"
} }

View File

@ -1,11 +1,11 @@
variable "domain" { variable "domain" {
type = "string" type = string
} }
# variable "airsonic-smtp-password" {} # variable "airsonic-smtp-password" {}
variable "traefik-labels" { variable "traefik-labels" {
type = "map" type = map(string)
} }
// TODO: Remove duplication // TODO: Remove duplication
@ -14,23 +14,29 @@ variable "basic_auth" {
} }
variable "ips" { variable "ips" {
type = "map" type = map(string)
}
variable "traefik-network-id" {
} }
variable "traefik-network-id" {}
variable "lastfm_api_key" { variable "lastfm_api_key" {
description = "Navidrome Configuration for lastfm_api_key" description = "Navidrome Configuration for lastfm_api_key"
type = "string" type = string
} }
variable "lastfm_secret" { variable "lastfm_secret" {
description = "Navidrome Configuration for lastfm_secret" description = "Navidrome Configuration for lastfm_secret"
type = "string" type = string
} }
variable "spotify_id" { variable "spotify_id" {
description = "Navidrome Configuration for spotify_id" description = "Navidrome Configuration for spotify_id"
type = "string" type = string
} }
variable "spotify_secret" { variable "spotify_secret" {
description = "Navidrome Configuration for spotify_secret" description = "Navidrome Configuration for spotify_secret"
type = "string" type = string
} }

4
media/versions.tf Normal file
View File

@ -0,0 +1,4 @@
terraform {
required_version = ">= 0.12"
}

View File

@ -1,19 +1,20 @@
module "miniflux-container" { module "miniflux-container" {
name = "miniflux" name = "miniflux"
source = "modules/container" source = "./modules/container"
image = "miniflux/miniflux:2.0.28" image = "miniflux/miniflux:2.0.28"
web { web = {
expose = true expose = true
port = 8080 port = 8080
host = "rss.captnemo.in" host = "rss.captnemo.in"
} }
networks = "${list( # TODO FIXME
data.docker_network.bridge.id, # networks = [
module.docker.traefik-network-id, # data.docker_network.bridge.id,
module.db.postgres-network-id # module.docker.traefik-network-id,
)}" # module.db.postgres-network-id,
# ]
env = [ env = [
"DATABASE_URL=postgres://miniflux:${data.pass_password.miniflux-db-password.password}@postgres/miniflux?sslmode=disable", "DATABASE_URL=postgres://miniflux:${data.pass_password.miniflux-db-password.password}@postgres/miniflux?sslmode=disable",
@ -22,7 +23,8 @@ module "miniflux-container" {
} }
module "miniflux-db" { module "miniflux-db" {
source = "modules/postgres" source = "./modules/postgres"
name = "miniflux" name = "miniflux"
password = "${data.pass_password.miniflux-db-password.password}" password = data.pass_password.miniflux-db-password.password
} }

View File

@ -1,36 +1,34 @@
locals { locals {
default_labels { default_labels = {
"managed.by" = "nebula" "managed.by" = "nebula"
} }
web { web = {
"traefik.port" = "${lookup(var.web, "port", "80")}" "traefik.port" = lookup(var.web, "port", "80")
"traefik.frontend.rule" = "Host:${lookup(var.web, "host", "example.invalid")}" "traefik.frontend.rule" = "Host:${lookup(var.web, "host", "example.invalid")}"
"traefik.protocol" = "${lookup(var.web, "protocol", "http")}" "traefik.protocol" = lookup(var.web, "protocol", "http")
} }
resource { resource = {
memory = "${lookup(var.resource, "memory", 64)}" memory = lookup(var.resource, "memory", 64)
memory_swap = "${lookup(var.resource, "memory_swap", 128)}" memory_swap = lookup(var.resource, "memory_swap", 128)
} }
traefik_common_labels { traefik_common_labels = {
"traefik.enable" = "true" "traefik.enable" = "true"
// HSTS // HSTS
"traefik.frontend.headers.SSLTemporaryRedirect" = "true" "traefik.frontend.headers.SSLTemporaryRedirect" = "true"
"traefik.frontend.headers.STSSeconds" = "2592000" "traefik.frontend.headers.STSSeconds" = "2592000"
"traefik.frontend.headers.STSIncludeSubdomains" = "false" "traefik.frontend.headers.STSIncludeSubdomains" = "false"
// X-Powered-By, Server headers // X-Powered-By, Server headers
"traefik.frontend.headers.customResponseHeaders" = "${var.xpoweredby}" "traefik.frontend.headers.customResponseHeaders" = var.xpoweredby
"traefik.frontend.headers.contentTypeNosniff" = "true" "traefik.frontend.headers.contentTypeNosniff" = "true"
"traefik.frontend.headers.browserXSSFilter" = "true" "traefik.frontend.headers.browserXSSFilter" = "true"
"traefik.docker.network" = "traefik"
"traefik.docker.network" = "traefik"
} }
traefik_auth_labels { traefik_auth_labels = {
"traefik.frontend.auth.basic" = "${var.auth_header}" "traefik.frontend.auth.basic" = var.auth_header
} }
} }

View File

@ -1,11 +1,11 @@
data "docker_registry_image" "image" { data "docker_registry_image" "image" {
name = "${var.image}" name = var.image
} }
resource "docker_image" "image" { resource "docker_image" "image" {
name = "${var.image}" name = var.image
pull_triggers = ["${data.docker_registry_image.image.sha256_digest}"] pull_triggers = [data.docker_registry_image.image.sha256_digest]
keep_locally = "${var.keep_image}" keep_locally = var.keep_image
} }
data "docker_network" "traefik" { data "docker_network" "traefik" {
@ -13,113 +13,181 @@ data "docker_network" "traefik" {
} }
resource "docker_container" "container" { resource "docker_container" "container" {
name = "${var.name}" name = var.name
image = "${docker_image.image.latest}" image = docker_image.image.latest
ports = "${var.ports}" dynamic "ports" {
restart = "${var.restart}" for_each = var.ports
env = ["${var.env}"] content {
command = "${var.command}" external = ports.value.external
entrypoint = "${var.entrypoint}" internal = ports.value.internal
user = "${var.user}" ip = ports.value.ip
protocol = lookup(ports.value, "protocol", "tcp")
}
}
restart = var.restart
env = var.env
command = var.command
entrypoint = var.entrypoint
user = var.user
network_mode = "${var.network_mode}" network_mode = var.network_mode
capabilities = ["${var.capabilities}"] dynamic "capabilities" {
for_each = [var.capabilities]
content {
add = lookup(capabilities.value, "add", [])
drop = lookup(capabilities.value, "drop", [])
}
}
// Only attach the traefik network if dynamic "networks_advanced" {
// service is exposed to the web for_each = [var.networks_advanced]
networks = ["${concat(var.networks,compact(split(",",lookup(var.web, "expose", "false") == "false" ? "" :"${data.docker_network.traefik.id}")))}"] content {
# TF-UPGRADE-TODO: The automatic upgrade tool can't predict
# which keys might be set in maps assigned here, so it has
# produced a comprehensive set here. Consider simplifying
# this after confirming which keys can be set in practice.
networks_advanced = ["${var.networks_advanced}"] aliases = lookup(networks_advanced.value, "aliases", null)
ipv4_address = lookup(networks_advanced.value, "ipv4_address", null)
ipv6_address = lookup(networks_advanced.value, "ipv6_address", null)
name = networks_advanced.value.name
}
}
memory = "${local.resource["memory"]}" memory = local.resource["memory"]
memory_swap = "${local.resource["memory_swap"]}" memory_swap = local.resource["memory_swap"]
volumes = ["${var.volumes}"] dynamic "volumes" {
devices = ["${var.devices}"] for_each = [var.volumes]
content {
# TF-UPGRADE-TODO: The automatic upgrade tool can't predict
# which keys might be set in maps assigned here, so it has
# produced a comprehensive set here. Consider simplifying
# this after confirming which keys can be set in practice.
upload = ["${var.uploads}"] container_path = lookup(volumes.value, "container_path", null)
from_container = lookup(volumes.value, "from_container", null)
host_path = lookup(volumes.value, "host_path", null)
read_only = lookup(volumes.value, "read_only", null)
volume_name = lookup(volumes.value, "volume_name", null)
}
}
dynamic "devices" {
for_each = [var.devices]
content {
# TF-UPGRADE-TODO: The automatic upgrade tool can't predict
# which keys might be set in maps assigned here, so it has
# produced a comprehensive set here. Consider simplifying
# this after confirming which keys can be set in practice.
container_path = lookup(devices.value, "container_path", null)
host_path = devices.value.host_path
permissions = lookup(devices.value, "permissions", null)
}
}
dynamic "upload" {
for_each = [var.uploads]
content {
# TF-UPGRADE-TODO: The automatic upgrade tool can't predict
# which keys might be set in maps assigned here, so it has
# produced a comprehensive set here. Consider simplifying
# this after confirming which keys can be set in practice.
content = lookup(upload.value, "content", null)
content_base64 = lookup(upload.value, "content_base64", null)
executable = lookup(upload.value, "executable", null)
file = upload.value.file
source = lookup(upload.value, "source", null)
source_hash = lookup(upload.value, "source_hash", null)
}
}
# Look at this monstrosity # Look at this monstrosity
# And then https://github.com/hashicorp/terraform/issues/12453#issuecomment-365569618 # And then https://github.com/hashicorp/terraform/issues/12453#issuecomment-365569618
# for why this is needed # for why this is needed
labels = "${merge(local.default_labels, dynamic "labels" {
zipmap( for_each = merge(
concat( local.default_labels,
keys(local.default_labels), zipmap(
split("~", concat(
lookup(var.web, "expose", "false") == "false" ? keys(local.default_labels),
"" : split(
join("~", keys(local.traefik_common_labels)) "~",
) lookup(var.web, "expose", "false") == "false" ? "" : join("~", keys(local.traefik_common_labels)),
),
),
concat(
values(local.default_labels),
split(
"~",
lookup(var.web, "expose", "false") == "false" ? "" : join("~", values(local.traefik_common_labels)),
),
),
), ),
concat( zipmap(
values(local.default_labels), concat(
split("~", keys(local.default_labels),
lookup(var.web, "expose", "false") == "false" ? split(
"" : "~",
join("~", values(local.traefik_common_labels)) lookup(var.web, "expose", "false") == "false" ? "" : join("~", keys(local.web)),
) ),
) ),
), concat(
zipmap( values(local.default_labels),
concat( split(
keys(local.default_labels), "~",
split("~", lookup(var.web, "expose", "false") == "false" ? "" : join("~", values(local.web)),
lookup(var.web, "expose", "false") == "false" ? ),
"" : ),
join("~", keys(local.web))
)
), ),
concat( zipmap(
values(local.default_labels), concat(
split("~", keys(local.default_labels),
lookup(var.web, "expose", "false") == "false" ? split(
"" : "~",
join("~", values(local.web)) lookup(var.web, "expose", "false") == "false" ? "" : join("~", keys(local.traefik_common_labels)),
) ),
) ),
), concat(
values(local.default_labels),
split(
zipmap( "~",
concat( lookup(var.web, "expose", "false") == "false" ? "" : join("~", values(local.traefik_common_labels)),
keys(local.default_labels), ),
split("~", ),
lookup(var.web, "expose", "false") == "false" ?
"" :
join("~", keys(local.traefik_common_labels))
)
), ),
concat( zipmap(
values(local.default_labels), concat(
split("~", keys(local.default_labels),
lookup(var.web, "expose", "false") == "false" ? split(
"" : "~",
join("~", values(local.traefik_common_labels)) lookup(var.web, "auth", "false") == "false" ? "" : join("~", keys(local.traefik_auth_labels)),
) ),
) ),
), concat(
zipmap( values(local.default_labels),
concat( split(
keys(local.default_labels), "~",
split("~", lookup(var.web, "auth", "false") == "false" ? "" : join("~", values(local.traefik_auth_labels)),
lookup(var.web, "auth", "false") == "false" ? ),
"" : ),
join("~", keys(local.traefik_auth_labels))
)
), ),
concat(
values(local.default_labels),
split("~",
lookup(var.web, "auth", "false") == "false" ?
"" :
join("~", values(local.traefik_auth_labels))
)
)
) )
)}" content {
destroy_grace_seconds = "${var.destroy_grace_seconds}" # TF-UPGRADE-TODO: The automatic upgrade tool can't predict
must_run = "${var.must_run}" # which keys might be set in maps assigned here, so it has
# produced a comprehensive set here. Consider simplifying
# this after confirming which keys can be set in practice.
label = labels.value.label
value = labels.value.value
}
}
destroy_grace_seconds = var.destroy_grace_seconds
must_run = var.must_run
} }

View File

@ -8,20 +8,16 @@ variable "name" {
variable "ports" { variable "ports" {
description = "list of port mappings" description = "list of port mappings"
type = "list" type = list(string)
default = [] default = []
} }
variable "networks_advanced" { variable "networks_advanced" {
description = "list of networks_advanced" description = "list of networks_advanced"
type = "list" type = map
default = [] default = {
}
variable "networks" { }
description = "list of networks"
type = "list"
default = []
} }
variable "restart" { variable "restart" {
@ -32,7 +28,7 @@ variable "restart" {
variable "must_run" { variable "must_run" {
description = "If true, then the Docker container will be kept running. " description = "If true, then the Docker container will be kept running. "
default = "true" default = "true"
type = "string" type = string
} }
variable "user" { variable "user" {
@ -43,7 +39,7 @@ variable "user" {
variable "destroy_grace_seconds" { variable "destroy_grace_seconds" {
description = "Container will be destroyed after n seconds or on successful stop." description = "Container will be destroyed after n seconds or on successful stop."
default = 10 default = 10
type = "string" type = string
} }
variable "command" { variable "command" {
@ -95,20 +91,21 @@ variable "resource" {
variable "volumes" { variable "volumes" {
description = "volumes" description = "volumes"
type = "list" default = {}
default = []
} }
variable "capabilities" { variable "capabilities" {
description = "capabilities" description = "capabilities"
type = "list"
default = [] default = {
add = []
drop = []
}
} }
variable "devices" { variable "devices" {
description = "devices" description = "devices"
type = "list" default = {}
default = []
} }
variable "keep_image" { variable "keep_image" {
@ -119,3 +116,4 @@ variable "keep_image" {
variable "uploads" { variable "uploads" {
default = [] default = []
} }

View File

@ -0,0 +1,4 @@
terraform {
required_version = ">= 0.12"
}

View File

@ -3,14 +3,15 @@ variable "image" {
} }
data "docker_registry_image" "image" { data "docker_registry_image" "image" {
name = "${var.image}" name = var.image
} }
resource "docker_image" "image" { resource "docker_image" "image" {
name = "${data.docker_registry_image.image.name}" name = data.docker_registry_image.image.name
pull_triggers = ["${data.docker_registry_image.image.sha256_digest}"] pull_triggers = [data.docker_registry_image.image.sha256_digest]
} }
output "image" { output "image" {
value = "${docker_image.image.latest}" value = docker_image.image.latest
} }

View File

@ -0,0 +1,4 @@
terraform {
required_version = ">= 0.12"
}

View File

@ -1,10 +1,11 @@
resource "postgresql_database" "db" { resource "postgresql_database" "db" {
name = "${var.name}" name = var.name
owner = "${var.name}" owner = var.name
} }
resource "postgresql_role" "role" { resource "postgresql_role" "role" {
name = "${var.name}" name = var.name
login = true login = true
password = "${var.password}" password = var.password
} }

View File

@ -1,9 +1,10 @@
variable "name" { variable "name" {
description = "database/role name" description = "database/role name"
type = "string" type = string
} }
variable "password" { variable "password" {
description = "role password" description = "role password"
type = "string" type = string
} }

View File

@ -0,0 +1,4 @@
terraform {
required_version = ">= 0.12"
}

View File

@ -4,7 +4,7 @@ data "docker_registry_image" "act-exporter" {
resource "docker_container" "act-exporter" { resource "docker_container" "act-exporter" {
name = "act-exporter" name = "act-exporter"
image = "${docker_image.act-exporter.latest}" image = docker_image.act-exporter.latest
entrypoint = ["/usr/local/bin/node", "server.js"] entrypoint = ["/usr/local/bin/node", "server.js"]
@ -22,3 +22,4 @@ resource "docker_container" "act-exporter" {
destroy_grace_seconds = 10 destroy_grace_seconds = 10
must_run = true must_run = true
} }

View File

@ -3,7 +3,7 @@ module "cadvisor" {
name = "cadvisor" name = "cadvisor"
image = "google/cadvisor:latest" image = "google/cadvisor:latest"
resource { resource = {
memory = 512 memory = 512
memory_swap = 512 memory_swap = 512
} }
@ -48,9 +48,10 @@ module "cadvisor" {
}, },
] ]
web { web = {
expose = true expose = true
port = 8080 port = 8080
auth = true auth = true
} }
} }

View File

@ -1,3 +1,4 @@
data "docker_registry_image" "prometheus" { data "docker_registry_image" "prometheus" {
name = "prom/prometheus:latest" name = "prom/prometheus:latest"
} }

View File

@ -7,16 +7,18 @@ module "grafana" {
// grafana:grafana // grafana:grafana
user = "984:982" user = "984:982"
web { web = {
port = 3000 port = 3000
host = "grafana.${var.domain}" host = "grafana.${var.domain}"
expose = true expose = true
} }
volumes = [{ volumes = [
host_path = "/mnt/xwing/data/grafana" {
container_path = "/var/lib/grafana" host_path = "/mnt/xwing/data/grafana"
}] container_path = "/var/lib/grafana"
},
]
networks_advanced = [ networks_advanced = [
{ {
@ -31,8 +33,6 @@ module "grafana" {
"GF_SERVER_ROOT_URL=https://grafana.${var.domain}", "GF_SERVER_ROOT_URL=https://grafana.${var.domain}",
"GF_AUTH_ANONYMOUS_ENABLED=true", "GF_AUTH_ANONYMOUS_ENABLED=true",
"GF_AUTH_ANONYMOUS_ORG_NAME=Tatooine", "GF_AUTH_ANONYMOUS_ORG_NAME=Tatooine",
# Keep this disabled unless bringing up a new grafana instance
"GF_SECURITY_ADMIN_PASSWORD=${var.gf-security-admin-password}", "GF_SECURITY_ADMIN_PASSWORD=${var.gf-security-admin-password}",
] ]
@ -40,3 +40,4 @@ module "grafana" {
destroy_grace_seconds = 10 destroy_grace_seconds = 10
must_run = true must_run = true
} }

View File

@ -1,10 +1,11 @@
resource "docker_image" "prometheus" { resource "docker_image" "prometheus" {
name = "${data.docker_registry_image.prometheus.name}" name = data.docker_registry_image.prometheus.name
pull_triggers = ["${data.docker_registry_image.prometheus.sha256_digest}"] pull_triggers = [data.docker_registry_image.prometheus.sha256_digest]
} }
resource "docker_image" "act-exporter" { resource "docker_image" "act-exporter" {
name = "${data.docker_registry_image.act-exporter.name}" name = data.docker_registry_image.act-exporter.name
pull_triggers = ["${data.docker_registry_image.act-exporter.sha256_digest}"] pull_triggers = [data.docker_registry_image.act-exporter.sha256_digest]
keep_locally = true keep_locally = true
} }

View File

@ -3,3 +3,4 @@ resource "docker_network" "monitoring" {
driver = "bridge" driver = "bridge"
internal = true internal = true
} }

View File

@ -27,14 +27,17 @@ module "nodeexporter" {
command = [ command = [
"--path.procfs=/host/proc", "--path.procfs=/host/proc",
"--path.sysfs=/host/sys", "--path.sysfs=/host/sys",
"--collector.filesystem.ignored-mount-points=\"^/(sys|proc|dev|host|etc)($$|/)\"", "--collector.filesystem.ignored-mount-points=\"^/(sys|proc|dev|host|etc)($|/)\"",
] ]
networks = [ # TODO FIXME
"${docker_network.monitoring.id}",
] # networks = [
# docker_network.monitoring.id,
# ]
restart = "unless-stopped" restart = "unless-stopped"
destroy_grace_seconds = 10 destroy_grace_seconds = 10
must_run = true must_run = true
} }

View File

@ -1,6 +1,6 @@
resource "docker_container" "prometheus" { resource "docker_container" "prometheus" {
name = "prometheus" name = "prometheus"
image = "${docker_image.prometheus.latest}" image = docker_image.prometheus.latest
# prometheus:prometheus # prometheus:prometheus
user = "985:983" user = "985:983"
@ -8,13 +8,13 @@ resource "docker_container" "prometheus" {
ports { ports {
internal = 9090 internal = 9090
external = 8811 external = 8811
ip = "${var.ips["eth0"]}" ip = var.ips["eth0"]
} }
ports { ports {
internal = 9090 internal = 9090
external = 8811 external = 8811
ip = "${var.ips["tun0"]}" ip = var.ips["tun0"]
} }
command = ["--config.file=/etc/prometheus/prometheus.yml"] command = ["--config.file=/etc/prometheus/prometheus.yml"]
@ -25,7 +25,7 @@ resource "docker_container" "prometheus" {
} }
upload { upload {
content = "${file("${path.module}/config/prometheus.yml")}" content = file("${path.module}/config/prometheus.yml")
file = "/etc/prometheus/prometheus.yml" file = "/etc/prometheus/prometheus.yml"
} }
@ -38,8 +38,8 @@ resource "docker_container" "prometheus" {
} }
networks = [ networks = [
"${data.docker_network.bridge.id}", data.docker_network.bridge.id,
"${docker_network.monitoring.id}", docker_network.monitoring.id,
] ]
restart = "unless-stopped" restart = "unless-stopped"
@ -50,3 +50,4 @@ resource "docker_container" "prometheus" {
data "docker_network" "bridge" { data "docker_network" "bridge" {
name = "bridge" name = "bridge"
} }

View File

@ -17,7 +17,7 @@ module "speedtest" {
}, },
] ]
resource { resource = {
memory = 256 memory = 256
memory_swap = 256 memory_swap = 256
} }
@ -26,3 +26,4 @@ module "speedtest" {
destroy_grace_seconds = 10 destroy_grace_seconds = 10
must_run = true must_run = true
} }

View File

@ -1,17 +1,17 @@
variable "gf-security-admin-password" { variable "gf-security-admin-password" {
type = "string" type = string
} }
variable "domain" { variable "domain" {
type = "string" type = string
} }
variable "transmission" { variable "transmission" {
type = "string" type = string
} }
variable "links-traefik" { variable "links-traefik" {
type = "string" type = string
} }
variable "alert-slack-username" { variable "alert-slack-username" {
@ -31,11 +31,13 @@ variable "basic_auth" {
} }
variable "traefik-labels" { variable "traefik-labels" {
type = "map" type = map(string)
} }
variable "ips" { variable "ips" {
type = "map" type = map(string)
}
variable "traefik-network-id" {
} }
variable "traefik-network-id" {}

4
monitoring/versions.tf Normal file
View File

@ -0,0 +1,4 @@
terraform {
required_version = ">= 0.12"
}

View File

@ -1,18 +1,20 @@
module "nextcloud-db" { module "nextcloud-db" {
source = "modules/postgres" source = "./modules/postgres"
name = "nextcloud" name = "nextcloud"
password = "${data.pass_password.nextcloud-db-password.password}" password = data.pass_password.nextcloud-db-password.password
} }
module "nextcloud-container" { module "nextcloud-container" {
source = "modules/container" source = "./modules/container"
name = "nextcloud" name = "nextcloud"
image = "nextcloud:stable-apache" image = "nextcloud:stable-apache"
volumes = [{ volumes = [
container_path = "/var/www/html" {
host_path = "/mnt/xwing/data/nextcloud" container_path = "/var/www/html"
}] host_path = "/mnt/xwing/data/nextcloud"
},
]
env = [ env = [
"POSTGRES_DB=nextcloud", "POSTGRES_DB=nextcloud",
@ -24,12 +26,12 @@ module "nextcloud-container" {
"REDIS_HOST=nextcloud-redis", "REDIS_HOST=nextcloud-redis",
] ]
resource { resource = {
memory = 1024 memory = 1024
memory_swap = 1024 memory_swap = 1024
} }
web { web = {
expose = true expose = true
port = 80 port = 80
host = "c.${var.root-domain}" host = "c.${var.root-domain}"
@ -55,7 +57,7 @@ resource "docker_network" "nextcloud" {
module "nextcloud-redis" { module "nextcloud-redis" {
name = "nextcloud-redis" name = "nextcloud-redis"
source = "modules/container" source = "./modules/container"
image = "redis:alpine" image = "redis:alpine"
keep_image = true keep_image = true
@ -66,12 +68,13 @@ module "nextcloud-redis" {
] ]
# ThisSucks # ThisSucks
web { web = {
expose = "false" expose = "false"
} }
resource { resource = {
memory = 256 memory = 256
memory_swap = 256 memory_swap = 256
} }
} }

View File

@ -1,12 +1,13 @@
module "opml" { module "opml" {
name = "opml" name = "opml"
source = "../modules/container" source = "../modules/container"
image = "captn3m0/opml-gen:latest" image = "captn3m0/opml-gen:latest"
networks = ["${docker_network.opml.id}", "${var.traefik-network-id}"] # TODO FIXME
# networks = [docker_network.opml.id, var.traefik-network-id]
web { web = {
expose = true expose = true
host = "${var.domain}" host = var.domain
} }
env = [ env = [
@ -15,8 +16,9 @@ module "opml" {
"REDIS_URL=redis://opml-redis:6379/1", "REDIS_URL=redis://opml-redis:6379/1",
] ]
resource { resource = {
memory = 256 memory = 256
memory_swap = 256 memory_swap = 256
} }
} }

View File

@ -2,3 +2,4 @@ resource "docker_network" "opml" {
name = "opml" name = "opml"
driver = "bridge" driver = "bridge"
} }

View File

@ -1,17 +1,19 @@
module "redis" { module "redis" {
name = "opml-redis" name = "opml-redis"
source = "../modules/container" source = "../modules/container"
image = "redis:alpine" image = "redis:alpine"
networks = ["${docker_network.opml.id}"] # TODO FIXME
# networks = [docker_network.opml.id]
keep_image = true keep_image = true
# ThisSucks # ThisSucks
web { web = {
expose = "false" expose = "false"
} }
resource { resource = {
memory = 256 memory = 256
memory_swap = 256 memory_swap = 256
} }
} }

View File

@ -1,5 +1,12 @@
variable "domain" {} variable "domain" {
variable "client-id" {} }
variable "client-secret" {}
variable "client-id" {
}
variable "client-secret" {
}
variable "traefik-network-id" {
}
variable "traefik-network-id" {}

4
opml/versions.tf Normal file
View File

@ -0,0 +1,4 @@
terraform {
required_version = ">= 0.12"
}

View File

@ -19,23 +19,24 @@ provider "kubernetes" {
} }
provider "cloudflare" { provider "cloudflare" {
email = "bb8@captnemo.in" email = "bb8@captnemo.in"
token = "${data.pass_password.cloudflare_key.password}" api_key = data.pass_password.cloudflare_key.password
} }
provider "postgresql" { provider "postgresql" {
host = "postgres.vpn.bb8.fun" host = "postgres.vpn.bb8.fun"
port = 5432 port = 5432
username = "postgres" username = "postgres"
password = "${data.pass_password.postgres-root-password.password}" password = data.pass_password.postgres-root-password.password
sslmode = "disable" sslmode = "disable"
} }
provider "digitalocean" { provider "digitalocean" {
token = "${data.pass_password.digitalocean-token.password}" token = data.pass_password.digitalocean-token.password
} }
provider "pass" { provider "pass" {
store_dir = "/home/nemo/.password-store/Nebula/" store_dir = "/home/nemo/.password-store/Nebula/"
refresh_store = false refresh_store = false
} }

View File

@ -21,4 +21,3 @@
# memory = 2048 # memory = 2048
# } # }
# } # }

View File

@ -3,15 +3,15 @@ module "container" {
source = "../modules/container" source = "../modules/container"
image = "tomsquest/docker-radicale:amd64" image = "tomsquest/docker-radicale:amd64"
resource { resource = {
memory = 512 memory = 512
memory_swap = 512 memory_swap = 512
} }
web { web = {
expose = true expose = true
port = 5232 port = 5232
host = "${var.domain}" host = var.domain
} }
volumes = [ volumes = [
@ -97,3 +97,4 @@ EOT
}, },
] ]
} }

View File

@ -1,3 +1,4 @@
variable "domain" { variable "domain" {
type = "string" type = string
} }

4
radicale/versions.tf Normal file
View File

@ -0,0 +1,4 @@
terraform {
required_version = ">= 0.12"
}

View File

@ -1,15 +1,15 @@
module "rss-bridge" { module "rss-bridge" {
name = "rss-bridge" name = "rss-bridge"
source = "modules/container" source = "./modules/container"
image = "captn3m0/rss-bridge:develop" image = "captn3m0/rss-bridge:develop"
resource { resource = {
memory = 256 memory = 256
memory_swap = 256 memory_swap = 256
} }
web { web = {
expose = "true" expose = "true"
host = "rss-bridge.${var.root-domain}" host = "rss-bridge.${var.root-domain}"
} }
@ -23,8 +23,11 @@ module "rss-bridge" {
}, },
] ]
volumes = [{ volumes = [
container_path = "/app/whitelist.txt" {
host_path = "/mnt/xwing/config/rss-bridge/whitelist.txt" container_path = "/app/whitelist.txt"
}] host_path = "/mnt/xwing/config/rss-bridge/whitelist.txt"
},
]
} }

View File

@ -139,6 +139,7 @@ data "pass_password" "stringer-db-password" {
data "pass_password" "stringer-secret-token" { data "pass_password" "stringer-secret-token" {
path = "stringer-secret-token" path = "stringer-secret-token"
} }
data "pass_password" "wiki-db-password" { data "pass_password" "wiki-db-password" {
path = "wiki-db-password" path = "wiki-db-password"
} }
@ -150,20 +151,24 @@ data "pass_password" "klaxon-db-password" {
data "pass_password" "klaxon-secret-key" { data "pass_password" "klaxon-secret-key" {
path = "klaxon-secret-key" path = "klaxon-secret-key"
} }
data "pass_password" "klaxon-sendgrid-password" { data "pass_password" "klaxon-sendgrid-password" {
path = "klaxon-sendgrid-password" path = "klaxon-sendgrid-password"
} }
data "pass_password" "navidrome-lastfm-api-key" { data "pass_password" "navidrome-lastfm-api-key" {
path = "navidrome-lastfm-api-key" path = "navidrome-lastfm-api-key"
} }
data "pass_password" "navidrome-lastfm-secret" { data "pass_password" "navidrome-lastfm-secret" {
path = "navidrome-lastfm-secret" path = "navidrome-lastfm-secret"
} }
data "pass_password" "navidrome-spotify-id" { data "pass_password" "navidrome-spotify-id" {
path = "navidrome-spotify-id" path = "navidrome-spotify-id"
} }
data "pass_password" "navidrome-spotify-secret" { data "pass_password" "navidrome-spotify-secret" {
path = "navidrome-spotify-secret" path = "navidrome-spotify-secret"
} }

View File

@ -1 +0,0 @@

View File

@ -6,3 +6,4 @@ terraform {
profile = "nebula" profile = "nebula"
} }
} }

Some files were not shown because too many files have changed in this diff Show More