The Configuration File
======================

Exosphere loads all of its settings and inventory from a configuration file.
The configuration file can be provided in multiple formats, including
`yaml`_, `toml`_, and `json`_.

Location
--------

Where the configuration file lives will depend on your platform.
For instance, for a **YAML** configuration file, the default locations are:

.. tabs::

    .. group-tab:: Linux, Unix

        ``~/.config/exosphere/config.yaml``

    .. group-tab:: macOS

        ``~/Library/Application Support/exosphere/config.yaml``

    .. group-tab:: Windows

        ``%LOCALAPPDATA%\exosphere\config.yaml``

You can of course substitute the file extension with `.toml` or `.json` if you wish
to use those formats instead.

You can also ask Exosphere where it expects the configuration file to be on your
platform:

.. code-block:: bash

    exosphere config paths

Additionally, you can specify a custom configuration file location via the
``EXOSPHERE_CONFIG_FILE`` environment variable, with the full path to the file
as the value.

Structure
---------

Below is a full example of a configuration file, in all supported formats.
Any option left out will use the default values, which are documented below.

.. tabs::

    .. group-tab:: YAML

        .. literalinclude:: ../../examples/config.yaml

    .. group-tab:: TOML

        .. literalinclude:: ../../examples/config.toml

    .. group-tab:: JSON

        .. literalinclude:: ../../examples/config.json

The configuration file is split into two main sections, :ref:`config_options` and :ref:`Hosts<config_inventory>`.
The :ref:`config_options` section contains general settings for Exosphere, while the :ref:`Hosts<config_inventory>`
section contains the Inventory of hosts that Exosphere will connect to.

.. _config_env_vars:

Environment Variables
---------------------

The location of the configuration file can be overridden by setting the
``EXOSPHERE_CONFIG_FILE`` environment variable to the full path of the
file you wish to use.

.. tabs::

    .. group-tab:: Unix/macOS

        .. code-block:: shell

            export EXOSPHERE_CONFIG_FILE="/path/to/my/config.yaml"

    .. group-tab:: Windows/PowerShell

        .. code-block:: powershell

            $env:EXOSPHERE_CONFIG_FILE = "c:\path\to\my\config.yaml"

    .. group-tab:: Windows/cmd

        .. code-block:: batch

            set EXOSPHERE_CONFIG_FILE="c:\path\to\my\config.yaml"

.. tip::

    There is also ``EXOSPHERE_CONFIG_PATH``, which you can use to specify
    a **directory** where a config file named ``config.{yaml,yml,toml,json}``
    will be searched for. This can be useful in certain deployments.

Exosphere also supports loading configuration options from environment variables.
You can use this to override any specific `Option` from the configuration file.
You cannot use environment variables to override the `Hosts` section.

The environment variable names are prefixed with ``EXOSPHERE_OPTIONS_`` and
the option name in uppercase.

For example, to override the ``log_level`` option, set the following
environment variable:

.. tabs::

    .. group-tab:: Unix/macOS

        .. code-block:: shell

            export EXOSPHERE_OPTIONS_LOG_LEVEL="DEBUG"

    .. group-tab:: Windows/PowerShell

        .. code-block:: powershell

            $env:EXOSPHERE_OPTIONS_LOG_LEVEL = "DEBUG"

    .. group-tab:: Windows/cmd

        .. code-block:: batch

            set EXOSPHERE_OPTIONS_LOG_LEVEL=DEBUG

This pattern applies to all configuration options.

.. admonition:: Note

    Option types are all strings in this context, but they will be parsed
    as `json`_ types when loaded. This means "true" and "false" will correctly
    be interpreted as booleans, and "null" will be interpreted as ``None``.
    Essentially, you do not need to worry about it as type conversion is
    properly handled automatically.

Exosphere can display which environment variables are influencing
the configuration (if any):

.. code-block:: shell

    exosphere config source

.. _config_options:

Options
-------

The options section contains general settings for Exosphere.
These options are applied globally, and affect how Exosphere behaves at runtime.

- :option:`log_level`
- :option:`default_sudo_policy`
- :option:`debug`
- :option:`log_file`
- :option:`log_max_bytes`
- :option:`log_backup_count`
- :option:`history_file`
- :option:`history_max_entries`
- :option:`cache_autosave`
- :option:`cache_autopurge`
- :option:`cache_file`
- :option:`stale_threshold`
- :option:`default_timeout`
- :option:`default_username`
- :option:`default_ssh_locale`
- :option:`max_threads`
- :option:`ssh_pipelining`
- :option:`ssh_pipelining_lifetime`
- :option:`ssh_pipelining_reap_interval`
- :option:`update_checks`
- :option:`no_banner`
- :option:`editor`

