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