diff --git a/templates/nomad_jobs/reverse-proxy.hcl b/templates/nomad_jobs/reverse-proxy.hcl index e5c5a91..3bdbf80 100644 --- a/templates/nomad_jobs/reverse-proxy.hcl +++ b/templates/nomad_jobs/reverse-proxy.hcl @@ -4,327 +4,327 @@ job "reverse-proxy" { type = "service" constraint { - attribute = "${node.unique.name}" - value = "rpi1" + attribute = "${node.unique.name}" + value = "rpi1" } update { - max_parallel = 1 - health_check = "checks" - min_healthy_time = "10s" - healthy_deadline = "5m" - progress_deadline = "10m" - auto_revert = true - canary = 0 - stagger = "30s" + max_parallel = 1 + health_check = "checks" + min_healthy_time = "10s" + healthy_deadline = "5m" + progress_deadline = "10m" + auto_revert = true + canary = 0 + stagger = "30s" } group "reverse-proxy-group" { - restart { - attempts = 0 - delay = "30s" - } - - network { - port "authelia-port" { - static = {{ authelia_port }} - to = 9091 - } - port "whoami" { - to = 80 - } - port "dashboard" { - static = 8080 - to = 8080 - } - port "web" { - static = 80 - to = 80 - } - port "websecure" { - static = 443 - to = 443 - } - port "externalwebsecure" { - static = 4430 - to = 4430 - } - } - - task "authelia" { - - env { - TZ = "America/New_York" - PUID = "${meta.PUID}" - PGID = "${meta.PGID}" + restart { + attempts = 0 + delay = "30s" } - driver = "docker" - config { - image = "authelia/authelia" - hostname = "authelia" - ports = ["authelia-port"] - volumes = [ - "${meta.nfsStorageRoot}/pi-cluster/authelia:/config" - ] - args = [ - "--config", - "/local/authelia/config.yaml" - ] - } // docker config - - template { - destination = "local/authelia/config.yaml" - env = false - change_mode = "noop" - perms = "644" - data = <<-EOH - --- - ## The theme to display: light, dark, grey, auto. - theme: auto - - jwt_secret: {{ authelia_jwt_secret}} - default_redirection_url: https://authelia.{{ homelab_domain_name}} - - server: - host: 0.0.0.0 - port: 9091 - path: "" - read_buffer_size: 4096 - write_buffer_size: 4096 - enable_pprof: false - enable_expvars: false - disable_healthcheck: false - - log: - level: info - format: text - # file_path: "/config/log.txt" - keep_stdout: false - - totp: - issuer: authelia.com - - authentication_backend: - disable_reset_password: false - file: - path: /config/users.yml - password: - algorithm: argon2id - iterations: 1 - salt_length: 16 - parallelism: 8 - memory: 64 - - access_control: - default_policy: deny - networks: - - name: internal - networks: - - 10.0.0.0/16 - #- 172.16.0.0/12 - #- 192.168.0.0/18 - rules: - # Rules applied to everyone - - domain: "*.{{ homelab_domain_name }}" - policy: two_factor - networks: - - internal - - session: - name: authelia_session - domain: {{ homelab_domain_name }} - same_site: lax - secret: {{ authelia_session_secret }} - expiration: 1h - inactivity: 15m - remember_me_duration: 1w - - regulation: - max_retries: 5 - find_time: 10m - ban_time: 15m - - storage: - encryption_key: {{ authelia_sqlite_encryption_key}} - local: - path: /config/db.sqlite3 - - notifier: - smtp: - username: {{ email_smtp_account }} - password: {{ authelia_smtp_password }} - host: {{ email_smtp_host }} - port: {{ email_smtp_port }} - sender: "Authelia <{{ my_email_address }}>" - subject: "[Authelia] {title}" - startup_check_address: {{ my_email_address }} - - EOH + network { + port "authelia-port" { + static = {{ authelia_port }} + to = 9091 + } + port "whoami" { + to = 80 + } + port "dashboard" { + static = 8080 + to = 8080 + } + port "web" { + static = 80 + to = 80 + } + port "websecure" { + static = 443 + to = 443 + } + port "externalwebsecure" { + static = 4430 + to = 4430 + } } - service { - port = "authelia-port" - name = "${NOMAD_TASK_NAME}" - tags = [ - "traefik.enable=true", - "traefik.http.routers.${NOMAD_TASK_NAME}.rule=Host(`authelia.{{ homelab_domain_name }}`)", - "traefik.http.routers.${NOMAD_TASK_NAME}.entryPoints=web,websecure", - "traefik.http.routers.${NOMAD_TASK_NAME}.service=${NOMAD_TASK_NAME}", - "traefik.http.routers.${NOMAD_TASK_NAME}.tls=true", - "traefik.http.routers.${NOMAD_TASK_NAME}.tls.certresolver=cloudflare", - "traefik.http.middlewares.authelia-headers.headers.customResponseHeaders.Cache-Control=no-store", - "traefik.http.middlewares.authelia-headers.headers.customResponseHeaders.Pragma=no-cache", - "traefik.http.routers.authelia.middlewares=authelia-headers" - ] + task "authelia" { - check { - type = "tcp" - port = "authelia-port" - interval = "30s" - timeout = "4s" - } + env { + TZ = "America/New_York" + PUID = "${meta.PUID}" + PGID = "${meta.PGID}" + } - check_restart { - limit = 0 - grace = "1m" - ignore_warnings = true - } - } // service + driver = "docker" + config { + image = "authelia/authelia" + hostname = "authelia" + ports = ["authelia-port"] + volumes = [ + "${meta.nfsStorageRoot}/pi-cluster/authelia:/config" + ] + args = [ + "--config", + "/local/authelia/config.yaml" + ] + } // docker config - resources { - cpu = 200 # MHz - memory = 110 # MB - } + template { + destination = "local/authelia/config.yaml" + env = false + change_mode = "noop" + perms = "644" + data = <<-EOH + --- + ## The theme to display: light, dark, grey, auto. + theme: auto - } // task authelia + jwt_secret: {{ authelia_jwt_secret}} + default_redirection_url: https://authelia.{{ homelab_domain_name}} - task "whoami" { - driver = "docker" - config { - image = "containous/whoami:latest" - hostname = "${NOMAD_TASK_NAME}" - ports = ["whoami"] + server: + host: 0.0.0.0 + port: 9091 + path: "" + read_buffer_size: 4096 + write_buffer_size: 4096 + enable_pprof: false + enable_expvars: false + disable_healthcheck: false - } // /docker config + log: + level: info + format: text + # file_path: "/config/log.txt" + keep_stdout: false - service { - port = "whoami" - name = "${NOMAD_TASK_NAME}" - tags = [ - "traefik.enable=true", - "traefik.http.routers.${NOMAD_TASK_NAME}.rule=Host(`${NOMAD_TASK_NAME}.{{ homelab_domain_name }}`)", - "traefik.http.routers.${NOMAD_TASK_NAME}.entryPoints=web,websecure", - "traefik.http.routers.${NOMAD_TASK_NAME}.service=${NOMAD_TASK_NAME}", - "traefik.http.routers.${NOMAD_TASK_NAME}.tls=true", - "traefik.http.routers.${NOMAD_TASK_NAME}.tls.certresolver=cloudflare", - "traefik.http.routers.${NOMAD_TASK_NAME}.middlewares=authelia@file" - ] - check { - type = "http" - path = "/" - interval = "90s" - timeout = "15s" - } - check_restart { - limit = 2 - grace = "1m" - ignore_warnings = true - } - } - resources { - cpu = 25 # MHz - memory = 10 # MB - } + totp: + issuer: authelia.com - } // /task whoami + authentication_backend: + disable_reset_password: false + file: + path: /config/users.yml + password: + algorithm: argon2id + iterations: 1 + salt_length: 16 + parallelism: 8 + memory: 64 - task "traefik" { + access_control: + default_policy: deny + networks: + - name: internal + networks: + - 10.0.0.0/8 + #- 172.16.0.0/12 + #- 192.168.0.0/18 + rules: + # Rules applied to everyone + - domain: "*.{{ homelab_domain_name }}" + policy: two_factor + networks: + - internal - env { - PUID = "${meta.PUID}" - PGID = "${meta.PGID}" - TZ = "America/New_York" - CF_API_EMAIL = "{{ my_email_address }}" - CF_DNS_API_TOKEN = "{{ traefik_cf_api_token }}" - } + session: + name: authelia_session + domain: {{ homelab_domain_name }} + same_site: lax + secret: {{ authelia_session_secret }} + expiration: 1h + inactivity: 15m + remember_me_duration: 1w - driver = "docker" - config { - image = "traefik:{{ traefik_version }}" - hostname = "traefik" - ports = ["dashboard", "web", "websecure", "externalwebsecure"] - volumes = ["${meta.nfsStorageRoot}/pi-cluster/traefik/acme:/acme"] - args = [ - "--global.sendAnonymousUsage=false", - "--global.checkNewVersion=false", - "--entryPoints.web.address=:80", - "--entryPoints.websecure.address=:443", - "--entryPoints.externalwebsecure.address=:4430", - "--entrypoints.web.http.redirections.entryPoint.to=websecure", - "--entrypoints.web.http.redirections.entryPoint.scheme=https", - "--entrypoints.web.http.redirections.entryPoint.permanent=true", - "--providers.file.filename=/local/traefik/siteconfigs.toml", - "--providers.file.watch=true", - "--providers.consulcatalog=true", - "--providers.consulcatalog.endpoint.address=http://consul.service.consul:8500", - "--providers.consulcatalog.prefix=traefik", - "--providers.consulcatalog.exposedbydefault=false", - "--metrics=true", - "--metrics.influxdb=true", - "--metrics.influxdb.address=influxdb.service.consul:{{ influxdb_port }}", - "--metrics.influxdb.protocol=http", - "--metrics.influxdb.pushinterval=10s", - "--metrics.influxdb.database=homelab", - "--metrics.influxdb.retentionpolicy=2day", - "--metrics.influxdb.addentrypointslabels=true", - "--metrics.influxdb.addserviceslabels=true", - "--accesslog=true", - "--log=true", - "--log.level=ERROR", - "--api=true", - "--api.dashboard=true", - "--api.insecure=true", - "--certificatesresolvers.cloudflare.acme.email={{ my_email_address }}", - "--certificatesresolvers.cloudflare.acme.storage=/acme/acme-${node.unique.name}.json", - "--certificatesresolvers.cloudflare.acme.dnschallenge=true", - "--certificatesresolvers.cloudflare.acme.dnschallenge.provider=cloudflare", - "--certificatesresolvers.cloudflare.acme.dnschallenge.delaybeforecheck=10", - "--certificatesresolvers.cloudflare.acme.dnschallenge.resolvers=1.1.1.1:53,8.8.8.8:53" - ] - } // docker config + regulation: + max_retries: 5 + find_time: 10m + ban_time: 15m - template { - destination = "local/traefik/httpasswd" - env = false - change_mode = "noop" - data = <<-EOH + storage: + encryption_key: {{ authelia_sqlite_encryption_key}} + local: + path: /config/db.sqlite3 + + notifier: + smtp: + username: {{ email_smtp_account }} + password: {{ authelia_smtp_password }} + host: {{ email_smtp_host }} + port: {{ email_smtp_port }} + sender: "Authelia <{{ my_email_address }}>" + subject: "[Authelia] {title}" + startup_check_address: {{ my_email_address }} + + EOH + } + + service { + port = "authelia-port" + name = "${NOMAD_TASK_NAME}" + tags = [ + "traefik.enable=true", + "traefik.http.routers.${NOMAD_TASK_NAME}.rule=Host(`authelia.{{ homelab_domain_name }}`)", + "traefik.http.routers.${NOMAD_TASK_NAME}.entryPoints=web,websecure", + "traefik.http.routers.${NOMAD_TASK_NAME}.service=${NOMAD_TASK_NAME}", + "traefik.http.routers.${NOMAD_TASK_NAME}.tls=true", + "traefik.http.routers.${NOMAD_TASK_NAME}.tls.certresolver=cloudflare", + "traefik.http.middlewares.authelia-headers.headers.customResponseHeaders.Cache-Control=no-store", + "traefik.http.middlewares.authelia-headers.headers.customResponseHeaders.Pragma=no-cache", + "traefik.http.routers.authelia.middlewares=authelia-headers" + ] + + check { + type = "tcp" + port = "authelia-port" + interval = "30s" + timeout = "4s" + } + + check_restart { + limit = 0 + grace = "1m" + ignore_warnings = true + } + } // service + + resources { + cpu = 200 # MHz + memory = 110 # MB + } + + } // task authelia + + task "whoami" { + driver = "docker" + config { + image = "containous/whoami:latest" + hostname = "${NOMAD_TASK_NAME}" + ports = ["whoami"] + + } // /docker config + + service { + port = "whoami" + name = "${NOMAD_TASK_NAME}" + tags = [ + "traefik.enable=true", + "traefik.http.routers.${NOMAD_TASK_NAME}.rule=Host(`${NOMAD_TASK_NAME}.{{ homelab_domain_name }}`)", + "traefik.http.routers.${NOMAD_TASK_NAME}.entryPoints=web,websecure", + "traefik.http.routers.${NOMAD_TASK_NAME}.service=${NOMAD_TASK_NAME}", + "traefik.http.routers.${NOMAD_TASK_NAME}.tls=true", + "traefik.http.routers.${NOMAD_TASK_NAME}.tls.certresolver=cloudflare", + "traefik.http.routers.${NOMAD_TASK_NAME}.middlewares=authelia@file" + ] + check { + type = "http" + path = "/" + interval = "90s" + timeout = "15s" + } + check_restart { + limit = 2 + grace = "1m" + ignore_warnings = true + } + } + resources { + cpu = 25 # MHz + memory = 10 # MB + } + + } // /task whoami + + task "traefik" { + + env { + PUID = "${meta.PUID}" + PGID = "${meta.PGID}" + TZ = "America/New_York" + CF_API_EMAIL = "{{ my_email_address }}" + CF_DNS_API_TOKEN = "{{ traefik_cf_api_token }}" + } + + driver = "docker" + config { + image = "traefik:{{ traefik_version }}" + hostname = "traefik" + ports = ["dashboard", "web", "websecure","externalwebsecure"] + volumes = [ "${meta.nfsStorageRoot}/pi-cluster/traefik/acme:/acme" ] + args = [ + "--global.sendAnonymousUsage=false", + "--global.checkNewVersion=false", + "--entryPoints.web.address=:80", + "--entryPoints.websecure.address=:443", + "--entryPoints.externalwebsecure.address=:4430", + "--entrypoints.web.http.redirections.entryPoint.to=websecure", + "--entrypoints.web.http.redirections.entryPoint.scheme=https", + "--entrypoints.web.http.redirections.entryPoint.permanent=true", + "--providers.file.filename=/local/traefik/siteconfigs.toml", + "--providers.file.watch=true", + "--providers.consulcatalog=true", + "--providers.consulcatalog.endpoint.address=http://consul.service.consul:8500", + "--providers.consulcatalog.prefix=traefik", + "--providers.consulcatalog.exposedbydefault=false", + "--metrics=true", + "--metrics.influxdb=true", + "--metrics.influxdb.address=influxdb.service.consul:{{ influxdb_port }}", + "--metrics.influxdb.protocol=http", + "--metrics.influxdb.pushinterval=10s", + "--metrics.influxdb.database=homelab", + "--metrics.influxdb.retentionpolicy=2day", + "--metrics.influxdb.addentrypointslabels=true", + "--metrics.influxdb.addserviceslabels=true", + "--accesslog=true", + "--log=true", + "--log.level=ERROR", + "--api=true", + "--api.dashboard=true", + "--api.insecure=true", + "--certificatesresolvers.cloudflare.acme.email={{ my_email_address }}", + "--certificatesresolvers.cloudflare.acme.storage=/acme/acme-${node.unique.name}.json", + "--certificatesresolvers.cloudflare.acme.dnschallenge=true", + "--certificatesresolvers.cloudflare.acme.dnschallenge.provider=cloudflare", + "--certificatesresolvers.cloudflare.acme.dnschallenge.delaybeforecheck=10", + "--certificatesresolvers.cloudflare.acme.dnschallenge.resolvers=1.1.1.1:53,8.8.8.8:53" + ] + } // docker config + + template { + destination = "local/traefik/httpasswd" + env = false + change_mode = "noop" + data = <<-EOH {{ my_username }}:{{ traefik_http_pass_me }} family:{{ traefik_http_pass_family }} EOH - } + } - template { - destination = "local/traefik/httpasswdFamily" - env = false - change_mode = "noop" - data = <<-EOH + template { + destination = "local/traefik/httpasswdFamily" + env = false + change_mode = "noop" + data = <<-EOH {{ my_username }}:{{ traefik_http_pass_me }} family:{{ traefik_http_pass_family }} EOH - } + } - template { - destination = "local/traefik/siteconfigs.toml" - env = false - change_mode = "noop" - data = <<-EOH + template { + destination = "local/traefik/siteconfigs.toml" + env = false + change_mode = "noop" + data = <<-EOH [http] [http.middlewares] [http.middlewares.compress.compress] [http.middlewares.localIPOnly.ipWhiteList] - sourceRange = ["10.0.0.0/16"] + sourceRange = ["10.0.0.0/8"] [http.middlewares.redirectScheme.redirectScheme] scheme = "https" @@ -362,107 +362,108 @@ job "reverse-proxy" { passHostHeader = true [[http.services.consul.loadBalancer.servers]] url = "http://consul.service.consul:8500" + EOH - } - - service { - port = "dashboard" - name = "${NOMAD_TASK_NAME}" - tags = [ - "traefik.enable=true", - "traefik.http.routers.${NOMAD_TASK_NAME}.rule=Host(`${NOMAD_TASK_NAME}.{{ homelab_domain_name }}`)", - "traefik.http.routers.${NOMAD_TASK_NAME}.entryPoints=web,websecure", - "traefik.http.routers.${NOMAD_TASK_NAME}.service=${NOMAD_TASK_NAME}", - "traefik.http.routers.${NOMAD_TASK_NAME}.tls=true", - "traefik.http.routers.${NOMAD_TASK_NAME}.tls.certresolver=cloudflare", - "traefik.http.routers.${NOMAD_TASK_NAME}.middlewares=authelia@file,redirectScheme@file" - ] - - check { - type = "tcp" - port = "dashboard" - interval = "30s" - timeout = "4s" } - check_restart { - limit = 0 - grace = "1m" - ignore_warnings = true - } - } // service + service { + port = "dashboard" + name = "${NOMAD_TASK_NAME}" + tags = [ + "traefik.enable=true", + "traefik.http.routers.${NOMAD_TASK_NAME}.rule=Host(`${NOMAD_TASK_NAME}.{{ homelab_domain_name }}`)", + "traefik.http.routers.${NOMAD_TASK_NAME}.entryPoints=web,websecure", + "traefik.http.routers.${NOMAD_TASK_NAME}.service=${NOMAD_TASK_NAME}", + "traefik.http.routers.${NOMAD_TASK_NAME}.tls=true", + "traefik.http.routers.${NOMAD_TASK_NAME}.tls.certresolver=cloudflare", + "traefik.http.routers.${NOMAD_TASK_NAME}.middlewares=authelia@file,redirectScheme@file" + ] - resources { - //cpu = 40 # MHz - memory = 64 # MB - } // resources + check { + type = "tcp" + port = "dashboard" + interval = "30s" + timeout = "4s" + } - } // task traefik + check_restart { + limit = 0 + grace = "1m" + ignore_warnings = true + } + } // service - // task "promtail-traefik" { + resources { + //cpu = 40 # MHz + memory = 64 # MB + } // resources - // driver = "docker" - // config { - // image = "grafana/promtail" - // hostname = "promtail-traefik" - // volumes = [ - // "/mnt/pi-cluster/logs:/traefik" - // ] - // args = [ - // "-config.file", - // "/local/promtail-config.yaml", - // "-print-config-stderr", - // ] - // } // docker config + } // task traefik - // template { - // destination = "local/promtail-config.yaml" - // env = false - // data = <<-EOH - // server: - // http_listen_port: 9080 - // grpc_listen_port: 0 + // task "promtail-traefik" { - // positions: - // filename: /alloc/positions.yaml + // driver = "docker" + // config { + // image = "grafana/promtail" + // hostname = "promtail-traefik" + // volumes = [ + // "/mnt/pi-cluster/logs:/traefik" + // ] + // args = [ + // "-config.file", + // "/local/promtail-config.yaml", + // "-print-config-stderr", + // ] + // } // docker config - // {% raw -%} - // clients: - // - url: http://{{ range service "loki" }}{{ .Address }}:{{ .Port }}{{ end }}/loki/api/v1/push - // {% endraw %} + // template { + // destination = "local/promtail-config.yaml" + // env = false + // data = <<-EOH + // server: + // http_listen_port: 9080 + // grpc_listen_port: 0 - // scrape_configs: - // - job_name: traefik - // static_configs: - // - targets: - // - localhost - // labels: - // job: traefik_access - // {% raw %}host: {{ env "node.unique.name" }}{% endraw +%} - // __path__: "/alloc/logs/traefik.std*.0" - // pipeline_stages: - // - regex: - // expression: '^(?P[\w\.]+) - (?P[^ ]*) \[(?P.*)\] "(?P[^ ]*) (?P[^ ]*) (?P[^ ]*)" (?P[\d]+) (?P[\d]+) "(?P[^"]*)" "(?P[^"]*)" (?P[^ ]+) "(?P[^ ]+)" "(?P[^ ]+)" (?P[^ ]+)ms$' - // - labels: - // method: - // status: - // router: - // response_time_ms: + // positions: + // filename: /alloc/positions.yaml - // EOH - // } // template + // {% raw -%} + // clients: + // - url: http://{{ range service "loki" }}{{ .Address }}:{{ .Port }}{{ end }}/loki/api/v1/push + // {% endraw %} - // lifecycle { - // hook = "poststart" - // sidecar = true - // } + // scrape_configs: + // - job_name: traefik + // static_configs: + // - targets: + // - localhost + // labels: + // job: traefik_access + // {% raw %}host: {{ env "node.unique.name" }}{% endraw +%} + // __path__: "/alloc/logs/traefik.std*.0" + // pipeline_stages: + // - regex: + // expression: '^(?P[\w\.]+) - (?P[^ ]*) \[(?P.*)\] "(?P[^ ]*) (?P[^ ]*) (?P[^ ]*)" (?P[\d]+) (?P[\d]+) "(?P[^"]*)" "(?P[^"]*)" (?P[^ ]+) "(?P[^ ]+)" "(?P[^ ]+)" (?P[^ ]+)ms$' + // - labels: + // method: + // status: + // router: + // response_time_ms: - // resources { - // cpu = 30 # MHz - // memory = 30 # MB - // } // resources + // EOH + // } // template - // } // promtail sidecar task + // lifecycle { + // hook = "poststart" + // sidecar = true + // } + + // resources { + // cpu = 30 # MHz + // memory = 30 # MB + // } // resources + + // } // promtail sidecar task } // reverse-proxy-group }