feat: deployable playbook

This commit is contained in:
Doni Crosby 2025-09-27 13:36:00 -04:00
parent f8e1de4f0a
commit 7ab2b719dc
23 changed files with 754 additions and 176 deletions

View file

@ -25,6 +25,11 @@ netbox_redis_host: "redis"
netbox_redis_port: "6379"
netbox_redis_password: ""
# Redis Cache configuration
netbox_redis_cache_host: "redis-cache"
netbox_redis_cache_port: "6379"
netbox_redis_cache_password: ""
# NetBox settings
netbox_allowed_hosts: "localhost,127.0.0.1"
netbox_time_zone: "UTC"

View file

@ -45,7 +45,7 @@
- name: Generate NetBox secret key
set_fact:
netbox_secret_key: "{{ netbox_secret_key | default(128 | random_string) }}"
netbox_secret_key: "{{ netbox_secret_key | default(ansible.builtin.random_string(length=128)) }}"
when: netbox_secret_key == ""
tags:
- netbox-deploy
@ -97,15 +97,15 @@
- config
- name: Pull Docker images
docker_compose:
community.docker.docker_compose_v2:
project_src: "{{ netbox_install_dir }}"
pull: yes
pull: always
tags:
- netbox-deploy
- docker-pull
- name: Start NetBox services
docker_compose:
community.docker.docker_compose_v2:
project_src: "{{ netbox_install_dir }}"
state: present
tags:
@ -114,31 +114,14 @@
- name: Wait for NetBox to be ready
uri:
url: "http://localhost:8000/"
url: "https://{{ netbox_domain }}/"
method: GET
status_code: 200
validate_certs: false
register: netbox_ready
until: netbox_ready.status == 200
retries: 30
delay: 10
tags:
- netbox-deploy
- health-check
- name: Create NetBox superuser
docker_compose:
project_src: "{{ netbox_install_dir }}"
command: "netbox /opt/netbox/netbox/manage.py createsuperuser --noinput --username {{ netbox_superuser_name }} --email {{ netbox_superuser_email }}"
register: superuser_result
failed_when: superuser_result.rc != 0 and "already exists" not in superuser_result.stderr
tags:
- netbox-deploy
- superuser
- name: Set NetBox superuser password
docker_compose:
project_src: "{{ netbox_install_dir }}"
command: "netbox /opt/netbox/netbox/manage.py shell -c \"from django.contrib.auth import get_user_model; User = get_user_model(); u = User.objects.get(username='{{ netbox_superuser_name }}'); u.set_password('{{ netbox_superuser_password }}'); u.save()\""
tags:
- netbox-deploy
- superuser
- health-check

View file

@ -1,8 +0,0 @@
---
# Variables for netbox-deploy role
netbox_install_dir: "/opt/netbox-docker"
netbox_repo_url: "https://github.com/netbox-community/netbox-docker.git"
netbox_repo_branch: "release"
netbox_repo_update: true
netbox_backup_dir: "/opt/netbox-backups"
netbox_data_dir: "/opt/netbox-data"

View file

@ -0,0 +1,56 @@
---
# Default variables for traefik role
# Traefik Configuration
traefik_install_dir: "/opt/traefik"
traefik_data_dir: "/opt/traefik-data"
traefik_config_dir: "/opt/traefik-config"
# Traefik Image
traefik_image: "traefik:v3.0"
traefik_image_tag: "v3.0"
# Traefik Configuration
traefik_dashboard_enabled: true
traefik_dashboard_port: 8080
traefik_api_insecure: false
traefik_api_dashboard: true
# ACME Configuration
traefik_acme_enabled: true
traefik_acme_email: "admin@example.com"
# traefik_acme_ca_server should be defined in group_vars or host_vars
traefik_acme_storage: "/data/acme.json"
traefik_acme_key_type: "RSA4096"
# Entry Points
traefik_entrypoints:
web:
address: ":80"
websecure:
address: ":443"
traefik:
address: ":8080"
# Providers
traefik_providers:
docker:
endpoint: "unix:///var/run/docker.sock"
exposedByDefault: false
network: "traefik"
# Networks
traefik_networks:
- name: "traefik"
external: false
# Logging
traefik_log_level: "INFO"
traefik_access_logs: false
# Custom Root CA Configuration
# Users should define these in their group_vars or host_vars
# traefik_custom_ca_enabled: false
# traefik_custom_ca_url: "https://your-ca-server.com/root-ca.pem"
traefik_custom_ca_path: "/etc/traefik/custom-ca.pem"
traefik_custom_ca_verify_ssl: true

View file

@ -0,0 +1,10 @@
---
- name: restart traefik
community.docker.docker_compose_v2:
project_src: "{{ traefik_install_dir }}"
state: present
recreate: always
pull: always
tags:
- traefik-deploy
- handlers

View file

@ -0,0 +1,19 @@
---
galaxy_info:
author: NetBox Ansible Deployment
description: Traefik reverse proxy with ACME TLS support
company:
license: MIT
min_ansible_version: 2.9
platforms:
- name: Ubuntu
versions:
- focal
- jammy
galaxy_tags:
- traefik
- reverse-proxy
- tls
- acme
dependencies: []

View file