Below is a detailed list of all available options, their defaults,
and examples of how to set them in the configuration file.


.. _log_level_option:

.. option:: log_level

    The logging level for Exosphere. This can be set to one of the following values,
    as a string:

    - DEBUG
    - INFO
    - WARNING
    - ERROR

    This controls the verbosity of the logs generated by Exosphere.

    **Default**: ``INFO``

    **Example**:

    .. tabs::

        .. group-tab:: YAML

            .. code-block:: yaml

                options:
                  log_level: DEBUG

        .. group-tab:: TOML

            .. code-block:: toml

                [options]
                log_level = "DEBUG"

        .. group-tab:: JSON

            .. code-block:: json

                {
                    "options": {
                        "log_level": "DEBUG"
                    }
                }

.. _default_sudo_policy_option:

.. option:: default_sudo_policy

    The global sudo policy to use when running commands on hosts.
    This can be set to one of the following values:

    - ``skip``: Do not run commands that require sudo at all
    - ``nopasswd``: Assume sudoers configuration allows running the provider
      commands without a password

    This controls how Exosphere will handle sudo permissions when running commands
    on hosts. The default is `skip`, which means Exosphere will not attempt to use
    sudo at all.

    If you want Exosphere to run commands that require elevated privileges at all,
    you must configure your sudoers file to allow the user Exosphere connects as
    to run those commands with ``NOPASSWD:`` in the sudoers file.

    More details on how to configure this can be found in the :doc:`sudo`
    documentation.

    .. admonition:: Note

        Depending on the Providers you use, you may not need to configure this at all!
        See the :doc:`providers` documentation for more details.

        This is the global value that, by default, applies to all hosts.
        It can be overridden on a per-host basis in the inventory, inside
        the `hosts` section, via :option:`sudo_policy`.


    **Default**: ``skip``

    **Example**:

    .. tabs::

        .. group-tab:: YAML

            .. code-block:: yaml

                options:
                  default_sudo_policy: nopasswd

        .. group-tab:: TOML

            .. code-block:: toml

                [options]
                default_sudo_policy = "nopasswd"

        .. group-tab:: JSON

            .. code-block:: json

                {
                    "options": {
                        "default_sudo_policy": "nopasswd"
                    }
                }

.. _debug_option:

.. option:: debug

    Enable debug mode, which sets the root logger to DEBUG level.
    This is useful for development and debugging purposes, if you also
    want to see debug logs from libraries and other components.

    Normally, there's very little reason to enable this unless you are
    actively developing Exosphere or troubleshooting a specific issue.

    .. caution::

        Enabling debug mode will absolutely flood your logs with
        debug messages from both Exosphere and *all* of its dependencies.
        We do not recommend enabling this unless you know what you are doing.

        You probably want to set :option:`log_level` to ``DEBUG`` instead.

    **Default**: ``false``

    **Example**:

    .. tabs::

        .. group-tab:: YAML

            .. code-block:: yaml

                options:
                  debug: true

        .. group-tab:: TOML

            .. code-block:: toml

                [options]
                debug = true

        .. group-tab:: JSON

            .. code-block:: json

                {
                    "options": {
                        "debug": true
                    }
                }

.. _log_file_option:

.. option:: log_file

    A filesystem path to a file where Exosphere will write logs.
    If not set, Exosphere will use the platform default location for
    application logs.

    You can set this to any valid path on your filesystem where you have
    write permissions.

    **Default**: (Platform Default)

    **Example**:

    .. tabs::

        .. group-tab:: YAML

            .. code-block:: yaml

                options:
                  log_file: /home/alice/tmp/exosphere.log

        .. group-tab:: TOML

            .. code-block:: toml

                [options]
                log_file = "/home/alice/exosphere.log"

        .. group-tab:: JSON

            .. code-block:: json

                {
                    "options": {
                        "log_file": "/home/alice/exosphere.log"
                    }
                }

.. _log_max_bytes_option:

.. option:: log_max_bytes

    The maximum size, in bytes, that the :option:`log_file` may reach before
    it is rotated. When the log file grows past this size, it is rolled over
    and a fresh file is started.

    This only applies when logging to a file; it has no effect on console
    logging. Set to ``0`` to disable rotation entirely and let the log grow
    without bound.

    **Default**: ``5242880`` (5 MiB)

    **Example**:

    .. tabs::

        .. group-tab:: YAML

            .. code-block:: yaml

                options:
                  log_max_bytes: 10485760  # 10 MiB

        .. group-tab:: TOML

            .. code-block:: toml

                [options]
                log_max_bytes = 10485760  # 10 MiB

        .. group-tab:: JSON

            .. code-block:: json

                {
                    "options": {
                        "log_max_bytes": 10485760
                    }
                }

.. _log_backup_count_option:

.. option:: log_backup_count

    The number of rotated log files to keep. When :option:`log_file` is
    rotated, older files are named with a numeric suffix (e.g.
    ``exosphere.log.1``), and any beyond this count are deleted.

    With the defaults, the total disk used by logs is therefore essentially
    ``log_max_bytes * (log_backup_count + 1)``.

    This must be a positive integer of ``1`` or more, any lower value is
    rejected as invalid.

    To disable rotation entirely, set :option:`log_max_bytes` to ``0`` instead.

    **Default**: ``3``

    **Example**:

    .. tabs::

        .. group-tab:: YAML

            .. code-block:: yaml

                options:
                  log_backup_count: 5

        .. group-tab:: TOML

            .. code-block:: toml

                [options]
                log_backup_count = 5

        .. group-tab:: JSON

            .. code-block:: json

                {
                    "options": {
                        "log_backup_count": 5
                    }
                }

.. option:: history_file

    A filesystem path to a file where Exosphere will store the REPL history.
    If not set, Exosphere will use the platform default and name the
    file ``repl_history``.

    This file is used to persist the command history across executions of Exosphere,
    allowing you to navigate through or search for previously executed commands.

    **Default**: (Platform Default)

    **Example**:

    .. tabs::

        .. group-tab:: YAML

            .. code-block:: yaml

                options:
                  history_file: /home/alice/.exosphere_history

        .. group-tab:: TOML

            .. code-block:: toml

                [options]
                history_file = "/home/alice/.exosphere_history"

        .. group-tab:: JSON

            .. code-block:: json

                {
                    "options": {
                        "history_file": "/home/alice/.exosphere_history"
                    }
                }

.. _history_max_entries_option:

.. option:: history_max_entries

    The maximum number of entries to retain in the :option:`history_file`.
    The history file is trimmed to the most recent entries when the
    interactive REPL starts, so it cannot grow without bound.

    Set to ``0`` to disable trimming and keep unlimited history.

    **Default**: ``1000``

    **Example**:

    .. tabs::

        .. group-tab:: YAML

            .. code-block:: yaml

                options:
                  history_max_entries: 5000

        .. group-tab:: TOML

            .. code-block:: toml

                [options]
                history_max_entries = 5000

        .. group-tab:: JSON

            .. code-block:: json

                {
                    "options": {
                        "history_max_entries": 5000
                    }
                }

.. _cache_autosave_option:

.. option:: cache_autosave

    Automatically save the state to disk when changes are made.
    This is on by default, and probably should not be turned off
    unless you have a very specific reason to do so.

    If this is disabled, you will need to manually save the state
    with ``inventory save`` from the interactive mode for changes
    to systems state to persist across executions.

    See :doc:`cachefile` for more details on the cache file

    .. caution::

        Note that a manual save can only be done in interactive mode.
        Running Exosphere in non-interactive mode with this option disabled
        will not save the state at all between executions.


    **Default**: ``true``

    **Example**:

    .. tabs::

        .. group-tab:: YAML

            .. code-block:: yaml

                options:
                  cache_autosave: false

        .. group-tab:: TOML

            .. code-block:: toml

                [options]
                cache_autosave = false

        .. group-tab:: JSON

            .. code-block:: json

                {
                    "options": {
                        "cache_autosave": false
                    }
                }


.. option:: cache_autopurge

    Whether or not to automatically remove hosts from cache when they are
    removed from the configuration file.

    If :option:`cache_autosave` is set to False, **this option has no effect**.

    .. admonition:: Note

        If **all** of the hosts are removed from the configuration file,
        Exosphere will err on the side of caution and leave the cache file alone,
        regardless of this setting.

        This is to prevent accidental cache loss if the wrong configuration is
        loaded, or if the file is made temporarily inaccessible.

        If you really want to remove all the contents of the cache file,
        use the ``exosphere inventory clear`` command.

    **Default**: ``true``

    **Example**:

    .. tabs::

        .. group-tab:: YAML

            .. code-block:: yaml

                options:
                  cache_autopurge: false

        .. group-tab:: TOML

            .. code-block:: toml

                [options]
                cache_autopurge = false

        .. group-tab:: JSON

            .. code-block:: json

                {
                    "options": {
                        "cache_autopurge": false
                    }
                }

