Initial Commit
This commit is contained in:
parent
825f466a25
commit
2a613ec57b
13 changed files with 433 additions and 0 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
/debug/*
|
||||||
|
/.idea
|
19
default.conf
Normal file
19
default.conf
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
resolver 127.0.0.11 ipv6=off valid=1s;
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
listen [::]:80;
|
||||||
|
#listen 443 ssl;
|
||||||
|
#listen [::]:443 ssl;
|
||||||
|
server_name localhost;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
index index.html index.htm;
|
||||||
|
}
|
||||||
|
|
||||||
|
error_page 500 502 503 504 /50x.html;
|
||||||
|
location = /50x.html {
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
}
|
||||||
|
}
|
19
default_page.tf
Normal file
19
default_page.tf
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
locals {
|
||||||
|
default_page = "<h1>Hello, World!</h1>"
|
||||||
|
}
|
||||||
|
resource "docker_config" "default_page" {
|
||||||
|
name = "${var.service_name}.index.html-${substr(sha1(local.default_page), 0, 4)}"
|
||||||
|
data = base64encode(local.default_page)
|
||||||
|
}
|
||||||
|
resource "local_file" "default_page" {
|
||||||
|
content = base64decode(docker_config.default_page.data)
|
||||||
|
filename = "${path.root}/.debug/nginx/index.html"
|
||||||
|
}
|
||||||
|
resource "docker_config" "default_conf" {
|
||||||
|
name = "${var.service_name}.default.conf-${substr(sha1(file("${path.module}/default.conf")), 0, 4)}"
|
||||||
|
data = base64encode(file("${path.module}/default.conf"))
|
||||||
|
}
|
||||||
|
resource "local_file" "default_conf" {
|
||||||
|
content = base64decode(docker_config.default_conf.data)
|
||||||
|
filename = "${path.root}/.debug/nginx/default.conf"
|
||||||
|
}
|
22
inputs.tf
Normal file
22
inputs.tf
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
variable "service_name" {
|
||||||
|
type = string
|
||||||
|
default = "nginx"
|
||||||
|
}
|
||||||
|
variable "configs" {
|
||||||
|
type = list(object({
|
||||||
|
file = string
|
||||||
|
id = string
|
||||||
|
name = string
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
variable "networks" {
|
||||||
|
type = list(object({
|
||||||
|
name = string
|
||||||
|
id = string
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
variable "replicas" {
|
||||||
|
type = number
|
||||||
|
default = 2
|
||||||
|
description = "The number of instances to deploy"
|
||||||
|
}
|
11
nginx-site-available/basic-auth.tf
Normal file
11
nginx-site-available/basic-auth.tf
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
# Auth file
|
||||||
|
resource "docker_config" "auth" {
|
||||||
|
count = var.basic_auth != null ? 1 : 0
|
||||||
|
name = join(".", [var.config_prefix, "auth", var.hostname, random_id.config_instance.id])
|
||||||
|
data = base64encode(local.auth)
|
||||||
|
}
|
||||||
|
resource "local_file" "auth" {
|
||||||
|
count = var.basic_auth != null ? 1 : 0
|
||||||
|
content = local.auth
|
||||||
|
filename = "${path.root}/.debug/nginx/${local.filenames.auth}"
|
||||||
|
}
|
20
nginx-site-available/cert.tf
Normal file
20
nginx-site-available/cert.tf
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
resource "docker_config" "certificate" {
|
||||||
|
count = var.certificate != null ? 1 : 0
|
||||||
|
name = join(".", [var.config_prefix, "crt", var.hostname, random_id.config_instance.id])
|
||||||
|
data = base64encode("${var.certificate.certificate_pem}${var.certificate.issuer_pem}")
|
||||||
|
}
|
||||||
|
resource "local_file" "certificate" {
|
||||||
|
count = var.certificate != null ? 1 : 0
|
||||||
|
content = local.cert_public
|
||||||
|
filename = "${path.root}/.debug/nginx/${local.filenames.certificate}"
|
||||||
|
}
|
||||||
|
resource "docker_config" "certificate_key" {
|
||||||
|
count = var.certificate != null ? 1 : 0
|
||||||
|
name = join(".", [var.config_prefix, "key", var.hostname, random_id.config_instance.id])
|
||||||
|
data = base64encode(local.cert_private)
|
||||||
|
}
|
||||||
|
resource "local_file" "certificate_key" {
|
||||||
|
count = var.certificate != null ? 1 : 0
|
||||||
|
content = var.certificate.private_key_pem
|
||||||
|
filename = "${path.root}/.debug/nginx/${local.filenames.certificate_key}"
|
||||||
|
}
|
70
nginx-site-available/config.tf
Normal file
70
nginx-site-available/config.tf
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
locals {
|
||||||
|
auth = var.basic_auth != null ? "${var.basic_auth.username}:${var.basic_auth.password}" : null
|
||||||
|
config = templatefile("${path.module}/nginx_template.conf", {
|
||||||
|
hostname = var.hostname
|
||||||
|
service_name = var.service_name
|
||||||
|
http_port = var.http_port
|
||||||
|
https_port = var.https_port
|
||||||
|
upstream_host = var.upstream_host
|
||||||
|
enable_ssl = var.certificate != null
|
||||||
|
certificate = var.certificate
|
||||||
|
basic_auth = var.basic_auth
|
||||||
|
auth_file = var.basic_auth != null ? "${var.hostname}-auth.conf" : ""
|
||||||
|
allow_non_ssl = var.allow_non_ssl
|
||||||
|
redirect_non_ssl = var.redirect_non_ssl
|
||||||
|
timeout_seconds = var.timeout_seconds
|
||||||
|
host_override = var.host_override
|
||||||
|
extra_upstreams = var.extra_upstreams
|
||||||
|
extra_locations = var.extra_locations
|
||||||
|
})
|
||||||
|
cert_public = "${var.certificate.issuer_pem}${var.certificate.certificate_pem}"
|
||||||
|
cert_private = var.certificate.private_key_pem
|
||||||
|
filenames = {
|
||||||
|
nginx = "${var.hostname}.conf"
|
||||||
|
auth = "${var.hostname}.auth"
|
||||||
|
certificate_key = "${var.hostname}.key"
|
||||||
|
certificate = "${var.hostname}.crt"
|
||||||
|
}
|
||||||
|
files = [for f in [
|
||||||
|
{
|
||||||
|
file = local.filenames.nginx
|
||||||
|
name = docker_config.nginx_site_available.name
|
||||||
|
id = docker_config.nginx_site_available.id
|
||||||
|
},
|
||||||
|
var.basic_auth != null ? {
|
||||||
|
file = local.filenames.auth
|
||||||
|
name = docker_config.auth[0].name
|
||||||
|
id = docker_config.auth[0].id
|
||||||
|
} : null,
|
||||||
|
var.certificate != null ? {
|
||||||
|
file = local.filenames.certificate
|
||||||
|
name = docker_config.certificate[0].name
|
||||||
|
id = docker_config.certificate[0].id
|
||||||
|
} : null,
|
||||||
|
var.certificate != null ? {
|
||||||
|
file = local.filenames.certificate_key
|
||||||
|
name = docker_config.certificate_key[0].name
|
||||||
|
id = docker_config.certificate_key[0].id
|
||||||
|
} : null
|
||||||
|
] : f if f != null]
|
||||||
|
}
|
||||||
|
|
||||||
|
# Nginx config
|
||||||
|
resource "random_id" "config_instance" {
|
||||||
|
byte_length = 4
|
||||||
|
keepers = {
|
||||||
|
config : local.config,
|
||||||
|
auth : local.auth,
|
||||||
|
cert_public : local.cert_public,
|
||||||
|
cert_private : local.cert_private,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resource "docker_config" "nginx_site_available" {
|
||||||
|
name = join(".", [var.config_prefix, "conf", var.hostname, random_id.config_instance.id])
|
||||||
|
data = base64encode(local.config)
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "local_file" "nginx_site_available" {
|
||||||
|
filename = "${path.root}/.debug/nginx/${local.filenames.nginx}"
|
||||||
|
content = local.config
|
||||||
|
}
|
67
nginx-site-available/inputs.tf
Normal file
67
nginx-site-available/inputs.tf
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
variable "hostname" {
|
||||||
|
type = string
|
||||||
|
description = "The hostname of the server"
|
||||||
|
}
|
||||||
|
variable "service_name" {
|
||||||
|
type = string
|
||||||
|
description = "The name of the service"
|
||||||
|
}
|
||||||
|
variable "upstream_host" {
|
||||||
|
type = string
|
||||||
|
description = "The host uri of the upstream server"
|
||||||
|
}
|
||||||
|
variable "certificate" {
|
||||||
|
type = object({
|
||||||
|
private_key_pem = string
|
||||||
|
certificate_pem = string
|
||||||
|
issuer_pem = string
|
||||||
|
})
|
||||||
|
default = null
|
||||||
|
}
|
||||||
|
variable "basic_auth" {
|
||||||
|
type = object({
|
||||||
|
username = string
|
||||||
|
password = string
|
||||||
|
})
|
||||||
|
default = null
|
||||||
|
}
|
||||||
|
variable "allow_non_ssl" {
|
||||||
|
type = bool
|
||||||
|
default = false
|
||||||
|
}
|
||||||
|
variable "redirect_non_ssl" {
|
||||||
|
type = bool
|
||||||
|
default = true
|
||||||
|
}
|
||||||
|
variable "timeout_seconds" {
|
||||||
|
type = number
|
||||||
|
default = 10
|
||||||
|
}
|
||||||
|
variable "http_port" {
|
||||||
|
type = number
|
||||||
|
default = 80
|
||||||
|
}
|
||||||
|
variable "https_port" {
|
||||||
|
type = number
|
||||||
|
default = 443
|
||||||
|
}
|
||||||
|
variable "host_override" {
|
||||||
|
type = string
|
||||||
|
default = null
|
||||||
|
}
|
||||||
|
variable "config_prefix" {
|
||||||
|
type = string
|
||||||
|
default = "nginx"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "extra_upstreams" {
|
||||||
|
type = list(object({
|
||||||
|
name = string
|
||||||
|
servers = list(string)
|
||||||
|
}))
|
||||||
|
default = []
|
||||||
|
}
|
||||||
|
variable "extra_locations" {
|
||||||
|
type = string
|
||||||
|
default = ""
|
||||||
|
}
|
83
nginx-site-available/nginx_template.conf
Normal file
83
nginx-site-available/nginx_template.conf
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
upstream ${service_name} {
|
||||||
|
least_conn;
|
||||||
|
server ${upstream_host};
|
||||||
|
}
|
||||||
|
%{for upstream in extra_upstreams~}
|
||||||
|
upstream ${upstream.name} {
|
||||||
|
least_conn;
|
||||||
|
%{for server in upstream.servers~}
|
||||||
|
server ${server};
|
||||||
|
%{endfor~}
|
||||||
|
}
|
||||||
|
%{endfor~}
|
||||||
|
|
||||||
|
%{if !allow_non_ssl~}
|
||||||
|
server {
|
||||||
|
# Redirect non-ssl to ssl
|
||||||
|
listen ${http_port};
|
||||||
|
listen [::]:${http_port};
|
||||||
|
server_name ${hostname};
|
||||||
|
return 301 https://$host$request_uri;
|
||||||
|
}
|
||||||
|
%{endif~}
|
||||||
|
|
||||||
|
server {
|
||||||
|
%{if allow_non_ssl~}
|
||||||
|
# Non-SSL Traffic is allowed
|
||||||
|
listen ${http_port~}
|
||||||
|
listen [::]:${http_port};
|
||||||
|
%{endif~}
|
||||||
|
# SSL Traffic is allowed
|
||||||
|
listen ${https_port} ssl;
|
||||||
|
listen [::]:${https_port} ssl;
|
||||||
|
server_name ${hostname};
|
||||||
|
access_log /var/log/nginx/${hostname}.access.log;
|
||||||
|
error_log /var/log/nginx/${hostname}.error.log;
|
||||||
|
|
||||||
|
%{if enable_ssl~}
|
||||||
|
ssl_certificate /etc/nginx/conf.d/${hostname}.crt;
|
||||||
|
ssl_certificate_key /etc/nginx/conf.d/${hostname}.key;
|
||||||
|
# ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
|
||||||
|
# ssl_ciphers HIGH:!aNULL:!MD5;
|
||||||
|
%{endif~}
|
||||||
|
|
||||||
|
client_max_body_size 0;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
%{if host_override != null~}
|
||||||
|
proxy_set_header Host ${host_override};
|
||||||
|
%{else~}
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
%{endif~}
|
||||||
|
|
||||||
|
# Server to send the request on to
|
||||||
|
proxy_pass http://${service_name};
|
||||||
|
|
||||||
|
# Standard headers setting origin data
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
|
||||||
|
%{if basic_auth != null~}
|
||||||
|
# Http Basic Auth
|
||||||
|
auth_basic "closed site";
|
||||||
|
auth_basic_user_file sites-enabled/${auth_file};
|
||||||
|
%{endif~}
|
||||||
|
|
||||||
|
# WebSocket support
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection "Upgrade";
|
||||||
|
proxy_cache_bypass $http_upgrade;
|
||||||
|
proxy_buffering off;
|
||||||
|
proxy_set_header Origin "";
|
||||||
|
|
||||||
|
# Proxy timeouts
|
||||||
|
proxy_read_timeout ${timeout_seconds};
|
||||||
|
proxy_connect_timeout ${timeout_seconds};
|
||||||
|
proxy_send_timeout ${timeout_seconds};
|
||||||
|
}
|
||||||
|
|
||||||
|
${extra_locations}
|
||||||
|
}
|
||||||
|
|
6
nginx-site-available/outputs.tf
Normal file
6
nginx-site-available/outputs.tf
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
output "files" {
|
||||||
|
value = local.files
|
||||||
|
}
|
||||||
|
output "hostname" {
|
||||||
|
value = var.hostname
|
||||||
|
}
|
22
nginx-site-available/terraform.tf
Normal file
22
nginx-site-available/terraform.tf
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
terraform {
|
||||||
|
required_providers {
|
||||||
|
docker = {
|
||||||
|
source = "kreuzwerker/docker"
|
||||||
|
version = "~>3.0"
|
||||||
|
}
|
||||||
|
random = {
|
||||||
|
source = "hashicorp/random"
|
||||||
|
version = "~>3.3"
|
||||||
|
}
|
||||||
|
local = {
|
||||||
|
source = "hashicorp/local"
|
||||||
|
version = "~>2.1"
|
||||||
|
}
|
||||||
|
scratch = {
|
||||||
|
source = "BrendanThompson/scratch"
|
||||||
|
version = "0.4.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
78
nginx.tf
Normal file
78
nginx.tf
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
data "docker_registry_image" "nginx" {
|
||||||
|
name = "nginx:latest"
|
||||||
|
}
|
||||||
|
resource "random_id" "iteration" {
|
||||||
|
keepers = {
|
||||||
|
configs = jsonencode(var.configs)
|
||||||
|
}
|
||||||
|
byte_length = 4
|
||||||
|
}
|
||||||
|
resource "docker_service" "nginx" {
|
||||||
|
name = var.service_name
|
||||||
|
mode {
|
||||||
|
replicated {
|
||||||
|
replicas = var.replicas
|
||||||
|
}
|
||||||
|
}
|
||||||
|
task_spec {
|
||||||
|
container_spec {
|
||||||
|
image = "${data.docker_registry_image.nginx.name}@${data.docker_registry_image.nginx.sha256_digest}"
|
||||||
|
configs {
|
||||||
|
config_id = docker_config.default_page.id
|
||||||
|
config_name = docker_config.default_page.name
|
||||||
|
file_name = "/usr/share/nginx/html/index.html"
|
||||||
|
}
|
||||||
|
configs {
|
||||||
|
config_id = docker_config.default_conf.id
|
||||||
|
config_name = docker_config.default_conf.name
|
||||||
|
file_name = "/etc/nginx/conf.d/default.conf"
|
||||||
|
}
|
||||||
|
dynamic "configs" {
|
||||||
|
for_each = var.configs
|
||||||
|
content {
|
||||||
|
config_id = configs.value.id
|
||||||
|
config_name = configs.value.name
|
||||||
|
file_name = "/etc/nginx/conf.d/${configs.value.file}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
# Healthcheck that checks that the nginx process is running
|
||||||
|
#healthcheck {
|
||||||
|
# test = ["CMD", "pgrep", "nginx"]
|
||||||
|
# interval = "10s"
|
||||||
|
# timeout = "5s"
|
||||||
|
# retries = 3
|
||||||
|
# start_period = "10s"
|
||||||
|
#}
|
||||||
|
healthcheck {
|
||||||
|
test = ["CMD", "true"]
|
||||||
|
}
|
||||||
|
labels {
|
||||||
|
label = "com.nginx.iteration-id"
|
||||||
|
value = random_id.iteration.hex
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dynamic "networks_advanced" {
|
||||||
|
for_each = var.networks
|
||||||
|
content {
|
||||||
|
name = networks_advanced.value.id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
endpoint_spec {
|
||||||
|
ports {
|
||||||
|
target_port = 80
|
||||||
|
publish_mode = "ingress"
|
||||||
|
published_port = 80
|
||||||
|
}
|
||||||
|
ports {
|
||||||
|
target_port = 443
|
||||||
|
publish_mode = "ingress"
|
||||||
|
published_port = 443
|
||||||
|
}
|
||||||
|
}
|
||||||
|
update_config {
|
||||||
|
parallelism = ceil(var.replicas / 3)
|
||||||
|
delay = "10s"
|
||||||
|
order = "start-first"
|
||||||
|
}
|
||||||
|
}
|
14
terraform.tf
Normal file
14
terraform.tf
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
terraform {
|
||||||
|
required_providers {
|
||||||
|
docker = {
|
||||||
|
source = "kreuzwerker/docker"
|
||||||
|
version = "~>3.0"
|
||||||
|
}
|
||||||
|
scratch = {
|
||||||
|
source = "BrendanThompson/scratch"
|
||||||
|
version = "0.4.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue