Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
cc4556c
fix(ui): use ansible_host attributes for host ids
wiseflat Oct 5, 2025
70e67ef
fix(ui): disable instance and software validation
wiseflat Oct 5, 2025
3006540
fix(ui): include key param in variables_read request
wiseflat Oct 5, 2025
0451408
feat(ui): enable first account creation in account schema
wiseflat Oct 5, 2025
2d9a049
fix(lookup): simplify missing key error messages
wiseflat Oct 5, 2025
beceb14
refactor(nomad): replace fact_instance vars with software vars in con…
wiseflat Oct 5, 2025
1c4795a
chore(forgejo): remove debug task
wiseflat Oct 5, 2025
177d2fb
feat(caddy): generate Caddyfile with Nomad template
wiseflat Oct 5, 2025
19cb77a
refactor(traefik): use software_path and delegate tasks to instance
wiseflat Oct 5, 2025
39171a4
feat(traefik): enable traefik API dashboard and expose API port
wiseflat Oct 5, 2025
5155756
refactor(ansible): move temporary build dir creation to pre_tasks
wiseflat Oct 5, 2025
51bbf33
refactor(nomad): simplify role configuration and remove legacy settings
wiseflat Oct 5, 2025
7cdb719
style(ansible): use fully qualified modules and quote mode
wiseflat Oct 5, 2025
eb3b9c6
style(ansible): fully qualify modules and drop unused packages
wiseflat Oct 5, 2025
aefb3f2
feat(ansible): add systemd-resolved configuration playbook
wiseflat Oct 5, 2025
b5ce62d
feat(nomad): Update debug tasks and timezone configuration
wiseflat Oct 5, 2025
fde5100
fix(nomad): use ansible interface IP for nomad server address
wiseflat Oct 5, 2025
d488efc
feat(nomad): ensure latest nomad binary is installed
wiseflat Oct 5, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 3 additions & 9 deletions ansible/playbooks/paas/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@
become: true
pre_tasks:
- name: Create ansible facts.d directory
become: yes
file:
become: true
ansible.builtin.file:
path: /etc/ansible/facts.d
state: directory
owner: "root"
group: "root"
mode: 0755
mode: '0755'

- name: Get ipinfo.io
ansible.builtin.uri:
Expand All @@ -32,13 +32,8 @@
ansible.builtin.apt:
pkg:
- python3-debian
- python3-passlib
- libxml2-utils
- ruby-rubygems
- binutils
- unzip
- make
- python3-pymysql
- jq

state: present
Expand All @@ -49,4 +44,3 @@
retries: 10
roles:
- unattended-upgrades
- restic
4 changes: 2 additions & 2 deletions ansible/playbooks/paas/nomad.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
---
- name: Create CA TLS
any_errors_fatal: true
hosts: "{{ hosts_limit | default('infrastructure') }}"
hosts: localhost
gather_facts: false
strategy: linear
become: true
become: false
tasks:
- name: "Create TLS CA"
ansible.builtin.include_role:
Expand Down
4 changes: 2 additions & 2 deletions ansible/playbooks/paas/roles/certificate/defaults/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
# defaults file for certificate

certificate_ca_host: localhost
certificate_ca_host_dir: "~/.simple-stack/tls/{{ inventory_hostname }}"
certificate_ca_host_dir: "~/.simple-stack/tls"
certificate_ca_pubkey: simplestack-ca.pem
certificate_ca_privatekey: simplestack-ca-key.pem
certificate_host_certificate_dir: /etc/ssl/simplestack
certificate_common_name: simplestack
certificate_common_name: nomad
18 changes: 1 addition & 17 deletions ansible/playbooks/paas/roles/certificate/tasks/ca.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
become: false
register: cert_ca_tls_priv_present

- name: "Certificate | Create private key for CA (simplestack-ca-key.pem)"
- name: "Certificate | Create private key for CA"
community.crypto.openssl_privatekey:
path: "{{ certificate_ca_host_dir }}/{{ certificate_ca_privatekey }}"
delegate_to: "{{ certificate_ca_host }}"
Expand Down Expand Up @@ -54,19 +54,3 @@
become: false
when: not cert_ca_tls_priv_present.stat.exists

- name: "Certificate | Create TLS directory on target"
ansible.builtin.file:
path: "{{ certificate_host_certificate_dir }}"
state: directory
mode: '0755'
recurse: true
when: not ca_pubkey_present.stat.exists