.. _cache_file_option:

.. option:: cache_file

    A filesystem path to a file where Exosphere will store the state of the inventory.
    If not set, Exosphere will use the platform default location for the cache file.

    This file is used to persist the state of the inventory across executions,
    including the results of discovery, host updates, last check times, and more.

    The file is lzma compressed to save space, and is not human readable.

    It can be cleared with the ``exosphere inventory clear`` command, without
    having to delete the file manually.

    See :doc:`cachefile` for more details on the cache file

    **Default**: (Platform Default)

    **Example**:

    .. tabs::

        .. group-tab:: YAML

            .. code-block:: yaml

                options:
                  cache_file: /home/alice/tmp/exosphere.db

        .. group-tab:: TOML

            .. code-block:: toml

                [options]
                cache_file = "/home/alice/tmp/exosphere.db"

        .. group-tab:: JSON

            .. code-block:: json

                {
                    "options": {
                        "cache_file": "/home/alice/tmp/exosphere.db"
                    }
                }

.. _stale_threshold_option:

.. option:: stale_threshold

    The number of seconds after which a host's data is considered stale.

    If a host has not been refreshed in this many seconds, an asterisk or
    similar flag will be shown in the UIs to indicate that the update count
    may not be accurate, and that the host should be refreshed.

    The default is 24 hours, which is reasonable, but you may want a shorter
    or longer span of time depending on your environment.

    **Default**: ``86400`` (24 hours)

    **Example**:

    .. tabs::

        .. group-tab:: YAML

            .. code-block:: yaml

                options:
                  stale_threshold: 3600  # 1 hour

        .. group-tab:: TOML

            .. code-block:: toml

                [options]
                stale_threshold = 3600  # 1 hour

        .. group-tab:: JSON

            .. code-block:: json

                {
                    "options": {
                        "stale_threshold": 3600
                    }
                }

.. _default_timeout_option:

.. option:: default_timeout

    The number of seconds to wait for a response from a host over SSH.

    This is the maximum time Exosphere will wait for a response from a host
    before timing out, flagging the host as offline, or raising an error condition.

    This is useful for hosts that may be slow to respond, or if you have
    a large number of hosts and want to avoid long delays on That One Host.

    .. admonition:: Note

        This is the global value that, by default, applies to all hosts.
        It can be overridden on a per-host basis in the inventory, inside
        the `hosts` section, via :option:`connect_timeout`.


    **Default**: ``10`` (seconds)

    **Example**:

    .. tabs::

        .. group-tab:: YAML

            .. code-block:: yaml

                options:
                  default_timeout: 60  # 1 minute

        .. group-tab:: TOML

            .. code-block:: toml

                [options]
                default_timeout = 60  # 1 minute

        .. group-tab:: JSON

            .. code-block:: json

                {
                    "options": {
                        "default_timeout": 60
                    }
                }

.. _default_username_option:

