From 5d8c63aec125a55a67c435fd590879d1f64bd756 Mon Sep 17 00:00:00 2001 From: Stephen Simpson Date: Fri, 28 Aug 2026 09:18:51 -0500 Subject: [PATCH 1/5] docs: point operator references at ascender-operator The docsite linked upstream ansible/awx-operator for install, migration, upgrade, and uninstall, and referred to the AWX Operator documentation for mesh ingress, custom receptor certs, and private registry EEs. All four doc paths exist at the same locations in ctrliq/ascender-operator on devel. The readthedocs links become GitHub links because ascender-operator has no published docs site yet. Co-Authored-By: Claude Opus 5 (1M context) --- docs/docsite/rst/administration/init_script.rst | 8 ++++---- docs/docsite/rst/administration/instances.rst | 6 +++--- docs/docsite/rst/administration/performance.rst | 2 +- docs/docsite/rst/administration/troubleshooting.rst | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/docsite/rst/administration/init_script.rst b/docs/docsite/rst/administration/init_script.rst index cc76e1da7..ca67c424e 100644 --- a/docs/docsite/rst/administration/init_script.rst +++ b/docs/docsite/rst/administration/init_script.rst @@ -3,15 +3,15 @@ Starting, Stopping, and Restarting Ascender --------------------------------------------- -To install Ascender: https://github.com/ansible/awx-operator/tree/devel/docs/installation +To install Ascender: https://github.com/ctrliq/ascender-operator/tree/devel/docs/installation .. these instructions will be ported over to here in the near future (TBD) -To migrate from an old Ascender to a new Ascender instance: https://github.com/ansible/awx-operator/blob/devel/docs/migration/migration.md +To migrate from an old Ascender to a new Ascender instance: https://github.com/ctrliq/ascender-operator/blob/devel/docs/migration/migration.md .. these instructions will be ported over to here in the near future (TBD) -To upgrade you Ascender instance: https://github.com/ansible/awx-operator/blob/devel/docs/upgrade/upgrading.md +To upgrade you Ascender instance: https://github.com/ctrliq/ascender-operator/blob/devel/docs/upgrade/upgrading.md .. these instructions will be ported over to here in the near future (TBD) @@ -21,7 +21,7 @@ To restart an Ascender instance, you must first kill the container and restart i .. these instructions will need to be fleshed out (TBD) -To uninstall you Ascender instance: https://github.com/ansible/awx-operator/blob/devel/docs/uninstall/uninstall.md +To uninstall you Ascender instance: https://github.com/ctrliq/ascender-operator/blob/devel/docs/uninstall/uninstall.md .. these instructions will be ported over to here in the near future (TBD) diff --git a/docs/docsite/rst/administration/instances.rst b/docs/docsite/rst/administration/instances.rst index a053326e4..e4f45a3a2 100644 --- a/docs/docsite/rst/administration/instances.rst +++ b/docs/docsite/rst/administration/instances.rst @@ -149,7 +149,7 @@ Below are sample values used to configure each node in a mesh ingress topology: - [hop node] -In order to create a mesh ingress for Ascender, see the `Mesh Ingress `_ chapter of the AWX Operator Documentation for information on setting up this type of topology. The last step is to create a remote execution node and add the execution node to an instance group in order for it to be used in your job execution. Whatever execution environment image used to run a playbook needs to be accessible for your remote execution node. Everything you are using in your playbook also needs to be accessible from this remote execution node. +In order to create a mesh ingress for Ascender, see the `Mesh Ingress `_ chapter of the Ascender Operator documentation for information on setting up this type of topology. The last step is to create a remote execution node and add the execution node to an instance group in order for it to be used in your job execution. Whatever execution environment image used to run a playbook needs to be accessible for your remote execution node. Everything you are using in your playbook also needs to be accessible from this remote execution node. .. image:: ../common/images/instances-job-template-using-remote-execution-ig.png :alt: Job template using the instance group with the execution node to run jobs. @@ -334,13 +334,13 @@ The example health check shows the status updates with an error on node 'one': Using a custom Receptor CA --------------------------- -Refer to the AWX Operator Documentation, `Custom Receptor CA `_ for detail. +Refer to the Ascender Operator documentation, `Custom Receptor CA `_ for detail. Using a private image for the default EE ------------------------------------------ -Refer to the AWX Operator Documentation on `Default execution environments from private registries `_ for detail. +Refer to the Ascender Operator documentation on `Default execution environments from private registries `_ for detail. Troubleshooting diff --git a/docs/docsite/rst/administration/performance.rst b/docs/docsite/rst/administration/performance.rst index a806ee767..0690ba011 100644 --- a/docs/docsite/rst/administration/performance.rst +++ b/docs/docsite/rst/administration/performance.rst @@ -206,7 +206,7 @@ Capacity planning for Operator based Deployments .. index:: pair: Operator; deployment -For Operator based deployments, refer to `Ansible AWX Operator documentation `_. +For Operator based deployments, refer to `Ascender Operator documentation `_. Monitoring Ascender diff --git a/docs/docsite/rst/administration/troubleshooting.rst b/docs/docsite/rst/administration/troubleshooting.rst index 39b97b560..d27e79b2b 100644 --- a/docs/docsite/rst/administration/troubleshooting.rst +++ b/docs/docsite/rst/administration/troubleshooting.rst @@ -33,7 +33,7 @@ Error logging and extra settings Ascender server errors are streamed and not logged, however you may be able to pass them in on the Ascender spec file. -With ``extra_settings``, you can pass multiple custom settings via the ``awx-operator``. The parameter ``extra_settings`` will be appended to the ``/etc/tower/settings.py`` file and can be an alternative to the ``extra_volumes`` parameter. +With ``extra_settings``, you can pass multiple custom settings via the Ascender Operator. The parameter ``extra_settings`` will be appended to the ``/etc/tower/settings.py`` file and can be an alternative to the ``extra_volumes`` parameter. +----------------+----------------+---------+ | Name | Description | Default | From 7355b0792e0af254fcbcc18daf711634522ca6e6 Mon Sep 17 00:00:00 2001 From: Stephen Simpson Date: Fri, 28 Aug 2026 09:40:52 -0500 Subject: [PATCH 2/5] docs: add an installation section The docsite had no installation section. index.rst carried no entry, quickstart/setup.rst is the Settings page, and quick_start.rst told the reader to install Ascender without a link. The only install content was a single line on the Starting, Stopping, and Restarting page. Adds an Install section covering the ascender-install path and a manual Kustomize install of the operator and the Ascender resource, and points the quickstart at it. The manual page follows the resource that ascender-install generates, so it includes postgres_data_volume_init for root-owned volumes and CSRF_TRUSTED_ORIGINS, both of which a bare operator install needs. Co-Authored-By: Claude Opus 5 (1M context) --- docs/docsite/rst/index.rst | 6 + docs/docsite/rst/installation/index.rst | 24 ++ docs/docsite/rst/installation/install.rst | 252 ++++++++++++++++++ .../rst/installation/manual_install.rst | 186 +++++++++++++ .../rst/installation/quick_start_k3s.rst | 107 ++++++++ docs/docsite/rst/quickstart/quick_start.rst | 2 +- 6 files changed, 576 insertions(+), 1 deletion(-) create mode 100644 docs/docsite/rst/installation/index.rst create mode 100644 docs/docsite/rst/installation/install.rst create mode 100644 docs/docsite/rst/installation/manual_install.rst create mode 100644 docs/docsite/rst/installation/quick_start_k3s.rst diff --git a/docs/docsite/rst/index.rst b/docs/docsite/rst/index.rst index 36e5d017c..d7d88d9f9 100644 --- a/docs/docsite/rst/index.rst +++ b/docs/docsite/rst/index.rst @@ -15,6 +15,12 @@ Ascender helps teams manage complex multi-tier deployments by adding control, kn contributor/index +.. toctree:: + :maxdepth: 2 + :caption: Install + + installation/index + .. toctree:: :maxdepth: 2 :caption: Users diff --git a/docs/docsite/rst/installation/index.rst b/docs/docsite/rst/installation/index.rst new file mode 100644 index 000000000..d76ddb0c1 --- /dev/null +++ b/docs/docsite/rst/installation/index.rst @@ -0,0 +1,24 @@ +.. _in_start: + +===================== +Installing Ascender +===================== + +Deploy Ascender on Kubernetes, from a single-node evaluation to a production cluster. + +This guide applies to the latest version of Ascender only. +The content in this guide is updated frequently and might contain functionality that is not available in previous versions. +Likewise content in this guide can be removed or replaced if it applies to functionality that is no longer available in the latest version. + +Ascender runs on Kubernetes and is managed by the `Ascender Operator `_. +Most deployments should use `ascender-install `_, which provisions the cluster where supported, deploys the operator, and creates the Ascender resource from a single configuration file. +If you manage your own cluster or deploy through GitOps tooling, you can install the operator and create the Ascender resource yourself. + +.. toctree:: + :maxdepth: 2 + :numbered: + + self + quick_start_k3s + install + manual_install diff --git a/docs/docsite/rst/installation/install.rst b/docs/docsite/rst/installation/install.rst new file mode 100644 index 000000000..108a63328 --- /dev/null +++ b/docs/docsite/rst/installation/install.rst @@ -0,0 +1,252 @@ +.. _in_install: + +************************* +Installation Guide +************************* + +.. index:: + single: installation + pair: installation; ascender-install + pair: installation; configuration + +`ascender-install `_ is the supported way to deploy Ascender. It runs Ansible under the hood, driven by a single configuration file, and handles cluster provisioning where supported, the Ascender Operator, and the Ascender resource itself. + +To evaluate Ascender on a single machine, start with :ref:`in_quick_start_k3s`. + +What the installer does +======================== + +Running ``./setup.sh`` performs these steps on your behalf: + +- Installs its own dependencies, including ansible-core, the required collections, and the Python Kubernetes client +- Provisions the cluster, on K3s and RKE2 only, when ``kube_install`` is set +- Deploys the Ascender Operator with Kustomize, pinned to ``ASCENDER_OPERATOR_VERSION`` +- Creates the namespace, the administrator password secret, and any TLS, custom CA, or external database secrets your configuration calls for +- Creates the Ascender resource that the operator reconciles into a running deployment + +Understanding these steps is useful even if you never run the installer, because :ref:`in_manual_install` covers doing them yourself. + +Requirements +============= + +The machine you run the installer from needs Rocky Linux 8 or 9 on x86_64, ``git``, and root or sudo access. The installer refuses to run on other distributions and on non-x86_64 hosts. Cloud platforms require Rocky Linux 9 and the relevant CLI tool, authenticated. + +For on-premise deployments on K3s or RKE2, this can be the same machine that runs the cluster. For EKS, GKE, and AKS, use a small administrative host. + +Getting started +================ + +Clone the installer:: + + git clone https://github.com/ctrliq/ascender-install.git + cd ascender-install + +Create ``custom.config.yml`` with the settings for your deployment. Use ``default.config.yml`` as a reference for the available options rather than a starting point, as it contains settings for every platform and needs heavy editing. The repository also ships ``config_vars.sh``, which generates a configuration file through a series of prompts. + +Install with:: + + sudo ./setup.sh + +Platforms +========== + +**K3s** is covered in :ref:`in_quick_start_k3s`. Set ``kube_install: true`` and the installer creates the cluster. + +**RKE2** suits production and supports single-node and highly available clusters. The installer does not create an RKE2 cluster, so build it first and then run the installer against it. + +**EKS, GKE, and AKS** each require their own CLI tool, IAM or role configuration, and a DNS zone. Cloud installs require Rocky Linux 9 on the administrative host. + +**DKP** needs one extra setting, ``DKP_CLUSTER_NAME``, naming the cluster to deploy to or create. + +**OCP** follows the common configuration. Check ``default.config.yml`` for OpenShift-specific defaults. + +Upgrading +========== + +Pull the latest installer first so you pick up any fixes, then raise ``ASCENDER_VERSION``, and ``ASCENDER_OPERATOR_VERSION`` if it also changed, and re-run:: + + git pull + sudo ./setup.sh + +The upgrade is carried out by the Ascender Operator. + +.. note:: + + The operator and Ascender are released independently. Ascender releases are at `ctrliq/ascender `_ and operator releases at `ctrliq/ascender-operator `_. + +Configuration reference +======================== + +Kubernetes platform +-------------------- + +.. list-table:: + :widths: 30 20 50 + :header-rows: 1 + + * - Variable + - Default + - Description + * - ``k8s_platform`` + - ``k3s`` + - Target platform. One of ``k3s``, ``eks``, ``aks``, ``gke``, ``rke2``, ``dkp``, ``ocp`` + * - ``k8s_lb_protocol`` + - ``http`` + - Load balancer protocol. Set to ``https`` to enable TLS, which requires the certificate settings below + * - ``download_kubeconfig`` + - ``false`` + - Copy the kubeconfig from the target host to ``~/.kube/config`` on the installing machine + +Ascender application +--------------------- + +.. list-table:: + :widths: 30 20 50 + :header-rows: 1 + + * - Variable + - Default + - Description + * - ``ASCENDER_HOSTNAME`` + - ``ascender.example.com`` + - DNS-resolvable hostname for the web interface. Required + * - ``ASCENDER_DOMAIN`` + - ``example.com`` + - Base domain for all components. Required on EKS, GKE, and AKS, and unused on K3s and RKE2 + * - ``ASCENDER_NAMESPACE`` + - ``ascender`` + - Namespace for Ascender objects + * - ``ASCENDER_ADMIN_USER`` + - ``admin`` + - Administrator username + * - ``ASCENDER_ADMIN_PASSWORD`` + - ``myadminpassword`` + - Administrator password. Change this before installing + * - ``ASCENDER_IMAGE`` + - ``ghcr.io/ctrliq/ascender`` + - Container image. Change only when using an internal registry + * - ``ASCENDER_VERSION`` + - ``25.5.1`` + - Tag applied to ``ASCENDER_IMAGE`` + * - ``ASCENDER_OPERATOR_VERSION`` + - ``25.5.1`` + - Version of the Ascender Operator + * - ``ascender_replicas`` + - ``1`` + - Number of Ascender web pods + * - ``ascender_garbage_collect_secrets`` + - ``true`` + - When true, the administrator password, secret key, and database credential secrets are deleted if the Ascender resource is removed. Set to ``false`` to keep them + * - ``ascender_setup_playbooks`` + - ``true`` + - Deploy demonstration playbooks after installation + * - ``ascender_image_pull_policy`` + - ``Always`` + - Image pull policy. Set to ``Never`` for offline installs + * - ``ASCENDER_MESH_HOSTNAME`` + - unset + - Hostname for Automation Mesh. Mesh is not configured unless this is set + +.. warning:: + + ``ascender_garbage_collect_secrets`` controls whether Kubernetes deletes the secrets when the Ascender resource is removed. Those secrets include the secret key that encrypts stored credentials. Losing them makes an existing database unreadable, so set this to ``false`` where preserving a deployment matters more than tidy cleanup. + +TLS +---- + +Required when ``k8s_lb_protocol`` is ``https``. Certificate handling differs on cloud platforms. + +.. list-table:: + :widths: 30 20 50 + :header-rows: 1 + + * - Variable + - Default + - Description + * - ``tls_crt_path`` + - ``~/ascender.crt`` + - Certificate file in PEM format + * - ``tls_key_path`` + - ``~/ascender.key`` + - Private key file in PEM format + * - ``custom_cacert_bundle`` + - unset + - CA bundle containing your CA certificate and any external CA certificates + * - ``custom_ldap_cacert`` + - unset + - LDAP CA certificate + +Set the certificate paths to ``"{{ playbook_dir }}/../ascender.crt"`` and the matching key when you keep the files in the ``ascender-install`` directory. + +External database +------------------ + +Ascender deploys its own PostgreSQL instance by default. To use an existing server, set the following. + +.. list-table:: + :widths: 30 20 50 + :header-rows: 1 + + * - Variable + - Default + - Description + * - ``ASCENDER_PGSQL_HOST`` + - unset + - PostgreSQL hostname or address + * - ``ASCENDER_PGSQL_PORT`` + - ``5432`` + - Port + * - ``ASCENDER_PGSQL_USER`` + - ``ascender`` + - Username + * - ``ASCENDER_PGSQL_PWD`` + - unset + - Password + * - ``ASCENDER_PGSQL_DB`` + - ``ascenderdb`` + - Database name, which must already exist + +.. warning:: + + The PostgreSQL password cannot contain special characters. This is a limitation of how the installer passes the password through its configuration. + +Storage for the built-in PostgreSQL instance is set with ``POSTGRES_PVC_SIZE_GB`` and ``POSTGRES_STORAGE_CLASS``. Both apply to new installations only. Changing either on an existing deployment does not resize or move the volume. + +Execution environments +----------------------- + +To pull additional images for use as execution environments, add an ``ee_images`` list. Each entry takes a ``name`` used as a label and an ``image`` giving the full registry path:: + + ee_images: + - name: my-custom-ee + image: registry.example.com/namespace/my-custom-ee:latest + +Offline installation +--------------------- + +These apply to air-gapped deployments on K3s and RKE2. + +.. list-table:: + :widths: 35 20 45 + :header-rows: 1 + + * - Variable + - Default + - Description + * - ``k8s_offline`` + - ``false`` + - Use local assets rather than pulling from the internet + * - ``k8s_container_registry`` + - empty + - Internal registry and namespace holding the Ascender and operator images. Also sets the operator image path + * - ``k8s_image_pull_secret`` + - ``None`` + - Secret holding credentials for that registry. Leave as ``None`` when no authentication is needed + * - ``k8s_ee_pull_credentials_secret`` + - ``None`` + - Secret holding credentials for the registry serving execution environment images + +Artifacts +---------- + +``tmp_dir`` sets where the installer writes generated manifests, backups, and temporary files, and defaults to ``ascender_install_artifacts/`` inside the cloned repository. diff --git a/docs/docsite/rst/installation/manual_install.rst b/docs/docsite/rst/installation/manual_install.rst new file mode 100644 index 000000000..1e5da48a7 --- /dev/null +++ b/docs/docsite/rst/installation/manual_install.rst @@ -0,0 +1,186 @@ +.. _in_manual_install: + +********************************** +Installing without the installer +********************************** + +.. index:: + single: installation + pair: installation; Kustomize + pair: installation; operator + +You can deploy the Ascender Operator and create the Ascender resource yourself, without `ascender-install `_. Use this path when you manage your own cluster, deploy through GitOps tooling such as Argo CD or Flux, or run on a host the installer does not support. + +The installer is the supported path and does more for you, including provisioning the cluster on K3s and RKE2. See :ref:`in_install`. + +The deployment is two steps: install the operator, then create an ``AWX`` resource for the operator to reconcile. + +Requirements +============= + +- A running Kubernetes cluster and a ``kubectl`` context pointing at it +- A default storage class, used for the database volume +- An ingress controller, if you want to reach Ascender by hostname +- ``kubectl`` 1.14 or later, which includes Kustomize + +Install the operator +===================== + +Create a ``kustomization.yaml``, replacing ``25.5.1`` with the version you want from the `operator releases `_:: + + apiVersion: kustomize.config.k8s.io/v1beta1 + kind: Kustomization + resources: + - github.com/ctrliq/ascender-operator/config/default?ref=25.5.1 + + images: + - name: ghcr.io/ctrliq/ascender-operator + newTag: 25.5.1 + + namespace: ascender + +Apply it:: + + kubectl apply -k . + +.. note:: + + The ``ref`` pins the manifests and the ``newTag`` pins the image, and they are separate. Setting only the ``ref`` leaves the operator running whatever image tag the manifests carry, so keep both at the same version. + +This creates the namespace, the ``awxs``, ``awxbackups``, and ``awxrestores`` custom resource definitions, the service account and roles, and the controller deployment. Confirm the operator is running:: + + kubectl get pods -n ascender + +Create the administrator secret +================================ + +The operator generates most of its own secrets, but the administrator password is worth supplying so you know it:: + + apiVersion: v1 + kind: Secret + metadata: + name: ascender-app-admin-password + namespace: ascender + stringData: + password: + +Create the Ascender resource +============================= + +The resource is ``kind: AWX``, not an Ascender-named kind. The operator keeps the upstream API group, so all three custom resources are under ``awx.ansible.com/v1beta1``. + +The following is a working starting point for a cluster with an ingress controller:: + + apiVersion: awx.ansible.com/v1beta1 + kind: AWX + metadata: + name: ascender-app + namespace: ascender + spec: + image: ghcr.io/ctrliq/ascender + image_version: 25.5.1 + init_container_image: ghcr.io/ctrliq/ascender-ee + init_container_image_version: 25.5.1 + control_plane_ee_image: ghcr.io/ctrliq/ascender-ee:25.5.1 + postgres_image: quay.io/sclorg/postgresql-15-c9s + postgres_image_version: "latest" + redis_image: ghcr.io/valkey-io/valkey + redis_image_version: "9-alpine" + replicas: 1 + admin_user: admin + admin_password_secret: ascender-app-admin-password + service_type: ClusterIP + ingress_type: ingress + ingress_path: "/" + ingress_path_type: Prefix + hostname: ascender.example.com + postgres_data_volume_init: true + init_postgres_extra_commands: | + chown 26:0 /var/lib/pgsql/data + chmod 700 /var/lib/pgsql/data + extra_settings: + - setting: CSRF_TRUSTED_ORIGINS + value: + - https://ascender.example.com + +Apply it and watch the operator build the deployment:: + + kubectl apply -f ascender.yml + kubectl get pods -n ascender -w + +.. note:: + + ``postgres_data_volume_init`` and the accompanying commands set ownership on the database volume. Many storage classes provision volumes owned by root, which the PostgreSQL container cannot write to. Omit both on OpenShift, where they are not needed and not supported. + +Set ``CSRF_TRUSTED_ORIGINS`` to the URL you actually reach Ascender on. Without it, signing in fails with a CSRF error even though the pods are healthy. + +TLS +==== + +To terminate TLS at the ingress, create a secret holding the certificate and reference it from the resource:: + + kubectl create secret tls ascender-tls-secret -n ascender \ + --cert=ascender.crt --key=ascender.key + +Then add ``ingress_tls_secret: ascender-tls-secret`` to the spec, and use the ``https`` URL in ``CSRF_TRUSTED_ORIGINS``. + +Using an external database +=========================== + +By default the operator deploys and manages PostgreSQL. To point at an existing server, create a secret describing it and reference it from the spec with ``postgres_configuration_secret``:: + + apiVersion: v1 + kind: Secret + metadata: + name: ascender-app-postgres-configuration + namespace: ascender + stringData: + host: postgres.example.com + port: '5432' + database: ascenderdb + username: ascender + password: + sslmode: prefer + type: unmanaged + type: Opaque + +The database must already exist. When you supply this secret, omit ``postgres_data_volume_init`` and the initialization commands, which apply only to the managed database. + +Secrets the operator generates +=============================== + +Unless you supply them, the operator creates these secrets on first reconcile: + +.. list-table:: + :widths: 40 60 + :header-rows: 1 + + * - Secret + - Contents + * - ``ascender-app-secret-key`` + - The key that encrypts credentials stored in the database + * - ``ascender-app-admin-password`` + - Administrator password, if you did not create it yourself + * - ``ascender-app-postgres-configuration`` + - Connection details for the managed database + * - ``ascender-app-broadcast-websocket`` + - Shared secret used between web pods + +.. warning:: + + The secret key encrypts every credential Ascender stores. A database restored alongside a different secret key leaves those credentials unreadable, and there is no way to recover them. Capture these secrets somewhere safe before you need them, and keep them with any database backup you take. + +Verifying +========== + +The deployment is up when the task and web pods are running:: + + kubectl get pods -n ascender + +If pods do not start, the operator log usually says why:: + + kubectl logs -n ascender deployment/ascender-operator-controller-manager + +Reconcile errors also surface on the resource itself:: + + kubectl describe awx ascender-app -n ascender diff --git a/docs/docsite/rst/installation/quick_start_k3s.rst b/docs/docsite/rst/installation/quick_start_k3s.rst new file mode 100644 index 000000000..acc5de5de --- /dev/null +++ b/docs/docsite/rst/installation/quick_start_k3s.rst @@ -0,0 +1,107 @@ +.. _in_quick_start_k3s: + +************************* +Quick Start on K3s +************************* + +.. index:: + single: installation + pair: installation; K3s + pair: installation; quick start + +K3s is the fastest way to get a working Ascender instance. The installer provisions a single-node K3s cluster and deploys Ascender onto it, so no existing Kubernetes cluster is required. + +This procedure produces an evaluation deployment on one machine. For production, see :ref:`in_install`. + +Requirements +============= + +The machine you install on needs: + +- 2 CPUs +- 8 GB memory +- 20 GB free in ``/var`` +- Rocky Linux 8 or 9 on x86_64 +- ``git``, installed with ``sudo dnf install -y git`` +- Root or sudo access + +Get the installer +================== + +Clone the installer and change into it:: + + git clone https://github.com/ctrliq/ascender-install.git + cd ascender-install + +Create a certificate +===================== + +Generate a self-signed certificate. Run this from inside the ``ascender-install`` directory so the installer finds the files without further configuration. Replace ```` with the address of your machine:: + + openssl req -x509 -newkey rsa:4096 -keyout ascender.key -out ascender.crt -days 365 -nodes \ + -subj "/CN=ascender..nip.io" \ + -addext "subjectAltName=DNS:ascender..nip.io" + +.. note:: + + This quick start uses `nip.io `_, a public wildcard DNS service, so that ``ascender..nip.io`` resolves to your machine with no DNS setup. Use your own hostname for anything beyond an evaluation. + +Configure the deployment +========================= + +Create ``custom.config.yml`` in the ``ascender-install`` directory, again replacing ````:: + + k8s_platform: k3s + k8s_lb_protocol: https + kube_install: true + download_kubeconfig: true + k3s_master_node_ip: "" + + tls_crt_path: "{{ playbook_dir }}/../ascender.crt" + tls_key_path: "{{ playbook_dir }}/../ascender.key" + + ASCENDER_HOSTNAME: ascender..nip.io + ASCENDER_NAMESPACE: ascender + ASCENDER_ADMIN_USER: admin + ASCENDER_ADMIN_PASSWORD: "" + ASCENDER_VERSION: 25.5.1 + ASCENDER_OPERATOR_VERSION: 25.5.1 + + ascender_setup_playbooks: true + +Set ``ASCENDER_ADMIN_PASSWORD`` before you install. ``default.config.yml`` lists every available setting, but do not copy it wholesale, as it carries defaults for every supported platform. + +.. note:: + + ``kube_install: true`` tells the installer to build the K3s cluster for you. This is specific to K3s and RKE2. On every other platform the cluster must already exist. + +Install +======== + +Run the installer from the same machine. The default ``inventory`` file targets ``localhost``, so it needs no changes:: + + sudo ./setup.sh + +A successful run ends with:: + + ASCENDER SUCCESSFULLY SETUP + +Verify +======= + +Confirm the pods are running:: + + kubectl get pods -n ascender + +Then open ``https://ascender..nip.io`` and sign in with the administrator credentials from your configuration file. Your browser warns about the self-signed certificate, which is expected. + +If pods do not reach ``Running``, check the operator:: + + kubectl logs -n ascender deployment/ascender-operator-controller-manager + +Next steps +=========== + +Work through the :ref:`Ascender Quickstart ` to run your first playbook. + +For a production deployment, read :ref:`in_install` for the full configuration reference and the other supported platforms. diff --git a/docs/docsite/rst/quickstart/quick_start.rst b/docs/docsite/rst/quickstart/quick_start.rst index 8e125ed1e..03d20e229 100644 --- a/docs/docsite/rst/quickstart/quick_start.rst +++ b/docs/docsite/rst/quickstart/quick_start.rst @@ -6,6 +6,6 @@ Quick Start Welcome to the Ascender Quick Start Guide. At the end of the Quick Start, you will have a functioning Ascender application that you can use to launch more sophisticated playbooks. You can expect the Quick Start process to take less than thirty minutes. -To begin, you must install Ascender and you must choose a target system where an initial playbook can be deployed (provided by Ascender). +To begin, you must install Ascender and you must choose a target system where an initial playbook can be deployed (provided by Ascender). If you do not have Ascender running yet, see :ref:`in_quick_start_k3s` to get a single-node deployment up, or :ref:`in_install` for the full installation guide. This first playbook executes simple Ansible tasks, while teaching you how to use Ascender, as well as ensuring its proper setup. This can be any sort of system manageable by Ansible, as described in the `Managed nodes `_ section of the Ansible documentation. From 550bf09d633545ae642ab86b86db26d54b7cb851 Mon Sep 17 00:00:00 2001 From: Stephen Simpson Date: Fri, 28 Aug 2026 09:56:24 -0500 Subject: [PATCH 3/5] docs: correct the installation section after review Two commands were wrong. The operator deployment is awx-operator-controller-manager, not ascender-operator-controller-manager: config/default/kustomization.yaml sets namePrefix awx-operator- and that is not renamed downstream. And init_postgres_extra_commands is not a CRD field, so the API server silently prunes it; postgres_data_volume_init alone gets the documented behaviour. Also: k8s_platform defaults to eks rather than k3s, eight platforms ship rather than seven, host support includes Ubuntu and Debian, offline covers DKP, the installer disables firewalld, and two more operator-generated secrets exist than were listed. Puts Install ahead of Get started so the quickstart no longer points down the sidebar, and renames the K3s page so it does not collide with the existing Quick Start. Co-Authored-By: Claude Opus 5 (1M context) --- docs/docsite/rst/index.rst | 12 ++-- docs/docsite/rst/installation/index.rst | 16 +++-- docs/docsite/rst/installation/install.rst | 68 +++++++++++++++---- .../rst/installation/manual_install.rst | 32 +++++---- .../rst/installation/quick_start_k3s.rst | 63 +++++++++-------- 5 files changed, 127 insertions(+), 64 deletions(-) diff --git a/docs/docsite/rst/index.rst b/docs/docsite/rst/index.rst index d7d88d9f9..6d92d28ef 100644 --- a/docs/docsite/rst/index.rst +++ b/docs/docsite/rst/index.rst @@ -5,21 +5,21 @@ Ascender helps teams manage complex multi-tier deployments by adding control, kn .. toctree:: :maxdepth: 2 - :caption: Get started + :caption: Install - quickstart/index + installation/index .. toctree:: :maxdepth: 2 - :caption: Community + :caption: Get started - contributor/index + quickstart/index .. toctree:: :maxdepth: 2 - :caption: Install + :caption: Community - installation/index + contributor/index .. toctree:: :maxdepth: 2 diff --git a/docs/docsite/rst/installation/index.rst b/docs/docsite/rst/installation/index.rst index d76ddb0c1..2104027c1 100644 --- a/docs/docsite/rst/installation/index.rst +++ b/docs/docsite/rst/installation/index.rst @@ -14,11 +14,15 @@ Ascender runs on Kubernetes and is managed by the `Ascender Operator `_, which provisions the cluster where supported, deploys the operator, and creates the Ascender resource from a single configuration file. If you manage your own cluster or deploy through GitOps tooling, you can install the operator and create the Ascender resource yourself. +**Join us online** + +You can find lots of Ascender discussion and get answers to questions at `Ascender Discussion Forum `_. + .. toctree:: - :maxdepth: 2 - :numbered: + :maxdepth: 2 + :numbered: - self - quick_start_k3s - install - manual_install + self + quick_start_k3s + install + manual_install diff --git a/docs/docsite/rst/installation/install.rst b/docs/docsite/rst/installation/install.rst index 108a63328..32c97d87a 100644 --- a/docs/docsite/rst/installation/install.rst +++ b/docs/docsite/rst/installation/install.rst @@ -16,22 +16,27 @@ To evaluate Ascender on a single machine, start with :ref:`in_quick_start_k3s`. What the installer does ======================== -Running ``./setup.sh`` performs these steps on your behalf: +When you run ``./setup.sh``, it: - Installs its own dependencies, including ansible-core, the required collections, and the Python Kubernetes client -- Provisions the cluster, on K3s and RKE2 only, when ``kube_install`` is set +- Provisions the cluster, on K3s and RKE2 only, when you set ``kube_install`` +- Stops and disables ``firewalld``, unless you set ``firewalld_disable: false`` - Deploys the Ascender Operator with Kustomize, pinned to ``ASCENDER_OPERATOR_VERSION`` - Creates the namespace, the administrator password secret, and any TLS, custom CA, or external database secrets your configuration calls for - Creates the Ascender resource that the operator reconciles into a running deployment -Understanding these steps is useful even if you never run the installer, because :ref:`in_manual_install` covers doing them yourself. +.. warning:: + + The installer turns off the host firewall by default. Set ``firewalld_disable: false`` to keep it running, and the installer opens ports 6443, 80, and 443 and trusts the cluster networks instead. This setting is not listed in ``default.config.yml``. Requirements ============= -The machine you run the installer from needs Rocky Linux 8 or 9 on x86_64, ``git``, and root or sudo access. The installer refuses to run on other distributions and on non-x86_64 hosts. Cloud platforms require Rocky Linux 9 and the relevant CLI tool, authenticated. +You run the installer from a machine with ``git``, ``openssl``, and root or sudo access, on x86_64. Supported hosts are Enterprise Linux 8 or 9, meaning Rocky, RHEL, AlmaLinux, CentOS, or Fedora, and Ubuntu or Debian 24 or 26. + +For EKS, GKE, and AKS you need Enterprise Linux 9 specifically, plus the relevant CLI tool authenticated. Ubuntu and Debian are not supported for those three. -For on-premise deployments on K3s or RKE2, this can be the same machine that runs the cluster. For EKS, GKE, and AKS, use a small administrative host. +On K3s or RKE2 this can be the same machine that runs the cluster. For the cloud platforms, use a small administrative host. Getting started ================ @@ -50,15 +55,27 @@ Install with:: Platforms ========== -**K3s** is covered in :ref:`in_quick_start_k3s`. Set ``kube_install: true`` and the installer creates the cluster. +Eight platforms are supported: ``k3s``, ``rke2``, ``eks``, ``gke``, ``aks``, ``dkp``, ``tkgi``, and ``ocp``. -**RKE2** suits production and supports single-node and highly available clusters. The installer does not create an RKE2 cluster, so build it first and then run the installer against it. +K3s +---- + +Covered in :ref:`in_quick_start_k3s`. Set ``kube_install: true`` and the installer creates the cluster for you. -**EKS, GKE, and AKS** each require their own CLI tool, IAM or role configuration, and a DNS zone. Cloud installs require Rocky Linux 9 on the administrative host. +RKE2 +----- -**DKP** needs one extra setting, ``DKP_CLUSTER_NAME``, naming the cluster to deploy to or create. +Suits production, and supports single-node and highly available clusters. The installer does not create an RKE2 cluster, so build it first and run the installer against it. -**OCP** follows the common configuration. Check ``default.config.yml`` for OpenShift-specific defaults. +EKS, GKE, and AKS +------------------ + +Each needs its own CLI tool authenticated, IAM or role configuration, and a DNS zone. You run these from an Enterprise Linux 9 host. + +DKP, TKGI, and OCP +------------------- + +DKP takes one extra setting, ``DKP_CLUSTER_NAME``, naming the cluster to deploy to or create. TKGI and OpenShift follow the common configuration. Check ``default.config.yml`` for platform-specific defaults. Upgrading ========== @@ -88,8 +105,8 @@ Kubernetes platform - Default - Description * - ``k8s_platform`` - - ``k3s`` - - Target platform. One of ``k3s``, ``eks``, ``aks``, ``gke``, ``rke2``, ``dkp``, ``ocp`` + - ``eks`` + - Target platform. One of ``k3s``, ``eks``, ``aks``, ``gke``, ``rke2``, ``dkp``, ``tkgi``, ``ocp``. Set this explicitly, as the default is not K3s * - ``k8s_lb_protocol`` - ``http`` - Load balancer protocol. Set to ``https`` to enable TLS, which requires the certificate settings below @@ -97,6 +114,31 @@ Kubernetes platform - ``false`` - Copy the kubeconfig from the target host to ``~/.kube/config`` on the installing machine +K3s cluster +------------ + +These apply when the installer builds the cluster for you. + +.. list-table:: + :widths: 30 20 50 + :header-rows: 1 + + * - Variable + - Default + - Description + * - ``kube_install`` + - ``false`` + - Provision the cluster before deploying Ascender. K3s and RKE2 only + * - ``k3s_master_node_ip`` + - ``127.0.0.1`` + - Address of the K3s node. Set this to the machine's real address + * - ``use_etc_hosts`` + - ``true`` + - Add the Ascender hostname to ``/etc/hosts`` on the node + * - ``firewalld_disable`` + - ``true`` + - Stop and disable ``firewalld``. Set to ``false`` to keep it running with the required ports opened + Ascender application --------------------- @@ -224,7 +266,7 @@ To pull additional images for use as execution environments, add an ``ee_images` Offline installation --------------------- -These apply to air-gapped deployments on K3s and RKE2. +These apply to air-gapped deployments on K3s, RKE2, and DKP. .. list-table:: :widths: 35 20 45 diff --git a/docs/docsite/rst/installation/manual_install.rst b/docs/docsite/rst/installation/manual_install.rst index 1e5da48a7..5e0c30f8e 100644 --- a/docs/docsite/rst/installation/manual_install.rst +++ b/docs/docsite/rst/installation/manual_install.rst @@ -26,7 +26,7 @@ Requirements Install the operator ===================== -Create a ``kustomization.yaml``, replacing ``25.5.1`` with the version you want from the `operator releases `_:: +In an empty directory, create ``kustomization.yaml``, replacing ``25.5.1`` with the version you want from the `operator releases `_:: apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization @@ -47,14 +47,14 @@ Apply it:: The ``ref`` pins the manifests and the ``newTag`` pins the image, and they are separate. Setting only the ``ref`` leaves the operator running whatever image tag the manifests carry, so keep both at the same version. -This creates the namespace, the ``awxs``, ``awxbackups``, and ``awxrestores`` custom resource definitions, the service account and roles, and the controller deployment. Confirm the operator is running:: +This creates the namespace, the ``awxs``, ``awxbackups``, ``awxrestores``, and ``awxmeshingresses`` custom resource definitions, the service account and roles, and the controller deployment. Confirm the operator is running:: kubectl get pods -n ascender Create the administrator secret ================================ -The operator generates most of its own secrets, but the administrator password is worth supplying so you know it:: +Supply the administrator password yourself so you know what it is. The operator generates one otherwise. Save this as ``admin-secret.yml``:: apiVersion: v1 kind: Secret @@ -62,14 +62,18 @@ The operator generates most of its own secrets, but the administrator password i name: ascender-app-admin-password namespace: ascender stringData: - password: + password: + +Apply it:: + + kubectl apply -f admin-secret.yml Create the Ascender resource ============================= The resource is ``kind: AWX``, not an Ascender-named kind. The operator keeps the upstream API group, so all three custom resources are under ``awx.ansible.com/v1beta1``. -The following is a working starting point for a cluster with an ingress controller:: +The following is a working starting point for a cluster with an ingress controller. Save it as ``ascender.yml``:: apiVersion: awx.ansible.com/v1beta1 kind: AWX @@ -95,12 +99,10 @@ The following is a working starting point for a cluster with an ingress controll ingress_path_type: Prefix hostname: ascender.example.com postgres_data_volume_init: true - init_postgres_extra_commands: | - chown 26:0 /var/lib/pgsql/data - chmod 700 /var/lib/pgsql/data extra_settings: - setting: CSRF_TRUSTED_ORIGINS value: + - http://ascender.example.com - https://ascender.example.com Apply it and watch the operator build the deployment:: @@ -110,9 +112,11 @@ Apply it and watch the operator build the deployment:: .. note:: - ``postgres_data_volume_init`` and the accompanying commands set ownership on the database volume. Many storage classes provision volumes owned by root, which the PostgreSQL container cannot write to. Omit both on OpenShift, where they are not needed and not supported. + ``postgres_data_volume_init`` sets ownership on the database volume with an init container. Many storage classes provision volumes owned by root, which the PostgreSQL container cannot write to. The operator's default commands already do the right thing, so you rarely need ``postgres_init_container_commands``. OpenShift manages volume ownership itself. + +Set ``CSRF_TRUSTED_ORIGINS`` to the URLs you actually reach Ascender on. Without it, signing in can fail with a CSRF error even though the pods are healthy, because the scheme Django computes behind an ingress does not always match the one the browser sent. Listing both schemes, as the installer does, covers the common cases. -Set ``CSRF_TRUSTED_ORIGINS`` to the URL you actually reach Ascender on. Without it, signing in fails with a CSRF error even though the pods are healthy. +Pin ``image_version``. Left unset, the operator falls back to ``latest``, so the version you get depends on when the image was last pushed. TLS ==== @@ -144,7 +148,7 @@ By default the operator deploys and manages PostgreSQL. To point at an existing type: unmanaged type: Opaque -The database must already exist. When you supply this secret, omit ``postgres_data_volume_init`` and the initialization commands, which apply only to the managed database. +Apply it with ``kubectl apply -f postgres-secret.yml``. The database must already exist. When you supply this secret, omit ``postgres_data_volume_init`` and the initialization commands, which apply only to the managed database. Secrets the operator generates =============================== @@ -165,6 +169,10 @@ Unless you supply them, the operator creates these secrets on first reconcile: - Connection details for the managed database * - ``ascender-app-broadcast-websocket`` - Shared secret used between web pods + * - ``ascender-app-receptor-ca`` + - Certificate authority for the automation mesh + * - ``ascender-app-receptor-work-signing`` + - Key used to sign mesh work units .. warning:: @@ -179,7 +187,7 @@ The deployment is up when the task and web pods are running:: If pods do not start, the operator log usually says why:: - kubectl logs -n ascender deployment/ascender-operator-controller-manager + kubectl logs -n ascender deployment/awx-operator-controller-manager Reconcile errors also surface on the resource itself:: diff --git a/docs/docsite/rst/installation/quick_start_k3s.rst b/docs/docsite/rst/installation/quick_start_k3s.rst index acc5de5de..c39386084 100644 --- a/docs/docsite/rst/installation/quick_start_k3s.rst +++ b/docs/docsite/rst/installation/quick_start_k3s.rst @@ -1,30 +1,34 @@ .. _in_quick_start_k3s: -************************* -Quick Start on K3s -************************* +****************************** +Single-node install on K3s +****************************** .. index:: single: installation pair: installation; K3s - pair: installation; quick start + pair: installation; evaluation -K3s is the fastest way to get a working Ascender instance. The installer provisions a single-node K3s cluster and deploys Ascender onto it, so no existing Kubernetes cluster is required. +K3s is the fastest way to get a working Ascender instance. The installer provisions a single-node K3s cluster and deploys Ascender onto it, so you do not need an existing Kubernetes cluster. -This procedure produces an evaluation deployment on one machine. For production, see :ref:`in_install`. +This gets you an evaluation deployment on one machine. For production, see :ref:`in_install`. Requirements ============= -The machine you install on needs: +You need a machine with: - 2 CPUs - 8 GB memory -- 20 GB free in ``/var`` -- Rocky Linux 8 or 9 on x86_64 -- ``git``, installed with ``sudo dnf install -y git`` +- 20 GB free disk +- Enterprise Linux 8 or 9, or Ubuntu or Debian 24 or 26 +- ``git`` and ``openssl``, installed with ``sudo dnf install -y git openssl`` - Root or sudo access +.. warning:: + + The installer stops and disables ``firewalld`` by default. Set ``firewalld_disable: false`` in your configuration to keep it running, in which case the installer opens ports 6443, 80, and 443 and trusts the cluster networks instead. + Get the installer ================== @@ -36,47 +40,47 @@ Clone the installer and change into it:: Create a certificate ===================== -Generate a self-signed certificate. Run this from inside the ``ascender-install`` directory so the installer finds the files without further configuration. Replace ```` with the address of your machine:: +Generate a self-signed certificate. Run this from inside the ``ascender-install`` directory so the installer finds the files without further configuration. Replace ```` with the address of your machine:: openssl req -x509 -newkey rsa:4096 -keyout ascender.key -out ascender.crt -days 365 -nodes \ - -subj "/CN=ascender..nip.io" \ - -addext "subjectAltName=DNS:ascender..nip.io" + -subj "/CN=ascender..nip.io" \ + -addext "subjectAltName=DNS:ascender..nip.io" .. note:: - This quick start uses `nip.io `_, a public wildcard DNS service, so that ``ascender..nip.io`` resolves to your machine with no DNS setup. Use your own hostname for anything beyond an evaluation. + This uses `nip.io `_, a public wildcard DNS service, so that ``ascender..nip.io`` resolves to your machine with no DNS setup. Use your own hostname for anything beyond an evaluation. Configure the deployment ========================= -Create ``custom.config.yml`` in the ``ascender-install`` directory, again replacing ````:: +Create ``custom.config.yml`` in the ``ascender-install`` directory, again replacing ````:: k8s_platform: k3s k8s_lb_protocol: https kube_install: true download_kubeconfig: true - k3s_master_node_ip: "" + k3s_master_node_ip: "" tls_crt_path: "{{ playbook_dir }}/../ascender.crt" tls_key_path: "{{ playbook_dir }}/../ascender.key" - ASCENDER_HOSTNAME: ascender..nip.io + ASCENDER_HOSTNAME: ascender..nip.io ASCENDER_NAMESPACE: ascender ASCENDER_ADMIN_USER: admin - ASCENDER_ADMIN_PASSWORD: "" + ASCENDER_ADMIN_PASSWORD: ASCENDER_VERSION: 25.5.1 ASCENDER_OPERATOR_VERSION: 25.5.1 ascender_setup_playbooks: true -Set ``ASCENDER_ADMIN_PASSWORD`` before you install. ``default.config.yml`` lists every available setting, but do not copy it wholesale, as it carries defaults for every supported platform. +Set ``ASCENDER_ADMIN_PASSWORD`` before you install. ``default.config.yml`` lists the available settings, but do not copy it wholesale. It carries defaults for every supported platform. .. note:: - ``kube_install: true`` tells the installer to build the K3s cluster for you. This is specific to K3s and RKE2. On every other platform the cluster must already exist. + ``kube_install: true`` tells the installer to build the K3s cluster for you. This works on K3s and RKE2 only. On every other platform the cluster must already exist. -Install -======== +Run the installer +================== Run the installer from the same machine. The default ``inventory`` file targets ``localhost``, so it needs no changes:: @@ -86,18 +90,23 @@ A successful run ends with:: ASCENDER SUCCESSFULLY SETUP -Verify -======= +Verify the deployment +====================== + +The installer writes the kubeconfig for the user it ran as, so under ``sudo`` it belongs to root. Copy it to your own user before using ``kubectl``:: + + sudo cp /root/.kube/config ~/.kube/config + sudo chown $(id -u):$(id -g) ~/.kube/config Confirm the pods are running:: kubectl get pods -n ascender -Then open ``https://ascender..nip.io`` and sign in with the administrator credentials from your configuration file. Your browser warns about the self-signed certificate, which is expected. +Then open ``https://ascender..nip.io`` and sign in with the administrator credentials from your configuration file. Your browser warns about the self-signed certificate, which is expected. -If pods do not reach ``Running``, check the operator:: +If pods do not reach ``Running``, the operator log usually says why:: - kubectl logs -n ascender deployment/ascender-operator-controller-manager + kubectl logs -n ascender deployment/awx-operator-controller-manager Next steps =========== From 695765523b12fd251e390bb0ec040865b29143ca Mon Sep 17 00:00:00 2001 From: Stephen Simpson Date: Fri, 28 Aug 2026 16:26:36 -0500 Subject: [PATCH 4/5] docs: document backup and restore, and drop the setup.sh procedure There was no backup and restore page and no TOC entry for one. The three places it was mentioned all described the Tower-era setup.sh, which Ascender does not ship, so a customer looking for how to back up found a feature blurb promising it was easy and a command they could not run. Adds a backup and restore page covering the ascender-install path, the AWXBackup and AWXRestore resources behind it, and restoring onto a new cluster after losing the old one. States what a backup does and does not contain, since the projects volume is in neither, and that backup silently captures nothing when the database is external. Removes common/setup-playbook.rst, which documented installer tarball flags that do not exist, and corrects the overview blurb and the setup.sh -k procedure in secret_handling. Also points the install and upgrade links on init_script at the new installation section rather than at GitHub. Co-Authored-By: Claude Opus 5 (1M context) --- .../rst/administration/backup_restore.rst | 208 ++++++++++++++ docs/docsite/rst/administration/index.rst | 1 + .../rst/administration/init_script.rst | 4 +- .../rst/administration/secret_handling.rst | 27 +- docs/docsite/rst/common/setup-playbook.rst | 24 -- docs/docsite/rst/installation/index.rst | 12 +- docs/docsite/rst/installation/install.rst | 271 ++++-------------- .../rst/installation/manual_install.rst | 49 ++-- .../rst/installation/quick_start_k3s.rst | 72 ++--- .../upgrade_considerations.rst | 8 +- docs/docsite/rst/userguide/overview.rst | 2 +- 11 files changed, 325 insertions(+), 353 deletions(-) create mode 100644 docs/docsite/rst/administration/backup_restore.rst delete mode 100644 docs/docsite/rst/common/setup-playbook.rst diff --git a/docs/docsite/rst/administration/backup_restore.rst b/docs/docsite/rst/administration/backup_restore.rst new file mode 100644 index 000000000..ed4e1cab3 --- /dev/null +++ b/docs/docsite/rst/administration/backup_restore.rst @@ -0,0 +1,208 @@ +.. _ag_backup_restore: + +************************ +Backup and Restore +************************ + +.. index:: + single: backup + single: restore + pair: backup; database + pair: restore; secret key + +Ascender is backed up through the Ascender Operator, which captures the database, the secrets that encrypt it, and the deployment configuration. `ascender-install `_ drives that process and copies the result off the cluster for you, so use it if you installed with it. + +What a backup contains +======================= + +A backup is three files: + +.. list-table:: + :widths: 25 75 + :header-rows: 1 + + * - File + - Contents + * - ``tower.db`` + - The PostgreSQL database, as a ``pg_dump`` custom-format archive + * - ``secrets.yml`` + - The secret key, admin password, database credentials, and any TLS, custom CA, and receptor secrets + * - ``awx_object`` + - The Ascender resource specification + +Project files are not included. Projects that sync from source control are fetched again after a restore, so they need nothing. Manual projects, whose files exist only on the volume, need backing up separately. + +The secret key in ``secrets.yml`` is what makes the database readable. Restore it alongside the database and stored credentials work; restore the database on its own against a new deployment and every credential in it is unreadable, with no way to recover them. + +Backing up with the installer +============================== + +Run the backup from the ``ascender-install`` directory, with the ``custom.config.yml`` you installed with:: + + ./setup.sh -b + +The files land in ``ascender_install_artifacts/backups/``, in a timestamped directory, with a ``current`` symlink pointing at the newest. Copy that directory somewhere off the machine, because nothing does it for you, and treat it as credentials when you do. + +See `Backup and restore `_ in the installer repository for the full procedure. + +.. note:: + + A backup needs a running deployment, because it executes commands inside a live task pod. Take them routinely rather than reaching for one after something has already broken. + +Restoring with the installer +============================= + +Restore reads from ``ascender_install_artifacts/backups/current``, so put the backup you want there first:: + + ./setup.sh -r + +.. warning:: + + Restoring is destructive. It scales the deployment down, deletes the PostgreSQL volume, and rebuilds the database from the backup. It also replaces the current administrator password with the one from the backup. There is no confirmation prompt. + +After a restore, confirm the pods come back and sign in with the administrator credentials from the backup, not the ones you were using before. If you are restoring into a disaster recovery deployment that should not run jobs, disable schedules before it starts reconciling. + +To restore onto a rebuilt or replacement machine, see `Restoring onto a rebuilt k3s node `_ in the installer repository, or `Restoring onto a new cluster`_ below. + +Backing up and restoring manually +=================================== + +To back up and restore by hand, create the operator's ``AWXBackup`` and ``AWXRestore`` resources yourself. This is what ``ascender-install`` does on your behalf, with the addition of copying the files off the cluster. + +Taking a backup +---------------- + +Create an ``AWXBackup`` naming the deployment to back up:: + + apiVersion: awx.ansible.com/v1beta1 + kind: AWXBackup + metadata: + name: ascender-backup-2026-08-28 + namespace: ascender + spec: + deployment_name: ascender-app + backup_storage_requirements: + requests: + storage: 20Gi + +Give each backup a distinct name, with the date in it. Re-applying an existing ``AWXBackup`` updates that resource rather than producing a new backup, and the resources stay in the namespace as the record of what you have. + +``deployment_name`` is the only required field. The operator creates a persistent volume claim named ``-backup-claim`` unless you point ``backup_pvc`` at one you made yourself. Set ``backup_storage_requirements``, because the default is empty and leaves the size to whatever your storage class does with an unset value. + +Apply it and wait for the operator to finish:: + + kubectl apply -f backup.yml + kubectl get awxbackup ascender-backup-2026-08-28 -n ascender -o yaml + +The backup is complete when ``status.backupDirectory`` and ``status.backupClaim`` are populated. The directory is timestamped, so the claim accumulates one per run. + +Copying a backup off the cluster +--------------------------------- + +The operator writes to the claim and stops there. To get the files out, run a pod that mounts the claim and copy from it:: + + kubectl run backup-access -n ascender --image=busybox:stable --restart=Never \ + --overrides='{"spec":{"containers":[{"name":"backup-access","image":"busybox:stable","command":["sleep","3600"],"volumeMounts":[{"name":"backup","mountPath":"/backups"}]}],"volumes":[{"name":"backup","persistentVolumeClaim":{"claimName":"ascender-app-backup-claim"}}]}}' + + BACKUP_DIR=$(kubectl get awxbackup ascender-backup-2026-08-28 -n ascender \ + -o jsonpath='{.status.backupDirectory}') + + kubectl cp ascender/backup-access:$BACKUP_DIR ./ascender-backup + kubectl delete pod backup-access -n ascender + +.. note:: + + A backup is a set of credentials. ``secrets.yml`` holds the secret key, the administrator password, the database credentials, and any TLS private keys, all recoverable in plain text. Once it is off the cluster it has none of the protection a Kubernetes secret gave it, so store it where you would store those credentials, restrict who can read it, and keep it out of source control and shared drives. + +Restoring from a backup resource +--------------------------------- + +Restore rebuilds the deployment from the backup, so remove the old one first. Confirm you have a copy of the backup off the cluster before you start. + +Find the database volume claim. Its name is derived from the PostgreSQL version and the deployment name, so read it rather than assuming it:: + + kubectl get pvc -n ascender + +Then delete the Ascender resource and that claim:: + + kubectl delete awx ascender-app -n ascender + kubectl delete pvc postgres-15-ascender-app-postgres-15-0 -n ascender + +.. warning:: + + Do not delete the namespace. The backup claim lives in it, so removing the namespace destroys the backup you are about to restore from. + +Then create an ``AWXRestore`` pointing at the backup:: + + apiVersion: awx.ansible.com/v1beta1 + kind: AWXRestore + metadata: + name: ascender-restore + namespace: ascender + spec: + deployment_name: ascender-app + backup_name: ascender-backup-2026-08-28 + +Naming ``backup_name`` works when the original ``AWXBackup`` resource is still in the cluster, because the operator reads the claim and directory from its status. + +Apply it and watch:: + + kubectl apply -f restore.yml + kubectl get pods -n ascender -w + +The operator applies the secrets first, then recreates the Ascender resource from the backed-up specification, then loads the database. Applying the secrets before the resource is what preserves the secret key, so the restored deployment can still read its own credentials. + +Restoring onto a new cluster +----------------------------- + +After losing a cluster, there is no ``AWXBackup`` resource to name, so point the restore at the files directly. + +Install the operator and create the namespace first, as described in :ref:`in_manual_install`. + +Create a claim to hold the backup. On a new cluster nothing has made one yet, so this is the same shape the operator would have created:: + + kubectl apply -n ascender -f - <<'EOF' + apiVersion: v1 + kind: PersistentVolumeClaim + metadata: + name: ascender-app-backup-claim + spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 20Gi + EOF + +Add ``storageClassName`` if the cluster has no default. Size it for the database dump, not the deployment. + +Copy the files onto the claim, which is the reverse of getting them off:: + + kubectl run backup-access -n ascender --image=busybox:stable --restart=Never \ + --overrides='{"spec":{"containers":[{"name":"backup-access","image":"busybox:stable","command":["sleep","3600"],"volumeMounts":[{"name":"backup","mountPath":"/backups"}]}],"volumes":[{"name":"backup","persistentVolumeClaim":{"claimName":"ascender-app-backup-claim"}}]}}' + + kubectl cp ./ascender-backup ascender/backup-access:/backups/ascender-restore + kubectl delete pod backup-access -n ascender + +Then name the claim and the directory instead of a backup:: + + apiVersion: awx.ansible.com/v1beta1 + kind: AWXRestore + metadata: + name: ascender-restore + namespace: ascender + spec: + deployment_name: ascender-app + backup_pvc: ascender-app-backup-claim + backup_dir: /backups/ascender-restore + +``backup_dir`` is an absolute path, because the operator mounts the claim at ``/backups`` and checks that the directory exists before it starts. The three files must sit directly inside it. + +Apply it the same way. The restored deployment takes its name from ``deployment_name`` and its configuration from the ``awx_object`` file in the backup, so it comes back as it was rather than as a fresh install. + +External databases +=================== + +.. warning:: + + Backup and restore cover the database the operator manages. If you set ``ASCENDER_PGSQL_HOST`` to use your own PostgreSQL server, restore stops without doing anything, and backup runs without capturing your database. Back up an external database with your own tooling, and keep ``secrets.yml`` from an Ascender backup alongside it so the secret key survives. diff --git a/docs/docsite/rst/administration/index.rst b/docs/docsite/rst/administration/index.rst index d746867ff..c59792b15 100644 --- a/docs/docsite/rst/administration/index.rst +++ b/docs/docsite/rst/administration/index.rst @@ -31,6 +31,7 @@ Likewise content in this guide can be removed or replaced if it applies to funct metrics performance secret_handling + backup_restore security_best_practices awx-manage configure_ascender diff --git a/docs/docsite/rst/administration/init_script.rst b/docs/docsite/rst/administration/init_script.rst index ca67c424e..dd1d4231c 100644 --- a/docs/docsite/rst/administration/init_script.rst +++ b/docs/docsite/rst/administration/init_script.rst @@ -3,7 +3,7 @@ Starting, Stopping, and Restarting Ascender --------------------------------------------- -To install Ascender: https://github.com/ctrliq/ascender-operator/tree/devel/docs/installation +To install Ascender, see :ref:`in_start`. .. these instructions will be ported over to here in the near future (TBD) @@ -11,7 +11,7 @@ To migrate from an old Ascender to a new Ascender instance: https://github.com/c .. these instructions will be ported over to here in the near future (TBD) -To upgrade you Ascender instance: https://github.com/ctrliq/ascender-operator/blob/devel/docs/upgrade/upgrading.md +To upgrade your Ascender instance, see :ref:`in_install`. .. these instructions will be ported over to here in the near future (TBD) diff --git a/docs/docsite/rst/administration/secret_handling.rst b/docs/docsite/rst/administration/secret_handling.rst index 73e6b8b15..dfc786bf9 100644 --- a/docs/docsite/rst/administration/secret_handling.rst +++ b/docs/docsite/rst/administration/secret_handling.rst @@ -37,38 +37,31 @@ Secret handling for operational use Ascender contains the following secrets used operationally: -- ``/etc/awx/SECRET_KEY`` +- ``-secret-key`` - A secret key used for encrypting automation secrets in the - database (see below). If the ``SECRET_KEY`` changes or is unknown, + database (see below). If the secret key changes or is unknown, no encrypted fields in the database will be accessible. -- ``/etc/awx/awx.{cert,key}`` +- The ingress TLS secret - - SSL certificate and key for the Ascender web service. A - self-signed cert/key is installed by default; the customer can - provide a locally appropriate certificate and key. + - SSL certificate and key for the Ascender web service, supplied + when the deployment is created. -- Database password in ``/etc/awx/conf.d/postgres.py`` and message bus - password in ``/etc/awx/conf.d/channels.py`` +- ``-postgres-configuration`` - - Passwords for connecting to Ascender component services + - Host, database name, and password for connecting to PostgreSQL -These secrets are all stored unencrypted on the Ascender server, as they are all needed to be read by the Ascender service at startup -in an automated fashion. All secrets are protected by Unix permissions, and restricted to root and the Ascender service user awx. +These are Kubernetes secrets in the namespace Ascender is deployed to, readable by the Ascender service account so the service can read them at startup. Restrict who can read secrets in that namespace to control access to them. -If hiding of these secrets is required, the files that these secrets are read from are interpreted Python. These files can be adjusted to retrieve these secrets via some other mechanism anytime a service restarts. +List them with ``kubectl get secrets -n ``. .. note:: If the secrets system is down, Ascender will be unable to get the information and may fail in a way that would be recoverable once the service is restored. Using some redundancy on that system is highly recommended. -If, for any reason you believe the ``SECRET_KEY`` Ascender generated for you has been compromised and needs to be regenerated, you can run a tool from the installer that behaves much like Ascender backup and restore tool. - -To generate a new secret key, run ``setup.sh -k`` using the inventory from your install. - -A backup copy of the prior key is saved in ``/etc/awx/``. +If you believe the secret key has been compromised, replacing it is not a routine operation. Everything already encrypted with it, meaning every stored credential, becomes unreadable the moment it changes. Plan to re-enter those credentials, and keep a copy of the old secret alongside a database backup taken before the change. See :ref:`ag_backup_restore`. Secret handling for automation use diff --git a/docs/docsite/rst/common/setup-playbook.rst b/docs/docsite/rst/common/setup-playbook.rst deleted file mode 100644 index c153e05ab..000000000 --- a/docs/docsite/rst/common/setup-playbook.rst +++ /dev/null @@ -1,24 +0,0 @@ - -.. index:: - pair: installation script; playbook setup - single: playbook setup - pair: playbook setup; setup.sh - -Ascender setup playbook script uses the ``inventory`` file and is invoked as ``./setup.sh`` from the path where you unpacked the Ascender installer tarball. - -:: - - root@localhost:~$ ./setup.sh - - -The setup script takes the following arguments: - -- ``-h`` -- Show this help message and exit -- ``-i INVENTORY_FILE`` -- Path to Ansible inventory file (default: ``inventory``) -- ``-e EXTRA_VARS`` -- Set additional Ansible variables as key=value or YAML/JSON (i.e. ``-e bundle_install=false`` forces an online installation) -- ``-b`` -- Perform a database backup in lieu of installing -- ``-r`` -- Perform a database restore in lieu of installing (a default restore path is used unless EXTRA_VARS are provided with a non-default path, as shown in the code example below) - -:: - - ./setup.sh -e 'restore_backup_file=/path/to/nondefault/location' -r diff --git a/docs/docsite/rst/installation/index.rst b/docs/docsite/rst/installation/index.rst index 2104027c1..ba9699b5c 100644 --- a/docs/docsite/rst/installation/index.rst +++ b/docs/docsite/rst/installation/index.rst @@ -6,23 +6,13 @@ Installing Ascender Deploy Ascender on Kubernetes, from a single-node evaluation to a production cluster. -This guide applies to the latest version of Ascender only. -The content in this guide is updated frequently and might contain functionality that is not available in previous versions. -Likewise content in this guide can be removed or replaced if it applies to functionality that is no longer available in the latest version. - Ascender runs on Kubernetes and is managed by the `Ascender Operator `_. -Most deployments should use `ascender-install `_, which provisions the cluster where supported, deploys the operator, and creates the Ascender resource from a single configuration file. -If you manage your own cluster or deploy through GitOps tooling, you can install the operator and create the Ascender resource yourself. - -**Join us online** - -You can find lots of Ascender discussion and get answers to questions at `Ascender Discussion Forum `_. +Install it with `ascender-install `_, which provisions the cluster where supported, deploys the operator, and creates the Ascender resource from a single configuration file. .. toctree:: :maxdepth: 2 :numbered: - self quick_start_k3s install manual_install diff --git a/docs/docsite/rst/installation/install.rst b/docs/docsite/rst/installation/install.rst index 32c97d87a..d07f4ac3c 100644 --- a/docs/docsite/rst/installation/install.rst +++ b/docs/docsite/rst/installation/install.rst @@ -9,7 +9,7 @@ Installation Guide pair: installation; ascender-install pair: installation; configuration -`ascender-install `_ is the supported way to deploy Ascender. It runs Ansible under the hood, driven by a single configuration file, and handles cluster provisioning where supported, the Ascender Operator, and the Ascender resource itself. +`ascender-install `_ is the best way to deploy Ascender. It runs Ansible under the hood, driven by a single configuration file, and handles cluster provisioning where supported, the Ascender Operator, and the Ascender resource itself. To evaluate Ascender on a single machine, start with :ref:`in_quick_start_k3s`. @@ -19,24 +19,20 @@ What the installer does When you run ``./setup.sh``, it: - Installs its own dependencies, including ansible-core, the required collections, and the Python Kubernetes client -- Provisions the cluster, on K3s and RKE2 only, when you set ``kube_install`` +- Provisions the cluster, on K3s only, when you set ``kube_install`` - Stops and disables ``firewalld``, unless you set ``firewalld_disable: false`` - Deploys the Ascender Operator with Kustomize, pinned to ``ASCENDER_OPERATOR_VERSION`` - Creates the namespace, the administrator password secret, and any TLS, custom CA, or external database secrets your configuration calls for - Creates the Ascender resource that the operator reconciles into a running deployment -.. warning:: - - The installer turns off the host firewall by default. Set ``firewalld_disable: false`` to keep it running, and the installer opens ports 6443, 80, and 443 and trusts the cluster networks instead. This setting is not listed in ``default.config.yml``. - Requirements ============= -You run the installer from a machine with ``git``, ``openssl``, and root or sudo access, on x86_64. Supported hosts are Enterprise Linux 8 or 9, meaning Rocky, RHEL, AlmaLinux, CentOS, or Fedora, and Ubuntu or Debian 24 or 26. +You run the installer from a machine with ``git``, ``openssl``, and root or sudo access, on x86_64. Supported hosts are Enterprise Linux 8 or 9 such as Rocky Linux, or Ubuntu or Debian 24 or 26. -For EKS, GKE, and AKS you need Enterprise Linux 9 specifically, plus the relevant CLI tool authenticated. Ubuntu and Debian are not supported for those three. +Unless the machine is also a cluster node, as it is when the installer builds a K3s cluster on it, this is only an administrative host. It runs the install and takes no part in the cluster afterwards, so a small VM is enough. Keep it around, along with the configuration file you used, because upgrades run from the same place. -On K3s or RKE2 this can be the same machine that runs the cluster. For the cloud platforms, use a small administrative host. +For EKS, GKE, and AKS you need Enterprise Linux 9 specifically, plus the relevant CLI tool authenticated. Ubuntu and Debian are not supported for those three. Getting started ================ @@ -46,7 +42,7 @@ Clone the installer:: git clone https://github.com/ctrliq/ascender-install.git cd ascender-install -Create ``custom.config.yml`` with the settings for your deployment. Use ``default.config.yml`` as a reference for the available options rather than a starting point, as it contains settings for every platform and needs heavy editing. The repository also ships ``config_vars.sh``, which generates a configuration file through a series of prompts. +Create ``custom.config.yml`` with the settings for your deployment. Do not copy ``default.config.yml`` as a starting point, as it carries settings for every platform. Install with:: @@ -55,27 +51,45 @@ Install with:: Platforms ========== -Eight platforms are supported: ``k3s``, ``rke2``, ``eks``, ``gke``, ``aks``, ``dkp``, ``tkgi``, and ``ocp``. - -K3s ----- +Eight platforms are supported. Each has its own guide in the installer repository, with a working sample configuration file alongside it. -Covered in :ref:`in_quick_start_k3s`. Set ``kube_install: true`` and the installer creates the cluster for you. +K3s is the only platform where the installer builds the cluster, with ``kube_install: true``. On the cloud platforms it can create the cluster through the provider's API when you set the matching ``*_CLUSTER_STATUS`` to ``provision``. Everywhere else, RKE2 included, the cluster must already exist before you run the installer. -RKE2 ------ - -Suits production, and supports single-node and highly available clusters. The installer does not create an RKE2 cluster, so build it first and run the installer against it. - -EKS, GKE, and AKS ------------------- - -Each needs its own CLI tool authenticated, IAM or role configuration, and a DNS zone. You run these from an Enterprise Linux 9 host. - -DKP, TKGI, and OCP -------------------- +.. list-table:: + :widths: 20 55 25 + :header-rows: 1 -DKP takes one extra setting, ``DKP_CLUSTER_NAME``, naming the cluster to deploy to or create. TKGI and OpenShift follow the common configuration. Check ``default.config.yml`` for platform-specific defaults. + * - Platform + - Notes + - Guide + * - K3s + - Single node, and the installer builds the cluster. The shortest path from a bare machine to a running Ascender + - `K3s `_ + * - RKE2 + - Single node or highly available. You build the cluster, then run the installer against it + - `RKE2 `_ + * - Amazon EKS + - Needs the AWS CLI configured as root and an ACM certificate covering your hostnames + - `EKS `_ + * - Google GKE + - Needs the ``gcloud`` CLI authenticated and a project to deploy into + - `GKE `_ + * - Azure AKS + - Needs the ``az`` CLI authenticated + - `AKS `_ + * - DKP + - Takes one extra setting, ``DKP_CLUSTER_NAME`` + - `DKP `_ + * - TKGI + - Follows the common configuration + - `TKGI `_ + * - OpenShift + - Follows the common configuration + - `OCP `_ + +To install onto a Kubernetes cluster you manage yourself, such as kubeadm, Rancher, or Tanzu, use ``k8s_platform: rke2``. It is the most general of the platform types and assumes the cluster is already running, with an ingress controller, a default storage class, and a kubeconfig at ``~/.kube/config`` readable by root. + +For a worked K3s example with a self-signed certificate, see :ref:`in_quick_start_k3s`. Upgrading ========== @@ -85,210 +99,25 @@ Pull the latest installer first so you pick up any fixes, then raise ``ASCENDER_ git pull sudo ./setup.sh -The upgrade is carried out by the Ascender Operator. +The upgrade is carried out by the Ascender Operator. See `Upgrading `_ for the detail, and `Uninstalling `_ to remove a deployment. .. note:: The operator and Ascender are released independently. Ascender releases are at `ctrliq/ascender `_ and operator releases at `ctrliq/ascender-operator `_. -Configuration reference -======================== - -Kubernetes platform --------------------- - -.. list-table:: - :widths: 30 20 50 - :header-rows: 1 - - * - Variable - - Default - - Description - * - ``k8s_platform`` - - ``eks`` - - Target platform. One of ``k3s``, ``eks``, ``aks``, ``gke``, ``rke2``, ``dkp``, ``tkgi``, ``ocp``. Set this explicitly, as the default is not K3s - * - ``k8s_lb_protocol`` - - ``http`` - - Load balancer protocol. Set to ``https`` to enable TLS, which requires the certificate settings below - * - ``download_kubeconfig`` - - ``false`` - - Copy the kubeconfig from the target host to ``~/.kube/config`` on the installing machine +Configuration +============== -K3s cluster ------------- +``default.config.yml`` in the installer documents every available setting, and each platform guide above ships a working sample configuration alongside it. ``config_vars.sh`` will generate a configuration file through a series of prompts. -These apply when the installer builds the cluster for you. - -.. list-table:: - :widths: 30 20 50 - :header-rows: 1 - - * - Variable - - Default - - Description - * - ``kube_install`` - - ``false`` - - Provision the cluster before deploying Ascender. K3s and RKE2 only - * - ``k3s_master_node_ip`` - - ``127.0.0.1`` - - Address of the K3s node. Set this to the machine's real address - * - ``use_etc_hosts`` - - ``true`` - - Add the Ascender hostname to ``/etc/hosts`` on the node - * - ``firewalld_disable`` - - ``true`` - - Stop and disable ``firewalld``. Set to ``false`` to keep it running with the required ports opened - -Ascender application ---------------------- - -.. list-table:: - :widths: 30 20 50 - :header-rows: 1 - - * - Variable - - Default - - Description - * - ``ASCENDER_HOSTNAME`` - - ``ascender.example.com`` - - DNS-resolvable hostname for the web interface. Required - * - ``ASCENDER_DOMAIN`` - - ``example.com`` - - Base domain for all components. Required on EKS, GKE, and AKS, and unused on K3s and RKE2 - * - ``ASCENDER_NAMESPACE`` - - ``ascender`` - - Namespace for Ascender objects - * - ``ASCENDER_ADMIN_USER`` - - ``admin`` - - Administrator username - * - ``ASCENDER_ADMIN_PASSWORD`` - - ``myadminpassword`` - - Administrator password. Change this before installing - * - ``ASCENDER_IMAGE`` - - ``ghcr.io/ctrliq/ascender`` - - Container image. Change only when using an internal registry - * - ``ASCENDER_VERSION`` - - ``25.5.1`` - - Tag applied to ``ASCENDER_IMAGE`` - * - ``ASCENDER_OPERATOR_VERSION`` - - ``25.5.1`` - - Version of the Ascender Operator - * - ``ascender_replicas`` - - ``1`` - - Number of Ascender web pods - * - ``ascender_garbage_collect_secrets`` - - ``true`` - - When true, the administrator password, secret key, and database credential secrets are deleted if the Ascender resource is removed. Set to ``false`` to keep them - * - ``ascender_setup_playbooks`` - - ``true`` - - Deploy demonstration playbooks after installation - * - ``ascender_image_pull_policy`` - - ``Always`` - - Image pull policy. Set to ``Never`` for offline installs - * - ``ASCENDER_MESH_HOSTNAME`` - - unset - - Hostname for Automation Mesh. Mesh is not configured unless this is set +At minimum you set ``k8s_platform``, ``ASCENDER_HOSTNAME``, and ``ASCENDER_ADMIN_PASSWORD``. Note that ``k8s_platform`` defaults to ``eks``, so set it explicitly even for K3s. .. warning:: - ``ascender_garbage_collect_secrets`` controls whether Kubernetes deletes the secrets when the Ascender resource is removed. Those secrets include the secret key that encrypts stored credentials. Losing them makes an existing database unreadable, so set this to ``false`` where preserving a deployment matters more than tidy cleanup. - -TLS ----- - -Required when ``k8s_lb_protocol`` is ``https``. Certificate handling differs on cloud platforms. - -.. list-table:: - :widths: 30 20 50 - :header-rows: 1 - - * - Variable - - Default - - Description - * - ``tls_crt_path`` - - ``~/ascender.crt`` - - Certificate file in PEM format - * - ``tls_key_path`` - - ``~/ascender.key`` - - Private key file in PEM format - * - ``custom_cacert_bundle`` - - unset - - CA bundle containing your CA certificate and any external CA certificates - * - ``custom_ldap_cacert`` - - unset - - LDAP CA certificate - -Set the certificate paths to ``"{{ playbook_dir }}/../ascender.crt"`` and the matching key when you keep the files in the ``ascender-install`` directory. - -External database ------------------- - -Ascender deploys its own PostgreSQL instance by default. To use an existing server, set the following. - -.. list-table:: - :widths: 30 20 50 - :header-rows: 1 - - * - Variable - - Default - - Description - * - ``ASCENDER_PGSQL_HOST`` - - unset - - PostgreSQL hostname or address - * - ``ASCENDER_PGSQL_PORT`` - - ``5432`` - - Port - * - ``ASCENDER_PGSQL_USER`` - - ``ascender`` - - Username - * - ``ASCENDER_PGSQL_PWD`` - - unset - - Password - * - ``ASCENDER_PGSQL_DB`` - - ``ascenderdb`` - - Database name, which must already exist + ``ascender_garbage_collect_secrets`` defaults to ``true``, which deletes the Kubernetes secrets when the Ascender resource is removed. Those include the secret key that encrypts stored credentials, and without it an existing database is unreadable. Set it to ``false`` where preserving a deployment matters more than tidy cleanup. .. warning:: - The PostgreSQL password cannot contain special characters. This is a limitation of how the installer passes the password through its configuration. - -Storage for the built-in PostgreSQL instance is set with ``POSTGRES_PVC_SIZE_GB`` and ``POSTGRES_STORAGE_CLASS``. Both apply to new installations only. Changing either on an existing deployment does not resize or move the volume. - -Execution environments ------------------------ - -To pull additional images for use as execution environments, add an ``ee_images`` list. Each entry takes a ``name`` used as a label and an ``image`` giving the full registry path:: - - ee_images: - - name: my-custom-ee - image: registry.example.com/namespace/my-custom-ee:latest - -Offline installation ---------------------- - -These apply to air-gapped deployments on K3s, RKE2, and DKP. - -.. list-table:: - :widths: 35 20 45 - :header-rows: 1 + An external PostgreSQL password cannot contain special characters. This is a limitation of how the installer passes it through its configuration. - * - Variable - - Default - - Description - * - ``k8s_offline`` - - ``false`` - - Use local assets rather than pulling from the internet - * - ``k8s_container_registry`` - - empty - - Internal registry and namespace holding the Ascender and operator images. Also sets the operator image path - * - ``k8s_image_pull_secret`` - - ``None`` - - Secret holding credentials for that registry. Leave as ``None`` when no authentication is needed - * - ``k8s_ee_pull_credentials_secret`` - - ``None`` - - Secret holding credentials for the registry serving execution environment images - -Artifacts ----------- - -``tmp_dir`` sets where the installer writes generated manifests, backups, and temporary files, and defaults to ``ascender_install_artifacts/`` inside the cloned repository. +The installer repository also documents `automation mesh `_, `changing hostnames `_, and `backup and restore `_. diff --git a/docs/docsite/rst/installation/manual_install.rst b/docs/docsite/rst/installation/manual_install.rst index 5e0c30f8e..78b30bddc 100644 --- a/docs/docsite/rst/installation/manual_install.rst +++ b/docs/docsite/rst/installation/manual_install.rst @@ -9,9 +9,9 @@ Installing without the installer pair: installation; Kustomize pair: installation; operator -You can deploy the Ascender Operator and create the Ascender resource yourself, without `ascender-install `_. Use this path when you manage your own cluster, deploy through GitOps tooling such as Argo CD or Flux, or run on a host the installer does not support. +`ascender-install `_ is the best way to install Ascender. It does considerably more for you than the steps below, including provisioning the cluster on K3s, so start there if you can. See :ref:`in_install`. -The installer is the supported path and does more for you, including provisioning the cluster on K3s and RKE2. See :ref:`in_install`. +This page covers deploying the operator and creating the Ascender resource by hand, for readers who manage their own cluster or deploy through GitOps tooling. The deployment is two steps: install the operator, then create an ``AWX`` resource for the operator to reconcile. @@ -54,25 +54,24 @@ This creates the namespace, the ``awxs``, ``awxbackups``, ``awxrestores``, and ` Create the administrator secret ================================ -Supply the administrator password yourself so you know what it is. The operator generates one otherwise. Save this as ``admin-secret.yml``:: +Supply the administrator password yourself so you know what it is. The operator generates one otherwise:: - apiVersion: v1 - kind: Secret - metadata: - name: ascender-app-admin-password - namespace: ascender - stringData: - password: + kubectl create secret generic ascender-app-admin-password -n ascender \ + --from-literal=password= -Apply it:: +The key must be ``password``. The operator looks for a secret named after the Ascender resource, so ``ascender-app-admin-password`` is found automatically for a resource named ``ascender-app``. + +Create the TLS secret +====================== - kubectl apply -f admin-secret.yml +Terminate TLS at the ingress with a certificate for the hostname you will use:: + + kubectl create secret tls ascender-tls-secret -n ascender \ + --cert=ascender.crt --key=ascender.key Create the Ascender resource ============================= -The resource is ``kind: AWX``, not an Ascender-named kind. The operator keeps the upstream API group, so all three custom resources are under ``awx.ansible.com/v1beta1``. - The following is a working starting point for a cluster with an ingress controller. Save it as ``ascender.yml``:: apiVersion: awx.ansible.com/v1beta1 @@ -97,12 +96,17 @@ The following is a working starting point for a cluster with an ingress controll ingress_type: ingress ingress_path: "/" ingress_path_type: Prefix + ingress_class_name: nginx + ingress_tls_secret: ascender-tls-secret hostname: ascender.example.com postgres_data_volume_init: true + postgres_storage_class: + postgres_storage_requirements: + requests: + storage: 20Gi extra_settings: - setting: CSRF_TRUSTED_ORIGINS value: - - http://ascender.example.com - https://ascender.example.com Apply it and watch the operator build the deployment:: @@ -114,19 +118,18 @@ Apply it and watch the operator build the deployment:: ``postgres_data_volume_init`` sets ownership on the database volume with an init container. Many storage classes provision volumes owned by root, which the PostgreSQL container cannot write to. The operator's default commands already do the right thing, so you rarely need ``postgres_init_container_commands``. OpenShift manages volume ownership itself. -Set ``CSRF_TRUSTED_ORIGINS`` to the URLs you actually reach Ascender on. Without it, signing in can fail with a CSRF error even though the pods are healthy, because the scheme Django computes behind an ingress does not always match the one the browser sent. Listing both schemes, as the installer does, covers the common cases. +``ingress_class_name`` and ``postgres_storage_class`` both fall back to the cluster default when unset. Name them explicitly if the cluster has more than one, or no default. List what is available with ``kubectl get ingressclass`` and ``kubectl get storageclass``. -Pin ``image_version``. Left unset, the operator falls back to ``latest``, so the version you get depends on when the image was last pushed. +The resource accepts far more than this example uses. Every field is described in the custom resource definition, which you can read from the cluster:: -TLS -==== + kubectl explain awx.spec + kubectl explain awx.spec.postgres_storage_class -To terminate TLS at the ingress, create a secret holding the certificate and reference it from the resource:: +The Ascender Operator repository documents individual topics in more depth under `advanced configuration `_, covering things like persisting the projects directory, security contexts, node assignment, and horizontal pod autoscaling. - kubectl create secret tls ascender-tls-secret -n ascender \ - --cert=ascender.crt --key=ascender.key +Set ``CSRF_TRUSTED_ORIGINS`` to the URL you actually reach Ascender on, scheme included. Without it, signing in can fail with a CSRF error even though the pods are healthy, because the scheme Django computes behind an ingress does not always match the one the browser sent. -Then add ``ingress_tls_secret: ascender-tls-secret`` to the spec, and use the ``https`` URL in ``CSRF_TRUSTED_ORIGINS``. +Pin ``image_version``. Left unset, the operator falls back to ``latest``, so the version you get depends on when the image was last pushed. Using an external database =========================== diff --git a/docs/docsite/rst/installation/quick_start_k3s.rst b/docs/docsite/rst/installation/quick_start_k3s.rst index c39386084..1d7c8db7c 100644 --- a/docs/docsite/rst/installation/quick_start_k3s.rst +++ b/docs/docsite/rst/installation/quick_start_k3s.rst @@ -1,38 +1,25 @@ .. _in_quick_start_k3s: -****************************** -Single-node install on K3s -****************************** +******************** +Local Quick Start +******************** .. index:: single: installation pair: installation; K3s - pair: installation; evaluation + pair: installation; quick start -K3s is the fastest way to get a working Ascender instance. The installer provisions a single-node K3s cluster and deploys Ascender onto it, so you do not need an existing Kubernetes cluster. +Get Ascender running on a single machine. The installer builds a K3s cluster and deploys Ascender onto it, so you need nothing but the machine itself. -This gets you an evaluation deployment on one machine. For production, see :ref:`in_install`. +Before you start +================= -Requirements -============= - -You need a machine with: - -- 2 CPUs -- 8 GB memory -- 20 GB free disk -- Enterprise Linux 8 or 9, or Ubuntu or Debian 24 or 26 -- ``git`` and ``openssl``, installed with ``sudo dnf install -y git openssl`` -- Root or sudo access - -.. warning:: - - The installer stops and disables ``firewalld`` by default. Set ``firewalld_disable: false`` in your configuration to keep it running, in which case the installer opens ports 6443, 80, and 443 and trusts the cluster networks instead. +You need a machine with 2 CPUs, 8 GB memory, and 20 GB free disk, running Enterprise Linux 8 or 9 such as Rocky Linux, or Ubuntu or Debian 24 or 26, with root or sudo access. Install ``git`` and ``openssl`` if they are missing. Get the installer ================== -Clone the installer and change into it:: +:: git clone https://github.com/ctrliq/ascender-install.git cd ascender-install @@ -40,20 +27,18 @@ Clone the installer and change into it:: Create a certificate ===================== -Generate a self-signed certificate. Run this from inside the ``ascender-install`` directory so the installer finds the files without further configuration. Replace ```` with the address of your machine:: +Run this from the ``ascender-install`` directory so the installer finds the files. Replace ```` with your machine's address:: openssl req -x509 -newkey rsa:4096 -keyout ascender.key -out ascender.crt -days 365 -nodes \ -subj "/CN=ascender..nip.io" \ -addext "subjectAltName=DNS:ascender..nip.io" -.. note:: - - This uses `nip.io `_, a public wildcard DNS service, so that ``ascender..nip.io`` resolves to your machine with no DNS setup. Use your own hostname for anything beyond an evaluation. +``nip.io`` is a wildcard DNS service, so ``ascender..nip.io`` resolves to your machine with no DNS setup. Use a real hostname for anything beyond evaluation. -Configure the deployment -========================= +Configure +========== -Create ``custom.config.yml`` in the ``ascender-install`` directory, again replacing ````:: +Create ``custom.config.yml`` alongside the certificate, replacing ```` with your machine's address and ```` with the password you want:: k8s_platform: k3s k8s_lb_protocol: https @@ -73,44 +58,33 @@ Create ``custom.config.yml`` in the ``ascender-install`` directory, again replac ascender_setup_playbooks: true -Set ``ASCENDER_ADMIN_PASSWORD`` before you install. ``default.config.yml`` lists the available settings, but do not copy it wholesale. It carries defaults for every supported platform. - -.. note:: - - ``kube_install: true`` tells the installer to build the K3s cluster for you. This works on K3s and RKE2 only. On every other platform the cluster must already exist. +Set ``ASCENDER_ADMIN_PASSWORD`` before you install. Run the installer ================== -Run the installer from the same machine. The default ``inventory`` file targets ``localhost``, so it needs no changes:: +The default ``inventory`` targets ``localhost``, so it needs no changes:: sudo ./setup.sh -A successful run ends with:: - - ASCENDER SUCCESSFULLY SETUP +A successful run ends with ``ASCENDER SUCCESSFULLY SETUP``. -Verify the deployment -====================== +Verify +======= -The installer writes the kubeconfig for the user it ran as, so under ``sudo`` it belongs to root. Copy it to your own user before using ``kubectl``:: +The installer writes the kubeconfig for the user it ran as, so under ``sudo`` it belongs to root. Copy it to your own user first:: sudo cp /root/.kube/config ~/.kube/config sudo chown $(id -u):$(id -g) ~/.kube/config - -Confirm the pods are running:: - kubectl get pods -n ascender -Then open ``https://ascender..nip.io`` and sign in with the administrator credentials from your configuration file. Your browser warns about the self-signed certificate, which is expected. +Open ``https://ascender..nip.io`` and sign in. Your browser warns about the self-signed certificate, which is expected. If pods do not reach ``Running``, the operator log usually says why:: kubectl logs -n ascender deployment/awx-operator-controller-manager -Next steps -=========== +Next +===== Work through the :ref:`Ascender Quickstart ` to run your first playbook. - -For a production deployment, read :ref:`in_install` for the full configuration reference and the other supported platforms. diff --git a/docs/docsite/rst/upgrade_migration/upgrade_considerations.rst b/docs/docsite/rst/upgrade_migration/upgrade_considerations.rst index c8bb4d602..d60656274 100644 --- a/docs/docsite/rst/upgrade_migration/upgrade_considerations.rst +++ b/docs/docsite/rst/upgrade_migration/upgrade_considerations.rst @@ -19,11 +19,9 @@ Upgrade Planning This section covers changes that you should keep in mind as you attempt to upgrade your Ascender instance. -- Clustered upgrades require special attention to instance and instance groups prior to starting the upgrade. See `:ref:`ag_clustering` for details. +- Clustered upgrades require special attention to instance and instance groups prior to starting the upgrade. See :ref:`ag_clustering` for details. +- Back up the deployment before upgrading. See :ref:`ag_backup_restore`. +For the upgrade procedure itself, see :ref:`in_install`. -Running the Setup Playbook ----------------------------- - -.. include:: ../common/setup-playbook.rst diff --git a/docs/docsite/rst/userguide/overview.rst b/docs/docsite/rst/userguide/overview.rst index a1c78bae6..03f99bdcd 100644 --- a/docs/docsite/rst/userguide/overview.rst +++ b/docs/docsite/rst/userguide/overview.rst @@ -69,7 +69,7 @@ Backup and Restore .. index:: pair: features; backup and restore -The ability to backup and restore your system(s) has been integrated into the Ascender setup playbook, making it easy for you to backup and replicate your instance as needed. +Ascender is backed up and restored through the Ascender Operator, which captures the database, the secrets that encrypt it, and the deployment configuration. See :ref:`ag_backup_restore`. Ansible Galaxy Integration ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From 3d5b6c0514bae30ad805c7ce77819f141c86060a Mon Sep 17 00:00:00 2001 From: Stephen Simpson Date: Mon, 31 Aug 2026 08:12:07 -0500 Subject: [PATCH 5/5] docs: correct wording in uninstall instructions for clarity Signed-off-by: Stephen Simpson --- docs/docsite/rst/administration/init_script.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docsite/rst/administration/init_script.rst b/docs/docsite/rst/administration/init_script.rst index dd1d4231c..d0a72fa91 100644 --- a/docs/docsite/rst/administration/init_script.rst +++ b/docs/docsite/rst/administration/init_script.rst @@ -21,7 +21,7 @@ To restart an Ascender instance, you must first kill the container and restart i .. these instructions will need to be fleshed out (TBD) -To uninstall you Ascender instance: https://github.com/ctrliq/ascender-operator/blob/devel/docs/uninstall/uninstall.md +To uninstall your Ascender instance: https://github.com/ctrliq/ascender-operator/blob/devel/docs/uninstall/uninstall.md .. these instructions will be ported over to here in the near future (TBD)