- name: "Certificate | Copy Public certs on nodes - {{ certificate_ca_pubkey }}"
ansible.builtin.copy:
src: "{{ certificate_ca_host_dir }}/{{ certificate_ca_pubkey }}"
dest: "{{ certificate_host_certificate_dir }}/{{ certificate_ca_pubkey }}"
owner: "root"
group: "root"
mode: "0640"
when: not ca_pubkey_present.stat.exists
176 changes: 90 additions & 86 deletions ansible/playbooks/paas/roles/nomad/defaults/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,29 @@
# defaults file for install

# General
nomad_mode: "{% if (ansible_play_hosts | length) == 1 %}single{% elif (ansible_play_hosts | length) > 1 %}cluster{% endif %}"
nomad_node_role: "{% if nomad_mode == 'single' %}both{% elif nomad_mode == 'cluster' %}{{ nomad_node_role | default('both') }}{% endif %}"

## single / cluster
nomad_mode: single

## client / server / both
nomad_node_role: both

nomad_deploy_cluster_name: "{{ nomad_cluster_name | default('default') }}"
nomad_firewall: true
nomad_timezone: "Europe/Paris"

nomad_group: "simplestack"
nomad_group: simplestack

# Configuration
nomad_dc_name: "dc1"

nomad_node_name: "{{ inventory_hostname }}"
nomad_project: "{{ fact_instance.project }}"
nomad_region: "{{ fact_instance.region }}"
nomad_location: "{{ fact_instance.region }}"

nomad_node_name: "{{ inventory_hostname }}"

nomad_system_user: "{% if nomad_node_role == 'server' %}nomad{% elif nomad_node_role == 'client' or nomad_node_role == 'both' %}root{% endif %}"
nomad_system_group: "{% if nomad_node_role == 'server' %}nomad{% elif nomad_node_role == 'client' or nomad_node_role == 'both' %}root{% endif %}"
nomad_system_user: "{{ (nomad_node_role == 'server') | ternary('nomad', 'root') }}"
nomad_system_group: "{{ (nomad_node_role == 'server') | ternary('nomad', 'root') }}"

nomad_config_dir: "/etc/nomad.d"
nomad_config_file: "nomad.hcl"
Expand All @@ -28,120 +34,116 @@ nomad_data_dir_server: "/opt/nomad/server"
nomad_state_dir_client: "/opt/nomad/client"
nomad_job_files_dir: "/var/tmp"

nomad_disable_anonymous_signature: "false"
nomad_disable_update_check: "false"
nomad_disable_anonymous_signature: false
nomad_disable_update_check: false

nomad_leave_on_terminate: true
nomad_leave_on_interrupt: true

nomad_client_auto_join: 'true'
nomad_server_auto_join: 'true'
nomad_client_auto_join: true
nomad_server_auto_join: true

nomad_s3_storage_enabled: true

# Network
nomad_http_scheme: "https"
nomad_http_scheme: https
nomad_http_ip: "127.0.0.1"
nomad_http_port: 4646

nomad_cluster_bridge: "br0"
nomad_iface: "{{ ansible_default_ipv4.interface }}"
nomad_cluster_bridge: "ens3"
nomad_iface: "ens3"

nomad_list_node_ip: "\
{% set nomad_list_node_ip = [] %}\
{% for host in groups[consul_deploy_cluster_name] %}\
{% if nomad_list_node_ip.append(hostvars[host]['ansible_' + hostvars[host].nomad_cluster_bridge].ipv4.address | default(nomad_cluster_bridge)) %}{% endif %}\
{% endfor %}\
{{ nomad_list_node_ip }}"
nomad_bind_address: "0.0.0.0"
nomad_advertise_address: "{{ hostvars[inventory_hostname]['ansible_' + nomad_iface]['ipv4']['address'] }}"

nomad_bind_address: "{{ hostvars[inventory_hostname]['ansible_' + nomad_iface | replace('-', '_')]['ipv4']['address'] }}"
nomad_ports:
http: "{{ nomad_ports_http | default('4646', true) }}"
rpc: "{{ nomad_ports_rpc | default('4647', true) }}"
serf: "{{ nomad_ports_serf | default('4648', true) }}"

nomad_bind_addr: "0.0.0.0"

