parent
8d7875d174
commit
137eb3469f
|
@ -3,6 +3,7 @@
|
|||
.terraform
|
||||
*.tfstate
|
||||
*.tfstate.backup
|
||||
*.terraform.lock.hcl
|
||||
*.out
|
||||
*.backup
|
||||
secrets
|
||||
|
|
|
@ -1 +1 @@
|
|||
0.11.13
|
||||
1.0.9
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
# Hacking on the thing
|
||||
|
||||
Generate certs as per:
|
||||
|
||||
https://gist.github.com/captn3m0/2c2e723b2dcd5cdaad733aad12be59a2
|
||||
|
||||
Copy ca.pem, server-cert.pem, server-key.pem to /etc/docker/certs.
|
||||
|
||||
Make sure server-key.pem is 0400 in permissions.
|
||||
|
||||
Run `systemctl edit docker`
|
||||
|
||||
````
|
||||
/etc/systemd/system/docker.service.d/override.conf
|
||||
[Service]
|
||||
ExecStart=
|
||||
ExecStart=/usr/bin/dockerd --tlsverify --tlscacert=/etc/docker/certs/ca.pem --tlscert=/etc/docker/certs/server-cert.pem --tlskey=/etc/docker/certs/server-key.pem -H=0.0.0.0:2376 -H unix:///var/run/docker.sock
|
||||
````
|
|
@ -4,18 +4,18 @@
|
|||
*/
|
||||
|
||||
resource "cloudflare_record" "home" {
|
||||
domain = "${var.domain}"
|
||||
name = "in"
|
||||
value = "${var.ips["eth0"]}"
|
||||
type = "A"
|
||||
zone_id = var.zone_id
|
||||
name = "in"
|
||||
value = var.ips["eth0"]
|
||||
type = "A"
|
||||
}
|
||||
|
||||
resource "cloudflare_record" "home-wildcard" {
|
||||
domain = "${var.domain}"
|
||||
name = "*.in"
|
||||
value = "${cloudflare_record.home.hostname}"
|
||||
type = "CNAME"
|
||||
ttl = 3600
|
||||
zone_id = var.zone_id
|
||||
name = "*.in"
|
||||
value = cloudflare_record.home.hostname
|
||||
type = "CNAME"
|
||||
ttl = 3600
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -23,42 +23,42 @@ resource "cloudflare_record" "home-wildcard" {
|
|||
* *.bb8.fun -> bb8.fun
|
||||
*/
|
||||
resource "cloudflare_record" "internet" {
|
||||
domain = "${var.domain}"
|
||||
name = "@"
|
||||
value = "${var.droplet_ip}"
|
||||
type = "A"
|
||||
zone_id = var.zone_id
|
||||
name = "@"
|
||||
value = var.droplet_ip
|
||||
type = "A"
|
||||
}
|
||||
|
||||
resource "cloudflare_record" "internet-wildcard" {
|
||||
domain = "${var.domain}"
|
||||
name = "*.${var.domain}"
|
||||
value = "${cloudflare_record.internet.hostname}"
|
||||
type = "CNAME"
|
||||
ttl = 3600
|
||||
zone_id = var.zone_id
|
||||
name = var.domain
|
||||
value = cloudflare_record.internet.hostname
|
||||
type = "CNAME"
|
||||
ttl = 3600
|
||||
}
|
||||
|
||||
resource "cloudflare_record" "dns" {
|
||||
domain = "${var.domain}"
|
||||
name = "dns"
|
||||
value = "${var.ips["static"]}"
|
||||
type = "A"
|
||||
zone_id = var.zone_id
|
||||
name = "dns"
|
||||
value = var.ips["static"]
|
||||
type = "A"
|
||||
}
|
||||
|
||||
resource "cloudflare_record" "doh" {
|
||||
domain = "${var.domain}"
|
||||
name = "doh"
|
||||
value = "${var.ips["static"]}"
|
||||
type = "A"
|
||||
zone_id = var.zone_id
|
||||
name = "doh"
|
||||
value = var.ips["static"]
|
||||
type = "A"
|
||||
}
|
||||
|
||||
// This ensures that _acme-challenge is not a CNAME
|
||||
// alongside the above wildcard CNAME entry.
|
||||
resource "cloudflare_record" "acme-no-cname-1" {
|
||||
domain = "${var.domain}"
|
||||
name = "_acme-challenge.${var.domain}"
|
||||
type = "A"
|
||||
value = "127.0.0.1"
|
||||
ttl = "300"
|
||||
zone_id = var.zone_id
|
||||
name = "_acme-challenge.${var.domain}"
|
||||
type = "A"
|
||||
value = "127.0.0.1"
|
||||
ttl = "300"
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -66,18 +66,18 @@ resource "cloudflare_record" "acme-no-cname-1" {
|
|||
* *.vpn.bb8.fun
|
||||
*/
|
||||
resource "cloudflare_record" "vpn" {
|
||||
domain = "${var.domain}"
|
||||
name = "vpn"
|
||||
value = "${var.ips["tun0"]}"
|
||||
type = "A"
|
||||
zone_id = var.zone_id
|
||||
name = "vpn"
|
||||
value = var.ips["tun0"]
|
||||
type = "A"
|
||||
}
|
||||
|
||||
resource "cloudflare_record" "vpn_wildcard" {
|
||||
domain = "${var.domain}"
|
||||
name = "*.vpn.${var.domain}"
|
||||
value = "${cloudflare_record.vpn.hostname}"
|
||||
type = "CNAME"
|
||||
ttl = 3600
|
||||
zone_id = var.zone_id
|
||||
name = "*.vpn.${var.domain}"
|
||||
value = cloudflare_record.vpn.hostname
|
||||
type = "CNAME"
|
||||
ttl = 3600
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -85,25 +85,25 @@ resource "cloudflare_record" "vpn_wildcard" {
|
|||
* *.vpn.bb8.fun
|
||||
*/
|
||||
resource "cloudflare_record" "dovpn" {
|
||||
domain = "${var.domain}"
|
||||
name = "dovpn"
|
||||
value = "${var.ips["dovpn"]}"
|
||||
type = "A"
|
||||
zone_id = var.zone_id
|
||||
name = "dovpn"
|
||||
value = var.ips["dovpn"]
|
||||
type = "A"
|
||||
}
|
||||
|
||||
resource "cloudflare_record" "dovpn_wildcard" {
|
||||
domain = "${var.domain}"
|
||||
name = "*.dovpn.${var.domain}"
|
||||
value = "${cloudflare_record.dovpn.hostname}"
|
||||
type = "CNAME"
|
||||
ttl = 3600
|
||||
zone_id = var.zone_id
|
||||
name = "*.dovpn.${var.domain}"
|
||||
value = cloudflare_record.dovpn.hostname
|
||||
type = "CNAME"
|
||||
ttl = 3600
|
||||
}
|
||||
|
||||
resource "cloudflare_record" "etcd" {
|
||||
domain = "${var.domain}"
|
||||
name = "etcd"
|
||||
value = "${var.ips["dovpn"]}"
|
||||
type = "A"
|
||||
zone_id = var.zone_id
|
||||
name = "etcd"
|
||||
value = var.ips["dovpn"]
|
||||
type = "A"
|
||||
}
|
||||
|
||||
########################
|
||||
|
@ -111,21 +111,21 @@ resource "cloudflare_record" "etcd" {
|
|||
########################
|
||||
|
||||
resource "cloudflare_record" "mailgun-spf" {
|
||||
domain = "${var.domain}"
|
||||
name = "l"
|
||||
value = "v=spf1 include:mailgun.org ~all"
|
||||
type = "TXT"
|
||||
zone_id = var.zone_id
|
||||
name = "l"
|
||||
value = "v=spf1 include:mailgun.org ~all"
|
||||
type = "TXT"
|
||||
}
|
||||
|
||||
resource "cloudflare_record" "mailgun-dkim" {
|
||||
domain = "${var.domain}"
|
||||
name = "k1._domainkey.l"
|
||||
value = "k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCnbP+IQkuPkgmUhpqCKzIdDSZ0HazaMp+cdBH++LBed8oY8/jmV8BhxMp5JwyePzRTxneT8ASsRtcp7CQ3z4nMC7aFX0kH6Bnu2v+u2JWudxs8x0I02OrPbSaQ5QVQdbAaCUCEfCQ06LJsn8aqPNrRIOWEMnxln+ebFJ0wKGscFQIDAQAB"
|
||||
type = "TXT"
|
||||
zone_id = var.zone_id
|
||||
name = "k1._domainkey.l"
|
||||
value = "k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCnbP+IQkuPkgmUhpqCKzIdDSZ0HazaMp+cdBH++LBed8oY8/jmV8BhxMp5JwyePzRTxneT8ASsRtcp7CQ3z4nMC7aFX0kH6Bnu2v+u2JWudxs8x0I02OrPbSaQ5QVQdbAaCUCEfCQ06LJsn8aqPNrRIOWEMnxln+ebFJ0wKGscFQIDAQAB"
|
||||
type = "TXT"
|
||||
}
|
||||
|
||||
resource "cloudflare_record" "mailgun-mxa" {
|
||||
domain = "${var.domain}"
|
||||
zone_id = var.zone_id
|
||||
name = "l"
|
||||
value = "mxa.mailgun.org"
|
||||
type = "MX"
|
||||
|
@ -133,7 +133,7 @@ resource "cloudflare_record" "mailgun-mxa" {
|
|||
}
|
||||
|
||||
resource "cloudflare_record" "mailgun-mxb" {
|
||||
domain = "${var.domain}"
|
||||
zone_id = var.zone_id
|
||||
name = "l"
|
||||
value = "mxb.mailgun.org"
|
||||
type = "MX"
|
||||
|
@ -141,9 +141,9 @@ resource "cloudflare_record" "mailgun-mxb" {
|
|||
}
|
||||
|
||||
resource "cloudflare_record" "k8s" {
|
||||
domain = "${var.domain}"
|
||||
name = "k8s"
|
||||
value = "10.8.0.1"
|
||||
type = "A"
|
||||
ttl = 3600
|
||||
zone_id = var.zone_id
|
||||
name = "k8s"
|
||||
value = "10.8.0.1"
|
||||
type = "A"
|
||||
ttl = 3600
|
||||
}
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
terraform {
|
||||
required_providers {
|
||||
cloudflare = {
|
||||
source = "cloudflare/cloudflare"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,10 @@
|
|||
variable "domain" {
|
||||
type = "string"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "ips" {
|
||||
type = "map"
|
||||
type = map
|
||||
}
|
||||
|
||||
variable "droplet_ip" {}
|
||||
variable "zone_id" {}
|
||||
|
|
8
data.tf
8
data.tf
|
@ -1,3 +1,11 @@
|
|||
data "docker_network" "bridge" {
|
||||
name = "bridge"
|
||||
}
|
||||
|
||||
data "cloudflare_zones" "bb8" {
|
||||
filter {
|
||||
name = "bb8"
|
||||
lookup_type = "exact"
|
||||
match = "bb8.fun"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,3 +8,4 @@ resource "docker_network" "postgres" {
|
|||
gateway = "172.20.0.9"
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
output "postgres-network-id" {
|
||||
value = "${docker_network.postgres.name}"
|
||||
value = docker_network.postgres.name
|
||||
}
|
||||
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
resource "docker_container" "postgres" {
|
||||
name = "postgres"
|
||||
image = "${docker_image.postgres.latest}"
|
||||
image = docker_image.postgres.latest
|
||||
|
||||
volumes {
|
||||
volume_name = "${docker_volume.postgres_volume.name}"
|
||||
volume_name = docker_volume.postgres_volume.name
|
||||
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
|
||||
ports {
|
||||
internal = 5432
|
||||
external = 5432
|
||||
ip = "${var.ips["eth0"]}"
|
||||
ip = var.ips["eth0"]
|
||||
}
|
||||
|
||||
// This is a not-so-great idea
|
||||
|
@ -20,7 +20,7 @@ resource "docker_container" "postgres" {
|
|||
ports {
|
||||
internal = 5432
|
||||
external = 5432
|
||||
ip = "${var.ips["tun0"]}"
|
||||
ip = var.ips["tun0"]
|
||||
}
|
||||
|
||||
memory = 256
|
||||
|
@ -32,12 +32,12 @@ resource "docker_container" "postgres" {
|
|||
"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" {
|
||||
name = "${data.docker_registry_image.postgres.name}"
|
||||
pull_triggers = ["${data.docker_registry_image.postgres.sha256_digest}"]
|
||||
name = data.docker_registry_image.postgres.name
|
||||
pull_triggers = [data.docker_registry_image.postgres.sha256_digest]
|
||||
}
|
||||
|
||||
data "docker_registry_image" "postgres" {
|
||||
|
@ -47,3 +47,4 @@ data "docker_registry_image" "postgres" {
|
|||
data "docker_network" "bridge" {
|
||||
name = "bridge"
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
terraform {
|
||||
required_providers {
|
||||
pass = {
|
||||
source = "camptocamp/pass"
|
||||
}
|
||||
digitalocean = {
|
||||
source = "digitalocean/digitalocean"
|
||||
}
|
||||
postgresql = {
|
||||
source = "cyrilgdn/postgresql"
|
||||
}
|
||||
cloudflare = {
|
||||
source = "cloudflare/cloudflare"
|
||||
}
|
||||
docker = {
|
||||
source = "kreuzwerker/docker"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,7 +4,9 @@ variable "postgres-version" {
|
|||
}
|
||||
|
||||
variable "ips" {
|
||||
type = "map"
|
||||
type = map(string)
|
||||
}
|
||||
|
||||
variable "postgres-root-password" {
|
||||
}
|
||||
|
||||
variable "postgres-root-password" {}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
resource "docker_volume" "postgres_volume" {
|
||||
name = "postgres_volume"
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
resource "digitalocean_droplet" "sydney" {
|
||||
image = ""
|
||||
image = "??"
|
||||
name = "sydney.captnemo.in"
|
||||
region = "blr1"
|
||||
size = "s-1vcpu-2gb"
|
||||
|
@ -18,5 +18,6 @@ resource "digitalocean_droplet" "sydney" {
|
|||
}
|
||||
|
||||
output "droplet_ipv4" {
|
||||
value = "${digitalocean_droplet.sydney.ipv4_address}"
|
||||
value = digitalocean_droplet.sydney.ipv4_address
|
||||
}
|
||||
|
||||
|
|
|
@ -1,38 +1,35 @@
|
|||
resource "digitalocean_firewall" "web" {
|
||||
name = "web-inbound"
|
||||
|
||||
inbound_rule = [
|
||||
{
|
||||
protocol = "tcp"
|
||||
port_range = "80"
|
||||
source_addresses = ["0.0.0.0/0", "::/0"]
|
||||
},
|
||||
{
|
||||
protocol = "tcp"
|
||||
port_range = "443"
|
||||
source_addresses = ["0.0.0.0/0", "::/0"]
|
||||
},
|
||||
]
|
||||
inbound_rule {
|
||||
protocol = "tcp"
|
||||
port_range = "80"
|
||||
source_addresses = ["0.0.0.0/0", "::/0"]
|
||||
}
|
||||
inbound_rule {
|
||||
protocol = "tcp"
|
||||
port_range = "443"
|
||||
source_addresses = ["0.0.0.0/0", "::/0"]
|
||||
}
|
||||
}
|
||||
|
||||
resource "digitalocean_firewall" "ssh" {
|
||||
name = "ssh-inbound"
|
||||
|
||||
inbound_rule = [
|
||||
{
|
||||
protocol = "tcp"
|
||||
port_range = "22"
|
||||
source_addresses = ["0.0.0.0/0", "::/0"]
|
||||
},
|
||||
{
|
||||
protocol = "tcp"
|
||||
port_range = "222"
|
||||
source_addresses = ["0.0.0.0/0", "::/0"]
|
||||
},
|
||||
{
|
||||
protocol = "tcp"
|
||||
port_range = "24"
|
||||
source_addresses = ["0.0.0.0/0", "::/0"]
|
||||
},
|
||||
]
|
||||
inbound_rule {
|
||||
protocol = "tcp"
|
||||
port_range = "22"
|
||||
source_addresses = ["0.0.0.0/0", "::/0"]
|
||||
}
|
||||
inbound_rule {
|
||||
protocol = "tcp"
|
||||
port_range = "222"
|
||||
source_addresses = ["0.0.0.0/0", "::/0"]
|
||||
}
|
||||
inbound_rule {
|
||||
protocol = "tcp"
|
||||
port_range = "24"
|
||||
source_addresses = ["0.0.0.0/0", "::/0"]
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
resource "digitalocean_floating_ip" "sydney" {
|
||||
droplet_id = "${digitalocean_droplet.sydney.id}"
|
||||
region = "${digitalocean_droplet.sydney.region}"
|
||||
droplet_id = digitalocean_droplet.sydney.id
|
||||
region = digitalocean_droplet.sydney.region
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
terraform {
|
||||
required_providers {
|
||||
pass = {
|
||||
source = "camptocamp/pass"
|
||||
}
|
||||
digitalocean = {
|
||||
source = "digitalocean/digitalocean"
|
||||
}
|
||||
postgresql = {
|
||||
source = "cyrilgdn/postgresql"
|
||||
}
|
||||
cloudflare = {
|
||||
source = "cloudflare/cloudflare"
|
||||
}
|
||||
docker = {
|
||||
source = "kreuzwerker/docker"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -38,33 +38,6 @@ checkNewVersion = false
|
|||
# Since I can't apply a authentication
|
||||
# on this yet
|
||||
|
||||
[backends.elibsrv]
|
||||
[backends.elibsrv.servers.default]
|
||||
url = "http://elibsrv.captnemo.in:90"
|
||||
|
||||
[backends.scan]
|
||||
[backends.scan.servers.default]
|
||||
url = "http://scan.in.bb8.fun:90"
|
||||
|
||||
[frontends]
|
||||
|
||||
[frontends.scan]
|
||||
backend = "scan"
|
||||
[frontends.scan.headers]
|
||||
SSLRedirect = true
|
||||
SSLTemporaryRedirect = true
|
||||
STSSeconds = 2592000
|
||||
FrameDeny = true
|
||||
ContentTypeNosniff = true
|
||||
BrowserXssFilter = true
|
||||
ReferrerPolicy = "no-referrer"
|
||||
[frontends.scan.headers.customresponseheaders]
|
||||
X-Powered-By = "Allomancy"
|
||||
Server = "BlackBox"
|
||||
X-Clacks-Overhead = "GNU Terry Pratchett"
|
||||
[frontends.scan.routes.domain]
|
||||
rule = "Host:scan.bb8.fun"
|
||||
|
||||
[web]
|
||||
address = ":1111"
|
||||
readOnly = true
|
||||
|
|
|
@ -9,3 +9,4 @@ data "docker_registry_image" "ubooquity" {
|
|||
data "docker_registry_image" "lychee" {
|
||||
name = "linuxserver/lychee:latest"
|
||||
}
|
||||
|
||||
|
|
|
@ -6,22 +6,15 @@ data "docker_registry_image" "gotviz" {
|
|||
# name = "${data.docker_registry_image.gotviz.name}"
|
||||
# pull_triggers = ["${data.docker_registry_image.gotviz.sha256_digest}"]
|
||||
# }
|
||||
|
||||
|
||||
# resource "docker_container" "gotviz" {
|
||||
# name = "gotviz"
|
||||
# image = "${docker_image.gotviz.latest}"
|
||||
|
||||
|
||||
# labels = "${merge(
|
||||
# local.traefik_common_labels, map(
|
||||
# "traefik.port", 8080,
|
||||
# "traefik.frontend.rule","Host:got-relationships.${var.domain}"
|
||||
# ))}"
|
||||
|
||||
|
||||
# restart = "unless-stopped"
|
||||
# destroy_grace_seconds = 60
|
||||
# must_run = true
|
||||
# }
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
resource "docker_image" "traefik17" {
|
||||
name = "${data.docker_registry_image.traefik.name}"
|
||||
pull_triggers = ["${data.docker_registry_image.traefik.sha256_digest}"]
|
||||
name = data.docker_registry_image.traefik.name
|
||||
pull_triggers = [data.docker_registry_image.traefik.sha256_digest]
|
||||
}
|
||||
|
||||
resource "docker_image" "ubooquity" {
|
||||
name = "${data.docker_registry_image.ubooquity.name}"
|
||||
pull_triggers = ["${data.docker_registry_image.ubooquity.sha256_digest}"]
|
||||
name = data.docker_registry_image.ubooquity.name
|
||||
pull_triggers = [data.docker_registry_image.ubooquity.sha256_digest]
|
||||
}
|
||||
|
||||
# resource "docker_image" "lychee" {
|
||||
|
|
|
@ -1,20 +1,17 @@
|
|||
locals {
|
||||
traefik_common_labels {
|
||||
traefik_common_labels = {
|
||||
"traefik.enable" = "true"
|
||||
|
||||
// HSTS
|
||||
"traefik.frontend.headers.SSLTemporaryRedirect" = "true"
|
||||
"traefik.frontend.headers.STSSeconds" = "2592000"
|
||||
"traefik.frontend.headers.STSIncludeSubdomains" = "false"
|
||||
|
||||
// X-Powered-By, Server headers
|
||||
"traefik.frontend.headers.customResponseHeaders" = "${var.xpoweredby}"
|
||||
|
||||
"traefik.frontend.headers.customResponseHeaders" = var.xpoweredby
|
||||
// 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.browserXSSFilter" = "true"
|
||||
|
||||
"traefik.docker.network" = "traefik"
|
||||
"traefik.docker.network" = "traefik"
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -28,4 +28,3 @@
|
|||
# ]
|
||||
# # links = ["${var.links-mariadb}"]
|
||||
# }
|
||||
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
|
|
@ -3,3 +3,4 @@ resource "docker_network" "traefik" {
|
|||
driver = "bridge"
|
||||
internal = true
|
||||
}
|
||||
|
||||
|
|
|
@ -3,13 +3,14 @@
|
|||
# }
|
||||
|
||||
output "names-traefik" {
|
||||
value = "${docker_container.traefik.name}"
|
||||
value = docker_container.traefik.name
|
||||
}
|
||||
|
||||
output "traefik-network-id" {
|
||||
value = "${docker_network.traefik.id}"
|
||||
value = docker_network.traefik.id
|
||||
}
|
||||
|
||||
output "auth-header" {
|
||||
value = "${var.basic_auth}"
|
||||
value = var.basic_auth
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
terraform {
|
||||
required_providers {
|
||||
pass = {
|
||||
source = "camptocamp/pass"
|
||||
}
|
||||
digitalocean = {
|
||||
source = "digitalocean/digitalocean"
|
||||
}
|
||||
postgresql = {
|
||||
source = "cyrilgdn/postgresql"
|
||||
}
|
||||
cloudflare = {
|
||||
source = "cloudflare/cloudflare"
|
||||
}
|
||||
docker = {
|
||||
source = "kreuzwerker/docker"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,70 +1,78 @@
|
|||
resource "docker_container" "traefik" {
|
||||
name = "traefik"
|
||||
image = "${docker_image.traefik17.latest}"
|
||||
image = docker_image.traefik17.latest
|
||||
|
||||
# Admin Backend
|
||||
ports {
|
||||
internal = 1111
|
||||
external = 1111
|
||||
ip = "${var.ips["eth0"]}"
|
||||
ip = var.ips["eth0"]
|
||||
}
|
||||
|
||||
ports {
|
||||
internal = 1111
|
||||
external = 1111
|
||||
ip = "${var.ips["tun0"]}"
|
||||
ip = var.ips["tun0"]
|
||||
}
|
||||
|
||||
# Local Web Server
|
||||
ports {
|
||||
internal = 80
|
||||
external = 80
|
||||
ip = "${var.ips["eth0"]}"
|
||||
ip = var.ips["eth0"]
|
||||
}
|
||||
|
||||
# Local Web Server (HTTPS)
|
||||
ports {
|
||||
internal = 443
|
||||
external = 443
|
||||
ip = "${var.ips["eth0"]}"
|
||||
ip = var.ips["eth0"]
|
||||
}
|
||||
|
||||
# Proxied via sydney.captnemo.in
|
||||
ports {
|
||||
internal = 443
|
||||
external = 443
|
||||
ip = "${var.ips["tun0"]}"
|
||||
ip = var.ips["tun0"]
|
||||
}
|
||||
|
||||
ports {
|
||||
internal = 80
|
||||
external = 80
|
||||
ip = "${var.ips["tun0"]}"
|
||||
ip = var.ips["tun0"]
|
||||
}
|
||||
|
||||
upload {
|
||||
content = "${file("${path.module}/conf/traefik.toml")}"
|
||||
content = file("${path.module}/conf/traefik.toml")
|
||||
file = "/etc/traefik/traefik.toml"
|
||||
}
|
||||
|
||||
upload {
|
||||
content = "${file("/home/nemo/projects/personal/certs/git.captnemo.in/fullchain.pem")}"
|
||||
file = "/etc/traefik/git.captnemo.in.crt"
|
||||
content = file(
|
||||
"/home/nemo/projects/personal/certs/git.captnemo.in/fullchain.pem",
|
||||
)
|
||||
file = "/etc/traefik/git.captnemo.in.crt"
|
||||
}
|
||||
|
||||
upload {
|
||||
content = "${file("/home/nemo/projects/personal/certs/git.captnemo.in/privkey.pem")}"
|
||||
file = "/etc/traefik/git.captnemo.in.key"
|
||||
content = file(
|
||||
"/home/nemo/projects/personal/certs/git.captnemo.in/privkey.pem",
|
||||
)
|
||||
file = "/etc/traefik/git.captnemo.in.key"
|
||||
}
|
||||
|
||||
upload {
|
||||
content = "${file("/home/nemo/projects/personal/certs/rss.captnemo.in/fullchain.pem")}"
|
||||
file = "/etc/traefik/rss.captnemo.in.crt"
|
||||
content = file(
|
||||
"/home/nemo/projects/personal/certs/rss.captnemo.in/fullchain.pem",
|
||||
)
|
||||
file = "/etc/traefik/rss.captnemo.in.crt"
|
||||
}
|
||||
|
||||
upload {
|
||||
content = "${file("/home/nemo/projects/personal/certs/rss.captnemo.in/privkey.pem")}"
|
||||
file = "/etc/traefik/rss.captnemo.in.key"
|
||||
content = file(
|
||||
"/home/nemo/projects/personal/certs/rss.captnemo.in/privkey.pem",
|
||||
)
|
||||
file = "/etc/traefik/rss.captnemo.in.key"
|
||||
}
|
||||
|
||||
volumes {
|
||||
|
@ -85,17 +93,16 @@ resource "docker_container" "traefik" {
|
|||
|
||||
// `bridge` is auto-connected for now
|
||||
// https://github.com/terraform-providers/terraform-provider-docker/issues/10
|
||||
networks = [
|
||||
"${docker_network.traefik.id}",
|
||||
"${data.docker_network.bridge.id}",
|
||||
]
|
||||
networks_advanced {
|
||||
name = "traefik"
|
||||
}
|
||||
|
||||
networks_advanced {
|
||||
name = "bridge"
|
||||
}
|
||||
|
||||
env = [
|
||||
"CLOUDFLARE_EMAIL=${var.cloudflare_email}",
|
||||
"CLOUDFLARE_API_KEY=${var.cloudflare_key}",
|
||||
]
|
||||
}
|
||||
|
||||
data "docker_network" "bridge" {
|
||||
name = "bridge"
|
||||
}
|
||||
|
|
|
@ -1,6 +1,13 @@
|
|||
locals {
|
||||
l = merge(local.traefik_common_labels, {
|
||||
"traefik.port" = 3000
|
||||
"traefik.frontend.rule" = "Host:${var.domain}"
|
||||
})
|
||||
}
|
||||
|
||||
resource "docker_container" "ubooquity" {
|
||||
name = "ubooquity"
|
||||
image = "${docker_image.ubooquity.latest}"
|
||||
image = docker_image.ubooquity.latest
|
||||
|
||||
restart = "unless-stopped"
|
||||
destroy_grace_seconds = 30
|
||||
|
@ -25,32 +32,37 @@ resource "docker_container" "ubooquity" {
|
|||
host_path = "/mnt/xwing/media/EBooks/Comics"
|
||||
container_path = "/comics"
|
||||
}
|
||||
|
||||
labels {
|
||||
"traefik.enable" = "true"
|
||||
|
||||
"traefik.admin.port" = 2203
|
||||
"traefik.admin.frontend.rule" = "Host:library.${var.domain}"
|
||||
|
||||
# I do not trust the Ubooquity authentication
|
||||
# it does some shady JS encryption
|
||||
"traefik.admin.frontend.auth.basic" = "${var.basic_auth}"
|
||||
|
||||
"traefik.read.port" = 2202
|
||||
"traefik.read.frontend.rule" = "Host:read.${var.domain},comics.${var.domain},books.${var.domain}"
|
||||
|
||||
"traefik.read.frontend.headers.SSLTemporaryRedirect" = "true"
|
||||
"traefik.read.frontend.headers.STSSeconds" = "2592000"
|
||||
"traefik.read.frontend.headers.STSIncludeSubdomains" = "false"
|
||||
"traefik.read.frontend.headers.contentTypeNosniff" = "true"
|
||||
"traefik.read.frontend.headers.browserXSSFilter" = "true"
|
||||
"traefik.read.frontend.headers.customResponseHeaders" = "${var.xpoweredby}"
|
||||
"traefik.frontend.headers.customFrameOptionsValue" = "${var.xfo_allow}"
|
||||
"traefik.docker.network" = "traefik"
|
||||
label = "traefik.enable"
|
||||
value = "true"
|
||||
}
|
||||
labels {
|
||||
label = "traefik.admin.port"
|
||||
value = 2203
|
||||
}
|
||||
labels {
|
||||
label = "traefik.admin.frontend.rule"
|
||||
value = "Host:library.${var.domain}"
|
||||
}
|
||||
labels {
|
||||
label = "traefik.admin.frontend.auth.basic"
|
||||
value = var.basic_auth
|
||||
}
|
||||
labels {
|
||||
label = "traefik.read.port"
|
||||
value = 2202
|
||||
}
|
||||
labels {
|
||||
label = "traefik.read.frontend.rule"
|
||||
value = "Host:read.${var.domain},comics.${var.domain},books.${var.domain}"
|
||||
}
|
||||
labels {
|
||||
label = "traefik.docker.network"
|
||||
value = "traefik"
|
||||
}
|
||||
|
||||
upload {
|
||||
content = "${file("${path.module}/conf/ubooquity.json")}"
|
||||
content = file("${path.module}/conf/ubooquity.json")
|
||||
file = "/config/preferences.json"
|
||||
}
|
||||
|
||||
|
@ -61,3 +73,4 @@ resource "docker_container" "ubooquity" {
|
|||
"MAXMEM=800",
|
||||
]
|
||||
}
|
||||
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
variable "web_username" {
|
||||
type = "string"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "web_password" {
|
||||
type = "string"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "cloudflare_key" {
|
||||
type = "string"
|
||||
type = string
|
||||
description = "cloudflare API Key"
|
||||
}
|
||||
|
||||
variable "cloudflare_email" {
|
||||
type = "string"
|
||||
type = string
|
||||
description = "cloudflare email address"
|
||||
}
|
||||
|
||||
|
@ -39,15 +39,15 @@ variable "refpolicy" {
|
|||
}
|
||||
|
||||
variable "wiki_session_secret" {
|
||||
type = "string"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "domain" {
|
||||
type = "string"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "ips" {
|
||||
type = "map"
|
||||
type = map(string)
|
||||
}
|
||||
|
||||
# variable "links-mariadb" {}
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
module "echo-server" {
|
||||
source = "modules/container"
|
||||
source = "./modules/container"
|
||||
name = "echo-server"
|
||||
image = "jmalloc/echo-server:latest"
|
||||
|
||||
web {
|
||||
web = {
|
||||
expose = "true"
|
||||
port = 8080
|
||||
host = "debug.${var.root-domain},debug.in.${var.root-domain}"
|
||||
}
|
||||
}
|
||||
|
||||
|
|
16
elibsrv.tf
16
elibsrv.tf
|
@ -1,14 +1,14 @@
|
|||
module "elibsrv" {
|
||||
name = "elibsrv"
|
||||
name = "./elibsrv"
|
||||
source = "./modules/container"
|
||||
image = "captn3m0/elibsrv"
|
||||
|
||||
resource {
|
||||
resource = {
|
||||
memory = 512
|
||||
memory_swap = 512
|
||||
}
|
||||
|
||||
web {
|
||||
web = {
|
||||
expose = true
|
||||
host = "ebooks.${var.root-domain}"
|
||||
auth = true
|
||||
|
@ -40,12 +40,6 @@ module "elibsrv" {
|
|||
"elibsrv_thumbheight=320",
|
||||
"elibsrv_title=Scarif Media Archives",
|
||||
]
|
||||
networks_advanced = [
|
||||
{
|
||||
name = "traefik"
|
||||
},
|
||||
{
|
||||
name = "bridge"
|
||||
},
|
||||
]
|
||||
networks = ["bridge"]
|
||||
}
|
||||
|
||||
|
|
|
@ -4,21 +4,23 @@ module "firefox-sync" {
|
|||
image = "mozilla/syncserver:latest"
|
||||
|
||||
// Default is port 80
|
||||
web {
|
||||
web = {
|
||||
expose = true
|
||||
port = "5000"
|
||||
host = "firesync.${var.root-domain}"
|
||||
}
|
||||
|
||||
resource {
|
||||
resource = {
|
||||
memory = "400"
|
||||
memory_swap = "400"
|
||||
}
|
||||
|
||||
volumes = [{
|
||||
host_path = "/mnt/xwing/data/firefox-sync"
|
||||
container_path = "/data"
|
||||
}]
|
||||
volumes = [
|
||||
{
|
||||
host_path = "/mnt/xwing/data/firefox-sync"
|
||||
container_path = "/data"
|
||||
},
|
||||
]
|
||||
|
||||
env = [
|
||||
"SYNCSERVER_PUBLIC_URL=https://firesync.${var.root-domain}",
|
||||
|
@ -29,12 +31,6 @@ module "firefox-sync" {
|
|||
"PORT=5000",
|
||||
]
|
||||
|
||||
networks_advanced = [
|
||||
{
|
||||
name = "traefik"
|
||||
},
|
||||
{
|
||||
name = "bridge"
|
||||
},
|
||||
]
|
||||
networks = ["bridge"]
|
||||
}
|
||||
|
||||
|
|
|
@ -137,7 +137,7 @@ ACTIVE_CODE_LIVE_MINUTES = 15
|
|||
RESET_PASSWD_CODE_LIVE_MINUTES = 30
|
||||
REGISTER_EMAIL_CONFIRM = true
|
||||
ENABLE_NOTIFY_MAIL = true
|
||||
DISABLE_REGISTRATION = false
|
||||
DISABLE_REGISTRATION = true
|
||||
; ; Enable captcha validation for registration
|
||||
ENABLE_CAPTCHA = true
|
||||
REQUIRE_EXTERNAL_REGISTRATION_CAPTCHA = true
|
||||
|
@ -146,7 +146,7 @@ CAPTCHA_TYPE = image
|
|||
REQUIRE_SIGNIN_VIEW = false
|
||||
; ; Default value for KeepEmailPrivate
|
||||
; ; New user will get the value of this setting copied into their profile
|
||||
DEFAULT_KEEP_EMAIL_PRIVATE = false
|
||||
DEFAULT_KEEP_EMAIL_PRIVATE = true
|
||||
; ; Default value for AllowCreateOrganization
|
||||
; ; New user will have rights set to create organizations depending on this setting
|
||||
DEFAULT_ALLOW_CREATE_ORGANIZATION = true
|
||||
|
@ -249,7 +249,7 @@ SHOW_FOOTER_TEMPLATE_LOAD_TIME = false
|
|||
|
||||
[openid]
|
||||
ENABLE_OPENID_SIGNIN = true
|
||||
ENABLE_OPENID_SIGNUP = true
|
||||
ENABLE_OPENID_SIGNUP = false
|
||||
|
||||
[metrics]
|
||||
; Enables metrics endpoint. True or false; default is false.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# https://github.com/go-gitea/gitea/releases
|
||||
data "docker_registry_image" "gitea" {
|
||||
name = "gitea/gitea:1.14"
|
||||
name = "gitea/gitea:1.15"
|
||||
}
|
||||
|
||||
data "docker_registry_image" "redis" {
|
||||
|
@ -8,14 +8,15 @@ data "docker_registry_image" "redis" {
|
|||
}
|
||||
|
||||
data "template_file" "gitea-config-file" {
|
||||
template = "${file("${path.module}/conf/conf.ini.tpl")}"
|
||||
template = file("${path.module}/conf/conf.ini.tpl")
|
||||
|
||||
vars {
|
||||
secret_key = "${var.secret-key}"
|
||||
internal_token = "${var.internal-token}"
|
||||
smtp_password = "${var.smtp-password}"
|
||||
lfs-jwt-secret = "${var.lfs-jwt-secret}"
|
||||
mysql-password = "${var.mysql-password}"
|
||||
oauth2-jwt-secret = "${var.oauth2-jwt-secret}"
|
||||
vars = {
|
||||
secret_key = var.secret-key
|
||||
internal_token = var.internal-token
|
||||
smtp_password = var.smtp-password
|
||||
lfs-jwt-secret = var.lfs-jwt-secret
|
||||
mysql-password = var.mysql-password
|
||||
oauth2-jwt-secret = var.oauth2-jwt-secret
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,71 +1,74 @@
|
|||
locals {
|
||||
l = merge(var.traefik-labels, {
|
||||
"traefik.port" = 3000
|
||||
"traefik.frontend.rule" = "Host:${var.domain}"
|
||||
})
|
||||
}
|
||||
|
||||
resource "docker_container" "gitea" {
|
||||
name = "gitea"
|
||||
image = "${docker_image.gitea.latest}"
|
||||
image = docker_image.gitea.latest
|
||||
|
||||
labels = "${merge(
|
||||
var.traefik-labels, map(
|
||||
"traefik.port", 3000,
|
||||
"traefik.frontend.rule", "Host:${var.domain}"
|
||||
))}"
|
||||
dynamic "labels" {
|
||||
for_each = local.l
|
||||
content {
|
||||
label = labels.key
|
||||
value = labels.value
|
||||
}
|
||||
}
|
||||
|
||||
volumes {
|
||||
volume_name = "${docker_volume.gitea_volume.name}"
|
||||
volume_name = docker_volume.gitea_volume.name
|
||||
container_path = "/data"
|
||||
host_path = "${docker_volume.gitea_volume.mountpoint}"
|
||||
host_path = docker_volume.gitea_volume.mountpoint
|
||||
}
|
||||
|
||||
# Logos
|
||||
# TODO: Add svg
|
||||
|
||||
upload {
|
||||
content = "${file("${path.module}/conf/public/img/gitea-lg.png")}"
|
||||
file = "/data/gitea/public/img/gitea-lg.png"
|
||||
content_base64 = filebase64("${path.module}/conf/public/img/gitea-lg.png")
|
||||
file = "/data/gitea/public/img/gitea-lg.png"
|
||||
}
|
||||
upload {
|
||||
content = "${file("${path.module}/conf/public/img/gitea-sm.png")}"
|
||||
file = "/data/gitea/public/img/gitea-sm.png"
|
||||
content_base64 = filebase64("${path.module}/conf/public/img/gitea-sm.png")
|
||||
file = "/data/gitea/public/img/gitea-sm.png"
|
||||
}
|
||||
upload {
|
||||
content = "${file("${path.module}/conf/public/img/gitea-sm.png")}"
|
||||
file = "/data/gitea/public/img/favicon.png"
|
||||
executable = false
|
||||
content_base64 = filebase64("${path.module}/conf/public/img/gitea-sm.png")
|
||||
file = "/data/gitea/public/img/favicon.png"
|
||||
executable = false
|
||||
}
|
||||
upload {
|
||||
content = "${file("${path.module}/../docker/conf/humans.txt")}"
|
||||
content = file("${path.module}/../docker/conf/humans.txt")
|
||||
file = "/data/gitea/public/humans.txt"
|
||||
}
|
||||
upload {
|
||||
content = "${file("${path.module}/conf/public/robots.txt")}"
|
||||
content = file("${path.module}/conf/public/robots.txt")
|
||||
file = "/data/gitea/public/robots.txt"
|
||||
}
|
||||
|
||||
# Extra Links in header
|
||||
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"
|
||||
}
|
||||
|
||||
# This is the main configuration file
|
||||
upload {
|
||||
content = "${data.template_file.gitea-config-file.rendered}"
|
||||
content = data.template_file.gitea-config-file.rendered
|
||||
file = "/data/gitea/conf/app.ini"
|
||||
}
|
||||
|
||||
memory = 800
|
||||
restart = "always"
|
||||
destroy_grace_seconds = 10
|
||||
must_run = true
|
||||
networks = ["${docker_network.gitea.id}", "${var.traefik-network-id}"]
|
||||
|
||||
# This doesn't work.
|
||||
# See https://github.com/terraform-providers/terraform-provider-docker/issues/48
|
||||
# lifecycle {
|
||||
# ignore_changes = [
|
||||
# "upload.2151376053.content",
|
||||
# "upload.2151376053.executable",
|
||||
# "upload.2151376053.file",
|
||||
# ]
|
||||
# }
|
||||
networks = ["gitea", "traefik"]
|
||||
}
|
||||
|
||||
resource "docker_image" "gitea" {
|
||||
name = "${data.docker_registry_image.gitea.name}"
|
||||
pull_triggers = ["${data.docker_registry_image.gitea.sha256_digest}"]
|
||||
name = data.docker_registry_image.gitea.name
|
||||
pull_triggers = [data.docker_registry_image.gitea.sha256_digest]
|
||||
}
|
||||
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
|
|
@ -2,3 +2,4 @@ resource "docker_network" "gitea" {
|
|||
name = "gitea"
|
||||
driver = "bridge"
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
terraform {
|
||||
required_providers {
|
||||
pass = {
|
||||
source = "camptocamp/pass"
|
||||
}
|
||||
digitalocean = {
|
||||
source = "digitalocean/digitalocean"
|
||||
}
|
||||
postgresql = {
|
||||
source = "cyrilgdn/postgresql"
|
||||
}
|
||||
cloudflare = {
|
||||
source = "cloudflare/cloudflare"
|
||||
}
|
||||
docker = {
|
||||
source = "kreuzwerker/docker"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
resource "docker_container" "redis" {
|
||||
name = "gitea-redis"
|
||||
image = "${docker_image.redis.latest}"
|
||||
image = docker_image.redis.latest
|
||||
|
||||
volumes {
|
||||
host_path = "/mnt/xwing/cache/gitea"
|
||||
|
@ -12,11 +12,12 @@ resource "docker_container" "redis" {
|
|||
destroy_grace_seconds = 10
|
||||
must_run = true
|
||||
|
||||
networks = ["${docker_network.gitea.id}"]
|
||||
networks = [docker_network.gitea.id]
|
||||
}
|
||||
|
||||
resource "docker_image" "redis" {
|
||||
name = "${data.docker_registry_image.redis.name}"
|
||||
pull_triggers = ["${data.docker_registry_image.redis.sha256_digest}"]
|
||||
name = data.docker_registry_image.redis.name
|
||||
pull_triggers = [data.docker_registry_image.redis.sha256_digest]
|
||||
keep_locally = true
|
||||
}
|
||||
|
||||
|
|
|
@ -1,18 +1,32 @@
|
|||
variable "traefik-labels" {
|
||||
type = "map"
|
||||
type = map(string)
|
||||
}
|
||||
|
||||
variable "domain" {}
|
||||
variable "domain" {
|
||||
}
|
||||
|
||||
variable "ips" {
|
||||
type = "map"
|
||||
type = map(string)
|
||||
}
|
||||
|
||||
variable "secret-key" {}
|
||||
variable "internal-token" {}
|
||||
variable "smtp-password" {}
|
||||
variable "lfs-jwt-secret" {}
|
||||
variable "oauth2-jwt-secret" {}
|
||||
variable "mysql-password" {}
|
||||
variable "secret-key" {
|
||||
}
|
||||
|
||||
variable "internal-token" {
|
||||
}
|
||||
|
||||
variable "smtp-password" {
|
||||
}
|
||||
|
||||
variable "lfs-jwt-secret" {
|
||||
}
|
||||
|
||||
variable "oauth2-jwt-secret" {
|
||||
}
|
||||
|
||||
variable "mysql-password" {
|
||||
}
|
||||
|
||||
variable "traefik-network-id" {
|
||||
}
|
||||
|
||||
variable "traefik-network-id" {}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
resource "docker_volume" "gitea_volume" {
|
||||
name = "gitea_volume"
|
||||
}
|
||||
|
||||
|
|
|
@ -10,4 +10,3 @@
|
|||
# },
|
||||
# ]
|
||||
# }
|
||||
|
||||
|
|
17
kaarana.tf
17
kaarana.tf
|
@ -1,15 +1,15 @@
|
|||
# kaarana related stuff
|
||||
|
||||
module "kaarana" {
|
||||
source = "./kaarana"
|
||||
# module "kaarana" {
|
||||
# source = "./kaarana"
|
||||
|
||||
root_db_password = "${data.pass_password.kaarana-root-db-password.password}"
|
||||
db_password = "${data.pass_password.kaarana-db-password.password}"
|
||||
# root_db_password = data.pass_password.kaarana-root-db-password.password
|
||||
# db_password = data.pass_password.kaarana-db-password.password
|
||||
|
||||
providers = {
|
||||