@ -0,0 +1,101 @@
---
- name: Create Traefik installation directory
file:
path: "{{ traefik_install_dir }}"
state: directory
owner: root
group: root
mode: '0755'
tags:
- traefik-deploy
- directories
- name: Create Traefik data directory
file:
path: "{{ traefik_data_dir }}"
state: directory
owner: root
group: root
mode: '0755'
tags:
- traefik-deploy
- directories
- name: Create Traefik config directory
file:
path: "{{ traefik_config_dir }}"
state: directory
owner: root
group: root
mode: '0755'
tags:
- traefik-deploy
- directories
- name: Create ACME storage file
file:
path: "{{ traefik_data_dir }}/acme.json"
state: touch
owner: root
group: root
mode: '0600'
tags:
- traefik-deploy
- config
- name: Download custom root CA certificate
get_url:
url: "{{ traefik_custom_ca_url }}"
dest: "{{ traefik_custom_ca_path }}"
mode: '0644'
owner: root
group: root
validate_certs: "{{ traefik_custom_ca_verify_ssl }}"
timeout: 30
when: traefik_custom_ca_enabled | default(false) and traefik_custom_ca_url | default('') != ''
notify: restart traefik
tags:
- traefik-deploy
- custom-ca
- name: Create Traefik static configuration
template:
src: traefik.yml.j2
dest: "{{ traefik_config_dir }}/traefik.yml"
mode: '0644'
notify: restart traefik
tags:
- traefik-deploy
- config
- name: Create Traefik Docker Compose file
template:
src: docker-compose.yml.j2
dest: "{{ traefik_install_dir }}/docker-compose.yml"
mode: '0644'
notify: restart traefik
tags:
- traefik-deploy
- config
- name: Start Traefik services
community.docker.docker_compose_v2:
project_src: "{{ traefik_install_dir }}"
state: present
tags:
- traefik-deploy
- docker-start
- name: Wait for Traefik to be ready
uri:
url: "https://traefik.{{ traefik_domain | default('localhost') }}/api/rawdata"
method: GET
status_code: 200
ca_path: "{{ traefik_custom_ca_path }}"
register: traefik_ready
until: traefik_ready.status == 200
retries: 30
delay: 5
tags:
- traefik-deploy
- health-check

View file

@ -0,0 +1,41 @@
name: traefik
services:
traefik:
image: "{{ traefik_image }}"
container_name: traefik
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- "{{ traefik_config_dir }}/traefik.yml:/etc/traefik/traefik.yml:ro"
- "{{ traefik_data_dir }}:/data"
{% if traefik_custom_ca_enabled | default(false) %}
- "{{ traefik_custom_ca_path }}:/etc/ssl/certs/custom-ca.pem:ro"
{% endif %}
networks:
{% for network in traefik_networks %}
- "{{ network.name }}"
{% endfor %}
{% if traefik_custom_ca_enabled | default(false) %}
environment:
- LEGO_CA_CERTIFICATES=/etc/ssl/certs/ca-certificates.crt:/etc/ssl/certs/custom-ca.pem
{% endif %}
command:
- --configfile=/etc/traefik/traefik.yml
labels:
- "traefik.enable=true"
- "traefik.http.routers.traefik-dashboard.rule=Host(`traefik.{{ traefik_domain | default('localhost') }}`) && (PathPrefix(`/api`) || PathPrefix(`/dashboard`))"
- "traefik.http.routers.traefik-dashboard.service=api@internal"
networks:
{% for network in traefik_networks %}
{{ network.name }}:
{% if network.external | default(false) %}
external: true
{% else %}
driver: bridge
{% endif %}
{% endfor %}

View file

@ -0,0 +1,86 @@
# Traefik Static Configuration
# Generated by Ansible - DO NOT EDIT MANUALLY
# Global Configuration
global:
checkNewVersion: false
sendAnonymousUsage: false
# API Configuration
api:
dashboard: true
insecure: false
# Entry Points
entryPoints:
{% for name, config in traefik_entrypoints.items() %}
{{ name }}:
address: "{{ config.address }}"
{% if config.http is defined %}
http:
{% if config.http.tls is defined %}
tls:
{% if config.http.tls.certResolver is defined %}
certResolver: {{ config.http.tls.certResolver }}
{% endif %}
{% endif %}
{% if config.http.redirections is defined %}
redirections:
{% for redirection in config.http.redirections %}
entryPoint:
to: "{{ redirection.entrypoint.to }}"
scheme: "{{ redirection.entrypoint.scheme }}"
permanent: {{ redirection.entrypoint.permanent | lower }}
{% endfor %}
{% endif %}
{% endif %}
{% endfor %}
# Providers
providers:
{% for name, config in traefik_providers.items() %}
{{ name }}:
{% for key, value in config.items() %}
{{ key }}: {{ value | to_json if value is mapping else (value | lower if value is boolean else value) }}
{% endfor %}
{% endfor %}
{% if traefik_acme_enabled %}
# Certificate Resolvers
certificatesResolvers:
letsencrypt:
acme:
email: "{{ traefik_acme_email }}"
storage: "{{ traefik_acme_storage }}"
{% if traefik_acme_ca_server is defined %}
caServer: "{{ traefik_acme_ca_server }}"
{% endif %}
httpChallenge:
entryPoint: web
{% endif %}
# Logging
log:
level: "{{ traefik_log_level }}"
{% if traefik_access_logs %}
accessLog:
{% if traefik_access_logs_format is defined %}
format: "{{ traefik_access_logs_format }}"
{% endif %}
{% if traefik_access_logs_fields is defined %}
fields:
defaultMode: "{{ traefik_access_logs_fields.defaultMode }}"
{% if traefik_access_logs_fields.headers is defined %}
headers:
defaultMode: "{{ traefik_access_logs_fields.headers.defaultMode }}"
{% if traefik_access_logs_fields.headers.names is defined %}
names:
{% for header, mode in traefik_access_logs_fields.headers.names.items() %}
"{{ header }}": "{{ mode }}"
{% endfor %}
{% endif %}
{% endif %}
{% endif %}
{% endif %}