nomad_address_http: "0.0.0.0"
nomad_address_rpc: "{% if nomad_mode == 'single' %}0.0.0.0{% else %}{{ hostvars[inventory_hostname]['ansible_' + nomad_cluster_bridge | replace('-', '_')]['ipv4']['address'] }}{% endif %}"
nomad_address_serf: "{% if nomad_mode == 'single' %}0.0.0.0{% else %}{{ hostvars[inventory_hostname]['ansible_' + nomad_cluster_bridge | replace('-', '_')]['ipv4']['address'] }}{% endif %}"

nomad_advertise_http: "{% if nomad_mode == 'single' %}127.0.0.1{% else %}{{ hostvars[inventory_hostname]['ansible_' + nomad_cluster_bridge | replace('-', '_')]['ipv4']['address'] }}{% endif %}"
nomad_advertise_rpc: "{% if nomad_mode == 'single' %}127.0.0.1{% else %}{{ hostvars[inventory_hostname]['ansible_' + nomad_cluster_bridge | replace('-', '_')]['ipv4']['address'] }}{% endif %}"
nomad_advertise_serf: "{% if nomad_mode == 'single' %}127.0.0.1{% else %}{{ hostvars[inventory_hostname]['ansible_' + nomad_cluster_bridge | replace('-', '_')]['ipv4']['address'] }}{% endif %}"

nomad_port_http: 4646
nomad_port_rpc: 4647
nomad_port_serf: 4648

# Network
nomad_bridge: true

nomad_bridge_list:
- { name: "internal", interface: "br-internal", ip_range: "172.18.0.1/16" }
- { name: "metrics", interface: "br-metrics", ip_range: "172.19.0.1/16" }

# Log
nomad_debug: "false"
nomad_log_file: "/var/log/nomad/nomad.log"
nomad_log_level: "WARN"
nomad_debug: false
nomad_log_file: /var/log/nomad/nomad.log
nomad_log_level: WARN
nomad_log_rotate_bytes: 0
nomad_log_rotate_duration: "24h"
nomad_log_rotate_duration: 24h
nomad_log_rotate_max_files: 0

# Server
nomad_server_enabled: "true"
nomad_server_enabled: true

nomad_server_bootstrap_expect: "\
{% set nomad_server_bootstrap_expect = [] %}\
nomad_servers: "\
{% set nomad_servers = [] %}\
{% if nomad_mode == 'single' %}\
{% set _ = nomad_server_bootstrap_expect.append(1) %}\
{% set _ = nomad_servers.append(inventory_hostname) %}\
{% else %}\
{% for host in groups[nomad_deploy_cluster_name] %}\
{% if hostvars[host].consul_node_role in ['server', 'both'] %}\
{% set _ = nomad_server_bootstrap_expect.append(1) %}\
{% if hostvars[host].nomad_node_role in ['server', 'both'] %}\
{% set _ = nomad_servers.append(host) %}\
{% endif %}\
{% endfor %}\
{% endif %}\
{{ nomad_server_bootstrap_expect | length }}"
{{ nomad_servers }}"

nomad_server_rejoin_after_leave: "true"
nomad_servers_advertise_address: "\
{% set nomad_servers_advertise_address = [] %}\
{% if nomad_mode == 'single' %}\
{% set _ = nomad_servers_advertise_address.append(hostvars[inventory_hostname]['ansible_' + nomad_iface]['ipv4']['address']) %}\
{% else %}\
{% for host in groups[nomad_deploy_cluster_name] %}\
{% if hostvars[host].nomad_node_role in ['server', 'both'] %}\
{% set _ = nomad_servers_advertise_address.append(hostvars[host]['ansible_' + hostvars[host].nomad_iface]['ipv4']['address']) %}\
{% endif %}\
{% endfor %}\
{% endif %}\
{{ nomad_servers_advertise_address }}"

nomad_server_retry_max: 0
nomad_server_retry_join: false
nomad_serer_retry_interval: 30s
nomad_server_rejoin_after_leave: true

nomad_server_enabled_schedulers:
- service
- batch
- system
nomad_num_schedulers: "{{ ansible_processor_vcpus }}"

nomad_server_num_schedulers: 2
nomad_server_num_schedulers: 1

