Introduction

System identity and time configuration are foundational server setup tasks. Ansible's hostname and timezone modules configure these idempotently, ensuring consistency across your fleet.

Set Hostname

# Set the system hostname
- name: Set hostname
  ansible.builtin.hostname:
    name: "{{ inventory_hostname }}"

# Set FQDN
- name: Set hostname
  ansible.builtin.hostname:
    name: web-01.prod.example.com

# Update /etc/hosts to match
- name: Update /etc/hosts
  ansible.builtin.lineinfile:
    path: /etc/hosts
    regexp: '^127\.0\.1\.1'
    line: "127.0.1.1 {{ inventory_hostname }}.{{ domain }} {{ inventory_hostname }}"

Hostname Parameters

ParameterDescription
nameHostname to set (required)
useBackend: systemd, debian, redhat, alpine, etc. (auto-detected)

Set Timezone

# Set timezone
- name: Set timezone to UTC
  community.general.timezone:
    name: UTC

# Set to specific timezone
- name: Set timezone
  community.general.timezone:
    name: America/New_York

# Set European timezone
- name: Set timezone
  community.general.timezone:
    name: Europe/Rome

Common Timezones

TimezoneRegion
UTCUniversal
America/New_YorkUS Eastern
America/ChicagoUS Central
America/DenverUS Mountain
America/Los_AngelesUS Pacific
Europe/LondonUK
Europe/BerlinGermany
Europe/RomeItaly
Europe/ParisFrance
Asia/TokyoJapan
Asia/ShanghaiChina
Asia/KolkataIndia
Australia/SydneyAustralia Eastern
# List all available timezones
timedatectl list-timezones

Configure NTP

# Install and configure chrony (modern NTP)
- name: Install chrony
  ansible.builtin.package:
    name: chrony
    state: present

- name: Configure NTP servers
  ansible.builtin.template:
    src: chrony.conf.j2
    dest: /etc/chrony/chrony.conf
  notify: Restart chrony

- name: Enable chrony
  ansible.builtin.service:
    name: chronyd
    state: started
    enabled: true

# Or use systemd-timesyncd
- name: Enable NTP with timedatectl
  ansible.builtin.command: timedatectl set-ntp true
  changed_when: false

Practical Pattern: Full System Bootstrap

---
- name: Bootstrap server identity
  hosts: all
  become: true
  tasks:
    - name: Set hostname
      ansible.builtin.hostname:
        name: "{{ inventory_hostname }}"

    - name: Configure /etc/hosts
      ansible.builtin.blockinfile:
        path: /etc/hosts
        marker: "# {mark} ANSIBLE MANAGED"
        block: |
          127.0.0.1 localhost
          127.0.1.1 {{ inventory_hostname }}.{{ domain }} {{ inventory_hostname }}
          {% for host in groups['all'] %}
          {{ hostvars[host]['ansible_host'] }} {{ host }}.{{ domain }} {{ host }}
          {% endfor %}

    - name: Set timezone
      community.general.timezone:
        name: "{{ server_timezone | default('UTC') }}"

    - name: Install NTP
      ansible.builtin.package:
        name: chrony
        state: present

    - name: Enable NTP
      ansible.builtin.service:
        name: "{{ 'chronyd' if ansible_os_family == 'RedHat' else 'chrony' }}"
        state: started
        enabled: true

    - name: Set locale
      ansible.builtin.command: localectl set-locale LANG=en_US.UTF-8
      changed_when: false

Set Locale

# Generate locale
- name: Generate locale
  community.general.locale_gen:
    name: en_US.UTF-8
    state: present

# Set system locale
- name: Set default locale
  ansible.builtin.command: localectl set-locale LANG=en_US.UTF-8
  changed_when: false

# Or with file
- name: Set locale via file
  ansible.builtin.copy:
    content: |
      LANG=en_US.UTF-8
      LC_ALL=en_US.UTF-8
    dest: /etc/default/locale

Troubleshooting

Hostname Reverts After Reboot

Ensure cloud-init isn't overriding it:

# Disable cloud-init hostname management
- name: Prevent cloud-init from changing hostname
  ansible.builtin.copy:
    content: "preserve_hostname: true\n"
    dest: /etc/cloud/cloud.cfg.d/99-hostname.cfg
  when: ansible_service_mgr == 'systemd'

Timezone Module Not Found

Install the collection:

ansible-galaxy collection install community.general

Conclusion

ansible.builtin.hostname and community.general.timezone handle fundamental server identity. Set hostname from inventory_hostname for consistency. Always update /etc/hosts to match. Use UTC for servers unless there's a specific reason not to. Configure NTP (chrony) for accurate time — critical for logging, certificates, and cluster coordination. These should be the first tasks in any server bootstrap playbook.