.. option:: default_username

    The default SSH username to use when connecting to hosts.
    This is useful if you have a common username across all hosts,
    and do not want to specify it for each host in the inventory.

    If not set, Exosphere will try to use the current user's username
    on the system where Exosphere is running.

    .. admonition:: Note

        This is the global value that, by default, applies to all hosts.
        It can be overridden on a per-host basis in the inventory, inside
        the `hosts` section, via :option:`username`.

    **Default**: ``None`` (Current user's username)

    **Example**:

    .. tabs::

        .. group-tab:: YAML

            .. code-block:: yaml

                options:
                  default_username: alice  # Use 'alice' as the default SSH username

        .. group-tab:: TOML

            .. code-block:: toml

                [options]
                default_username = "alice"  # Use 'alice' as the default SSH username

        .. group-tab:: JSON

            .. code-block:: json

                {
                    "options": {
                        "default_username": "alice"
                    }
                }

.. _default_ssh_locale_option:

.. option:: default_ssh_locale

    The locale forced on every command Exosphere runs on a remote host.

    Some exosphere providers have to rely on parsing the human-readable output
    of remote commands to determine the state of the host.

    Since many of these commands are subject to gettext translation, which
    changes on the remote host depending on the locale, this can lead to
    non-deterministic results.

    In order to prevent this scenario, Exosphere, by default, forces the locale
    on the remote host to ``C`` (POSIX locale), which is guaranteed to be available
    and will always produce canonical, untranslated output.

    A reasonable alternative, if available, is ``C.UTF-8``.

    .. attention::
        Unless you have a very specific reason to do so, we do not recommend
        changing this value from the default, as it may break functionality in
        some providers.

    **Default**: ``C``

    **Example**:

    .. tabs::

        .. group-tab:: YAML

            .. code-block:: yaml

                options:
                  default_ssh_locale: C.UTF-8

        .. group-tab:: TOML

            .. code-block:: toml

                [options]
                default_ssh_locale = "C.UTF-8"

        .. group-tab:: JSON

            .. code-block:: json

                {
                    "options": {
                        "default_ssh_locale": "C.UTF-8"
                    }
                }

.. _max_threads_option:

.. option:: max_threads

    The maximum number of threads to use for parallel operations.

    This is the maximum number of threads Exosphere will use for parallel
    operations, such as discovery, ping, checking for updates or synchronizing
    repositories.

    This can be useful to limit the number of concurrent operations, especially
    in environments with many hosts, to avoid overwhelming the network or the computer
    where you are running Exosphere.

    The default is a generous 15 threads, which you may want to lower depending on
    your context.

    **Default**: ``15``

    **Example**:

    .. tabs::

        .. group-tab:: YAML

            .. code-block:: yaml

                options:
                  max_threads: 5  # Limit parallel actions to 5 threads

        .. group-tab:: TOML

            .. code-block:: toml

                [options]
                max_threads = 5  # Limit parallel actions to 5 threads

        .. group-tab:: JSON

            .. code-block:: json

                {
                    "options": {
                        "max_threads": 5
                    }
                }

.. _ssh_pipelining_option:

.. option:: ssh_pipelining

    Enable SSH connection pipelining to improve performance when connecting
    to multiple hosts.

    By default, Exosphere closes connections automatically after each Host
    operation (sync, discover, refresh, ping etc).

    Enabling this option will leave connections open for reuse across multiple
    operations, significantly improving performance in workflows that involve
    multiple operations on the same hosts.

    Idle connections will be closed automatically after a certain period of time,
    configurable via :option:`ssh_pipelining_lifetime`, and reaped periodically
    via :option:`ssh_pipelining_reap_interval`.

    **Default**: ``false``

    **Example**:

    .. tabs::

        .. group-tab:: YAML

            .. code-block:: yaml

                options:
                  ssh_pipelining: true

        .. group-tab:: TOML

            .. code-block:: toml

                [options]
                ssh_pipelining = true

        .. group-tab:: JSON

            .. code-block:: json

                {
                    "options": {
                        "ssh_pipelining": true
                    }
                }

.. _ssh_pipelining_lifetime_option:

.. option:: ssh_pipelining_lifetime

    The number of seconds an idle SSH connection will be kept open
    when SSH pipelining is enabled.

    This setting only applies if :option:`ssh_pipelining` is set to ``true``.

    When a connection has been idle (unused) for longer than this duration,
    it will be closed by the connection reaper thread.

    .. attention::

        Setting this value too low may negate the performance benefits
        of SSH pipelining, as connections will be closed before they
        can be reused.

        You will get a warning in the logs to this effect if you configure
        this value to be less than ``60`` seconds. Consider setting this
        to at least the longest time an operation may take on your slowest host,
        as a baseline.

        Otherwise, you can leave this at the default value.


    **Default**: ``300`` (5 minutes)

    **Example**:

    .. tabs::

        .. group-tab:: YAML

            .. code-block:: yaml

                options:
                  ssh_pipelining_lifetime: 240  # 4 minutes

        .. group-tab:: TOML

            .. code-block:: toml

                [options]
                ssh_pipelining_lifetime = 240  # 4 minutes

        .. group-tab:: JSON

            .. code-block:: json

                {
                    "options": {
                        "ssh_pipelining_lifetime": 240
                    }
                }

.. _ssh_pipelining_reap_interval_option:

.. option:: ssh_pipelining_reap_interval

    The interval (in seconds) at which the reaper thread wakes up to check for
    and close idle SSH connections when SSH pipelining is enabled.

    This setting only applies if :option:`ssh_pipelining` is set to ``true``.

    .. attention::

        Setting this value too high will cause idle connections to remain
        open for longer than necessary, potentially extending their lifetime
        beyond :option:`ssh_pipelining_lifetime` by up to this interval duration.

        Conversely, having the reaper thread wake up frequently has negligible overhead
        since it will only perform work when there are actually idle connections to close.

        You should consider that this value effectively adds up to this amount of time
        to the actual lifetime of idle connections. For example, with a lifetime of
        300s and an interval of 30s, connections may remain open for up to 330s.

        If in doubt, leave this at the default value.

    **Default**: ``30`` (30 seconds)

    **Example**:

    .. tabs::

        .. group-tab:: YAML

            .. code-block:: yaml

                options:
                  ssh_pipelining_reap_interval: 60  # 1 minute

        .. group-tab:: TOML

            .. code-block:: toml

                [options]
                ssh_pipelining_reap_interval = 60  # 1 minute

        .. group-tab:: JSON

            .. code-block:: json

                {
                    "options": {
                        "ssh_pipelining_reap_interval": 60
                    }
                }

.. _update_checks_option:

.. option:: update_checks

    Whether or not Exosphere is allowed to check for updates on PyPI.

    Exosphere currently doesn't perform any automatic update checks, only
    when explicitly asked to via the ``version check`` command.

    This option allows you to disable that functionality entirely.

    This is intended for:

    - Environments that have stringent policies about external connectivity
    - Environments where Exosphere is installed by other means than PyPI
    - Brave souls who would package Exosphere in the context of an OS distribution.

    In all of these contexts, the ``version check`` command will be disabled
    and print a clear message instead.

    If in doubt, leave this at the default value.

    **Default**: ``true``

    **Example**:

    .. tabs::

        .. group-tab:: YAML

            .. code-block:: yaml

                options:
                  update_checks: false

        .. group-tab:: TOML

            .. code-block:: toml

                [options]
                update_checks = false

        .. group-tab:: JSON

            .. code-block:: json

                {
                    "options": {
                        "update_checks": false
                    }
                }

.. _no_banner_option:

.. option:: no_banner

    Do not show the ascii banner when starting Exosphere in interactive mode.
    Setting this to ``true`` will suppress the banner entirely, showing only
    the welcome text and the prompt.

    .. tip::

        This can be set contextually with the environment variable
        ``EXOSPHERE_OPTIONS_NO_BANNER`` set to ``true``.
        For more details see :ref:`config_env_vars`.

    **Default**: ``false``

    **Example**:

    .. tabs::

        .. group-tab:: YAML

            .. code-block:: yaml

                options:
                  no_banner: true

        .. group-tab:: TOML

            .. code-block:: toml

                [options]
                no_banner = true

        .. group-tab:: JSON

            .. code-block:: json

                {
                    "options": {
                        "no_banner": true
                    }
                }

.. _editor_option:

.. option:: editor

    The editor command used by the :ref:`config edit <config_edit_cmd>` command
    to open the configuration file.

    When unset, Exosphere falls back to the ``VISUAL`` environment variable,
    then ``EDITOR``, and finally a platform default (``notepad`` on Windows,
    ``vi`` everywhere else).

    The value is a command that may include arguments.

    .. attention::

        For graphical editors that return immediately, pass the appropriate "wait"
        or "block" flag so Exosphere can validate the file once you are done editing
        (for example: ``code --wait``, ``subl -w``, or ``gvim -f``).

        On Windows, a path that contains spaces must be quoted within the value,
        or it will be ambiguous and fail to resolve. See the examples below for
        the correct form in each format. A bare command found on ``PATH`` (like
        ``code --wait``) needs no quoting.

    .. tip::

        This can be set contextually with the environment variable
        ``EXOSPHERE_OPTIONS_EDITOR``.
        For more details see :ref:`config_env_vars`.

    **Default**: ``(Unset)`` (use ``VISUAL`` / ``EDITOR`` / platform default)

    **Example**:

    .. tabs::

        .. group-tab:: YAML

            Command on path

            .. code-block:: yaml

                options:
                  editor: "code --wait"


            Windows path with spaces and arguments

            .. code-block:: yaml

                options:
                  editor: '"C:\Program Files\Editor\ed.exe" --wait'

        .. group-tab:: TOML

            Command on path

            .. code-block:: toml

                [options]
                editor = "code --wait"

            Windows path with spaces and arguments

            .. code-block:: toml

                [options]
                editor = '"C:\Program Files\Editor\ed.exe" --wait'

        .. group-tab:: JSON

            Command on path

            .. code-block:: json

                {
                    "options": {
                        "editor": "code --wait"
                    }
                }


            Windows path with spaces and arguments

            .. code-block:: json

                {
                    "options": {
                        "editor": "\"C:\\Program Files\\Editor\\ed.exe\" --wait"
                    }
                }

.. _config_inventory:

Inventory
---------

The second section of the configuration file is the `Hosts` section, which is
referred to throughout the documentation as **The Inventory**.

The `Hosts` section contains a list of hosts that Exosphere will connect to, as well
as their connection parameters and any specific option for each host.

Host entries are structured as follows. This example describes two hosts, one of which
has a custom connection timeout value set, overriding :option:`default_timeout`.

.. tabs::
    .. group-tab:: YAML

        .. code-block:: yaml

            hosts:
              - name: myhost
                ip: myhost.example.com
              - name: anotherhost
                ip: 127.0.1.8
                connect_timeout: 30

    .. group-tab:: TOML

        .. code-block:: toml

            [[hosts]]
            name = "myhost"
            ip = "myhost.example.com"

            [[hosts]]
            name = "anotherhost"
            ip = "127.0.1.8"
            connect_timeout = 30


    .. group-tab:: JSON

        .. code-block:: json

            {
                "hosts": [
                    {
                        "name": "myhost",
                        "ip": "myhost.example.com"
                    },
                    {
                        "name": "anotherhost",
                        "ip": "127.0.1.8",
                        "connect_timeout": 30
                    }
                ]
            }

.. _hosts_options_section:

**Mandatory** fields for each host entry are:

- :option:`name`: The name of the host, which is used to identify it in the UI and logs.
- :option:`ip`: The address of the host, which can be a hostname or an IP address.

*Optional* fields for each host entry include:

- :option:`port`: The SSH port to connect to the host. Defaults to 22.
- :option:`username`: An optional SSH username to use when connecting to the host
- :option:`description`: A short string describing the host, to be displayed in UIs
- :option:`connect_timeout`: The number of seconds to wait for a response from the host over SSH
- :option:`sudo_policy`: The sudo policy to use when running commands on the host
- :option:`ssh_locale`: The locale forced on remote commands run against the host

Below is the detailed list of all available host options and their defaults.

.. _hosts_name_option:

.. option:: name

    The name of the host, which uniquely identifies the host within the inventory.
    It is recommended to keep this to a short string rather than a fully qualified domain name,
    although it can be arbitrary.

    .. attention::

        The **name** field has a unicity constraint within the inventory!
        You cannot have two hosts with the same name value, and Exosphere will
        inform you of this if it is the case, before promptly refusing to load the
        configuration file.

    **Mandatory**: Yes

    **Example**:

    .. tabs::

        .. group-tab:: YAML

            .. code-block:: yaml

                hosts:
                  - name: myhost

        .. group-tab:: TOML

            .. code-block:: toml

                [[hosts]]
                name = "myhost"

        .. group-tab:: JSON

            .. code-block:: json

                {
                    "hosts": [
                        {
                            "name": "myhost"
                        }
                    ]
                }

.. _hosts_ip_option:

.. option:: ip

    The IP address or hostname of the host to connect to over SSH.
    This can be a fully qualified domain name, an IP address, or a short hostname,
    so long as it resolves.
    It is recommended to use a fully qualified domain name or an IP address
    to avoid issues with DNS resolution.

    .. attention::

        The **ip** field must not contain the ``@`` character. To specify a username,
        use the :option:`username` field instead.

    **Mandatory**: Yes

    **Example**:

    .. tabs::

        .. group-tab:: YAML

            .. code-block:: yaml

                hosts:
                  - name: myhost
                    ip: myhost.example.com

        .. group-tab:: TOML

            .. code-block:: toml

                [[hosts]]
                name = "myhost"
                ip = "myhost.example.com"

        .. group-tab:: JSON

            .. code-block:: json

                {
                    "hosts": [
                        {
                            "name": "myhost",
                            "ip": "myhost.example.com"
                        }
                    ]
                }

.. _hosts_port_option:

.. option:: port

    The SSH port to connect to the host. This is optional, and defaults to 22.
    If your host uses a different port for SSH, you can specify it here.

    **Default**: ``22``

    **Example**:

    .. tabs::

        .. group-tab:: YAML

            .. code-block:: yaml

                hosts:
                  - name: myhost
                    ip: myhost.example.com
                    port: 2222

        .. group-tab:: TOML

            .. code-block:: toml

                [[hosts]]
                name = "myhost"
                ip = "myhost.example.com"
                port = 2222

        .. group-tab:: JSON

            .. code-block:: json

                {
                    "hosts": [
                        {
                            "name": "myhost",
                            "ip": "myhost.example.com",
                            "port": 2222
                        }
                    ]
                }

.. option:: username

    An optional SSH username to use when connecting to the host.

    .. admonition:: Note

        This option has precedence over :option:`default_username`

    This is useful if you need to connect to a particular host with a different
    user than the one you are running Exosphere as, or the one configured
    globally in :option:`default_username`.

    **Default**: Current user's username

    **Example**:

    .. tabs::

        .. group-tab:: YAML

            .. code-block:: yaml

                hosts:
                  - name: myhost
                    ip: myhost.example.com
                    username: alice

        .. group-tab:: TOML

            .. code-block:: toml

                [[hosts]]
                name = "myhost"
                ip = "myhost.example.com"
                username = "alice"

        .. group-tab:: JSON

            .. code-block:: json

                {
                    "hosts": [
                        {
                            "name": "myhost",
                            "ip": "myhost.example.com",
                            "username": "alice"
                        }
                    ]
                }

.. option:: description

    A short string describing the host, to be displayed in UIs.
    This is optional, but can be useful to provide additional context
    about the host, such as its role or purpose.

    **Default**: ``None``

    **Example**:

    .. tabs::

        .. group-tab:: YAML

            .. code-block:: yaml

                hosts:
                  - name: myhost
                    ip: myhost.example.com
                    description: "Web Server"

        .. group-tab:: TOML

            .. code-block:: toml

                [[hosts]]
                name = "myhost"
                ip = "myhost.example.com"
                description = "Web Server"

        .. group-tab:: JSON

            .. code-block:: json

                {
                    "hosts": [
                        {
                            "name": "myhost",
                            "ip": "myhost.example.com",
                            "description": "Web Server"
                        }
                    ]
                }

.. _connect_timeout_host_option:

.. option:: connect_timeout

    The number of seconds to wait for a response from the host over SSH.
    This is optional, and defaults to the value set in :option:`default_timeout`.

    If you have hosts that are particularly slow to respond, you can increase this value
    on a per-host basis.

    **Default**: Value of :option:`default_timeout`

    **Example**:

    .. tabs::

        .. group-tab:: YAML

            .. code-block:: yaml

                hosts:
                  - name: myhost
                    ip: myhost.example.com
                    connect_timeout: 30  # 30 seconds

        .. group-tab:: TOML

            .. code-block:: toml

                [[hosts]]
                name = "myhost"
                ip = "myhost.example.com"
                connect_timeout = 30  # 30 seconds

        .. group-tab:: JSON

            .. code-block:: json

                {
                    "hosts": [
                        {
                            "name": "myhost",
                            "ip": "myhost.example.com",
                            "connect_timeout": 30
                        }
                    ]
                }

.. _hosts_sudo_policy_option:

.. option:: sudo_policy

    The sudo policy to use when running commands on the host.

    .. admonition:: Note

        This option has precedence over the global option,
        see :option:`default_sudo_policy` for documentation and
        usage details.


    **Default**: Value of :option:`default_sudo_policy`

    **Example**:

    .. tabs::

        .. group-tab:: YAML

            .. code-block:: yaml

                hosts:
                  - name: myhost
                    ip: myhost.example.com
                    sudo_policy: nopasswd

        .. group-tab:: TOML

            .. code-block:: toml

                [[hosts]]
                name = "myhost"
                ip = "myhost.example.com"
                sudo_policy = "nopasswd"

        .. group-tab:: JSON

            .. code-block:: json

                {
                    "hosts": [
                        {
                            "name": "myhost",
                            "ip": "myhost.example.com",
                            "sudo_policy": "nopasswd"
                        }
                    ]
                }

.. _hosts_ssh_locale_option:

.. option:: ssh_locale

    The locale forced on remote commands run against this host.

    .. admonition:: Note

        This option has precedence over the global option,
        see :option:`default_ssh_locale` for documentation and
        usage detail.

    .. attention::

        Unless you have a very specific reason to do so, we do not recommend
        changing this value from the default, as it may break functionality in
        some providers.


    **Default**: Value of :option:`default_ssh_locale`

    **Example**:

    .. tabs::

        .. group-tab:: YAML

            .. code-block:: yaml

                hosts:
                  - name: myhost
                    ip: myhost.example.com
                    ssh_locale: C.UTF-8

        .. group-tab:: TOML

            .. code-block:: toml

                [[hosts]]
                name = "myhost"
                ip = "myhost.example.com"
                ssh_locale = "C.UTF-8"

        .. group-tab:: JSON

            .. code-block:: json

                {
                    "hosts": [
                        {
                            "name": "myhost",
                            "ip": "myhost.example.com",
                            "ssh_locale": "C.UTF-8"
                        }
                    ]
                }

.. _yaml: https://yaml.org/
.. _toml: https://toml.io/en/
.. _json: https://www.json.org/