nomad_server_event_buffer_size: 100
nomad_server_node_gc_threshold: "24h"
nomad_server_eval_gc_threshold: "1h"
nomad_server_job_gc_threshold: "4h"
nomad_server_deployment_gc_threshold: "1h"

nomad_server_heartbeat_grace: "10s"
nomad_server_min_heartbeat_ttl: "10s"
nomad_server_failover_heartbeat_ttl: "5m"
nomad_server_node_gc_threshold: 24h
nomad_server_eval_gc_threshold: 1h
nomad_server_job_gc_threshold: 4h
nomad_server_deployment_gc_threshold: 1h

nomad_server_heartbeat_grace: 10s
nomad_server_min_heartbeat_ttl: 10s
nomad_server_failover_heartbeat_ttl: 5m
nomad_server_max_heartbeats_per_second: 50.0

# nomad_server_encrypt: ""

nomad_server_raft_protocol: 3

# Client
nomad_client_enabled: "true"
nomad_client_enabled: true

nomad_client_node_class: "{{ inventory_hostname }}-client"
nomad_client_node_pool: "default"
nomad_client_node_pool: default

nomad_client_no_host_uuid: "false"
nomad_client_max_kill_timeout: "30s"
nomad_client_no_host_uuid: false
nomad_client_max_kill_timeout: 30s

nomad_client_network_interface: docker0
nomad_client_network_interface: "{{ nomad_iface }}"

nomad_client_host_network_default:
name: "public"
name: public
interface: "{{ ansible_default_ipv4.interface }}"

nomad_client_host_network_cluster:
name: "cluster"
name: cluster
interface: "{{ nomad_cluster_bridge }}"

nomad_client_meta_list: {"arch": "{{ architecture_map[ansible_facts.architecture] }}", "location": "{{ fact_instance.location }}", "instance": "{{ inventory_hostname }}"}
Expand Down Expand Up @@ -173,39 +175,41 @@ nomad_client_reserved_disk: 0

# TLS
nomad_tls_ca_host: localhost
nomad_tls_ca_host_dir: "~/.simple-stack/tls/{{ inventory_hostname }}"
nomad_tls_ca_host_dir: "~/.simple-stack/tls"
nomad_tls_ca_pubkey: "simplestack-ca.pem"
nomad_tls_ca_privatekey: "simplestack-ca-key.pem"
nomad_tls_ca_provider: "ownca"
nomad_tls_host_certificate_dir: "/etc/ssl/simplestack"
nomad_tls_common_name: "nomad"
nomad_tls_check_delay: "+2w"

nomad_tls_http: "true"
nomad_tls_rpc: "true"

# TLS Server
nomad_tls_cert_server: "{{ nomad_dc_name }}-server-nomad.pem"
nomad_tls_privatekey_server: "{{ nomad_dc_name }}-server-nomad.key"

nomad_tls_common_name_server: "*.{{ nomad_dc_name }}.nomad"
nomad_tls_subject_alt_name_server: "DNS:localhost,IP:127.0.0.1,DNS:server.global.nomad,DNS:server.{{ nomad_region }}.nomad,DNS:server.{{ nomad_dc_name }}.nomad,DNS:*.{{ nomad_dc_name }}.nomad,IP:172.26.64.1,IP:172.17.0.1,IP:172.18.0.1"
nomad_tls_common_name_server: "*.{{ nomad_dc_name }}.{{ nomad_tls_common_name }}"
# nomad_tls_subject_alt_name_server: "DNS:localhost,IP:127.0.0.1,DNS:server.global.{{ certificate_subject_alt_name }},DNS:server.{{ nomad_region }}.{{ certificate_subject_alt_name }},DNS:server.{{ nomad_dc_name }}.{{ certificate_subject_alt_name }},DNS:*.{{ nomad_dc_name }}.{{ certificate_subject_alt_name }},IP:172.26.64.1,IP:172.17.0.1,IP:172.18.0.1"
# nomad_tls_subject_alt_name_server: "DNS:localhost,IP:127.0.0.1,DNS:server.global.nomad,DNS:server.{{ nomad_region }}.nomad,DNS:server.{{ nomad_dc_name }}.nomad,DNS:*.{{ nomad_dc_name }}.nomad,IP:172.26.64.1,IP:172.17.0.1,IP:172.18.0.1"
nomad_tls_subject_alt_name_server: "DNS:localhost,IP:127.0.0.1,IP:172.17.0.1,DNS:server.global.nomad,DNS:server.{{ nomad_region }}.nomad,DNS:server.{{ nomad_dc_name }}.nomad,DNS:*.{{ nomad_dc_name }}.nomad"

