commit 68c762ee03c5c56e8a82bee66e1af7007df0cc13 Author: Patrick de Ruiter Date: Mon Feb 2 00:22:29 2026 +0100 Initial commit: Terraform module for Nexus on Docker Deploys Sonatype Nexus Repository Manager with: - Traefik ingress with TLS (production certresolver) - Persistent storage at /opt/nexus-data - Health checks and memory limits diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..76b6051 --- /dev/null +++ b/.gitignore @@ -0,0 +1,25 @@ +# Local .terraform directories +**/.terraform/* + +# .tfstate files +*.tfstate +*.tfstate.* + +# Crash log files +crash.log + +# Exclude all .tfvars files, which are likely to contain sensitive data +# *.tfvars + +# Ignore override files as they are usually used to override resources locally +override.tf +override.tf.json +*_override.tf +*_override.tf.json + +# Ignore CLI configuration files +.terraformrc +terraform.rc + +# Ignore lock file +.terraform.lock.hcl diff --git a/README.md b/README.md new file mode 100644 index 0000000..1017bb0 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# Terraform Docker Nexus + +Deploys Sonatype Nexus Repository Manager on Docker with Traefik ingress. diff --git a/backend.tf b/backend.tf new file mode 100644 index 0000000..327adf9 --- /dev/null +++ b/backend.tf @@ -0,0 +1,20 @@ +terraform { + backend "s3" { + endpoints = { + s3 = "https://minio.bsdserver.nl:443" + } + + bucket = "home-terraform" + key = "home/docker/nexus/nexus.tfstate" + + access_key = "R9lCycfEO8qJ2dxlQT1S" + secret_key = "6rtVLjDIjx7U9ecNRkdbS3idSBNWsfNhN6wB20sJ" + + region = "main" + skip_credentials_validation = true + skip_metadata_api_check = true + skip_requesting_account_id = true + skip_region_validation = true + use_path_style = true + } +} diff --git a/main.tf b/main.tf new file mode 100644 index 0000000..7fa0dfd --- /dev/null +++ b/main.tf @@ -0,0 +1,88 @@ +# Description: This file contains the main Terraform configuration for the Nexus Docker container configuration. + +# Define the local variables +locals { + app_name = "nexus" + app_version = "latest" + app_src_port = "8081" +} + +# Get the ID of the traefik_network +data "docker_network" "traefik_network" { + name = "traefik_network" +} + +# Create Docker image for Nexus +resource "docker_image" "application" { + name = "sonatype/nexus3:${local.app_version}" +} + +# Create Docker container for Nexus +resource "docker_container" "application" { + image = docker_image.application.image_id + name = local.app_name + hostname = local.app_name + user = "200:200" + restart = "unless-stopped" + + networks_advanced { + name = data.docker_network.traefik_network.name + } + + env = [ + "INSTALL4J_ADD_VM_PARAMS=-Xms1024m -Xmx2048m -XX:MaxDirectMemorySize=2g -Djava.util.prefs.userRoot=/nexus-data/javaprefs" + ] + + # Mount host path for persistent data (existing data from previous deployment) + volumes { + host_path = "/opt/nexus-data" + container_path = "/nexus-data" + } + + # Traefik labels for ingress + labels { + label = "traefik.enable" + value = "true" + } + + labels { + label = "traefik.http.routers.nexus.entrypoints" + value = "websecure" + } + + labels { + label = "traefik.http.routers.nexus.rule" + value = "Host(`nexus.${var.domain}`)" + } + + labels { + label = "traefik.http.services.nexus.loadBalancer.server.port" + value = local.app_src_port + } + + labels { + label = "traefik.http.routers.nexus.tls" + value = "true" + } + + labels { + label = "traefik.http.routers.nexus.tls.certresolver" + value = "production" + } + + # Health check + healthcheck { + test = ["CMD", "curl", "-f", "http://localhost:8081/service/rest/v1/status"] + interval = "30s" + timeout = "10s" + retries = 5 + start_period = "120s" + } + + # Resource limits + memory = 4096 + + lifecycle { + ignore_changes = [network_mode] + } +} diff --git a/outputs.tf b/outputs.tf new file mode 100644 index 0000000..a5bcce8 --- /dev/null +++ b/outputs.tf @@ -0,0 +1,11 @@ +# Purpose: This file is used to output the values of the resources created in the main.tf file. + +output "container_id" { + description = "The ID of the Nexus container" + value = docker_container.application.id +} + +output "container_name" { + description = "The name of the Nexus container" + value = docker_container.application.name +} diff --git a/provider.tf b/provider.tf new file mode 100644 index 0000000..28f23ea --- /dev/null +++ b/provider.tf @@ -0,0 +1,33 @@ +# Description: This file is used to configure the Docker and Vault providers. +terraform { + required_providers { + docker = { + source = "abh80/docker" + version = "1.0.1" + } + + vault = { + source = "hashicorp/vault" + version = "5.5.0" + } + } +} + +# Configure the Docker provider +provider "docker" { + host = "tcp://192.168.2.170:2376" + + cert_path = pathexpand("~/.docker") +} + +# Configure the Vault provider +provider "vault" { + address = "https://wbyc-srv-docker01.bsdserver.lan:8200" + auth_login { + path = "auth/approle/login" + parameters = { + role_id = var.role_id + secret_id = var.secret_id + } + } +} diff --git a/renovate.json b/renovate.json new file mode 100644 index 0000000..39a2b6e --- /dev/null +++ b/renovate.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": [ + "config:base" + ] +} diff --git a/terraform.tfvars b/terraform.tfvars new file mode 100644 index 0000000..d58823e --- /dev/null +++ b/terraform.tfvars @@ -0,0 +1,3 @@ +domain = "bsdserver.nl" +role_id = "599bed98-baee-57d8-0ff6-9e6dff214ceb" +secret_id = "89ca5f5c-f4fa-9034-5261-c4b7593a6541" diff --git a/variables.tf b/variables.tf new file mode 100644 index 0000000..3384189 --- /dev/null +++ b/variables.tf @@ -0,0 +1,17 @@ +variable "domain" { + description = "Domain name for the application" + type = string + default = "bsdserver.nl" +} + +variable "role_id" { + description = "Role ID for Vault AppRole authentication" + type = string + sensitive = true +} + +variable "secret_id" { + description = "Secret ID for Vault AppRole authentication" + type = string + sensitive = true +}