Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0a3d2d9b33 | |||
| d6ebabce8b | |||
| 5d0f008f6b | |||
| dcbf28a48d |
@@ -117,9 +117,9 @@ uv run ansible-playbook -i inventory.ini playbook.yml
|
||||
### 6.1 Refactoring Inline Configurations to Jinja2 Templates
|
||||
To improve maintainability and separate configuration data from playbook logic, inline file content blocks in `playbook.yml` were refactored into dedicated Jinja2 template files located in the `templates/` directory:
|
||||
|
||||
* **[templates/Caddyfile.j2](file:///Users/doctor/Git/ovh_gridscale_test_task/templates/Caddyfile.j2)**: Contains Caddy server block definitions and metrics setup.
|
||||
* **[templates/prometheus.yml.j2](file:///Users/doctor/Git/ovh_gridscale_test_task/templates/prometheus.yml.j2)**: Contains global scrape configuration and imports rule files via `rule_files: [/etc/prometheus/alert_rules.yml]`.
|
||||
* **[templates/alert_rules.yml.j2](file:///Users/doctor/Git/ovh_gridscale_test_task/templates/alert_rules.yml.j2)**: Defines Prometheus alert rules for monitoring Caddy service availability and error rates.
|
||||
* **[templates/Caddyfile.j2](templates/Caddyfile.j2)**: Contains Caddy server block definitions and metrics setup.
|
||||
* **[templates/prometheus.yml.j2](templates/prometheus.yml.j2)**: Contains global scrape configuration and imports rule files via `rule_files: [/etc/prometheus/alert_rules.yml]`.
|
||||
* **[templates/alert_rules.yml.j2](templates/alert_rules.yml.j2)**: Defines Prometheus alert rules for monitoring Caddy service availability and error rates.
|
||||
|
||||
The playbook tasks were updated to use `ansible.builtin.template` instead of `ansible.builtin.copy`.
|
||||
|
||||
@@ -154,7 +154,7 @@ resource "null_resource" "ansible_provisioner" {
|
||||
]
|
||||
|
||||
provisioner "local-exec" {
|
||||
command = "uv run ansible-playbook -i ${local_file.ansible_inventory.filename} playbook.yml"
|
||||
command = "sleep 60 &&uv run ansible-playbook -i ${local_file.ansible_inventory.filename} playbook.yml"
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -175,14 +175,14 @@ source .env
|
||||
```
|
||||
|
||||
### 7.2 Python Environment Initialization & Dependency Setup (`uv`)
|
||||
Initialize Python environment and install Ansible using `uv`:
|
||||
Initialize Python environment and install Ansible along with `passlib` and `bcrypt` (required for Jinja `password_hash` filter) using `uv`:
|
||||
|
||||
```bash
|
||||
# Initialize uv virtual environment and lockfile
|
||||
uv init --bare
|
||||
|
||||
# Add Ansible dependency
|
||||
uv add "ansible"
|
||||
# Add Ansible, passlib, and bcrypt dependencies (bcrypt<4.0.0 required for passlib compatibility)
|
||||
uv add ansible passlib "bcrypt<4.0.0"
|
||||
```
|
||||
|
||||
### 7.3 Infrastructure Provisioning & Automated Execution
|
||||
@@ -206,5 +206,135 @@ uv run ansible-playbook -i inventory.ini -l caddy playbook.yml
|
||||
uv run ansible-playbook -i inventory.ini -l monitoring playbook.yml
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. Additional Task: Nginx Integration and Custom Improvements
|
||||
|
||||
### 8.1 Nginx Infrastructure & Ansible Deployment
|
||||
Expanded the infrastructure to provision a dedicated Nginx web server node (`nginx01`) alongside Caddy and Monitoring nodes:
|
||||
* **Terraform Infrastructure**: Defined `gridscale_storage.storage_nginx` and `gridscale_server.server_nginx` attached to the internal private network (`gridscale_network.network_internal`) with port 80 allowed internally.
|
||||
* **Ansible Automation**: Added an `nginx` play in `playbook.yml` installing Nginx and deploying a custom `index.html.j2` page displaying host metadata.
|
||||
|
||||
### 8.2 HTTPS Reverse Proxying via `sslip.io` Dynamic Subdomains
|
||||
Configured Caddy as the central ingress gateway utilizing `sslip.io` dynamic DNS wildcard resolution to route traffic over HTTPS automatically:
|
||||
* `caddy.<ip>.sslip.io` $\rightarrow$ Caddy default static page
|
||||
* `nginx.<ip>.sslip.io` $\rightarrow$ Reverse proxies to private Nginx IP (`{{ private_ip_nginx }}:80`)
|
||||
* `monitoring.<ip>.sslip.io` $\rightarrow$ Reverse proxies to internal Prometheus IP (`{{ private_ip_monitoring }}:9090`)
|
||||
|
||||
### 8.3 Prometheus Subdomain Security via Basic Authentication & Health Checks
|
||||
Secured access to the Prometheus monitoring interface by embedding Caddy's `basic_auth` directive and active health checking directly into the monitoring subdomain block in `templates/Caddyfile.j2`:
|
||||
|
||||
```caddy
|
||||
monitoring.{{ ansible_default_ipv4.address | replace(".", "-") }}.sslip.io {
|
||||
reverse_proxy {{ private_ip_monitoring }}:9090 {
|
||||
health_uri /-/healthy
|
||||
health_interval 10s
|
||||
health_timeout 5s
|
||||
}
|
||||
basic_auth {
|
||||
{{ demo_user }} {{ demo_pass | password_hash('bcrypt') }}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 8.4 Python Dependencies & `bcrypt` Version Pinning
|
||||
Encountered and resolved a critical dependency issue during Ansible template rendering for `password_hash('bcrypt')`:
|
||||
* **Issue**: `passlib` (1.7.4) failed with `AttributeError: module 'bcrypt' has no attribute '__about__'` when paired with `bcrypt >= 4.0.0`, resulting in a `password cannot be longer than 72 bytes` exception.
|
||||
* **Fix**: Pinned `bcrypt` to `<4.0.0` (`bcrypt==3.2.2`) in `pyproject.toml` and installed via `uv`:
|
||||
```bash
|
||||
uv add ansible passlib "bcrypt<4.0.0"
|
||||
```
|
||||
|
||||
### 8.5 Direct Execution Output via Terraform `nonsensitive()`
|
||||
To display all endpoint URLs and auto-generated credentials immediately upon `terraform apply` completion without manual CLI commands:
|
||||
* Wrapped `random_password.demo_pass.result` using Terraform's `nonsensitive()` function in `outputs.tf`:
|
||||
|
||||
```hcl
|
||||
output "website_urls" {
|
||||
description = "Website URLs"
|
||||
value = [
|
||||
"Caddy: https://caddy.${replace(gridscale_ipv4.public_ipv4_caddy.ip, ".", "-")}.sslip.io",
|
||||
"Nginx behind Caddy: https://nginx.${replace(gridscale_ipv4.public_ipv4_caddy.ip, ".", "-")}.sslip.io",
|
||||
"Prometheus behind Caddy: https://monitoring.${replace(gridscale_ipv4.public_ipv4_caddy.ip, ".", "-")}.sslip.io",
|
||||
"Login for Monitoring: demo ${nonsensitive(random_password.demo_pass.result)}"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 8.6 Upstream Health Checks & Fault Tolerance in Caddy
|
||||
Configured active health checking inside Caddy's `reverse_proxy` directives in `templates/Caddyfile.j2` to ensure fault tolerance for upstream services:
|
||||
* **Nginx Health Probes**: Periodic `health_uri /` checks every 10 seconds (5s timeout).
|
||||
* **Prometheus Health Probes**: Periodic `health_uri /-/healthy` checks every 10 seconds (5s timeout).
|
||||
* If an upstream service or node becomes unresponsive, Caddy automatically marks the backend as unhealthy and prevents routing traffic to dead backends.
|
||||
|
||||
---
|
||||
|
||||
## 9. Summary: Service Execution & Access Guide
|
||||
|
||||
### 9.1 Quickstart Execution Steps
|
||||
|
||||
1. **Configure Environment Credentials**:
|
||||
Copy `.env.example` to `.env`, set your Gridscale API credentials, and export them:
|
||||
```bash
|
||||
cp .env.example .env
|
||||
# Edit .env with your credentials
|
||||
source .env
|
||||
```
|
||||
|
||||
2. **Initialize Python Environment & Dependencies**:
|
||||
Initialize `uv` environment and install Ansible, `passlib`, and `bcrypt`:
|
||||
```bash
|
||||
uv init --bare
|
||||
uv add ansible passlib "bcrypt<4.0.0"
|
||||
```
|
||||
|
||||
3. **Provision Infrastructure & Execute Playbooks**:
|
||||
Apply Terraform to provision all cloud resources, generate `inventory.ini`, and automatically trigger Ansible configuration management via `null_resource`:
|
||||
```bash
|
||||
terraform init
|
||||
terraform apply -auto-approve
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 9.2 Service Access & Endpoints Summary
|
||||
|
||||
Upon successful completion, Terraform outputs all HTTPS endpoints and Basic Authentication credentials:
|
||||
|
||||
| Service | Host / Subdomain Format | Target / Upstream | Access Details |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| **Caddy Ingress** | `https://caddy.<caddy-ip-with-dashes>.sslip.io` | Local Caddy static server | Public landing page |
|
||||
| **Nginx Web Server** | `https://nginx.<caddy-ip-with-dashes>.sslip.io` | `http://<nginx-ip-private>:80` | Reverse proxied Hello World page |
|
||||
| **Prometheus Monitoring** | `https://monitoring.<caddy-ip-with-dashes>.sslip.io` | `http://<monitoring-ip-private>:9090` with caddy `basic_auth` | **Username**: `demo`<br>**Password**: Auto-generated password from Terraform output |
|
||||
|
||||
*(Optional)* Display all endpoint URLs and active credentials at any time:
|
||||
```bash
|
||||
terraform output website_urls
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 10. Exercise Requirement Traceability & Execution Summary
|
||||
|
||||
The following matrix maps every requirement, deliverable, and bonus task from the Gridscale hiring exercise prompt to its exact technical implementation, file location, and execution method in this repository:
|
||||
|
||||
| Exercise Requirement / Task | Status | Implementation Details & File Location | Execution & Automation Method |
|
||||
| :--- | :---: | :--- | :--- |
|
||||
| **Install & Configure Caddy Server** | Completed | Provisioned `caddy01` VM on Debian 13 in [resources.tf](resources.tf). Installed Caddy via Deb822 repo in [playbook.yml](playbook.yml#L41-L80). | Automated via Ansible `ansible.builtin.apt` & `ansible.builtin.template` |
|
||||
| **Serve Sample Web Application** | Completed | Configured static file server (`root * /usr/share/caddy`, `file_server`) in [templates/Caddyfile.j2](templates/Caddyfile.j2#L10-L13). | Rendered via Ansible template `Caddyfile.j2` |
|
||||
| **Prometheus Monitoring Setup** | Completed | Provisioned `monitoring01` VM in [resources.tf](resources.tf). Installed Prometheus in [playbook.yml](playbook.yml#L81-L120). | Configured scrape job `caddy` targeting `{{ private_ip_caddy }}:2019` |
|
||||
| **Metrics Collection (Codes, Latency, Uptime)** | Completed | Enabled Caddy metrics directive `metrics /metrics` with `per_host` and `observe_catchall_hosts` on Admin API `:2019` in [templates/Caddyfile.j2](templates/Caddyfile.j2#L1-L9). | Scraped every 15s by Prometheus over internal network (`192.168.121.0/27`) |
|
||||
| **Prometheus Alerting Pipeline & Rules** | Completed | Defined `Caddy Down` (`up{job="caddy"} == 0`) and `CaddyHighHTTP4xxErrorRateService` (> 5% 4xx rate) rules in [templates/alert_rules.yml.j2](templates/alert_rules.yml.j2). Imported in [templates/prometheus.yml.j2](templates/prometheus.yml.j2). | Deployed to `/etc/prometheus/alert_rules.yml` via Ansible |
|
||||
| **IaC Automation (Terraform + Ansible)** | Completed | 100% automated with Terraform (Gridscale provider) & Ansible. Built `null_resource.ansible_provisioner` in [inventory.tf](inventory.tf#L29-L43) to execute Ansible automatically. | Runs end-to-end via `terraform apply -auto-approve` |
|
||||
| **Additional Task: Nginx "Hello World" VM** | Completed | Provisioned `nginx01` VM in [resources.tf](resources.tf). Installed Nginx and deployed `index.html.j2` in [playbook.yml](playbook.yml#L121-L140). | Bound strictly to internal private IP (`192.168.121.5:80`) |
|
||||
| **Additional Task: Caddy Reverse Proxy & Routing** | Completed | Configured subdomain reverse proxy routing in [templates/Caddyfile.j2](templates/Caddyfile.j2#L15-L31): `nginx.<ip>.sslip.io` $\rightarrow$ Nginx, `monitoring.<ip>.sslip.io` $\rightarrow$ Prometheus. | Managed via Caddy ingress rules |
|
||||
| **Bonus: Upstream Health Checks & Fault Tolerance** | Completed | Added `health_uri /` (Nginx) and `health_uri /-/healthy` (Prometheus) with 10s intervals in [templates/Caddyfile.j2](templates/Caddyfile.j2#L16-L28). | Probed actively by Caddy to bypass dead nodes |
|
||||
| **Bonus: SSL Termination & Client Encryption** | Completed | Used `sslip.io` dynamic wildcard subdomains on port 443 in [templates/Caddyfile.j2](templates/Caddyfile.j2). | Caddy Auto-HTTPS manages Let's Encrypt TLS termination |
|
||||
| **Deliverables: Endpoints & Output Credentials** | Completed | Configured unmasked output using `nonsensitive()` in [outputs.tf](outputs.tf). | Printed directly to terminal on `terraform apply` |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+14
-2
@@ -1,3 +1,8 @@
|
||||
resource "random_password" "demo_pass" {
|
||||
length = 16
|
||||
special = true
|
||||
}
|
||||
|
||||
resource "local_file" "ansible_inventory" {
|
||||
filename = "${path.module}/inventory.ini"
|
||||
file_permission = "0644"
|
||||
@@ -6,12 +11,18 @@ resource "local_file" "ansible_inventory" {
|
||||
ansible_ssh_extra_args='-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null'
|
||||
private_ip_caddy='${gridscale_server.server_caddy.network[1].auto_assigned_ip}'
|
||||
private_ip_monitoring='${gridscale_server.server_monitoring.network[1].auto_assigned_ip}'
|
||||
private_ip_nginx='${gridscale_server.server_nginx.network[1].auto_assigned_ip}'
|
||||
demo_pass="${random_password.demo_pass.result}"
|
||||
demo_user="demo"
|
||||
|
||||
[caddy]
|
||||
${var.caddy_hostname} ansible_host=${gridscale_ipv4.public_ipv4.ip} ansible_user=root
|
||||
${var.caddy_hostname} ansible_host=${gridscale_ipv4.public_ipv4_caddy.ip} ansible_user=root
|
||||
|
||||
[monitoring]
|
||||
${var.monitoring_hostname} ansible_host=${gridscale_ipv4.public_ipv4_monitoring.ip} ansible_user=root
|
||||
|
||||
[nginx]
|
||||
${var.nginx_hostname} ansible_host=${gridscale_ipv4.public_ipv4_nginx.ip} ansible_user=root
|
||||
EOT
|
||||
}
|
||||
|
||||
@@ -19,7 +30,8 @@ resource "null_resource" "ansible_provisioner" {
|
||||
depends_on = [
|
||||
local_file.ansible_inventory,
|
||||
gridscale_server.server_caddy,
|
||||
gridscale_server.server_monitoring
|
||||
gridscale_server.server_monitoring,
|
||||
gridscale_server.server_nginx
|
||||
]
|
||||
|
||||
provisioner "local-exec" {
|
||||
|
||||
+20
-4
@@ -1,6 +1,6 @@
|
||||
output "caddy_public_ip" {
|
||||
description = "Public IPv4 address of the Caddy server"
|
||||
value = gridscale_ipv4.public_ipv4.ip
|
||||
value = gridscale_ipv4.public_ipv4_caddy.ip
|
||||
}
|
||||
|
||||
output "monitoring_public_ip" {
|
||||
@@ -8,6 +8,11 @@ output "monitoring_public_ip" {
|
||||
value = gridscale_ipv4.public_ipv4_monitoring.ip
|
||||
}
|
||||
|
||||
output "nginx_public_ip" {
|
||||
description = "Public IPv4 address of the Nginx server"
|
||||
value = gridscale_ipv4.public_ipv4_nginx.ip
|
||||
}
|
||||
|
||||
output "caddy_private_ip" {
|
||||
description = "Private IPv4 address of the Caddy server"
|
||||
value = gridscale_server.server_caddy.network[1].auto_assigned_ip
|
||||
@@ -18,7 +23,18 @@ output "monitoring_private_ip" {
|
||||
value = gridscale_server.server_monitoring.network[1].auto_assigned_ip
|
||||
}
|
||||
|
||||
output "ansible_inventory" {
|
||||
description = "Generated Ansible inventory content"
|
||||
value = local_file.ansible_inventory.content
|
||||
output "nginx_private_ip" {
|
||||
description = "Private IPv4 address of the Nginx server"
|
||||
value = gridscale_server.server_nginx.network[1].auto_assigned_ip
|
||||
}
|
||||
|
||||
|
||||
output "website_urls" {
|
||||
description = "Website URLs"
|
||||
value = [
|
||||
"Caddy: https://caddy.${replace(gridscale_ipv4.public_ipv4_caddy.ip, ".", "-")}.sslip.io",
|
||||
"Nginx behind Caddy: https://nginx.${replace(gridscale_ipv4.public_ipv4_caddy.ip, ".", "-")}.sslip.io",
|
||||
"Prometheus behind Caddy: https://monitoring.${replace(gridscale_ipv4.public_ipv4_caddy.ip, ".", "-")}.sslip.io",
|
||||
"Login for Monitoring: demo ${nonsensitive(random_password.demo_pass.result)}"
|
||||
]
|
||||
}
|
||||
@@ -115,3 +115,22 @@
|
||||
src: prometheus.yml.j2
|
||||
dest: /etc/prometheus/prometheus.yml
|
||||
mode: "0644"
|
||||
|
||||
- name: Configure Nginx Server
|
||||
hosts: nginx
|
||||
become: true
|
||||
tags:
|
||||
- nginx
|
||||
|
||||
tasks:
|
||||
- name: Install Nginx
|
||||
ansible.builtin.apt:
|
||||
pkg:
|
||||
- nginx
|
||||
state: present
|
||||
|
||||
- name: Create Hello World page
|
||||
ansible.builtin.template:
|
||||
src: index.html.j2
|
||||
dest: /var/www/html/index.html
|
||||
mode: "0644"
|
||||
|
||||
+84
-20
@@ -7,12 +7,12 @@ resource "gridscale_network" "network_internal"{
|
||||
dhcp_reserved_subnet = ["192.168.121.0/31"]
|
||||
}
|
||||
|
||||
resource "gridscale_ipv4" "public_ipv4" {
|
||||
name = "public_ipv4"
|
||||
resource "gridscale_ipv4" "public_ipv4_caddy" {
|
||||
name = "public_ipv4_caddy"
|
||||
}
|
||||
|
||||
resource "gridscale_ipv6" "public_ipv6" {
|
||||
name = "public_ipv6"
|
||||
resource "gridscale_ipv6" "public_ipv6_caddy" {
|
||||
name = "public_ipv6_caddy"
|
||||
}
|
||||
|
||||
resource "gridscale_ipv4" "public_ipv4_monitoring" {
|
||||
@@ -23,6 +23,14 @@ resource "gridscale_ipv6" "public_ipv6_monitoring" {
|
||||
name = "public_ipv6_monitoring"
|
||||
}
|
||||
|
||||
resource "gridscale_ipv4" "public_ipv4_nginx" {
|
||||
name = "public_ipv4_nginx"
|
||||
}
|
||||
|
||||
resource "gridscale_ipv6" "public_ipv6_nginx" {
|
||||
name = "public_ipv6_nginx"
|
||||
}
|
||||
|
||||
data "gridscale_template" "template_debian_13" {
|
||||
name = "Debian 13"
|
||||
}
|
||||
@@ -68,6 +76,13 @@ resource "gridscale_server" "server_caddy" {
|
||||
dst_port = 80
|
||||
comment = "Allow HTTP access"
|
||||
}
|
||||
rules_v4_in {
|
||||
order = 15
|
||||
protocol = "tcp"
|
||||
action = "accept"
|
||||
dst_port = 443
|
||||
comment = "Allow HTTPS access"
|
||||
}
|
||||
rules_v6_in {
|
||||
order = 0
|
||||
protocol = "tcp"
|
||||
@@ -82,6 +97,13 @@ resource "gridscale_server" "server_caddy" {
|
||||
dst_port = 80
|
||||
comment = "Allow HTTPv6 access"
|
||||
}
|
||||
rules_v6_in {
|
||||
order = 15
|
||||
protocol = "tcp"
|
||||
action = "accept"
|
||||
dst_port = 443
|
||||
comment = "Allow HTTPSv6 access"
|
||||
}
|
||||
}
|
||||
network {
|
||||
# Private network
|
||||
@@ -95,8 +117,8 @@ resource "gridscale_server" "server_caddy" {
|
||||
src_cidr = "192.168.121.0/27"
|
||||
}
|
||||
}
|
||||
ipv4 = gridscale_ipv4.public_ipv4.id
|
||||
ipv6 = gridscale_ipv6.public_ipv6.id
|
||||
ipv4 = gridscale_ipv4.public_ipv4_caddy.id
|
||||
ipv6 = gridscale_ipv6.public_ipv6_caddy.id
|
||||
timeouts {
|
||||
create = "10m"
|
||||
}
|
||||
@@ -131,13 +153,6 @@ resource "gridscale_server" "server_monitoring" {
|
||||
dst_port = 22
|
||||
comment = "Allow SSH access"
|
||||
}
|
||||
rules_v4_in {
|
||||
order = 10
|
||||
protocol = "tcp"
|
||||
action = "accept"
|
||||
dst_port = 80
|
||||
comment = "Allow HTTP access"
|
||||
}
|
||||
rules_v6_in {
|
||||
order = 0
|
||||
protocol = "tcp"
|
||||
@@ -145,13 +160,6 @@ resource "gridscale_server" "server_monitoring" {
|
||||
dst_port = 22
|
||||
comment = "Allow SSHv6 access"
|
||||
}
|
||||
rules_v6_in {
|
||||
order = 10
|
||||
protocol = "tcp"
|
||||
action = "accept"
|
||||
dst_port = 80
|
||||
comment = "Allow HTTPv6 access"
|
||||
}
|
||||
}
|
||||
network {
|
||||
# Private Network
|
||||
@@ -163,3 +171,59 @@ resource "gridscale_server" "server_monitoring" {
|
||||
create = "10m"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
resource "gridscale_storage" "storage_nginx" {
|
||||
name = "storage_nginx"
|
||||
storage_type = "storage"
|
||||
capacity = 20
|
||||
template {
|
||||
sshkeys = [gridscale_sshkey.sshkey_richard.id]
|
||||
template_uuid = data.gridscale_template.template_debian_13.id
|
||||
hostname = var.nginx_hostname
|
||||
}
|
||||
}
|
||||
|
||||
resource "gridscale_server" "server_nginx" {
|
||||
name = var.nginx_hostname
|
||||
cores = 2
|
||||
memory = 1
|
||||
power = true
|
||||
storage {
|
||||
object_uuid = gridscale_storage.storage_nginx.id
|
||||
}
|
||||
network {
|
||||
# Public Network
|
||||
object_uuid = "5557a73b-31ee-4b1f-aa15-7789ad6ae04c"
|
||||
rules_v4_in {
|
||||
order = 0
|
||||
protocol = "tcp"
|
||||
action = "accept"
|
||||
dst_port = 22
|
||||
comment = "Allow SSH access"
|
||||
}
|
||||
rules_v6_in {
|
||||
order = 0
|
||||
protocol = "tcp"
|
||||
action = "accept"
|
||||
dst_port = 22
|
||||
comment = "Allow SSHv6 access"
|
||||
}
|
||||
}
|
||||
network {
|
||||
# Private Network
|
||||
object_uuid = gridscale_network.network_internal.id
|
||||
rules_v4_in {
|
||||
order = 10
|
||||
protocol = "tcp"
|
||||
action = "accept"
|
||||
dst_port = 80
|
||||
comment = "Allow HTTP access for Loadbalancer"
|
||||
}
|
||||
}
|
||||
ipv4 = gridscale_ipv4.public_ipv4_nginx.id
|
||||
ipv6 = gridscale_ipv6.public_ipv6_nginx.id
|
||||
timeouts {
|
||||
create = "10m"
|
||||
}
|
||||
}
|
||||
+20
-1
@@ -7,7 +7,26 @@
|
||||
origins http://{{ private_ip_caddy }}:2019
|
||||
}
|
||||
}
|
||||
:80 {
|
||||
caddy.{{ ansible_default_ipv4.address | replace(".", "-") }}.sslip.io {
|
||||
root * /usr/share/caddy
|
||||
file_server
|
||||
}
|
||||
|
||||
nginx.{{ ansible_default_ipv4.address | replace(".", "-") }}.sslip.io {
|
||||
reverse_proxy {{ private_ip_nginx }}:80 {
|
||||
health_uri /
|
||||
health_interval 10s
|
||||
health_timeout 5s
|
||||
}
|
||||
}
|
||||
|
||||
monitoring.{{ ansible_default_ipv4.address | replace(".", "-") }}.sslip.io {
|
||||
reverse_proxy {{ private_ip_monitoring }}:9090 {
|
||||
health_uri /-/healthy
|
||||
health_interval 10s
|
||||
health_timeout 5s
|
||||
}
|
||||
basic_auth {
|
||||
{{ demo_user }} {{ demo_pass | password_hash('bcrypt') }}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Hello World</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello World</h1>
|
||||
<p>This is {{ ansible_hostname }}</p>
|
||||
<p>Listening on {{ private_ip_nginx }}</p>
|
||||
<p>Behind Reverseproxy from Caddy</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -20,3 +20,9 @@ variable "monitoring_hostname" {
|
||||
description = "Monitoring hostname"
|
||||
default = "monitoring01"
|
||||
}
|
||||
|
||||
variable "nginx_hostname" {
|
||||
type = string
|
||||
description = "Nginx hostname"
|
||||
default = "nginx01"
|
||||
}
|
||||
Reference in New Issue
Block a user