# TLS client
nomad_tls_cert_client: "{{ nomad_dc_name }}-client-nomad.pem"
nomad_tls_privatekey_client: "{{ nomad_dc_name }}-client-nomad.key"
nomad_tls_cert_client: "{{ inventory_hostname }}-{{ nomad_dc_name }}-client-nomad.pem"
nomad_tls_privatekey_client: "{{ inventory_hostname }}-{{ nomad_dc_name }}-client-nomad.key"

nomad_tls_common_name_client: "*.{{ nomad_dc_name }}.nomad"
nomad_tls_subject_alt_name_client: "DNS:localhost,IP:127.0.0.1,DNS:client.global.nomad,DNS:client.{{ nomad_region }}.nomad,DNS:client.{{ nomad_dc_name }}.nomad,DNS:*.{{ nomad_dc_name }}.nomad,IP:172.26.64.1,IP:172.17.0.1,IP:172.18.0.1"
nomad_tls_common_name_client: "*.{{ nomad_dc_name }}.{{ nomad_tls_common_name }}"
# nomad_tls_subject_alt_name_client: "DNS:localhost,IP:127.0.0.1,DNS:client.global.{{ certificate_subject_alt_name }},DNS:client.{{ nomad_region }}.{{ nomad_tls_common_name }},DNS:client.{{ nomad_dc_name }}.{{ nomad_tls_common_name }},DNS:*.{{ nomad_dc_name }}.{{ nomad_tls_common_name }},IP:172.26.64.1,IP:172.17.0.1,IP:172.18.0.1"
# nomad_tls_subject_alt_name_client: "DNS:localhost,IP:127.0.0.1,DNS:client.global.nomad,DNS:client.{{ nomad_region }}.nomad,DNS:client.{{ nomad_dc_name }}.nomad,DNS:*.{{ nomad_dc_name }}.nomad,IP:172.26.64.1,IP:172.17.0.1,IP:172.18.0.1"
nomad_tls_subject_alt_name_client: "DNS:localhost,IP:127.0.0.1,IP:172.17.0.1,DNS:client.global.nomad,DNS:client.{{ nomad_region }}.nomad,DNS:client.{{ nomad_dc_name }}.nomad,DNS:*.{{ nomad_dc_name }}.nomad"

nomad_tls_rpc_upgrade_mode: "false"
nomad_tls_verify_server_hostname: "true"
nomad_tls_verify_https_client: "false"

# ACL
nomad_acl_enabled: "true"
nomad_acl_token_ttl: "30s"
nomad_acl_policy_ttl: "30s"
nomad_acl_enabled: true
nomad_acl_token_ttl: 30s
nomad_acl_policy_ttl: 30s
nomad_acl_replication_token: ""

# Docker
nomad_docker_client_dc_name: "dc1"
Expand Down Expand Up @@ -279,13 +283,13 @@ nomad_telemetry_circonus_check_force_metric_activation: "false"
# nomad_telemetry_circonus_broker_select_tag: ""

# Autopilot
nomad_autopilot_cleanup_dead_servers: "true"
nomad_autopilot_last_contact_threshold: "200ms"
nomad_autopilot_cleanup_dead_servers: true
nomad_autopilot_last_contact_threshold: 200ms
nomad_autopilot_max_trailing_logs: 250
nomad_autopilot_server_stabilization_time: "10s"
nomad_autopilot_server_stabilization_time: 10s

# UI
nomad_ui_enabled: "true"
nomad_ui_enabled: true
nomad_ui_content_security_policy_connect_src: "*"
nomad_ui_content_security_policy_default_src: "'none'"
nomad_ui_content_security_policy_form_action: "'none'"
Expand Down
7 changes: 0 additions & 7 deletions ansible/playbooks/paas/roles/nomad/handlers/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,6 @@
ansible.builtin.apt:
update_cache: true

- name: Netplan_apply
ansible.builtin.command: "netplan apply"
async: 45
poll: 0
register: netplan_apply
changed_when: netplan_apply.ansible_job_id != 0

- name: Nomad_restart
ansible.builtin.systemd_service:
name: nomad
Expand Down
Loading