<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.williams-net.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=DrEdWilliams</id>
	<title>WilliamsNet Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.williams-net.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=DrEdWilliams"/>
	<link rel="alternate" type="text/html" href="https://wiki.williams-net.org/wiki/Special:Contributions/DrEdWilliams"/>
	<updated>2026-06-01T01:38:37Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.40.1</generator>
	<entry>
		<id>https://wiki.williams-net.org/index.php?title=GitLab_V18_Upgrade&amp;diff=721</id>
		<title>GitLab V18 Upgrade</title>
		<link rel="alternate" type="text/html" href="https://wiki.williams-net.org/index.php?title=GitLab_V18_Upgrade&amp;diff=721"/>
		<updated>2025-06-13T22:52:09Z</updated>

		<summary type="html">&lt;p&gt;DrEdWilliams: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Once again, the GitLab team has introduced a breaking change in the upgrade from v17 to v18.  The PostgreSQL database version in v18+ is 16 (instead of 14 in previous versions).  The upgrade of the database must be done in multiple steps: &lt;br /&gt;
* running their database_upgrade script before (to capture the state of the deployment)&lt;br /&gt;
* deleting the database PVCs&lt;br /&gt;
* performing the upgrade (without the migrations step)&lt;br /&gt;
* running their database_upgrade script again to restore the database and restart the services.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
All this is documented on their documentation site:&lt;br /&gt;
&lt;br /&gt;
 https://docs.gitlab.com/charts/installation/database_upgrade/#steps-for-upgrading-the-bundled-postgresql&lt;br /&gt;
&lt;br /&gt;
This is all well and good -- it&#039;s been required before ... but the postgresql user in the new configuration doesn&#039;t have all the needed permissions to do the database restore.  Searching for the error message in google gemini results in the following response (which solved the problem).&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;permission denied for function pg_ls_waldir&amp;quot; error during a GitLab upgrade (especially with Helm charts) to a newer version of GitLab or PostgreSQL usually indicates that the database user GitLab is using **lacks the necessary privileges** to execute this specific PostgreSQL function.&lt;br /&gt;
&lt;br /&gt;
The function `pg_ls_waldir()` (or `pg_ls_dir()` in older PostgreSQL versions) is a function that allows listing the contents of the PostgreSQL Write-Ahead Log (WAL) directory. This is often used for monitoring, replication, or certain administrative tasks.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s why this happens and how to resolve it in a Helm-based GitLab deployment:&lt;br /&gt;
&lt;br /&gt;
==Why it happens:==&lt;br /&gt;
&lt;br /&gt;
* **Security hardening:** Newer PostgreSQL versions or stricter configurations of GitLab&#039;s chart might restrict access to sensitive functions like `pg_ls_waldir()` to only superusers or specific roles (like `pg_monitor`).&lt;br /&gt;
* **Non-superuser GitLab user:** GitLab typically runs with a non-superuser database user for security reasons. This user might not have the permissions by default.&lt;br /&gt;
* **Monitoring tools:** Sometimes, this error isn&#039;t from GitLab&#039;s core migrations but from a monitoring tool (like `postgres_exporter` for Prometheus) trying to gather WAL-related metrics. If the GitLab upgrade involves an upgrade of the bundled PostgreSQL or a change in how permissions are managed, this can manifest.&lt;br /&gt;
&lt;br /&gt;
==How to resolve it (with Helm):==&lt;br /&gt;
&lt;br /&gt;
The solution involves granting the necessary permissions to the database user that GitLab uses. Since you&#039;re using Helm, you&#039;ll generally achieve this by either:&lt;br /&gt;
&lt;br /&gt;
1.  **Running a `psql` command manually (temporary/quick fix):** This is useful for immediate unblocking, but might not persist across pod restarts if your database setup doesn&#039;t automatically apply grants.&lt;br /&gt;
2.  **Modifying your Helm `values.yaml` to apply grants during initialization (recommended for persistence).**&lt;br /&gt;
&lt;br /&gt;
==Method 1: Manual Grant (via `kubectl exec` and `psql`)==&lt;br /&gt;
&lt;br /&gt;
This method is good for immediate troubleshooting.&lt;br /&gt;
&lt;br /&gt;
1.  **Find your PostgreSQL pod:**&lt;br /&gt;
If GitLab is managing its own PostgreSQL (the default for the Helm chart), find the PostgreSQL primary pod:&lt;br /&gt;
&lt;br /&gt;
 kubectl get pods -l app=postgresql,release=&amp;lt;your-gitlab-release-name&amp;gt;,statefulset=postgresql-ha-postgresql -n &amp;lt;your-gitlab-namespace&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you&#039;re using an external PostgreSQL, you&#039;ll need to connect to it directly using a PostgreSQL client.&lt;br /&gt;
&lt;br /&gt;
2.  **Exec into the PostgreSQL pod (or connect externally):**&lt;br /&gt;
 kubectl exec -it &amp;lt;postgresql-primary-pod-name&amp;gt; -n &amp;lt;your-gitlab-namespace&amp;gt; -- bash&lt;br /&gt;
&lt;br /&gt;
(Once inside, you might need to become the `postgres` user: `su - postgres`)&lt;br /&gt;
&lt;br /&gt;
3.  **Connect to the GitLab database with `psql`:**&lt;br /&gt;
 psql -d gitlabhq_production -U postgres # Or your PostgreSQL superuser&lt;br /&gt;
&lt;br /&gt;
(Replace `gitlabhq_production` if your database name is different, and `postgres` with your superuser if it&#039;s not the default.)&lt;br /&gt;
&lt;br /&gt;
4.  **Grant the permission:**&lt;br /&gt;
Identify the GitLab database user (it&#039;s often `gitlab` or `gitlab-rails` if you&#039;re using the default Helm chart). You can check it in your `values.yaml` or in the `webservice` pod&#039;s environment variables.&lt;br /&gt;
 GRANT EXECUTE ON FUNCTION pg_catalog.pg_ls_waldir() TO &amp;lt;gitlab_database_user&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
For example, if your GitLab user is `gitlab`:&lt;br /&gt;
 GRANT EXECUTE ON FUNCTION pg_catalog.pg_ls_waldir() TO gitlab;&lt;br /&gt;
&lt;br /&gt;
You might also consider granting the `pg_monitor` role to the GitLab user if that&#039;s appropriate for your security model and the version of PostgreSQL:&lt;br /&gt;
 GRANT pg_monitor TO &amp;lt;gitlab_database_user&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The `pg_monitor` role provides access to several monitoring-related functions, including `pg_ls_waldir()`, so this can be a more comprehensive solution.&lt;br /&gt;
&lt;br /&gt;
5.  **Exit `psql` and the pod:**&lt;br /&gt;
 \q&lt;br /&gt;
 exit&lt;br /&gt;
&lt;br /&gt;
6.  **Retry the GitLab upgrade:**&lt;br /&gt;
 helm upgrade &amp;lt;your-gitlab-release-name&amp;gt; gitlab/gitlab -f your_values.yaml --version &amp;lt;new-gitlab-version&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Method 2: Persistent Grant (via Helm `values.yaml`)==&lt;br /&gt;
&lt;br /&gt;
This is the preferred method for Helm deployments as it ensures the grant is applied consistently.&lt;br /&gt;
&lt;br /&gt;
You can inject an initialization script into the PostgreSQL container that grants the necessary permissions. This typically involves using the `postgresql.initdb` configuration in your `values.yaml`.&lt;br /&gt;
&lt;br /&gt;
===Example `values.yaml` addition:===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # Add this to your values.yaml file&lt;br /&gt;
 postgresql:&lt;br /&gt;
   # This section assumes you are using the bundled PostgreSQL with the GitLab chart.&lt;br /&gt;
   # If using an external PostgreSQL, you would need to run this command on your external DB.&lt;br /&gt;
   initdb:&lt;br /&gt;
     ## @param initdb.scripts Allows mounting scripts into /docker-entrypoint-initdb.d/ to be executed at first boot of the Postgres container&lt;br /&gt;
     ## This can be used for custom grants or other database initialization.&lt;br /&gt;
     scripts:&lt;br /&gt;
       grant-wal-permissions.sql: |&lt;br /&gt;
         DO&lt;br /&gt;
         $do$&lt;br /&gt;
         BEGIN&lt;br /&gt;
           IF EXISTS (SELECT 1 FROM pg_catalog.pg_proc p JOIN pg_catalog.pg_namespace n ON p.pronamespace = n.oid WHERE p.proname = &#039;pg_ls_waldir&#039; AND n.nspname = &#039;pg_catalog&#039;) THEN&lt;br /&gt;
             GRANT EXECUTE ON FUNCTION pg_catalog.pg_ls_waldir() TO gitlab; -- Replace &#039;gitlab&#039; with your actual GitLab database user if different&lt;br /&gt;
           END IF;&lt;br /&gt;
           -- Also consider granting pg_monitor role if appropriate for your security model&lt;br /&gt;
           IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = &#039;pg_monitor&#039;) THEN&lt;br /&gt;
             GRANT pg_monitor TO gitlab; -- Replace &#039;gitlab&#039; with your actual GitLab database user if different&lt;br /&gt;
           END IF;&lt;br /&gt;
         END&lt;br /&gt;
         $do$;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Explanation of the `initdb.scripts` addition:===&lt;br /&gt;
&lt;br /&gt;
* `initdb.scripts`: This section allows you to define custom SQL scripts that will be run when the PostgreSQL container is first initialized.&lt;br /&gt;
* `grant-wal-permissions.sql`: This is a descriptive name for your script.&lt;br /&gt;
* `DO $$BEGIN ... END$$;`: This is an anonymous PL/pgSQL block, which allows for conditional logic (like checking if the function exists before trying to grant).&lt;br /&gt;
* `IF EXISTS (...) THEN ... END IF;`: This checks if `pg_ls_waldir` function exists (useful for PostgreSQL version compatibility) and if the `pg_monitor` role exists before attempting the `GRANT`.&lt;br /&gt;
* `TO gitlab;`: **Crucially, replace `gitlab` with the actual database user GitLab uses.** This is usually configured in your GitLab Helm chart&#039;s `global.psql.username` or `global.postgresql.username` setting, or if you&#039;re using the bundled PostgreSQL, it&#039;s often `gitlab`.&lt;br /&gt;
&lt;br /&gt;
===After modifying `values.yaml`:===&lt;br /&gt;
&lt;br /&gt;
Run the `helm upgrade` command again:&lt;br /&gt;
&lt;br /&gt;
 helm upgrade &amp;lt;your-gitlab-release-name&amp;gt; gitlab/gitlab -f your_values.yaml --version &amp;lt;new-gitlab-version&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Important Notes:==&lt;br /&gt;
&lt;br /&gt;
* **Database Restart:** For the `initdb.scripts` method, the script runs only on *initialization* of the PostgreSQL container. If your PostgreSQL pods are already running, you might need to force a recreation of the PostgreSQL primary pod for the `initdb` script to execute. Be careful doing this in a production environment as it will cause a brief database downtime. A common way to force recreation after an `initdb` change is to taint the old pods or delete them gracefully, allowing Kubernetes to reschedule new ones.&lt;br /&gt;
* **GitLab Database User:** Double-check the exact database user name GitLab is using. This is critical for granting permissions to the correct user.&lt;br /&gt;
* **PostgreSQL Version:** The `pg_ls_waldir()` function is present in PostgreSQL 10 and newer. If you are on a very old PostgreSQL version, the function might be `pg_ls_dir()`, but GitLab 18 definitely requires a modern PostgreSQL.&lt;br /&gt;
* **Backups:** Always ensure you have a complete and tested backup of your GitLab instance and its database before performing any major upgrade or making database permission changes.&lt;br /&gt;
&lt;br /&gt;
By applying the correct `GRANT` statement to the appropriate GitLab database user, you should resolve the &amp;quot;permission denied for function pg_ls_waldir&amp;quot; error and allow your GitLab upgrade to proceed.&lt;/div&gt;</summary>
		<author><name>DrEdWilliams</name></author>
	</entry>
	<entry>
		<id>https://wiki.williams-net.org/index.php?title=GitLab_V18_Upgrade&amp;diff=720</id>
		<title>GitLab V18 Upgrade</title>
		<link rel="alternate" type="text/html" href="https://wiki.williams-net.org/index.php?title=GitLab_V18_Upgrade&amp;diff=720"/>
		<updated>2025-06-13T22:47:56Z</updated>

		<summary type="html">&lt;p&gt;DrEdWilliams: Created page with &amp;quot;Once again, the GitLab team has introduced a breaking change in the upgrade from v17 to v18.  The PostgreSQL database version in v18+ is 16 (instead of 14 in previous versions).  The upgrade of the database must be done in multiple steps:  * running their database_upgrade script before (to capture the state of the deployment) * deleting the database PVCs * performing the upgrade (without the migrations step) * running their database_upgrade script again to restore the da...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Once again, the GitLab team has introduced a breaking change in the upgrade from v17 to v18.  The PostgreSQL database version in v18+ is 16 (instead of 14 in previous versions).  The upgrade of the database must be done in multiple steps: &lt;br /&gt;
* running their database_upgrade script before (to capture the state of the deployment)&lt;br /&gt;
* deleting the database PVCs&lt;br /&gt;
* performing the upgrade (without the migrations step)&lt;br /&gt;
* running their database_upgrade script again to restore the database and restarting the services.&lt;br /&gt;
&lt;br /&gt;
This is all well and good -- it&#039;s been required before ... but the postgresql user in the new configuration doesn&#039;t have all the needed permissions to do the database restore.  Searching for the error message in google gemini results in the following response (which solved the problem).&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;permission denied for function pg_ls_waldir&amp;quot; error during a GitLab upgrade (especially with Helm charts) to a newer version of GitLab or PostgreSQL usually indicates that the database user GitLab is using **lacks the necessary privileges** to execute this specific PostgreSQL function.&lt;br /&gt;
&lt;br /&gt;
The function `pg_ls_waldir()` (or `pg_ls_dir()` in older PostgreSQL versions) is a function that allows listing the contents of the PostgreSQL Write-Ahead Log (WAL) directory. This is often used for monitoring, replication, or certain administrative tasks.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s why this happens and how to resolve it in a Helm-based GitLab deployment:&lt;br /&gt;
&lt;br /&gt;
==Why it happens:==&lt;br /&gt;
&lt;br /&gt;
* **Security hardening:** Newer PostgreSQL versions or stricter configurations of GitLab&#039;s chart might restrict access to sensitive functions like `pg_ls_waldir()` to only superusers or specific roles (like `pg_monitor`).&lt;br /&gt;
* **Non-superuser GitLab user:** GitLab typically runs with a non-superuser database user for security reasons. This user might not have the permissions by default.&lt;br /&gt;
* **Monitoring tools:** Sometimes, this error isn&#039;t from GitLab&#039;s core migrations but from a monitoring tool (like `postgres_exporter` for Prometheus) trying to gather WAL-related metrics. If the GitLab upgrade involves an upgrade of the bundled PostgreSQL or a change in how permissions are managed, this can manifest.&lt;br /&gt;
&lt;br /&gt;
==How to resolve it (with Helm):==&lt;br /&gt;
&lt;br /&gt;
The solution involves granting the necessary permissions to the database user that GitLab uses. Since you&#039;re using Helm, you&#039;ll generally achieve this by either:&lt;br /&gt;
&lt;br /&gt;
1.  **Running a `psql` command manually (temporary/quick fix):** This is useful for immediate unblocking, but might not persist across pod restarts if your database setup doesn&#039;t automatically apply grants.&lt;br /&gt;
2.  **Modifying your Helm `values.yaml` to apply grants during initialization (recommended for persistence).**&lt;br /&gt;
&lt;br /&gt;
==Method 1: Manual Grant (via `kubectl exec` and `psql`)==&lt;br /&gt;
&lt;br /&gt;
This method is good for immediate troubleshooting.&lt;br /&gt;
&lt;br /&gt;
1.  **Find your PostgreSQL pod:**&lt;br /&gt;
If GitLab is managing its own PostgreSQL (the default for the Helm chart), find the PostgreSQL primary pod:&lt;br /&gt;
&lt;br /&gt;
 kubectl get pods -l app=postgresql,release=&amp;lt;your-gitlab-release-name&amp;gt;,statefulset=postgresql-ha-postgresql -n &amp;lt;your-gitlab-namespace&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you&#039;re using an external PostgreSQL, you&#039;ll need to connect to it directly using a PostgreSQL client.&lt;br /&gt;
&lt;br /&gt;
2.  **Exec into the PostgreSQL pod (or connect externally):**&lt;br /&gt;
 kubectl exec -it &amp;lt;postgresql-primary-pod-name&amp;gt; -n &amp;lt;your-gitlab-namespace&amp;gt; -- bash&lt;br /&gt;
&lt;br /&gt;
(Once inside, you might need to become the `postgres` user: `su - postgres`)&lt;br /&gt;
&lt;br /&gt;
3.  **Connect to the GitLab database with `psql`:**&lt;br /&gt;
 psql -d gitlabhq_production -U postgres # Or your PostgreSQL superuser&lt;br /&gt;
&lt;br /&gt;
(Replace `gitlabhq_production` if your database name is different, and `postgres` with your superuser if it&#039;s not the default.)&lt;br /&gt;
&lt;br /&gt;
4.  **Grant the permission:**&lt;br /&gt;
Identify the GitLab database user (it&#039;s often `gitlab` or `gitlab-rails` if you&#039;re using the default Helm chart). You can check it in your `values.yaml` or in the `webservice` pod&#039;s environment variables.&lt;br /&gt;
 GRANT EXECUTE ON FUNCTION pg_catalog.pg_ls_waldir() TO &amp;lt;gitlab_database_user&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
For example, if your GitLab user is `gitlab`:&lt;br /&gt;
 GRANT EXECUTE ON FUNCTION pg_catalog.pg_ls_waldir() TO gitlab;&lt;br /&gt;
&lt;br /&gt;
You might also consider granting the `pg_monitor` role to the GitLab user if that&#039;s appropriate for your security model and the version of PostgreSQL:&lt;br /&gt;
 GRANT pg_monitor TO &amp;lt;gitlab_database_user&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The `pg_monitor` role provides access to several monitoring-related functions, including `pg_ls_waldir()`, so this can be a more comprehensive solution.&lt;br /&gt;
&lt;br /&gt;
5.  **Exit `psql` and the pod:**&lt;br /&gt;
 \q&lt;br /&gt;
 exit&lt;br /&gt;
&lt;br /&gt;
6.  **Retry the GitLab upgrade:**&lt;br /&gt;
 helm upgrade &amp;lt;your-gitlab-release-name&amp;gt; gitlab/gitlab -f your_values.yaml --version &amp;lt;new-gitlab-version&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Method 2: Persistent Grant (via Helm `values.yaml`)==&lt;br /&gt;
&lt;br /&gt;
This is the preferred method for Helm deployments as it ensures the grant is applied consistently.&lt;br /&gt;
&lt;br /&gt;
You can inject an initialization script into the PostgreSQL container that grants the necessary permissions. This typically involves using the `postgresql.initdb` configuration in your `values.yaml`.&lt;br /&gt;
&lt;br /&gt;
===Example `values.yaml` addition:===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # Add this to your values.yaml file&lt;br /&gt;
 postgresql:&lt;br /&gt;
   # This section assumes you are using the bundled PostgreSQL with the GitLab chart.&lt;br /&gt;
   # If using an external PostgreSQL, you would need to run this command on your external DB.&lt;br /&gt;
   initdb:&lt;br /&gt;
     ## @param initdb.scripts Allows mounting scripts into /docker-entrypoint-initdb.d/ to be executed at first boot of the Postgres container&lt;br /&gt;
     ## This can be used for custom grants or other database initialization.&lt;br /&gt;
     scripts:&lt;br /&gt;
       grant-wal-permissions.sql: |&lt;br /&gt;
         DO&lt;br /&gt;
         $do$&lt;br /&gt;
         BEGIN&lt;br /&gt;
           IF EXISTS (SELECT 1 FROM pg_catalog.pg_proc p JOIN pg_catalog.pg_namespace n ON p.pronamespace = n.oid WHERE p.proname = &#039;pg_ls_waldir&#039; AND n.nspname = &#039;pg_catalog&#039;) THEN&lt;br /&gt;
             GRANT EXECUTE ON FUNCTION pg_catalog.pg_ls_waldir() TO gitlab; -- Replace &#039;gitlab&#039; with your actual GitLab database user if different&lt;br /&gt;
           END IF;&lt;br /&gt;
           -- Also consider granting pg_monitor role if appropriate for your security model&lt;br /&gt;
           IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = &#039;pg_monitor&#039;) THEN&lt;br /&gt;
             GRANT pg_monitor TO gitlab; -- Replace &#039;gitlab&#039; with your actual GitLab database user if different&lt;br /&gt;
           END IF;&lt;br /&gt;
         END&lt;br /&gt;
         $do$;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Explanation of the `initdb.scripts` addition:===&lt;br /&gt;
&lt;br /&gt;
* `initdb.scripts`: This section allows you to define custom SQL scripts that will be run when the PostgreSQL container is first initialized.&lt;br /&gt;
* `grant-wal-permissions.sql`: This is a descriptive name for your script.&lt;br /&gt;
* `DO $$BEGIN ... END$$;`: This is an anonymous PL/pgSQL block, which allows for conditional logic (like checking if the function exists before trying to grant).&lt;br /&gt;
* `IF EXISTS (...) THEN ... END IF;`: This checks if `pg_ls_waldir` function exists (useful for PostgreSQL version compatibility) and if the `pg_monitor` role exists before attempting the `GRANT`.&lt;br /&gt;
* `TO gitlab;`: **Crucially, replace `gitlab` with the actual database user GitLab uses.** This is usually configured in your GitLab Helm chart&#039;s `global.psql.username` or `global.postgresql.username` setting, or if you&#039;re using the bundled PostgreSQL, it&#039;s often `gitlab`.&lt;br /&gt;
&lt;br /&gt;
===After modifying `values.yaml`:===&lt;br /&gt;
&lt;br /&gt;
Run the `helm upgrade` command again:&lt;br /&gt;
&lt;br /&gt;
 helm upgrade &amp;lt;your-gitlab-release-name&amp;gt; gitlab/gitlab -f your_values.yaml --version &amp;lt;new-gitlab-version&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Important Notes:==&lt;br /&gt;
&lt;br /&gt;
* **Database Restart:** For the `initdb.scripts` method, the script runs only on *initialization* of the PostgreSQL container. If your PostgreSQL pods are already running, you might need to force a recreation of the PostgreSQL primary pod for the `initdb` script to execute. Be careful doing this in a production environment as it will cause a brief database downtime. A common way to force recreation after an `initdb` change is to taint the old pods or delete them gracefully, allowing Kubernetes to reschedule new ones.&lt;br /&gt;
* **GitLab Database User:** Double-check the exact database user name GitLab is using. This is critical for granting permissions to the correct user.&lt;br /&gt;
* **PostgreSQL Version:** The `pg_ls_waldir()` function is present in PostgreSQL 10 and newer. If you are on a very old PostgreSQL version, the function might be `pg_ls_dir()`, but GitLab 18 definitely requires a modern PostgreSQL.&lt;br /&gt;
* **Backups:** Always ensure you have a complete and tested backup of your GitLab instance and its database before performing any major upgrade or making database permission changes.&lt;br /&gt;
&lt;br /&gt;
By applying the correct `GRANT` statement to the appropriate GitLab database user, you should resolve the &amp;quot;permission denied for function pg_ls_waldir&amp;quot; error and allow your GitLab upgrade to proceed.&lt;/div&gt;</summary>
		<author><name>DrEdWilliams</name></author>
	</entry>
	<entry>
		<id>https://wiki.williams-net.org/index.php?title=Repair_GRUB_Installation&amp;diff=719</id>
		<title>Repair GRUB Installation</title>
		<link rel="alternate" type="text/html" href="https://wiki.williams-net.org/index.php?title=Repair_GRUB_Installation&amp;diff=719"/>
		<updated>2025-05-17T18:57:04Z</updated>

		<summary type="html">&lt;p&gt;DrEdWilliams: /* Reinstall GRUB */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Unlike most other problems where you have a (mostly) functioning Linux system to work with, if your GRUB install gets trashed you are almost literally toast.&lt;br /&gt;
&lt;br /&gt;
== How it happens ==&lt;br /&gt;
It doesn&#039;t really take much to mess with your GRUB configuration.  Fortunately, it lives in an infrequently accessed part of your filesystem (/boot) and survives by obscurity.  The biggest risk of corruption is actually when applying an update to the GRUB software -- if that gets interrupted and you don&#039;t have a chance to re-run the update (i.e. the system freezes) you are in trouble.&lt;br /&gt;
&lt;br /&gt;
== Resources ==&lt;br /&gt;
As mentioned above, if you can&#039;t boot, you don&#039;t have the usual suite of tools to help you fix the problem -- but most major distributions offer &amp;quot;live&amp;quot; CD/DVD ISOs that allow you to &#039;try before you buy&#039;.  This can provide enough of a workable system to allow you to bootstrap your way to a solution.  Simply download a recent ISO image of a live system and put it somewhere you can boot from.  Note that Ubuntu related distribution ISOs (including kubuntu) operate in this mode by default -- you boot from the ISO and it gives you an option to install from the live system.  Other OS distributions have separate &#039;live&#039; ISOs.&lt;br /&gt;
&lt;br /&gt;
For ubuntu related distributions, there is also a dedicated rescue disk:&lt;br /&gt;
&lt;br /&gt;
 https://sourceforge.net/projects/boot-repair-cd/files/boot-repair-disk-64bit.iso/download&lt;br /&gt;
&lt;br /&gt;
It is the same toolset described below, but in a form that is automatically run at boot time.&lt;br /&gt;
&lt;br /&gt;
== Fixing It ==&lt;br /&gt;
The process summarized below is from this web page:&lt;br /&gt;
&lt;br /&gt;
 https://phoenixnap.com/kb/grub-rescue&lt;br /&gt;
&lt;br /&gt;
That page describes the process for restoring a GRUB configuration from the GRUB command line if you don&#039;t have a live ISO image available; it does require a significant level of knowledge about the system being restored ... which may not be available.&lt;br /&gt;
&lt;br /&gt;
Also on that page is the rather simple process using his boot-repair tool (free) to rescue a ubuntu system.  There is a lot of context on that page, but the gist is here.  Once you get the live image booted, open a terminal and issue these commands:&lt;br /&gt;
&lt;br /&gt;
 sudo add-apt-repository ppa:yannubuntu/boot-repair&lt;br /&gt;
 sudo apt update&lt;br /&gt;
 sudo apt install boot-repair -y&lt;br /&gt;
 sudo boot-repair&lt;br /&gt;
&lt;br /&gt;
The application will show a status dialog with a bunch of activities, then give you a big dialog with an option to implement the recommended changes ... if you have anything other than a single-disk simple configuration, click on the &#039;Advanced Options&#039; link to look at what it wants to do.  Make sure the location of your deployment is correct; it assumes the first disk with a reasonably valid configuration is what you want (not always the case).  Make any changes and then hit the &#039;Apply&#039; button.  Cross your fingers ... and you will hopefully get the success dialog.  Then you reboot back into your normal configuration.&lt;br /&gt;
&lt;br /&gt;
== Reinstall GRUB ==&lt;br /&gt;
If the repair tool can&#039;t salvage your configuration, you will need to reinstall GRUB.  This does require a live ISO image of the same distribution as is on the main system drive.&lt;br /&gt;
&lt;br /&gt;
The trick here is that you have to fool the GRUB installer into thinking it is working on the OS image on the system drive, but with the multitude of faux filesystem in a current Linux system, you need to make sure enough of them are available in the main disk image:&lt;br /&gt;
&lt;br /&gt;
 sudo mount /dev/sda1 /mnt&lt;br /&gt;
 sudo mount --bind /dev /mnt/dev &amp;amp;&amp;amp;&lt;br /&gt;
 sudo mount --bind /dev/pts /mnt/dev/pts &amp;amp;&amp;amp;&lt;br /&gt;
 sudo mount --bind /proc /mnt/proc &amp;amp;&amp;amp;&lt;br /&gt;
 sudo mount --bind /sys /mnt/sys&lt;br /&gt;
&lt;br /&gt;
Now you can do the installation of the new grub configuration:&lt;br /&gt;
&lt;br /&gt;
 sudo grub-install -root-directory=/mnt/ /dev/sda&lt;br /&gt;
&lt;br /&gt;
If that succeeds, then you need to clean things up:&lt;br /&gt;
&lt;br /&gt;
 sudo umount /mnt/sys &amp;amp;&amp;amp;&lt;br /&gt;
 sudo umount /mnt/proc &amp;amp;&amp;amp;&lt;br /&gt;
 sudo umount /mnt/dev/pts &amp;amp;&amp;amp;&lt;br /&gt;
 sudo umount /mnt/dev &amp;amp;&amp;amp;&lt;br /&gt;
 sudo umount /mnt&lt;br /&gt;
&lt;br /&gt;
Of course, substitute the correct device name for your main system drive ...&lt;/div&gt;</summary>
		<author><name>DrEdWilliams</name></author>
	</entry>
	<entry>
		<id>https://wiki.williams-net.org/index.php?title=Repair_GRUB_Installation&amp;diff=718</id>
		<title>Repair GRUB Installation</title>
		<link rel="alternate" type="text/html" href="https://wiki.williams-net.org/index.php?title=Repair_GRUB_Installation&amp;diff=718"/>
		<updated>2025-05-17T18:53:11Z</updated>

		<summary type="html">&lt;p&gt;DrEdWilliams: Created page with &amp;quot;Unlike most other problems where you have a (mostly) functioning Linux system to work with, if your GRUB install gets trashed you are almost literally toast.  == How it happens == It doesn&amp;#039;t really take much to mess with your GRUB configuration.  Fortunately, it lives in an infrequently accessed part of your filesystem (/boot) and survives by obscurity.  The biggest risk of corruption is actually when applying an update to the GRUB software -- if that gets interrupted an...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Unlike most other problems where you have a (mostly) functioning Linux system to work with, if your GRUB install gets trashed you are almost literally toast.&lt;br /&gt;
&lt;br /&gt;
== How it happens ==&lt;br /&gt;
It doesn&#039;t really take much to mess with your GRUB configuration.  Fortunately, it lives in an infrequently accessed part of your filesystem (/boot) and survives by obscurity.  The biggest risk of corruption is actually when applying an update to the GRUB software -- if that gets interrupted and you don&#039;t have a chance to re-run the update (i.e. the system freezes) you are in trouble.&lt;br /&gt;
&lt;br /&gt;
== Resources ==&lt;br /&gt;
As mentioned above, if you can&#039;t boot, you don&#039;t have the usual suite of tools to help you fix the problem -- but most major distributions offer &amp;quot;live&amp;quot; CD/DVD ISOs that allow you to &#039;try before you buy&#039;.  This can provide enough of a workable system to allow you to bootstrap your way to a solution.  Simply download a recent ISO image of a live system and put it somewhere you can boot from.  Note that Ubuntu related distribution ISOs (including kubuntu) operate in this mode by default -- you boot from the ISO and it gives you an option to install from the live system.  Other OS distributions have separate &#039;live&#039; ISOs.&lt;br /&gt;
&lt;br /&gt;
For ubuntu related distributions, there is also a dedicated rescue disk:&lt;br /&gt;
&lt;br /&gt;
 https://sourceforge.net/projects/boot-repair-cd/files/boot-repair-disk-64bit.iso/download&lt;br /&gt;
&lt;br /&gt;
It is the same toolset described below, but in a form that is automatically run at boot time.&lt;br /&gt;
&lt;br /&gt;
== Fixing It ==&lt;br /&gt;
The process summarized below is from this web page:&lt;br /&gt;
&lt;br /&gt;
 https://phoenixnap.com/kb/grub-rescue&lt;br /&gt;
&lt;br /&gt;
That page describes the process for restoring a GRUB configuration from the GRUB command line if you don&#039;t have a live ISO image available; it does require a significant level of knowledge about the system being restored ... which may not be available.&lt;br /&gt;
&lt;br /&gt;
Also on that page is the rather simple process using his boot-repair tool (free) to rescue a ubuntu system.  There is a lot of context on that page, but the gist is here.  Once you get the live image booted, open a terminal and issue these commands:&lt;br /&gt;
&lt;br /&gt;
 sudo add-apt-repository ppa:yannubuntu/boot-repair&lt;br /&gt;
 sudo apt update&lt;br /&gt;
 sudo apt install boot-repair -y&lt;br /&gt;
 sudo boot-repair&lt;br /&gt;
&lt;br /&gt;
The application will show a status dialog with a bunch of activities, then give you a big dialog with an option to implement the recommended changes ... if you have anything other than a single-disk simple configuration, click on the &#039;Advanced Options&#039; link to look at what it wants to do.  Make sure the location of your deployment is correct; it assumes the first disk with a reasonably valid configuration is what you want (not always the case).  Make any changes and then hit the &#039;Apply&#039; button.  Cross your fingers ... and you will hopefully get the success dialog.  Then you reboot back into your normal configuration.&lt;br /&gt;
&lt;br /&gt;
== Reinstall GRUB ==&lt;br /&gt;
If the repair tool can&#039;t salvage your configuration, you will need to reinstall GRUB.  This does require a live ISO image of the same distribution as is on the main system drive.&lt;br /&gt;
&lt;br /&gt;
The trick here is that you have to fool the live system into thinking it is working on the OS image on the system drive using the &#039;change root&#039; utility, but with the multitude of faux filesystem in a current Linux system, you need to make sure enough of them are available when you chroot to the main disk image:&lt;br /&gt;
&lt;br /&gt;
 sudo mount /dev/sda1 /mnt&lt;br /&gt;
 sudo mount --bind /dev /mnt/dev &amp;amp;&amp;amp;&lt;br /&gt;
 sudo mount --bind /dev/pts /mnt/dev/pts &amp;amp;&amp;amp;&lt;br /&gt;
 sudo mount --bind /proc /mnt/proc &amp;amp;&amp;amp;&lt;br /&gt;
 sudo mount --bind /sys /mnt/sys&lt;br /&gt;
&lt;br /&gt;
Now you can do the installation of the new grub configuration:&lt;br /&gt;
&lt;br /&gt;
 sudo grub-install -root-directory=/mnt/ /dev/sda&lt;br /&gt;
&lt;br /&gt;
If that succeeds, then you need to clean things up:&lt;br /&gt;
&lt;br /&gt;
 sudo umount /mnt/sys &amp;amp;&amp;amp;&lt;br /&gt;
 sudo umount /mnt/proc &amp;amp;&amp;amp;&lt;br /&gt;
 sudo umount /mnt/dev/pts &amp;amp;&amp;amp;&lt;br /&gt;
 sudo umount /mnt/dev &amp;amp;&amp;amp;&lt;br /&gt;
 sudo umount /mnt&lt;/div&gt;</summary>
		<author><name>DrEdWilliams</name></author>
	</entry>
	<entry>
		<id>https://wiki.williams-net.org/index.php?title=System_Administration_Processes&amp;diff=717</id>
		<title>System Administration Processes</title>
		<link rel="alternate" type="text/html" href="https://wiki.williams-net.org/index.php?title=System_Administration_Processes&amp;diff=717"/>
		<updated>2025-05-17T18:20:39Z</updated>

		<summary type="html">&lt;p&gt;DrEdWilliams: /* Sustainment Practices */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Non-standard Repositories ==&lt;br /&gt;
* [[Centos Repos]]&lt;br /&gt;
&lt;br /&gt;
== Basic OS installation ==&lt;br /&gt;
* [[Basic Ubuntu Installation]]&lt;br /&gt;
* [[Basic CentOS 7 Installation]]&lt;br /&gt;
* [[Basic Debian Installation]]&lt;br /&gt;
* [[Basic Fedora 31+ Installation]]&lt;br /&gt;
* [[Fedora 33 - Workstation Installation]]&lt;br /&gt;
* [[Basic Rocky Linux 8 Installation]]&lt;br /&gt;
* [[Common Post-Install]]&lt;br /&gt;
&lt;br /&gt;
== System Configuration ==&lt;br /&gt;
* [[HPE ProLiant System Configuration/Support]]&lt;br /&gt;
* [[Ethernet Device Configuration]]&lt;br /&gt;
* [[CUDA + NVIDIA drivers]]&lt;br /&gt;
* [[NVIDIA Docker Runtime|Installing NVIDIA Docker Runtime]]&lt;br /&gt;
* [[VLAN Interfaces]]&lt;br /&gt;
*[[Mounting Google Drive and Dropbox]]&lt;br /&gt;
*[[Mounting iSCSI LUNs]]&lt;br /&gt;
&lt;br /&gt;
== Application Installation ==&lt;br /&gt;
* [[Plex Media Server - Debian]]&lt;br /&gt;
* [[Docker Installation]]&lt;br /&gt;
* [[Ceph Storage Cluster]]&lt;br /&gt;
* [[Kubernetes Cluster Installation]]&lt;br /&gt;
* [http://www.webmin.com/download.html Webmin Installation]&lt;br /&gt;
* [[Mail Server Installation]]&lt;br /&gt;
&lt;br /&gt;
== Sustainment Practices ==&lt;br /&gt;
* [[SSH Host Key Management]]&lt;br /&gt;
* [[Log Accumulator]]&lt;br /&gt;
* [[Benchmark commands]]&lt;br /&gt;
* [[Memory Testing]]&lt;br /&gt;
* [[Repair GRUB Installation]]&lt;br /&gt;
&lt;br /&gt;
== Deprecated ==&lt;br /&gt;
*&lt;/div&gt;</summary>
		<author><name>DrEdWilliams</name></author>
	</entry>
	<entry>
		<id>https://wiki.williams-net.org/index.php?title=K3s_-_Kubernetes_Simplified&amp;diff=716</id>
		<title>K3s - Kubernetes Simplified</title>
		<link rel="alternate" type="text/html" href="https://wiki.williams-net.org/index.php?title=K3s_-_Kubernetes_Simplified&amp;diff=716"/>
		<updated>2025-03-29T19:32:26Z</updated>

		<summary type="html">&lt;p&gt;DrEdWilliams: /* External LoadBalancer/Reverse Proxy */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Lightweight Kubernetes. Production ready, easy to install, half the memory, all in a binary less than 100 MB.&lt;br /&gt;
&lt;br /&gt;
Great for:&lt;br /&gt;
* Edge&lt;br /&gt;
* IoT&lt;br /&gt;
* CI&lt;br /&gt;
* Development&lt;br /&gt;
* ARM&lt;br /&gt;
* Embedding k8s&lt;br /&gt;
* Situations where a PhD in k8s clusterology is infeasible&lt;br /&gt;
&lt;br /&gt;
Extracted from https://github.com/k3s-io/k3s ... YMMV&lt;br /&gt;
&lt;br /&gt;
What makes &#039;&#039;&#039;k3s&#039;&#039;&#039; special is that they have stripped out all the bloat-ware from upstream kubernetes that is not needed for small and bare-metal deployments.  None of the so-called cloud features are present, and most of the CSI storage drivers are also gone.&lt;br /&gt;
&lt;br /&gt;
As such, it is a simpler replacement for the &#039;&#039;&#039;kubeadm&#039;&#039;&#039; command, and it does a bit more for you:&lt;br /&gt;
* installs &#039;&#039;&#039;traefix&#039;&#039;&#039; as the default ingress controller -- it works ... especially for a test/dev cluster, but for production I&#039;ll use Contour/Envoy&lt;br /&gt;
* installs &#039;&#039;&#039;flannel&#039;&#039;&#039; as the CNI networking layer ... I had problems with flannel before, let&#039;s see if this works any better&lt;br /&gt;
* installs &#039;&#039;&#039;metrics-server&#039;&#039;&#039; to collect node/pod performance data&lt;br /&gt;
* provides a &#039;local path provisioner&#039; ... not sure what this does ... yet ...&lt;br /&gt;
__NOTOC__&lt;br /&gt;
== Basic Cluster Installation ==&lt;br /&gt;
They weren&#039;t kidding ... this is all it takes to create a simple cluster:&lt;br /&gt;
 curl -sfL https://get.k3s.io | sh -&lt;br /&gt;
A kubeconfig file is written to /etc/rancher/k3s/k3s.yaml and the service is automatically started or restarted. The install script will install K3s and additional utilities, such as kubectl, crictl, k3s-killall.sh, and k3s-uninstall.sh, for example:&lt;br /&gt;
 sudo kubectl get nodes&lt;br /&gt;
K3S_TOKEN is created at /var/lib/rancher/k3s/server/node-token on your server. To install on worker nodes we should pass K3S_URL along with K3S_TOKEN or K3S_CLUSTER_SECRET environment variables, for example:&lt;br /&gt;
 curl -sfL https://get.k3s.io | K3S_URL=https://myserver:6443 K3S_TOKEN=XXX sh -&lt;br /&gt;
&lt;br /&gt;
== HA Cluster Installation ==&lt;br /&gt;
One thing that attracted me to this distribution (as it is a distribution, not a fork of kubernetes) is that it provides a very simple way to set up a HA cluster control plane.  There are command options in the deployment that provide for the configuration of a common etcd server to facilitate a HA control plane.  Even with that ... it can get a bit cumbersome.  Enter [https://github.com/alexellis/k3sup k3sup].&lt;br /&gt;
&lt;br /&gt;
=== k3sup ===&lt;br /&gt;
k3sup is a wrapper for the k3s installer that enables:&lt;br /&gt;
* installation of a complete cluster from a single login session using SSH&lt;br /&gt;
* combining multiple k3s parameters into single options to k3sup for simplicity (i.e. &#039;&#039;&#039;--cluster&#039;&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
=== External LoadBalancer/Reverse Proxy ===&lt;br /&gt;
The one remaining item needed for a fully HA control plane is an external load balancer or reverse proxy to provide a single IP address for accessing the control API from inside or outside the cluster.  Lacking something like a BigIron F5 load balancer or something equivalent, the poor-man&#039;s approach is to use a separate reverse proxy.  This can be done with HAproxy or NGINX.  HAproxy can support a HA reverse proxy if you need that level of redundancy, or a simple NGINX configuration like this will work:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;stream {&lt;br /&gt;
  upstream k3s-servers {&lt;br /&gt;
    server 10.0.0.10:6443;&lt;br /&gt;
    server 10.0.0.74:6443;&lt;br /&gt;
    server 10.0.0.64:6443;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  server {&lt;br /&gt;
    listen 6443;&lt;br /&gt;
    proxy_pass k3s-servers;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This needs to be at the top level in the NGINX configuration -- either in the /etc/nginx/nginx.conf itself, or included at the top level.  This process is more completely described in the K3S documentation:&lt;br /&gt;
&lt;br /&gt;
  https://docs.k3s.io/datastore/cluster-loadbalancer&lt;br /&gt;
&lt;br /&gt;
If setting up a reverse proxy is not an option, you can set up a round robin in the DNS.  Problem is, the pfSense firewall doesn&#039;t do round robins by default, so a little arm twisting is needed.  Put this in the &#039;custom options&#039; in the DNS Resolver settings page:&lt;br /&gt;
 server:&lt;br /&gt;
 rrset-roundrobin: yes&lt;br /&gt;
 local-zone: &amp;quot;kube-test.williams.localnet&amp;quot; transparent&lt;br /&gt;
 local-data: &amp;quot;kube-test.williams.localnet A 10.0.0.10&amp;quot;&lt;br /&gt;
 local-data: &amp;quot;kube-test.williams.localnet A 10.0.0.64&amp;quot;&lt;br /&gt;
 local-data: &amp;quot;kube-test.williams.localnet A 10.0.0.74&amp;quot;&lt;br /&gt;
Change the name and IP addresses as needed, and then load the changes.  &lt;br /&gt;
&lt;br /&gt;
Using either approach somewhat complicates the deployment commands below, so pay attention ...&lt;br /&gt;
&lt;br /&gt;
=== Get k3sup ===&lt;br /&gt;
Not surprisingly, there are multiple ways to do this.  The author wants you to download it from a marketplace app (arkade):&lt;br /&gt;
 curl -sLS https://dl.get-arkade.dev | sh&lt;br /&gt;
 # Install the binary using the command given as output, such as: &lt;br /&gt;
 sudo cp arkade-darwin /usr/local/bin/arkade&lt;br /&gt;
 # Or on Linux:&lt;br /&gt;
 sudo cp arkade /usr/local/bin/arkade&lt;br /&gt;
 arkade get k3sup&lt;br /&gt;
&lt;br /&gt;
... or you can just download it directly ...&lt;br /&gt;
 curl -sLS https://get.k3sup.dev | sh&lt;br /&gt;
 sudo install k3sup /usr/local/bin/&lt;br /&gt;
&lt;br /&gt;
You just need to put it somewhere in your path (or use a full path reference).&lt;br /&gt;
&lt;br /&gt;
=== Install the master nodes ===&lt;br /&gt;
Install the first master node with these commands.  This will put it on the node that the command is issued from ... if that is not the desire, remove the &#039;--local&#039; parameter&lt;br /&gt;
 mkdir $HOME/.kube&lt;br /&gt;
 export EXTRA_ARGS=&amp;quot;--disable servicelb --disable traefik --disable local-storage --write-kubeconfig-mode=644 --flannel-backend host-gw&amp;quot; \&lt;br /&gt;
 k3sup install --cluster --local --ip &amp;lt;server-ip-1&amp;gt; --k3s-channel stable --k3s-extra-args &#039;$EXTRA_ARGS&#039; \&lt;br /&gt;
               --local-path $HOME/.kube/config --tls-san &amp;lt;rr-dns-name&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Explanations:&lt;br /&gt;
* --cluster sets this up for a HA control plane&lt;br /&gt;
* --local says to do it on this system, instead of using SSH to the node -- &#039;&#039;&#039;but you still need to provide the IP address&#039;&#039;&#039;, otherwise it will put 127.0.0.1 as the API server address&lt;br /&gt;
* get the last stable version available from k3s (use &#039;latest&#039; to get bleeding edge updates)&lt;br /&gt;
* we want to disable the simplified k3s loadbalancer ... it really is a crowbar solution and doesn&#039;t provide IP request capability&lt;br /&gt;
* disable the default ingress controller, as we really want something better&lt;br /&gt;
* disable the local storage driver (it&#039;s a pain if you&#039;re installing another storage driver)&lt;br /&gt;
* make the k3s.yaml file readable by the pods ... really should be by default&lt;br /&gt;
* (temporary workaround) force the flannel backend to use &#039;host-gw&#039; mode since &#039;vxlan&#039; mode seems to be broken with Debian 11&lt;br /&gt;
* the --local-path tells k3sup where to put the kubeconfig files ... this is the standard place, so we will put it there.  The directory has to exist -- hence the &#039;mkdir&#039; command ...&lt;br /&gt;
* by providing the name of the DNS round robin, it should be able to pass muster on TLS connections ...&lt;br /&gt;
&lt;br /&gt;
Subsequent master nodes can be installed next:&lt;br /&gt;
 k3sup join --server --host &amp;lt;new master server&amp;gt; --k3s-channel stable --server-host &amp;lt;original master server&amp;gt; --user ewilliam --k3s-extra-args &amp;quot;$EXTRA_ARGS&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Explanations:&lt;br /&gt;
* join as another server, not an agent/worker&lt;br /&gt;
* provide the hostname of the new master node to be joined&lt;br /&gt;
* specify the hostname of the first master created&lt;br /&gt;
* use the same EXTRA_ARGS provided to the first server&lt;br /&gt;
&lt;br /&gt;
Repeat this for all the masters (minimum 3) providing the same server IP address of the first master.  Note that if you need to add/remove more parameters to the k3s service, you need to do it on all server nodes -- just edit the k3s.service file and restart one server at a time.&lt;br /&gt;
&lt;br /&gt;
Now that you have all the masters online, reset the kubeconfig file (~/.kube/config) to use the common  name through the reverse proxy or DNS Round Robin instead of the IP of the first master:&lt;br /&gt;
 sed -i -e s/&amp;lt;server-ip-1&amp;gt;/&amp;lt;common-name&amp;gt;/g $HOME/.kube/config&lt;br /&gt;
&lt;br /&gt;
=== Install Worker Nodes ===&lt;br /&gt;
At this point, you should have an operational cluster.  k3s enables masters to be used for normal pods by default, so this is the minimum operational cluster.  Next, install the agent/worker nodes:&lt;br /&gt;
 k3sup join --ip &amp;lt;agent-node-x&amp;gt; --k3s-channel stable --server-host &amp;lt;common-name&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Explanations:&lt;br /&gt;
* Joining as an agent, so no &#039;--server&#039; this time&lt;br /&gt;
* provide each agent/worker IP in turn&lt;br /&gt;
* instead of the &#039;--server-ip&#039; parameter, we are using the &#039;--server-host&#039; parameter so we can use the DNS RR to ensure that the nodes always can access a master&lt;br /&gt;
&lt;br /&gt;
== Automated Upgrades:  System Upgrade Controller ==&lt;br /&gt;
&lt;br /&gt;
Rancher has taken the simplicity of k3s to another level by providing a kubernetes controller that can update the cluster ``from within the cluster`` using the [https://rancher.com/docs/k3s/latest/en/upgrades/automated/ System Upgrade Controller].&lt;br /&gt;
&lt;br /&gt;
Installing the controller is straightforward using a single manifest (also located in the git repo): &lt;br /&gt;
 kubectl apply -f https://github.com/rancher/system-upgrade-controller/releases/download/v0.7.6/system-upgrade-controller.yaml&lt;br /&gt;
&lt;br /&gt;
The controller looks for upgrade plans as custom resources (of type &#039;Plan&#039;, for some odd reason) to define its behavior.  Two &#039;Plan&#039;s are required ... one for server/master nodes and one for agent/worker nodes.  These plans can be set up to either upgrade to a specific k3s version or to monitor the release channel and automatically upgrade when a new release is available.  The manifest looks like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# Server plan&lt;br /&gt;
apiVersion: upgrade.cattle.io/v1&lt;br /&gt;
kind: Plan&lt;br /&gt;
metadata:&lt;br /&gt;
  name: server-plan&lt;br /&gt;
  namespace: system-upgrade&lt;br /&gt;
spec:&lt;br /&gt;
  concurrency: 1&lt;br /&gt;
  cordon: true&lt;br /&gt;
  nodeSelector:&lt;br /&gt;
    matchExpressions:&lt;br /&gt;
    - key: node-role.kubernetes.io/master&lt;br /&gt;
      operator: In&lt;br /&gt;
      values:&lt;br /&gt;
      - &amp;quot;true&amp;quot;&lt;br /&gt;
  serviceAccountName: system-upgrade&lt;br /&gt;
  upgrade:&lt;br /&gt;
    image: rancher/k3s-upgrade&lt;br /&gt;
  #version: v1.20.4+k3s1&lt;br /&gt;
  channel: https://update.k3s.io/v1-release/channels/stable&lt;br /&gt;
---&lt;br /&gt;
# Agent plan&lt;br /&gt;
apiVersion: upgrade.cattle.io/v1&lt;br /&gt;
kind: Plan&lt;br /&gt;
metadata:&lt;br /&gt;
  name: agent-plan&lt;br /&gt;
  namespace: system-upgrade&lt;br /&gt;
spec:&lt;br /&gt;
  concurrency: 1&lt;br /&gt;
  cordon: true&lt;br /&gt;
  nodeSelector:&lt;br /&gt;
    matchExpressions:&lt;br /&gt;
    - key: node-role.kubernetes.io/master&lt;br /&gt;
      operator: DoesNotExist&lt;br /&gt;
  prepare:&lt;br /&gt;
    args:&lt;br /&gt;
    - prepare&lt;br /&gt;
    - server-plan&lt;br /&gt;
    image: rancher/k3s-upgrade #:v1.17.4-k3s1&lt;br /&gt;
  serviceAccountName: system-upgrade&lt;br /&gt;
  upgrade:&lt;br /&gt;
    image: rancher/k3s-upgrade&lt;br /&gt;
  #version: v1.20.4+k3s1&lt;br /&gt;
  channel: https://update.k3s.io/v1-release/channels/stable&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Simply apply this manifest and the controller will identify nodes to upgrade and will take care of them as instructed.  It&#039;s as simple as that.  If you don&#039;t want to automatically upgrade, comment out the &#039;channel&#039; parameter in each Plan, and uncomment the &#039;version&#039; parameter and set it to the version to upgrade to and apply.  The controller will see the new plan and act accordingly.  If there is nothing to do, the controller just sits there waiting for a new plan with some work.&lt;br /&gt;
&lt;br /&gt;
== Cluster Access==&lt;br /&gt;
The kubeconfig file stored at /etc/rancher/k3s/k3s.yaml is used to configure access to the Kubernetes cluster. If you have installed upstream Kubernetes command line tools such as kubectl or helm you will need to configure them with the correct kubeconfig path. This can be done by either exporting the KUBECONFIG environment variable or by invoking the --kubeconfig command line flag. Refer to the examples below for details.&lt;br /&gt;
&lt;br /&gt;
Leverage the KUBECONFIG environment variable:&lt;br /&gt;
 export KUBECONFIG=/etc/rancher/k3s/k3s.yaml&lt;br /&gt;
 kubectl get pods --all-namespaces&lt;br /&gt;
 helm ls --all-namespaces&lt;br /&gt;
 &lt;br /&gt;
Or specify the location of the kubeconfig file in the command:&lt;br /&gt;
&lt;br /&gt;
 kubectl --kubeconfig /etc/rancher/k3s/k3s.yaml get pods --all-namespaces&lt;br /&gt;
 helm --kubeconfig /etc/rancher/k3s/k3s.yaml ls --all-namespaces&lt;br /&gt;
&lt;br /&gt;
To access the kubernetes cluster from outside the cluster, copy &amp;lt;pre&amp;gt;/etc/rancher/k3s/k3s.yaml&amp;lt;/pre&amp;gt; on your machine located outside the cluster as &amp;lt;pre&amp;gt;~/.kube/config&amp;lt;/pre&amp;gt;Then replace the value of the server field with the common name of the K3s server cluster as described above. kubectl can now manage your K3s cluster.&lt;br /&gt;
&lt;br /&gt;
==Cluster Maintenance==&lt;br /&gt;
As packages (particularly helm charts) are updated, old container images are left behind.  Not deleting container images is not generally a bad thing since it enables pods to migrate between nodes in the cluster without waiting for the container to be downloaded.  Upgrading packages, however leaves a lot of cruft behind that can eventually cause issues with disk space.  Supposedly Kubernetes manages this garbage collection, but other related packages (such as ceph) complain about low disk space long before Kubernetes decides to do anything about it.  Cleaning out the old containers is simple, fortunately:&lt;br /&gt;
 /usr/local/bin/k3s crictl rmi -q&lt;br /&gt;
While this can be run at any time, running it too often will remove containers that are still valid, just not used at that time on that node -- resulting in longer migration times when nodes are drained or fail.&lt;br /&gt;
&lt;br /&gt;
==Finishing The Job==&lt;br /&gt;
These instructions will create a simple or HA kubernetes cluster.  The HA cluster can survive a single master failure, but two will take down the cluster.&lt;br /&gt;
&lt;br /&gt;
At this point you jump back into the rest of the instructions for installing a [[Kubernetes Cluster Installation|Kubernetes Cluster]], remembering that the network layer and metrics server have already been installed.&lt;/div&gt;</summary>
		<author><name>DrEdWilliams</name></author>
	</entry>
	<entry>
		<id>https://wiki.williams-net.org/index.php?title=K3s_-_Kubernetes_Simplified&amp;diff=715</id>
		<title>K3s - Kubernetes Simplified</title>
		<link rel="alternate" type="text/html" href="https://wiki.williams-net.org/index.php?title=K3s_-_Kubernetes_Simplified&amp;diff=715"/>
		<updated>2025-03-29T19:30:16Z</updated>

		<summary type="html">&lt;p&gt;DrEdWilliams: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Lightweight Kubernetes. Production ready, easy to install, half the memory, all in a binary less than 100 MB.&lt;br /&gt;
&lt;br /&gt;
Great for:&lt;br /&gt;
* Edge&lt;br /&gt;
* IoT&lt;br /&gt;
* CI&lt;br /&gt;
* Development&lt;br /&gt;
* ARM&lt;br /&gt;
* Embedding k8s&lt;br /&gt;
* Situations where a PhD in k8s clusterology is infeasible&lt;br /&gt;
&lt;br /&gt;
Extracted from https://github.com/k3s-io/k3s ... YMMV&lt;br /&gt;
&lt;br /&gt;
What makes &#039;&#039;&#039;k3s&#039;&#039;&#039; special is that they have stripped out all the bloat-ware from upstream kubernetes that is not needed for small and bare-metal deployments.  None of the so-called cloud features are present, and most of the CSI storage drivers are also gone.&lt;br /&gt;
&lt;br /&gt;
As such, it is a simpler replacement for the &#039;&#039;&#039;kubeadm&#039;&#039;&#039; command, and it does a bit more for you:&lt;br /&gt;
* installs &#039;&#039;&#039;traefix&#039;&#039;&#039; as the default ingress controller -- it works ... especially for a test/dev cluster, but for production I&#039;ll use Contour/Envoy&lt;br /&gt;
* installs &#039;&#039;&#039;flannel&#039;&#039;&#039; as the CNI networking layer ... I had problems with flannel before, let&#039;s see if this works any better&lt;br /&gt;
* installs &#039;&#039;&#039;metrics-server&#039;&#039;&#039; to collect node/pod performance data&lt;br /&gt;
* provides a &#039;local path provisioner&#039; ... not sure what this does ... yet ...&lt;br /&gt;
__NOTOC__&lt;br /&gt;
== Basic Cluster Installation ==&lt;br /&gt;
They weren&#039;t kidding ... this is all it takes to create a simple cluster:&lt;br /&gt;
 curl -sfL https://get.k3s.io | sh -&lt;br /&gt;
A kubeconfig file is written to /etc/rancher/k3s/k3s.yaml and the service is automatically started or restarted. The install script will install K3s and additional utilities, such as kubectl, crictl, k3s-killall.sh, and k3s-uninstall.sh, for example:&lt;br /&gt;
 sudo kubectl get nodes&lt;br /&gt;
K3S_TOKEN is created at /var/lib/rancher/k3s/server/node-token on your server. To install on worker nodes we should pass K3S_URL along with K3S_TOKEN or K3S_CLUSTER_SECRET environment variables, for example:&lt;br /&gt;
 curl -sfL https://get.k3s.io | K3S_URL=https://myserver:6443 K3S_TOKEN=XXX sh -&lt;br /&gt;
&lt;br /&gt;
== HA Cluster Installation ==&lt;br /&gt;
One thing that attracted me to this distribution (as it is a distribution, not a fork of kubernetes) is that it provides a very simple way to set up a HA cluster control plane.  There are command options in the deployment that provide for the configuration of a common etcd server to facilitate a HA control plane.  Even with that ... it can get a bit cumbersome.  Enter [https://github.com/alexellis/k3sup k3sup].&lt;br /&gt;
&lt;br /&gt;
=== k3sup ===&lt;br /&gt;
k3sup is a wrapper for the k3s installer that enables:&lt;br /&gt;
* installation of a complete cluster from a single login session using SSH&lt;br /&gt;
* combining multiple k3s parameters into single options to k3sup for simplicity (i.e. &#039;&#039;&#039;--cluster&#039;&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
=== External LoadBalancer/Reverse Proxy ===&lt;br /&gt;
The one remaining item needed for a fully HA control plane is an external load balancer or reverse proxy to provide a single IP address for accessing the control API from inside or outside the cluster.  Lacking something like a BigIron F5 load balancer or something equivalent, the poor-man&#039;s approach is to use a separate reverse proxy.  This can be done with HAproxy or NGINX.  HAproxy can support a HA reverse proxy if you need that level of redundancy, or a simple NGINX configuration like this will work:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;stream {&lt;br /&gt;
  upstream k3s-servers {&lt;br /&gt;
    server 10.0.0.10:6443;&lt;br /&gt;
    server 10.0.0.74:6443;&lt;br /&gt;
    server 10.0.0.64:6443;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  server {&lt;br /&gt;
    listen 6443;&lt;br /&gt;
    proxy_pass k3s-servers;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This needs to be at the top level in the NGINX configuration -- either in the /etc/nginx/nginx.conf itself, or included at the top level.&lt;br /&gt;
&lt;br /&gt;
If setting up a reverse proxy is not an option, you can set up a round robin in the DNS.  Problem is, the pfSense firewall doesn&#039;t do round robins by default, so a little arm twisting is needed.  Put this in the &#039;custom options&#039; in the DNS Resolver settings page:&lt;br /&gt;
 server:&lt;br /&gt;
 rrset-roundrobin: yes&lt;br /&gt;
 local-zone: &amp;quot;kube-test.williams.localnet&amp;quot; transparent&lt;br /&gt;
 local-data: &amp;quot;kube-test.williams.localnet A 10.0.0.10&amp;quot;&lt;br /&gt;
 local-data: &amp;quot;kube-test.williams.localnet A 10.0.0.64&amp;quot;&lt;br /&gt;
 local-data: &amp;quot;kube-test.williams.localnet A 10.0.0.74&amp;quot;&lt;br /&gt;
Change the name and IP addresses as needed, and then load the changes.  &lt;br /&gt;
&lt;br /&gt;
Using either approach somewhat complicates the deployment commands below, so pay attention ...&lt;br /&gt;
&lt;br /&gt;
=== Get k3sup ===&lt;br /&gt;
Not surprisingly, there are multiple ways to do this.  The author wants you to download it from a marketplace app (arkade):&lt;br /&gt;
 curl -sLS https://dl.get-arkade.dev | sh&lt;br /&gt;
 # Install the binary using the command given as output, such as: &lt;br /&gt;
 sudo cp arkade-darwin /usr/local/bin/arkade&lt;br /&gt;
 # Or on Linux:&lt;br /&gt;
 sudo cp arkade /usr/local/bin/arkade&lt;br /&gt;
 arkade get k3sup&lt;br /&gt;
&lt;br /&gt;
... or you can just download it directly ...&lt;br /&gt;
 curl -sLS https://get.k3sup.dev | sh&lt;br /&gt;
 sudo install k3sup /usr/local/bin/&lt;br /&gt;
&lt;br /&gt;
You just need to put it somewhere in your path (or use a full path reference).&lt;br /&gt;
&lt;br /&gt;
=== Install the master nodes ===&lt;br /&gt;
Install the first master node with these commands.  This will put it on the node that the command is issued from ... if that is not the desire, remove the &#039;--local&#039; parameter&lt;br /&gt;
 mkdir $HOME/.kube&lt;br /&gt;
 export EXTRA_ARGS=&amp;quot;--disable servicelb --disable traefik --disable local-storage --write-kubeconfig-mode=644 --flannel-backend host-gw&amp;quot; \&lt;br /&gt;
 k3sup install --cluster --local --ip &amp;lt;server-ip-1&amp;gt; --k3s-channel stable --k3s-extra-args &#039;$EXTRA_ARGS&#039; \&lt;br /&gt;
               --local-path $HOME/.kube/config --tls-san &amp;lt;rr-dns-name&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Explanations:&lt;br /&gt;
* --cluster sets this up for a HA control plane&lt;br /&gt;
* --local says to do it on this system, instead of using SSH to the node -- &#039;&#039;&#039;but you still need to provide the IP address&#039;&#039;&#039;, otherwise it will put 127.0.0.1 as the API server address&lt;br /&gt;
* get the last stable version available from k3s (use &#039;latest&#039; to get bleeding edge updates)&lt;br /&gt;
* we want to disable the simplified k3s loadbalancer ... it really is a crowbar solution and doesn&#039;t provide IP request capability&lt;br /&gt;
* disable the default ingress controller, as we really want something better&lt;br /&gt;
* disable the local storage driver (it&#039;s a pain if you&#039;re installing another storage driver)&lt;br /&gt;
* make the k3s.yaml file readable by the pods ... really should be by default&lt;br /&gt;
* (temporary workaround) force the flannel backend to use &#039;host-gw&#039; mode since &#039;vxlan&#039; mode seems to be broken with Debian 11&lt;br /&gt;
* the --local-path tells k3sup where to put the kubeconfig files ... this is the standard place, so we will put it there.  The directory has to exist -- hence the &#039;mkdir&#039; command ...&lt;br /&gt;
* by providing the name of the DNS round robin, it should be able to pass muster on TLS connections ...&lt;br /&gt;
&lt;br /&gt;
Subsequent master nodes can be installed next:&lt;br /&gt;
 k3sup join --server --host &amp;lt;new master server&amp;gt; --k3s-channel stable --server-host &amp;lt;original master server&amp;gt; --user ewilliam --k3s-extra-args &amp;quot;$EXTRA_ARGS&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Explanations:&lt;br /&gt;
* join as another server, not an agent/worker&lt;br /&gt;
* provide the hostname of the new master node to be joined&lt;br /&gt;
* specify the hostname of the first master created&lt;br /&gt;
* use the same EXTRA_ARGS provided to the first server&lt;br /&gt;
&lt;br /&gt;
Repeat this for all the masters (minimum 3) providing the same server IP address of the first master.  Note that if you need to add/remove more parameters to the k3s service, you need to do it on all server nodes -- just edit the k3s.service file and restart one server at a time.&lt;br /&gt;
&lt;br /&gt;
Now that you have all the masters online, reset the kubeconfig file (~/.kube/config) to use the common  name through the reverse proxy or DNS Round Robin instead of the IP of the first master:&lt;br /&gt;
 sed -i -e s/&amp;lt;server-ip-1&amp;gt;/&amp;lt;common-name&amp;gt;/g $HOME/.kube/config&lt;br /&gt;
&lt;br /&gt;
=== Install Worker Nodes ===&lt;br /&gt;
At this point, you should have an operational cluster.  k3s enables masters to be used for normal pods by default, so this is the minimum operational cluster.  Next, install the agent/worker nodes:&lt;br /&gt;
 k3sup join --ip &amp;lt;agent-node-x&amp;gt; --k3s-channel stable --server-host &amp;lt;common-name&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Explanations:&lt;br /&gt;
* Joining as an agent, so no &#039;--server&#039; this time&lt;br /&gt;
* provide each agent/worker IP in turn&lt;br /&gt;
* instead of the &#039;--server-ip&#039; parameter, we are using the &#039;--server-host&#039; parameter so we can use the DNS RR to ensure that the nodes always can access a master&lt;br /&gt;
&lt;br /&gt;
== Automated Upgrades:  System Upgrade Controller ==&lt;br /&gt;
&lt;br /&gt;
Rancher has taken the simplicity of k3s to another level by providing a kubernetes controller that can update the cluster ``from within the cluster`` using the [https://rancher.com/docs/k3s/latest/en/upgrades/automated/ System Upgrade Controller].&lt;br /&gt;
&lt;br /&gt;
Installing the controller is straightforward using a single manifest (also located in the git repo): &lt;br /&gt;
 kubectl apply -f https://github.com/rancher/system-upgrade-controller/releases/download/v0.7.6/system-upgrade-controller.yaml&lt;br /&gt;
&lt;br /&gt;
The controller looks for upgrade plans as custom resources (of type &#039;Plan&#039;, for some odd reason) to define its behavior.  Two &#039;Plan&#039;s are required ... one for server/master nodes and one for agent/worker nodes.  These plans can be set up to either upgrade to a specific k3s version or to monitor the release channel and automatically upgrade when a new release is available.  The manifest looks like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# Server plan&lt;br /&gt;
apiVersion: upgrade.cattle.io/v1&lt;br /&gt;
kind: Plan&lt;br /&gt;
metadata:&lt;br /&gt;
  name: server-plan&lt;br /&gt;
  namespace: system-upgrade&lt;br /&gt;
spec:&lt;br /&gt;
  concurrency: 1&lt;br /&gt;
  cordon: true&lt;br /&gt;
  nodeSelector:&lt;br /&gt;
    matchExpressions:&lt;br /&gt;
    - key: node-role.kubernetes.io/master&lt;br /&gt;
      operator: In&lt;br /&gt;
      values:&lt;br /&gt;
      - &amp;quot;true&amp;quot;&lt;br /&gt;
  serviceAccountName: system-upgrade&lt;br /&gt;
  upgrade:&lt;br /&gt;
    image: rancher/k3s-upgrade&lt;br /&gt;
  #version: v1.20.4+k3s1&lt;br /&gt;
  channel: https://update.k3s.io/v1-release/channels/stable&lt;br /&gt;
---&lt;br /&gt;
# Agent plan&lt;br /&gt;
apiVersion: upgrade.cattle.io/v1&lt;br /&gt;
kind: Plan&lt;br /&gt;
metadata:&lt;br /&gt;
  name: agent-plan&lt;br /&gt;
  namespace: system-upgrade&lt;br /&gt;
spec:&lt;br /&gt;
  concurrency: 1&lt;br /&gt;
  cordon: true&lt;br /&gt;
  nodeSelector:&lt;br /&gt;
    matchExpressions:&lt;br /&gt;
    - key: node-role.kubernetes.io/master&lt;br /&gt;
      operator: DoesNotExist&lt;br /&gt;
  prepare:&lt;br /&gt;
    args:&lt;br /&gt;
    - prepare&lt;br /&gt;
    - server-plan&lt;br /&gt;
    image: rancher/k3s-upgrade #:v1.17.4-k3s1&lt;br /&gt;
  serviceAccountName: system-upgrade&lt;br /&gt;
  upgrade:&lt;br /&gt;
    image: rancher/k3s-upgrade&lt;br /&gt;
  #version: v1.20.4+k3s1&lt;br /&gt;
  channel: https://update.k3s.io/v1-release/channels/stable&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Simply apply this manifest and the controller will identify nodes to upgrade and will take care of them as instructed.  It&#039;s as simple as that.  If you don&#039;t want to automatically upgrade, comment out the &#039;channel&#039; parameter in each Plan, and uncomment the &#039;version&#039; parameter and set it to the version to upgrade to and apply.  The controller will see the new plan and act accordingly.  If there is nothing to do, the controller just sits there waiting for a new plan with some work.&lt;br /&gt;
&lt;br /&gt;
== Cluster Access==&lt;br /&gt;
The kubeconfig file stored at /etc/rancher/k3s/k3s.yaml is used to configure access to the Kubernetes cluster. If you have installed upstream Kubernetes command line tools such as kubectl or helm you will need to configure them with the correct kubeconfig path. This can be done by either exporting the KUBECONFIG environment variable or by invoking the --kubeconfig command line flag. Refer to the examples below for details.&lt;br /&gt;
&lt;br /&gt;
Leverage the KUBECONFIG environment variable:&lt;br /&gt;
 export KUBECONFIG=/etc/rancher/k3s/k3s.yaml&lt;br /&gt;
 kubectl get pods --all-namespaces&lt;br /&gt;
 helm ls --all-namespaces&lt;br /&gt;
 &lt;br /&gt;
Or specify the location of the kubeconfig file in the command:&lt;br /&gt;
&lt;br /&gt;
 kubectl --kubeconfig /etc/rancher/k3s/k3s.yaml get pods --all-namespaces&lt;br /&gt;
 helm --kubeconfig /etc/rancher/k3s/k3s.yaml ls --all-namespaces&lt;br /&gt;
&lt;br /&gt;
To access the kubernetes cluster from outside the cluster, copy &amp;lt;pre&amp;gt;/etc/rancher/k3s/k3s.yaml&amp;lt;/pre&amp;gt; on your machine located outside the cluster as &amp;lt;pre&amp;gt;~/.kube/config&amp;lt;/pre&amp;gt;Then replace the value of the server field with the common name of the K3s server cluster as described above. kubectl can now manage your K3s cluster.&lt;br /&gt;
&lt;br /&gt;
==Cluster Maintenance==&lt;br /&gt;
As packages (particularly helm charts) are updated, old container images are left behind.  Not deleting container images is not generally a bad thing since it enables pods to migrate between nodes in the cluster without waiting for the container to be downloaded.  Upgrading packages, however leaves a lot of cruft behind that can eventually cause issues with disk space.  Supposedly Kubernetes manages this garbage collection, but other related packages (such as ceph) complain about low disk space long before Kubernetes decides to do anything about it.  Cleaning out the old containers is simple, fortunately:&lt;br /&gt;
 /usr/local/bin/k3s crictl rmi -q&lt;br /&gt;
While this can be run at any time, running it too often will remove containers that are still valid, just not used at that time on that node -- resulting in longer migration times when nodes are drained or fail.&lt;br /&gt;
&lt;br /&gt;
==Finishing The Job==&lt;br /&gt;
These instructions will create a simple or HA kubernetes cluster.  The HA cluster can survive a single master failure, but two will take down the cluster.&lt;br /&gt;
&lt;br /&gt;
At this point you jump back into the rest of the instructions for installing a [[Kubernetes Cluster Installation|Kubernetes Cluster]], remembering that the network layer and metrics server have already been installed.&lt;/div&gt;</summary>
		<author><name>DrEdWilliams</name></author>
	</entry>
	<entry>
		<id>https://wiki.williams-net.org/index.php?title=K3s_-_Kubernetes_Simplified&amp;diff=714</id>
		<title>K3s - Kubernetes Simplified</title>
		<link rel="alternate" type="text/html" href="https://wiki.williams-net.org/index.php?title=K3s_-_Kubernetes_Simplified&amp;diff=714"/>
		<updated>2025-03-29T19:25:53Z</updated>

		<summary type="html">&lt;p&gt;DrEdWilliams: /* External LoadBalancer/Reverse Proxy */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Lightweight Kubernetes. Production ready, easy to install, half the memory, all in a binary less than 100 MB.&lt;br /&gt;
&lt;br /&gt;
Great for:&lt;br /&gt;
* Edge&lt;br /&gt;
* IoT&lt;br /&gt;
* CI&lt;br /&gt;
* Development&lt;br /&gt;
* ARM&lt;br /&gt;
* Embedding k8s&lt;br /&gt;
* Situations where a PhD in k8s clusterology is infeasible&lt;br /&gt;
&lt;br /&gt;
Extracted from https://github.com/k3s-io/k3s ... YMMV&lt;br /&gt;
&lt;br /&gt;
What makes &#039;&#039;&#039;k3s&#039;&#039;&#039; special is that they have stripped out all the bloat-ware from upstream kubernetes that is not needed for small and bare-metal deployments.  None of the so-called cloud features are present, and most of the CSI storage drivers are also gone.&lt;br /&gt;
&lt;br /&gt;
As such, it is a simpler replacement for the &#039;&#039;&#039;kubeadm&#039;&#039;&#039; command, and it does a bit more for you:&lt;br /&gt;
* installs &#039;&#039;&#039;traefix&#039;&#039;&#039; as the default ingress controller -- it works ... especially for a test/dev cluster, but for production I&#039;ll use Contour/Envoy&lt;br /&gt;
* installs &#039;&#039;&#039;flannel&#039;&#039;&#039; as the CNI networking layer ... I had problems with flannel before, let&#039;s see if this works any better&lt;br /&gt;
* installs &#039;&#039;&#039;metrics-server&#039;&#039;&#039; to collect node/pod performance data&lt;br /&gt;
* provides a &#039;local path provisioner&#039; ... not sure what this does ... yet ...&lt;br /&gt;
__NOTOC__&lt;br /&gt;
== Basic Cluster Installation ==&lt;br /&gt;
They weren&#039;t kidding ... this is all it takes to create a simple cluster:&lt;br /&gt;
 curl -sfL https://get.k3s.io | sh -&lt;br /&gt;
A kubeconfig file is written to /etc/rancher/k3s/k3s.yaml and the service is automatically started or restarted. The install script will install K3s and additional utilities, such as kubectl, crictl, k3s-killall.sh, and k3s-uninstall.sh, for example:&lt;br /&gt;
 sudo kubectl get nodes&lt;br /&gt;
K3S_TOKEN is created at /var/lib/rancher/k3s/server/node-token on your server. To install on worker nodes we should pass K3S_URL along with K3S_TOKEN or K3S_CLUSTER_SECRET environment variables, for example:&lt;br /&gt;
 curl -sfL https://get.k3s.io | K3S_URL=https://myserver:6443 K3S_TOKEN=XXX sh -&lt;br /&gt;
&lt;br /&gt;
== HA Cluster Installation ==&lt;br /&gt;
One thing that attracted me to this distribution (as it is a distribution, not a fork of kubernetes) is that it provides a very simple way to set up a HA cluster control plane.  There are command options in the deployment that provide for the configuration of a common etcd server to facilitate a HA control plane.  Even with that ... it can get a bit cumbersome.  Enter [https://github.com/alexellis/k3sup k3sup].&lt;br /&gt;
&lt;br /&gt;
=== k3sup ===&lt;br /&gt;
k3sup is a wrapper for the k3s installer that enables:&lt;br /&gt;
* installation of a complete cluster from a single login session using SSH&lt;br /&gt;
* combining multiple k3s parameters into single options to k3sup for simplicity (i.e. &#039;&#039;&#039;--cluster&#039;&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
=== External LoadBalancer/Reverse Proxy ===&lt;br /&gt;
The one remaining item needed for a fully HA control plane is an external load balancer or reverse proxy to provide a single IP address for accessing the control API from inside or outside the cluster.  Lacking something like a BigIron F5 load balancer or something equivalent, the poor-man&#039;s approach is to use a separate reverse proxy.  This can be done with HAproxy or NGINX.  HAproxy can support a HA reverse proxy if you need that level of redundancy, or a simple NGINX configuration like this will work:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;stream {&lt;br /&gt;
  upstream k3s-servers {&lt;br /&gt;
    server 10.0.0.10:6443;&lt;br /&gt;
    server 10.0.0.74:6443;&lt;br /&gt;
    server 10.0.0.64:6443;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  server {&lt;br /&gt;
    listen 6443;&lt;br /&gt;
    proxy_pass k3s-servers;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This needs to be at the top level in the NGINX configuration -- either in the /etc/nginx/nginx.conf itself, or included at the top level.&lt;br /&gt;
&lt;br /&gt;
If setting up a reverse proxy is not an option, you can set up a round robin in the DNS.  Problem is, the pfSense firewall doesn&#039;t do round robins by default, so a little arm twisting is needed.  Put this in the &#039;custom options&#039; in the DNS Resolver settings page:&lt;br /&gt;
 server:&lt;br /&gt;
 rrset-roundrobin: yes&lt;br /&gt;
 local-zone: &amp;quot;kube-test.williams.localnet&amp;quot; transparent&lt;br /&gt;
 local-data: &amp;quot;kube-test.williams.localnet A 10.0.0.10&amp;quot;&lt;br /&gt;
 local-data: &amp;quot;kube-test.williams.localnet A 10.0.0.64&amp;quot;&lt;br /&gt;
 local-data: &amp;quot;kube-test.williams.localnet A 10.0.0.74&amp;quot;&lt;br /&gt;
Change the name and IP addresses as needed, and then load the changes.  &lt;br /&gt;
&lt;br /&gt;
Using either approach somewhat complicates the deployment commands below, so pay attention ...&lt;br /&gt;
&lt;br /&gt;
=== Get k3sup ===&lt;br /&gt;
Not surprisingly, there are multiple ways to do this.  The author wants you to download it from a marketplace app (arkade):&lt;br /&gt;
 curl -sLS https://dl.get-arkade.dev | sh&lt;br /&gt;
 # Install the binary using the command given as output, such as: &lt;br /&gt;
 sudo cp arkade-darwin /usr/local/bin/arkade&lt;br /&gt;
 # Or on Linux:&lt;br /&gt;
 sudo cp arkade /usr/local/bin/arkade&lt;br /&gt;
 arkade get k3sup&lt;br /&gt;
&lt;br /&gt;
... or you can just download it directly ...&lt;br /&gt;
 curl -sLS https://get.k3sup.dev | sh&lt;br /&gt;
 sudo install k3sup /usr/local/bin/&lt;br /&gt;
&lt;br /&gt;
You just need to put it somewhere in your path (or use a full path reference).&lt;br /&gt;
&lt;br /&gt;
=== Install the master nodes ===&lt;br /&gt;
Install the first master node with these commands.  This will put it on the node that the command is issued from ... if that is not the desire, remove the &#039;--local&#039; parameter&lt;br /&gt;
 mkdir $HOME/.kube&lt;br /&gt;
 export EXTRA_ARGS=&amp;quot;--disable servicelb --disable traefik --disable local-storage --write-kubeconfig-mode=644 --flannel-backend host-gw&amp;quot; \&lt;br /&gt;
 k3sup install --cluster --local --ip &amp;lt;server-ip-1&amp;gt; --k3s-channel stable --k3s-extra-args &#039;$EXTRA_ARGS&#039; \&lt;br /&gt;
               --local-path $HOME/.kube/config --tls-san &amp;lt;rr-dns-name&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Explanations:&lt;br /&gt;
* --cluster sets this up for a HA control plane&lt;br /&gt;
* --local says to do it on this system, instead of using SSH to the node -- &#039;&#039;&#039;but you still need to provide the IP address&#039;&#039;&#039;, otherwise it will put 127.0.0.1 as the API server address&lt;br /&gt;
* get the last stable version available from k3s (use &#039;latest&#039; to get bleeding edge updates)&lt;br /&gt;
* we want to disable the simplified k3s loadbalancer ... it really is a crowbar solution and doesn&#039;t provide IP request capability&lt;br /&gt;
* disable the default ingress controller, as we really want something better&lt;br /&gt;
* disable the local storage driver (it&#039;s a pain if you&#039;re installing another storage driver)&lt;br /&gt;
* make the k3s.yaml file readable by the pods ... really should be by default&lt;br /&gt;
* (temporary workaround) force the flannel backend to use &#039;host-gw&#039; mode since &#039;vxlan&#039; mode seems to be broken with Debian 11&lt;br /&gt;
* the --local-path tells k3sup where to put the kubeconfig files ... this is the standard place, so we will put it there.  The directory has to exist -- hence the &#039;mkdir&#039; command ...&lt;br /&gt;
* by providing the name of the DNS round robin, it should be able to pass muster on TLS connections ...&lt;br /&gt;
&lt;br /&gt;
Subsequent master nodes can be installed next:&lt;br /&gt;
 k3sup join --server --host &amp;lt;new master server&amp;gt; --k3s-channel stable --server-host &amp;lt;original master server&amp;gt; --user ewilliam --k3s-extra-args &amp;quot;$EXTRA_ARGS&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Explanations:&lt;br /&gt;
* join as another server, not an agent/worker&lt;br /&gt;
* provide the hostname of the new master node to be joined&lt;br /&gt;
* specify the hostname of the first master created&lt;br /&gt;
* use the same EXTRA_ARGS provided to the first server&lt;br /&gt;
&lt;br /&gt;
Repeat this for all the masters (minimum 3) providing the same server IP address of the first master.  Note that if you need to add/remove more parameters to the k3s service, you need to do it on all server nodes -- just edit the k3s.service file and restart one server at a time.&lt;br /&gt;
&lt;br /&gt;
Now that you have all the masters online, reset the kubeconfig file (~/.kube/config) to use the DNS RR name instead of the IP of the first master:&lt;br /&gt;
 sed -i -e s/&amp;lt;server-ip-1&amp;gt;/&amp;lt;rr-dns-name&amp;gt;/g $HOME/.kube/config&lt;br /&gt;
&lt;br /&gt;
=== Install Worker Nodes ===&lt;br /&gt;
At this point, you should have an operational cluster.  k3s enables masters to be used for normal pods by default, so this is the minimum operational cluster.  Next, install the agent/worker nodes:&lt;br /&gt;
 k3sup join --ip &amp;lt;agent-node-x&amp;gt; --k3s-channel stable --server-host &amp;lt;rr-dns-name&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Explanations:&lt;br /&gt;
* Joining as an agent, so no &#039;--server&#039; this time&lt;br /&gt;
* provide each agent/worker IP in turn&lt;br /&gt;
* instead of the &#039;--server-ip&#039; parameter, we are using the &#039;--server-host&#039; parameter so we can use the DNS RR to ensure that the nodes always can access a master&lt;br /&gt;
&lt;br /&gt;
== Automated Upgrades:  System Upgrade Controller ==&lt;br /&gt;
&lt;br /&gt;
Rancher has taken the simplicity of k3s to another level by providing a kubernetes controller that can update the cluster ``from within the cluster`` using the [https://rancher.com/docs/k3s/latest/en/upgrades/automated/ System Upgrade Controller].&lt;br /&gt;
&lt;br /&gt;
Installing the controller is straightforward using a single manifest (also located in the git repo): &lt;br /&gt;
 kubectl apply -f https://github.com/rancher/system-upgrade-controller/releases/download/v0.7.6/system-upgrade-controller.yaml&lt;br /&gt;
&lt;br /&gt;
The controller looks for upgrade plans as custom resources (of type &#039;Plan&#039;, for some odd reason) to define its behavior.  Two &#039;Plan&#039;s are required ... one for server/master nodes and one for agent/worker nodes.  These plans can be set up to either upgrade to a specific k3s version or to monitor the release channel and automatically upgrade when a new release is available.  The manifest looks like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# Server plan&lt;br /&gt;
apiVersion: upgrade.cattle.io/v1&lt;br /&gt;
kind: Plan&lt;br /&gt;
metadata:&lt;br /&gt;
  name: server-plan&lt;br /&gt;
  namespace: system-upgrade&lt;br /&gt;
spec:&lt;br /&gt;
  concurrency: 1&lt;br /&gt;
  cordon: true&lt;br /&gt;
  nodeSelector:&lt;br /&gt;
    matchExpressions:&lt;br /&gt;
    - key: node-role.kubernetes.io/master&lt;br /&gt;
      operator: In&lt;br /&gt;
      values:&lt;br /&gt;
      - &amp;quot;true&amp;quot;&lt;br /&gt;
  serviceAccountName: system-upgrade&lt;br /&gt;
  upgrade:&lt;br /&gt;
    image: rancher/k3s-upgrade&lt;br /&gt;
  #version: v1.20.4+k3s1&lt;br /&gt;
  channel: https://update.k3s.io/v1-release/channels/stable&lt;br /&gt;
---&lt;br /&gt;
# Agent plan&lt;br /&gt;
apiVersion: upgrade.cattle.io/v1&lt;br /&gt;
kind: Plan&lt;br /&gt;
metadata:&lt;br /&gt;
  name: agent-plan&lt;br /&gt;
  namespace: system-upgrade&lt;br /&gt;
spec:&lt;br /&gt;
  concurrency: 1&lt;br /&gt;
  cordon: true&lt;br /&gt;
  nodeSelector:&lt;br /&gt;
    matchExpressions:&lt;br /&gt;
    - key: node-role.kubernetes.io/master&lt;br /&gt;
      operator: DoesNotExist&lt;br /&gt;
  prepare:&lt;br /&gt;
    args:&lt;br /&gt;
    - prepare&lt;br /&gt;
    - server-plan&lt;br /&gt;
    image: rancher/k3s-upgrade #:v1.17.4-k3s1&lt;br /&gt;
  serviceAccountName: system-upgrade&lt;br /&gt;
  upgrade:&lt;br /&gt;
    image: rancher/k3s-upgrade&lt;br /&gt;
  #version: v1.20.4+k3s1&lt;br /&gt;
  channel: https://update.k3s.io/v1-release/channels/stable&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Simply apply this manifest and the controller will identify nodes to upgrade and will take care of them as instructed.  It&#039;s as simple as that.  If you don&#039;t want to automatically upgrade, comment out the &#039;channel&#039; parameter in each Plan, and uncomment the &#039;version&#039; parameter and set it to the version to upgrade to and apply.  The controller will see the new plan and act accordingly.  If there is nothing to do, the controller just sits there waiting for a new plan with some work.&lt;br /&gt;
&lt;br /&gt;
== Cluster Access==&lt;br /&gt;
The kubeconfig file stored at /etc/rancher/k3s/k3s.yaml is used to configure access to the Kubernetes cluster. If you have installed upstream Kubernetes command line tools such as kubectl or helm you will need to configure them with the correct kubeconfig path. This can be done by either exporting the KUBECONFIG environment variable or by invoking the --kubeconfig command line flag. Refer to the examples below for details.&lt;br /&gt;
&lt;br /&gt;
Leverage the KUBECONFIG environment variable:&lt;br /&gt;
 export KUBECONFIG=/etc/rancher/k3s/k3s.yaml&lt;br /&gt;
 kubectl get pods --all-namespaces&lt;br /&gt;
 helm ls --all-namespaces&lt;br /&gt;
 &lt;br /&gt;
Or specify the location of the kubeconfig file in the command:&lt;br /&gt;
&lt;br /&gt;
 kubectl --kubeconfig /etc/rancher/k3s/k3s.yaml get pods --all-namespaces&lt;br /&gt;
 helm --kubeconfig /etc/rancher/k3s/k3s.yaml ls --all-namespaces&lt;br /&gt;
&lt;br /&gt;
To access the kubernetes cluster from outside the cluster, copy &amp;lt;pre&amp;gt;/etc/rancher/k3s/k3s.yaml&amp;lt;/pre&amp;gt; on your machine located outside the cluster as &amp;lt;pre&amp;gt;~/.kube/config&amp;lt;/pre&amp;gt;Then replace the value of the server field with the modified name of the K3s server cluster as described above. kubectl can now manage your K3s cluster.&lt;br /&gt;
&lt;br /&gt;
==Cluster Maintenance==&lt;br /&gt;
As packages (particularly helm charts) are updated, old container images are left behind.  Not deleting container images is not generally a bad thing since it enables pods to migrate between nodes in the cluster without waiting for the container to be downloaded.  Upgrading packages, however leaves a lot of cruft behind that can eventually cause issues with disk space.  Supposedly Kubernetes manages this garbage collection, but other related packages (such as ceph) complain about low disk space long before Kubernetes decides to do anything about it.  Cleaning out the old containers is simple, fortunately:&lt;br /&gt;
 /usr/local/bin/k3s crictl rmi -q&lt;br /&gt;
While this can be run at any time, running it too often will remove containers that are still valid, just not used at that time on that node -- resulting in longer migration times when nodes are drained or fail.&lt;br /&gt;
&lt;br /&gt;
==Finishing The Job==&lt;br /&gt;
These instructions will create a simple or HA kubernetes cluster.  The HA cluster can survive a single master failure, but two will take down the cluster.&lt;br /&gt;
&lt;br /&gt;
At this point you jump back into the rest of the instructions for installing a [[Kubernetes Cluster Installation|Kubernetes Cluster]], remembering that the network layer and metrics server have already been installed.&lt;/div&gt;</summary>
		<author><name>DrEdWilliams</name></author>
	</entry>
	<entry>
		<id>https://wiki.williams-net.org/index.php?title=K3s_-_Kubernetes_Simplified&amp;diff=713</id>
		<title>K3s - Kubernetes Simplified</title>
		<link rel="alternate" type="text/html" href="https://wiki.williams-net.org/index.php?title=K3s_-_Kubernetes_Simplified&amp;diff=713"/>
		<updated>2025-03-29T19:24:34Z</updated>

		<summary type="html">&lt;p&gt;DrEdWilliams: update to include nginx reverse proxy&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Lightweight Kubernetes. Production ready, easy to install, half the memory, all in a binary less than 100 MB.&lt;br /&gt;
&lt;br /&gt;
Great for:&lt;br /&gt;
* Edge&lt;br /&gt;
* IoT&lt;br /&gt;
* CI&lt;br /&gt;
* Development&lt;br /&gt;
* ARM&lt;br /&gt;
* Embedding k8s&lt;br /&gt;
* Situations where a PhD in k8s clusterology is infeasible&lt;br /&gt;
&lt;br /&gt;
Extracted from https://github.com/k3s-io/k3s ... YMMV&lt;br /&gt;
&lt;br /&gt;
What makes &#039;&#039;&#039;k3s&#039;&#039;&#039; special is that they have stripped out all the bloat-ware from upstream kubernetes that is not needed for small and bare-metal deployments.  None of the so-called cloud features are present, and most of the CSI storage drivers are also gone.&lt;br /&gt;
&lt;br /&gt;
As such, it is a simpler replacement for the &#039;&#039;&#039;kubeadm&#039;&#039;&#039; command, and it does a bit more for you:&lt;br /&gt;
* installs &#039;&#039;&#039;traefix&#039;&#039;&#039; as the default ingress controller -- it works ... especially for a test/dev cluster, but for production I&#039;ll use Contour/Envoy&lt;br /&gt;
* installs &#039;&#039;&#039;flannel&#039;&#039;&#039; as the CNI networking layer ... I had problems with flannel before, let&#039;s see if this works any better&lt;br /&gt;
* installs &#039;&#039;&#039;metrics-server&#039;&#039;&#039; to collect node/pod performance data&lt;br /&gt;
* provides a &#039;local path provisioner&#039; ... not sure what this does ... yet ...&lt;br /&gt;
__NOTOC__&lt;br /&gt;
== Basic Cluster Installation ==&lt;br /&gt;
They weren&#039;t kidding ... this is all it takes to create a simple cluster:&lt;br /&gt;
 curl -sfL https://get.k3s.io | sh -&lt;br /&gt;
A kubeconfig file is written to /etc/rancher/k3s/k3s.yaml and the service is automatically started or restarted. The install script will install K3s and additional utilities, such as kubectl, crictl, k3s-killall.sh, and k3s-uninstall.sh, for example:&lt;br /&gt;
 sudo kubectl get nodes&lt;br /&gt;
K3S_TOKEN is created at /var/lib/rancher/k3s/server/node-token on your server. To install on worker nodes we should pass K3S_URL along with K3S_TOKEN or K3S_CLUSTER_SECRET environment variables, for example:&lt;br /&gt;
 curl -sfL https://get.k3s.io | K3S_URL=https://myserver:6443 K3S_TOKEN=XXX sh -&lt;br /&gt;
&lt;br /&gt;
== HA Cluster Installation ==&lt;br /&gt;
One thing that attracted me to this distribution (as it is a distribution, not a fork of kubernetes) is that it provides a very simple way to set up a HA cluster control plane.  There are command options in the deployment that provide for the configuration of a common etcd server to facilitate a HA control plane.  Even with that ... it can get a bit cumbersome.  Enter [https://github.com/alexellis/k3sup k3sup].&lt;br /&gt;
&lt;br /&gt;
=== k3sup ===&lt;br /&gt;
k3sup is a wrapper for the k3s installer that enables:&lt;br /&gt;
* installation of a complete cluster from a single login session using SSH&lt;br /&gt;
* combining multiple k3s parameters into single options to k3sup for simplicity (i.e. &#039;&#039;&#039;--cluster&#039;&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
=== External LoadBalancer/Reverse Proxy ===&lt;br /&gt;
The one remaining item needed for a fully HA control plane is an external load balancer or reverse proxy to provide a single IP address for accessing the control API from inside or outside the cluster.  Lacking something like a BigIron F5 load balancer or something equivalent, the poor-man&#039;s approach is to use a separate reverse proxy.  This can be done with HAproxy or NGINX.  HAproxy can support a HA reverse proxy if you need that level of redundancy, or a simple NGINX configuration like this will work:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;stream {&lt;br /&gt;
  upstream k3s-servers {&lt;br /&gt;
    server 10.0.0.10:6443;&lt;br /&gt;
    server 10.0.0.74:6443;&lt;br /&gt;
    server 10.0.0.64:6443;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  server {&lt;br /&gt;
    listen 6443;&lt;br /&gt;
    proxy_pass k3s-servers;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This needs to be at the top level in the NGINX configuration -- either in the /etc/nginx/nginx.conf itself, or included at the top level.&lt;br /&gt;
&lt;br /&gt;
If setting up a reverse proxy is not an option, you can set up a round robin in the DNS.  Problem is, the pfSense firewall doesn&#039;t do round robins by default, so a little arm twisting is needed.  Put this in the &#039;custom options&#039; in the DNS Resolver settings page:&lt;br /&gt;
 server:&lt;br /&gt;
 rrset-roundrobin: yes&lt;br /&gt;
 local-zone: &amp;quot;kube-test.williams.localnet&amp;quot; transparent&lt;br /&gt;
 local-data: &amp;quot;kube-test.williams.localnet A 10.0.0.10&amp;quot;&lt;br /&gt;
 local-data: &amp;quot;kube-test.williams.localnet A 10.0.0.64&amp;quot;&lt;br /&gt;
 local-data: &amp;quot;kube-test.williams.localnet A 10.0.0.74&amp;quot;&lt;br /&gt;
Change the name and IP addresses as needed, and then load the changes.  This approach somewhat complicates the deployment commands below, so pay attention ...&lt;br /&gt;
&lt;br /&gt;
=== Get k3sup ===&lt;br /&gt;
Not surprisingly, there are multiple ways to do this.  The author wants you to download it from a marketplace app (arkade):&lt;br /&gt;
 curl -sLS https://dl.get-arkade.dev | sh&lt;br /&gt;
 # Install the binary using the command given as output, such as: &lt;br /&gt;
 sudo cp arkade-darwin /usr/local/bin/arkade&lt;br /&gt;
 # Or on Linux:&lt;br /&gt;
 sudo cp arkade /usr/local/bin/arkade&lt;br /&gt;
 arkade get k3sup&lt;br /&gt;
&lt;br /&gt;
... or you can just download it directly ...&lt;br /&gt;
 curl -sLS https://get.k3sup.dev | sh&lt;br /&gt;
 sudo install k3sup /usr/local/bin/&lt;br /&gt;
&lt;br /&gt;
You just need to put it somewhere in your path (or use a full path reference).&lt;br /&gt;
&lt;br /&gt;
=== Install the master nodes ===&lt;br /&gt;
Install the first master node with these commands.  This will put it on the node that the command is issued from ... if that is not the desire, remove the &#039;--local&#039; parameter&lt;br /&gt;
 mkdir $HOME/.kube&lt;br /&gt;
 export EXTRA_ARGS=&amp;quot;--disable servicelb --disable traefik --disable local-storage --write-kubeconfig-mode=644 --flannel-backend host-gw&amp;quot; \&lt;br /&gt;
 k3sup install --cluster --local --ip &amp;lt;server-ip-1&amp;gt; --k3s-channel stable --k3s-extra-args &#039;$EXTRA_ARGS&#039; \&lt;br /&gt;
               --local-path $HOME/.kube/config --tls-san &amp;lt;rr-dns-name&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Explanations:&lt;br /&gt;
* --cluster sets this up for a HA control plane&lt;br /&gt;
* --local says to do it on this system, instead of using SSH to the node -- &#039;&#039;&#039;but you still need to provide the IP address&#039;&#039;&#039;, otherwise it will put 127.0.0.1 as the API server address&lt;br /&gt;
* get the last stable version available from k3s (use &#039;latest&#039; to get bleeding edge updates)&lt;br /&gt;
* we want to disable the simplified k3s loadbalancer ... it really is a crowbar solution and doesn&#039;t provide IP request capability&lt;br /&gt;
* disable the default ingress controller, as we really want something better&lt;br /&gt;
* disable the local storage driver (it&#039;s a pain if you&#039;re installing another storage driver)&lt;br /&gt;
* make the k3s.yaml file readable by the pods ... really should be by default&lt;br /&gt;
* (temporary workaround) force the flannel backend to use &#039;host-gw&#039; mode since &#039;vxlan&#039; mode seems to be broken with Debian 11&lt;br /&gt;
* the --local-path tells k3sup where to put the kubeconfig files ... this is the standard place, so we will put it there.  The directory has to exist -- hence the &#039;mkdir&#039; command ...&lt;br /&gt;
* by providing the name of the DNS round robin, it should be able to pass muster on TLS connections ...&lt;br /&gt;
&lt;br /&gt;
Subsequent master nodes can be installed next:&lt;br /&gt;
 k3sup join --server --host &amp;lt;new master server&amp;gt; --k3s-channel stable --server-host &amp;lt;original master server&amp;gt; --user ewilliam --k3s-extra-args &amp;quot;$EXTRA_ARGS&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Explanations:&lt;br /&gt;
* join as another server, not an agent/worker&lt;br /&gt;
* provide the hostname of the new master node to be joined&lt;br /&gt;
* specify the hostname of the first master created&lt;br /&gt;
* use the same EXTRA_ARGS provided to the first server&lt;br /&gt;
&lt;br /&gt;
Repeat this for all the masters (minimum 3) providing the same server IP address of the first master.  Note that if you need to add/remove more parameters to the k3s service, you need to do it on all server nodes -- just edit the k3s.service file and restart one server at a time.&lt;br /&gt;
&lt;br /&gt;
Now that you have all the masters online, reset the kubeconfig file (~/.kube/config) to use the DNS RR name instead of the IP of the first master:&lt;br /&gt;
 sed -i -e s/&amp;lt;server-ip-1&amp;gt;/&amp;lt;rr-dns-name&amp;gt;/g $HOME/.kube/config&lt;br /&gt;
&lt;br /&gt;
=== Install Worker Nodes ===&lt;br /&gt;
At this point, you should have an operational cluster.  k3s enables masters to be used for normal pods by default, so this is the minimum operational cluster.  Next, install the agent/worker nodes:&lt;br /&gt;
 k3sup join --ip &amp;lt;agent-node-x&amp;gt; --k3s-channel stable --server-host &amp;lt;rr-dns-name&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Explanations:&lt;br /&gt;
* Joining as an agent, so no &#039;--server&#039; this time&lt;br /&gt;
* provide each agent/worker IP in turn&lt;br /&gt;
* instead of the &#039;--server-ip&#039; parameter, we are using the &#039;--server-host&#039; parameter so we can use the DNS RR to ensure that the nodes always can access a master&lt;br /&gt;
&lt;br /&gt;
== Automated Upgrades:  System Upgrade Controller ==&lt;br /&gt;
&lt;br /&gt;
Rancher has taken the simplicity of k3s to another level by providing a kubernetes controller that can update the cluster ``from within the cluster`` using the [https://rancher.com/docs/k3s/latest/en/upgrades/automated/ System Upgrade Controller].&lt;br /&gt;
&lt;br /&gt;
Installing the controller is straightforward using a single manifest (also located in the git repo): &lt;br /&gt;
 kubectl apply -f https://github.com/rancher/system-upgrade-controller/releases/download/v0.7.6/system-upgrade-controller.yaml&lt;br /&gt;
&lt;br /&gt;
The controller looks for upgrade plans as custom resources (of type &#039;Plan&#039;, for some odd reason) to define its behavior.  Two &#039;Plan&#039;s are required ... one for server/master nodes and one for agent/worker nodes.  These plans can be set up to either upgrade to a specific k3s version or to monitor the release channel and automatically upgrade when a new release is available.  The manifest looks like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# Server plan&lt;br /&gt;
apiVersion: upgrade.cattle.io/v1&lt;br /&gt;
kind: Plan&lt;br /&gt;
metadata:&lt;br /&gt;
  name: server-plan&lt;br /&gt;
  namespace: system-upgrade&lt;br /&gt;
spec:&lt;br /&gt;
  concurrency: 1&lt;br /&gt;
  cordon: true&lt;br /&gt;
  nodeSelector:&lt;br /&gt;
    matchExpressions:&lt;br /&gt;
    - key: node-role.kubernetes.io/master&lt;br /&gt;
      operator: In&lt;br /&gt;
      values:&lt;br /&gt;
      - &amp;quot;true&amp;quot;&lt;br /&gt;
  serviceAccountName: system-upgrade&lt;br /&gt;
  upgrade:&lt;br /&gt;
    image: rancher/k3s-upgrade&lt;br /&gt;
  #version: v1.20.4+k3s1&lt;br /&gt;
  channel: https://update.k3s.io/v1-release/channels/stable&lt;br /&gt;
---&lt;br /&gt;
# Agent plan&lt;br /&gt;
apiVersion: upgrade.cattle.io/v1&lt;br /&gt;
kind: Plan&lt;br /&gt;
metadata:&lt;br /&gt;
  name: agent-plan&lt;br /&gt;
  namespace: system-upgrade&lt;br /&gt;
spec:&lt;br /&gt;
  concurrency: 1&lt;br /&gt;
  cordon: true&lt;br /&gt;
  nodeSelector:&lt;br /&gt;
    matchExpressions:&lt;br /&gt;
    - key: node-role.kubernetes.io/master&lt;br /&gt;
      operator: DoesNotExist&lt;br /&gt;
  prepare:&lt;br /&gt;
    args:&lt;br /&gt;
    - prepare&lt;br /&gt;
    - server-plan&lt;br /&gt;
    image: rancher/k3s-upgrade #:v1.17.4-k3s1&lt;br /&gt;
  serviceAccountName: system-upgrade&lt;br /&gt;
  upgrade:&lt;br /&gt;
    image: rancher/k3s-upgrade&lt;br /&gt;
  #version: v1.20.4+k3s1&lt;br /&gt;
  channel: https://update.k3s.io/v1-release/channels/stable&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Simply apply this manifest and the controller will identify nodes to upgrade and will take care of them as instructed.  It&#039;s as simple as that.  If you don&#039;t want to automatically upgrade, comment out the &#039;channel&#039; parameter in each Plan, and uncomment the &#039;version&#039; parameter and set it to the version to upgrade to and apply.  The controller will see the new plan and act accordingly.  If there is nothing to do, the controller just sits there waiting for a new plan with some work.&lt;br /&gt;
&lt;br /&gt;
== Cluster Access==&lt;br /&gt;
The kubeconfig file stored at /etc/rancher/k3s/k3s.yaml is used to configure access to the Kubernetes cluster. If you have installed upstream Kubernetes command line tools such as kubectl or helm you will need to configure them with the correct kubeconfig path. This can be done by either exporting the KUBECONFIG environment variable or by invoking the --kubeconfig command line flag. Refer to the examples below for details.&lt;br /&gt;
&lt;br /&gt;
Leverage the KUBECONFIG environment variable:&lt;br /&gt;
 export KUBECONFIG=/etc/rancher/k3s/k3s.yaml&lt;br /&gt;
 kubectl get pods --all-namespaces&lt;br /&gt;
 helm ls --all-namespaces&lt;br /&gt;
 &lt;br /&gt;
Or specify the location of the kubeconfig file in the command:&lt;br /&gt;
&lt;br /&gt;
 kubectl --kubeconfig /etc/rancher/k3s/k3s.yaml get pods --all-namespaces&lt;br /&gt;
 helm --kubeconfig /etc/rancher/k3s/k3s.yaml ls --all-namespaces&lt;br /&gt;
&lt;br /&gt;
To access the kubernetes cluster from outside the cluster, copy &amp;lt;pre&amp;gt;/etc/rancher/k3s/k3s.yaml&amp;lt;/pre&amp;gt; on your machine located outside the cluster as &amp;lt;pre&amp;gt;~/.kube/config&amp;lt;/pre&amp;gt;Then replace the value of the server field with the modified name of the K3s server cluster as described above. kubectl can now manage your K3s cluster.&lt;br /&gt;
&lt;br /&gt;
==Cluster Maintenance==&lt;br /&gt;
As packages (particularly helm charts) are updated, old container images are left behind.  Not deleting container images is not generally a bad thing since it enables pods to migrate between nodes in the cluster without waiting for the container to be downloaded.  Upgrading packages, however leaves a lot of cruft behind that can eventually cause issues with disk space.  Supposedly Kubernetes manages this garbage collection, but other related packages (such as ceph) complain about low disk space long before Kubernetes decides to do anything about it.  Cleaning out the old containers is simple, fortunately:&lt;br /&gt;
 /usr/local/bin/k3s crictl rmi -q&lt;br /&gt;
While this can be run at any time, running it too often will remove containers that are still valid, just not used at that time on that node -- resulting in longer migration times when nodes are drained or fail.&lt;br /&gt;
&lt;br /&gt;
==Finishing The Job==&lt;br /&gt;
These instructions will create a simple or HA kubernetes cluster.  The HA cluster can survive a single master failure, but two will take down the cluster.&lt;br /&gt;
&lt;br /&gt;
At this point you jump back into the rest of the instructions for installing a [[Kubernetes Cluster Installation|Kubernetes Cluster]], remembering that the network layer and metrics server have already been installed.&lt;/div&gt;</summary>
		<author><name>DrEdWilliams</name></author>
	</entry>
	<entry>
		<id>https://wiki.williams-net.org/index.php?title=K3s_-_Kubernetes_Simplified&amp;diff=712</id>
		<title>K3s - Kubernetes Simplified</title>
		<link rel="alternate" type="text/html" href="https://wiki.williams-net.org/index.php?title=K3s_-_Kubernetes_Simplified&amp;diff=712"/>
		<updated>2025-03-29T12:44:35Z</updated>

		<summary type="html">&lt;p&gt;DrEdWilliams: /* External LoadBalancer (or DNS Round Robin) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Lightweight Kubernetes. Production ready, easy to install, half the memory, all in a binary less than 100 MB.&lt;br /&gt;
&lt;br /&gt;
Great for:&lt;br /&gt;
* Edge&lt;br /&gt;
* IoT&lt;br /&gt;
* CI&lt;br /&gt;
* Development&lt;br /&gt;
* ARM&lt;br /&gt;
* Embedding k8s&lt;br /&gt;
* Situations where a PhD in k8s clusterology is infeasible&lt;br /&gt;
&lt;br /&gt;
Extracted from https://github.com/k3s-io/k3s ... YMMV&lt;br /&gt;
&lt;br /&gt;
What makes &#039;&#039;&#039;k3s&#039;&#039;&#039; special is that they have stripped out all the bloat-ware from upstream kubernetes that is not needed for small and bare-metal deployments.  None of the so-called cloud features are present, and most of the CSI storage drivers are also gone.&lt;br /&gt;
&lt;br /&gt;
As such, it is a simpler replacement for the &#039;&#039;&#039;kubeadm&#039;&#039;&#039; command, and it does a bit more for you:&lt;br /&gt;
* installs &#039;&#039;&#039;traefix&#039;&#039;&#039; as the default ingress controller -- it works ... especially for a test/dev cluster, but for production I&#039;ll use Contour/Envoy&lt;br /&gt;
* installs &#039;&#039;&#039;flannel&#039;&#039;&#039; as the CNI networking layer ... I had problems with flannel before, let&#039;s see if this works any better&lt;br /&gt;
* installs &#039;&#039;&#039;metrics-server&#039;&#039;&#039; to collect node/pod performance data&lt;br /&gt;
* provides a &#039;local path provisioner&#039; ... not sure what this does ... yet ...&lt;br /&gt;
__NOTOC__&lt;br /&gt;
== Basic Cluster Installation ==&lt;br /&gt;
They weren&#039;t kidding ... this is all it takes to create a simple cluster:&lt;br /&gt;
 curl -sfL https://get.k3s.io | sh -&lt;br /&gt;
A kubeconfig file is written to /etc/rancher/k3s/k3s.yaml and the service is automatically started or restarted. The install script will install K3s and additional utilities, such as kubectl, crictl, k3s-killall.sh, and k3s-uninstall.sh, for example:&lt;br /&gt;
 sudo kubectl get nodes&lt;br /&gt;
K3S_TOKEN is created at /var/lib/rancher/k3s/server/node-token on your server. To install on worker nodes we should pass K3S_URL along with K3S_TOKEN or K3S_CLUSTER_SECRET environment variables, for example:&lt;br /&gt;
 curl -sfL https://get.k3s.io | K3S_URL=https://myserver:6443 K3S_TOKEN=XXX sh -&lt;br /&gt;
&lt;br /&gt;
== HA Cluster Installation ==&lt;br /&gt;
One thing that attracted me to this distribution (as it is a distribution, not a fork of kubernetes) is that it provides a very simple way to set up a HA cluster control plane.  There are command options in the deployment that provide for the configuration of a common etcd server to facilitate a HA control plane.  Even with that ... it can get a bit cumbersome.  Enter [https://github.com/alexellis/k3sup k3sup].&lt;br /&gt;
&lt;br /&gt;
=== k3sup ===&lt;br /&gt;
k3sup is a wrapper for the k3s installer that enables:&lt;br /&gt;
* installation of a complete cluster from a single login session using SSH&lt;br /&gt;
* combining multiple k3s parameters into single options to k3sup for simplicity (i.e. &#039;&#039;&#039;--cluster&#039;&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
=== External LoadBalancer (or DNS Round Robin) ===&lt;br /&gt;
The one remaining item needed for a fully HA control plane is an external load balancer to provide a single IP address for accessing the control API from inside or outside the cluster.  Lacking something like a BigIron F5 load balancer or something equivalent, the poor-man&#039;s approach is to use a round robin in the DNS.  Problem is, the pfSense firewall doesn&#039;t do round robins by default, so a little arm twisting is needed.  Put this in the &#039;custom options&#039; in the DNS Resolver settings page:&lt;br /&gt;
 server:&lt;br /&gt;
 rrset-roundrobin: yes&lt;br /&gt;
 local-zone: &amp;quot;kube-test.williams.localnet&amp;quot; transparent&lt;br /&gt;
 local-data: &amp;quot;kube-test.williams.localnet A 10.0.0.10&amp;quot;&lt;br /&gt;
 local-data: &amp;quot;kube-test.williams.localnet A 10.0.0.64&amp;quot;&lt;br /&gt;
 local-data: &amp;quot;kube-test.williams.localnet A 10.0.0.74&amp;quot;&lt;br /&gt;
Change the name and IP addresses as needed, and then load the changes.  This approach somewhat complicates the deployment commands below, so pay attention ...&lt;br /&gt;
&lt;br /&gt;
=== Get k3sup ===&lt;br /&gt;
Not surprisingly, there are multiple ways to do this.  The author wants you to download it from a marketplace app (arkade):&lt;br /&gt;
 curl -sLS https://dl.get-arkade.dev | sh&lt;br /&gt;
 # Install the binary using the command given as output, such as: &lt;br /&gt;
 sudo cp arkade-darwin /usr/local/bin/arkade&lt;br /&gt;
 # Or on Linux:&lt;br /&gt;
 sudo cp arkade /usr/local/bin/arkade&lt;br /&gt;
 arkade get k3sup&lt;br /&gt;
&lt;br /&gt;
... or you can just download it directly ...&lt;br /&gt;
 curl -sLS https://get.k3sup.dev | sh&lt;br /&gt;
 sudo install k3sup /usr/local/bin/&lt;br /&gt;
&lt;br /&gt;
You just need to put it somewhere in your path (or use a full path reference).&lt;br /&gt;
&lt;br /&gt;
=== Install the master nodes ===&lt;br /&gt;
Install the first master node with these commands.  This will put it on the node that the command is issued from ... if that is not the desire, remove the &#039;--local&#039; parameter&lt;br /&gt;
 mkdir $HOME/.kube&lt;br /&gt;
 export EXTRA_ARGS=&amp;quot;--disable servicelb --disable traefik --disable local-storage --write-kubeconfig-mode=644 --flannel-backend host-gw&amp;quot; \&lt;br /&gt;
 k3sup install --cluster --local --ip &amp;lt;server-ip-1&amp;gt; --k3s-channel stable --k3s-extra-args &#039;$EXTRA_ARGS&#039; \&lt;br /&gt;
               --local-path $HOME/.kube/config --tls-san &amp;lt;rr-dns-name&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Explanations:&lt;br /&gt;
* --cluster sets this up for a HA control plane&lt;br /&gt;
* --local says to do it on this system, instead of using SSH to the node -- &#039;&#039;&#039;but you still need to provide the IP address&#039;&#039;&#039;, otherwise it will put 127.0.0.1 as the API server address&lt;br /&gt;
* get the last stable version available from k3s (use &#039;latest&#039; to get bleeding edge updates)&lt;br /&gt;
* we want to disable the simplified k3s loadbalancer ... it really is a crowbar solution and doesn&#039;t provide IP request capability&lt;br /&gt;
* disable the default ingress controller, as we really want something better&lt;br /&gt;
* disable the local storage driver (it&#039;s a pain if you&#039;re installing another storage driver)&lt;br /&gt;
* make the k3s.yaml file readable by the pods ... really should be by default&lt;br /&gt;
* (temporary workaround) force the flannel backend to use &#039;host-gw&#039; mode since &#039;vxlan&#039; mode seems to be broken with Debian 11&lt;br /&gt;
* the --local-path tells k3sup where to put the kubeconfig files ... this is the standard place, so we will put it there.  The directory has to exist -- hence the &#039;mkdir&#039; command ...&lt;br /&gt;
* by providing the name of the DNS round robin, it should be able to pass muster on TLS connections ...&lt;br /&gt;
&lt;br /&gt;
Subsequent master nodes can be installed next:&lt;br /&gt;
 k3sup join --server --host &amp;lt;new master server&amp;gt; --k3s-channel stable --server-host &amp;lt;original master server&amp;gt; --user ewilliam --k3s-extra-args &amp;quot;$EXTRA_ARGS&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Explanations:&lt;br /&gt;
* join as another server, not an agent/worker&lt;br /&gt;
* provide the hostname of the new master node to be joined&lt;br /&gt;
* specify the hostname of the first master created&lt;br /&gt;
* use the same EXTRA_ARGS provided to the first server&lt;br /&gt;
&lt;br /&gt;
Repeat this for all the masters (minimum 3) providing the same server IP address of the first master.  Note that if you need to add/remove more parameters to the k3s service, you need to do it on all server nodes -- just edit the k3s.service file and restart one server at a time.&lt;br /&gt;
&lt;br /&gt;
Now that you have all the masters online, reset the kubeconfig file (~/.kube/config) to use the DNS RR name instead of the IP of the first master:&lt;br /&gt;
 sed -i -e s/&amp;lt;server-ip-1&amp;gt;/&amp;lt;rr-dns-name&amp;gt;/g $HOME/.kube/config&lt;br /&gt;
&lt;br /&gt;
=== Install Worker Nodes ===&lt;br /&gt;
At this point, you should have an operational cluster.  k3s enables masters to be used for normal pods by default, so this is the minimum operational cluster.  Next, install the agent/worker nodes:&lt;br /&gt;
 k3sup join --ip &amp;lt;agent-node-x&amp;gt; --k3s-channel stable --server-host &amp;lt;rr-dns-name&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Explanations:&lt;br /&gt;
* Joining as an agent, so no &#039;--server&#039; this time&lt;br /&gt;
* provide each agent/worker IP in turn&lt;br /&gt;
* instead of the &#039;--server-ip&#039; parameter, we are using the &#039;--server-host&#039; parameter so we can use the DNS RR to ensure that the nodes always can access a master&lt;br /&gt;
&lt;br /&gt;
== Automated Upgrades:  System Upgrade Controller ==&lt;br /&gt;
&lt;br /&gt;
Rancher has taken the simplicity of k3s to another level by providing a kubernetes controller that can update the cluster ``from within the cluster`` using the [https://rancher.com/docs/k3s/latest/en/upgrades/automated/ System Upgrade Controller].&lt;br /&gt;
&lt;br /&gt;
Installing the controller is straightforward using a single manifest (also located in the git repo): &lt;br /&gt;
 kubectl apply -f https://github.com/rancher/system-upgrade-controller/releases/download/v0.7.6/system-upgrade-controller.yaml&lt;br /&gt;
&lt;br /&gt;
The controller looks for upgrade plans as custom resources (of type &#039;Plan&#039;, for some odd reason) to define its behavior.  Two &#039;Plan&#039;s are required ... one for server/master nodes and one for agent/worker nodes.  These plans can be set up to either upgrade to a specific k3s version or to monitor the release channel and automatically upgrade when a new release is available.  The manifest looks like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# Server plan&lt;br /&gt;
apiVersion: upgrade.cattle.io/v1&lt;br /&gt;
kind: Plan&lt;br /&gt;
metadata:&lt;br /&gt;
  name: server-plan&lt;br /&gt;
  namespace: system-upgrade&lt;br /&gt;
spec:&lt;br /&gt;
  concurrency: 1&lt;br /&gt;
  cordon: true&lt;br /&gt;
  nodeSelector:&lt;br /&gt;
    matchExpressions:&lt;br /&gt;
    - key: node-role.kubernetes.io/master&lt;br /&gt;
      operator: In&lt;br /&gt;
      values:&lt;br /&gt;
      - &amp;quot;true&amp;quot;&lt;br /&gt;
  serviceAccountName: system-upgrade&lt;br /&gt;
  upgrade:&lt;br /&gt;
    image: rancher/k3s-upgrade&lt;br /&gt;
  #version: v1.20.4+k3s1&lt;br /&gt;
  channel: https://update.k3s.io/v1-release/channels/stable&lt;br /&gt;
---&lt;br /&gt;
# Agent plan&lt;br /&gt;
apiVersion: upgrade.cattle.io/v1&lt;br /&gt;
kind: Plan&lt;br /&gt;
metadata:&lt;br /&gt;
  name: agent-plan&lt;br /&gt;
  namespace: system-upgrade&lt;br /&gt;
spec:&lt;br /&gt;
  concurrency: 1&lt;br /&gt;
  cordon: true&lt;br /&gt;
  nodeSelector:&lt;br /&gt;
    matchExpressions:&lt;br /&gt;
    - key: node-role.kubernetes.io/master&lt;br /&gt;
      operator: DoesNotExist&lt;br /&gt;
  prepare:&lt;br /&gt;
    args:&lt;br /&gt;
    - prepare&lt;br /&gt;
    - server-plan&lt;br /&gt;
    image: rancher/k3s-upgrade #:v1.17.4-k3s1&lt;br /&gt;
  serviceAccountName: system-upgrade&lt;br /&gt;
  upgrade:&lt;br /&gt;
    image: rancher/k3s-upgrade&lt;br /&gt;
  #version: v1.20.4+k3s1&lt;br /&gt;
  channel: https://update.k3s.io/v1-release/channels/stable&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Simply apply this manifest and the controller will identify nodes to upgrade and will take care of them as instructed.  It&#039;s as simple as that.  If you don&#039;t want to automatically upgrade, comment out the &#039;channel&#039; parameter in each Plan, and uncomment the &#039;version&#039; parameter and set it to the version to upgrade to and apply.  The controller will see the new plan and act accordingly.  If there is nothing to do, the controller just sits there waiting for a new plan with some work.&lt;br /&gt;
&lt;br /&gt;
== Cluster Access==&lt;br /&gt;
The kubeconfig file stored at /etc/rancher/k3s/k3s.yaml is used to configure access to the Kubernetes cluster. If you have installed upstream Kubernetes command line tools such as kubectl or helm you will need to configure them with the correct kubeconfig path. This can be done by either exporting the KUBECONFIG environment variable or by invoking the --kubeconfig command line flag. Refer to the examples below for details.&lt;br /&gt;
&lt;br /&gt;
Leverage the KUBECONFIG environment variable:&lt;br /&gt;
 export KUBECONFIG=/etc/rancher/k3s/k3s.yaml&lt;br /&gt;
 kubectl get pods --all-namespaces&lt;br /&gt;
 helm ls --all-namespaces&lt;br /&gt;
 &lt;br /&gt;
Or specify the location of the kubeconfig file in the command:&lt;br /&gt;
&lt;br /&gt;
 kubectl --kubeconfig /etc/rancher/k3s/k3s.yaml get pods --all-namespaces&lt;br /&gt;
 helm --kubeconfig /etc/rancher/k3s/k3s.yaml ls --all-namespaces&lt;br /&gt;
&lt;br /&gt;
To access the kubernetes cluster from outside the cluster, copy &amp;lt;pre&amp;gt;/etc/rancher/k3s/k3s.yaml&amp;lt;/pre&amp;gt; on your machine located outside the cluster as &amp;lt;pre&amp;gt;~/.kube/config&amp;lt;/pre&amp;gt;Then replace the value of the server field with the modified name of the K3s server cluster as described above. kubectl can now manage your K3s cluster.&lt;br /&gt;
&lt;br /&gt;
==Cluster Maintenance==&lt;br /&gt;
As packages (particularly helm charts) are updated, old container images are left behind.  Not deleting container images is not generally a bad thing since it enables pods to migrate between nodes in the cluster without waiting for the container to be downloaded.  Upgrading packages, however leaves a lot of cruft behind that can eventually cause issues with disk space.  Supposedly Kubernetes manages this garbage collection, but other related packages (such as ceph) complain about low disk space long before Kubernetes decides to do anything about it.  Cleaning out the old containers is simple, fortunately:&lt;br /&gt;
 /usr/local/bin/k3s crictl rmi -q&lt;br /&gt;
While this can be run at any time, running it too often will remove containers that are still valid, just not used at that time on that node -- resulting in longer migration times when nodes are drained or fail.&lt;br /&gt;
&lt;br /&gt;
==Finishing The Job==&lt;br /&gt;
These instructions will create a simple or HA kubernetes cluster.  The HA cluster can survive a single master failure, but two will take down the cluster.&lt;br /&gt;
&lt;br /&gt;
At this point you jump back into the rest of the instructions for installing a [[Kubernetes Cluster Installation|Kubernetes Cluster]], remembering that the network layer and metrics server have already been installed.&lt;/div&gt;</summary>
		<author><name>DrEdWilliams</name></author>
	</entry>
	<entry>
		<id>https://wiki.williams-net.org/index.php?title=External_Name_Resolution&amp;diff=711</id>
		<title>External Name Resolution</title>
		<link rel="alternate" type="text/html" href="https://wiki.williams-net.org/index.php?title=External_Name_Resolution&amp;diff=711"/>
		<updated>2025-03-27T23:07:14Z</updated>

		<summary type="html">&lt;p&gt;DrEdWilliams: added customization instructions&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;While the coredns configuration is supposed to refer all non-cluster names out to the system defined DNS resolver, it seems that it doesn&#039;t always happen.  It may be related to the observation I&#039;ve made that the nameserver IP in the /etc/resolv.conf file is changed to 127.0.0.53 - which doesn&#039;t always work.  In any case, the coredns configuration allows you to add custom domain override definitions by creating a ConfigMap named &#039;coredns-custom&#039; using a YAML file like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;ApiVersion: v1&lt;br /&gt;
kind: ConfigMap&lt;br /&gt;
metadata:&lt;br /&gt;
  name: coredns-custom&lt;br /&gt;
  namespace: kube-system&lt;br /&gt;
data:&lt;br /&gt;
  # Log all incoming DNS queries.&lt;br /&gt;
  log.override: |&lt;br /&gt;
    log&lt;br /&gt;
  # Private DNS resolution. Handles FQDN resolutions for *.williams.localnet&lt;br /&gt;
  dev.server: |&lt;br /&gt;
    williams.localnet.:53 {&lt;br /&gt;
      forward . 10.0.0.254&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The general process is described in the online kubernetes documentation:&lt;br /&gt;
&lt;br /&gt;
 https://kubernetes.io/docs/tasks/administer-cluster/dns-custom-nameservers/&lt;br /&gt;
&lt;br /&gt;
Note that the &#039;*.override&#039; tag is different from the online documentation.  The correct label was identified by looking at the standard &#039;coredns&#039; ConfigMap to see where and how these custom sections are added.&lt;br /&gt;
&lt;br /&gt;
You can include multiple *.override sections and multiple *.server sections if needed to include all the overrides desired.&lt;/div&gt;</summary>
		<author><name>DrEdWilliams</name></author>
	</entry>
	<entry>
		<id>https://wiki.williams-net.org/index.php?title=External_Name_Resolution&amp;diff=710</id>
		<title>External Name Resolution</title>
		<link rel="alternate" type="text/html" href="https://wiki.williams-net.org/index.php?title=External_Name_Resolution&amp;diff=710"/>
		<updated>2025-03-27T23:01:50Z</updated>

		<summary type="html">&lt;p&gt;DrEdWilliams: instructions on how to provide DNS overrides&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;While the coredns configuration is supposed to refer all non-cluster names out to the system defined DNS resolver, it seems that it doesn&#039;t always happen.  It may be related to the observation I&#039;ve made that the nameserver IP in the /etc/resolv.conf file is changed to 127.0.0.53 - which doesn&#039;t always work.  In any case, the coredns configuration allows you to add custom domain override definitions by creating a ConfigMap named &#039;coredns-custom&#039; using a YAML file like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;ApiVersion: v1&lt;br /&gt;
kind: ConfigMap&lt;br /&gt;
metadata:&lt;br /&gt;
  name: coredns-custom&lt;br /&gt;
  namespace: kube-system&lt;br /&gt;
data:&lt;br /&gt;
  # Log all incoming DNS queries.&lt;br /&gt;
  log.override: |&lt;br /&gt;
    log&lt;br /&gt;
  # Private DNS resolution example. Handles FQDN resolutions for *.mydomain.com&lt;br /&gt;
  # Replace &amp;lt;dns-private-ip&amp;gt; with the target IP address.&lt;br /&gt;
  dev.server: |&lt;br /&gt;
    williams.localnet.:53 {&lt;br /&gt;
      forward . 10.0.0.254&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The general process is described in the online kubernetes documentation:&lt;br /&gt;
&lt;br /&gt;
 https://kubernetes.io/docs/tasks/administer-cluster/dns-custom-nameservers/&lt;/div&gt;</summary>
		<author><name>DrEdWilliams</name></author>
	</entry>
	<entry>
		<id>https://wiki.williams-net.org/index.php?title=Talk:Rook_Storage_for_Kubernetes&amp;diff=708</id>
		<title>Talk:Rook Storage for Kubernetes</title>
		<link rel="alternate" type="text/html" href="https://wiki.williams-net.org/index.php?title=Talk:Rook_Storage_for_Kubernetes&amp;diff=708"/>
		<updated>2025-03-26T01:31:25Z</updated>

		<summary type="html">&lt;p&gt;DrEdWilliams: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;clearing/reusing drives in rook/ceph:&lt;br /&gt;
&lt;br /&gt;
 lsblk /dev/xxxx&lt;br /&gt;
&lt;br /&gt;
if you see a ceph ID, you need to remove it:&lt;br /&gt;
&lt;br /&gt;
 dmsetup remove ceph--(whatever you see in lsblk)&lt;br /&gt;
&lt;br /&gt;
you also need to clean out the partition table:&lt;br /&gt;
&lt;br /&gt;
 wipefs -a /dev/xxxx&lt;br /&gt;
&lt;br /&gt;
if that device had been in ceph before, you need to remove the old OSD (that should be marked as down/out).  open the rook-ceph-tools container:&lt;br /&gt;
&lt;br /&gt;
 ceph osd purge &amp;lt;number&amp;gt; --yes-i-really-mean-it&lt;br /&gt;
&lt;br /&gt;
You need to make sure that the osd is truly dead ...&lt;br /&gt;
&lt;br /&gt;
Removing error messages that make no sense:&lt;br /&gt;
&lt;br /&gt;
- warning about low host disk space&lt;br /&gt;
&lt;br /&gt;
 ceph config set mon mon_data_avail_warn 10&lt;br /&gt;
&lt;br /&gt;
- warning about pool objects per pg &lt;br /&gt;
&lt;br /&gt;
 ceph config set mgr mon_pg_warn_max_object_skew 0.0&lt;/div&gt;</summary>
		<author><name>DrEdWilliams</name></author>
	</entry>
	<entry>
		<id>https://wiki.williams-net.org/index.php?title=Production_Cluster_Configuration&amp;diff=703</id>
		<title>Production Cluster Configuration</title>
		<link rel="alternate" type="text/html" href="https://wiki.williams-net.org/index.php?title=Production_Cluster_Configuration&amp;diff=703"/>
		<updated>2024-09-14T23:09:36Z</updated>

		<summary type="html">&lt;p&gt;DrEdWilliams: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;These packages form the basic functionality of the production cluster.  &lt;br /&gt;
&lt;br /&gt;
Scripts &amp;amp; config files are checked into gitlab under the Kubernetes group project listed.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! activity !! gitlab !! script/procedures/config !! IP !! hostname(s)&lt;br /&gt;
|-&lt;br /&gt;
| [[Ceph Storage Cluster]] || k8s-admin || || ||&lt;br /&gt;
|-&lt;br /&gt;
| [[Rook Storage for Kubernetes|Rook Storage]] || k8s-admin || || || (StorageClass)&amp;lt;br/&amp;gt;rook-ceph-hdd&amp;lt;br/&amp;gt;rook-ceph-nvme&lt;br /&gt;
|-&lt;br /&gt;
| gitlab registry secrets || || gitlab-registry-kube-system.yaml &amp;lt;br /&amp;gt; gitlab-registry-secret.yaml || ||&lt;br /&gt;
|-&lt;br /&gt;
| wordpress (dredwilliams.com) || k8s/dredwilliams || || || dredwilliams.williams-net.org&lt;br /&gt;
|-&lt;br /&gt;
| mediawiki || mediawiki || || 10.0.0.116 || wiki.williams.localnet &amp;lt;br /&amp;gt;wiki.williams-net.org&lt;br /&gt;
|-&lt;br /&gt;
| [[MariaDB]] || mariadb || || 10.0.0.117 || database.williams.localnet&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Storage ===&lt;br /&gt;
The production cluster depends on the &#039;&#039;&#039;/shared&#039;&#039;&#039; filesystem for its persistent storage as provided by the production Ceph cluster.  The Ceph is configured as shown here:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! system !! function !! storage !! size&lt;br /&gt;
|-&lt;br /&gt;
| caspian || master || NVMe&amp;lt;br/&amp;gt;HDD || 1TB&amp;lt;br/&amp;gt;1TB&lt;br /&gt;
|-&lt;br /&gt;
| uvilas || node || NVMe&amp;lt;br/&amp;gt;HDD&amp;lt;br/&amp;gt;HDD || 1TB&amp;lt;br/&amp;gt;1TB&amp;lt;br/&amp;gt;1TB&lt;br /&gt;
|-&lt;br /&gt;
| belisar || node || NVMe&amp;lt;br/&amp;gt;HDD || 1TB&amp;lt;br/&amp;gt;250GB&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The work filesystem can be mounted via NFS:&lt;br /&gt;
&lt;br /&gt;
 10.0.0.75:/work /work nfs4 soft 0 0&lt;br /&gt;
&lt;br /&gt;
=== Backups ===&lt;br /&gt;
&lt;br /&gt;
In addition to the normal backups configured in the basic OS installation steps, the databases in the production cluster must be backed up daily using the &#039;mysqldump&#039; command:&lt;br /&gt;
&lt;br /&gt;
 TBD&lt;br /&gt;
&lt;br /&gt;
These commands should be inserted into the /etc/cron.daily/backup file on one of the cluster nodes (telmar is a good choice).  The first does a complete database dump of the MediaWiki database server, the second dumps just the mediawiki database itself, and the third dumps the general purpose database server.  Additional dump commands should be inserted for additional significant databases, as parsing individual databases out of a system dump can be tedious.&lt;/div&gt;</summary>
		<author><name>DrEdWilliams</name></author>
	</entry>
	<entry>
		<id>https://wiki.williams-net.org/index.php?title=Mail_Server_Installation&amp;diff=702</id>
		<title>Mail Server Installation</title>
		<link rel="alternate" type="text/html" href="https://wiki.williams-net.org/index.php?title=Mail_Server_Installation&amp;diff=702"/>
		<updated>2024-09-14T23:07:56Z</updated>

		<summary type="html">&lt;p&gt;DrEdWilliams: initial version&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The previous deployment of a mail server as a home grown kubernetes deployment finally broke when the underlying centos7 container was discontinued.  This solution surfaced recently, and after some challenges in adapting to this environment seems to be working properly.  Like the previous solution, it uses docker containers; but the author only provided a docker compose deployment method, so it requires a VM to keep it contained.&lt;br /&gt;
&lt;br /&gt;
The solution is called &amp;quot;MailCow&amp;quot;, and is located on GitHub:&lt;br /&gt;
&lt;br /&gt;
 https://docs.mailcow.email/getstarted/install/&lt;br /&gt;
&lt;br /&gt;
The package contains multiple docker containers that implement all the basic services required to support the mail server -- including a webmail application (that I couldn&#039;t get to work).&lt;br /&gt;
&lt;br /&gt;
== Pre-requisites ==&lt;br /&gt;
Per the documentation, MailCow is best installed in its own system, so a small VM is the best hosting solution.  They recommended ubuntu, but my [[Basic Debian Installation]] worked just fine.  Preparing for this deployment is straightforward:&lt;br /&gt;
&lt;br /&gt;
# Create a VM with 2 cores, 4 GB RAM, and 100GB in a single storage volume &lt;br /&gt;
# Install Debian in the VM as described in [[Basic Debian Installation]]&lt;br /&gt;
# Create a static DHCP IP assignment (or use a static network configuration) for the mail server to provide a consistent IP address&lt;br /&gt;
# Create a DNS entry for the server as &#039;mail.williams.localnet&#039; with CNAMES for &#039;imap&#039; and &#039;smtp&#039;&lt;br /&gt;
&lt;br /&gt;
== Installation ==&lt;br /&gt;
The instructions for MailCow are very comprehensive and easy to follow:&lt;br /&gt;
&lt;br /&gt;
# Follow the instructions in the documentation to install docker&lt;br /&gt;
# Clone the MailCow GitHub repo&lt;br /&gt;
# Generate a config file -- edit to specify the hostname and to disable the &amp;quot;Let&#039;s Encrypt&amp;quot; certificate generation (it will generate self-signed certs as needed)&lt;br /&gt;
# Edit config files as needed to accept mail from the local systems (10.0.0.0/24) as specified in &amp;lt;br/&amp;gt; `https://docs.mailcow.email/manual-guides/Postfix/u_e-postfix-unauthenticated-relaying/?h=relay`&lt;br /&gt;
# Start the server as specified in the docs (NOTE: it takes several minutes to get things initialized, so be patient).&lt;br /&gt;
&lt;br /&gt;
== Follow-up ==&lt;br /&gt;
Reconnecting Thunderbird to the new server is a manual process, but not massively eventful.  This more robust server did require a modification to the standard SSMTP mail client configuration (the source domain needed to be specified), and it has become obvious that I need to actually switch back to a more robust postfix mail deployment on each server in the environment.  It is definitely overkill, but the SSMTP client is not very robust or fault tolerant.&lt;/div&gt;</summary>
		<author><name>DrEdWilliams</name></author>
	</entry>
	<entry>
		<id>https://wiki.williams-net.org/index.php?title=Basic_Debian_Installation&amp;diff=699</id>
		<title>Basic Debian Installation</title>
		<link rel="alternate" type="text/html" href="https://wiki.williams-net.org/index.php?title=Basic_Debian_Installation&amp;diff=699"/>
		<updated>2024-02-10T16:49:18Z</updated>

		<summary type="html">&lt;p&gt;DrEdWilliams: added HP watchdog timer fix&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE&#039;&#039;&#039;:  The instructions on this page have been tested and appear to work properly on Debian 10 (&#039;&#039;&#039;Buster&#039;&#039;&#039;), Debian 11 (&#039;&#039;&#039;Bullseye&#039;&#039;&#039;), and Debian 12 (&#039;&#039;&#039;Bookworm&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
Debian standard install from distributed ISO images: &lt;br /&gt;
* Debian 10/11 - &#039;&#039;firmware-amd64-DVD&#039;&#039; (which includes the proprietary firmware that is supposedly not included in the other install disks)&lt;br /&gt;
* Debian 12 - select the full or network standard media - they have appeared to include the extra firmware in the primary install images&lt;br /&gt;
&lt;br /&gt;
Basic instructions for all versions:&lt;br /&gt;
* Do a normal &#039;Install&#039; option from the boot menu &lt;br /&gt;
** if that hangs on the network device detection, do the &#039;Expert Install&#039; option from the &#039;Advanced&#039; menu and select the default options&lt;br /&gt;
* select basic options, one partition formatting, and only the minimal software selection, but make sure the &#039;SSHD server&#039; option is selected&lt;br /&gt;
* For a graphic workstation, select the desired desktop from the list&lt;br /&gt;
* select &#039;yes&#039; for network mirror, using the defaults (USA/deb.debian.org)&lt;br /&gt;
* let it finish and reboot &lt;br /&gt;
&lt;br /&gt;
== Basic system prep ==&lt;br /&gt;
Most of the initial configuration is now contained in a script that can be executed directly from the config server as root on the target system:&lt;br /&gt;
&lt;br /&gt;
 curl -s http://config/config/debian-basic-config.sh | bash -x | tee config.out&lt;br /&gt;
 wget -qO - http://config/config/debian-basic-config.sh | bash -x | tee config.out&lt;br /&gt;
&lt;br /&gt;
The contents of this script are included here for reference, though updates to the script may occur without updates to this page:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#!/bin/sh&lt;br /&gt;
#&lt;br /&gt;
# script to do the basic install of a debian headless server&lt;br /&gt;
#&lt;br /&gt;
# Assumptions:&lt;br /&gt;
#  - this is run as root immediately after the install has completed&lt;br /&gt;
#  - the hostname has been set as desired before this script is run&lt;br /&gt;
#  - an administrator account &#039;ewilliam&#039; was created during installation&lt;br /&gt;
#&lt;br /&gt;
# invoke using one of these commands:&lt;br /&gt;
#&lt;br /&gt;
#   wget -qO http://config/config/debian-basic-config.sh | bash&lt;br /&gt;
#   curl -s http://config/config/debian-basic-config.sh | bash&lt;br /&gt;
#&lt;br /&gt;
&lt;br /&gt;
CONFIG=http://config/config&lt;br /&gt;
&lt;br /&gt;
# first -- install all the basic necessities (some may already be there)&lt;br /&gt;
apt-get update&lt;br /&gt;
apt-get install -y net-tools zsh sudo rsync mlocate wget nfs-common psmisc&lt;br /&gt;
apt-get install -y aptitude sshfs git curl smartmontools vim&lt;br /&gt;
&lt;br /&gt;
# the ssmtp package is not officially supported under buster&lt;br /&gt;
#  download the package from stretch and install&lt;br /&gt;
#SSMTP_DEB=ssmtp_2.64-9_amd64.deb&lt;br /&gt;
SSMTP_DEB=ssmtp_2.64-8+b2_amd64.deb&lt;br /&gt;
wget http://http.us.debian.org/debian/pool/main/s/ssmtp/${SSMTP_DEB}&lt;br /&gt;
apt-get install -y ./${SSMTP_DEB}&lt;br /&gt;
&lt;br /&gt;
# now get all the updates&lt;br /&gt;
apt-get -y upgrade&lt;br /&gt;
&lt;br /&gt;
# make sudo passwordless for group sudo&lt;br /&gt;
echo &amp;quot;%sudo ALL=(ALL) NOPASSWD:ALL&amp;quot; &amp;gt;&amp;gt; /etc/sudoers.d/91-wheel-NOPASSWD&lt;br /&gt;
chmod 440 /etc/sudoers.d/91-wheel-NOPASSWD&lt;br /&gt;
usermod -aG sudo ewilliam&lt;br /&gt;
&lt;br /&gt;
# now that zsh is installed, make it the default&lt;br /&gt;
chsh -s /bin/zsh&lt;br /&gt;
chsh -s /bin/zsh ewilliam&lt;br /&gt;
&lt;br /&gt;
# copy the standard zsh config files&lt;br /&gt;
curl -s $CONFIG/common/.zshrc -o /root/.zshrc&lt;br /&gt;
curl -s $CONFIG/common/.zshrc -o /home/ewilliam/.zshrc&lt;br /&gt;
chown ewilliam.ewilliam /home/ewilliam/.zshrc&lt;br /&gt;
&lt;br /&gt;
# load ssh known_hosts from the config server&lt;br /&gt;
curl -s http://config/config/ssh/known_hosts -o /etc/ssh/ssh_known_hosts&lt;br /&gt;
&lt;br /&gt;
# get backup scripts&lt;br /&gt;
curl -s $CONFIG/common/backup -o /etc/cron.daily/backup&lt;br /&gt;
curl -s $CONFIG/common/rsync_backup.sh -o /usr/local/bin/rsync_backup.sh&lt;br /&gt;
chmod +x /usr/local/bin/rsync_backup.sh /etc/cron.daily/backup&lt;br /&gt;
&lt;br /&gt;
# configure log server&lt;br /&gt;
curl -s $CONFIG/common/99-remotelog.conf -o /etc/rsyslog.d/99-remotelog.conf&lt;br /&gt;
systemctl restart rsyslog&lt;br /&gt;
&lt;br /&gt;
# enable mail to the central email server&lt;br /&gt;
#  unlike the CentOS version of the ssmtp package, this doesn&#039;t recognize the /etc/aliases file&lt;br /&gt;
#  to make it work, the hostname needs to be set to &#039;williams.localnet&#039; and the mail server must be at &#039;mail&#039;&lt;br /&gt;
sed -i &#039;s/^hostname=.*$/hostname=williams.localnet/&#039; /etc/ssmtp/ssmtp.conf&lt;br /&gt;
&lt;br /&gt;
# get rid of the obnoxious political statement in the /etc/motd&lt;br /&gt;
echo &amp;gt; /etc/motd&lt;br /&gt;
&lt;br /&gt;
# get the standard /etc/hosts file&lt;br /&gt;
curl -s $CONFIG/hosts -o /etc/hosts&lt;br /&gt;
&lt;br /&gt;
# install more supporting stuff&lt;br /&gt;
apt-get install -y gpg apt-transport-https&lt;br /&gt;
&lt;br /&gt;
# install webmin&lt;br /&gt;
wget -qO - https://download.webmin.com/jcameron-key.asc | sudo apt-key add -&lt;br /&gt;
echo &amp;quot;deb https://download.webmin.com/download/repository sarge contrib&amp;quot; | sudo tee -a /etc/apt/sources.list.d/webmin.list&lt;br /&gt;
apt-get update&lt;br /&gt;
apt-get install -y webmin&lt;br /&gt;
&lt;br /&gt;
# install the host/known_hosts synchronization&lt;br /&gt;
curl -s $CONFIG/host_check.sh &amp;gt; /etc/cron.hourly/host_check&lt;br /&gt;
chmod +x /etc/cron.hourly/host_check&lt;br /&gt;
&lt;br /&gt;
# provide a daily list of packages that need updating&lt;br /&gt;
curl -s $CONFIG/debian/0-apt-upgradeable -o /etc/cron.daily/0-apt-upgradable&lt;br /&gt;
chmod +x /etc/cron.daily/0-apt-upgradable&lt;br /&gt;
&lt;br /&gt;
# install other status checks&lt;br /&gt;
curl -s $CONFIG/common/ssd-endurance &amp;gt; /etc/cron.weekly/ssd-endurance&lt;br /&gt;
chmod +x /etc/cron.weekly/ssd-endurance&lt;br /&gt;
&lt;br /&gt;
# now reboot&lt;br /&gt;
reboot&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Proliant System Utilities ==&lt;br /&gt;
For Proliant servers, we need to install the [[HPE ProLiant System Configuration/Support|Management Component Pack (MCP)]] to manage the storage controller.  A script to do this is available on the config server:&lt;br /&gt;
 curl -s http://config/config/debian/install-mcp.sh | bash -x&lt;br /&gt;
&lt;br /&gt;
[[Proliant SSA Command Examples | Here]] are some useful command examples.&lt;br /&gt;
&lt;br /&gt;
== Proliant iLO Watchdog Timer ==&lt;br /&gt;
There appears to be an issue during boot with the watchdog timer that ends up in a deadlock waiting for a response from iLO.  It has happened now on most of the HP servers running Debian.  Thanks to a rather in-depth analysis and testing [[ https://www.claudiokuenzler.com/blog/1125/debian-11-bullseye-boot-freeze-kernel-panic-hp-proliant-dl380 | here ]], the problem seems to be the hpwdt module.  According to the article, it has been blacklisted in most other distros already.  The script below creates the blacklist entry and rebuilds the initramfs images:&lt;br /&gt;
&lt;br /&gt;
 #!/bin/bash&lt;br /&gt;
 #&lt;br /&gt;
 # blacklist the HP iLO watchdog timer module (hpwdt) to avoid boot freezes under debian&lt;br /&gt;
 #&lt;br /&gt;
 echo &amp;quot;blacklist hpwdt&amp;quot; &amp;gt;&amp;gt; /etc/modprobe.d/blacklist-hp.conf&lt;br /&gt;
 update-initramfs -k all -u&lt;br /&gt;
 update-grub&lt;br /&gt;
&lt;br /&gt;
This script is available on the config server:&lt;br /&gt;
 curl -s http://config/config/debian/fix-hpwdt.sh | bash -x&lt;br /&gt;
&lt;br /&gt;
== Non-Free Drivers ==&lt;br /&gt;
Debian&#039;s militant policy towards non-free drivers can be rather annoying.  The Radeon built-in graphics controller on the motherboard for lamppost (ASUS M4A785-M) apparently needs some &#039;non-free&#039; firmware, which is not detected during the install process, even though I&#039;m using the non-free firmware installation disk image.  Because the firmmware is not loaded during the install, it isn&#039;t included in the initramdisk, and therefore the device is loaded in an inoperative state.  There is a firmware package available to install:&lt;br /&gt;
 apt install firmware-amd-graphics&lt;br /&gt;
... but even after rebooting it doesn&#039;t load because by the time the root filesystem is mounted, the devices are already initialized.  Until I find a better way, the device needs to be unloaded and reloaded after boot to enable the graphics&lt;br /&gt;
 rmmod radeon&lt;br /&gt;
 modprobe radeon&lt;br /&gt;
&lt;br /&gt;
Similarly, some RealTek drivers need to be added:&lt;br /&gt;
 apt install firmware-realtek&lt;br /&gt;
&lt;br /&gt;
Some systems also require tigon/tg3 drivers.  This one installs more than a few other packages, too ... including the amd-graphics package mentioned above.&lt;br /&gt;
 apt install -y firmware-linux-nonfree&lt;br /&gt;
&lt;br /&gt;
== Next Steps ==&lt;br /&gt;
The rest of the installation process is not OS-dependent and is described [[Common Post-Install|here]].&lt;/div&gt;</summary>
		<author><name>DrEdWilliams</name></author>
	</entry>
	<entry>
		<id>https://wiki.williams-net.org/index.php?title=Basic_Debian_Installation&amp;diff=698</id>
		<title>Basic Debian Installation</title>
		<link rel="alternate" type="text/html" href="https://wiki.williams-net.org/index.php?title=Basic_Debian_Installation&amp;diff=698"/>
		<updated>2024-02-10T16:41:01Z</updated>

		<summary type="html">&lt;p&gt;DrEdWilliams: remove webmin, fix known_hosts load, updated for Debian 12&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE&#039;&#039;&#039;:  The instructions on this page have been tested and appear to work properly on Debian 10 (&#039;&#039;&#039;Buster&#039;&#039;&#039;), Debian 11 (&#039;&#039;&#039;Bullseye&#039;&#039;&#039;), and Debian 12 (&#039;&#039;&#039;Bookworm&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
Debian standard install from distributed ISO images: &lt;br /&gt;
* Debian 10/11 - &#039;&#039;firmware-amd64-DVD&#039;&#039; (which includes the proprietary firmware that is supposedly not included in the other install disks)&lt;br /&gt;
* Debian 12 - select the full or network standard media - they have appeared to include the extra firmware in the primary install images&lt;br /&gt;
&lt;br /&gt;
Basic instructions for all versions:&lt;br /&gt;
* Do a normal &#039;Install&#039; option from the boot menu &lt;br /&gt;
** if that hangs on the network device detection, do the &#039;Expert Install&#039; option from the &#039;Advanced&#039; menu and select the default options&lt;br /&gt;
* select basic options, one partition formatting, and only the minimal software selection, but make sure the &#039;SSHD server&#039; option is selected&lt;br /&gt;
* For a graphic workstation, select the desired desktop from the list&lt;br /&gt;
* select &#039;yes&#039; for network mirror, using the defaults (USA/deb.debian.org)&lt;br /&gt;
* let it finish and reboot &lt;br /&gt;
&lt;br /&gt;
== Basic system prep ==&lt;br /&gt;
Most of the initial configuration is now contained in a script that can be executed directly from the config server as root on the target system:&lt;br /&gt;
&lt;br /&gt;
 curl -s http://config/config/debian-basic-config.sh | bash -x | tee config.out&lt;br /&gt;
 wget -qO - http://config/config/debian-basic-config.sh | bash -x | tee config.out&lt;br /&gt;
&lt;br /&gt;
The contents of this script are included here for reference, though updates to the script may occur without updates to this page:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#!/bin/sh&lt;br /&gt;
#&lt;br /&gt;
# script to do the basic install of a debian headless server&lt;br /&gt;
#&lt;br /&gt;
# Assumptions:&lt;br /&gt;
#  - this is run as root immediately after the install has completed&lt;br /&gt;
#  - the hostname has been set as desired before this script is run&lt;br /&gt;
#  - an administrator account &#039;ewilliam&#039; was created during installation&lt;br /&gt;
#&lt;br /&gt;
# invoke using one of these commands:&lt;br /&gt;
#&lt;br /&gt;
#   wget -qO http://config/config/debian-basic-config.sh | bash&lt;br /&gt;
#   curl -s http://config/config/debian-basic-config.sh | bash&lt;br /&gt;
#&lt;br /&gt;
&lt;br /&gt;
CONFIG=http://config/config&lt;br /&gt;
&lt;br /&gt;
# first -- install all the basic necessities (some may already be there)&lt;br /&gt;
apt-get update&lt;br /&gt;
apt-get install -y net-tools zsh sudo rsync mlocate wget nfs-common psmisc&lt;br /&gt;
apt-get install -y aptitude sshfs git curl smartmontools vim&lt;br /&gt;
&lt;br /&gt;
# the ssmtp package is not officially supported under buster&lt;br /&gt;
#  download the package from stretch and install&lt;br /&gt;
#SSMTP_DEB=ssmtp_2.64-9_amd64.deb&lt;br /&gt;
SSMTP_DEB=ssmtp_2.64-8+b2_amd64.deb&lt;br /&gt;
wget http://http.us.debian.org/debian/pool/main/s/ssmtp/${SSMTP_DEB}&lt;br /&gt;
apt-get install -y ./${SSMTP_DEB}&lt;br /&gt;
&lt;br /&gt;
# now get all the updates&lt;br /&gt;
apt-get -y upgrade&lt;br /&gt;
&lt;br /&gt;
# make sudo passwordless for group sudo&lt;br /&gt;
echo &amp;quot;%sudo ALL=(ALL) NOPASSWD:ALL&amp;quot; &amp;gt;&amp;gt; /etc/sudoers.d/91-wheel-NOPASSWD&lt;br /&gt;
chmod 440 /etc/sudoers.d/91-wheel-NOPASSWD&lt;br /&gt;
usermod -aG sudo ewilliam&lt;br /&gt;
&lt;br /&gt;
# now that zsh is installed, make it the default&lt;br /&gt;
chsh -s /bin/zsh&lt;br /&gt;
chsh -s /bin/zsh ewilliam&lt;br /&gt;
&lt;br /&gt;
# copy the standard zsh config files&lt;br /&gt;
curl -s $CONFIG/common/.zshrc -o /root/.zshrc&lt;br /&gt;
curl -s $CONFIG/common/.zshrc -o /home/ewilliam/.zshrc&lt;br /&gt;
chown ewilliam.ewilliam /home/ewilliam/.zshrc&lt;br /&gt;
&lt;br /&gt;
# load ssh known_hosts from the config server&lt;br /&gt;
curl -s http://config/config/ssh/known_hosts -o /etc/ssh/ssh_known_hosts&lt;br /&gt;
&lt;br /&gt;
# get backup scripts&lt;br /&gt;
curl -s $CONFIG/common/backup -o /etc/cron.daily/backup&lt;br /&gt;
curl -s $CONFIG/common/rsync_backup.sh -o /usr/local/bin/rsync_backup.sh&lt;br /&gt;
chmod +x /usr/local/bin/rsync_backup.sh /etc/cron.daily/backup&lt;br /&gt;
&lt;br /&gt;
# configure log server&lt;br /&gt;
curl -s $CONFIG/common/99-remotelog.conf -o /etc/rsyslog.d/99-remotelog.conf&lt;br /&gt;
systemctl restart rsyslog&lt;br /&gt;
&lt;br /&gt;
# enable mail to the central email server&lt;br /&gt;
#  unlike the CentOS version of the ssmtp package, this doesn&#039;t recognize the /etc/aliases file&lt;br /&gt;
#  to make it work, the hostname needs to be set to &#039;williams.localnet&#039; and the mail server must be at &#039;mail&#039;&lt;br /&gt;
sed -i &#039;s/^hostname=.*$/hostname=williams.localnet/&#039; /etc/ssmtp/ssmtp.conf&lt;br /&gt;
&lt;br /&gt;
# get rid of the obnoxious political statement in the /etc/motd&lt;br /&gt;
echo &amp;gt; /etc/motd&lt;br /&gt;
&lt;br /&gt;
# get the standard /etc/hosts file&lt;br /&gt;
curl -s $CONFIG/hosts -o /etc/hosts&lt;br /&gt;
&lt;br /&gt;
# install more supporting stuff&lt;br /&gt;
apt-get install -y gpg apt-transport-https&lt;br /&gt;
&lt;br /&gt;
# install webmin&lt;br /&gt;
wget -qO - https://download.webmin.com/jcameron-key.asc | sudo apt-key add -&lt;br /&gt;
echo &amp;quot;deb https://download.webmin.com/download/repository sarge contrib&amp;quot; | sudo tee -a /etc/apt/sources.list.d/webmin.list&lt;br /&gt;
apt-get update&lt;br /&gt;
apt-get install -y webmin&lt;br /&gt;
&lt;br /&gt;
# install the host/known_hosts synchronization&lt;br /&gt;
curl -s $CONFIG/host_check.sh &amp;gt; /etc/cron.hourly/host_check&lt;br /&gt;
chmod +x /etc/cron.hourly/host_check&lt;br /&gt;
&lt;br /&gt;
# provide a daily list of packages that need updating&lt;br /&gt;
curl -s $CONFIG/debian/0-apt-upgradeable -o /etc/cron.daily/0-apt-upgradable&lt;br /&gt;
chmod +x /etc/cron.daily/0-apt-upgradable&lt;br /&gt;
&lt;br /&gt;
# install other status checks&lt;br /&gt;
curl -s $CONFIG/common/ssd-endurance &amp;gt; /etc/cron.weekly/ssd-endurance&lt;br /&gt;
chmod +x /etc/cron.weekly/ssd-endurance&lt;br /&gt;
&lt;br /&gt;
# now reboot&lt;br /&gt;
reboot&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Proliant System Utilities ==&lt;br /&gt;
For Proliant servers, we need to install the [[HPE ProLiant System Configuration/Support|Management Component Pack (MCP)]] to manage the storage controller.  A script to do this is available on the config server:&lt;br /&gt;
 curl -s http://config/config/debian/install-mcp.sh | bash -x&lt;br /&gt;
&lt;br /&gt;
[[Proliant SSA Command Examples | Here]] are some useful command examples.&lt;br /&gt;
&lt;br /&gt;
== Non-Free Drivers ==&lt;br /&gt;
Debian&#039;s militant policy towards non-free drivers can be rather annoying.  The Radeon built-in graphics controller on the motherboard for lamppost (ASUS M4A785-M) apparently needs some &#039;non-free&#039; firmware, which is not detected during the install process, even though I&#039;m using the non-free firmware installation disk image.  Because the firmmware is not loaded during the install, it isn&#039;t included in the initramdisk, and therefore the device is loaded in an inoperative state.  There is a firmware package available to install:&lt;br /&gt;
 apt install firmware-amd-graphics&lt;br /&gt;
... but even after rebooting it doesn&#039;t load because by the time the root filesystem is mounted, the devices are already initialized.  Until I find a better way, the device needs to be unloaded and reloaded after boot to enable the graphics&lt;br /&gt;
 rmmod radeon&lt;br /&gt;
 modprobe radeon&lt;br /&gt;
&lt;br /&gt;
Similarly, some RealTek drivers need to be added:&lt;br /&gt;
 apt install firmware-realtek&lt;br /&gt;
&lt;br /&gt;
Some systems also require tigon/tg3 drivers.  This one installs more than a few other packages, too ... including the amd-graphics package mentioned above.&lt;br /&gt;
 apt install -y firmware-linux-nonfree&lt;br /&gt;
&lt;br /&gt;
== Next Steps ==&lt;br /&gt;
The rest of the installation process is not OS-dependent and is described [[Common Post-Install|here]].&lt;/div&gt;</summary>
		<author><name>DrEdWilliams</name></author>
	</entry>
	<entry>
		<id>https://wiki.williams-net.org/index.php?title=IP_Controller&amp;diff=697</id>
		<title>IP Controller</title>
		<link rel="alternate" type="text/html" href="https://wiki.williams-net.org/index.php?title=IP_Controller&amp;diff=697"/>
		<updated>2024-02-10T01:03:46Z</updated>

		<summary type="html">&lt;p&gt;DrEdWilliams: updates for newer version of metallb&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;In order for kubernetes services to be accessible outside the cluster, they need to have externally routable IP addresses.  While it would seem that this is a basic need that should be provided by kubernetes itself, its implementation is actually very dependent on the underlying platform -- and therefore left for the provider to implement.&lt;br /&gt;
&lt;br /&gt;
We are using the bare metal load balancer called [https://metallb.universe.tf/ MetalLB].  It is a full featured loadbalancer and IP controller that has multiple modes of operation.  As deployed here, it is using simple Layer 2 operation, advertising IP addresses using the existing network interfaces.&lt;br /&gt;
&lt;br /&gt;
The basic load balancer is deployed with a simple manifest:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.14.3/config/manifests/metallb-native.yaml&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point, the controller itself is active, but it has nothing to do -- it doesn&#039;t have any IP addresses to hand out.  The controller uses a Custom Resource Definition to define address pools, allocation methods, and routing protocols.  There are multiple definitions in the [https://gitlab.williams-net.org/k8s/k8s-admin k8s-admin repository on GitLab], use the one appropriate to the system:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! filename !! IP range&lt;br /&gt;
|-&lt;br /&gt;
| ipaddresspool-prod.yaml || 10.0.0.110 - 10.0.0.127&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Apply the correct pool definition to get things working:&lt;br /&gt;
 kubectl apply -f &amp;lt;filename&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This loadbalancer implementation supports the requesting of IP addresses through the &#039;&#039;&#039;loadBalancerIP&#039;&#039;&#039; parameter in the service -- if the address is available, it will allocate it.  The &#039;&#039;&#039;externalTrafficPolicy&#039;&#039;&#039; parameter is also respected.&lt;br /&gt;
&lt;br /&gt;
See the home page for the MetalLB package for complete installation and configuration options.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>DrEdWilliams</name></author>
	</entry>
	<entry>
		<id>https://wiki.williams-net.org/index.php?title=K3s_-_Kubernetes_Simplified&amp;diff=689</id>
		<title>K3s - Kubernetes Simplified</title>
		<link rel="alternate" type="text/html" href="https://wiki.williams-net.org/index.php?title=K3s_-_Kubernetes_Simplified&amp;diff=689"/>
		<updated>2023-07-09T18:36:37Z</updated>

		<summary type="html">&lt;p&gt;DrEdWilliams: added description on how to access the cluster from outside&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Lightweight Kubernetes. Production ready, easy to install, half the memory, all in a binary less than 100 MB.&lt;br /&gt;
&lt;br /&gt;
Great for:&lt;br /&gt;
* Edge&lt;br /&gt;
* IoT&lt;br /&gt;
* CI&lt;br /&gt;
* Development&lt;br /&gt;
* ARM&lt;br /&gt;
* Embedding k8s&lt;br /&gt;
* Situations where a PhD in k8s clusterology is infeasible&lt;br /&gt;
&lt;br /&gt;
Extracted from https://github.com/k3s-io/k3s ... YMMV&lt;br /&gt;
&lt;br /&gt;
What makes &#039;&#039;&#039;k3s&#039;&#039;&#039; special is that they have stripped out all the bloat-ware from upstream kubernetes that is not needed for small and bare-metal deployments.  None of the so-called cloud features are present, and most of the CSI storage drivers are also gone.&lt;br /&gt;
&lt;br /&gt;
As such, it is a simpler replacement for the &#039;&#039;&#039;kubeadm&#039;&#039;&#039; command, and it does a bit more for you:&lt;br /&gt;
* installs &#039;&#039;&#039;traefix&#039;&#039;&#039; as the default ingress controller -- it works ... especially for a test/dev cluster, but for production I&#039;ll use Contour/Envoy&lt;br /&gt;
* installs &#039;&#039;&#039;flannel&#039;&#039;&#039; as the CNI networking layer ... I had problems with flannel before, let&#039;s see if this works any better&lt;br /&gt;
* installs &#039;&#039;&#039;metrics-server&#039;&#039;&#039; to collect node/pod performance data&lt;br /&gt;
* provides a &#039;local path provisioner&#039; ... not sure what this does ... yet ...&lt;br /&gt;
__NOTOC__&lt;br /&gt;
== Basic Cluster Installation ==&lt;br /&gt;
They weren&#039;t kidding ... this is all it takes to create a simple cluster:&lt;br /&gt;
 curl -sfL https://get.k3s.io | sh -&lt;br /&gt;
A kubeconfig file is written to /etc/rancher/k3s/k3s.yaml and the service is automatically started or restarted. The install script will install K3s and additional utilities, such as kubectl, crictl, k3s-killall.sh, and k3s-uninstall.sh, for example:&lt;br /&gt;
 sudo kubectl get nodes&lt;br /&gt;
K3S_TOKEN is created at /var/lib/rancher/k3s/server/node-token on your server. To install on worker nodes we should pass K3S_URL along with K3S_TOKEN or K3S_CLUSTER_SECRET environment variables, for example:&lt;br /&gt;
 curl -sfL https://get.k3s.io | K3S_URL=https://myserver:6443 K3S_TOKEN=XXX sh -&lt;br /&gt;
&lt;br /&gt;
== HA Cluster Installation ==&lt;br /&gt;
One thing that attracted me to this distribution (as it is a distribution, not a fork of kubernetes) is that it provides a very simple way to set up a HA cluster control plane.  There are command options in the deployment that provide for the configuration of a common etcd server to facilitate a HA control plane.  Even with that ... it can get a bit cumbersome.  Enter [https://github.com/alexellis/k3sup k3sup].&lt;br /&gt;
&lt;br /&gt;
=== k3sup ===&lt;br /&gt;
k3sup is a wrapper for the k3s installer that enables:&lt;br /&gt;
* installation of a complete cluster from a single login session using SSH&lt;br /&gt;
* combining multiple k3s parameters into single options to k3sup for simplicity (i.e. &#039;&#039;&#039;--cluster&#039;&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
=== External LoadBalancer (or DNS Round Robin) ===&lt;br /&gt;
The one remaining item needed for a fully HA control plane is an external load balancer to provide a single IP address for accessing the control API from inside or outside the cluster.  Lacking something like a BigIron F5 load balancer or something equivalent, the poor-man&#039;s approach is to use a round robin in the DNS.  Problem is, the pfSense firewall doesn&#039;t do round robins by default, so a little arm twisting is needed.  Put this in the &#039;custom options&#039; in the DNS Resolver settings page:&lt;br /&gt;
 server:&lt;br /&gt;
 rrset-roundrobin: yes&lt;br /&gt;
 local-zone: &amp;quot;kube-test.williams.localnet&amp;quot; transparent&lt;br /&gt;
 local-data: &amp;quot;kube-test.williams.localnet A 10.0.0.70&amp;quot;&lt;br /&gt;
 local-data: &amp;quot;kube-test.williams.localnet A 10.0.0.71&amp;quot;&lt;br /&gt;
 local-data: &amp;quot;kube-test.williams.localnet A 10.0.0.72&amp;quot;&lt;br /&gt;
Change the name and IP addresses as needed, and then load the changes.  This approach somewhat complicates the deployment commands below, so pay attention ...&lt;br /&gt;
&lt;br /&gt;
=== Get k3sup ===&lt;br /&gt;
Not surprisingly, there are multiple ways to do this.  The author wants you to download it from a marketplace app (arkade):&lt;br /&gt;
 curl -sLS https://dl.get-arkade.dev | sh&lt;br /&gt;
 # Install the binary using the command given as output, such as: &lt;br /&gt;
 sudo cp arkade-darwin /usr/local/bin/arkade&lt;br /&gt;
 # Or on Linux:&lt;br /&gt;
 sudo cp arkade /usr/local/bin/arkade&lt;br /&gt;
 arkade get k3sup&lt;br /&gt;
&lt;br /&gt;
... or you can just download it directly ...&lt;br /&gt;
 curl -sLS https://get.k3sup.dev | sh&lt;br /&gt;
 sudo install k3sup /usr/local/bin/&lt;br /&gt;
&lt;br /&gt;
You just need to put it somewhere in your path (or use a full path reference).&lt;br /&gt;
&lt;br /&gt;
=== Install the master nodes ===&lt;br /&gt;
Install the first master node with these commands.  This will put it on the node that the command is issued from ... if that is not the desire, remove the &#039;--local&#039; parameter&lt;br /&gt;
 mkdir $HOME/.kube&lt;br /&gt;
 EXTRA_ARGS=&amp;quot;--disable servicelb --disable traefik --disable local-storage --write-kubeconfig-mode=644 --flannel-backend host-gw&amp;quot; \&lt;br /&gt;
 k3sup install --cluster --local --ip &amp;lt;server-ip-1&amp;gt; --k3s-channel stable --k3s-extra-args &#039;$EXTRA_ARGS&#039; \&lt;br /&gt;
               --local-path $HOME/.kube/config --tls-san &amp;lt;rr-dns-name&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Explanations:&lt;br /&gt;
* --cluster sets this up for a HA control plane&lt;br /&gt;
* --local says to do it on this system, instead of using SSH to the node -- &#039;&#039;&#039;but you still need to provide the IP address&#039;&#039;&#039;, otherwise it will put 127.0.0.1 as the API server address&lt;br /&gt;
* get the last stable version available from k3s (use &#039;latest&#039; to get bleeding edge updates)&lt;br /&gt;
* we want to disable the simplified k3s loadbalancer ... it really is a crowbar solution and doesn&#039;t provide IP request capability&lt;br /&gt;
* disable the default ingress controller, as we really want something better&lt;br /&gt;
* disable the local storage driver (it&#039;s a pain if you&#039;re installing another storage driver)&lt;br /&gt;
* make the k3s.yaml file readable by the pods ... really should be by default&lt;br /&gt;
* (temporary workaround) force the flannel backend to use &#039;host-gw&#039; mode since &#039;vxlan&#039; mode seems to be broken with Debian 11&lt;br /&gt;
* the --local-path tells k3sup where to put the kubeconfig files ... this is the standard place, so we will put it there.  The directory has to exist -- hence the &#039;mkdir&#039; command ...&lt;br /&gt;
* by providing the name of the DNS round robin, it should be able to pass muster on TLS connections ...&lt;br /&gt;
&lt;br /&gt;
Subsequent master nodes can be installed next:&lt;br /&gt;
 k3sup join --server --ip &amp;lt;server-ip-2&amp;gt; --k3s-channel stable --server-ip &amp;lt;server-ip-1&amp;gt; --k3s-extra-args &amp;quot;$EXTRA_ARGS&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Explanations:&lt;br /&gt;
* join as another server, not an agent/worker&lt;br /&gt;
* provide the IP address of the node to be joined&lt;br /&gt;
* specify the IP of the first mater created&lt;br /&gt;
* use the same EXTRA_ARGS provided to the first server&lt;br /&gt;
&lt;br /&gt;
Repeat this for all the masters (minimum 3) providing the same server IP address of the first master.  Note that if you need to add/remove more parameters to the k3s service, you need to do it on all server nodes -- just edit the k3s.service file and restart one server at a time.&lt;br /&gt;
&lt;br /&gt;
Now that you have all the masters online, reset the kubeconfig file (~/.kube/config) to use the DNS RR name instead of the IP of the first master:&lt;br /&gt;
 sed -i -e s/&amp;lt;server-ip-1&amp;gt;/&amp;lt;rr-dns-name&amp;gt;/g $HOME/.kube/config&lt;br /&gt;
&lt;br /&gt;
=== Install Worker Nodes ===&lt;br /&gt;
At this point, you should have an operational cluster.  k3s enables masters to be used for normal pods by default, so this is the minimum operational cluster.  Next, install the agent/worker nodes:&lt;br /&gt;
 k3sup join --ip &amp;lt;agent-node-x&amp;gt; --k3s-channel stable --server-host &amp;lt;rr-dns-name&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Explanations:&lt;br /&gt;
* Joining as an agent, so no &#039;--server&#039; this time&lt;br /&gt;
* provide each agent/worker IP in turn&lt;br /&gt;
* instead of the &#039;--server-ip&#039; parameter, we are using the &#039;--server-host&#039; parameter so we can use the DNS RR to ensure that the nodes always can access a master&lt;br /&gt;
&lt;br /&gt;
== Automated Upgrades:  System Upgrade Controller ==&lt;br /&gt;
&lt;br /&gt;
Rancher has taken the simplicity of k3s to another level by providing a kubernetes controller that can update the cluster ``from within the cluster`` using the [https://rancher.com/docs/k3s/latest/en/upgrades/automated/ System Upgrade Controller].&lt;br /&gt;
&lt;br /&gt;
Installing the controller is straightforward using a single manifest (also located in the git repo): &lt;br /&gt;
 kubectl apply -f https://github.com/rancher/system-upgrade-controller/releases/download/v0.7.6/system-upgrade-controller.yaml&lt;br /&gt;
&lt;br /&gt;
The controller looks for upgrade plans as custom resources (of type &#039;Plan&#039;, for some odd reason) to define its behavior.  Two &#039;Plan&#039;s are required ... one for server/master nodes and one for agent/worker nodes.  These plans can be set up to either upgrade to a specific k3s version or to monitor the release channel and automatically upgrade when a new release is available.  The manifest looks like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# Server plan&lt;br /&gt;
apiVersion: upgrade.cattle.io/v1&lt;br /&gt;
kind: Plan&lt;br /&gt;
metadata:&lt;br /&gt;
  name: server-plan&lt;br /&gt;
  namespace: system-upgrade&lt;br /&gt;
spec:&lt;br /&gt;
  concurrency: 1&lt;br /&gt;
  cordon: true&lt;br /&gt;
  nodeSelector:&lt;br /&gt;
    matchExpressions:&lt;br /&gt;
    - key: node-role.kubernetes.io/master&lt;br /&gt;
      operator: In&lt;br /&gt;
      values:&lt;br /&gt;
      - &amp;quot;true&amp;quot;&lt;br /&gt;
  serviceAccountName: system-upgrade&lt;br /&gt;
  upgrade:&lt;br /&gt;
    image: rancher/k3s-upgrade&lt;br /&gt;
  #version: v1.20.4+k3s1&lt;br /&gt;
  channel: https://update.k3s.io/v1-release/channels/stable&lt;br /&gt;
---&lt;br /&gt;
# Agent plan&lt;br /&gt;
apiVersion: upgrade.cattle.io/v1&lt;br /&gt;
kind: Plan&lt;br /&gt;
metadata:&lt;br /&gt;
  name: agent-plan&lt;br /&gt;
  namespace: system-upgrade&lt;br /&gt;
spec:&lt;br /&gt;
  concurrency: 1&lt;br /&gt;
  cordon: true&lt;br /&gt;
  nodeSelector:&lt;br /&gt;
    matchExpressions:&lt;br /&gt;
    - key: node-role.kubernetes.io/master&lt;br /&gt;
      operator: DoesNotExist&lt;br /&gt;
  prepare:&lt;br /&gt;
    args:&lt;br /&gt;
    - prepare&lt;br /&gt;
    - server-plan&lt;br /&gt;
    image: rancher/k3s-upgrade #:v1.17.4-k3s1&lt;br /&gt;
  serviceAccountName: system-upgrade&lt;br /&gt;
  upgrade:&lt;br /&gt;
    image: rancher/k3s-upgrade&lt;br /&gt;
  #version: v1.20.4+k3s1&lt;br /&gt;
  channel: https://update.k3s.io/v1-release/channels/stable&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Simply apply this manifest and the controller will identify nodes to upgrade and will take care of them as instructed.  It&#039;s as simple as that.  If you don&#039;t want to automatically upgrade, comment out the &#039;channel&#039; parameter in each Plan, and uncomment the &#039;version&#039; parameter and set it to the version to upgrade to and apply.  The controller will see the new plan and act accordingly.  If there is nothing to do, the controller just sits there waiting for a new plan with some work.&lt;br /&gt;
&lt;br /&gt;
== Cluster Access==&lt;br /&gt;
The kubeconfig file stored at /etc/rancher/k3s/k3s.yaml is used to configure access to the Kubernetes cluster. If you have installed upstream Kubernetes command line tools such as kubectl or helm you will need to configure them with the correct kubeconfig path. This can be done by either exporting the KUBECONFIG environment variable or by invoking the --kubeconfig command line flag. Refer to the examples below for details.&lt;br /&gt;
&lt;br /&gt;
Leverage the KUBECONFIG environment variable:&lt;br /&gt;
 export KUBECONFIG=/etc/rancher/k3s/k3s.yaml&lt;br /&gt;
 kubectl get pods --all-namespaces&lt;br /&gt;
 helm ls --all-namespaces&lt;br /&gt;
 &lt;br /&gt;
Or specify the location of the kubeconfig file in the command:&lt;br /&gt;
&lt;br /&gt;
 kubectl --kubeconfig /etc/rancher/k3s/k3s.yaml get pods --all-namespaces&lt;br /&gt;
 helm --kubeconfig /etc/rancher/k3s/k3s.yaml ls --all-namespaces&lt;br /&gt;
&lt;br /&gt;
To access the kubernetes cluster from outside the cluster, copy &amp;lt;pre&amp;gt;/etc/rancher/k3s/k3s.yaml&amp;lt;/pre&amp;gt; on your machine located outside the cluster as &amp;lt;pre&amp;gt;~/.kube/config&amp;lt;/pre&amp;gt;Then replace the value of the server field with the modified name of the K3s server cluster as described above. kubectl can now manage your K3s cluster.&lt;br /&gt;
&lt;br /&gt;
==Cluster Maintenance==&lt;br /&gt;
As packages (particularly helm charts) are updated, old container images are left behind.  Not deleting container images is not generally a bad thing since it enables pods to migrate between nodes in the cluster without waiting for the container to be downloaded.  Upgrading packages, however leaves a lot of cruft behind that can eventually cause issues with disk space.  Supposedly Kubernetes manages this garbage collection, but other related packages (such as ceph) complain about low disk space long before Kubernetes decides to do anything about it.  Cleaning out the old containers is simple, fortunately:&lt;br /&gt;
 /usr/local/bin/k3s crictl rmi -q&lt;br /&gt;
While this can be run at any time, running it too often will remove containers that are still valid, just not used at that time on that node -- resulting in longer migration times when nodes are drained or fail.&lt;br /&gt;
&lt;br /&gt;
==Finishing The Job==&lt;br /&gt;
These instructions will create a simple or HA kubernetes cluster.  The HA cluster can survive a single master failure, but two will take down the cluster.&lt;br /&gt;
&lt;br /&gt;
At this point you jump back into the rest of the instructions for installing a [[Kubernetes Cluster Installation|Kubernetes Cluster]], remembering that the network layer and metrics server have already been installed.&lt;/div&gt;</summary>
		<author><name>DrEdWilliams</name></author>
	</entry>
	<entry>
		<id>https://wiki.williams-net.org/index.php?title=Aslan&amp;diff=688</id>
		<title>Aslan</title>
		<link rel="alternate" type="text/html" href="https://wiki.williams-net.org/index.php?title=Aslan&amp;diff=688"/>
		<updated>2023-06-04T01:14:43Z</updated>

		<summary type="html">&lt;p&gt;DrEdWilliams: &amp;quot;removed vmware horizon &amp;amp; fixed spacing&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This system is the primary linux workstation in the office and needs to have the basic apps for a graphic workstation:&lt;br /&gt;
&lt;br /&gt;
* KDE Plasma Desktop&lt;br /&gt;
* Mate terminal (Ubuntu app)&lt;br /&gt;
* VideoLAN media player (https://videolan.org/vlc/download-redhat.html)&lt;br /&gt;
* Visual Studio Code (vscode - https://code.visualstudio.com/download)&lt;br /&gt;
* Calibre library manager (download)&lt;br /&gt;
* HPCMP Kerberos Kit (https://centers.hpc.mil)&lt;br /&gt;
** CAC software (CA CoolKey?)&lt;br /&gt;
* Kontena Lens (download latest)&lt;br /&gt;
* Thunderbird&lt;br /&gt;
* Slack&lt;br /&gt;
* Synergy (v1)&lt;br /&gt;
* NVIDIA drivers (default with kubuntu/nonfree)&lt;br /&gt;
* Zoom client&lt;br /&gt;
* Firefox&lt;br /&gt;
* rclone (for google &amp;amp; dropbox mounts)&lt;br /&gt;
* pdsh&lt;br /&gt;
* Oracle Java (the real thing) for the Dell Storage manager&lt;br /&gt;
* minio client (mc) for gitlab backup -- there is a copy in /work/bin if that will work for the platform.&lt;br /&gt;
* Dell Equalogic Group Manager (java webstart - requires iSCSInet interface below and Oracle Java)&lt;br /&gt;
&lt;br /&gt;
Configurations:&lt;br /&gt;
* mount /work and /files filesystems&lt;br /&gt;
* configure extra network devices&lt;br /&gt;
** StorageNet (10.1.0.8) - use the second ethernet interface&lt;br /&gt;
** iSCSInet (10.2.0.200) - done via [[VLAN Interfaces|VLAN]] 15 on the StorageNet interface&lt;br /&gt;
* set up [[Mounting Google Drive and Dropbox|dropbox/google drive mounts]] (gdrives script in /work/bin)&lt;br /&gt;
&lt;br /&gt;
Tasks/Applications (in addition to normal housekeeping):&lt;br /&gt;
&lt;br /&gt;
* cron daily:&lt;br /&gt;
** check-all (moved to pro6)&lt;br /&gt;
** Backup GitLab (moved to caspian)&lt;br /&gt;
*** mount storage1:/backup/systems to /backup_systems&lt;br /&gt;
*** install the cert for the gitlab instance (since it is self-signed)&lt;/div&gt;</summary>
		<author><name>DrEdWilliams</name></author>
	</entry>
	<entry>
		<id>https://wiki.williams-net.org/index.php?title=Aslan&amp;diff=687</id>
		<title>Aslan</title>
		<link rel="alternate" type="text/html" href="https://wiki.williams-net.org/index.php?title=Aslan&amp;diff=687"/>
		<updated>2023-01-15T03:16:35Z</updated>

		<summary type="html">&lt;p&gt;DrEdWilliams: &amp;quot;gitlab backup moved to caspian&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This system is the primary linux workstation in the office and needs to have the basic apps for a graphic workstation:&lt;br /&gt;
&lt;br /&gt;
* KDE Plasma Desktop&lt;br /&gt;
* Mate terminal (Ubuntu app)&lt;br /&gt;
* VideoLAN media player (https://videolan.org/vlc/download-redhat.html)&lt;br /&gt;
* VMware Horizon Client (for SAIC VDI access)&lt;br /&gt;
* Visual Studio Code (vscode - https://code.visualstudio.com/download)&lt;br /&gt;
* Calibre library manager (download)&lt;br /&gt;
* HPCMP Kerberos Kit (https://centers.hpc.mil)&lt;br /&gt;
** CAC software (CA CoolKey?)&lt;br /&gt;
* Kontena Lens (download latest)&lt;br /&gt;
* Thunderbird&lt;br /&gt;
* Slack&lt;br /&gt;
* Synergy (v1)&lt;br /&gt;
* NVIDIA drivers (default with kubuntu/nonfree)&lt;br /&gt;
* Zoom client&lt;br /&gt;
* Firefox&lt;br /&gt;
* rclone (for google &amp;amp; dropbox mounts)&lt;br /&gt;
*pdsh&lt;br /&gt;
*Oracle Java (the real thing) for the Dell Storage manager&lt;br /&gt;
*minio client (mc) for gitlab backup -- there is a copy in /work/bin if that will work for the platform.&lt;br /&gt;
*Dell Equalogic Group Manager (java webstart - requires iSCSInet interface below and Oracle Java)&lt;br /&gt;
&lt;br /&gt;
Configurations:&lt;br /&gt;
* mount /work and /files filesystems&lt;br /&gt;
*configure extra network devices&lt;br /&gt;
**StorageNet (10.1.0.8) - use the second ethernet interface&lt;br /&gt;
**iSCSInet (10.2.0.200) - done via [[VLAN Interfaces|VLAN]] 15 on the StorageNet interface&lt;br /&gt;
* set up [[Mounting Google Drive and Dropbox|dropbox/google drive mounts]] (gdrives script in /work/bin)&lt;br /&gt;
Tasks/Applications (in addition to normal housekeeping):&lt;br /&gt;
&lt;br /&gt;
* cron daily:&lt;br /&gt;
** check-all (moved to pro6)&lt;br /&gt;
** Backup GitLab (moved to caspian)&lt;br /&gt;
*** mount storage1:/backup/systems to /backup_systems&lt;br /&gt;
*** install the cert for the gitlab instance (since it is self-signed)&lt;/div&gt;</summary>
		<author><name>DrEdWilliams</name></author>
	</entry>
	<entry>
		<id>https://wiki.williams-net.org/index.php?title=Aslan&amp;diff=686</id>
		<title>Aslan</title>
		<link rel="alternate" type="text/html" href="https://wiki.williams-net.org/index.php?title=Aslan&amp;diff=686"/>
		<updated>2023-01-15T03:16:35Z</updated>

		<summary type="html">&lt;p&gt;DrEdWilliams: &amp;quot;test commit&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This system is the primary linux workstation in the office and needs to have the basic apps for a graphic workstation:&lt;br /&gt;
&lt;br /&gt;
* KDE Plasma Desktop&lt;br /&gt;
* Mate terminal (Ubuntu app)&lt;br /&gt;
* VideoLAN media player (https://videolan.org/vlc/download-redhat.html)&lt;br /&gt;
* VMware Horizon Client (for SAIC VDI access)&lt;br /&gt;
* Visual Studio Code (vscode - https://code.visualstudio.com/download)&lt;br /&gt;
* Calibre library manager (download)&lt;br /&gt;
* HPCMP Kerberos Kit (https://centers.hpc.mil)&lt;br /&gt;
** CAC software (CA CoolKey?)&lt;br /&gt;
* Kontena Lens (download latest)&lt;br /&gt;
* Thunderbird&lt;br /&gt;
* Slack&lt;br /&gt;
* Synergy (v1)&lt;br /&gt;
* NVIDIA drivers (default with kubuntu/nonfree)&lt;br /&gt;
* Zoom client&lt;br /&gt;
* Firefox&lt;br /&gt;
* rclone (for google &amp;amp; dropbox mounts)&lt;br /&gt;
*pdsh&lt;br /&gt;
*Oracle Java (the real thing) for the Dell Storage manager&lt;br /&gt;
*minio client (mc) for gitlab backup -- there is a copy in /work/bin if that will work for the platform.&lt;br /&gt;
*Dell Equalogic Group Manager (java webstart - requires iSCSInet interface below and Oracle Java)&lt;br /&gt;
&lt;br /&gt;
Configurations:&lt;br /&gt;
* mount /work and /files filesystems&lt;br /&gt;
*configure extra network devices&lt;br /&gt;
**StorageNet (10.1.0.8) - use the second ethernet interface&lt;br /&gt;
**iSCSInet (10.2.0.200) - done via [[VLAN Interfaces|VLAN]] 15 on the StorageNet interface&lt;br /&gt;
* set up [[Mounting Google Drive and Dropbox|dropbox/google drive mounts]] (gdrives script in /work/bin)&lt;br /&gt;
Tasks/Applications (in addition to normal housekeeping):&lt;br /&gt;
&lt;br /&gt;
* cron daily:&lt;br /&gt;
** check-all (moved to pro6)&lt;br /&gt;
** Backup GitLab&lt;br /&gt;
***mount storage1:/backup/systems to /backup_systems&lt;br /&gt;
***install the cert for the gitlab instance (since it is self-signed)&lt;/div&gt;</summary>
		<author><name>DrEdWilliams</name></author>
	</entry>
	<entry>
		<id>https://wiki.williams-net.org/index.php?title=Production_Cluster_Configuration&amp;diff=685</id>
		<title>Production Cluster Configuration</title>
		<link rel="alternate" type="text/html" href="https://wiki.williams-net.org/index.php?title=Production_Cluster_Configuration&amp;diff=685"/>
		<updated>2022-05-18T00:21:36Z</updated>

		<summary type="html">&lt;p&gt;DrEdWilliams: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;These packages form the basic functionality of the production cluster.  &lt;br /&gt;
&lt;br /&gt;
Scripts &amp;amp; config files are checked into gitlab under the Kubernetes group project listed.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! activity !! gitlab !! script/procedures/config !! IP !! hostname(s)&lt;br /&gt;
|-&lt;br /&gt;
| [[Ceph Storage Cluster]] || k8s-admin || || ||&lt;br /&gt;
|-&lt;br /&gt;
| [[Rook Storage for Kubernetes|Rook Storage]] || k8s-admin || || || (StorageClass)&amp;lt;br/&amp;gt;rook-ceph-hdd&amp;lt;br/&amp;gt;rook-ceph-nvme&lt;br /&gt;
|-| gitlab registry secrets || || gitlab-registry-kube-system.yaml &amp;lt;br /&amp;gt; gitlab-registry-secret.yaml || ||&lt;br /&gt;
|-&lt;br /&gt;
| mail || k8s/mail || || 10.0.0.114 || mail.williams.localnet&lt;br /&gt;
|-&lt;br /&gt;
| wordpress (dredwilliams.com) || k8s/dredwilliams || || || dredwilliams.williams-net.org&lt;br /&gt;
|-&lt;br /&gt;
| mediawiki || mediawiki || || 10.0.0.116 || wiki.williams.localnet &amp;lt;br /&amp;gt;wiki.williams-net.org&lt;br /&gt;
|-&lt;br /&gt;
| [[MariaDB]] || mariadb || || 10.0.0.117 || database.williams.localnet&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Storage ===&lt;br /&gt;
The production cluster depends on the &#039;&#039;&#039;/shared&#039;&#039;&#039; filesystem for its persistent storage as provided by the production Ceph cluster.  The Ceph is configured as shown here:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! system !! function !! storage !! size&lt;br /&gt;
|-&lt;br /&gt;
| caspian || master || NVMe&amp;lt;br/&amp;gt;HDD || 1TB&amp;lt;br/&amp;gt;1TB&lt;br /&gt;
|-&lt;br /&gt;
| uvilas || node || NVMe&amp;lt;br/&amp;gt;HDD&amp;lt;br/&amp;gt;HDD || 1TB&amp;lt;br/&amp;gt;1TB&amp;lt;br/&amp;gt;1TB&lt;br /&gt;
|-&lt;br /&gt;
| belisar || node || NVMe&amp;lt;br/&amp;gt;HDD || 1TB&amp;lt;br/&amp;gt;250GB&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The work filesystem can be mounted via NFS:&lt;br /&gt;
&lt;br /&gt;
 10.0.0.75:/work /work nfs4 soft 0 0&lt;br /&gt;
&lt;br /&gt;
=== Backups ===&lt;br /&gt;
&lt;br /&gt;
In addition to the normal backups configured in the basic OS installation steps, the databases in the production cluster must be backed up daily using the &#039;mysqldump&#039; command:&lt;br /&gt;
&lt;br /&gt;
 TBD&lt;br /&gt;
&lt;br /&gt;
These commands should be inserted into the /etc/cron.daily/backup file on one of the cluster nodes (telmar is a good choice).  The first does a complete database dump of the MediaWiki database server, the second dumps just the mediawiki database itself, and the third dumps the general purpose database server.  Additional dump commands should be inserted for additional significant databases, as parsing individual databases out of a system dump can be tedious.&lt;/div&gt;</summary>
		<author><name>DrEdWilliams</name></author>
	</entry>
	<entry>
		<id>https://wiki.williams-net.org/index.php?title=K3s_-_Kubernetes_Simplified&amp;diff=684</id>
		<title>K3s - Kubernetes Simplified</title>
		<link rel="alternate" type="text/html" href="https://wiki.williams-net.org/index.php?title=K3s_-_Kubernetes_Simplified&amp;diff=684"/>
		<updated>2022-02-25T12:34:46Z</updated>

		<summary type="html">&lt;p&gt;DrEdWilliams: added container cleanup instructions&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Lightweight Kubernetes. Production ready, easy to install, half the memory, all in a binary less than 100 MB.&lt;br /&gt;
&lt;br /&gt;
Great for:&lt;br /&gt;
* Edge&lt;br /&gt;
* IoT&lt;br /&gt;
* CI&lt;br /&gt;
* Development&lt;br /&gt;
* ARM&lt;br /&gt;
* Embedding k8s&lt;br /&gt;
* Situations where a PhD in k8s clusterology is infeasible&lt;br /&gt;
&lt;br /&gt;
Extracted from https://github.com/k3s-io/k3s ... YMMV&lt;br /&gt;
&lt;br /&gt;
What makes &#039;&#039;&#039;k3s&#039;&#039;&#039; special is that they have stripped out all the bloat-ware from upstream kubernetes that is not needed for small and bare-metal deployments.  None of the so-called cloud features are present, and most of the CSI storage drivers are also gone.&lt;br /&gt;
&lt;br /&gt;
As such, it is a simpler replacement for the &#039;&#039;&#039;kubeadm&#039;&#039;&#039; command, and it does a bit more for you:&lt;br /&gt;
* installs &#039;&#039;&#039;traefix&#039;&#039;&#039; as the default ingress controller -- it works ... especially for a test/dev cluster, but for production I&#039;ll use Contour/Envoy&lt;br /&gt;
* installs &#039;&#039;&#039;flannel&#039;&#039;&#039; as the CNI networking layer ... I had problems with flannel before, let&#039;s see if this works any better&lt;br /&gt;
* installs &#039;&#039;&#039;metrics-server&#039;&#039;&#039; to collect node/pod performance data&lt;br /&gt;
* provides a &#039;local path provisioner&#039; ... not sure what this does ... yet ...&lt;br /&gt;
__NOTOC__&lt;br /&gt;
== Basic Cluster Installation ==&lt;br /&gt;
They weren&#039;t kidding ... this is all it takes to create a simple cluster:&lt;br /&gt;
 curl -sfL https://get.k3s.io | sh -&lt;br /&gt;
A kubeconfig file is written to /etc/rancher/k3s/k3s.yaml and the service is automatically started or restarted. The install script will install K3s and additional utilities, such as kubectl, crictl, k3s-killall.sh, and k3s-uninstall.sh, for example:&lt;br /&gt;
 sudo kubectl get nodes&lt;br /&gt;
K3S_TOKEN is created at /var/lib/rancher/k3s/server/node-token on your server. To install on worker nodes we should pass K3S_URL along with K3S_TOKEN or K3S_CLUSTER_SECRET environment variables, for example:&lt;br /&gt;
 curl -sfL https://get.k3s.io | K3S_URL=https://myserver:6443 K3S_TOKEN=XXX sh -&lt;br /&gt;
&lt;br /&gt;
== HA Cluster Installation ==&lt;br /&gt;
One thing that attracted me to this distribution (as it is a distribution, not a fork of kubernetes) is that it provides a very simple way to set up a HA cluster control plane.  There are command options in the deployment that provide for the configuration of a common etcd server to facilitate a HA control plane.  Even with that ... it can get a bit cumbersome.  Enter [https://github.com/alexellis/k3sup k3sup].&lt;br /&gt;
&lt;br /&gt;
=== k3sup ===&lt;br /&gt;
k3sup is a wrapper for the k3s installer that enables:&lt;br /&gt;
* installation of a complete cluster from a single login session using SSH&lt;br /&gt;
* combining multiple k3s parameters into single options to k3sup for simplicity (i.e. &#039;&#039;&#039;--cluster&#039;&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
=== External LoadBalancer (or DNS Round Robin) ===&lt;br /&gt;
The one remaining item needed for a fully HA control plane is an external load balancer to provide a single IP address for accessing the control API from inside or outside the cluster.  Lacking something like a BigIron F5 load balancer or something equivalent, the poor-man&#039;s approach is to use a round robin in the DNS.  Problem is, the pfSense firewall doesn&#039;t do round robins by default, so a little arm twisting is needed.  Put this in the &#039;custom options&#039; in the DNS Resolver settings page:&lt;br /&gt;
 server:&lt;br /&gt;
 rrset-roundrobin: yes&lt;br /&gt;
 local-zone: &amp;quot;kube-test.williams.localnet&amp;quot; transparent&lt;br /&gt;
 local-data: &amp;quot;kube-test.williams.localnet A 10.0.0.70&amp;quot;&lt;br /&gt;
 local-data: &amp;quot;kube-test.williams.localnet A 10.0.0.71&amp;quot;&lt;br /&gt;
 local-data: &amp;quot;kube-test.williams.localnet A 10.0.0.72&amp;quot;&lt;br /&gt;
Change the name and IP addresses as needed, and then load the changes.  This approach somewhat complicates the deployment commands below, so pay attention ...&lt;br /&gt;
&lt;br /&gt;
=== Get k3sup ===&lt;br /&gt;
Not surprisingly, there are multiple ways to do this.  The author wants you to download it from a marketplace app (arkade):&lt;br /&gt;
 curl -sLS https://dl.get-arkade.dev | sh&lt;br /&gt;
 # Install the binary using the command given as output, such as: &lt;br /&gt;
 sudo cp arkade-darwin /usr/local/bin/arkade&lt;br /&gt;
 # Or on Linux:&lt;br /&gt;
 sudo cp arkade /usr/local/bin/arkade&lt;br /&gt;
 arkade get k3sup&lt;br /&gt;
&lt;br /&gt;
... or you can just download it directly ...&lt;br /&gt;
 curl -sLS https://get.k3sup.dev | sh&lt;br /&gt;
 sudo install k3sup /usr/local/bin/&lt;br /&gt;
&lt;br /&gt;
You just need to put it somewhere in your path (or use a full path reference).&lt;br /&gt;
&lt;br /&gt;
=== Install the master nodes ===&lt;br /&gt;
Install the first master node with these commands.  This will put it on the node that the command is issued from ... if that is not the desire, remove the &#039;--local&#039; parameter&lt;br /&gt;
 mkdir $HOME/.kube&lt;br /&gt;
 EXTRA_ARGS=&amp;quot;--disable servicelb --disable traefik --disable local-storage --write-kubeconfig-mode=644 --flannel-backend host-gw&amp;quot; \&lt;br /&gt;
 k3sup install --cluster --local --ip &amp;lt;server-ip-1&amp;gt; --k3s-channel stable --k3s-extra-args &#039;$EXTRA_ARGS&#039; \&lt;br /&gt;
               --local-path $HOME/.kube/config --tls-san &amp;lt;rr-dns-name&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Explanations:&lt;br /&gt;
* --cluster sets this up for a HA control plane&lt;br /&gt;
* --local says to do it on this system, instead of using SSH to the node -- &#039;&#039;&#039;but you still need to provide the IP address&#039;&#039;&#039;, otherwise it will put 127.0.0.1 as the API server address&lt;br /&gt;
* get the last stable version available from k3s (use &#039;latest&#039; to get bleeding edge updates)&lt;br /&gt;
* we want to disable the simplified k3s loadbalancer ... it really is a crowbar solution and doesn&#039;t provide IP request capability&lt;br /&gt;
* disable the default ingress controller, as we really want something better&lt;br /&gt;
* disable the local storage driver (it&#039;s a pain if you&#039;re installing another storage driver)&lt;br /&gt;
* make the k3s.yaml file readable by the pods ... really should be by default&lt;br /&gt;
* (temporary workaround) force the flannel backend to use &#039;host-gw&#039; mode since &#039;vxlan&#039; mode seems to be broken with Debian 11&lt;br /&gt;
* the --local-path tells k3sup where to put the kubeconfig files ... this is the standard place, so we will put it there.  The directory has to exist -- hence the &#039;mkdir&#039; command ...&lt;br /&gt;
* by providing the name of the DNS round robin, it should be able to pass muster on TLS connections ...&lt;br /&gt;
&lt;br /&gt;
Subsequent master nodes can be installed next:&lt;br /&gt;
 k3sup join --server --ip &amp;lt;server-ip-2&amp;gt; --k3s-channel stable --server-ip &amp;lt;server-ip-1&amp;gt; --k3s-extra-args &amp;quot;$EXTRA_ARGS&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Explanations:&lt;br /&gt;
* join as another server, not an agent/worker&lt;br /&gt;
* provide the IP address of the node to be joined&lt;br /&gt;
* specify the IP of the first mater created&lt;br /&gt;
* use the same EXTRA_ARGS provided to the first server&lt;br /&gt;
&lt;br /&gt;
Repeat this for all the masters (minimum 3) providing the same server IP address of the first master.  Note that if you need to add/remove more parameters to the k3s service, you need to do it on all server nodes -- just edit the k3s.service file and restart one server at a time.&lt;br /&gt;
&lt;br /&gt;
Now that you have all the masters online, reset the kubeconfig file (~/.kube/config) to use the DNS RR name instead of the IP of the first master:&lt;br /&gt;
 sed -i -e s/&amp;lt;server-ip-1&amp;gt;/&amp;lt;rr-dns-name&amp;gt;/g $HOME/.kube/config&lt;br /&gt;
&lt;br /&gt;
=== Install Worker Nodes ===&lt;br /&gt;
At this point, you should have an operational cluster.  k3s enables masters to be used for normal pods by default, so this is the minimum operational cluster.  Next, install the agent/worker nodes:&lt;br /&gt;
 k3sup join --ip &amp;lt;agent-node-x&amp;gt; --k3s-channel stable --server-host &amp;lt;rr-dns-name&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Explanations:&lt;br /&gt;
* Joining as an agent, so no &#039;--server&#039; this time&lt;br /&gt;
* provide each agent/worker IP in turn&lt;br /&gt;
* instead of the &#039;--server-ip&#039; parameter, we are using the &#039;--server-host&#039; parameter so we can use the DNS RR to ensure that the nodes always can access a master&lt;br /&gt;
&lt;br /&gt;
== Automated Upgrades:  System Upgrade Controller ==&lt;br /&gt;
&lt;br /&gt;
Rancher has taken the simplicity of k3s to another level by providing a kubernetes controller that can update the cluster ``from within the cluster`` using the [https://rancher.com/docs/k3s/latest/en/upgrades/automated/ System Upgrade Controller].&lt;br /&gt;
&lt;br /&gt;
Installing the controller is straightforward using a single manifest (also located in the git repo): &lt;br /&gt;
 kubectl apply -f https://github.com/rancher/system-upgrade-controller/releases/download/v0.7.6/system-upgrade-controller.yaml&lt;br /&gt;
&lt;br /&gt;
The controller looks for upgrade plans as custom resources (of type &#039;Plan&#039;, for some odd reason) to define its behavior.  Two &#039;Plan&#039;s are required ... one for server/master nodes and one for agent/worker nodes.  These plans can be set up to either upgrade to a specific k3s version or to monitor the release channel and automatically upgrade when a new release is available.  The manifest looks like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# Server plan&lt;br /&gt;
apiVersion: upgrade.cattle.io/v1&lt;br /&gt;
kind: Plan&lt;br /&gt;
metadata:&lt;br /&gt;
  name: server-plan&lt;br /&gt;
  namespace: system-upgrade&lt;br /&gt;
spec:&lt;br /&gt;
  concurrency: 1&lt;br /&gt;
  cordon: true&lt;br /&gt;
  nodeSelector:&lt;br /&gt;
    matchExpressions:&lt;br /&gt;
    - key: node-role.kubernetes.io/master&lt;br /&gt;
      operator: In&lt;br /&gt;
      values:&lt;br /&gt;
      - &amp;quot;true&amp;quot;&lt;br /&gt;
  serviceAccountName: system-upgrade&lt;br /&gt;
  upgrade:&lt;br /&gt;
    image: rancher/k3s-upgrade&lt;br /&gt;
  #version: v1.20.4+k3s1&lt;br /&gt;
  channel: https://update.k3s.io/v1-release/channels/stable&lt;br /&gt;
---&lt;br /&gt;
# Agent plan&lt;br /&gt;
apiVersion: upgrade.cattle.io/v1&lt;br /&gt;
kind: Plan&lt;br /&gt;
metadata:&lt;br /&gt;
  name: agent-plan&lt;br /&gt;
  namespace: system-upgrade&lt;br /&gt;
spec:&lt;br /&gt;
  concurrency: 1&lt;br /&gt;
  cordon: true&lt;br /&gt;
  nodeSelector:&lt;br /&gt;
    matchExpressions:&lt;br /&gt;
    - key: node-role.kubernetes.io/master&lt;br /&gt;
      operator: DoesNotExist&lt;br /&gt;
  prepare:&lt;br /&gt;
    args:&lt;br /&gt;
    - prepare&lt;br /&gt;
    - server-plan&lt;br /&gt;
    image: rancher/k3s-upgrade #:v1.17.4-k3s1&lt;br /&gt;
  serviceAccountName: system-upgrade&lt;br /&gt;
  upgrade:&lt;br /&gt;
    image: rancher/k3s-upgrade&lt;br /&gt;
  #version: v1.20.4+k3s1&lt;br /&gt;
  channel: https://update.k3s.io/v1-release/channels/stable&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Simply apply this manifest and the controller will identify nodes to upgrade and will take care of them as instructed.  It&#039;s as simple as that.  If you don&#039;t want to automatically upgrade, comment out the &#039;channel&#039; parameter in each Plan, and uncomment the &#039;version&#039; parameter and set it to the version to upgrade to and apply.  The controller will see the new plan and act accordingly.  If there is nothing to do, the controller just sits there waiting for a new plan with some work.&lt;br /&gt;
&lt;br /&gt;
== Cluster Maintenance ==&lt;br /&gt;
As packages (particularly helm charts) are updated, old container images are left behind.  Not deleting container images is not generally a bad thing since it enables pods to migrate between nodes in the cluster without waiting for the container to be downloaded.  Upgrading packages, however leaves a lot of cruft behind that can eventually cause issues with disk space.  Supposedly Kubernetes manages this garbage collection, but other related packages (such as ceph) complain about low disk space long before Kubernetes decides to do anything about it.  Cleaning out the old containers is simple, fortunately:&lt;br /&gt;
 /usr/local/bin/k3s crictl rmi -q&lt;br /&gt;
While this can be run at any time, running it too often will remove containers that are still valid, just not used at that time on that node -- resulting in longer migration times when nodes are drained or fail.&lt;br /&gt;
&lt;br /&gt;
== Finishing The Job ==&lt;br /&gt;
These instructions will create a simple or HA kubernetes cluster.  The HA cluster can survive a single master failure, but two will take down the cluster.&lt;br /&gt;
&lt;br /&gt;
At this point you jump back into the rest of the instructions for installing a [[Kubernetes Cluster Installation|Kubernetes Cluster]], remembering that the network layer and metrics server have already been installed.&lt;/div&gt;</summary>
		<author><name>DrEdWilliams</name></author>
	</entry>
	<entry>
		<id>https://wiki.williams-net.org/index.php?title=Memory_Testing&amp;diff=683</id>
		<title>Memory Testing</title>
		<link rel="alternate" type="text/html" href="https://wiki.williams-net.org/index.php?title=Memory_Testing&amp;diff=683"/>
		<updated>2021-12-28T02:24:22Z</updated>

		<summary type="html">&lt;p&gt;DrEdWilliams: Created page with &amp;quot;Install the memtester utility from the software repository, if it is not already installed.   Ubuntu/Debian and Linux Mint:  sudo apt-get install memtester Fedora/RHEL/RPM:  y...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Install the memtester utility from the software repository, if it is not already installed. &lt;br /&gt;
&lt;br /&gt;
Ubuntu/Debian and Linux Mint:&lt;br /&gt;
 sudo apt-get install memtester&lt;br /&gt;
Fedora/RHEL/RPM:&lt;br /&gt;
 yum install memtester&lt;br /&gt;
As root, run the test:&lt;br /&gt;
 memtester &amp;lt;memory size&amp;gt; &amp;lt;repetitions&amp;gt;&lt;br /&gt;
... where:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;memory size&amp;gt; is in megabytes&lt;br /&gt;
* &amp;lt;repetitions&amp;gt; is the number of times the full suite will be run&lt;br /&gt;
&lt;br /&gt;
To get the exit status:&lt;br /&gt;
&lt;br /&gt;
echo $?&lt;br /&gt;
&lt;br /&gt;
Possible values:&lt;br /&gt;
&lt;br /&gt;
* x00: success&lt;br /&gt;
* x01: Error allocating or locking memory, or invocation error &lt;br /&gt;
* x02: Error during stuck address test &lt;br /&gt;
* x04: Error during one of the other tests.&lt;br /&gt;
&lt;br /&gt;
(excerpted from https://www.techwalla.com/articles/how-to-test-the-ram-on-linux)&lt;/div&gt;</summary>
		<author><name>DrEdWilliams</name></author>
	</entry>
	<entry>
		<id>https://wiki.williams-net.org/index.php?title=System_Administration_Processes&amp;diff=682</id>
		<title>System Administration Processes</title>
		<link rel="alternate" type="text/html" href="https://wiki.williams-net.org/index.php?title=System_Administration_Processes&amp;diff=682"/>
		<updated>2021-12-28T02:17:51Z</updated>

		<summary type="html">&lt;p&gt;DrEdWilliams: /* Sustainment Practices */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Non-standard Repositories ==&lt;br /&gt;
* [[Centos Repos]]&lt;br /&gt;
&lt;br /&gt;
== Basic OS installation ==&lt;br /&gt;
* [[Basic Ubuntu Installation]]&lt;br /&gt;
*[[Basic CentOS 7 Installation]]&lt;br /&gt;
* [[Basic Debian Installation]]&lt;br /&gt;
* [[Basic Fedora 31+ Installation]]&lt;br /&gt;
* [[Fedora 33 - Workstation Installation]]&lt;br /&gt;
*[[Common Post-Install]]&lt;br /&gt;
&lt;br /&gt;
== System Configuration ==&lt;br /&gt;
* [[HPE ProLiant System Configuration/Support]]&lt;br /&gt;
* [[Ethernet Device Configuration]]&lt;br /&gt;
* [[CUDA + NVIDIA drivers]]&lt;br /&gt;
* [[NVIDIA Docker Runtime|Installing NVIDIA Docker Runtime]]&lt;br /&gt;
* [[VLAN Interfaces]]&lt;br /&gt;
*[[Mounting Google Drive and Dropbox]]&lt;br /&gt;
*[[Mounting iSCSI LUNs]]&lt;br /&gt;
&lt;br /&gt;
== Application Installation ==&lt;br /&gt;
* [[Plex Media Server - Debian]]&lt;br /&gt;
* [[Docker Installation]]&lt;br /&gt;
* [[Ceph Storage Cluster]]&lt;br /&gt;
* [[Kubernetes Cluster Installation]]&lt;br /&gt;
* [http://www.webmin.com/download.html Webmin Installation]&lt;br /&gt;
&lt;br /&gt;
== Sustainment Practices ==&lt;br /&gt;
* [[SSH Host Key Management]]&lt;br /&gt;
* [[Log Accumulator]]&lt;br /&gt;
* [[Benchmark commands]]&lt;br /&gt;
*[[Memory Testing]]&lt;br /&gt;
&lt;br /&gt;
== Deprecated ==&lt;br /&gt;
*&lt;/div&gt;</summary>
		<author><name>DrEdWilliams</name></author>
	</entry>
	<entry>
		<id>https://wiki.williams-net.org/index.php?title=HPE_ProLiant_System_Configuration/Support&amp;diff=681</id>
		<title>HPE ProLiant System Configuration/Support</title>
		<link rel="alternate" type="text/html" href="https://wiki.williams-net.org/index.php?title=HPE_ProLiant_System_Configuration/Support&amp;diff=681"/>
		<updated>2021-12-24T18:07:06Z</updated>

		<summary type="html">&lt;p&gt;DrEdWilliams: /* HPE Enterprise Support */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Debian has a page in their Wiki covering anecdotal reports of compatibility/support for Debian on the HP ProLiant Server family:  https://wiki.debian.org/HP/ProLiant&lt;br /&gt;
&lt;br /&gt;
== HPE Software Repositories ==&lt;br /&gt;
HPE maintains RPM and Debian repositories for their system support software -- see http://downloads.linux.hpe.com/SDR/project/mcp/&lt;br /&gt;
&lt;br /&gt;
The software available through the repository includes:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! package !! description&lt;br /&gt;
|-&lt;br /&gt;
| hp-health || HPE System Health Application and Command line Utilities (Gen9 and earlier)&lt;br /&gt;
|-&lt;br /&gt;
| hponcfg || HPE RILOE II/iLO online configuration utility&lt;br /&gt;
|-&lt;br /&gt;
| amsd || HPE Agentless Management Service (Gen10 only)&lt;br /&gt;
|-&lt;br /&gt;
| hp-ams || HPE Agentless Management Service (Gen9 and earlier)&lt;br /&gt;
|-&lt;br /&gt;
| hp-snmp-agents || Insight Management SNMP Agents for HPE ProLiant Systems (Gen9 and earlier)&lt;br /&gt;
|-&lt;br /&gt;
| hpsmh || HPE System Management Homepage (Gen9 and earlier)&lt;br /&gt;
|-&lt;br /&gt;
| hp-smh-templates || HPE System Management Homepage Templates (Gen9 and earlier)&lt;br /&gt;
|-&lt;br /&gt;
| ssacli || HPE Command Line Smart Storage Administration Utility&lt;br /&gt;
|-&lt;br /&gt;
| ssaducli || HPE Command Line Smart Storage Administration Diagnostics&lt;br /&gt;
|-&lt;br /&gt;
| ssa || HPE Array Smart Storage Administration Service&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== RPM Repository ===&lt;br /&gt;
Cut-n-paste the following section (substituting distribution, architecture and project version) into /etc/yum.repos.d/mcp.repo on your system:&lt;br /&gt;
&lt;br /&gt;
 [mcp]&lt;br /&gt;
 name=Management Component Pack&lt;br /&gt;
 baseurl=http://downloads.linux.hpe.com/repo/mcp/dist/dist_ver/arch/project_ver&lt;br /&gt;
 enabled=1&lt;br /&gt;
 gpgcheck=0&lt;br /&gt;
 gpgkey=file:///etc/pki/rpm-gpg/GPG-KEY-mcp&lt;br /&gt;
&lt;br /&gt;
Where:&lt;br /&gt;
&amp;lt;pre&amp;gt;   dist          centos, fedora, opensuse, oracle, asianux&lt;br /&gt;
   dist_ver      [http://downloads.linux.hpe.com/SDR/repo/mcp/ Browse repo to identify supported distribution versions]&lt;br /&gt;
   arch          i386, x86_64&lt;br /&gt;
   project_ver   current, 11.30, 11.21, 11.05, 10.62, 10.50, 10.40, 10.20, 10.00, 9.30, 9.25&amp;lt;/pre&amp;gt;&lt;br /&gt;
        &lt;br /&gt;
List the packages in the repository&lt;br /&gt;
 yum --disablerepo=&amp;quot;*&amp;quot; --enablerepo=&amp;quot;short_repo_name&amp;quot; list available&lt;br /&gt;
&lt;br /&gt;
Install a specific package&lt;br /&gt;
 yum install &amp;lt;packagename&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Debian Repositories ===&lt;br /&gt;
Cut-n-paste the following section (substituting distribution, architecture and project version) into /etc/apt/sources.list.d/mcp.list on your system:&lt;br /&gt;
&lt;br /&gt;
 # HPE Management Component Pack &lt;br /&gt;
 deb http://downloads.linux.hpe.com/SDR/repo/mcp dist/project_ver non-free&lt;br /&gt;
&lt;br /&gt;
Where:&lt;br /&gt;
&amp;lt;pre&amp;gt;   dist             bionic, xenial, trusty, precise, stretch, jessie, squeeze, wheezy&lt;br /&gt;
   project_ver      current, 11.30, 11.21, 11.05, 10.80, 10.60, 10.50, 10.40, 9.50, 9.40&amp;lt;/pre&amp;gt;&lt;br /&gt;
        &lt;br /&gt;
Install the HPE public gpg key -- instructions at http://downloads.linux.hpe.com/SDR/keys&lt;br /&gt;
&lt;br /&gt;
Update the local apt indexes&lt;br /&gt;
 apt-get update&lt;br /&gt;
&lt;br /&gt;
Search for a specific package&lt;br /&gt;
 apt-cache search &amp;lt;packagename&amp;gt; # browse debs&lt;br /&gt;
&lt;br /&gt;
Install a specific package&lt;br /&gt;
 apt-get install &amp;lt;packagename&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== SmartArray P410i ==&lt;br /&gt;
=== Smart Storage Administration ===&lt;br /&gt;
The ssa utility provides a nice GUI for managing the drive arrays in the DL380G7 ... but it comes with a heavy cost in terms of software that must be installed.  Beyond the &#039;&#039;&#039;ssa&#039;&#039;&#039; package that must be installed, the use requires that firefox is installed and displayable from the local machine.  Given that the systems do not run in graphics mode, this means that you need to make sure that the X11 DISPLAY veriable is set properly to tunnel the result back to a graphical workstation.&lt;br /&gt;
&lt;br /&gt;
After installing the repository above, install the packages:&lt;br /&gt;
 yum install -y ssa firefox xauth&lt;br /&gt;
... or ...&lt;br /&gt;
 apt install -y ssa firefox-esr xauth&lt;br /&gt;
Be warned -- the firefox install alone grabs over 100 dependent packages ...&lt;br /&gt;
&lt;br /&gt;
After installing everything, run the SSA package in local mode:&lt;br /&gt;
 ssa -local&lt;br /&gt;
&lt;br /&gt;
This will start a background process and then launch firefox pointing at that process, which listens on a random high port number.  This is a very poor situation, but the tool itself is very nice and allows (as far as I can tell) do everything to configure the controller and attached disks and arrays.&lt;br /&gt;
&lt;br /&gt;
For a quick status that can be put in a regular status check (cron.daily or crontab), use the &#039;&#039;&#039;ssacli&#039;&#039;&#039; command:&lt;br /&gt;
 yum install ssacli&lt;br /&gt;
... or ...&lt;br /&gt;
 apt install ssacli&lt;br /&gt;
&lt;br /&gt;
 ssacli ctrl slot=0 pd all show&lt;br /&gt;
This will show all the drives in the first controller slot (ther is only one in the chassis, I think)&lt;br /&gt;
&lt;br /&gt;
=== HPE Enterprise Support ===&lt;br /&gt;
The HP overview is located here:  https://support.hpe.com/hpsc/doc/public/display?docId=emr_na-c01677092&lt;br /&gt;
&lt;br /&gt;
HPE full parts lists:  https://support.hpe.com/hpesc/public/docDisplay?docLocale=en_US&amp;amp;docId=c04396629&lt;br /&gt;
&lt;br /&gt;
The full enterprise support site is located at https://support.hpe.com/hpesc/public/km/product/3883933/Product#t=Documents&amp;amp;sort=relevancy&amp;amp;layout=table&amp;amp;f:@kmdoclanguagecode=[cv1871440]&amp;amp;hpe=1&lt;br /&gt;
&lt;br /&gt;
== ProLiant DL380G7 ==&lt;br /&gt;
HPE overview:  https://support.hpe.com/hpsc/doc/public/display?docId=emr_na-c02215285&lt;br /&gt;
&lt;br /&gt;
HPE ProLiant DL380 G7 Server - Specifications: https://support.hpe.com/hpsc/doc/public/display?docLocale=en_US&amp;amp;docId=emr_na-c02215298&lt;br /&gt;
&lt;br /&gt;
Search | HPE Support Center - Drivers for HPE ProLiant DL380 G7 Server Models : https://support.hpe.com/hpesc/public/km/product/4091567/Product#t=DriversandSoftware&amp;amp;sort=relevancy&amp;amp;layout=table&lt;br /&gt;
&lt;br /&gt;
== ProLiant DL380p Gen8 ==&lt;br /&gt;
&lt;br /&gt;
HPE Overview: https://support.hpe.com/hpesc/public/docDisplay?docId=emr_na-c03235277&lt;br /&gt;
&lt;br /&gt;
Intel CPU (Xeon E5-2640 2.5 GHz 6 core): &lt;br /&gt;
&lt;br /&gt;
https://ark.intel.com/content/www/us/en/ark/products/64591/intel-xeon-processor-e52640-15m-cache-2-50-ghz-7-20-gts-intel-qpi.html&lt;/div&gt;</summary>
		<author><name>DrEdWilliams</name></author>
	</entry>
	<entry>
		<id>https://wiki.williams-net.org/index.php?title=HPE_ProLiant_System_Configuration/Support&amp;diff=680</id>
		<title>HPE ProLiant System Configuration/Support</title>
		<link rel="alternate" type="text/html" href="https://wiki.williams-net.org/index.php?title=HPE_ProLiant_System_Configuration/Support&amp;diff=680"/>
		<updated>2021-12-21T00:12:04Z</updated>

		<summary type="html">&lt;p&gt;DrEdWilliams: /* ProLiant DL380p Gen8 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Debian has a page in their Wiki covering anecdotal reports of compatibility/support for Debian on the HP ProLiant Server family:  https://wiki.debian.org/HP/ProLiant&lt;br /&gt;
&lt;br /&gt;
== HPE Software Repositories ==&lt;br /&gt;
HPE maintains RPM and Debian repositories for their system support software -- see http://downloads.linux.hpe.com/SDR/project/mcp/&lt;br /&gt;
&lt;br /&gt;
The software available through the repository includes:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! package !! description&lt;br /&gt;
|-&lt;br /&gt;
| hp-health || HPE System Health Application and Command line Utilities (Gen9 and earlier)&lt;br /&gt;
|-&lt;br /&gt;
| hponcfg || HPE RILOE II/iLO online configuration utility&lt;br /&gt;
|-&lt;br /&gt;
| amsd || HPE Agentless Management Service (Gen10 only)&lt;br /&gt;
|-&lt;br /&gt;
| hp-ams || HPE Agentless Management Service (Gen9 and earlier)&lt;br /&gt;
|-&lt;br /&gt;
| hp-snmp-agents || Insight Management SNMP Agents for HPE ProLiant Systems (Gen9 and earlier)&lt;br /&gt;
|-&lt;br /&gt;
| hpsmh || HPE System Management Homepage (Gen9 and earlier)&lt;br /&gt;
|-&lt;br /&gt;
| hp-smh-templates || HPE System Management Homepage Templates (Gen9 and earlier)&lt;br /&gt;
|-&lt;br /&gt;
| ssacli || HPE Command Line Smart Storage Administration Utility&lt;br /&gt;
|-&lt;br /&gt;
| ssaducli || HPE Command Line Smart Storage Administration Diagnostics&lt;br /&gt;
|-&lt;br /&gt;
| ssa || HPE Array Smart Storage Administration Service&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== RPM Repository ===&lt;br /&gt;
Cut-n-paste the following section (substituting distribution, architecture and project version) into /etc/yum.repos.d/mcp.repo on your system:&lt;br /&gt;
&lt;br /&gt;
 [mcp]&lt;br /&gt;
 name=Management Component Pack&lt;br /&gt;
 baseurl=http://downloads.linux.hpe.com/repo/mcp/dist/dist_ver/arch/project_ver&lt;br /&gt;
 enabled=1&lt;br /&gt;
 gpgcheck=0&lt;br /&gt;
 gpgkey=file:///etc/pki/rpm-gpg/GPG-KEY-mcp&lt;br /&gt;
&lt;br /&gt;
Where:&lt;br /&gt;
&amp;lt;pre&amp;gt;   dist          centos, fedora, opensuse, oracle, asianux&lt;br /&gt;
   dist_ver      [http://downloads.linux.hpe.com/SDR/repo/mcp/ Browse repo to identify supported distribution versions]&lt;br /&gt;
   arch          i386, x86_64&lt;br /&gt;
   project_ver   current, 11.30, 11.21, 11.05, 10.62, 10.50, 10.40, 10.20, 10.00, 9.30, 9.25&amp;lt;/pre&amp;gt;&lt;br /&gt;
        &lt;br /&gt;
List the packages in the repository&lt;br /&gt;
 yum --disablerepo=&amp;quot;*&amp;quot; --enablerepo=&amp;quot;short_repo_name&amp;quot; list available&lt;br /&gt;
&lt;br /&gt;
Install a specific package&lt;br /&gt;
 yum install &amp;lt;packagename&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Debian Repositories ===&lt;br /&gt;
Cut-n-paste the following section (substituting distribution, architecture and project version) into /etc/apt/sources.list.d/mcp.list on your system:&lt;br /&gt;
&lt;br /&gt;
 # HPE Management Component Pack &lt;br /&gt;
 deb http://downloads.linux.hpe.com/SDR/repo/mcp dist/project_ver non-free&lt;br /&gt;
&lt;br /&gt;
Where:&lt;br /&gt;
&amp;lt;pre&amp;gt;   dist             bionic, xenial, trusty, precise, stretch, jessie, squeeze, wheezy&lt;br /&gt;
   project_ver      current, 11.30, 11.21, 11.05, 10.80, 10.60, 10.50, 10.40, 9.50, 9.40&amp;lt;/pre&amp;gt;&lt;br /&gt;
        &lt;br /&gt;
Install the HPE public gpg key -- instructions at http://downloads.linux.hpe.com/SDR/keys&lt;br /&gt;
&lt;br /&gt;
Update the local apt indexes&lt;br /&gt;
 apt-get update&lt;br /&gt;
&lt;br /&gt;
Search for a specific package&lt;br /&gt;
 apt-cache search &amp;lt;packagename&amp;gt; # browse debs&lt;br /&gt;
&lt;br /&gt;
Install a specific package&lt;br /&gt;
 apt-get install &amp;lt;packagename&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== SmartArray P410i ==&lt;br /&gt;
=== Smart Storage Administration ===&lt;br /&gt;
The ssa utility provides a nice GUI for managing the drive arrays in the DL380G7 ... but it comes with a heavy cost in terms of software that must be installed.  Beyond the &#039;&#039;&#039;ssa&#039;&#039;&#039; package that must be installed, the use requires that firefox is installed and displayable from the local machine.  Given that the systems do not run in graphics mode, this means that you need to make sure that the X11 DISPLAY veriable is set properly to tunnel the result back to a graphical workstation.&lt;br /&gt;
&lt;br /&gt;
After installing the repository above, install the packages:&lt;br /&gt;
 yum install -y ssa firefox xauth&lt;br /&gt;
... or ...&lt;br /&gt;
 apt install -y ssa firefox-esr xauth&lt;br /&gt;
Be warned -- the firefox install alone grabs over 100 dependent packages ...&lt;br /&gt;
&lt;br /&gt;
After installing everything, run the SSA package in local mode:&lt;br /&gt;
 ssa -local&lt;br /&gt;
&lt;br /&gt;
This will start a background process and then launch firefox pointing at that process, which listens on a random high port number.  This is a very poor situation, but the tool itself is very nice and allows (as far as I can tell) do everything to configure the controller and attached disks and arrays.&lt;br /&gt;
&lt;br /&gt;
For a quick status that can be put in a regular status check (cron.daily or crontab), use the &#039;&#039;&#039;ssacli&#039;&#039;&#039; command:&lt;br /&gt;
 yum install ssacli&lt;br /&gt;
... or ...&lt;br /&gt;
 apt install ssacli&lt;br /&gt;
&lt;br /&gt;
 ssacli ctrl slot=0 pd all show&lt;br /&gt;
This will show all the drives in the first controller slot (ther is only one in the chassis, I think)&lt;br /&gt;
&lt;br /&gt;
=== HPE Enterprise Support ===&lt;br /&gt;
The HP overview is located here:  https://support.hpe.com/hpsc/doc/public/display?docId=emr_na-c01677092&lt;br /&gt;
&lt;br /&gt;
The full enterprise support site is located at https://support.hpe.com/hpesc/public/km/product/3883933/Product#t=Documents&amp;amp;sort=relevancy&amp;amp;layout=table&amp;amp;f:@kmdoclanguagecode=[cv1871440]&amp;amp;hpe=1&lt;br /&gt;
&lt;br /&gt;
== ProLiant DL380G7 ==&lt;br /&gt;
HPE overview:  https://support.hpe.com/hpsc/doc/public/display?docId=emr_na-c02215285&lt;br /&gt;
&lt;br /&gt;
HPE ProLiant DL380 G7 Server - Specifications: https://support.hpe.com/hpsc/doc/public/display?docLocale=en_US&amp;amp;docId=emr_na-c02215298&lt;br /&gt;
&lt;br /&gt;
Search | HPE Support Center - Drivers for HPE ProLiant DL380 G7 Server Models : https://support.hpe.com/hpesc/public/km/product/4091567/Product#t=DriversandSoftware&amp;amp;sort=relevancy&amp;amp;layout=table&lt;br /&gt;
&lt;br /&gt;
== ProLiant DL380p Gen8 ==&lt;br /&gt;
&lt;br /&gt;
HPE Overview: https://support.hpe.com/hpesc/public/docDisplay?docId=emr_na-c03235277&lt;br /&gt;
&lt;br /&gt;
Intel CPU (Xeon E5-2640 2.5 GHz 6 core): &lt;br /&gt;
&lt;br /&gt;
https://ark.intel.com/content/www/us/en/ark/products/64591/intel-xeon-processor-e52640-15m-cache-2-50-ghz-7-20-gts-intel-qpi.html&lt;/div&gt;</summary>
		<author><name>DrEdWilliams</name></author>
	</entry>
	<entry>
		<id>https://wiki.williams-net.org/index.php?title=Hardware&amp;diff=679</id>
		<title>Hardware</title>
		<link rel="alternate" type="text/html" href="https://wiki.williams-net.org/index.php?title=Hardware&amp;diff=679"/>
		<updated>2021-12-21T00:10:34Z</updated>

		<summary type="html">&lt;p&gt;DrEdWilliams: /* HP ProLiant Server */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== HP NC364T 4-port PCIe GigaBit NIC ==&lt;br /&gt;
Overview:  http://www.harddrivesdirect.com/product_info.php?manufacturers_id=&amp;amp;products_id=454534&lt;br /&gt;
&lt;br /&gt;
== HP ProLiant Server ==&lt;br /&gt;
Here is some info on the HP servers ... reference:  https://en.wikipedia.org/wiki/ProLiant -- useful, but not as complete as the other page.&lt;br /&gt;
&lt;br /&gt;
ProLiant servers are also split into several series which denote processor configuration. &lt;br /&gt;
* The 100, 200, 300 and 400 series comprise single and dual socket capable systems, &lt;br /&gt;
* the 500 and 600 series comprise quad socket capable systems, &lt;br /&gt;
* the 700 and 900 series comprise eight socket capable systems. &lt;br /&gt;
* The 900 series also includes eight sockets, supporting up to 80 CPU cores and up to 4 TB of RAM.&lt;br /&gt;
The second digit represents the capability of the system -- sockets, DIMMs, cores, drives&lt;br /&gt;
* x20 -- single socket, very limited&lt;br /&gt;
* x60 -- good performance&lt;br /&gt;
* x80 -- high capacity&lt;br /&gt;
* x90 -- outrageous&lt;br /&gt;
&lt;br /&gt;
the &#039;Gen&#039; indicator is how modern the CPU is ... higher is newer ... Gen10 is current product line&lt;br /&gt;
&lt;br /&gt;
== Related Pages ==&lt;br /&gt;
[[HPE ProLiant System Configuration/Support]]&lt;/div&gt;</summary>
		<author><name>DrEdWilliams</name></author>
	</entry>
	<entry>
		<id>https://wiki.williams-net.org/index.php?title=HPE_ProLiant_System_Configuration/Support&amp;diff=678</id>
		<title>HPE ProLiant System Configuration/Support</title>
		<link rel="alternate" type="text/html" href="https://wiki.williams-net.org/index.php?title=HPE_ProLiant_System_Configuration/Support&amp;diff=678"/>
		<updated>2021-12-20T23:58:59Z</updated>

		<summary type="html">&lt;p&gt;DrEdWilliams: /* ProLiant DL380G7 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Debian has a page in their Wiki covering anecdotal reports of compatibility/support for Debian on the HP ProLiant Server family:  https://wiki.debian.org/HP/ProLiant&lt;br /&gt;
&lt;br /&gt;
== HPE Software Repositories ==&lt;br /&gt;
HPE maintains RPM and Debian repositories for their system support software -- see http://downloads.linux.hpe.com/SDR/project/mcp/&lt;br /&gt;
&lt;br /&gt;
The software available through the repository includes:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! package !! description&lt;br /&gt;
|-&lt;br /&gt;
| hp-health || HPE System Health Application and Command line Utilities (Gen9 and earlier)&lt;br /&gt;
|-&lt;br /&gt;
| hponcfg || HPE RILOE II/iLO online configuration utility&lt;br /&gt;
|-&lt;br /&gt;
| amsd || HPE Agentless Management Service (Gen10 only)&lt;br /&gt;
|-&lt;br /&gt;
| hp-ams || HPE Agentless Management Service (Gen9 and earlier)&lt;br /&gt;
|-&lt;br /&gt;
| hp-snmp-agents || Insight Management SNMP Agents for HPE ProLiant Systems (Gen9 and earlier)&lt;br /&gt;
|-&lt;br /&gt;
| hpsmh || HPE System Management Homepage (Gen9 and earlier)&lt;br /&gt;
|-&lt;br /&gt;
| hp-smh-templates || HPE System Management Homepage Templates (Gen9 and earlier)&lt;br /&gt;
|-&lt;br /&gt;
| ssacli || HPE Command Line Smart Storage Administration Utility&lt;br /&gt;
|-&lt;br /&gt;
| ssaducli || HPE Command Line Smart Storage Administration Diagnostics&lt;br /&gt;
|-&lt;br /&gt;
| ssa || HPE Array Smart Storage Administration Service&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== RPM Repository ===&lt;br /&gt;
Cut-n-paste the following section (substituting distribution, architecture and project version) into /etc/yum.repos.d/mcp.repo on your system:&lt;br /&gt;
&lt;br /&gt;
 [mcp]&lt;br /&gt;
 name=Management Component Pack&lt;br /&gt;
 baseurl=http://downloads.linux.hpe.com/repo/mcp/dist/dist_ver/arch/project_ver&lt;br /&gt;
 enabled=1&lt;br /&gt;
 gpgcheck=0&lt;br /&gt;
 gpgkey=file:///etc/pki/rpm-gpg/GPG-KEY-mcp&lt;br /&gt;
&lt;br /&gt;
Where:&lt;br /&gt;
&amp;lt;pre&amp;gt;   dist          centos, fedora, opensuse, oracle, asianux&lt;br /&gt;
   dist_ver      [http://downloads.linux.hpe.com/SDR/repo/mcp/ Browse repo to identify supported distribution versions]&lt;br /&gt;
   arch          i386, x86_64&lt;br /&gt;
   project_ver   current, 11.30, 11.21, 11.05, 10.62, 10.50, 10.40, 10.20, 10.00, 9.30, 9.25&amp;lt;/pre&amp;gt;&lt;br /&gt;
        &lt;br /&gt;
List the packages in the repository&lt;br /&gt;
 yum --disablerepo=&amp;quot;*&amp;quot; --enablerepo=&amp;quot;short_repo_name&amp;quot; list available&lt;br /&gt;
&lt;br /&gt;
Install a specific package&lt;br /&gt;
 yum install &amp;lt;packagename&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Debian Repositories ===&lt;br /&gt;
Cut-n-paste the following section (substituting distribution, architecture and project version) into /etc/apt/sources.list.d/mcp.list on your system:&lt;br /&gt;
&lt;br /&gt;
 # HPE Management Component Pack &lt;br /&gt;
 deb http://downloads.linux.hpe.com/SDR/repo/mcp dist/project_ver non-free&lt;br /&gt;
&lt;br /&gt;
Where:&lt;br /&gt;
&amp;lt;pre&amp;gt;   dist             bionic, xenial, trusty, precise, stretch, jessie, squeeze, wheezy&lt;br /&gt;
   project_ver      current, 11.30, 11.21, 11.05, 10.80, 10.60, 10.50, 10.40, 9.50, 9.40&amp;lt;/pre&amp;gt;&lt;br /&gt;
        &lt;br /&gt;
Install the HPE public gpg key -- instructions at http://downloads.linux.hpe.com/SDR/keys&lt;br /&gt;
&lt;br /&gt;
Update the local apt indexes&lt;br /&gt;
 apt-get update&lt;br /&gt;
&lt;br /&gt;
Search for a specific package&lt;br /&gt;
 apt-cache search &amp;lt;packagename&amp;gt; # browse debs&lt;br /&gt;
&lt;br /&gt;
Install a specific package&lt;br /&gt;
 apt-get install &amp;lt;packagename&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== SmartArray P410i ==&lt;br /&gt;
=== Smart Storage Administration ===&lt;br /&gt;
The ssa utility provides a nice GUI for managing the drive arrays in the DL380G7 ... but it comes with a heavy cost in terms of software that must be installed.  Beyond the &#039;&#039;&#039;ssa&#039;&#039;&#039; package that must be installed, the use requires that firefox is installed and displayable from the local machine.  Given that the systems do not run in graphics mode, this means that you need to make sure that the X11 DISPLAY veriable is set properly to tunnel the result back to a graphical workstation.&lt;br /&gt;
&lt;br /&gt;
After installing the repository above, install the packages:&lt;br /&gt;
 yum install -y ssa firefox xauth&lt;br /&gt;
... or ...&lt;br /&gt;
 apt install -y ssa firefox-esr xauth&lt;br /&gt;
Be warned -- the firefox install alone grabs over 100 dependent packages ...&lt;br /&gt;
&lt;br /&gt;
After installing everything, run the SSA package in local mode:&lt;br /&gt;
 ssa -local&lt;br /&gt;
&lt;br /&gt;
This will start a background process and then launch firefox pointing at that process, which listens on a random high port number.  This is a very poor situation, but the tool itself is very nice and allows (as far as I can tell) do everything to configure the controller and attached disks and arrays.&lt;br /&gt;
&lt;br /&gt;
For a quick status that can be put in a regular status check (cron.daily or crontab), use the &#039;&#039;&#039;ssacli&#039;&#039;&#039; command:&lt;br /&gt;
 yum install ssacli&lt;br /&gt;
... or ...&lt;br /&gt;
 apt install ssacli&lt;br /&gt;
&lt;br /&gt;
 ssacli ctrl slot=0 pd all show&lt;br /&gt;
This will show all the drives in the first controller slot (ther is only one in the chassis, I think)&lt;br /&gt;
&lt;br /&gt;
=== HPE Enterprise Support ===&lt;br /&gt;
The HP overview is located here:  https://support.hpe.com/hpsc/doc/public/display?docId=emr_na-c01677092&lt;br /&gt;
&lt;br /&gt;
The full enterprise support site is located at https://support.hpe.com/hpesc/public/km/product/3883933/Product#t=Documents&amp;amp;sort=relevancy&amp;amp;layout=table&amp;amp;f:@kmdoclanguagecode=[cv1871440]&amp;amp;hpe=1&lt;br /&gt;
&lt;br /&gt;
== ProLiant DL380G7 ==&lt;br /&gt;
HPE overview:  https://support.hpe.com/hpsc/doc/public/display?docId=emr_na-c02215285&lt;br /&gt;
&lt;br /&gt;
HPE ProLiant DL380 G7 Server - Specifications: https://support.hpe.com/hpsc/doc/public/display?docLocale=en_US&amp;amp;docId=emr_na-c02215298&lt;br /&gt;
&lt;br /&gt;
Search | HPE Support Center - Drivers for HPE ProLiant DL380 G7 Server Models : https://support.hpe.com/hpesc/public/km/product/4091567/Product#t=DriversandSoftware&amp;amp;sort=relevancy&amp;amp;layout=table&lt;br /&gt;
&lt;br /&gt;
== ProLiant DL380p Gen8 ==&lt;br /&gt;
&lt;br /&gt;
HPE Overview: https://support.hpe.com/hpesc/public/docDisplay?docId=emr_na-c03235277&lt;/div&gt;</summary>
		<author><name>DrEdWilliams</name></author>
	</entry>
	<entry>
		<id>https://wiki.williams-net.org/index.php?title=How-To&amp;diff=677</id>
		<title>How-To</title>
		<link rel="alternate" type="text/html" href="https://wiki.williams-net.org/index.php?title=How-To&amp;diff=677"/>
		<updated>2021-12-19T11:17:17Z</updated>

		<summary type="html">&lt;p&gt;DrEdWilliams: /* Miscellaneous How-To Instructions */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
== Miscellaneous How-To Instructions ==&lt;br /&gt;
* [[Linux RAID Array]]&lt;br /&gt;
*Certificate Procedures&lt;br /&gt;
** [[Creating a Self-Signed Certificate]]&lt;br /&gt;
**[[Creating a CA and certificates]]&lt;br /&gt;
**[[Verify certificate with CA]]&lt;br /&gt;
** [[Renewing  the &#039;localhost&#039; Certificate]]&lt;br /&gt;
** [[Adding a certificate to the system store]]&lt;br /&gt;
* [[Repositories for Miniconda]]&lt;br /&gt;
* [[Mobile IPsec Clients]]&lt;br /&gt;
* [[NVMe Drives]]&lt;br /&gt;
* iSCSI Procedures&lt;br /&gt;
** [[Mounting iSCSI LUNs]]&lt;br /&gt;
** [[Systemd mounted iSCSI volumes]]&lt;br /&gt;
** [[Removing a persistent iSCSI connection]]&lt;br /&gt;
* [[Installing a recent copy of git]]&lt;br /&gt;
* [[OSQuery|OSQuery - SQL-like access to system information]]&lt;br /&gt;
*[[Mounting Google Drive and Dropbox]]&lt;br /&gt;
*[[NGINX Basic Authentication]]&lt;br /&gt;
*[[Removing a disk from LVM]]&lt;br /&gt;
*Changing [[Open File Limits]]&lt;br /&gt;
&lt;br /&gt;
== System Update Procedures ==&lt;br /&gt;
* [[Upgrading Docker]]&lt;br /&gt;
&lt;br /&gt;
== MediaWiki notes ==&lt;br /&gt;
* [[Deleting old copies of pages from the database]]&lt;/div&gt;</summary>
		<author><name>DrEdWilliams</name></author>
	</entry>
	<entry>
		<id>https://wiki.williams-net.org/index.php?title=Open_File_Limits&amp;diff=676</id>
		<title>Open File Limits</title>
		<link rel="alternate" type="text/html" href="https://wiki.williams-net.org/index.php?title=Open_File_Limits&amp;diff=676"/>
		<updated>2021-12-19T11:16:35Z</updated>

		<summary type="html">&lt;p&gt;DrEdWilliams: Created page with &amp;quot;To change maximum open file limits for your terminal session, run this command:  # ulimit -n 3000 After closing the terminal and creating a new session, the limits will get ba...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;To change maximum open file limits for your terminal session, run this command:&lt;br /&gt;
 # ulimit -n 3000&lt;br /&gt;
After closing the terminal and creating a new session, the limits will get back to the original values specified in /etc/security/limits.conf.&lt;br /&gt;
&lt;br /&gt;
To change the general value for the system &amp;lt;code&amp;gt;/proc/sys/fs/file-max&amp;lt;/code&amp;gt;, change the &amp;lt;code&amp;gt;fs.file-max&amp;lt;/code&amp;gt; value in /&amp;lt;code&amp;gt;etc/sysctl.conf&amp;lt;/code&amp;gt;:&lt;br /&gt;
 fs.file-max = 100000&lt;br /&gt;
And apply it:&lt;br /&gt;
 # sysctl -p&lt;/div&gt;</summary>
		<author><name>DrEdWilliams</name></author>
	</entry>
	<entry>
		<id>https://wiki.williams-net.org/index.php?title=Cluster_Operations&amp;diff=675</id>
		<title>Cluster Operations</title>
		<link rel="alternate" type="text/html" href="https://wiki.williams-net.org/index.php?title=Cluster_Operations&amp;diff=675"/>
		<updated>2021-12-02T22:23:11Z</updated>

		<summary type="html">&lt;p&gt;DrEdWilliams: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Rolling Restart ==&lt;br /&gt;
The OpenSearch cluster is very resilient -- it tries to make sure it has all of its indices appropriately replicated at all times.  It can handle nodes dropping out and being added -- but sometimes we don&#039;t want that.  If nodes are simply restarted (to change settings) or the system is rebooted (for patching), we don&#039;t want to have OpenSearch move all its indices around.  &lt;br /&gt;
&lt;br /&gt;
This process works for a whole cluster restart (not recommended unless absolutely necessary) or individual node restarts.  If individual nodes are being restarted, only do one node at a time to avoid cluster panic should all shards of an index go offline on the nodes that get restarted.  The cluster &#039;&#039;&#039;&#039;&#039;should&#039;&#039;&#039;&#039;&#039; recover, but why stress it unnecessarily.&lt;br /&gt;
&lt;br /&gt;
The process is described in the [https://www.elastic.co/guide/en/elasticsearch/reference/current/restart-cluster.html Elastic documentation], and summarized below.&lt;br /&gt;
&lt;br /&gt;
=== Disable Shard Allocation ===&lt;br /&gt;
When you shut down a data node, the allocation process waits for &amp;lt;code&amp;gt;index.unassigned.node_left.delayed_timeout&amp;lt;/code&amp;gt; (by default, one minute) before starting to replicate the shards on that node to other nodes in the cluster, which can involve a lot of I/O. Since the node is shortly going to be restarted, this I/O is unnecessary. You can avoid racing the clock by disabling allocation of replicas before shutting down data nodes:&lt;br /&gt;
 curl -X PUT &amp;quot;localhost:9200/_cluster/settings?pretty&amp;quot; -H &#039;Content-Type: application/json&#039; -d&#039;&lt;br /&gt;
 {&lt;br /&gt;
   &amp;quot;persistent&amp;quot;: {&lt;br /&gt;
     &amp;quot;cluster.routing.allocation.enable&amp;quot;: &amp;quot;primaries&amp;quot;&lt;br /&gt;
   }&lt;br /&gt;
 }&#039;&lt;br /&gt;
&lt;br /&gt;
=== Flush Cache ===&lt;br /&gt;
This will prevent data loss by flushing any in-process activities to disk:&lt;br /&gt;
 curl -X POST &amp;quot;localhost:9200/_flush/synced?pretty&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== Shut Down/Restart Nodes ===&lt;br /&gt;
Now that things have settled out, we can stop/restart the opensearch services.  Note that a full cluster shutdown should be avoided, since any activity on the cluster as it is going down or coming up could cause errors to the user.  Use the systemd commands to stop/start/restart the nodes:&lt;br /&gt;
 # do this on all nodes&lt;br /&gt;
 sudo systemctl stop opensearch&lt;br /&gt;
  ... do required activity on all nodes ...&lt;br /&gt;
 sudo systemctl start opensearch&lt;br /&gt;
... or ...&lt;br /&gt;
 # restart a single node&lt;br /&gt;
 sudo systemctl restart opensearch&lt;br /&gt;
If it was a complete cluster shutdown, all nodes must rejoin the cluster before proceeding.  In either case, wait until the cluster (or node) achieves a &amp;quot;YELLOW&amp;quot; state before proceeding ... this means that all primary shards are accounted for, but replicas may not be.&lt;br /&gt;
&lt;br /&gt;
=== Enable Shard Allocation ===&lt;br /&gt;
As each node re-starts, it tries to identify which shards it had before.  Unless something has happened to disrupt the node&#039;s data, it will simply reactivate those shards (most likely as replica shards if it is a single-node restart).  To enable the cluster to get back to normal shard management, we remove the block we set above:&lt;br /&gt;
 curl -X PUT &amp;quot;localhost:9200/_cluster/settings?pretty&amp;quot; -H &#039;Content-Type: application/json&#039; -d&#039;&lt;br /&gt;
 {&lt;br /&gt;
   &amp;quot;persistent&amp;quot;: {&lt;br /&gt;
     &amp;quot;cluster.routing.allocation.enable&amp;quot;: null&lt;br /&gt;
   }&lt;br /&gt;
 }&#039;&lt;br /&gt;
&lt;br /&gt;
=== Follow Through ===&lt;br /&gt;
When doing any activity that disrupts the cluster operations enough to cause it to drop into a &amp;quot;YELLOW&amp;quot; or &amp;quot;RED&amp;quot; state, wait until the cluster is &amp;quot;GREEN&amp;quot; again before proceeding.  In the case of a full rolling restart (one node at a time), the cluster should be &amp;quot;GREEN&amp;quot; before proceeding to the next node.&lt;br /&gt;
&lt;br /&gt;
This process (node rolling restart, anyway) is captured in the script &amp;lt;code&amp;gt;node-restart.sh&amp;lt;/code&amp;gt;:&lt;br /&gt;
 #!/bin/bash&lt;br /&gt;
 #&lt;br /&gt;
 # perform a soft restart of a node, minimizing the reindexing that would&lt;br /&gt;
 #  normally occur when a node drops/inserts&lt;br /&gt;
 &lt;br /&gt;
 # set to one of the master nodes&lt;br /&gt;
 MASTER=master-node&lt;br /&gt;
 &lt;br /&gt;
 # replace with either the real admin password or a cert/key combination&lt;br /&gt;
 AUTH=&amp;quot;-u admin:admin&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 # first shut off shard allocation&lt;br /&gt;
 curl -XPUT -H &amp;quot;Content-Type: application/json&amp;quot; &amp;lt;nowiki&amp;gt;https://$MASTER:9200/_cluster/settings&amp;lt;/nowiki&amp;gt; $AUTH -d &#039;&lt;br /&gt;
 {&lt;br /&gt;
   &amp;quot;persistent&amp;quot;: {&lt;br /&gt;
     &amp;quot;cluster.routing.allocation.enable&amp;quot;: &amp;quot;primaries&amp;quot;&lt;br /&gt;
   }&lt;br /&gt;
 }&#039;&lt;br /&gt;
 echo&lt;br /&gt;
 &lt;br /&gt;
 # now flush the cache&lt;br /&gt;
 curl -XPOST &amp;lt;nowiki&amp;gt;https://$MASTER:9200/_flush&amp;lt;/nowiki&amp;gt; $AUTH&lt;br /&gt;
 echo&lt;br /&gt;
 &lt;br /&gt;
 # restart the opensearch process&lt;br /&gt;
 sudo systemctl restart opensearch&lt;br /&gt;
 &lt;br /&gt;
 # re-enable shard allocation&lt;br /&gt;
 curl -XPUT -H &amp;quot;Content-Type: application/json&amp;quot; &amp;lt;nowiki&amp;gt;https://$MASTER:9200/_cluster/settings&amp;lt;/nowiki&amp;gt; $AUTH -d &#039;&lt;br /&gt;
 {&lt;br /&gt;
   &amp;quot;persistent&amp;quot;: {&lt;br /&gt;
     &amp;quot;cluster.routing.allocation.enable&amp;quot;: null&lt;br /&gt;
   }&lt;br /&gt;
 }&#039;&lt;br /&gt;
 echo&lt;br /&gt;
This script is intended to be run on the node being restarted.&lt;br /&gt;
&lt;br /&gt;
== Cluster Upgrade ==&lt;br /&gt;
Assuming there are no other adjustments due to features and/or bugfixes, the basic process for upgrading a cluster is to upgrade one node at a time:&lt;br /&gt;
&lt;br /&gt;
# Expand tarball in the home directory of the &amp;lt;code&amp;gt;opensearch&amp;lt;/code&amp;gt; user&lt;br /&gt;
# Copy the certificates, keys, and CAs from the &amp;lt;code&amp;gt;config&amp;lt;/code&amp;gt; directory of the current version into the new one&lt;br /&gt;
# Copy the &amp;lt;code&amp;gt;opensearch.yml&amp;lt;/code&amp;gt; file from the current version into the new one and make any adjustments&lt;br /&gt;
# Copy the &amp;lt;code&amp;gt;jvm.options.d/heapsize.options&amp;lt;/code&amp;gt; file from the current version into the new one&lt;br /&gt;
# Move the &amp;lt;code&amp;gt;opensearch&amp;lt;/code&amp;gt; link in the home directory from the current version into the new one&lt;br /&gt;
# Reload and restart the opensearch process using the &#039;&#039;&#039;Rolling Restart&#039;&#039;&#039; process described above&lt;br /&gt;
# Wait for the cluster to get to a &amp;quot;GREEN&amp;quot; state before moving to the next node&lt;br /&gt;
&lt;br /&gt;
This assumes that the systemd unit file uses the softlink to access the opensearch executable as described in [[OpenSearch Cluster Installation]].&lt;br /&gt;
&lt;br /&gt;
== Certificate Updates ==&lt;br /&gt;
Given that the standard lifetime for certificates these days is one year, this is  something that will need to be accomplished several times during the lifetime of a cluster.&lt;br /&gt;
&lt;br /&gt;
This process does not require downtime for the cluster, but care must be taken to ensure that the mix of old and new certificates does not cripple the cluster.  This results in up to three complete cluster restarts (using the &#039;&#039;&#039;Rolling Restart&#039;&#039;&#039; method described above), but it does not disrupt the operation of the cluster as long as nothing exceptional happens, and the cluster is allowed to stabilize between each node restart.&lt;br /&gt;
&lt;br /&gt;
=== Create New Certificates ===&lt;br /&gt;
Using the process outlined in [https://wiki.williams-net.org/wiki/OpenSearch_Cluster_Installation#Create_Certificates OpenSearch Cluster Creation], create the required certificates and keys.  If at all possible, keep the DNs on all certificates the same as the ones they are replacing ... it reduces the number of restarts and minimizes the edits of the config files.  It also helps if the node certificate/key files have the same names ... for the same reasons.&lt;br /&gt;
&lt;br /&gt;
Send each node its new certificate/keys and the admin certificate/key -- or make them available for remote retrieval.  If user certificates were created, send them to the system(s) where they will be used.&lt;br /&gt;
&lt;br /&gt;
=== Create CA Bundle ===&lt;br /&gt;
Using a CA bundle with the old and new CAs will allow us to do a gradual transition and avoid downtime.  Fortunately, creating a bundle for the CAs is easy&lt;br /&gt;
 cat &amp;lt;old CA&amp;gt; &amp;lt;new CA&amp;gt; &amp;gt;&amp;gt; rootCAbundle.crt&lt;br /&gt;
Again, if there is currently a bundle in place, use the same name for the bundle file and you&#039;ll save yourself a lot of editing.  If the REST API uses a different CA bundle already that supports other (external) CAs, create a second CA bundle that includes the external CAs, the old internal CA, and the new internal CA.&lt;br /&gt;
&lt;br /&gt;
Send this new CA bundle to all cluster nodes, dashboard instances, and logstash instances.&lt;br /&gt;
&lt;br /&gt;
=== Update CA Files ===&lt;br /&gt;
For each cluster node:&lt;br /&gt;
&lt;br /&gt;
* Copy the new CA bundle in place (in the opensearch &amp;lt;code&amp;gt;config&amp;lt;/code&amp;gt; directory) making sure that permissions allow for read access to the &amp;lt;code&amp;gt;opensearch&amp;lt;/code&amp;gt; user.  &lt;br /&gt;
* DO NOT copy the node certificates yet.  &lt;br /&gt;
* Edit &amp;lt;code&amp;gt;opensearch.yml&amp;lt;/code&amp;gt; if needed:&lt;br /&gt;
** Update the name of the CA to the new CA bundle file (if needed) in both the &amp;lt;code&amp;gt;ssl&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;transport&amp;lt;/code&amp;gt; parameters, using the appropriate bundle for each parameter (see above)&lt;br /&gt;
** Add the DNs (DO NOT replace them yet) for the node and admin certificates if the new DNs are different from what is in the file&lt;br /&gt;
&lt;br /&gt;
* Perform a &#039;&#039;&#039;Rolling Restart&#039;&#039;&#039; of the node, verifying that there are no SSL/certificate errors, and waiting for &amp;quot;GREEN&amp;quot; status before proceeding &lt;br /&gt;
&lt;br /&gt;
Now do the same for all dashboards, logstash instances, and any other clients that use the CA to validate cluster identify:&lt;br /&gt;
&lt;br /&gt;
* Install the CA bundle as appropriate, ensuring that the client has read access to the CA bundle.&lt;br /&gt;
* Update the CA filename in the configuration file (if needed)&lt;br /&gt;
* DO NOT update user certificates at this point&lt;br /&gt;
* Restart the client (if needed) and verify proper operation&lt;br /&gt;
&lt;br /&gt;
=== Update Node Certificates ===&lt;br /&gt;
For each node in the cluster:&lt;br /&gt;
&lt;br /&gt;
* Copy the node certificate and key and the admin certificate and key into the opensearch &amp;lt;code&amp;gt;config&amp;lt;/code&amp;gt; directory, verifying that the &amp;lt;code&amp;gt;opensearch&amp;lt;/code&amp;gt; user has read permissions&lt;br /&gt;
* Edit &amp;lt;code&amp;gt;opensearch.yml&amp;lt;/code&amp;gt; if needed to correct certificate file names&lt;br /&gt;
* DO NOT remove extra DNs from the admin or node sections of the file yet&lt;br /&gt;
* Perform a &#039;&#039;&#039;Rolling Restart&#039;&#039;&#039; of the node, waiting for the cluster to achieve &amp;quot;GREEN&amp;quot; status before going to the next node&lt;br /&gt;
&lt;br /&gt;
=== Update Client Certificates ===&lt;br /&gt;
For each client that uses certificate authentication:&lt;br /&gt;
&lt;br /&gt;
* Copy the client certificate bundle (.p12 file) into place&lt;br /&gt;
* Edit the configuration file if needed to reflect the new file&lt;br /&gt;
* Restart the client (if needed) to activate the new configuration&lt;br /&gt;
&lt;br /&gt;
=== Clean Up ===&lt;br /&gt;
At this point we can remove any old DNs from the &amp;lt;code&amp;gt;opensearch.yml&amp;lt;/code&amp;gt; configurations and in general remove all traces of the old certificates in the cluster nodes and clients.  If a restart is warranted to verify that nothing critical was deleted, that should be done at this time.&lt;br /&gt;
&lt;br /&gt;
It is not necessary to replace the new CA bundle with the CA certificate -- it serves no purpose as the old cert is just along for the ride at this point, and once it reaches its expiration date, will not be used.  If it must be done, use the same process above that was used to install the CA bundle, performing a rolling restart on each node as it is completed.&lt;br /&gt;
&lt;br /&gt;
== Troubleshooting ==&lt;br /&gt;
Setting debug-level logging for opensearch and opensearch-dashboards:&lt;br /&gt;
 # Opensearch&lt;br /&gt;
 log4j2.properties:&lt;br /&gt;
   rootLogger.level = debug&lt;br /&gt;
 &lt;br /&gt;
 # Opensearch Dashboards&lt;br /&gt;
 opensearch_dashboards.yml:&lt;br /&gt;
   logging.verbose: true&lt;/div&gt;</summary>
		<author><name>DrEdWilliams</name></author>
	</entry>
	<entry>
		<id>https://wiki.williams-net.org/index.php?title=OpenSearch_Cluster_Installation&amp;diff=674</id>
		<title>OpenSearch Cluster Installation</title>
		<link rel="alternate" type="text/html" href="https://wiki.williams-net.org/index.php?title=OpenSearch_Cluster_Installation&amp;diff=674"/>
		<updated>2021-11-30T22:18:01Z</updated>

		<summary type="html">&lt;p&gt;DrEdWilliams: /* Install OpenSearch Dashboards */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;These instructions describe the creation of a multi-node OpenSearch cluster using the tarball distribution.  The configuration instructions below assume a cluster with the following components:&lt;br /&gt;
&lt;br /&gt;
* Multiple master/ingest nodes&lt;br /&gt;
* Multiple hot data nodes&lt;br /&gt;
* Multiple cold data nodes&lt;br /&gt;
&lt;br /&gt;
The instructions should be adaptable to any multi-node configuration, and even to a uniform node configuration (i.e. three master/ingress/data nodes) -- though that simple configuration does not need the multiple steps required for the more complex deployment.&lt;br /&gt;
&lt;br /&gt;
Read through the entire document before doing anything, as there is a specific order in which things must be done for a successful installation.&lt;br /&gt;
&lt;br /&gt;
== Node Preparation ==&lt;br /&gt;
Each node to be used in the cluster must be prepared to support the OpenSearch installation.&lt;br /&gt;
&lt;br /&gt;
=== Create Opensearch User ===&lt;br /&gt;
Debian/Ubuntu:&lt;br /&gt;
 sudo adduser --system -uid 968 --shell /bin/bash --gecos &#039;OpenSearch User&#039;  --group  --disabled-password --home /opt/opensearch opensearch&lt;br /&gt;
Fedora/RHEL:&lt;br /&gt;
 sudo adduser --system --uid 968 --shell /bin/bash --home-dir /opt/opensearch -m opensearch&lt;br /&gt;
Then add your normal user to the group:&lt;br /&gt;
 sudo usermod -aG opensearch ewilliam&lt;br /&gt;
&lt;br /&gt;
=== Set vm.max_map_count ===&lt;br /&gt;
Create &amp;lt;code&amp;gt;/etc/sysctl.d/vm.maxmap_count.conf&amp;lt;/code&amp;gt; (as root) and add the following line:&lt;br /&gt;
 vm.max_map_count=262144&lt;br /&gt;
Run the following command as root to load the new configuration:&lt;br /&gt;
 sysctl --system&lt;br /&gt;
&lt;br /&gt;
=== Systemd Unit File ===&lt;br /&gt;
One of the big things missing from the tarball distribution is a systemd unit file.  Fortunately, it isn&#039;t difficult to create a simple one that will work.&lt;br /&gt;
&lt;br /&gt;
Create a file &amp;lt;code&amp;gt;/etc/systemd/system/opensearch.service&amp;lt;/code&amp;gt; with the following contents:&lt;br /&gt;
 [Unit]&lt;br /&gt;
 Description=OpenSearch&lt;br /&gt;
 Documentation=&amp;lt;nowiki&amp;gt;https://opensearch.org/docs/&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 Wants=network-online.target&lt;br /&gt;
 After=network-online.target&lt;br /&gt;
 &lt;br /&gt;
 [Service]&lt;br /&gt;
 Type=exec&lt;br /&gt;
 RuntimeDirectory=opensearch&lt;br /&gt;
 PrivateTmp=true&lt;br /&gt;
 Environment=OPENSEARCH_HOME=/opt/opensearch/opensearch&lt;br /&gt;
 Environment=OPENSEARCH_PATH_CONF=/opt/opensearch/opensearch/config&lt;br /&gt;
 Environment=PID_DIR=/opt/opensearch/opensearch&lt;br /&gt;
 Environment=OPENSEARCH_SD_NOTIFY=true&lt;br /&gt;
 EnvironmentFile=-/opt/opensearch/opensearch/opensearch.env&lt;br /&gt;
 &lt;br /&gt;
 WorkingDirectory=/opt/opensearch/opensearch&lt;br /&gt;
 &lt;br /&gt;
 User=opensearch&lt;br /&gt;
 Group=opensearch&lt;br /&gt;
 &lt;br /&gt;
 ExecStart=/opt/opensearch/opensearch/bin/opensearch -p ${PID_DIR}/opensearch.pid --quiet&lt;br /&gt;
 &lt;br /&gt;
 # StandardOutput is configured to redirect to journalctl since&lt;br /&gt;
 # some error messages may be logged in standard output before&lt;br /&gt;
 # elasticsearch logging system is initialized. Elasticsearch&lt;br /&gt;
 # stores its logs in /var/log/elasticsearch and does not use&lt;br /&gt;
 # journalctl by default. If you also want to enable journalctl&lt;br /&gt;
 # logging, you can simply remove the &amp;quot;quiet&amp;quot; option from ExecStart.&lt;br /&gt;
 StandardOutput=journal&lt;br /&gt;
 StandardError=inherit&lt;br /&gt;
 &lt;br /&gt;
 # Specifies the maximum file descriptor number that can be opened by this process&lt;br /&gt;
 LimitNOFILE=65535&lt;br /&gt;
 &lt;br /&gt;
 # Specifies the maximum number of processes&lt;br /&gt;
 LimitNPROC=4096&lt;br /&gt;
 &lt;br /&gt;
 # Specifies the maximum size of virtual memory&lt;br /&gt;
 LimitAS=infinity&lt;br /&gt;
 &lt;br /&gt;
 # Specifies the maximum file size&lt;br /&gt;
 LimitFSIZE=infinity&lt;br /&gt;
 &lt;br /&gt;
 # Disable timeout logic and wait until process is stopped&lt;br /&gt;
 TimeoutStopSec=0&lt;br /&gt;
 &lt;br /&gt;
 # SIGTERM signal is used to stop the Java process&lt;br /&gt;
 KillSignal=SIGTERM&lt;br /&gt;
 &lt;br /&gt;
 # Send the signal only to the JVM rather than its control group&lt;br /&gt;
 KillMode=process&lt;br /&gt;
 &lt;br /&gt;
 # Java process is never killed&lt;br /&gt;
 SendSIGKILL=no&lt;br /&gt;
 &lt;br /&gt;
 # When a JVM receives a SIGTERM signal it exits with code 143&lt;br /&gt;
 SuccessExitStatus=143&lt;br /&gt;
 &lt;br /&gt;
 # Allow a slow startup before the systemd notifier module kicks in to extend the timeout&lt;br /&gt;
 TimeoutStartSec=75&lt;br /&gt;
 &lt;br /&gt;
 [Install]&lt;br /&gt;
 WantedBy=multi-user.target&lt;br /&gt;
&lt;br /&gt;
== Create Certificates ==&lt;br /&gt;
There are three types of certificates used in OpenSearch:&lt;br /&gt;
&lt;br /&gt;
* CA certificate - one for the whole cluster to validate everything else&lt;br /&gt;
* Node certificate/key - identifies the node for internal cluster communications (transport layer) and data ingest (http layer)&lt;br /&gt;
** the CN must be the FQDN of the node&lt;br /&gt;
** even though OpenSearch doesn&#039;t seem to use them at this point, there should be SANs for the full FQDN, the short hostname, and the node&#039;s IP address&lt;br /&gt;
* User certificate/key - identifies a specific OpenSearch user&lt;br /&gt;
** the CN is a username in OpenSearch (explicit or implicit)&lt;br /&gt;
** username is used to determine roles/privileges in the cluster&lt;br /&gt;
** Need at least one cert for admin authentication&lt;br /&gt;
&lt;br /&gt;
Node and User certificates must all be signed by the cluster CA, and &#039;&#039;&#039;all keys must be in PKCS8 format&#039;&#039;&#039;.  If user certificates are to be used for authentication by logstash, they must be imported (along with the key and CA) into a PKCS12 (.p12) keystore.  The OpenSearch documentation has a good piece on [https://opensearch.org/docs/latest/security-plugin/configuration/generate-certificates/ how to create certificates].&lt;br /&gt;
&lt;br /&gt;
In summary, create the following certificates/keys&lt;br /&gt;
&lt;br /&gt;
# CA certificate/key&lt;br /&gt;
# For each cluster node:&lt;br /&gt;
#* &amp;lt;node&amp;gt;.crt&lt;br /&gt;
#* &amp;lt;node&amp;gt;-pkcs8.key&lt;br /&gt;
# For each user:&lt;br /&gt;
#* &amp;lt;user&amp;gt;.crt&lt;br /&gt;
#* &amp;lt;user&amp;gt;-pkcs8.key&lt;br /&gt;
#* &amp;lt;user&amp;gt;.p12&lt;br /&gt;
&lt;br /&gt;
All these should be created and available for the configuration of each cluster node below.&lt;br /&gt;
&lt;br /&gt;
== Install OpenSearch Tarball ==&lt;br /&gt;
The OpenSearch tarball must be installed on each node in the cluster; there is no difference at this point between the installations on the different types of nodes.  Assuming the deployment will use the &amp;lt;code&amp;gt;opensearch&amp;lt;/code&amp;gt; user created above ... change to the &amp;lt;code&amp;gt;opensearch&amp;lt;/code&amp;gt; user (from root):&lt;br /&gt;
 su - opensearch&lt;br /&gt;
 cd ~&lt;br /&gt;
Run the following commands as user &amp;lt;code&amp;gt;opensearch&amp;lt;/code&amp;gt; (from the opensearch home directory &amp;lt;code&amp;gt;/opt/opensearch&amp;lt;/code&amp;gt;):&lt;br /&gt;
 wget https://artifacts.opensearch.org/releases/bundle/opensearch/1.2.0/opensearch-1.2.0-linux-x64.tar.gz&lt;br /&gt;
 tar -xvzf opensearch-1.2.0-linux-x64.tar.gz&lt;br /&gt;
== Configure OpenSearch ==&lt;br /&gt;
Configuration varies depending on the type of node, but these are the places that need to be touched.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;jvm.options&amp;lt;/code&amp;gt; ===&lt;br /&gt;
Set the heap size.  Common practice is that the heap should be between 4GB and half the available memory, but no higher than 32GB.  A minimum configuration might be (assuming the hot data nodes have 32GB installed RAM:&lt;br /&gt;
&lt;br /&gt;
* 4G for master and cold data nodes&lt;br /&gt;
* 16G for hot data nodes&lt;br /&gt;
&lt;br /&gt;
This must be done individually for each node -- create the file &amp;lt;code&amp;gt;config/jvm.options.d/heapsize.options&amp;lt;/code&amp;gt; with the heap size options:&lt;br /&gt;
 -Xms4g&lt;br /&gt;
 -Xmx4g&lt;br /&gt;
... with, of course, the proper heap size for that node.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;opensearch.yml&amp;lt;/code&amp;gt; ===&lt;br /&gt;
While the OpenSearch software can be rather forgiving for low-security environments, if you turn on full hostname verification, it is rather strict.  The biggest thing to remember is that &#039;&#039;&#039;SAN entries in the node certificates aren&#039;t always respected.&#039;&#039;&#039;  What this boils down to is that if full verification is turned on, you cannot use IP addresses in the &amp;lt;code&amp;gt;opensearch.yml&amp;lt;/code&amp;gt; (or any other configuration file such as the logstash pipelines).&lt;br /&gt;
&lt;br /&gt;
Each node will have a unique version of opensearch.yml due to certificate file names, the role(s) for the node, and the temperature (for data nodes).  The significant parameters in the opensearch.yml file are:&lt;br /&gt;
* &amp;lt;code&amp;gt;cluster.name&amp;lt;/code&amp;gt; - must be identical in all nodes&lt;br /&gt;
* &amp;lt;code&amp;gt;node.name&amp;lt;/code&amp;gt;- can be the hostname, but doesn&#039;t have to be (must be unique)&lt;br /&gt;
* &amp;lt;code&amp;gt;path.data&amp;lt;/code&amp;gt; - data nodes only -- must be unique to the node (i.e if using shared storage, each node must have its own directory on the shared volume)&lt;br /&gt;
* &amp;lt;code&amp;gt;path.logs&amp;lt;/code&amp;gt; - must be unique to the node (same as above)&lt;br /&gt;
* &amp;lt;code&amp;gt;network.host&amp;lt;/code&amp;gt; -- host&#039;s FQDN where all traffic will be received&lt;br /&gt;
**Can be a single hostname or an array of hostnames in &amp;lt;code&amp;gt;[&amp;quot;name&amp;quot;, &amp;quot;name&amp;quot;]&amp;lt;/code&amp;gt; format&lt;br /&gt;
**If you are doing transport-level host verification this CANNOT be an IP -- OpenSearch can&#039;t handle the SANs in the certificates needed to make it work&lt;br /&gt;
* &amp;lt;code&amp;gt;http.port&amp;lt;/code&amp;gt; -- leave it as the default (&amp;lt;code&amp;gt;9200&amp;lt;/code&amp;gt;) but uncomment it to lock it in&lt;br /&gt;
* &amp;lt;code&amp;gt;discovery.seed_hosts&amp;lt;/code&amp;gt; -- FQDN for all the masters (same for all nodes) -- only used for cluster bootstrap&lt;br /&gt;
* &amp;lt;code&amp;gt;cluster.initial_master_nodes&amp;lt;/code&amp;gt; -- put the master node names here (not the hostnames) -- same for all nodes&lt;br /&gt;
* &amp;lt;code&amp;gt;node.[master|data|ingest|remote]&amp;lt;/code&amp;gt; - set the type of the node (specify all four)&lt;br /&gt;
* &amp;lt;code&amp;gt;node.attr.temp&amp;lt;/code&amp;gt; - (data nodes only) defines data storage tiers (&amp;lt;code&amp;gt;hot&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;warm&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;cold&amp;lt;/code&amp;gt;)&lt;br /&gt;
The stock configuration file has most of these specified -- edit the file to fit the configuration of the node.&lt;br /&gt;
&lt;br /&gt;
The security configuration must be added next.  Since we are not using the demo security as our template, all the relevant entries must be added now.  Copy this block into the end of the stock opensearch.yml, editing as needed to provide the relevant certificate file names:&lt;br /&gt;
 node.master: true&lt;br /&gt;
 node.ingest: true&lt;br /&gt;
 node.data: false&lt;br /&gt;
 #node.remote: false&lt;br /&gt;
 &lt;br /&gt;
 #node.attr.temp: hot&lt;br /&gt;
 &lt;br /&gt;
 ######## Start OpenSearch Security Configuration ########&lt;br /&gt;
 plugins.security.ssl.transport.pemcert_filepath: &amp;lt;node&amp;gt;.crt&lt;br /&gt;
 plugins.security.ssl.transport.pemkey_filepath: &amp;lt;node&amp;gt;-pkcs8.key&lt;br /&gt;
 plugins.security.ssl.transport.pemtrustedcas_filepath: &amp;lt;CAcert&amp;gt;&lt;br /&gt;
 plugins.security.ssl.transport.enforce_hostname_verification: true&lt;br /&gt;
 &lt;br /&gt;
 plugins.security.ssl.http.enabled: true&lt;br /&gt;
 plugins.security.ssl.http.pemcert_filepath: &amp;lt;node&amp;gt;.crt&lt;br /&gt;
 plugins.security.ssl.http.pemkey_filepath: &amp;lt;node&amp;gt;-pkcs8.key&lt;br /&gt;
 plugins.security.ssl.http.pemtrustedcas_filepath: &amp;lt;CAcert&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 plugins.security.allow_unsafe_democertificates: false&lt;br /&gt;
 plugins.security.allow_default_init_securityindex: true&lt;br /&gt;
 &lt;br /&gt;
 # at least one cert -- must be an EXACT copy of the DN for the certificates to be used for admin auth&lt;br /&gt;
 plugins.security.authcz.admin_dn:&lt;br /&gt;
   - CN=Admin,O=OpenSearch,C=US&lt;br /&gt;
 &lt;br /&gt;
 # these must be EXACT copies of the DN for the node certificates&lt;br /&gt;
 plugins.security.nodes_dn:&lt;br /&gt;
   - CN=master-1.opensearch.localnet,O=OpenSearch,C=US&lt;br /&gt;
   - CN=data-hot-1.opensearch.localnet,O=OpenSearch,C=US&lt;br /&gt;
 &lt;br /&gt;
 # this is all boiler plate ... no modifications needed&lt;br /&gt;
 plugins.security.audit.type: internal_opensearch&lt;br /&gt;
 plugins.security.enable_snapshot_restore_privilege: true&lt;br /&gt;
 plugins.security.check_snapshot_restore_write_privileges: true&lt;br /&gt;
 plugins.security.restapi.roles_enabled: [&amp;quot;all_access&amp;quot;, &amp;quot;security_rest_api_access&amp;quot;]&lt;br /&gt;
 plugins.security.system_indices.enabled: true&lt;br /&gt;
 # this next bit should ALL be on one line ...&lt;br /&gt;
 plugins.security.system_indices.indices: [&amp;quot;.opendistro-alerting-config&amp;quot;, &amp;quot;.opendistro-alerting-alert*&amp;quot;, &amp;quot;.opendistro-anomaly-results*&amp;quot;, &amp;quot;.opendistro-anomaly-detector*&amp;quot;, &amp;quot;.opendistro-anomaly-checkpoints&amp;quot;, &amp;quot;.opendistro-anomaly-detection-state&amp;quot;, &amp;quot;.opendistro-reports-*&amp;quot;, &amp;quot;.opendistro-notifications-*&amp;quot;, &amp;quot;.opendistro-notebooks&amp;quot;, &amp;quot;.opendistro-asynchronous-search-response*&amp;quot;, &amp;quot;.replication-metadata-store&amp;quot;]&lt;br /&gt;
 &lt;br /&gt;
 node.max_local_storage_nodes: 3&lt;br /&gt;
 &lt;br /&gt;
 ######## End OpenSearch Security Configuration ########&lt;br /&gt;
Note that there are two sections where the DNs from the certificates must be provided to enable admin authentication for security configuration, and for validating the nodes that will be part of the cluster.  You can easily show the DNs for your certificates using this command:&lt;br /&gt;
 openssl x509 -subject -nameopt RFC2253 -noout -in &amp;lt;cert file name&amp;gt;&lt;br /&gt;
The DN for the admin cert and the DNs for the node certs go in separate sections as shown above.  Add all the cluster nodes into the nodes_dn section -- this must be the same for all nodes or they will not be able to communicate.&lt;br /&gt;
&lt;br /&gt;
=== Certificates ===&lt;br /&gt;
Copy the following certificates/keys that were created previously into the config directory of each node:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;CAcert&amp;gt;&lt;br /&gt;
* &amp;lt;node&amp;gt;.crt&lt;br /&gt;
* &amp;lt;node&amp;gt;-pkcs8.key&lt;br /&gt;
* admin.crt&lt;br /&gt;
* admin-pkcs8.crt&lt;br /&gt;
Verify that the &amp;lt;code&amp;gt;opensearch&amp;lt;/code&amp;gt; user is able to at least read all of the certs/keys, or the cluster will not function.&lt;br /&gt;
&lt;br /&gt;
=== Security Plugin Configuration ===&lt;br /&gt;
While the security configuration files exist on all the nodes in the cluster, they are only used once and only by the node where the security initialization is performed.  With that in mine, pick one node (the first master node will do nicely) to edit the configuration files as needed.  There are many things that can be done with these files, but two items in particular should be addressed.  The files are located in the &amp;lt;code&amp;gt;plugins/opensearch-security/securityconfig&amp;lt;/code&amp;gt; directory in the opensearch distribution.&lt;br /&gt;
&lt;br /&gt;
==== Authentication ====&lt;br /&gt;
&amp;lt;code&amp;gt;config.yml&amp;lt;/code&amp;gt; is where the authentication options are established.  This will need to be configured to support your authentication options.  The OpenSearch documentation describes the different options [https://opensearch.org/docs/latest/security-plugin/configuration/configuration/ here].&lt;br /&gt;
&lt;br /&gt;
The default configuration supports basic username/password authentication, but if you wish to use certificate authentication for API clients or ingest pipelines using logstash, you need to enable both &#039;&#039;&#039;http&#039;&#039;&#039; and &#039;&#039;&#039;transport&#039;&#039;&#039; under &amp;lt;code&amp;gt;clientcert_auth_domain&amp;lt;/code&amp;gt;.  Proxy authentication and OpenID Connect authentication is possible as well ... see the documentation.&lt;br /&gt;
&lt;br /&gt;
==== Admin user password ====&lt;br /&gt;
The default password for the admin user is well-known, and should be changed for a production environment.  The OpenSearch documentation provides instructions on how to [https://opensearch.org/docs/latest/security-plugin/configuration/yaml/#internal_usersyml generate passwords] for the &amp;lt;code&amp;gt;internal_users.yml&amp;lt;/code&amp;gt; file.  Note that &#039;&#039;&#039;the admin password cannot be set through the dashboard or the API&#039;&#039;&#039; -- it must be set in this file, and then (re)loaded to take effect.&lt;br /&gt;
&lt;br /&gt;
=== Security Plugin Initialization ===&lt;br /&gt;
Once all security configuration files are finished, they must be loaded into the OpenSearch cluster.  This can only be done once enough of the cluster is up to provide a master node and at least one data node, as the security configuration is loaded into an index in the cluster.  See the instructions below for specific sequencing.  This command will initialize the security plugin:&lt;br /&gt;
 plugins/opensearch-security/tools/securityadmin.sh \&lt;br /&gt;
     -cacert config/&amp;lt;CA cert&amp;gt; -cert config/admin.crt -key config/admin-pkcs8.key \&lt;br /&gt;
     -cd plugins/opensearch-security/securityconfig/ -host master-1.opensearch.localnet -icl -nhnv&lt;br /&gt;
... but again -- wait to do this until the right time below.&lt;br /&gt;
&lt;br /&gt;
=== Starting The Node ===&lt;br /&gt;
Subject to the constraints described in the next section, the only thing left is to start the opensearch service:&lt;br /&gt;
 sudo systemctl enable --now opensearch&lt;br /&gt;
Again, this must be done on each node in the correct sequence ... see below.&lt;br /&gt;
&lt;br /&gt;
== Cluster Bootstrapping ==&lt;br /&gt;
Starting up a multi-node cluster is a bit tricky:&lt;br /&gt;
&lt;br /&gt;
* Master-only nodes have no data&lt;br /&gt;
* Data-only nodes aren&#039;t master eligible&lt;br /&gt;
* Cluster initialization requires indexes to be available&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note that this process does NOT use the demo configuration -- put all the security plugin items in the &amp;lt;code&amp;gt;opensearch.yml&amp;lt;/code&amp;gt; file from the beginning&#039;&#039;&#039;.  This will cause the &amp;lt;code&amp;gt;opensearch-tar-install.sh&amp;lt;/code&amp;gt; script to skip the security initialization -- this is intentional.&lt;br /&gt;
&lt;br /&gt;
What this means is that you have to stand up multiple nodes before anything starts working ... the process should be:&lt;br /&gt;
&lt;br /&gt;
# Install and start what will be the &#039;primary&#039; master ... reference point for cluster startup operations&lt;br /&gt;
# Install and start one of the &#039;hot&#039; data nodes&lt;br /&gt;
# Run the &#039;securityadmin.sh&#039; script (using the command above) to initialize the security subsystem&lt;br /&gt;
# Install/start the other master nodes so that there is resiliency as nodes go up and down&lt;br /&gt;
# install/start the other data nodes to allow replication of the system indexes.&lt;br /&gt;
&lt;br /&gt;
== Install OpenSearch Dashboards ==&lt;br /&gt;
Finally, install the OpenSearch Dashboards using the tarball as well.&lt;br /&gt;
&lt;br /&gt;
Run the following commands as opensearch user:&lt;br /&gt;
 wget [https://artifacts.opensearch.org/releases/bundle/opensearch-dashboards/1.1.0/opensearch-dashboards-1.1.0-linux-x64.tar.gz https://artifacts.opensearch.org/releases/bundle/opensearch-dashboards/1.2.0/opensearch-dashboards-1.2.0-linux-x64.tar.gz]&lt;br /&gt;
 tar -zxf opensearch-dashboards-1.2.0-linux-x64.tar.gz&lt;br /&gt;
&lt;br /&gt;
Configure the &amp;lt;code&amp;gt;opensearch-dashboards.yml&amp;lt;/code&amp;gt; file as needed for your situation.&lt;br /&gt;
&lt;br /&gt;
Create file &amp;lt;code&amp;gt;/etc/systemd/system/opensearch-dashboards.service&amp;lt;/code&amp;gt; (as root) with the following contents:&lt;br /&gt;
 [Unit]&lt;br /&gt;
 Description=OpenSearch-Dasboards&lt;br /&gt;
 &lt;br /&gt;
 [Service]&lt;br /&gt;
 Type=simple&lt;br /&gt;
 User=opensearch&lt;br /&gt;
 Group=opensearch&lt;br /&gt;
 ExecStart=/opt/opensearch/opensearch-dashboards-1.2.0/bin/opensearch-dashboards&lt;br /&gt;
 Restart=always&lt;br /&gt;
 WorkingDirectory=/opt/opensearch/opensearch-dashboards-1.2.0&lt;br /&gt;
 &lt;br /&gt;
 [Install]&lt;br /&gt;
 WantedBy=multi-user.target&lt;br /&gt;
Run the following commands as root:&lt;br /&gt;
 systemctl daemon-reload&lt;br /&gt;
 systemctl start opensearch-dashboards.service &lt;br /&gt;
 systemctl enable opensearch-dashboards.service&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
* https://cryptopoolparty.com/blog/cardano-stake-pool-monitoring-ofo-stack/&lt;br /&gt;
** Describes how to use OpenSearch to monitor another application -- but portions were used to create this document&lt;br /&gt;
*https://github.com/opensearch-project/dashboards-reports/releases/tag/chromium-1.12.0.0&lt;br /&gt;
**download for headless chrome for generating PDF/PNG reports&lt;/div&gt;</summary>
		<author><name>DrEdWilliams</name></author>
	</entry>
	<entry>
		<id>https://wiki.williams-net.org/index.php?title=OpenSearch_Cluster_Installation&amp;diff=673</id>
		<title>OpenSearch Cluster Installation</title>
		<link rel="alternate" type="text/html" href="https://wiki.williams-net.org/index.php?title=OpenSearch_Cluster_Installation&amp;diff=673"/>
		<updated>2021-11-30T20:32:32Z</updated>

		<summary type="html">&lt;p&gt;DrEdWilliams: /* Systemd Unit File */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;These instructions describe the creation of a multi-node OpenSearch cluster using the tarball distribution.  The configuration instructions below assume a cluster with the following components:&lt;br /&gt;
&lt;br /&gt;
* Multiple master/ingest nodes&lt;br /&gt;
* Multiple hot data nodes&lt;br /&gt;
* Multiple cold data nodes&lt;br /&gt;
&lt;br /&gt;
The instructions should be adaptable to any multi-node configuration, and even to a uniform node configuration (i.e. three master/ingress/data nodes) -- though that simple configuration does not need the multiple steps required for the more complex deployment.&lt;br /&gt;
&lt;br /&gt;
Read through the entire document before doing anything, as there is a specific order in which things must be done for a successful installation.&lt;br /&gt;
&lt;br /&gt;
== Node Preparation ==&lt;br /&gt;
Each node to be used in the cluster must be prepared to support the OpenSearch installation.&lt;br /&gt;
&lt;br /&gt;
=== Create Opensearch User ===&lt;br /&gt;
Debian/Ubuntu:&lt;br /&gt;
 sudo adduser --system -uid 968 --shell /bin/bash --gecos &#039;OpenSearch User&#039;  --group  --disabled-password --home /opt/opensearch opensearch&lt;br /&gt;
Fedora/RHEL:&lt;br /&gt;
 sudo adduser --system --uid 968 --shell /bin/bash --home-dir /opt/opensearch -m opensearch&lt;br /&gt;
Then add your normal user to the group:&lt;br /&gt;
 sudo usermod -aG opensearch ewilliam&lt;br /&gt;
&lt;br /&gt;
=== Set vm.max_map_count ===&lt;br /&gt;
Create &amp;lt;code&amp;gt;/etc/sysctl.d/vm.maxmap_count.conf&amp;lt;/code&amp;gt; (as root) and add the following line:&lt;br /&gt;
 vm.max_map_count=262144&lt;br /&gt;
Run the following command as root to load the new configuration:&lt;br /&gt;
 sysctl --system&lt;br /&gt;
&lt;br /&gt;
=== Systemd Unit File ===&lt;br /&gt;
One of the big things missing from the tarball distribution is a systemd unit file.  Fortunately, it isn&#039;t difficult to create a simple one that will work.&lt;br /&gt;
&lt;br /&gt;
Create a file &amp;lt;code&amp;gt;/etc/systemd/system/opensearch.service&amp;lt;/code&amp;gt; with the following contents:&lt;br /&gt;
 [Unit]&lt;br /&gt;
 Description=OpenSearch&lt;br /&gt;
 Documentation=&amp;lt;nowiki&amp;gt;https://opensearch.org/docs/&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 Wants=network-online.target&lt;br /&gt;
 After=network-online.target&lt;br /&gt;
 &lt;br /&gt;
 [Service]&lt;br /&gt;
 Type=exec&lt;br /&gt;
 RuntimeDirectory=opensearch&lt;br /&gt;
 PrivateTmp=true&lt;br /&gt;
 Environment=OPENSEARCH_HOME=/opt/opensearch/opensearch&lt;br /&gt;
 Environment=OPENSEARCH_PATH_CONF=/opt/opensearch/opensearch/config&lt;br /&gt;
 Environment=PID_DIR=/opt/opensearch/opensearch&lt;br /&gt;
 Environment=OPENSEARCH_SD_NOTIFY=true&lt;br /&gt;
 EnvironmentFile=-/opt/opensearch/opensearch/opensearch.env&lt;br /&gt;
 &lt;br /&gt;
 WorkingDirectory=/opt/opensearch/opensearch&lt;br /&gt;
 &lt;br /&gt;
 User=opensearch&lt;br /&gt;
 Group=opensearch&lt;br /&gt;
 &lt;br /&gt;
 ExecStart=/opt/opensearch/opensearch/bin/opensearch -p ${PID_DIR}/opensearch.pid --quiet&lt;br /&gt;
 &lt;br /&gt;
 # StandardOutput is configured to redirect to journalctl since&lt;br /&gt;
 # some error messages may be logged in standard output before&lt;br /&gt;
 # elasticsearch logging system is initialized. Elasticsearch&lt;br /&gt;
 # stores its logs in /var/log/elasticsearch and does not use&lt;br /&gt;
 # journalctl by default. If you also want to enable journalctl&lt;br /&gt;
 # logging, you can simply remove the &amp;quot;quiet&amp;quot; option from ExecStart.&lt;br /&gt;
 StandardOutput=journal&lt;br /&gt;
 StandardError=inherit&lt;br /&gt;
 &lt;br /&gt;
 # Specifies the maximum file descriptor number that can be opened by this process&lt;br /&gt;
 LimitNOFILE=65535&lt;br /&gt;
 &lt;br /&gt;
 # Specifies the maximum number of processes&lt;br /&gt;
 LimitNPROC=4096&lt;br /&gt;
 &lt;br /&gt;
 # Specifies the maximum size of virtual memory&lt;br /&gt;
 LimitAS=infinity&lt;br /&gt;
 &lt;br /&gt;
 # Specifies the maximum file size&lt;br /&gt;
 LimitFSIZE=infinity&lt;br /&gt;
 &lt;br /&gt;
 # Disable timeout logic and wait until process is stopped&lt;br /&gt;
 TimeoutStopSec=0&lt;br /&gt;
 &lt;br /&gt;
 # SIGTERM signal is used to stop the Java process&lt;br /&gt;
 KillSignal=SIGTERM&lt;br /&gt;
 &lt;br /&gt;
 # Send the signal only to the JVM rather than its control group&lt;br /&gt;
 KillMode=process&lt;br /&gt;
 &lt;br /&gt;
 # Java process is never killed&lt;br /&gt;
 SendSIGKILL=no&lt;br /&gt;
 &lt;br /&gt;
 # When a JVM receives a SIGTERM signal it exits with code 143&lt;br /&gt;
 SuccessExitStatus=143&lt;br /&gt;
 &lt;br /&gt;
 # Allow a slow startup before the systemd notifier module kicks in to extend the timeout&lt;br /&gt;
 TimeoutStartSec=75&lt;br /&gt;
 &lt;br /&gt;
 [Install]&lt;br /&gt;
 WantedBy=multi-user.target&lt;br /&gt;
&lt;br /&gt;
== Create Certificates ==&lt;br /&gt;
There are three types of certificates used in OpenSearch:&lt;br /&gt;
&lt;br /&gt;
* CA certificate - one for the whole cluster to validate everything else&lt;br /&gt;
* Node certificate/key - identifies the node for internal cluster communications (transport layer) and data ingest (http layer)&lt;br /&gt;
** the CN must be the FQDN of the node&lt;br /&gt;
** even though OpenSearch doesn&#039;t seem to use them at this point, there should be SANs for the full FQDN, the short hostname, and the node&#039;s IP address&lt;br /&gt;
* User certificate/key - identifies a specific OpenSearch user&lt;br /&gt;
** the CN is a username in OpenSearch (explicit or implicit)&lt;br /&gt;
** username is used to determine roles/privileges in the cluster&lt;br /&gt;
** Need at least one cert for admin authentication&lt;br /&gt;
&lt;br /&gt;
Node and User certificates must all be signed by the cluster CA, and &#039;&#039;&#039;all keys must be in PKCS8 format&#039;&#039;&#039;.  If user certificates are to be used for authentication by logstash, they must be imported (along with the key and CA) into a PKCS12 (.p12) keystore.  The OpenSearch documentation has a good piece on [https://opensearch.org/docs/latest/security-plugin/configuration/generate-certificates/ how to create certificates].&lt;br /&gt;
&lt;br /&gt;
In summary, create the following certificates/keys&lt;br /&gt;
&lt;br /&gt;
# CA certificate/key&lt;br /&gt;
# For each cluster node:&lt;br /&gt;
#* &amp;lt;node&amp;gt;.crt&lt;br /&gt;
#* &amp;lt;node&amp;gt;-pkcs8.key&lt;br /&gt;
# For each user:&lt;br /&gt;
#* &amp;lt;user&amp;gt;.crt&lt;br /&gt;
#* &amp;lt;user&amp;gt;-pkcs8.key&lt;br /&gt;
#* &amp;lt;user&amp;gt;.p12&lt;br /&gt;
&lt;br /&gt;
All these should be created and available for the configuration of each cluster node below.&lt;br /&gt;
&lt;br /&gt;
== Install OpenSearch Tarball ==&lt;br /&gt;
The OpenSearch tarball must be installed on each node in the cluster; there is no difference at this point between the installations on the different types of nodes.  Assuming the deployment will use the &amp;lt;code&amp;gt;opensearch&amp;lt;/code&amp;gt; user created above ... change to the &amp;lt;code&amp;gt;opensearch&amp;lt;/code&amp;gt; user (from root):&lt;br /&gt;
 su - opensearch&lt;br /&gt;
 cd ~&lt;br /&gt;
Run the following commands as user &amp;lt;code&amp;gt;opensearch&amp;lt;/code&amp;gt; (from the opensearch home directory &amp;lt;code&amp;gt;/opt/opensearch&amp;lt;/code&amp;gt;):&lt;br /&gt;
 wget https://artifacts.opensearch.org/releases/bundle/opensearch/1.2.0/opensearch-1.2.0-linux-x64.tar.gz&lt;br /&gt;
 tar -xvzf opensearch-1.2.0-linux-x64.tar.gz&lt;br /&gt;
== Configure OpenSearch ==&lt;br /&gt;
Configuration varies depending on the type of node, but these are the places that need to be touched.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;jvm.options&amp;lt;/code&amp;gt; ===&lt;br /&gt;
Set the heap size.  Common practice is that the heap should be between 4GB and half the available memory, but no higher than 32GB.  A minimum configuration might be (assuming the hot data nodes have 32GB installed RAM:&lt;br /&gt;
&lt;br /&gt;
* 4G for master and cold data nodes&lt;br /&gt;
* 16G for hot data nodes&lt;br /&gt;
&lt;br /&gt;
This must be done individually for each node -- create the file &amp;lt;code&amp;gt;config/jvm.options.d/heapsize.options&amp;lt;/code&amp;gt; with the heap size options:&lt;br /&gt;
 -Xms4g&lt;br /&gt;
 -Xmx4g&lt;br /&gt;
... with, of course, the proper heap size for that node.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;opensearch.yml&amp;lt;/code&amp;gt; ===&lt;br /&gt;
While the OpenSearch software can be rather forgiving for low-security environments, if you turn on full hostname verification, it is rather strict.  The biggest thing to remember is that &#039;&#039;&#039;SAN entries in the node certificates aren&#039;t always respected.&#039;&#039;&#039;  What this boils down to is that if full verification is turned on, you cannot use IP addresses in the &amp;lt;code&amp;gt;opensearch.yml&amp;lt;/code&amp;gt; (or any other configuration file such as the logstash pipelines).&lt;br /&gt;
&lt;br /&gt;
Each node will have a unique version of opensearch.yml due to certificate file names, the role(s) for the node, and the temperature (for data nodes).  The significant parameters in the opensearch.yml file are:&lt;br /&gt;
* &amp;lt;code&amp;gt;cluster.name&amp;lt;/code&amp;gt; - must be identical in all nodes&lt;br /&gt;
* &amp;lt;code&amp;gt;node.name&amp;lt;/code&amp;gt;- can be the hostname, but doesn&#039;t have to be (must be unique)&lt;br /&gt;
* &amp;lt;code&amp;gt;path.data&amp;lt;/code&amp;gt; - data nodes only -- must be unique to the node (i.e if using shared storage, each node must have its own directory on the shared volume)&lt;br /&gt;
* &amp;lt;code&amp;gt;path.logs&amp;lt;/code&amp;gt; - must be unique to the node (same as above)&lt;br /&gt;
* &amp;lt;code&amp;gt;network.host&amp;lt;/code&amp;gt; -- host&#039;s FQDN where all traffic will be received&lt;br /&gt;
**Can be a single hostname or an array of hostnames in &amp;lt;code&amp;gt;[&amp;quot;name&amp;quot;, &amp;quot;name&amp;quot;]&amp;lt;/code&amp;gt; format&lt;br /&gt;
**If you are doing transport-level host verification this CANNOT be an IP -- OpenSearch can&#039;t handle the SANs in the certificates needed to make it work&lt;br /&gt;
* &amp;lt;code&amp;gt;http.port&amp;lt;/code&amp;gt; -- leave it as the default (&amp;lt;code&amp;gt;9200&amp;lt;/code&amp;gt;) but uncomment it to lock it in&lt;br /&gt;
* &amp;lt;code&amp;gt;discovery.seed_hosts&amp;lt;/code&amp;gt; -- FQDN for all the masters (same for all nodes) -- only used for cluster bootstrap&lt;br /&gt;
* &amp;lt;code&amp;gt;cluster.initial_master_nodes&amp;lt;/code&amp;gt; -- put the master node names here (not the hostnames) -- same for all nodes&lt;br /&gt;
* &amp;lt;code&amp;gt;node.[master|data|ingest|remote]&amp;lt;/code&amp;gt; - set the type of the node (specify all four)&lt;br /&gt;
* &amp;lt;code&amp;gt;node.attr.temp&amp;lt;/code&amp;gt; - (data nodes only) defines data storage tiers (&amp;lt;code&amp;gt;hot&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;warm&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;cold&amp;lt;/code&amp;gt;)&lt;br /&gt;
The stock configuration file has most of these specified -- edit the file to fit the configuration of the node.&lt;br /&gt;
&lt;br /&gt;
The security configuration must be added next.  Since we are not using the demo security as our template, all the relevant entries must be added now.  Copy this block into the end of the stock opensearch.yml, editing as needed to provide the relevant certificate file names:&lt;br /&gt;
 node.master: true&lt;br /&gt;
 node.ingest: true&lt;br /&gt;
 node.data: false&lt;br /&gt;
 #node.remote: false&lt;br /&gt;
 &lt;br /&gt;
 #node.attr.temp: hot&lt;br /&gt;
 &lt;br /&gt;
 ######## Start OpenSearch Security Configuration ########&lt;br /&gt;
 plugins.security.ssl.transport.pemcert_filepath: &amp;lt;node&amp;gt;.crt&lt;br /&gt;
 plugins.security.ssl.transport.pemkey_filepath: &amp;lt;node&amp;gt;-pkcs8.key&lt;br /&gt;
 plugins.security.ssl.transport.pemtrustedcas_filepath: &amp;lt;CAcert&amp;gt;&lt;br /&gt;
 plugins.security.ssl.transport.enforce_hostname_verification: true&lt;br /&gt;
 &lt;br /&gt;
 plugins.security.ssl.http.enabled: true&lt;br /&gt;
 plugins.security.ssl.http.pemcert_filepath: &amp;lt;node&amp;gt;.crt&lt;br /&gt;
 plugins.security.ssl.http.pemkey_filepath: &amp;lt;node&amp;gt;-pkcs8.key&lt;br /&gt;
 plugins.security.ssl.http.pemtrustedcas_filepath: &amp;lt;CAcert&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 plugins.security.allow_unsafe_democertificates: false&lt;br /&gt;
 plugins.security.allow_default_init_securityindex: true&lt;br /&gt;
 &lt;br /&gt;
 # at least one cert -- must be an EXACT copy of the DN for the certificates to be used for admin auth&lt;br /&gt;
 plugins.security.authcz.admin_dn:&lt;br /&gt;
   - CN=Admin,O=OpenSearch,C=US&lt;br /&gt;
 &lt;br /&gt;
 # these must be EXACT copies of the DN for the node certificates&lt;br /&gt;
 plugins.security.nodes_dn:&lt;br /&gt;
   - CN=master-1.opensearch.localnet,O=OpenSearch,C=US&lt;br /&gt;
   - CN=data-hot-1.opensearch.localnet,O=OpenSearch,C=US&lt;br /&gt;
 &lt;br /&gt;
 # this is all boiler plate ... no modifications needed&lt;br /&gt;
 plugins.security.audit.type: internal_opensearch&lt;br /&gt;
 plugins.security.enable_snapshot_restore_privilege: true&lt;br /&gt;
 plugins.security.check_snapshot_restore_write_privileges: true&lt;br /&gt;
 plugins.security.restapi.roles_enabled: [&amp;quot;all_access&amp;quot;, &amp;quot;security_rest_api_access&amp;quot;]&lt;br /&gt;
 plugins.security.system_indices.enabled: true&lt;br /&gt;
 # this next bit should ALL be on one line ...&lt;br /&gt;
 plugins.security.system_indices.indices: [&amp;quot;.opendistro-alerting-config&amp;quot;, &amp;quot;.opendistro-alerting-alert*&amp;quot;, &amp;quot;.opendistro-anomaly-results*&amp;quot;, &amp;quot;.opendistro-anomaly-detector*&amp;quot;, &amp;quot;.opendistro-anomaly-checkpoints&amp;quot;, &amp;quot;.opendistro-anomaly-detection-state&amp;quot;, &amp;quot;.opendistro-reports-*&amp;quot;, &amp;quot;.opendistro-notifications-*&amp;quot;, &amp;quot;.opendistro-notebooks&amp;quot;, &amp;quot;.opendistro-asynchronous-search-response*&amp;quot;, &amp;quot;.replication-metadata-store&amp;quot;]&lt;br /&gt;
 &lt;br /&gt;
 node.max_local_storage_nodes: 3&lt;br /&gt;
 &lt;br /&gt;
 ######## End OpenSearch Security Configuration ########&lt;br /&gt;
Note that there are two sections where the DNs from the certificates must be provided to enable admin authentication for security configuration, and for validating the nodes that will be part of the cluster.  You can easily show the DNs for your certificates using this command:&lt;br /&gt;
 openssl x509 -subject -nameopt RFC2253 -noout -in &amp;lt;cert file name&amp;gt;&lt;br /&gt;
The DN for the admin cert and the DNs for the node certs go in separate sections as shown above.  Add all the cluster nodes into the nodes_dn section -- this must be the same for all nodes or they will not be able to communicate.&lt;br /&gt;
&lt;br /&gt;
=== Certificates ===&lt;br /&gt;
Copy the following certificates/keys that were created previously into the config directory of each node:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;CAcert&amp;gt;&lt;br /&gt;
* &amp;lt;node&amp;gt;.crt&lt;br /&gt;
* &amp;lt;node&amp;gt;-pkcs8.key&lt;br /&gt;
* admin.crt&lt;br /&gt;
* admin-pkcs8.crt&lt;br /&gt;
Verify that the &amp;lt;code&amp;gt;opensearch&amp;lt;/code&amp;gt; user is able to at least read all of the certs/keys, or the cluster will not function.&lt;br /&gt;
&lt;br /&gt;
=== Security Plugin Configuration ===&lt;br /&gt;
While the security configuration files exist on all the nodes in the cluster, they are only used once and only by the node where the security initialization is performed.  With that in mine, pick one node (the first master node will do nicely) to edit the configuration files as needed.  There are many things that can be done with these files, but two items in particular should be addressed.  The files are located in the &amp;lt;code&amp;gt;plugins/opensearch-security/securityconfig&amp;lt;/code&amp;gt; directory in the opensearch distribution.&lt;br /&gt;
&lt;br /&gt;
==== Authentication ====&lt;br /&gt;
&amp;lt;code&amp;gt;config.yml&amp;lt;/code&amp;gt; is where the authentication options are established.  This will need to be configured to support your authentication options.  The OpenSearch documentation describes the different options [https://opensearch.org/docs/latest/security-plugin/configuration/configuration/ here].&lt;br /&gt;
&lt;br /&gt;
The default configuration supports basic username/password authentication, but if you wish to use certificate authentication for API clients or ingest pipelines using logstash, you need to enable both &#039;&#039;&#039;http&#039;&#039;&#039; and &#039;&#039;&#039;transport&#039;&#039;&#039; under &amp;lt;code&amp;gt;clientcert_auth_domain&amp;lt;/code&amp;gt;.  Proxy authentication and OpenID Connect authentication is possible as well ... see the documentation.&lt;br /&gt;
&lt;br /&gt;
==== Admin user password ====&lt;br /&gt;
The default password for the admin user is well-known, and should be changed for a production environment.  The OpenSearch documentation provides instructions on how to [https://opensearch.org/docs/latest/security-plugin/configuration/yaml/#internal_usersyml generate passwords] for the &amp;lt;code&amp;gt;internal_users.yml&amp;lt;/code&amp;gt; file.  Note that &#039;&#039;&#039;the admin password cannot be set through the dashboard or the API&#039;&#039;&#039; -- it must be set in this file, and then (re)loaded to take effect.&lt;br /&gt;
&lt;br /&gt;
=== Security Plugin Initialization ===&lt;br /&gt;
Once all security configuration files are finished, they must be loaded into the OpenSearch cluster.  This can only be done once enough of the cluster is up to provide a master node and at least one data node, as the security configuration is loaded into an index in the cluster.  See the instructions below for specific sequencing.  This command will initialize the security plugin:&lt;br /&gt;
 plugins/opensearch-security/tools/securityadmin.sh \&lt;br /&gt;
     -cacert config/&amp;lt;CA cert&amp;gt; -cert config/admin.crt -key config/admin-pkcs8.key \&lt;br /&gt;
     -cd plugins/opensearch-security/securityconfig/ -host master-1.opensearch.localnet -icl -nhnv&lt;br /&gt;
... but again -- wait to do this until the right time below.&lt;br /&gt;
&lt;br /&gt;
=== Starting The Node ===&lt;br /&gt;
Subject to the constraints described in the next section, the only thing left is to start the opensearch service:&lt;br /&gt;
 sudo systemctl enable --now opensearch&lt;br /&gt;
Again, this must be done on each node in the correct sequence ... see below.&lt;br /&gt;
&lt;br /&gt;
== Cluster Bootstrapping ==&lt;br /&gt;
Starting up a multi-node cluster is a bit tricky:&lt;br /&gt;
&lt;br /&gt;
* Master-only nodes have no data&lt;br /&gt;
* Data-only nodes aren&#039;t master eligible&lt;br /&gt;
* Cluster initialization requires indexes to be available&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note that this process does NOT use the demo configuration -- put all the security plugin items in the &amp;lt;code&amp;gt;opensearch.yml&amp;lt;/code&amp;gt; file from the beginning&#039;&#039;&#039;.  This will cause the &amp;lt;code&amp;gt;opensearch-tar-install.sh&amp;lt;/code&amp;gt; script to skip the security initialization -- this is intentional.&lt;br /&gt;
&lt;br /&gt;
What this means is that you have to stand up multiple nodes before anything starts working ... the process should be:&lt;br /&gt;
&lt;br /&gt;
# Install and start what will be the &#039;primary&#039; master ... reference point for cluster startup operations&lt;br /&gt;
# Install and start one of the &#039;hot&#039; data nodes&lt;br /&gt;
# Run the &#039;securityadmin.sh&#039; script (using the command above) to initialize the security subsystem&lt;br /&gt;
# Install/start the other master nodes so that there is resiliency as nodes go up and down&lt;br /&gt;
# install/start the other data nodes to allow replication of the system indexes.&lt;br /&gt;
&lt;br /&gt;
== Install OpenSearch Dashboards ==&lt;br /&gt;
Finally, install the OpenSearch Dashboards using the tarball as well.&lt;br /&gt;
&lt;br /&gt;
Run the following commands as opensearch user:&lt;br /&gt;
 wget [https://artifacts.opensearch.org/releases/bundle/opensearch-dashboards/1.1.0/opensearch-dashboards-1.1.0-linux-x64.tar.gz https://artifacts.opensearch.org/releases/bundle/opensearch-dashboards/1.2.0/opensearch-dashboards-1.2.0-linux-x64.tar.gz]&lt;br /&gt;
 tar -zxf opensearch-dashboards-1.2.0-linux-x64.tar.gz&lt;br /&gt;
&lt;br /&gt;
Configure the &amp;lt;code&amp;gt;opensearch-dashboards.yml&amp;lt;/code&amp;gt; file as needed for your situation.&lt;br /&gt;
&lt;br /&gt;
Create file &amp;lt;code&amp;gt;/etc/systemd/system/opensearch-dashboards.service&amp;lt;/code&amp;gt; (as root) with the following contents:&lt;br /&gt;
 [Unit]&lt;br /&gt;
 Description=OpenSeach-Dasboards&lt;br /&gt;
 &lt;br /&gt;
 [Service]&lt;br /&gt;
 Type=simple&lt;br /&gt;
 User=opensearch&lt;br /&gt;
 Group=opensearch&lt;br /&gt;
 ExecStart=/opt/opensearch/opensearch-dashboards-1.2.0/bin/opensearch-dashboards&lt;br /&gt;
 Restart=always&lt;br /&gt;
 WorkingDirectory=/opt/opensearch/opensearch-dashboards-1.2.0&lt;br /&gt;
 &lt;br /&gt;
 [Install]&lt;br /&gt;
 WantedBy=multi-user.target&lt;br /&gt;
Run the following commands as root:&lt;br /&gt;
 systemctl daemon-reload&lt;br /&gt;
 systemctl start opensearch-dashboards.service &lt;br /&gt;
 systemctl enable opensearch-dashboards.service&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
* https://cryptopoolparty.com/blog/cardano-stake-pool-monitoring-ofo-stack/&lt;br /&gt;
** Describes how to use OpenSearch to monitor another application -- but portions were used to create this document&lt;br /&gt;
*https://github.com/opensearch-project/dashboards-reports/releases/tag/chromium-1.12.0.0&lt;br /&gt;
**download for headless chrome for generating PDF/PNG reports&lt;/div&gt;</summary>
		<author><name>DrEdWilliams</name></author>
	</entry>
	<entry>
		<id>https://wiki.williams-net.org/index.php?title=Cluster_Operations&amp;diff=672</id>
		<title>Cluster Operations</title>
		<link rel="alternate" type="text/html" href="https://wiki.williams-net.org/index.php?title=Cluster_Operations&amp;diff=672"/>
		<updated>2021-11-26T16:47:56Z</updated>

		<summary type="html">&lt;p&gt;DrEdWilliams: /* Rolling Restart */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Rolling Restart ==&lt;br /&gt;
The OpenSearch cluster is very resilient -- it tries to make sure it has all of its indices appropriately replicated at all times.  It can handle nodes dropping out and being added -- but sometimes we don&#039;t want that.  If nodes are simply restarted (to change settings) or the system is rebooted (for patching), we don&#039;t want to have OpenSearch move all its indices around.  &lt;br /&gt;
&lt;br /&gt;
This process works for a whole cluster restart (not recommended unless absolutely necessary) or individual node restarts.  If individual nodes are being restarted, only do one node at a time to avoid cluster panic should all shards of an index go offline on the nodes that get restarted.  The cluster &#039;&#039;&#039;&#039;&#039;should&#039;&#039;&#039;&#039;&#039; recover, but why stress it unnecessarily.&lt;br /&gt;
&lt;br /&gt;
The process is described in the [https://www.elastic.co/guide/en/elasticsearch/reference/current/restart-cluster.html Elastic documentation], and summarized below.&lt;br /&gt;
&lt;br /&gt;
=== Disable Shard Allocation ===&lt;br /&gt;
When you shut down a data node, the allocation process waits for &amp;lt;code&amp;gt;index.unassigned.node_left.delayed_timeout&amp;lt;/code&amp;gt; (by default, one minute) before starting to replicate the shards on that node to other nodes in the cluster, which can involve a lot of I/O. Since the node is shortly going to be restarted, this I/O is unnecessary. You can avoid racing the clock by disabling allocation of replicas before shutting down data nodes:&lt;br /&gt;
 curl -X PUT &amp;quot;localhost:9200/_cluster/settings?pretty&amp;quot; -H &#039;Content-Type: application/json&#039; -d&#039;&lt;br /&gt;
 {&lt;br /&gt;
   &amp;quot;persistent&amp;quot;: {&lt;br /&gt;
     &amp;quot;cluster.routing.allocation.enable&amp;quot;: &amp;quot;primaries&amp;quot;&lt;br /&gt;
   }&lt;br /&gt;
 }&#039;&lt;br /&gt;
&lt;br /&gt;
=== Flush Cache ===&lt;br /&gt;
This will prevent data loss by flushing any in-process activities to disk:&lt;br /&gt;
 curl -X POST &amp;quot;localhost:9200/_flush/synced?pretty&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== Shut Down/Restart Nodes ===&lt;br /&gt;
Now that things have settled out, we can stop/restart the opensearch services.  Note that a full cluster shutdown should be avoided, since any activity on the cluster as it is going down or coming up could cause errors to the user.  Use the systemd commands to stop/start/restart the nodes:&lt;br /&gt;
 # do this on all nodes&lt;br /&gt;
 sudo systemctl stop opensearch&lt;br /&gt;
  ... do required activity on all nodes ...&lt;br /&gt;
 sudo systemctl start opensearch&lt;br /&gt;
... or ...&lt;br /&gt;
 # restart a single node&lt;br /&gt;
 sudo systemctl restart opensearch&lt;br /&gt;
If it was a complete cluster shutdown, all nodes must rejoin the cluster before proceeding.  In either case, wait until the cluster (or node) achieves a &amp;quot;YELLOW&amp;quot; state before proceeding ... this means that all primary shards are accounted for, but replicas may not be.&lt;br /&gt;
&lt;br /&gt;
=== Enable Shard Allocation ===&lt;br /&gt;
As each node re-starts, it tries to identify which shards it had before.  Unless something has happened to disrupt the node&#039;s data, it will simply reactivate those shards (most likely as replica shards if it is a single-node restart).  To enable the cluster to get back to normal shard management, we remove the block we set above:&lt;br /&gt;
 curl -X PUT &amp;quot;localhost:9200/_cluster/settings?pretty&amp;quot; -H &#039;Content-Type: application/json&#039; -d&#039;&lt;br /&gt;
 {&lt;br /&gt;
   &amp;quot;persistent&amp;quot;: {&lt;br /&gt;
     &amp;quot;cluster.routing.allocation.enable&amp;quot;: null&lt;br /&gt;
   }&lt;br /&gt;
 }&#039;&lt;br /&gt;
&lt;br /&gt;
=== Follow Through ===&lt;br /&gt;
When doing any activity that disrupts the cluster operations enough to cause it to drop into a &amp;quot;YELLOW&amp;quot; or &amp;quot;RED&amp;quot; state, wait until the cluster is &amp;quot;GREEN&amp;quot; again before proceeding.  In the case of a full rolling restart (one node at a time), the cluster should be &amp;quot;GREEN&amp;quot; before proceeding to the next node.&lt;br /&gt;
&lt;br /&gt;
This process (node rolling restart, anyway) is captured in the script &amp;lt;code&amp;gt;node-restart.sh&amp;lt;/code&amp;gt;:&lt;br /&gt;
 #!/bin/bash&lt;br /&gt;
 #&lt;br /&gt;
 # perform a soft restart of a node, minimizing the reindexing that would&lt;br /&gt;
 #  normally occur when a node drops/inserts&lt;br /&gt;
 &lt;br /&gt;
 # set to one of the master nodes&lt;br /&gt;
 MASTER=master-node&lt;br /&gt;
 &lt;br /&gt;
 # replace with either the real admin password or a cert/key combination&lt;br /&gt;
 AUTH=&amp;quot;-u admin:admin&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 # first shut off shard allocation&lt;br /&gt;
 curl -XPUT -H &amp;quot;Content-Type: application/json&amp;quot; &amp;lt;nowiki&amp;gt;https://$MASTER:9200/_cluster/settings&amp;lt;/nowiki&amp;gt; $AUTH -d &#039;&lt;br /&gt;
 {&lt;br /&gt;
   &amp;quot;persistent&amp;quot;: {&lt;br /&gt;
     &amp;quot;cluster.routing.allocation.enable&amp;quot;: &amp;quot;primaries&amp;quot;&lt;br /&gt;
   }&lt;br /&gt;
 }&#039;&lt;br /&gt;
 echo&lt;br /&gt;
 &lt;br /&gt;
 # now flush the cache&lt;br /&gt;
 curl -XPOST &amp;lt;nowiki&amp;gt;https://$MASTER:9200/_flush&amp;lt;/nowiki&amp;gt; $AUTH&lt;br /&gt;
 echo&lt;br /&gt;
 &lt;br /&gt;
 # restart the opensearch process&lt;br /&gt;
 sudo systemctl restart opensearch&lt;br /&gt;
 &lt;br /&gt;
 # re-enable shard allocation&lt;br /&gt;
 curl -XPUT -H &amp;quot;Content-Type: application/json&amp;quot; &amp;lt;nowiki&amp;gt;https://$MASTER:9200/_cluster/settings&amp;lt;/nowiki&amp;gt; $AUTH -d &#039;&lt;br /&gt;
 {&lt;br /&gt;
   &amp;quot;persistent&amp;quot;: {&lt;br /&gt;
     &amp;quot;cluster.routing.allocation.enable&amp;quot;: null&lt;br /&gt;
   }&lt;br /&gt;
 }&#039;&lt;br /&gt;
 echo&lt;br /&gt;
This script is intended to be run on the node being restarted.&lt;br /&gt;
&lt;br /&gt;
== Cluster Upgrade ==&lt;br /&gt;
Assuming there are no other adjustments due to features and/or bugfixes, the basic process for upgrading a cluster is to upgrade one node at a time:&lt;br /&gt;
&lt;br /&gt;
# Expand tarball in the home directory of the &amp;lt;code&amp;gt;opensearch&amp;lt;/code&amp;gt; user&lt;br /&gt;
# Copy the certificates, keys, and CAs from the &amp;lt;code&amp;gt;config&amp;lt;/code&amp;gt; directory of the current version into the new one&lt;br /&gt;
# Copy the &amp;lt;code&amp;gt;opensearch.yml&amp;lt;/code&amp;gt; file from the current version into the new one and make any adjustments&lt;br /&gt;
# Copy the &amp;lt;code&amp;gt;jvm.options.d/heapsize.options&amp;lt;/code&amp;gt; file from the current version into the new one&lt;br /&gt;
# Move the &amp;lt;code&amp;gt;opensearch&amp;lt;/code&amp;gt; link in the home directory from the current version into the new one&lt;br /&gt;
# Reload and restart the opensearch process using the &#039;&#039;&#039;Rolling Restart&#039;&#039;&#039; process described above&lt;br /&gt;
# Wait for the cluster to get to a &amp;quot;GREEN&amp;quot; state before moving to the next node&lt;br /&gt;
&lt;br /&gt;
This assumes that the systemd unit file uses the softlink to access the opensearch executable as described in [[OpenSearch Cluster Installation]].&lt;br /&gt;
&lt;br /&gt;
== Certificate Updates ==&lt;br /&gt;
Given that the standard lifetime for certificates these days is one year, this is  something that will need to be accomplished several times during the lifetime of a cluster.&lt;br /&gt;
&lt;br /&gt;
This process does not require downtime for the cluster, but care must be taken to ensure that the mix of old and new certificates does not cripple the cluster.  This results in up to three complete cluster restarts (using the &#039;&#039;&#039;Rolling Restart&#039;&#039;&#039; method described above), but it does not disrupt the operation of the cluster as long as nothing exceptional happens, and the cluster is allowed to stabilize between each node restart.&lt;br /&gt;
&lt;br /&gt;
=== Create New Certificates ===&lt;br /&gt;
Using the process outlined in [https://wiki.williams-net.org/wiki/OpenSearch_Cluster_Installation#Create_Certificates OpenSearch Cluster Creation], create the required certificates and keys.  If at all possible, keep the DNs on all certificates the same as the ones they are replacing ... it reduces the number of restarts and minimizes the edits of the config files.  It also helps if the node certificate/key files have the same names ... for the same reasons.&lt;br /&gt;
&lt;br /&gt;
Send each node its new certificate/keys and the admin certificate/key -- or make them available for remote retrieval.  If user certificates were created, send them to the system(s) where they will be used.&lt;br /&gt;
&lt;br /&gt;
=== Create CA Bundle ===&lt;br /&gt;
Using a CA bundle with the old and new CAs will allow us to do a gradual transition and avoid downtime.  Fortunately, creating a bundle for the CAs is easy&lt;br /&gt;
 cat &amp;lt;old CA&amp;gt; &amp;lt;new CA&amp;gt; &amp;gt;&amp;gt; rootCAbundle.crt&lt;br /&gt;
Again, if there is currently a bundle in place, use the same name for the bundle file and you&#039;ll save yourself a lot of editing.  If the REST API uses a different CA bundle already that supports other (external) CAs, create a second CA bundle that includes the external CAs, the old internal CA, and the new internal CA.&lt;br /&gt;
&lt;br /&gt;
Send this new CA bundle to all cluster nodes, dashboard instances, and logstash instances.&lt;br /&gt;
&lt;br /&gt;
=== Update CA Files ===&lt;br /&gt;
For each cluster node:&lt;br /&gt;
&lt;br /&gt;
* Copy the new CA bundle in place (in the opensearch &amp;lt;code&amp;gt;config&amp;lt;/code&amp;gt; directory) making sure that permissions allow for read access to the &amp;lt;code&amp;gt;opensearch&amp;lt;/code&amp;gt; user.  &lt;br /&gt;
* DO NOT copy the node certificates yet.  &lt;br /&gt;
* Edit &amp;lt;code&amp;gt;opensearch.yml&amp;lt;/code&amp;gt; if needed:&lt;br /&gt;
** Update the name of the CA to the new CA bundle file (if needed) in both the &amp;lt;code&amp;gt;ssl&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;transport&amp;lt;/code&amp;gt; parameters, using the appropriate bundle for each parameter (see above)&lt;br /&gt;
** Add the DNs (DO NOT replace them yet) for the node and admin certificates if the new DNs are different from what is in the file&lt;br /&gt;
&lt;br /&gt;
* Perform a &#039;&#039;&#039;Rolling Restart&#039;&#039;&#039; of the node, verifying that there are no SSL/certificate errors, and waiting for &amp;quot;GREEN&amp;quot; status before proceeding &lt;br /&gt;
&lt;br /&gt;
Now do the same for all dashboards, logstash instances, and any other clients that use the CA to validate cluster identify:&lt;br /&gt;
&lt;br /&gt;
* Install the CA bundle as appropriate, ensuring that the client has read access to the CA bundle.&lt;br /&gt;
* Update the CA filename in the configuration file (if needed)&lt;br /&gt;
* DO NOT update user certificates at this point&lt;br /&gt;
* Restart the client (if needed) and verify proper operation&lt;br /&gt;
&lt;br /&gt;
=== Update Node Certificates ===&lt;br /&gt;
For each node in the cluster:&lt;br /&gt;
&lt;br /&gt;
* Copy the node certificate and key and the admin certificate and key into the opensearch &amp;lt;code&amp;gt;config&amp;lt;/code&amp;gt; directory, verifying that the &amp;lt;code&amp;gt;opensearch&amp;lt;/code&amp;gt; user has read permissions&lt;br /&gt;
* Edit &amp;lt;code&amp;gt;opensearch.yml&amp;lt;/code&amp;gt; if needed to correct certificate file names&lt;br /&gt;
* DO NOT remove extra DNs from the admin or node sections of the file yet&lt;br /&gt;
* Perform a &#039;&#039;&#039;Rolling Restart&#039;&#039;&#039; of the node, waiting for the cluster to achieve &amp;quot;GREEN&amp;quot; status before going to the next node&lt;br /&gt;
&lt;br /&gt;
=== Update Client Certificates ===&lt;br /&gt;
For each client that uses certificate authentication:&lt;br /&gt;
&lt;br /&gt;
* Copy the client certificate bundle (.p12 file) into place&lt;br /&gt;
* Edit the configuration file if needed to reflect the new file&lt;br /&gt;
* Restart the client (if needed) to activate the new configuration&lt;br /&gt;
&lt;br /&gt;
=== Clean Up ===&lt;br /&gt;
At this point we can remove any old DNs from the &amp;lt;code&amp;gt;opensearch.yml&amp;lt;/code&amp;gt; configurations and in general remove all traces of the old certificates in the cluster nodes and clients.  If a restart is warranted to verify that nothing critical was deleted, that should be done at this time.&lt;br /&gt;
&lt;br /&gt;
It is not necessary to replace the new CA bundle with the CA certificate -- it serves no purpose as the old cert is just along for the ride at this point, and once it reaches its expiration date, will not be used.  If it must be done, use the same process above that was used to install the CA bundle, performing a rolling restart on each node as it is completed.&lt;/div&gt;</summary>
		<author><name>DrEdWilliams</name></author>
	</entry>
	<entry>
		<id>https://wiki.williams-net.org/index.php?title=OpenSearch_Cluster_Installation&amp;diff=671</id>
		<title>OpenSearch Cluster Installation</title>
		<link rel="alternate" type="text/html" href="https://wiki.williams-net.org/index.php?title=OpenSearch_Cluster_Installation&amp;diff=671"/>
		<updated>2021-11-26T15:55:06Z</updated>

		<summary type="html">&lt;p&gt;DrEdWilliams: /* Systemd Unit File */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;These instructions describe the creation of a multi-node OpenSearch cluster using the tarball distribution.  The configuration instructions below assume a cluster with the following components:&lt;br /&gt;
&lt;br /&gt;
* Multiple master/ingest nodes&lt;br /&gt;
* Multiple hot data nodes&lt;br /&gt;
* Multiple cold data nodes&lt;br /&gt;
&lt;br /&gt;
The instructions should be adaptable to any multi-node configuration, and even to a uniform node configuration (i.e. three master/ingress/data nodes) -- though that simple configuration does not need the multiple steps required for the more complex deployment.&lt;br /&gt;
&lt;br /&gt;
Read through the entire document before doing anything, as there is a specific order in which things must be done for a successful installation.&lt;br /&gt;
&lt;br /&gt;
== Node Preparation ==&lt;br /&gt;
Each node to be used in the cluster must be prepared to support the OpenSearch installation.&lt;br /&gt;
&lt;br /&gt;
=== Create Opensearch User ===&lt;br /&gt;
Debian/Ubuntu:&lt;br /&gt;
 sudo adduser --system -uid 968 --shell /bin/bash --gecos &#039;OpenSearch User&#039;  --group  --disabled-password --home /opt/opensearch opensearch&lt;br /&gt;
Fedora/RHEL:&lt;br /&gt;
 sudo adduser --system --uid 968 --shell /bin/bash --home-dir /opt/opensearch -m opensearch&lt;br /&gt;
Then add your normal user to the group:&lt;br /&gt;
 sudo usermod -aG opensearch ewilliam&lt;br /&gt;
&lt;br /&gt;
=== Set vm.max_map_count ===&lt;br /&gt;
Create &amp;lt;code&amp;gt;/etc/sysctl.d/vm.maxmap_count.conf&amp;lt;/code&amp;gt; (as root) and add the following line:&lt;br /&gt;
 vm.max_map_count=262144&lt;br /&gt;
Run the following command as root to load the new configuration:&lt;br /&gt;
 sysctl --system&lt;br /&gt;
&lt;br /&gt;
=== Systemd Unit File ===&lt;br /&gt;
One of the big things missing from the tarball distribution is a systemd unit file.  Fortunately, it isn&#039;t difficult to create a simple one that will work.&lt;br /&gt;
&lt;br /&gt;
Create a file &amp;lt;code&amp;gt;/etc/systemd/system/opensearch.service&amp;lt;/code&amp;gt; with the following contents:&lt;br /&gt;
 [Unit]&lt;br /&gt;
 Description=OpenSearch&lt;br /&gt;
 Documentation=&amp;lt;nowiki&amp;gt;https://opensearch.org/docs/&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 Wants=network-online.target&lt;br /&gt;
 After=network-online.target&lt;br /&gt;
 &lt;br /&gt;
 [Service]&lt;br /&gt;
 RuntimeDirectory=opensearch&lt;br /&gt;
 WorkingDirectory=/opt/opensearch/opensearch&lt;br /&gt;
 User=opensearch&lt;br /&gt;
 Group=opensearch&lt;br /&gt;
 &lt;br /&gt;
 ExecStart=/opt/opensearch/opensearch/opensearch-tar-install.sh&lt;br /&gt;
 &lt;br /&gt;
 # StandardOutput is configured to redirect to journalctl since&lt;br /&gt;
 # some error messages may be logged in standard output before&lt;br /&gt;
 # elasticsearch logging system is initialized. Elasticsearch&lt;br /&gt;
 # stores its logs in /var/log/elasticsearch and does not use&lt;br /&gt;
 # journalctl by default. If you also want to enable journalctl&lt;br /&gt;
 # logging, you can simply remove the &amp;quot;quiet&amp;quot; option from ExecStart.&lt;br /&gt;
 StandardOutput=journal&lt;br /&gt;
 StandardError=inherit&lt;br /&gt;
 &lt;br /&gt;
 # Specifies the maximum file descriptor number that can be opened by this process&lt;br /&gt;
 LimitNOFILE=65535&lt;br /&gt;
 &lt;br /&gt;
 # Specifies the maximum number of processes&lt;br /&gt;
 LimitNPROC=4096&lt;br /&gt;
 &lt;br /&gt;
 # Specifies the maximum size of virtual memory&lt;br /&gt;
 LimitAS=infinity&lt;br /&gt;
 &lt;br /&gt;
 # Specifies the maximum file size&lt;br /&gt;
 LimitFSIZE=infinity&lt;br /&gt;
 &lt;br /&gt;
 # Disable timeout logic and wait until process is stopped&lt;br /&gt;
 TimeoutStopSec=0&lt;br /&gt;
 &lt;br /&gt;
 # SIGTERM signal is used to stop the Java process&lt;br /&gt;
 KillSignal=SIGTERM&lt;br /&gt;
 &lt;br /&gt;
 # Send the signal only to the JVM rather than its control group&lt;br /&gt;
 KillMode=process&lt;br /&gt;
 &lt;br /&gt;
 # Java process is never killed&lt;br /&gt;
 SendSIGKILL=no&lt;br /&gt;
 &lt;br /&gt;
 # When a JVM receives a SIGTERM signal it exits with code 143&lt;br /&gt;
 SuccessExitStatus=143&lt;br /&gt;
 &lt;br /&gt;
 # Allow a slow startup before the systemd notifier module kicks in to extend the timeout&lt;br /&gt;
 TimeoutStartSec=75&lt;br /&gt;
 &lt;br /&gt;
 [Install]&lt;br /&gt;
 WantedBy=multi-user.target&lt;br /&gt;
&lt;br /&gt;
== Create Certificates ==&lt;br /&gt;
There are three types of certificates used in OpenSearch:&lt;br /&gt;
&lt;br /&gt;
* CA certificate - one for the whole cluster to validate everything else&lt;br /&gt;
* Node certificate/key - identifies the node for internal cluster communications (transport layer) and data ingest (http layer)&lt;br /&gt;
** the CN must be the FQDN of the node&lt;br /&gt;
** even though OpenSearch doesn&#039;t seem to use them at this point, there should be SANs for the full FQDN, the short hostname, and the node&#039;s IP address&lt;br /&gt;
* User certificate/key - identifies a specific OpenSearch user&lt;br /&gt;
** the CN is a username in OpenSearch (explicit or implicit)&lt;br /&gt;
** username is used to determine roles/privileges in the cluster&lt;br /&gt;
** Need at least one cert for admin authentication&lt;br /&gt;
&lt;br /&gt;
Node and User certificates must all be signed by the cluster CA, and &#039;&#039;&#039;all keys must be in PKCS8 format&#039;&#039;&#039;.  If user certificates are to be used for authentication by logstash, they must be imported (along with the key and CA) into a PKCS12 (.p12) keystore.  The OpenSearch documentation has a good piece on [https://opensearch.org/docs/latest/security-plugin/configuration/generate-certificates/ how to create certificates].&lt;br /&gt;
&lt;br /&gt;
In summary, create the following certificates/keys&lt;br /&gt;
&lt;br /&gt;
# CA certificate/key&lt;br /&gt;
# For each cluster node:&lt;br /&gt;
#* &amp;lt;node&amp;gt;.crt&lt;br /&gt;
#* &amp;lt;node&amp;gt;-pkcs8.key&lt;br /&gt;
# For each user:&lt;br /&gt;
#* &amp;lt;user&amp;gt;.crt&lt;br /&gt;
#* &amp;lt;user&amp;gt;-pkcs8.key&lt;br /&gt;
#* &amp;lt;user&amp;gt;.p12&lt;br /&gt;
&lt;br /&gt;
All these should be created and available for the configuration of each cluster node below.&lt;br /&gt;
&lt;br /&gt;
== Install OpenSearch Tarball ==&lt;br /&gt;
The OpenSearch tarball must be installed on each node in the cluster; there is no difference at this point between the installations on the different types of nodes.  Assuming the deployment will use the &amp;lt;code&amp;gt;opensearch&amp;lt;/code&amp;gt; user created above ... change to the &amp;lt;code&amp;gt;opensearch&amp;lt;/code&amp;gt; user (from root):&lt;br /&gt;
 su - opensearch&lt;br /&gt;
 cd ~&lt;br /&gt;
Run the following commands as user &amp;lt;code&amp;gt;opensearch&amp;lt;/code&amp;gt; (from the opensearch home directory &amp;lt;code&amp;gt;/opt/opensearch&amp;lt;/code&amp;gt;):&lt;br /&gt;
 wget https://artifacts.opensearch.org/releases/bundle/opensearch/1.2.0/opensearch-1.2.0-linux-x64.tar.gz&lt;br /&gt;
 tar -xvzf opensearch-1.2.0-linux-x64.tar.gz&lt;br /&gt;
== Configure OpenSearch ==&lt;br /&gt;
Configuration varies depending on the type of node, but these are the places that need to be touched.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;jvm.options&amp;lt;/code&amp;gt; ===&lt;br /&gt;
Set the heap size.  Common practice is that the heap should be between 4GB and half the available memory, but no higher than 32GB.  A minimum configuration might be (assuming the hot data nodes have 32GB installed RAM:&lt;br /&gt;
&lt;br /&gt;
* 4G for master and cold data nodes&lt;br /&gt;
* 16G for hot data nodes&lt;br /&gt;
&lt;br /&gt;
This must be done individually for each node -- create the file &amp;lt;code&amp;gt;config/jvm.options.d/heapsize.options&amp;lt;/code&amp;gt; with the heap size options:&lt;br /&gt;
 -Xms4g&lt;br /&gt;
 -Xmx4g&lt;br /&gt;
... with, of course, the proper heap size for that node.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;opensearch.yml&amp;lt;/code&amp;gt; ===&lt;br /&gt;
While the OpenSearch software can be rather forgiving for low-security environments, if you turn on full hostname verification, it is rather strict.  The biggest thing to remember is that &#039;&#039;&#039;SAN entries in the node certificates aren&#039;t always respected.&#039;&#039;&#039;  What this boils down to is that if full verification is turned on, you cannot use IP addresses in the &amp;lt;code&amp;gt;opensearch.yml&amp;lt;/code&amp;gt; (or any other configuration file such as the logstash pipelines).&lt;br /&gt;
&lt;br /&gt;
Each node will have a unique version of opensearch.yml due to certificate file names, the role(s) for the node, and the temperature (for data nodes).  The significant parameters in the opensearch.yml file are:&lt;br /&gt;
* &amp;lt;code&amp;gt;cluster.name&amp;lt;/code&amp;gt; - must be identical in all nodes&lt;br /&gt;
* &amp;lt;code&amp;gt;node.name&amp;lt;/code&amp;gt;- can be the hostname, but doesn&#039;t have to be (must be unique)&lt;br /&gt;
* &amp;lt;code&amp;gt;path.data&amp;lt;/code&amp;gt; - data nodes only -- must be unique to the node (i.e if using shared storage, each node must have its own directory on the shared volume)&lt;br /&gt;
* &amp;lt;code&amp;gt;path.logs&amp;lt;/code&amp;gt; - must be unique to the node (same as above)&lt;br /&gt;
* &amp;lt;code&amp;gt;network.host&amp;lt;/code&amp;gt; -- host&#039;s FQDN where all traffic will be received&lt;br /&gt;
**Can be a single hostname or an array of hostnames in &amp;lt;code&amp;gt;[&amp;quot;name&amp;quot;, &amp;quot;name&amp;quot;]&amp;lt;/code&amp;gt; format&lt;br /&gt;
**If you are doing transport-level host verification this CANNOT be an IP -- OpenSearch can&#039;t handle the SANs in the certificates needed to make it work&lt;br /&gt;
* &amp;lt;code&amp;gt;http.port&amp;lt;/code&amp;gt; -- leave it as the default (&amp;lt;code&amp;gt;9200&amp;lt;/code&amp;gt;) but uncomment it to lock it in&lt;br /&gt;
* &amp;lt;code&amp;gt;discovery.seed_hosts&amp;lt;/code&amp;gt; -- FQDN for all the masters (same for all nodes) -- only used for cluster bootstrap&lt;br /&gt;
* &amp;lt;code&amp;gt;cluster.initial_master_nodes&amp;lt;/code&amp;gt; -- put the master node names here (not the hostnames) -- same for all nodes&lt;br /&gt;
* &amp;lt;code&amp;gt;node.[master|data|ingest|remote]&amp;lt;/code&amp;gt; - set the type of the node (specify all four)&lt;br /&gt;
* &amp;lt;code&amp;gt;node.attr.temp&amp;lt;/code&amp;gt; - (data nodes only) defines data storage tiers (&amp;lt;code&amp;gt;hot&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;warm&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;cold&amp;lt;/code&amp;gt;)&lt;br /&gt;
The stock configuration file has most of these specified -- edit the file to fit the configuration of the node.&lt;br /&gt;
&lt;br /&gt;
The security configuration must be added next.  Since we are not using the demo security as our template, all the relevant entries must be added now.  Copy this block into the end of the stock opensearch.yml, editing as needed to provide the relevant certificate file names:&lt;br /&gt;
 node.master: true&lt;br /&gt;
 node.ingest: true&lt;br /&gt;
 node.data: false&lt;br /&gt;
 #node.remote: false&lt;br /&gt;
 &lt;br /&gt;
 #node.attr.temp: hot&lt;br /&gt;
 &lt;br /&gt;
 ######## Start OpenSearch Security Configuration ########&lt;br /&gt;
 plugins.security.ssl.transport.pemcert_filepath: &amp;lt;node&amp;gt;.crt&lt;br /&gt;
 plugins.security.ssl.transport.pemkey_filepath: &amp;lt;node&amp;gt;-pkcs8.key&lt;br /&gt;
 plugins.security.ssl.transport.pemtrustedcas_filepath: &amp;lt;CAcert&amp;gt;&lt;br /&gt;
 plugins.security.ssl.transport.enforce_hostname_verification: true&lt;br /&gt;
 &lt;br /&gt;
 plugins.security.ssl.http.enabled: true&lt;br /&gt;
 plugins.security.ssl.http.pemcert_filepath: &amp;lt;node&amp;gt;.crt&lt;br /&gt;
 plugins.security.ssl.http.pemkey_filepath: &amp;lt;node&amp;gt;-pkcs8.key&lt;br /&gt;
 plugins.security.ssl.http.pemtrustedcas_filepath: &amp;lt;CAcert&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 plugins.security.allow_unsafe_democertificates: false&lt;br /&gt;
 plugins.security.allow_default_init_securityindex: true&lt;br /&gt;
 &lt;br /&gt;
 # at least one cert -- must be an EXACT copy of the DN for the certificates to be used for admin auth&lt;br /&gt;
 plugins.security.authcz.admin_dn:&lt;br /&gt;
   - CN=Admin,O=OpenSearch,C=US&lt;br /&gt;
 &lt;br /&gt;
 # these must be EXACT copies of the DN for the node certificates&lt;br /&gt;
 plugins.security.nodes_dn:&lt;br /&gt;
   - CN=master-1.opensearch.localnet,O=OpenSearch,C=US&lt;br /&gt;
   - CN=data-hot-1.opensearch.localnet,O=OpenSearch,C=US&lt;br /&gt;
 &lt;br /&gt;
 # this is all boiler plate ... no modifications needed&lt;br /&gt;
 plugins.security.audit.type: internal_opensearch&lt;br /&gt;
 plugins.security.enable_snapshot_restore_privilege: true&lt;br /&gt;
 plugins.security.check_snapshot_restore_write_privileges: true&lt;br /&gt;
 plugins.security.restapi.roles_enabled: [&amp;quot;all_access&amp;quot;, &amp;quot;security_rest_api_access&amp;quot;]&lt;br /&gt;
 plugins.security.system_indices.enabled: true&lt;br /&gt;
 # this next bit should ALL be on one line ...&lt;br /&gt;
 plugins.security.system_indices.indices: [&amp;quot;.opendistro-alerting-config&amp;quot;, &amp;quot;.opendistro-alerting-alert*&amp;quot;, &amp;quot;.opendistro-anomaly-results*&amp;quot;, &amp;quot;.opendistro-anomaly-detector*&amp;quot;, &amp;quot;.opendistro-anomaly-checkpoints&amp;quot;, &amp;quot;.opendistro-anomaly-detection-state&amp;quot;, &amp;quot;.opendistro-reports-*&amp;quot;, &amp;quot;.opendistro-notifications-*&amp;quot;, &amp;quot;.opendistro-notebooks&amp;quot;, &amp;quot;.opendistro-asynchronous-search-response*&amp;quot;, &amp;quot;.replication-metadata-store&amp;quot;]&lt;br /&gt;
 &lt;br /&gt;
 node.max_local_storage_nodes: 3&lt;br /&gt;
 &lt;br /&gt;
 ######## End OpenSearch Security Configuration ########&lt;br /&gt;
Note that there are two sections where the DNs from the certificates must be provided to enable admin authentication for security configuration, and for validating the nodes that will be part of the cluster.  You can easily show the DNs for your certificates using this command:&lt;br /&gt;
 openssl x509 -subject -nameopt RFC2253 -noout -in &amp;lt;cert file name&amp;gt;&lt;br /&gt;
The DN for the admin cert and the DNs for the node certs go in separate sections as shown above.  Add all the cluster nodes into the nodes_dn section -- this must be the same for all nodes or they will not be able to communicate.&lt;br /&gt;
&lt;br /&gt;
=== Certificates ===&lt;br /&gt;
Copy the following certificates/keys that were created previously into the config directory of each node:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;CAcert&amp;gt;&lt;br /&gt;
* &amp;lt;node&amp;gt;.crt&lt;br /&gt;
* &amp;lt;node&amp;gt;-pkcs8.key&lt;br /&gt;
* admin.crt&lt;br /&gt;
* admin-pkcs8.crt&lt;br /&gt;
Verify that the &amp;lt;code&amp;gt;opensearch&amp;lt;/code&amp;gt; user is able to at least read all of the certs/keys, or the cluster will not function.&lt;br /&gt;
&lt;br /&gt;
=== Security Plugin Configuration ===&lt;br /&gt;
While the security configuration files exist on all the nodes in the cluster, they are only used once and only by the node where the security initialization is performed.  With that in mine, pick one node (the first master node will do nicely) to edit the configuration files as needed.  There are many things that can be done with these files, but two items in particular should be addressed.  The files are located in the &amp;lt;code&amp;gt;plugins/opensearch-security/securityconfig&amp;lt;/code&amp;gt; directory in the opensearch distribution.&lt;br /&gt;
&lt;br /&gt;
==== Authentication ====&lt;br /&gt;
&amp;lt;code&amp;gt;config.yml&amp;lt;/code&amp;gt; is where the authentication options are established.  This will need to be configured to support your authentication options.  The OpenSearch documentation describes the different options [https://opensearch.org/docs/latest/security-plugin/configuration/configuration/ here].&lt;br /&gt;
&lt;br /&gt;
The default configuration supports basic username/password authentication, but if you wish to use certificate authentication for API clients or ingest pipelines using logstash, you need to enable both &#039;&#039;&#039;http&#039;&#039;&#039; and &#039;&#039;&#039;transport&#039;&#039;&#039; under &amp;lt;code&amp;gt;clientcert_auth_domain&amp;lt;/code&amp;gt;.  Proxy authentication and OpenID Connect authentication is possible as well ... see the documentation.&lt;br /&gt;
&lt;br /&gt;
==== Admin user password ====&lt;br /&gt;
The default password for the admin user is well-known, and should be changed for a production environment.  The OpenSearch documentation provides instructions on how to [https://opensearch.org/docs/latest/security-plugin/configuration/yaml/#internal_usersyml generate passwords] for the &amp;lt;code&amp;gt;internal_users.yml&amp;lt;/code&amp;gt; file.  Note that &#039;&#039;&#039;the admin password cannot be set through the dashboard or the API&#039;&#039;&#039; -- it must be set in this file, and then (re)loaded to take effect.&lt;br /&gt;
&lt;br /&gt;
=== Security Plugin Initialization ===&lt;br /&gt;
Once all security configuration files are finished, they must be loaded into the OpenSearch cluster.  This can only be done once enough of the cluster is up to provide a master node and at least one data node, as the security configuration is loaded into an index in the cluster.  See the instructions below for specific sequencing.  This command will initialize the security plugin:&lt;br /&gt;
 plugins/opensearch-security/tools/securityadmin.sh \&lt;br /&gt;
     -cacert config/&amp;lt;CA cert&amp;gt; -cert config/admin.crt -key config/admin-pkcs8.key \&lt;br /&gt;
     -cd plugins/opensearch-security/securityconfig/ -host master-1.opensearch.localnet -icl -nhnv&lt;br /&gt;
... but again -- wait to do this until the right time below.&lt;br /&gt;
&lt;br /&gt;
=== Starting The Node ===&lt;br /&gt;
Subject to the constraints described in the next section, the only thing left is to start the opensearch service:&lt;br /&gt;
 sudo systemctl enable --now opensearch&lt;br /&gt;
Again, this must be done on each node in the correct sequence ... see below.&lt;br /&gt;
&lt;br /&gt;
== Cluster Bootstrapping ==&lt;br /&gt;
Starting up a multi-node cluster is a bit tricky:&lt;br /&gt;
&lt;br /&gt;
* Master-only nodes have no data&lt;br /&gt;
* Data-only nodes aren&#039;t master eligible&lt;br /&gt;
* Cluster initialization requires indexes to be available&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note that this process does NOT use the demo configuration -- put all the security plugin items in the &amp;lt;code&amp;gt;opensearch.yml&amp;lt;/code&amp;gt; file from the beginning&#039;&#039;&#039;.  This will cause the &amp;lt;code&amp;gt;opensearch-tar-install.sh&amp;lt;/code&amp;gt; script to skip the security initialization -- this is intentional.&lt;br /&gt;
&lt;br /&gt;
What this means is that you have to stand up multiple nodes before anything starts working ... the process should be:&lt;br /&gt;
&lt;br /&gt;
# Install and start what will be the &#039;primary&#039; master ... reference point for cluster startup operations&lt;br /&gt;
# Install and start one of the &#039;hot&#039; data nodes&lt;br /&gt;
# Run the &#039;securityadmin.sh&#039; script (using the command above) to initialize the security subsystem&lt;br /&gt;
# Install/start the other master nodes so that there is resiliency as nodes go up and down&lt;br /&gt;
# install/start the other data nodes to allow replication of the system indexes.&lt;br /&gt;
&lt;br /&gt;
== Install OpenSearch Dashboards ==&lt;br /&gt;
Finally, install the OpenSearch Dashboards using the tarball as well.&lt;br /&gt;
&lt;br /&gt;
Run the following commands as opensearch user:&lt;br /&gt;
 wget [https://artifacts.opensearch.org/releases/bundle/opensearch-dashboards/1.1.0/opensearch-dashboards-1.1.0-linux-x64.tar.gz https://artifacts.opensearch.org/releases/bundle/opensearch-dashboards/1.2.0/opensearch-dashboards-1.2.0-linux-x64.tar.gz]&lt;br /&gt;
 tar -zxf opensearch-dashboards-1.2.0-linux-x64.tar.gz&lt;br /&gt;
&lt;br /&gt;
Configure the &amp;lt;code&amp;gt;opensearch-dashboards.yml&amp;lt;/code&amp;gt; file as needed for your situation.&lt;br /&gt;
&lt;br /&gt;
Create file &amp;lt;code&amp;gt;/etc/systemd/system/opensearch-dashboards.service&amp;lt;/code&amp;gt; (as root) with the following contents:&lt;br /&gt;
 [Unit]&lt;br /&gt;
 Description=OpenSeach-Dasboards&lt;br /&gt;
 &lt;br /&gt;
 [Service]&lt;br /&gt;
 Type=simple&lt;br /&gt;
 User=opensearch&lt;br /&gt;
 Group=opensearch&lt;br /&gt;
 ExecStart=/opt/opensearch/opensearch-dashboards-1.2.0/bin/opensearch-dashboards&lt;br /&gt;
 Restart=always&lt;br /&gt;
 WorkingDirectory=/opt/opensearch/opensearch-dashboards-1.2.0&lt;br /&gt;
 &lt;br /&gt;
 [Install]&lt;br /&gt;
 WantedBy=multi-user.target&lt;br /&gt;
Run the following commands as root:&lt;br /&gt;
 systemctl daemon-reload&lt;br /&gt;
 systemctl start opensearch-dashboards.service &lt;br /&gt;
 systemctl enable opensearch-dashboards.service&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
* https://cryptopoolparty.com/blog/cardano-stake-pool-monitoring-ofo-stack/&lt;br /&gt;
** Describes how to use OpenSearch to monitor another application -- but portions were used to create this document&lt;br /&gt;
*https://github.com/opensearch-project/dashboards-reports/releases/tag/chromium-1.12.0.0&lt;br /&gt;
**download for headless chrome for generating PDF/PNG reports&lt;/div&gt;</summary>
		<author><name>DrEdWilliams</name></author>
	</entry>
	<entry>
		<id>https://wiki.williams-net.org/index.php?title=Cluster_Operations&amp;diff=670</id>
		<title>Cluster Operations</title>
		<link rel="alternate" type="text/html" href="https://wiki.williams-net.org/index.php?title=Cluster_Operations&amp;diff=670"/>
		<updated>2021-11-26T14:26:15Z</updated>

		<summary type="html">&lt;p&gt;DrEdWilliams: Created page with &amp;quot;== Rolling Restart == The OpenSearch cluster is very resilient -- it tries to make sure it has all of its indices appropriately replicated at all times.  It can handle nodes d...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Rolling Restart ==&lt;br /&gt;
The OpenSearch cluster is very resilient -- it tries to make sure it has all of its indices appropriately replicated at all times.  It can handle nodes dropping out and being added -- but sometimes we don&#039;t want that.  If nodes are simply restarted (to change settings) or the system is rebooted (for patching), we don&#039;t want to have OpenSearch move all its indices around.  &lt;br /&gt;
&lt;br /&gt;
This process works for a whole cluster restart (not recommended unless absolutely necessary) or individual node restarts.  If individual nodes are being restarted, only do one node at a time to avoid cluster panic should all shards of an index go offline on the nodes that get restarted.  The cluster &#039;&#039;&#039;&#039;&#039;should&#039;&#039;&#039;&#039;&#039; recover, but why stress it unnecessarily.&lt;br /&gt;
&lt;br /&gt;
The process is described in the [https://www.elastic.co/guide/en/elasticsearch/reference/current/restart-cluster.html Elastic documentation], and summarized below.&lt;br /&gt;
&lt;br /&gt;
=== Disable Shard Allocation ===&lt;br /&gt;
When you shut down a data node, the allocation process waits for &amp;lt;code&amp;gt;index.unassigned.node_left.delayed_timeout&amp;lt;/code&amp;gt; (by default, one minute) before starting to replicate the shards on that node to other nodes in the cluster, which can involve a lot of I/O. Since the node is shortly going to be restarted, this I/O is unnecessary. You can avoid racing the clock by disabling allocation of replicas before shutting down data nodes:&lt;br /&gt;
 curl -X PUT &amp;quot;localhost:9200/_cluster/settings?pretty&amp;quot; -H &#039;Content-Type: application/json&#039; -d&#039;&lt;br /&gt;
 {&lt;br /&gt;
   &amp;quot;persistent&amp;quot;: {&lt;br /&gt;
     &amp;quot;cluster.routing.allocation.enable&amp;quot;: &amp;quot;primaries&amp;quot;&lt;br /&gt;
   }&lt;br /&gt;
 }&#039;&lt;br /&gt;
&lt;br /&gt;
=== Flush Cache ===&lt;br /&gt;
This will prevent data loss by flushing any in-process activities to disk:&lt;br /&gt;
 curl -X POST &amp;quot;localhost:9200/_flush/synced?pretty&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== Shut Down/Restart Nodes ===&lt;br /&gt;
Now that things have settled out, we can stop/restart the opensearch services.  Note that a full cluster shutdown should be avoided, since any activity on the cluster as it is going down or coming up could cause errors to the user.  Use the systemd commands to stop/start/restart the nodes:&lt;br /&gt;
 # do this on all nodes&lt;br /&gt;
 sudo systemctl stop opensearch&lt;br /&gt;
  ... do required activity on all nodes ...&lt;br /&gt;
 sudo systemctl start opensearch&lt;br /&gt;
... or ...&lt;br /&gt;
 # restart a single node&lt;br /&gt;
 sudo systemctl restart opensearch&lt;br /&gt;
If it was a complete cluster shutdown, all nodes must rejoin the cluster before proceeding.  In either case, wait until the cluster (or node) achieves a &amp;quot;YELLOW&amp;quot; state before proceeding ... this means that all primary shards are accounted for, but replicas may not be.&lt;br /&gt;
&lt;br /&gt;
=== Enable Shard Allocation ===&lt;br /&gt;
As each node re-starts, it tries to identify which shards it had before.  Unless something has happened to disrupt the node&#039;s data, it will simply reactivate those shards (most likely as replica shards if it is a single-node restart).  To enable the cluster to get back to normal shard management, we remove the block we set above:&lt;br /&gt;
 curl -X PUT &amp;quot;localhost:9200/_cluster/settings?pretty&amp;quot; -H &#039;Content-Type: application/json&#039; -d&#039;&lt;br /&gt;
 {&lt;br /&gt;
   &amp;quot;persistent&amp;quot;: {&lt;br /&gt;
     &amp;quot;cluster.routing.allocation.enable&amp;quot;: null&lt;br /&gt;
   }&lt;br /&gt;
 }&#039;&lt;br /&gt;
&lt;br /&gt;
=== Follow Through ===&lt;br /&gt;
When doing any activity that disrupts the cluster operations enough to cause it to drop into a &amp;quot;YELLOW&amp;quot; or &amp;quot;RED&amp;quot; state, wait until the cluster is &amp;quot;GREEN&amp;quot; again before proceeding.  In the case of a full rolling restart (one node at a time), the cluster should be &amp;quot;GREEN&amp;quot; before proceeding to the next node.&lt;/div&gt;</summary>
		<author><name>DrEdWilliams</name></author>
	</entry>
	<entry>
		<id>https://wiki.williams-net.org/index.php?title=OpenSearch&amp;diff=669</id>
		<title>OpenSearch</title>
		<link rel="alternate" type="text/html" href="https://wiki.williams-net.org/index.php?title=OpenSearch&amp;diff=669"/>
		<updated>2021-11-26T12:51:19Z</updated>

		<summary type="html">&lt;p&gt;DrEdWilliams: /* OpenSearch How-Tos */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== WilliamsNet OpenSearch Architecture ==&lt;br /&gt;
For convenience, and to enable this cluster to be usable as a Test and Development System for the HPCMP OpenSearch cluster, the configuration and naming conventions here will mirror that used in the HPCMP environment:&lt;br /&gt;
&lt;br /&gt;
* Indices will be named using this style:  &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;&amp;lt;data source&amp;gt;-&amp;lt;schema version&amp;gt;-&amp;lt;system name&amp;gt;-YYYY.MM.DD&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* Data will be routed through logstash to enable processing and augmentation prior to indexing in the cluster&lt;br /&gt;
&lt;br /&gt;
=== OpenSearch Cluster &amp;amp; Dashboards ===&lt;br /&gt;
The OpenSearch Cluster is composed of these node types:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Node Type&lt;br /&gt;
!Servers&lt;br /&gt;
!System&lt;br /&gt;
RAM (GB)&lt;br /&gt;
!Heap&lt;br /&gt;
Size (GB)&lt;br /&gt;
|-&lt;br /&gt;
|Master/Ingest&lt;br /&gt;
|poggin&lt;br /&gt;
|16&lt;br /&gt;
|4&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|aravis&lt;br /&gt;
|8&lt;br /&gt;
|4&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|lamppost&lt;br /&gt;
|8&lt;br /&gt;
|4&lt;br /&gt;
|-&lt;br /&gt;
|Hot Data&lt;br /&gt;
|caspian&lt;br /&gt;
|72&lt;br /&gt;
|16&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|belisar&lt;br /&gt;
|72&lt;br /&gt;
|16&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|uvilas&lt;br /&gt;
|72&lt;br /&gt;
|16&lt;br /&gt;
|-&lt;br /&gt;
|Cold Data&lt;br /&gt;
|calormen&lt;br /&gt;
|16&lt;br /&gt;
|6&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|trumpkin&lt;br /&gt;
|12&lt;br /&gt;
|6&lt;br /&gt;
|-&lt;br /&gt;
|Dashboards&lt;br /&gt;
|pro1&lt;br /&gt;
|40&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|Monitoring&lt;br /&gt;
|pro1 (cerebro)&lt;br /&gt;
|40&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
All nodes have access to the &amp;lt;code&amp;gt;/work&amp;lt;/code&amp;gt; filesystem (NFS shared by &#039;&#039;&#039;pro6&#039;&#039;&#039;), and use &amp;lt;code&amp;gt;/work/osdata/&amp;lt;hostname&amp;gt;&amp;lt;/code&amp;gt; for logs and data (if appropriate).&lt;br /&gt;
&lt;br /&gt;
All communications with (port 9200) and within (port 9300) the cluster is SSL encrypted using certificates generated based on a self-signed CA.  All certs are located in &amp;lt;code&amp;gt;/work/osdata/certs&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Aggregation and Processing ===&lt;br /&gt;
Logstash is installed on &#039;&#039;&#039;calormen&#039;&#039;&#039; and serves as the primary ingest route for the cluster.  Additionally, another instance of logstash is installed on &#039;&#039;&#039;aslan&#039;&#039;&#039; for testing/validation purposes.&lt;br /&gt;
&lt;br /&gt;
=== Data Collection ===&lt;br /&gt;
&lt;br /&gt;
* All servers should have metricbeat installed, feeding data to logstash on calormen&lt;br /&gt;
* Servers with CUDA-capable NVIDIA GPUs have the NVIDIA collection script installed:&lt;br /&gt;
** &#039;&#039;&#039;poggin&#039;&#039;&#039; (Quadro GP100)&lt;br /&gt;
** &#039;&#039;&#039;aslan&#039;&#039;&#039; (GTX 1080 Ti)&lt;br /&gt;
** &#039;&#039;&#039;rogin&#039;&#039;&#039; (GTX 1080)&lt;br /&gt;
** &#039;&#039;&#039;compute1&#039;&#039;&#039; (GTX 1070)&lt;br /&gt;
** &#039;&#039;&#039;griffle&#039;&#039;&#039; (GTX 1060, GTX 950)&lt;br /&gt;
** &#039;&#039;&#039;trumpkin&#039;&#039;&#039; (GTX 950)&lt;br /&gt;
&lt;br /&gt;
=== Cluster Monitoring ===&lt;br /&gt;
The OpenSearch cluster is monitored using the methods described in the [[Cluster Monitoring]] page:&lt;br /&gt;
&lt;br /&gt;
* OpenSearch node logs are collected by a single instance of filebeat running on &#039;&#039;&#039;poggin&#039;&#039;&#039;, accessing the logs directly from the shared filesystem.  The log data is sent through logstash on &#039;&#039;&#039;calormen&#039;&#039;&#039;, where the JSON log data is expanded and time-tagged&lt;br /&gt;
* Dashboards and visualizations are set up to view the log data and the audit data&lt;br /&gt;
&lt;br /&gt;
=== Authentication ===&lt;br /&gt;
&lt;br /&gt;
* User authentication to Dashboards is username/password using the OpenSearch internal user database&lt;br /&gt;
* API authentication uses username/password and certificate authentication methods&lt;br /&gt;
* Authentication of nodes in the cluster uses node certificates and the DNs contained in the &amp;lt;code&amp;gt;opensearch.yml&amp;lt;/code&amp;gt; configuration files&lt;br /&gt;
*All certs are located in &amp;lt;code&amp;gt;/work/osdata/certs&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== OpenSearch How-Tos ==&lt;br /&gt;
Topics related to creating, maintaining, and using an elastic cluster&lt;br /&gt;
&lt;br /&gt;
* [[OpenSearch Cluster|Installing an OpenSearch Cluster &amp;amp; Dashboards]]&lt;br /&gt;
* [[Data Collection Methods]]&lt;br /&gt;
* [[OpenSearch Cluster Monitoring|Cluster Monitoring]]&lt;br /&gt;
*[[Cluster Operations]]&lt;/div&gt;</summary>
		<author><name>DrEdWilliams</name></author>
	</entry>
	<entry>
		<id>https://wiki.williams-net.org/index.php?title=MediaWiki:Sidebar&amp;diff=668</id>
		<title>MediaWiki:Sidebar</title>
		<link rel="alternate" type="text/html" href="https://wiki.williams-net.org/index.php?title=MediaWiki:Sidebar&amp;diff=668"/>
		<updated>2021-11-26T12:49:52Z</updated>

		<summary type="html">&lt;p&gt;DrEdWilliams: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
* navigation&lt;br /&gt;
** WilliamsNet Commons|Commons&lt;br /&gt;
** WilliamsNet Architecture|Architecture&lt;br /&gt;
** How-To|How-To&lt;br /&gt;
** Systems|Systems&lt;br /&gt;
** Hardware|Hardware&lt;br /&gt;
** System Administration Processes|SysAdmin&lt;br /&gt;
** Kubernetes|Kubernetes&lt;br /&gt;
** OpenSearch|OpenSearch&lt;br /&gt;
* Special&lt;br /&gt;
** Special:WantedPages|Pages to create&lt;br /&gt;
** Special:AllPages|All pages&lt;br /&gt;
** recentchanges-url|recentchanges&lt;br /&gt;
** randompage-url|randompage&lt;br /&gt;
** helppage|help-mediawiki&lt;br /&gt;
** https://www.mediawiki.org/wiki/Help:Formatting|Formatting Help&lt;br /&gt;
* SEARCH&lt;br /&gt;
* TOOLBOX&lt;br /&gt;
* LANGUAGES&lt;/div&gt;</summary>
		<author><name>DrEdWilliams</name></author>
	</entry>
	<entry>
		<id>https://wiki.williams-net.org/index.php?title=Aslan&amp;diff=667</id>
		<title>Aslan</title>
		<link rel="alternate" type="text/html" href="https://wiki.williams-net.org/index.php?title=Aslan&amp;diff=667"/>
		<updated>2021-11-26T12:18:42Z</updated>

		<summary type="html">&lt;p&gt;DrEdWilliams: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This system is the primary linux workstation in the office and needs to have the basic apps for a graphic workstation:&lt;br /&gt;
&lt;br /&gt;
* KDE Plasma Desktop&lt;br /&gt;
* Mate terminal (Ubuntu app)&lt;br /&gt;
* VideoLAN media player (https://videolan.org/vlc/download-redhat.html)&lt;br /&gt;
* VMware Horizon Client (for SAIC VDI access)&lt;br /&gt;
* Visual Studio Code (vscode - https://code.visualstudio.com/download)&lt;br /&gt;
* Calibre library manager (download)&lt;br /&gt;
* HPCMP Kerberos Kit (https://centers.hpc.mil)&lt;br /&gt;
** CAC software (CA CoolKey?)&lt;br /&gt;
* Kontena Lens (download latest)&lt;br /&gt;
* Thunderbird&lt;br /&gt;
* Slack&lt;br /&gt;
* Synergy (v1)&lt;br /&gt;
* NVIDIA drivers (default with kubuntu/nonfree)&lt;br /&gt;
* Zoom client&lt;br /&gt;
* Firefox&lt;br /&gt;
* rclone (for google &amp;amp; dropbox mounts)&lt;br /&gt;
*pdsh&lt;br /&gt;
*Oracle Java (the real thing) for the Dell Storage manager&lt;br /&gt;
*minio client (mc) for gitlab backup -- there is a copy in /work/bin if that will work for the platform.&lt;br /&gt;
*Dell Equalogic Group Manager (java webstart - requires iSCSInet interface below and Oracle Java)&lt;br /&gt;
&lt;br /&gt;
Configurations:&lt;br /&gt;
* mount /work and /files filesystems&lt;br /&gt;
*configure extra network devices&lt;br /&gt;
**StorageNet (10.1.0.8) - use the second ethernet interface&lt;br /&gt;
**iSCSInet (10.2.0.200) - done via [[VLAN Interfaces|VLAN]] 15 on the StorageNet interface&lt;br /&gt;
* set up [[Mounting Google Drive and Dropbox|dropbox/google drive mounts]] (gdrives script in /work/bin)&lt;br /&gt;
Tasks/Applications (in addition to normal housekeeping):&lt;br /&gt;
&lt;br /&gt;
* cron daily:&lt;br /&gt;
**check-all (moved to pro6)&lt;br /&gt;
** Backup GitLab&lt;br /&gt;
***mount storage1:/backup/systems to /backup_systems&lt;br /&gt;
***install the cert for the gitlab instance (since it is self-signed)&lt;/div&gt;</summary>
		<author><name>DrEdWilliams</name></author>
	</entry>
	<entry>
		<id>https://wiki.williams-net.org/index.php?title=Pages_that_need_to_be_updated&amp;diff=666</id>
		<title>Pages that need to be updated</title>
		<link rel="alternate" type="text/html" href="https://wiki.williams-net.org/index.php?title=Pages_that_need_to_be_updated&amp;diff=666"/>
		<updated>2021-11-26T12:15:37Z</updated>

		<summary type="html">&lt;p&gt;DrEdWilliams: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[SSH Host Key Management]]&lt;br /&gt;
&lt;br /&gt;
[[Diggle]] - manage configuration in GitLab&lt;br /&gt;
&lt;br /&gt;
[[MediaWiki Deployment]] (needs to be created)&lt;br /&gt;
&lt;br /&gt;
Update [[WilliamsNet Architecture|Architecture]] to reflect [[OpenSearch]] and [[Elastic Cluster|Elastic]] clusters&lt;br /&gt;
&lt;br /&gt;
[[Synergy Installation]] (needs to be created)&lt;br /&gt;
&lt;br /&gt;
[[Log Accumulator]] (needs to be created)&lt;/div&gt;</summary>
		<author><name>DrEdWilliams</name></author>
	</entry>
	<entry>
		<id>https://wiki.williams-net.org/index.php?title=OpenSearch_Cluster_Installation&amp;diff=665</id>
		<title>OpenSearch Cluster Installation</title>
		<link rel="alternate" type="text/html" href="https://wiki.williams-net.org/index.php?title=OpenSearch_Cluster_Installation&amp;diff=665"/>
		<updated>2021-11-26T01:16:44Z</updated>

		<summary type="html">&lt;p&gt;DrEdWilliams: /* jvm.options */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;These instructions describe the creation of a multi-node OpenSearch cluster using the tarball distribution.  The configuration instructions below assume a cluster with the following components:&lt;br /&gt;
&lt;br /&gt;
* Multiple master/ingest nodes&lt;br /&gt;
* Multiple hot data nodes&lt;br /&gt;
* Multiple cold data nodes&lt;br /&gt;
&lt;br /&gt;
The instructions should be adaptable to any multi-node configuration, and even to a uniform node configuration (i.e. three master/ingress/data nodes) -- though that simple configuration does not need the multiple steps required for the more complex deployment.&lt;br /&gt;
&lt;br /&gt;
Read through the entire document before doing anything, as there is a specific order in which things must be done for a successful installation.&lt;br /&gt;
&lt;br /&gt;
== Node Preparation ==&lt;br /&gt;
Each node to be used in the cluster must be prepared to support the OpenSearch installation.&lt;br /&gt;
&lt;br /&gt;
=== Create Opensearch User ===&lt;br /&gt;
Debian/Ubuntu:&lt;br /&gt;
 sudo adduser --system -uid 968 --shell /bin/bash --gecos &#039;OpenSearch User&#039;  --group  --disabled-password --home /opt/opensearch opensearch&lt;br /&gt;
Fedora/RHEL:&lt;br /&gt;
 sudo adduser --system --uid 968 --shell /bin/bash --home-dir /opt/opensearch -m opensearch&lt;br /&gt;
Then add your normal user to the group:&lt;br /&gt;
 sudo usermod -aG opensearch ewilliam&lt;br /&gt;
&lt;br /&gt;
=== Set vm.max_map_count ===&lt;br /&gt;
Create &amp;lt;code&amp;gt;/etc/sysctl.d/vm.maxmap_count.conf&amp;lt;/code&amp;gt; (as root) and add the following line:&lt;br /&gt;
 vm.max_map_count=262144&lt;br /&gt;
Run the following command as root to load the new configuration:&lt;br /&gt;
 sysctl --system&lt;br /&gt;
&lt;br /&gt;
=== Systemd Unit File ===&lt;br /&gt;
One of the big things missing from the tarball distribution is a systemd unit file.  Fortunately, it isn&#039;t difficult to create a simple one that will work.&lt;br /&gt;
&lt;br /&gt;
Create a file &amp;lt;code&amp;gt;/etc/systemd/system/opensearch.service&amp;lt;/code&amp;gt; with the following contents:&lt;br /&gt;
 [Unit]&lt;br /&gt;
 Description=OpenSearch&lt;br /&gt;
 Documentation=&amp;lt;nowiki&amp;gt;https://opensearch.org/docs/&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 Wants=network-online.target&lt;br /&gt;
 After=network-online.target&lt;br /&gt;
 &lt;br /&gt;
 [Service]&lt;br /&gt;
 RuntimeDirectory=opensearch&lt;br /&gt;
 WorkingDirectory=/opt/opensearch/opensearch-1.1.0&lt;br /&gt;
 User=opensearch&lt;br /&gt;
 Group=opensearch&lt;br /&gt;
 &lt;br /&gt;
 ExecStart=/opt/opensearch/opensearch-1.1.0/opensearch-tar-install.sh&lt;br /&gt;
 &lt;br /&gt;
 # StandardOutput is configured to redirect to journalctl since&lt;br /&gt;
 # some error messages may be logged in standard output before&lt;br /&gt;
 # elasticsearch logging system is initialized. Elasticsearch&lt;br /&gt;
 # stores its logs in /var/log/elasticsearch and does not use&lt;br /&gt;
 # journalctl by default. If you also want to enable journalctl&lt;br /&gt;
 # logging, you can simply remove the &amp;quot;quiet&amp;quot; option from ExecStart.&lt;br /&gt;
 StandardOutput=journal&lt;br /&gt;
 StandardError=inherit&lt;br /&gt;
 &lt;br /&gt;
 # Specifies the maximum file descriptor number that can be opened by this process&lt;br /&gt;
 LimitNOFILE=65535&lt;br /&gt;
 &lt;br /&gt;
 # Specifies the maximum number of processes&lt;br /&gt;
 LimitNPROC=4096&lt;br /&gt;
 &lt;br /&gt;
 # Specifies the maximum size of virtual memory&lt;br /&gt;
 LimitAS=infinity&lt;br /&gt;
 &lt;br /&gt;
 # Specifies the maximum file size&lt;br /&gt;
 LimitFSIZE=infinity&lt;br /&gt;
 &lt;br /&gt;
 # Disable timeout logic and wait until process is stopped&lt;br /&gt;
 TimeoutStopSec=0&lt;br /&gt;
 &lt;br /&gt;
 # SIGTERM signal is used to stop the Java process&lt;br /&gt;
 KillSignal=SIGTERM&lt;br /&gt;
 &lt;br /&gt;
 # Send the signal only to the JVM rather than its control group&lt;br /&gt;
 KillMode=process&lt;br /&gt;
 &lt;br /&gt;
 # Java process is never killed&lt;br /&gt;
 SendSIGKILL=no&lt;br /&gt;
 &lt;br /&gt;
 # When a JVM receives a SIGTERM signal it exits with code 143&lt;br /&gt;
 SuccessExitStatus=143&lt;br /&gt;
 &lt;br /&gt;
 # Allow a slow startup before the systemd notifier module kicks in to extend the timeout&lt;br /&gt;
 TimeoutStartSec=75&lt;br /&gt;
 &lt;br /&gt;
 [Install]&lt;br /&gt;
 WantedBy=multi-user.target&lt;br /&gt;
&lt;br /&gt;
== Create Certificates ==&lt;br /&gt;
There are three types of certificates used in OpenSearch:&lt;br /&gt;
&lt;br /&gt;
* CA certificate - one for the whole cluster to validate everything else&lt;br /&gt;
* Node certificate/key - identifies the node for internal cluster communications (transport layer) and data ingest (http layer)&lt;br /&gt;
** the CN must be the FQDN of the node&lt;br /&gt;
** even though OpenSearch doesn&#039;t seem to use them at this point, there should be SANs for the full FQDN, the short hostname, and the node&#039;s IP address&lt;br /&gt;
* User certificate/key - identifies a specific OpenSearch user&lt;br /&gt;
** the CN is a username in OpenSearch (explicit or implicit)&lt;br /&gt;
** username is used to determine roles/privileges in the cluster&lt;br /&gt;
** Need at least one cert for admin authentication&lt;br /&gt;
&lt;br /&gt;
Node and User certificates must all be signed by the cluster CA, and &#039;&#039;&#039;all keys must be in PKCS8 format&#039;&#039;&#039;.  If user certificates are to be used for authentication by logstash, they must be imported (along with the key and CA) into a PKCS12 (.p12) keystore.  The OpenSearch documentation has a good piece on [https://opensearch.org/docs/latest/security-plugin/configuration/generate-certificates/ how to create certificates].&lt;br /&gt;
&lt;br /&gt;
In summary, create the following certificates/keys&lt;br /&gt;
&lt;br /&gt;
# CA certificate/key&lt;br /&gt;
# For each cluster node:&lt;br /&gt;
#* &amp;lt;node&amp;gt;.crt&lt;br /&gt;
#* &amp;lt;node&amp;gt;-pkcs8.key&lt;br /&gt;
# For each user:&lt;br /&gt;
#* &amp;lt;user&amp;gt;.crt&lt;br /&gt;
#* &amp;lt;user&amp;gt;-pkcs8.key&lt;br /&gt;
#* &amp;lt;user&amp;gt;.p12&lt;br /&gt;
&lt;br /&gt;
All these should be created and available for the configuration of each cluster node below.&lt;br /&gt;
&lt;br /&gt;
== Install OpenSearch Tarball ==&lt;br /&gt;
The OpenSearch tarball must be installed on each node in the cluster; there is no difference at this point between the installations on the different types of nodes.  Assuming the deployment will use the &amp;lt;code&amp;gt;opensearch&amp;lt;/code&amp;gt; user created above ... change to the &amp;lt;code&amp;gt;opensearch&amp;lt;/code&amp;gt; user (from root):&lt;br /&gt;
 su - opensearch&lt;br /&gt;
 cd ~&lt;br /&gt;
Run the following commands as user &amp;lt;code&amp;gt;opensearch&amp;lt;/code&amp;gt; (from the opensearch home directory &amp;lt;code&amp;gt;/opt/opensearch&amp;lt;/code&amp;gt;):&lt;br /&gt;
 wget https://artifacts.opensearch.org/releases/bundle/opensearch/1.2.0/opensearch-1.2.0-linux-x64.tar.gz&lt;br /&gt;
 tar -xvzf opensearch-1.2.0-linux-x64.tar.gz&lt;br /&gt;
== Configure OpenSearch ==&lt;br /&gt;
Configuration varies depending on the type of node, but these are the places that need to be touched.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;jvm.options&amp;lt;/code&amp;gt; ===&lt;br /&gt;
Set the heap size.  Common practice is that the heap should be between 4GB and half the available memory, but no higher than 32GB.  A minimum configuration might be (assuming the hot data nodes have 32GB installed RAM:&lt;br /&gt;
&lt;br /&gt;
* 4G for master and cold data nodes&lt;br /&gt;
* 16G for hot data nodes&lt;br /&gt;
&lt;br /&gt;
This must be done individually for each node -- create the file &amp;lt;code&amp;gt;config/jvm.options.d/heapsize.options&amp;lt;/code&amp;gt; with the heap size options:&lt;br /&gt;
 -Xms4g&lt;br /&gt;
 -Xmx4g&lt;br /&gt;
... with, of course, the proper heap size for that node.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;opensearch.yml&amp;lt;/code&amp;gt; ===&lt;br /&gt;
While the OpenSearch software can be rather forgiving for low-security environments, if you turn on full hostname verification, it is rather strict.  The biggest thing to remember is that &#039;&#039;&#039;SAN entries in the node certificates aren&#039;t always respected.&#039;&#039;&#039;  What this boils down to is that if full verification is turned on, you cannot use IP addresses in the &amp;lt;code&amp;gt;opensearch.yml&amp;lt;/code&amp;gt; (or any other configuration file such as the logstash pipelines).&lt;br /&gt;
&lt;br /&gt;
Each node will have a unique version of opensearch.yml due to certificate file names, the role(s) for the node, and the temperature (for data nodes).  The significant parameters in the opensearch.yml file are:&lt;br /&gt;
* &amp;lt;code&amp;gt;cluster.name&amp;lt;/code&amp;gt; - must be identical in all nodes&lt;br /&gt;
* &amp;lt;code&amp;gt;node.name&amp;lt;/code&amp;gt;- can be the hostname, but doesn&#039;t have to be (must be unique)&lt;br /&gt;
* &amp;lt;code&amp;gt;path.data&amp;lt;/code&amp;gt; - data nodes only -- must be unique to the node (i.e if using shared storage, each node must have its own directory on the shared volume)&lt;br /&gt;
* &amp;lt;code&amp;gt;path.logs&amp;lt;/code&amp;gt; - must be unique to the node (same as above)&lt;br /&gt;
* &amp;lt;code&amp;gt;network.host&amp;lt;/code&amp;gt; -- host&#039;s FQDN where all traffic will be received&lt;br /&gt;
**Can be a single hostname or an array of hostnames in &amp;lt;code&amp;gt;[&amp;quot;name&amp;quot;, &amp;quot;name&amp;quot;]&amp;lt;/code&amp;gt; format&lt;br /&gt;
**If you are doing transport-level host verification this CANNOT be an IP -- OpenSearch can&#039;t handle the SANs in the certificates needed to make it work&lt;br /&gt;
* &amp;lt;code&amp;gt;http.port&amp;lt;/code&amp;gt; -- leave it as the default (&amp;lt;code&amp;gt;9200&amp;lt;/code&amp;gt;) but uncomment it to lock it in&lt;br /&gt;
* &amp;lt;code&amp;gt;discovery.seed_hosts&amp;lt;/code&amp;gt; -- FQDN for all the masters (same for all nodes) -- only used for cluster bootstrap&lt;br /&gt;
* &amp;lt;code&amp;gt;cluster.initial_master_nodes&amp;lt;/code&amp;gt; -- put the master node names here (not the hostnames) -- same for all nodes&lt;br /&gt;
* &amp;lt;code&amp;gt;node.[master|data|ingest|remote]&amp;lt;/code&amp;gt; - set the type of the node (specify all four)&lt;br /&gt;
* &amp;lt;code&amp;gt;node.attr.temp&amp;lt;/code&amp;gt; - (data nodes only) defines data storage tiers (&amp;lt;code&amp;gt;hot&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;warm&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;cold&amp;lt;/code&amp;gt;)&lt;br /&gt;
The stock configuration file has most of these specified -- edit the file to fit the configuration of the node.&lt;br /&gt;
&lt;br /&gt;
The security configuration must be added next.  Since we are not using the demo security as our template, all the relevant entries must be added now.  Copy this block into the end of the stock opensearch.yml, editing as needed to provide the relevant certificate file names:&lt;br /&gt;
 node.master: true&lt;br /&gt;
 node.ingest: true&lt;br /&gt;
 node.data: false&lt;br /&gt;
 #node.remote: false&lt;br /&gt;
 &lt;br /&gt;
 #node.attr.temp: hot&lt;br /&gt;
 &lt;br /&gt;
 ######## Start OpenSearch Security Configuration ########&lt;br /&gt;
 plugins.security.ssl.transport.pemcert_filepath: &amp;lt;node&amp;gt;.crt&lt;br /&gt;
 plugins.security.ssl.transport.pemkey_filepath: &amp;lt;node&amp;gt;-pkcs8.key&lt;br /&gt;
 plugins.security.ssl.transport.pemtrustedcas_filepath: &amp;lt;CAcert&amp;gt;&lt;br /&gt;
 plugins.security.ssl.transport.enforce_hostname_verification: true&lt;br /&gt;
 &lt;br /&gt;
 plugins.security.ssl.http.enabled: true&lt;br /&gt;
 plugins.security.ssl.http.pemcert_filepath: &amp;lt;node&amp;gt;.crt&lt;br /&gt;
 plugins.security.ssl.http.pemkey_filepath: &amp;lt;node&amp;gt;-pkcs8.key&lt;br /&gt;
 plugins.security.ssl.http.pemtrustedcas_filepath: &amp;lt;CAcert&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 plugins.security.allow_unsafe_democertificates: false&lt;br /&gt;
 plugins.security.allow_default_init_securityindex: true&lt;br /&gt;
 &lt;br /&gt;
 # at least one cert -- must be an EXACT copy of the DN for the certificates to be used for admin auth&lt;br /&gt;
 plugins.security.authcz.admin_dn:&lt;br /&gt;
   - CN=Admin,O=OpenSearch,C=US&lt;br /&gt;
 &lt;br /&gt;
 # these must be EXACT copies of the DN for the node certificates&lt;br /&gt;
 plugins.security.nodes_dn:&lt;br /&gt;
   - CN=master-1.opensearch.localnet,O=OpenSearch,C=US&lt;br /&gt;
   - CN=data-hot-1.opensearch.localnet,O=OpenSearch,C=US&lt;br /&gt;
 &lt;br /&gt;
 # this is all boiler plate ... no modifications needed&lt;br /&gt;
 plugins.security.audit.type: internal_opensearch&lt;br /&gt;
 plugins.security.enable_snapshot_restore_privilege: true&lt;br /&gt;
 plugins.security.check_snapshot_restore_write_privileges: true&lt;br /&gt;
 plugins.security.restapi.roles_enabled: [&amp;quot;all_access&amp;quot;, &amp;quot;security_rest_api_access&amp;quot;]&lt;br /&gt;
 plugins.security.system_indices.enabled: true&lt;br /&gt;
 # this next bit should ALL be on one line ...&lt;br /&gt;
 plugins.security.system_indices.indices: [&amp;quot;.opendistro-alerting-config&amp;quot;, &amp;quot;.opendistro-alerting-alert*&amp;quot;, &amp;quot;.opendistro-anomaly-results*&amp;quot;, &amp;quot;.opendistro-anomaly-detector*&amp;quot;, &amp;quot;.opendistro-anomaly-checkpoints&amp;quot;, &amp;quot;.opendistro-anomaly-detection-state&amp;quot;, &amp;quot;.opendistro-reports-*&amp;quot;, &amp;quot;.opendistro-notifications-*&amp;quot;, &amp;quot;.opendistro-notebooks&amp;quot;, &amp;quot;.opendistro-asynchronous-search-response*&amp;quot;, &amp;quot;.replication-metadata-store&amp;quot;]&lt;br /&gt;
 &lt;br /&gt;
 node.max_local_storage_nodes: 3&lt;br /&gt;
 &lt;br /&gt;
 ######## End OpenSearch Security Configuration ########&lt;br /&gt;
Note that there are two sections where the DNs from the certificates must be provided to enable admin authentication for security configuration, and for validating the nodes that will be part of the cluster.  You can easily show the DNs for your certificates using this command:&lt;br /&gt;
 openssl x509 -subject -nameopt RFC2253 -noout -in &amp;lt;cert file name&amp;gt;&lt;br /&gt;
The DN for the admin cert and the DNs for the node certs go in separate sections as shown above.  Add all the cluster nodes into the nodes_dn section -- this must be the same for all nodes or they will not be able to communicate.&lt;br /&gt;
&lt;br /&gt;
=== Certificates ===&lt;br /&gt;
Copy the following certificates/keys that were created previously into the config directory of each node:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;CAcert&amp;gt;&lt;br /&gt;
* &amp;lt;node&amp;gt;.crt&lt;br /&gt;
* &amp;lt;node&amp;gt;-pkcs8.key&lt;br /&gt;
* admin.crt&lt;br /&gt;
* admin-pkcs8.crt&lt;br /&gt;
Verify that the &amp;lt;code&amp;gt;opensearch&amp;lt;/code&amp;gt; user is able to at least read all of the certs/keys, or the cluster will not function.&lt;br /&gt;
&lt;br /&gt;
=== Security Plugin Configuration ===&lt;br /&gt;
While the security configuration files exist on all the nodes in the cluster, they are only used once and only by the node where the security initialization is performed.  With that in mine, pick one node (the first master node will do nicely) to edit the configuration files as needed.  There are many things that can be done with these files, but two items in particular should be addressed.  The files are located in the &amp;lt;code&amp;gt;plugins/opensearch-security/securityconfig&amp;lt;/code&amp;gt; directory in the opensearch distribution.&lt;br /&gt;
&lt;br /&gt;
==== Authentication ====&lt;br /&gt;
&amp;lt;code&amp;gt;config.yml&amp;lt;/code&amp;gt; is where the authentication options are established.  This will need to be configured to support your authentication options.  The OpenSearch documentation describes the different options [https://opensearch.org/docs/latest/security-plugin/configuration/configuration/ here].&lt;br /&gt;
&lt;br /&gt;
The default configuration supports basic username/password authentication, but if you wish to use certificate authentication for API clients or ingest pipelines using logstash, you need to enable both &#039;&#039;&#039;http&#039;&#039;&#039; and &#039;&#039;&#039;transport&#039;&#039;&#039; under &amp;lt;code&amp;gt;clientcert_auth_domain&amp;lt;/code&amp;gt;.  Proxy authentication and OpenID Connect authentication is possible as well ... see the documentation.&lt;br /&gt;
&lt;br /&gt;
==== Admin user password ====&lt;br /&gt;
The default password for the admin user is well-known, and should be changed for a production environment.  The OpenSearch documentation provides instructions on how to [https://opensearch.org/docs/latest/security-plugin/configuration/yaml/#internal_usersyml generate passwords] for the &amp;lt;code&amp;gt;internal_users.yml&amp;lt;/code&amp;gt; file.  Note that &#039;&#039;&#039;the admin password cannot be set through the dashboard or the API&#039;&#039;&#039; -- it must be set in this file, and then (re)loaded to take effect.&lt;br /&gt;
&lt;br /&gt;
=== Security Plugin Initialization ===&lt;br /&gt;
Once all security configuration files are finished, they must be loaded into the OpenSearch cluster.  This can only be done once enough of the cluster is up to provide a master node and at least one data node, as the security configuration is loaded into an index in the cluster.  See the instructions below for specific sequencing.  This command will initialize the security plugin:&lt;br /&gt;
 plugins/opensearch-security/tools/securityadmin.sh \&lt;br /&gt;
     -cacert config/&amp;lt;CA cert&amp;gt; -cert config/admin.crt -key config/admin-pkcs8.key \&lt;br /&gt;
     -cd plugins/opensearch-security/securityconfig/ -host master-1.opensearch.localnet -icl -nhnv&lt;br /&gt;
... but again -- wait to do this until the right time below.&lt;br /&gt;
&lt;br /&gt;
=== Starting The Node ===&lt;br /&gt;
Subject to the constraints described in the next section, the only thing left is to start the opensearch service:&lt;br /&gt;
 sudo systemctl enable --now opensearch&lt;br /&gt;
Again, this must be done on each node in the correct sequence ... see below.&lt;br /&gt;
&lt;br /&gt;
== Cluster Bootstrapping ==&lt;br /&gt;
Starting up a multi-node cluster is a bit tricky:&lt;br /&gt;
&lt;br /&gt;
* Master-only nodes have no data&lt;br /&gt;
* Data-only nodes aren&#039;t master eligible&lt;br /&gt;
* Cluster initialization requires indexes to be available&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note that this process does NOT use the demo configuration -- put all the security plugin items in the &amp;lt;code&amp;gt;opensearch.yml&amp;lt;/code&amp;gt; file from the beginning&#039;&#039;&#039;.  This will cause the &amp;lt;code&amp;gt;opensearch-tar-install.sh&amp;lt;/code&amp;gt; script to skip the security initialization -- this is intentional.&lt;br /&gt;
&lt;br /&gt;
What this means is that you have to stand up multiple nodes before anything starts working ... the process should be:&lt;br /&gt;
&lt;br /&gt;
# Install and start what will be the &#039;primary&#039; master ... reference point for cluster startup operations&lt;br /&gt;
# Install and start one of the &#039;hot&#039; data nodes&lt;br /&gt;
# Run the &#039;securityadmin.sh&#039; script (using the command above) to initialize the security subsystem&lt;br /&gt;
# Install/start the other master nodes so that there is resiliency as nodes go up and down&lt;br /&gt;
# install/start the other data nodes to allow replication of the system indexes.&lt;br /&gt;
&lt;br /&gt;
== Install OpenSearch Dashboards ==&lt;br /&gt;
Finally, install the OpenSearch Dashboards using the tarball as well.&lt;br /&gt;
&lt;br /&gt;
Run the following commands as opensearch user:&lt;br /&gt;
 wget [https://artifacts.opensearch.org/releases/bundle/opensearch-dashboards/1.1.0/opensearch-dashboards-1.1.0-linux-x64.tar.gz https://artifacts.opensearch.org/releases/bundle/opensearch-dashboards/1.2.0/opensearch-dashboards-1.2.0-linux-x64.tar.gz]&lt;br /&gt;
 tar -zxf opensearch-dashboards-1.2.0-linux-x64.tar.gz&lt;br /&gt;
&lt;br /&gt;
Configure the &amp;lt;code&amp;gt;opensearch-dashboards.yml&amp;lt;/code&amp;gt; file as needed for your situation.&lt;br /&gt;
&lt;br /&gt;
Create file &amp;lt;code&amp;gt;/etc/systemd/system/opensearch-dashboards.service&amp;lt;/code&amp;gt; (as root) with the following contents:&lt;br /&gt;
 [Unit]&lt;br /&gt;
 Description=OpenSeach-Dasboards&lt;br /&gt;
 &lt;br /&gt;
 [Service]&lt;br /&gt;
 Type=simple&lt;br /&gt;
 User=opensearch&lt;br /&gt;
 Group=opensearch&lt;br /&gt;
 ExecStart=/opt/opensearch/opensearch-dashboards-1.2.0/bin/opensearch-dashboards&lt;br /&gt;
 Restart=always&lt;br /&gt;
 WorkingDirectory=/opt/opensearch/opensearch-dashboards-1.2.0&lt;br /&gt;
 &lt;br /&gt;
 [Install]&lt;br /&gt;
 WantedBy=multi-user.target&lt;br /&gt;
Run the following commands as root:&lt;br /&gt;
 systemctl daemon-reload&lt;br /&gt;
 systemctl start opensearch-dashboards.service &lt;br /&gt;
 systemctl enable opensearch-dashboards.service&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
* https://cryptopoolparty.com/blog/cardano-stake-pool-monitoring-ofo-stack/&lt;br /&gt;
** Describes how to use OpenSearch to monitor another application -- but portions were used to create this document&lt;br /&gt;
*https://github.com/opensearch-project/dashboards-reports/releases/tag/chromium-1.12.0.0&lt;br /&gt;
**download for headless chrome for generating PDF/PNG reports&lt;/div&gt;</summary>
		<author><name>DrEdWilliams</name></author>
	</entry>
	<entry>
		<id>https://wiki.williams-net.org/index.php?title=OpenSearch_Cluster_Installation&amp;diff=664</id>
		<title>OpenSearch Cluster Installation</title>
		<link rel="alternate" type="text/html" href="https://wiki.williams-net.org/index.php?title=OpenSearch_Cluster_Installation&amp;diff=664"/>
		<updated>2021-11-25T19:15:34Z</updated>

		<summary type="html">&lt;p&gt;DrEdWilliams: /* Install Opensearch Tarball */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;These instructions describe the creation of a multi-node OpenSearch cluster using the tarball distribution.  The configuration instructions below assume a cluster with the following components:&lt;br /&gt;
&lt;br /&gt;
* Multiple master/ingest nodes&lt;br /&gt;
* Multiple hot data nodes&lt;br /&gt;
* Multiple cold data nodes&lt;br /&gt;
&lt;br /&gt;
The instructions should be adaptable to any multi-node configuration, and even to a uniform node configuration (i.e. three master/ingress/data nodes) -- though that simple configuration does not need the multiple steps required for the more complex deployment.&lt;br /&gt;
&lt;br /&gt;
Read through the entire document before doing anything, as there is a specific order in which things must be done for a successful installation.&lt;br /&gt;
&lt;br /&gt;
== Node Preparation ==&lt;br /&gt;
Each node to be used in the cluster must be prepared to support the OpenSearch installation.&lt;br /&gt;
&lt;br /&gt;
=== Create Opensearch User ===&lt;br /&gt;
Debian/Ubuntu:&lt;br /&gt;
 sudo adduser --system -uid 968 --shell /bin/bash --gecos &#039;OpenSearch User&#039;  --group  --disabled-password --home /opt/opensearch opensearch&lt;br /&gt;
Fedora/RHEL:&lt;br /&gt;
 sudo adduser --system --uid 968 --shell /bin/bash --home-dir /opt/opensearch -m opensearch&lt;br /&gt;
Then add your normal user to the group:&lt;br /&gt;
 sudo usermod -aG opensearch ewilliam&lt;br /&gt;
&lt;br /&gt;
=== Set vm.max_map_count ===&lt;br /&gt;
Create &amp;lt;code&amp;gt;/etc/sysctl.d/vm.maxmap_count.conf&amp;lt;/code&amp;gt; (as root) and add the following line:&lt;br /&gt;
 vm.max_map_count=262144&lt;br /&gt;
Run the following command as root to load the new configuration:&lt;br /&gt;
 sysctl --system&lt;br /&gt;
&lt;br /&gt;
=== Systemd Unit File ===&lt;br /&gt;
One of the big things missing from the tarball distribution is a systemd unit file.  Fortunately, it isn&#039;t difficult to create a simple one that will work.&lt;br /&gt;
&lt;br /&gt;
Create a file &amp;lt;code&amp;gt;/etc/systemd/system/opensearch.service&amp;lt;/code&amp;gt; with the following contents:&lt;br /&gt;
 [Unit]&lt;br /&gt;
 Description=OpenSearch&lt;br /&gt;
 Documentation=&amp;lt;nowiki&amp;gt;https://opensearch.org/docs/&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 Wants=network-online.target&lt;br /&gt;
 After=network-online.target&lt;br /&gt;
 &lt;br /&gt;
 [Service]&lt;br /&gt;
 RuntimeDirectory=opensearch&lt;br /&gt;
 WorkingDirectory=/opt/opensearch/opensearch-1.1.0&lt;br /&gt;
 User=opensearch&lt;br /&gt;
 Group=opensearch&lt;br /&gt;
 &lt;br /&gt;
 ExecStart=/opt/opensearch/opensearch-1.1.0/opensearch-tar-install.sh&lt;br /&gt;
 &lt;br /&gt;
 # StandardOutput is configured to redirect to journalctl since&lt;br /&gt;
 # some error messages may be logged in standard output before&lt;br /&gt;
 # elasticsearch logging system is initialized. Elasticsearch&lt;br /&gt;
 # stores its logs in /var/log/elasticsearch and does not use&lt;br /&gt;
 # journalctl by default. If you also want to enable journalctl&lt;br /&gt;
 # logging, you can simply remove the &amp;quot;quiet&amp;quot; option from ExecStart.&lt;br /&gt;
 StandardOutput=journal&lt;br /&gt;
 StandardError=inherit&lt;br /&gt;
 &lt;br /&gt;
 # Specifies the maximum file descriptor number that can be opened by this process&lt;br /&gt;
 LimitNOFILE=65535&lt;br /&gt;
 &lt;br /&gt;
 # Specifies the maximum number of processes&lt;br /&gt;
 LimitNPROC=4096&lt;br /&gt;
 &lt;br /&gt;
 # Specifies the maximum size of virtual memory&lt;br /&gt;
 LimitAS=infinity&lt;br /&gt;
 &lt;br /&gt;
 # Specifies the maximum file size&lt;br /&gt;
 LimitFSIZE=infinity&lt;br /&gt;
 &lt;br /&gt;
 # Disable timeout logic and wait until process is stopped&lt;br /&gt;
 TimeoutStopSec=0&lt;br /&gt;
 &lt;br /&gt;
 # SIGTERM signal is used to stop the Java process&lt;br /&gt;
 KillSignal=SIGTERM&lt;br /&gt;
 &lt;br /&gt;
 # Send the signal only to the JVM rather than its control group&lt;br /&gt;
 KillMode=process&lt;br /&gt;
 &lt;br /&gt;
 # Java process is never killed&lt;br /&gt;
 SendSIGKILL=no&lt;br /&gt;
 &lt;br /&gt;
 # When a JVM receives a SIGTERM signal it exits with code 143&lt;br /&gt;
 SuccessExitStatus=143&lt;br /&gt;
 &lt;br /&gt;
 # Allow a slow startup before the systemd notifier module kicks in to extend the timeout&lt;br /&gt;
 TimeoutStartSec=75&lt;br /&gt;
 &lt;br /&gt;
 [Install]&lt;br /&gt;
 WantedBy=multi-user.target&lt;br /&gt;
&lt;br /&gt;
== Create Certificates ==&lt;br /&gt;
There are three types of certificates used in OpenSearch:&lt;br /&gt;
&lt;br /&gt;
* CA certificate - one for the whole cluster to validate everything else&lt;br /&gt;
* Node certificate/key - identifies the node for internal cluster communications (transport layer) and data ingest (http layer)&lt;br /&gt;
** the CN must be the FQDN of the node&lt;br /&gt;
** even though OpenSearch doesn&#039;t seem to use them at this point, there should be SANs for the full FQDN, the short hostname, and the node&#039;s IP address&lt;br /&gt;
* User certificate/key - identifies a specific OpenSearch user&lt;br /&gt;
** the CN is a username in OpenSearch (explicit or implicit)&lt;br /&gt;
** username is used to determine roles/privileges in the cluster&lt;br /&gt;
** Need at least one cert for admin authentication&lt;br /&gt;
&lt;br /&gt;
Node and User certificates must all be signed by the cluster CA, and &#039;&#039;&#039;all keys must be in PKCS8 format&#039;&#039;&#039;.  If user certificates are to be used for authentication by logstash, they must be imported (along with the key and CA) into a PKCS12 (.p12) keystore.  The OpenSearch documentation has a good piece on [https://opensearch.org/docs/latest/security-plugin/configuration/generate-certificates/ how to create certificates].&lt;br /&gt;
&lt;br /&gt;
In summary, create the following certificates/keys&lt;br /&gt;
&lt;br /&gt;
# CA certificate/key&lt;br /&gt;
# For each cluster node:&lt;br /&gt;
#* &amp;lt;node&amp;gt;.crt&lt;br /&gt;
#* &amp;lt;node&amp;gt;-pkcs8.key&lt;br /&gt;
# For each user:&lt;br /&gt;
#* &amp;lt;user&amp;gt;.crt&lt;br /&gt;
#* &amp;lt;user&amp;gt;-pkcs8.key&lt;br /&gt;
#* &amp;lt;user&amp;gt;.p12&lt;br /&gt;
&lt;br /&gt;
All these should be created and available for the configuration of each cluster node below.&lt;br /&gt;
&lt;br /&gt;
== Install OpenSearch Tarball ==&lt;br /&gt;
The OpenSearch tarball must be installed on each node in the cluster; there is no difference at this point between the installations on the different types of nodes.  Assuming the deployment will use the &amp;lt;code&amp;gt;opensearch&amp;lt;/code&amp;gt; user created above ... change to the &amp;lt;code&amp;gt;opensearch&amp;lt;/code&amp;gt; user (from root):&lt;br /&gt;
 su - opensearch&lt;br /&gt;
 cd ~&lt;br /&gt;
Run the following commands as user &amp;lt;code&amp;gt;opensearch&amp;lt;/code&amp;gt; (from the opensearch home directory &amp;lt;code&amp;gt;/opt/opensearch&amp;lt;/code&amp;gt;):&lt;br /&gt;
 wget https://artifacts.opensearch.org/releases/bundle/opensearch/1.2.0/opensearch-1.2.0-linux-x64.tar.gz&lt;br /&gt;
 tar -xvzf opensearch-1.2.0-linux-x64.tar.gz&lt;br /&gt;
== Configure OpenSearch ==&lt;br /&gt;
Configuration varies depending on the type of node, but these are the places that need to be touched.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;jvm.options&amp;lt;/code&amp;gt; ===&lt;br /&gt;
Set the heap size.  Common practice is that the heap should be between 4GB and half the available memory, but no higher than 32GB.  A minimum configuration might be (assuming the hot data nodes have 32GB installed RAM:&lt;br /&gt;
&lt;br /&gt;
* 4G for master and cold data nodes&lt;br /&gt;
* 16G for hot data nodes&lt;br /&gt;
&lt;br /&gt;
This must be done individually for each node.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;opensearch.yml&amp;lt;/code&amp;gt; ===&lt;br /&gt;
While the OpenSearch software can be rather forgiving for low-security environments, if you turn on full hostname verification, it is rather strict.  The biggest thing to remember is that &#039;&#039;&#039;SAN entries in the node certificates aren&#039;t always respected.&#039;&#039;&#039;  What this boils down to is that if full verification is turned on, you cannot use IP addresses in the &amp;lt;code&amp;gt;opensearch.yml&amp;lt;/code&amp;gt; (or any other configuration file such as the logstash pipelines).&lt;br /&gt;
&lt;br /&gt;
Each node will have a unique version of opensearch.yml due to certificate file names, the role(s) for the node, and the temperature (for data nodes).  The significant parameters in the opensearch.yml file are:&lt;br /&gt;
* &amp;lt;code&amp;gt;cluster.name&amp;lt;/code&amp;gt; - must be identical in all nodes&lt;br /&gt;
* &amp;lt;code&amp;gt;node.name&amp;lt;/code&amp;gt;- can be the hostname, but doesn&#039;t have to be (must be unique)&lt;br /&gt;
* &amp;lt;code&amp;gt;path.data&amp;lt;/code&amp;gt; - data nodes only -- must be unique to the node (i.e if using shared storage, each node must have its own directory on the shared volume)&lt;br /&gt;
* &amp;lt;code&amp;gt;path.logs&amp;lt;/code&amp;gt; - must be unique to the node (same as above)&lt;br /&gt;
* &amp;lt;code&amp;gt;network.host&amp;lt;/code&amp;gt; -- host&#039;s FQDN where all traffic will be received&lt;br /&gt;
**Can be a single hostname or an array of hostnames in &amp;lt;code&amp;gt;[&amp;quot;name&amp;quot;, &amp;quot;name&amp;quot;]&amp;lt;/code&amp;gt; format&lt;br /&gt;
**If you are doing transport-level host verification this CANNOT be an IP -- OpenSearch can&#039;t handle the SANs in the certificates needed to make it work&lt;br /&gt;
* &amp;lt;code&amp;gt;http.port&amp;lt;/code&amp;gt; -- leave it as the default (&amp;lt;code&amp;gt;9200&amp;lt;/code&amp;gt;) but uncomment it to lock it in&lt;br /&gt;
* &amp;lt;code&amp;gt;discovery.seed_hosts&amp;lt;/code&amp;gt; -- FQDN for all the masters (same for all nodes) -- only used for cluster bootstrap&lt;br /&gt;
* &amp;lt;code&amp;gt;cluster.initial_master_nodes&amp;lt;/code&amp;gt; -- put the master node names here (not the hostnames) -- same for all nodes&lt;br /&gt;
* &amp;lt;code&amp;gt;node.[master|data|ingest|remote]&amp;lt;/code&amp;gt; - set the type of the node (specify all four)&lt;br /&gt;
* &amp;lt;code&amp;gt;node.attr.temp&amp;lt;/code&amp;gt; - (data nodes only) defines data storage tiers (&amp;lt;code&amp;gt;hot&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;warm&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;cold&amp;lt;/code&amp;gt;)&lt;br /&gt;
The stock configuration file has most of these specified -- edit the file to fit the configuration of the node.&lt;br /&gt;
&lt;br /&gt;
The security configuration must be added next.  Since we are not using the demo security as our template, all the relevant entries must be added now.  Copy this block into the end of the stock opensearch.yml, editing as needed to provide the relevant certificate file names:&lt;br /&gt;
 node.master: true&lt;br /&gt;
 node.ingest: true&lt;br /&gt;
 node.data: false&lt;br /&gt;
 #node.remote: false&lt;br /&gt;
 &lt;br /&gt;
 #node.attr.temp: hot&lt;br /&gt;
 &lt;br /&gt;
 ######## Start OpenSearch Security Configuration ########&lt;br /&gt;
 plugins.security.ssl.transport.pemcert_filepath: &amp;lt;node&amp;gt;.crt&lt;br /&gt;
 plugins.security.ssl.transport.pemkey_filepath: &amp;lt;node&amp;gt;-pkcs8.key&lt;br /&gt;
 plugins.security.ssl.transport.pemtrustedcas_filepath: &amp;lt;CAcert&amp;gt;&lt;br /&gt;
 plugins.security.ssl.transport.enforce_hostname_verification: true&lt;br /&gt;
 &lt;br /&gt;
 plugins.security.ssl.http.enabled: true&lt;br /&gt;
 plugins.security.ssl.http.pemcert_filepath: &amp;lt;node&amp;gt;.crt&lt;br /&gt;
 plugins.security.ssl.http.pemkey_filepath: &amp;lt;node&amp;gt;-pkcs8.key&lt;br /&gt;
 plugins.security.ssl.http.pemtrustedcas_filepath: &amp;lt;CAcert&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 plugins.security.allow_unsafe_democertificates: false&lt;br /&gt;
 plugins.security.allow_default_init_securityindex: true&lt;br /&gt;
 &lt;br /&gt;
 # at least one cert -- must be an EXACT copy of the DN for the certificates to be used for admin auth&lt;br /&gt;
 plugins.security.authcz.admin_dn:&lt;br /&gt;
   - CN=Admin,O=OpenSearch,C=US&lt;br /&gt;
 &lt;br /&gt;
 # these must be EXACT copies of the DN for the node certificates&lt;br /&gt;
 plugins.security.nodes_dn:&lt;br /&gt;
   - CN=master-1.opensearch.localnet,O=OpenSearch,C=US&lt;br /&gt;
   - CN=data-hot-1.opensearch.localnet,O=OpenSearch,C=US&lt;br /&gt;
 &lt;br /&gt;
 # this is all boiler plate ... no modifications needed&lt;br /&gt;
 plugins.security.audit.type: internal_opensearch&lt;br /&gt;
 plugins.security.enable_snapshot_restore_privilege: true&lt;br /&gt;
 plugins.security.check_snapshot_restore_write_privileges: true&lt;br /&gt;
 plugins.security.restapi.roles_enabled: [&amp;quot;all_access&amp;quot;, &amp;quot;security_rest_api_access&amp;quot;]&lt;br /&gt;
 plugins.security.system_indices.enabled: true&lt;br /&gt;
 # this next bit should ALL be on one line ...&lt;br /&gt;
 plugins.security.system_indices.indices: [&amp;quot;.opendistro-alerting-config&amp;quot;, &amp;quot;.opendistro-alerting-alert*&amp;quot;, &amp;quot;.opendistro-anomaly-results*&amp;quot;, &amp;quot;.opendistro-anomaly-detector*&amp;quot;, &amp;quot;.opendistro-anomaly-checkpoints&amp;quot;, &amp;quot;.opendistro-anomaly-detection-state&amp;quot;, &amp;quot;.opendistro-reports-*&amp;quot;, &amp;quot;.opendistro-notifications-*&amp;quot;, &amp;quot;.opendistro-notebooks&amp;quot;, &amp;quot;.opendistro-asynchronous-search-response*&amp;quot;, &amp;quot;.replication-metadata-store&amp;quot;]&lt;br /&gt;
 &lt;br /&gt;
 node.max_local_storage_nodes: 3&lt;br /&gt;
 &lt;br /&gt;
 ######## End OpenSearch Security Configuration ########&lt;br /&gt;
Note that there are two sections where the DNs from the certificates must be provided to enable admin authentication for security configuration, and for validating the nodes that will be part of the cluster.  You can easily show the DNs for your certificates using this command:&lt;br /&gt;
 openssl x509 -subject -nameopt RFC2253 -noout -in &amp;lt;cert file name&amp;gt;&lt;br /&gt;
The DN for the admin cert and the DNs for the node certs go in separate sections as shown above.  Add all the cluster nodes into the nodes_dn section -- this must be the same for all nodes or they will not be able to communicate.&lt;br /&gt;
&lt;br /&gt;
=== Certificates ===&lt;br /&gt;
Copy the following certificates/keys that were created previously into the config directory of each node:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;CAcert&amp;gt;&lt;br /&gt;
* &amp;lt;node&amp;gt;.crt&lt;br /&gt;
* &amp;lt;node&amp;gt;-pkcs8.key&lt;br /&gt;
* admin.crt&lt;br /&gt;
* admin-pkcs8.crt&lt;br /&gt;
Verify that the &amp;lt;code&amp;gt;opensearch&amp;lt;/code&amp;gt; user is able to at least read all of the certs/keys, or the cluster will not function.&lt;br /&gt;
&lt;br /&gt;
=== Security Plugin Configuration ===&lt;br /&gt;
While the security configuration files exist on all the nodes in the cluster, they are only used once and only by the node where the security initialization is performed.  With that in mine, pick one node (the first master node will do nicely) to edit the configuration files as needed.  There are many things that can be done with these files, but two items in particular should be addressed.  The files are located in the &amp;lt;code&amp;gt;plugins/opensearch-security/securityconfig&amp;lt;/code&amp;gt; directory in the opensearch distribution.&lt;br /&gt;
&lt;br /&gt;
==== Authentication ====&lt;br /&gt;
&amp;lt;code&amp;gt;config.yml&amp;lt;/code&amp;gt; is where the authentication options are established.  This will need to be configured to support your authentication options.  The OpenSearch documentation describes the different options [https://opensearch.org/docs/latest/security-plugin/configuration/configuration/ here].&lt;br /&gt;
&lt;br /&gt;
The default configuration supports basic username/password authentication, but if you wish to use certificate authentication for API clients or ingest pipelines using logstash, you need to enable both &#039;&#039;&#039;http&#039;&#039;&#039; and &#039;&#039;&#039;transport&#039;&#039;&#039; under &amp;lt;code&amp;gt;clientcert_auth_domain&amp;lt;/code&amp;gt;.  Proxy authentication and OpenID Connect authentication is possible as well ... see the documentation.&lt;br /&gt;
&lt;br /&gt;
==== Admin user password ====&lt;br /&gt;
The default password for the admin user is well-known, and should be changed for a production environment.  The OpenSearch documentation provides instructions on how to [https://opensearch.org/docs/latest/security-plugin/configuration/yaml/#internal_usersyml generate passwords] for the &amp;lt;code&amp;gt;internal_users.yml&amp;lt;/code&amp;gt; file.  Note that &#039;&#039;&#039;the admin password cannot be set through the dashboard or the API&#039;&#039;&#039; -- it must be set in this file, and then (re)loaded to take effect.&lt;br /&gt;
&lt;br /&gt;
=== Security Plugin Initialization ===&lt;br /&gt;
Once all security configuration files are finished, they must be loaded into the OpenSearch cluster.  This can only be done once enough of the cluster is up to provide a master node and at least one data node, as the security configuration is loaded into an index in the cluster.  See the instructions below for specific sequencing.  This command will initialize the security plugin:&lt;br /&gt;
 plugins/opensearch-security/tools/securityadmin.sh \&lt;br /&gt;
     -cacert config/&amp;lt;CA cert&amp;gt; -cert config/admin.crt -key config/admin-pkcs8.key \&lt;br /&gt;
     -cd plugins/opensearch-security/securityconfig/ -host master-1.opensearch.localnet -icl -nhnv&lt;br /&gt;
... but again -- wait to do this until the right time below.&lt;br /&gt;
&lt;br /&gt;
=== Starting The Node ===&lt;br /&gt;
Subject to the constraints described in the next section, the only thing left is to start the opensearch service:&lt;br /&gt;
 sudo systemctl enable --now opensearch&lt;br /&gt;
Again, this must be done on each node in the correct sequence ... see below.&lt;br /&gt;
&lt;br /&gt;
== Cluster Bootstrapping ==&lt;br /&gt;
Starting up a multi-node cluster is a bit tricky:&lt;br /&gt;
&lt;br /&gt;
* Master-only nodes have no data&lt;br /&gt;
* Data-only nodes aren&#039;t master eligible&lt;br /&gt;
* Cluster initialization requires indexes to be available&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note that this process does NOT use the demo configuration -- put all the security plugin items in the &amp;lt;code&amp;gt;opensearch.yml&amp;lt;/code&amp;gt; file from the beginning&#039;&#039;&#039;.  This will cause the &amp;lt;code&amp;gt;opensearch-tar-install.sh&amp;lt;/code&amp;gt; script to skip the security initialization -- this is intentional.&lt;br /&gt;
&lt;br /&gt;
What this means is that you have to stand up multiple nodes before anything starts working ... the process should be:&lt;br /&gt;
&lt;br /&gt;
# Install and start what will be the &#039;primary&#039; master ... reference point for cluster startup operations&lt;br /&gt;
# Install and start one of the &#039;hot&#039; data nodes&lt;br /&gt;
# Run the &#039;securityadmin.sh&#039; script (using the command above) to initialize the security subsystem&lt;br /&gt;
# Install/start the other master nodes so that there is resiliency as nodes go up and down&lt;br /&gt;
# install/start the other data nodes to allow replication of the system indexes.&lt;br /&gt;
&lt;br /&gt;
== Install OpenSearch Dashboards ==&lt;br /&gt;
Finally, install the OpenSearch Dashboards using the tarball as well.&lt;br /&gt;
&lt;br /&gt;
Run the following commands as opensearch user:&lt;br /&gt;
 wget [https://artifacts.opensearch.org/releases/bundle/opensearch-dashboards/1.1.0/opensearch-dashboards-1.1.0-linux-x64.tar.gz https://artifacts.opensearch.org/releases/bundle/opensearch-dashboards/1.2.0/opensearch-dashboards-1.2.0-linux-x64.tar.gz]&lt;br /&gt;
 tar -zxf opensearch-dashboards-1.2.0-linux-x64.tar.gz&lt;br /&gt;
&lt;br /&gt;
Configure the &amp;lt;code&amp;gt;opensearch-dashboards.yml&amp;lt;/code&amp;gt; file as needed for your situation.&lt;br /&gt;
&lt;br /&gt;
Create file &amp;lt;code&amp;gt;/etc/systemd/system/opensearch-dashboards.service&amp;lt;/code&amp;gt; (as root) with the following contents:&lt;br /&gt;
 [Unit]&lt;br /&gt;
 Description=OpenSeach-Dasboards&lt;br /&gt;
 &lt;br /&gt;
 [Service]&lt;br /&gt;
 Type=simple&lt;br /&gt;
 User=opensearch&lt;br /&gt;
 Group=opensearch&lt;br /&gt;
 ExecStart=/opt/opensearch/opensearch-dashboards-1.2.0/bin/opensearch-dashboards&lt;br /&gt;
 Restart=always&lt;br /&gt;
 WorkingDirectory=/opt/opensearch/opensearch-dashboards-1.2.0&lt;br /&gt;
 &lt;br /&gt;
 [Install]&lt;br /&gt;
 WantedBy=multi-user.target&lt;br /&gt;
Run the following commands as root:&lt;br /&gt;
 systemctl daemon-reload&lt;br /&gt;
 systemctl start opensearch-dashboards.service &lt;br /&gt;
 systemctl enable opensearch-dashboards.service&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
* https://cryptopoolparty.com/blog/cardano-stake-pool-monitoring-ofo-stack/&lt;br /&gt;
** Describes how to use OpenSearch to monitor another application -- but portions were used to create this document&lt;br /&gt;
*https://github.com/opensearch-project/dashboards-reports/releases/tag/chromium-1.12.0.0&lt;br /&gt;
**download for headless chrome for generating PDF/PNG reports&lt;/div&gt;</summary>
		<author><name>DrEdWilliams</name></author>
	</entry>
	<entry>
		<id>https://wiki.williams-net.org/index.php?title=OpenSearch_Cluster_Installation&amp;diff=663</id>
		<title>OpenSearch Cluster Installation</title>
		<link rel="alternate" type="text/html" href="https://wiki.williams-net.org/index.php?title=OpenSearch_Cluster_Installation&amp;diff=663"/>
		<updated>2021-11-25T19:14:12Z</updated>

		<summary type="html">&lt;p&gt;DrEdWilliams: /* Install Java 11 (optional) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;These instructions describe the creation of a multi-node OpenSearch cluster using the tarball distribution.  The configuration instructions below assume a cluster with the following components:&lt;br /&gt;
&lt;br /&gt;
* Multiple master/ingest nodes&lt;br /&gt;
* Multiple hot data nodes&lt;br /&gt;
* Multiple cold data nodes&lt;br /&gt;
&lt;br /&gt;
The instructions should be adaptable to any multi-node configuration, and even to a uniform node configuration (i.e. three master/ingress/data nodes) -- though that simple configuration does not need the multiple steps required for the more complex deployment.&lt;br /&gt;
&lt;br /&gt;
Read through the entire document before doing anything, as there is a specific order in which things must be done for a successful installation.&lt;br /&gt;
&lt;br /&gt;
== Node Preparation ==&lt;br /&gt;
Each node to be used in the cluster must be prepared to support the OpenSearch installation.&lt;br /&gt;
&lt;br /&gt;
=== Create Opensearch User ===&lt;br /&gt;
Debian/Ubuntu:&lt;br /&gt;
 sudo adduser --system -uid 968 --shell /bin/bash --gecos &#039;OpenSearch User&#039;  --group  --disabled-password --home /opt/opensearch opensearch&lt;br /&gt;
Fedora/RHEL:&lt;br /&gt;
 sudo adduser --system --uid 968 --shell /bin/bash --home-dir /opt/opensearch -m opensearch&lt;br /&gt;
Then add your normal user to the group:&lt;br /&gt;
 sudo usermod -aG opensearch ewilliam&lt;br /&gt;
&lt;br /&gt;
=== Set vm.max_map_count ===&lt;br /&gt;
Create &amp;lt;code&amp;gt;/etc/sysctl.d/vm.maxmap_count.conf&amp;lt;/code&amp;gt; (as root) and add the following line:&lt;br /&gt;
 vm.max_map_count=262144&lt;br /&gt;
Run the following command as root to load the new configuration:&lt;br /&gt;
 sysctl --system&lt;br /&gt;
&lt;br /&gt;
=== Systemd Unit File ===&lt;br /&gt;
One of the big things missing from the tarball distribution is a systemd unit file.  Fortunately, it isn&#039;t difficult to create a simple one that will work.&lt;br /&gt;
&lt;br /&gt;
Create a file &amp;lt;code&amp;gt;/etc/systemd/system/opensearch.service&amp;lt;/code&amp;gt; with the following contents:&lt;br /&gt;
 [Unit]&lt;br /&gt;
 Description=OpenSearch&lt;br /&gt;
 Documentation=&amp;lt;nowiki&amp;gt;https://opensearch.org/docs/&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 Wants=network-online.target&lt;br /&gt;
 After=network-online.target&lt;br /&gt;
 &lt;br /&gt;
 [Service]&lt;br /&gt;
 RuntimeDirectory=opensearch&lt;br /&gt;
 WorkingDirectory=/opt/opensearch/opensearch-1.1.0&lt;br /&gt;
 User=opensearch&lt;br /&gt;
 Group=opensearch&lt;br /&gt;
 &lt;br /&gt;
 ExecStart=/opt/opensearch/opensearch-1.1.0/opensearch-tar-install.sh&lt;br /&gt;
 &lt;br /&gt;
 # StandardOutput is configured to redirect to journalctl since&lt;br /&gt;
 # some error messages may be logged in standard output before&lt;br /&gt;
 # elasticsearch logging system is initialized. Elasticsearch&lt;br /&gt;
 # stores its logs in /var/log/elasticsearch and does not use&lt;br /&gt;
 # journalctl by default. If you also want to enable journalctl&lt;br /&gt;
 # logging, you can simply remove the &amp;quot;quiet&amp;quot; option from ExecStart.&lt;br /&gt;
 StandardOutput=journal&lt;br /&gt;
 StandardError=inherit&lt;br /&gt;
 &lt;br /&gt;
 # Specifies the maximum file descriptor number that can be opened by this process&lt;br /&gt;
 LimitNOFILE=65535&lt;br /&gt;
 &lt;br /&gt;
 # Specifies the maximum number of processes&lt;br /&gt;
 LimitNPROC=4096&lt;br /&gt;
 &lt;br /&gt;
 # Specifies the maximum size of virtual memory&lt;br /&gt;
 LimitAS=infinity&lt;br /&gt;
 &lt;br /&gt;
 # Specifies the maximum file size&lt;br /&gt;
 LimitFSIZE=infinity&lt;br /&gt;
 &lt;br /&gt;
 # Disable timeout logic and wait until process is stopped&lt;br /&gt;
 TimeoutStopSec=0&lt;br /&gt;
 &lt;br /&gt;
 # SIGTERM signal is used to stop the Java process&lt;br /&gt;
 KillSignal=SIGTERM&lt;br /&gt;
 &lt;br /&gt;
 # Send the signal only to the JVM rather than its control group&lt;br /&gt;
 KillMode=process&lt;br /&gt;
 &lt;br /&gt;
 # Java process is never killed&lt;br /&gt;
 SendSIGKILL=no&lt;br /&gt;
 &lt;br /&gt;
 # When a JVM receives a SIGTERM signal it exits with code 143&lt;br /&gt;
 SuccessExitStatus=143&lt;br /&gt;
 &lt;br /&gt;
 # Allow a slow startup before the systemd notifier module kicks in to extend the timeout&lt;br /&gt;
 TimeoutStartSec=75&lt;br /&gt;
 &lt;br /&gt;
 [Install]&lt;br /&gt;
 WantedBy=multi-user.target&lt;br /&gt;
&lt;br /&gt;
== Create Certificates ==&lt;br /&gt;
There are three types of certificates used in OpenSearch:&lt;br /&gt;
&lt;br /&gt;
* CA certificate - one for the whole cluster to validate everything else&lt;br /&gt;
* Node certificate/key - identifies the node for internal cluster communications (transport layer) and data ingest (http layer)&lt;br /&gt;
** the CN must be the FQDN of the node&lt;br /&gt;
** even though OpenSearch doesn&#039;t seem to use them at this point, there should be SANs for the full FQDN, the short hostname, and the node&#039;s IP address&lt;br /&gt;
* User certificate/key - identifies a specific OpenSearch user&lt;br /&gt;
** the CN is a username in OpenSearch (explicit or implicit)&lt;br /&gt;
** username is used to determine roles/privileges in the cluster&lt;br /&gt;
** Need at least one cert for admin authentication&lt;br /&gt;
&lt;br /&gt;
Node and User certificates must all be signed by the cluster CA, and &#039;&#039;&#039;all keys must be in PKCS8 format&#039;&#039;&#039;.  If user certificates are to be used for authentication by logstash, they must be imported (along with the key and CA) into a PKCS12 (.p12) keystore.  The OpenSearch documentation has a good piece on [https://opensearch.org/docs/latest/security-plugin/configuration/generate-certificates/ how to create certificates].&lt;br /&gt;
&lt;br /&gt;
In summary, create the following certificates/keys&lt;br /&gt;
&lt;br /&gt;
# CA certificate/key&lt;br /&gt;
# For each cluster node:&lt;br /&gt;
#* &amp;lt;node&amp;gt;.crt&lt;br /&gt;
#* &amp;lt;node&amp;gt;-pkcs8.key&lt;br /&gt;
# For each user:&lt;br /&gt;
#* &amp;lt;user&amp;gt;.crt&lt;br /&gt;
#* &amp;lt;user&amp;gt;-pkcs8.key&lt;br /&gt;
#* &amp;lt;user&amp;gt;.p12&lt;br /&gt;
&lt;br /&gt;
All these should be created and available for the configuration of each cluster node below.&lt;br /&gt;
&lt;br /&gt;
== Install Opensearch Tarball ==&lt;br /&gt;
The OpenSearch tarball must be installed on each node in the cluster; there is no difference at this point between the installations on the different types of nodes.  Assuming the deployment will use the &amp;lt;code&amp;gt;opensearch&amp;lt;/code&amp;gt; user created above ... change to the &amp;lt;code&amp;gt;opensearch&amp;lt;/code&amp;gt; user (from root):&lt;br /&gt;
 su - opensearch&lt;br /&gt;
 cd ~&lt;br /&gt;
Run the following commands as user &amp;lt;code&amp;gt;opensearch&amp;lt;/code&amp;gt; (from the opensearch home directory &amp;lt;code&amp;gt;/opt/opensearch&amp;lt;/code&amp;gt;):&lt;br /&gt;
 wget https://artifacts.opensearch.org/releases/bundle/opensearch/1.2.0/opensearch-1.2.0-linux-x64.tar.gz&lt;br /&gt;
 tar -xvzf opensearch-1.2.0-linux-x64.tar.gz&lt;br /&gt;
== Configure OpenSearch ==&lt;br /&gt;
Configuration varies depending on the type of node, but these are the places that need to be touched.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;jvm.options&amp;lt;/code&amp;gt; ===&lt;br /&gt;
Set the heap size.  Common practice is that the heap should be between 4GB and half the available memory, but no higher than 32GB.  A minimum configuration might be (assuming the hot data nodes have 32GB installed RAM:&lt;br /&gt;
&lt;br /&gt;
* 4G for master and cold data nodes&lt;br /&gt;
* 16G for hot data nodes&lt;br /&gt;
&lt;br /&gt;
This must be done individually for each node.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;opensearch.yml&amp;lt;/code&amp;gt; ===&lt;br /&gt;
While the OpenSearch software can be rather forgiving for low-security environments, if you turn on full hostname verification, it is rather strict.  The biggest thing to remember is that &#039;&#039;&#039;SAN entries in the node certificates aren&#039;t always respected.&#039;&#039;&#039;  What this boils down to is that if full verification is turned on, you cannot use IP addresses in the &amp;lt;code&amp;gt;opensearch.yml&amp;lt;/code&amp;gt; (or any other configuration file such as the logstash pipelines).&lt;br /&gt;
&lt;br /&gt;
Each node will have a unique version of opensearch.yml due to certificate file names, the role(s) for the node, and the temperature (for data nodes).  The significant parameters in the opensearch.yml file are:&lt;br /&gt;
* &amp;lt;code&amp;gt;cluster.name&amp;lt;/code&amp;gt; - must be identical in all nodes&lt;br /&gt;
* &amp;lt;code&amp;gt;node.name&amp;lt;/code&amp;gt;- can be the hostname, but doesn&#039;t have to be (must be unique)&lt;br /&gt;
* &amp;lt;code&amp;gt;path.data&amp;lt;/code&amp;gt; - data nodes only -- must be unique to the node (i.e if using shared storage, each node must have its own directory on the shared volume)&lt;br /&gt;
* &amp;lt;code&amp;gt;path.logs&amp;lt;/code&amp;gt; - must be unique to the node (same as above)&lt;br /&gt;
* &amp;lt;code&amp;gt;network.host&amp;lt;/code&amp;gt; -- host&#039;s FQDN where all traffic will be received&lt;br /&gt;
**Can be a single hostname or an array of hostnames in &amp;lt;code&amp;gt;[&amp;quot;name&amp;quot;, &amp;quot;name&amp;quot;]&amp;lt;/code&amp;gt; format&lt;br /&gt;
**If you are doing transport-level host verification this CANNOT be an IP -- OpenSearch can&#039;t handle the SANs in the certificates needed to make it work&lt;br /&gt;
* &amp;lt;code&amp;gt;http.port&amp;lt;/code&amp;gt; -- leave it as the default (&amp;lt;code&amp;gt;9200&amp;lt;/code&amp;gt;) but uncomment it to lock it in&lt;br /&gt;
* &amp;lt;code&amp;gt;discovery.seed_hosts&amp;lt;/code&amp;gt; -- FQDN for all the masters (same for all nodes) -- only used for cluster bootstrap&lt;br /&gt;
* &amp;lt;code&amp;gt;cluster.initial_master_nodes&amp;lt;/code&amp;gt; -- put the master node names here (not the hostnames) -- same for all nodes&lt;br /&gt;
* &amp;lt;code&amp;gt;node.[master|data|ingest|remote]&amp;lt;/code&amp;gt; - set the type of the node (specify all four)&lt;br /&gt;
* &amp;lt;code&amp;gt;node.attr.temp&amp;lt;/code&amp;gt; - (data nodes only) defines data storage tiers (&amp;lt;code&amp;gt;hot&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;warm&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;cold&amp;lt;/code&amp;gt;)&lt;br /&gt;
The stock configuration file has most of these specified -- edit the file to fit the configuration of the node.&lt;br /&gt;
&lt;br /&gt;
The security configuration must be added next.  Since we are not using the demo security as our template, all the relevant entries must be added now.  Copy this block into the end of the stock opensearch.yml, editing as needed to provide the relevant certificate file names:&lt;br /&gt;
 node.master: true&lt;br /&gt;
 node.ingest: true&lt;br /&gt;
 node.data: false&lt;br /&gt;
 #node.remote: false&lt;br /&gt;
 &lt;br /&gt;
 #node.attr.temp: hot&lt;br /&gt;
 &lt;br /&gt;
 ######## Start OpenSearch Security Configuration ########&lt;br /&gt;
 plugins.security.ssl.transport.pemcert_filepath: &amp;lt;node&amp;gt;.crt&lt;br /&gt;
 plugins.security.ssl.transport.pemkey_filepath: &amp;lt;node&amp;gt;-pkcs8.key&lt;br /&gt;
 plugins.security.ssl.transport.pemtrustedcas_filepath: &amp;lt;CAcert&amp;gt;&lt;br /&gt;
 plugins.security.ssl.transport.enforce_hostname_verification: true&lt;br /&gt;
 &lt;br /&gt;
 plugins.security.ssl.http.enabled: true&lt;br /&gt;
 plugins.security.ssl.http.pemcert_filepath: &amp;lt;node&amp;gt;.crt&lt;br /&gt;
 plugins.security.ssl.http.pemkey_filepath: &amp;lt;node&amp;gt;-pkcs8.key&lt;br /&gt;
 plugins.security.ssl.http.pemtrustedcas_filepath: &amp;lt;CAcert&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 plugins.security.allow_unsafe_democertificates: false&lt;br /&gt;
 plugins.security.allow_default_init_securityindex: true&lt;br /&gt;
 &lt;br /&gt;
 # at least one cert -- must be an EXACT copy of the DN for the certificates to be used for admin auth&lt;br /&gt;
 plugins.security.authcz.admin_dn:&lt;br /&gt;
   - CN=Admin,O=OpenSearch,C=US&lt;br /&gt;
 &lt;br /&gt;
 # these must be EXACT copies of the DN for the node certificates&lt;br /&gt;
 plugins.security.nodes_dn:&lt;br /&gt;
   - CN=master-1.opensearch.localnet,O=OpenSearch,C=US&lt;br /&gt;
   - CN=data-hot-1.opensearch.localnet,O=OpenSearch,C=US&lt;br /&gt;
 &lt;br /&gt;
 # this is all boiler plate ... no modifications needed&lt;br /&gt;
 plugins.security.audit.type: internal_opensearch&lt;br /&gt;
 plugins.security.enable_snapshot_restore_privilege: true&lt;br /&gt;
 plugins.security.check_snapshot_restore_write_privileges: true&lt;br /&gt;
 plugins.security.restapi.roles_enabled: [&amp;quot;all_access&amp;quot;, &amp;quot;security_rest_api_access&amp;quot;]&lt;br /&gt;
 plugins.security.system_indices.enabled: true&lt;br /&gt;
 # this next bit should ALL be on one line ...&lt;br /&gt;
 plugins.security.system_indices.indices: [&amp;quot;.opendistro-alerting-config&amp;quot;, &amp;quot;.opendistro-alerting-alert*&amp;quot;, &amp;quot;.opendistro-anomaly-results*&amp;quot;, &amp;quot;.opendistro-anomaly-detector*&amp;quot;, &amp;quot;.opendistro-anomaly-checkpoints&amp;quot;, &amp;quot;.opendistro-anomaly-detection-state&amp;quot;, &amp;quot;.opendistro-reports-*&amp;quot;, &amp;quot;.opendistro-notifications-*&amp;quot;, &amp;quot;.opendistro-notebooks&amp;quot;, &amp;quot;.opendistro-asynchronous-search-response*&amp;quot;, &amp;quot;.replication-metadata-store&amp;quot;]&lt;br /&gt;
 &lt;br /&gt;
 node.max_local_storage_nodes: 3&lt;br /&gt;
 &lt;br /&gt;
 ######## End OpenSearch Security Configuration ########&lt;br /&gt;
Note that there are two sections where the DNs from the certificates must be provided to enable admin authentication for security configuration, and for validating the nodes that will be part of the cluster.  You can easily show the DNs for your certificates using this command:&lt;br /&gt;
 openssl x509 -subject -nameopt RFC2253 -noout -in &amp;lt;cert file name&amp;gt;&lt;br /&gt;
The DN for the admin cert and the DNs for the node certs go in separate sections as shown above.  Add all the cluster nodes into the nodes_dn section -- this must be the same for all nodes or they will not be able to communicate.&lt;br /&gt;
&lt;br /&gt;
=== Certificates ===&lt;br /&gt;
Copy the following certificates/keys that were created previously into the config directory of each node:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;CAcert&amp;gt;&lt;br /&gt;
* &amp;lt;node&amp;gt;.crt&lt;br /&gt;
* &amp;lt;node&amp;gt;-pkcs8.key&lt;br /&gt;
* admin.crt&lt;br /&gt;
* admin-pkcs8.crt&lt;br /&gt;
Verify that the &amp;lt;code&amp;gt;opensearch&amp;lt;/code&amp;gt; user is able to at least read all of the certs/keys, or the cluster will not function.&lt;br /&gt;
&lt;br /&gt;
=== Security Plugin Configuration ===&lt;br /&gt;
While the security configuration files exist on all the nodes in the cluster, they are only used once and only by the node where the security initialization is performed.  With that in mine, pick one node (the first master node will do nicely) to edit the configuration files as needed.  There are many things that can be done with these files, but two items in particular should be addressed.  The files are located in the &amp;lt;code&amp;gt;plugins/opensearch-security/securityconfig&amp;lt;/code&amp;gt; directory in the opensearch distribution.&lt;br /&gt;
&lt;br /&gt;
==== Authentication ====&lt;br /&gt;
&amp;lt;code&amp;gt;config.yml&amp;lt;/code&amp;gt; is where the authentication options are established.  This will need to be configured to support your authentication options.  The OpenSearch documentation describes the different options [https://opensearch.org/docs/latest/security-plugin/configuration/configuration/ here].&lt;br /&gt;
&lt;br /&gt;
The default configuration supports basic username/password authentication, but if you wish to use certificate authentication for API clients or ingest pipelines using logstash, you need to enable both &#039;&#039;&#039;http&#039;&#039;&#039; and &#039;&#039;&#039;transport&#039;&#039;&#039; under &amp;lt;code&amp;gt;clientcert_auth_domain&amp;lt;/code&amp;gt;.  Proxy authentication and OpenID Connect authentication is possible as well ... see the documentation.&lt;br /&gt;
&lt;br /&gt;
==== Admin user password ====&lt;br /&gt;
The default password for the admin user is well-known, and should be changed for a production environment.  The OpenSearch documentation provides instructions on how to [https://opensearch.org/docs/latest/security-plugin/configuration/yaml/#internal_usersyml generate passwords] for the &amp;lt;code&amp;gt;internal_users.yml&amp;lt;/code&amp;gt; file.  Note that &#039;&#039;&#039;the admin password cannot be set through the dashboard or the API&#039;&#039;&#039; -- it must be set in this file, and then (re)loaded to take effect.&lt;br /&gt;
&lt;br /&gt;
=== Security Plugin Initialization ===&lt;br /&gt;
Once all security configuration files are finished, they must be loaded into the OpenSearch cluster.  This can only be done once enough of the cluster is up to provide a master node and at least one data node, as the security configuration is loaded into an index in the cluster.  See the instructions below for specific sequencing.  This command will initialize the security plugin:&lt;br /&gt;
 plugins/opensearch-security/tools/securityadmin.sh \&lt;br /&gt;
     -cacert config/&amp;lt;CA cert&amp;gt; -cert config/admin.crt -key config/admin-pkcs8.key \&lt;br /&gt;
     -cd plugins/opensearch-security/securityconfig/ -host master-1.opensearch.localnet -icl -nhnv&lt;br /&gt;
... but again -- wait to do this until the right time below.&lt;br /&gt;
&lt;br /&gt;
=== Starting The Node ===&lt;br /&gt;
Subject to the constraints described in the next section, the only thing left is to start the opensearch service:&lt;br /&gt;
 sudo systemctl enable --now opensearch&lt;br /&gt;
Again, this must be done on each node in the correct sequence ... see below.&lt;br /&gt;
&lt;br /&gt;
== Cluster Bootstrapping ==&lt;br /&gt;
Starting up a multi-node cluster is a bit tricky:&lt;br /&gt;
&lt;br /&gt;
* Master-only nodes have no data&lt;br /&gt;
* Data-only nodes aren&#039;t master eligible&lt;br /&gt;
* Cluster initialization requires indexes to be available&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note that this process does NOT use the demo configuration -- put all the security plugin items in the &amp;lt;code&amp;gt;opensearch.yml&amp;lt;/code&amp;gt; file from the beginning&#039;&#039;&#039;.  This will cause the &amp;lt;code&amp;gt;opensearch-tar-install.sh&amp;lt;/code&amp;gt; script to skip the security initialization -- this is intentional.&lt;br /&gt;
&lt;br /&gt;
What this means is that you have to stand up multiple nodes before anything starts working ... the process should be:&lt;br /&gt;
&lt;br /&gt;
# Install and start what will be the &#039;primary&#039; master ... reference point for cluster startup operations&lt;br /&gt;
# Install and start one of the &#039;hot&#039; data nodes&lt;br /&gt;
# Run the &#039;securityadmin.sh&#039; script (using the command above) to initialize the security subsystem&lt;br /&gt;
# Install/start the other master nodes so that there is resiliency as nodes go up and down&lt;br /&gt;
# install/start the other data nodes to allow replication of the system indexes.&lt;br /&gt;
&lt;br /&gt;
== Install OpenSearch Dashboards ==&lt;br /&gt;
Finally, install the OpenSearch Dashboards using the tarball as well.&lt;br /&gt;
&lt;br /&gt;
Run the following commands as opensearch user:&lt;br /&gt;
 wget [https://artifacts.opensearch.org/releases/bundle/opensearch-dashboards/1.1.0/opensearch-dashboards-1.1.0-linux-x64.tar.gz https://artifacts.opensearch.org/releases/bundle/opensearch-dashboards/1.2.0/opensearch-dashboards-1.2.0-linux-x64.tar.gz]&lt;br /&gt;
 tar -zxf opensearch-dashboards-1.2.0-linux-x64.tar.gz&lt;br /&gt;
&lt;br /&gt;
Configure the &amp;lt;code&amp;gt;opensearch-dashboards.yml&amp;lt;/code&amp;gt; file as needed for your situation.&lt;br /&gt;
&lt;br /&gt;
Create file &amp;lt;code&amp;gt;/etc/systemd/system/opensearch-dashboards.service&amp;lt;/code&amp;gt; (as root) with the following contents:&lt;br /&gt;
 [Unit]&lt;br /&gt;
 Description=OpenSeach-Dasboards&lt;br /&gt;
 &lt;br /&gt;
 [Service]&lt;br /&gt;
 Type=simple&lt;br /&gt;
 User=opensearch&lt;br /&gt;
 Group=opensearch&lt;br /&gt;
 ExecStart=/opt/opensearch/opensearch-dashboards-1.2.0/bin/opensearch-dashboards&lt;br /&gt;
 Restart=always&lt;br /&gt;
 WorkingDirectory=/opt/opensearch/opensearch-dashboards-1.2.0&lt;br /&gt;
 &lt;br /&gt;
 [Install]&lt;br /&gt;
 WantedBy=multi-user.target&lt;br /&gt;
Run the following commands as root:&lt;br /&gt;
 systemctl daemon-reload&lt;br /&gt;
 systemctl start opensearch-dashboards.service &lt;br /&gt;
 systemctl enable opensearch-dashboards.service&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
* https://cryptopoolparty.com/blog/cardano-stake-pool-monitoring-ofo-stack/&lt;br /&gt;
** Describes how to use OpenSearch to monitor another application -- but portions were used to create this document&lt;br /&gt;
*https://github.com/opensearch-project/dashboards-reports/releases/tag/chromium-1.12.0.0&lt;br /&gt;
**download for headless chrome for generating PDF/PNG reports&lt;/div&gt;</summary>
		<author><name>DrEdWilliams</name></author>
	</entry>
	<entry>
		<id>https://wiki.williams-net.org/index.php?title=Pages_that_need_to_be_updated&amp;diff=662</id>
		<title>Pages that need to be updated</title>
		<link rel="alternate" type="text/html" href="https://wiki.williams-net.org/index.php?title=Pages_that_need_to_be_updated&amp;diff=662"/>
		<updated>2021-11-25T13:14:46Z</updated>

		<summary type="html">&lt;p&gt;DrEdWilliams: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[SSH Host Key Management]]&lt;br /&gt;
&lt;br /&gt;
[[Diggle]] - manage configuration in GitLab&lt;br /&gt;
&lt;br /&gt;
[[MediaWiki Deployment]] (needs to be created)&lt;br /&gt;
&lt;br /&gt;
Update [[WilliamsNet Architecture|Architecture]] to reflect [[OpenSearch]] and [[Elastic Cluster|Elastic]] clusters&lt;br /&gt;
&lt;br /&gt;
[[Synergy Installation]] (needs to be created)&lt;/div&gt;</summary>
		<author><name>DrEdWilliams</name></author>
	</entry>
	<entry>
		<id>https://wiki.williams-net.org/index.php?title=Fedora_33_-_Workstation_Installation&amp;diff=661</id>
		<title>Fedora 33 - Workstation Installation</title>
		<link rel="alternate" type="text/html" href="https://wiki.williams-net.org/index.php?title=Fedora_33_-_Workstation_Installation&amp;diff=661"/>
		<updated>2021-11-25T13:05:44Z</updated>

		<summary type="html">&lt;p&gt;DrEdWilliams: /* System Configuration */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;After doing the [[Basic Fedora 31+ Installation]], these are the steps required to get the workstation up to general functionality.&lt;br /&gt;
&lt;br /&gt;
It is assumed that either the Fedora Workstation (Gnome desktop) or KDE Plasma spin is used as the base distribution and the desktop is configured and functioning properly.&lt;br /&gt;
&lt;br /&gt;
== System Configuration ==&lt;br /&gt;
In addition to the basic [[Basic Fedora 31+ Installation]] and [[Common Post-Install]] instructions:&lt;br /&gt;
* Select KDE as the desktop environment&lt;br /&gt;
*Mount the /files and /backup filesystems from storage1 (NFSv4 mount)&lt;br /&gt;
* Configure (or verify) the network devices:&lt;br /&gt;
** WilliamsNet (10.0.0.0/24)&lt;br /&gt;
** StorageNet (10.1.0.0/24) - optional if needed (if device is available or VLAN device definition)&lt;br /&gt;
** iSCSINet (10.2.0.0/24) - optional if needed (may require VLAN device definition)&lt;br /&gt;
* [[CUDA + NVIDIA drivers]] (if NVIDIA GPU installed)&lt;br /&gt;
&lt;br /&gt;
== General Utilities ==&lt;br /&gt;
A collection of tools that are useful in a workstation; some may already be installed, but just covering the bases:&lt;br /&gt;
* [http://www.webmin.com/download.html Webmin] - web-based system administration&lt;br /&gt;
* Google Chrome&lt;br /&gt;
** use the repo-based installation on the Google instructions page so you get updates&lt;br /&gt;
** make it the default browser by searching for &#039;Application&#039; in the KDE settings app and selecting it for the default web browser. &lt;br /&gt;
* pdsh - parallel shell&lt;br /&gt;
** see [https://www.admin-magazine.com/HPC/Articles/pdsh-Parallel-Shell pdsh article] in ADMIN Magazine&lt;br /&gt;
** in fedora repo -- need to specify the SSH module since it isn&#039;t included by default (??):  &lt;br /&gt;
 sudo dnf install -y pdsh pdsh-rcmd-ssh&lt;br /&gt;
* Synergy (see [[Synergy Installation]])&lt;br /&gt;
* Java&lt;br /&gt;
** either the openjdk in the fedora repo or the &#039;real stuff&#039; from Oracle&lt;br /&gt;
** Oracle Java 8 (the real thing) is required to support java web start applications (like the EquaLogic Group Manager tool)&lt;br /&gt;
* MATE or gnome Terminal -- it&#039;s just better than the KDE konsole app, though konsole has gotten a lot better&lt;br /&gt;
 sudo dnf install -y gnome-terminal&lt;br /&gt;
&lt;br /&gt;
== Communications and Collaboration Tools ==&lt;br /&gt;
There are a lot ... but these cover much of the landscape:&lt;br /&gt;
* Microsoft Teams&lt;br /&gt;
** download client from https://teams.microsoft.com&lt;br /&gt;
** default install will establish a teams repo to facilitate updates&lt;br /&gt;
* Slack&lt;br /&gt;
** download client from https://slack.com/download&lt;br /&gt;
* Zoom&lt;br /&gt;
** download client from https://zoom.com&lt;br /&gt;
* Kopete (Jabber client)&lt;br /&gt;
** in fedora repo&lt;br /&gt;
* VMware Horizon Client (for access to SAIC VDS)&lt;br /&gt;
** download from SAIC VDS webpage&lt;br /&gt;
&lt;br /&gt;
== Development Tools ==&lt;br /&gt;
* VS Code&lt;br /&gt;
** download client at https://code.visualstudio.com/download&lt;br /&gt;
** will create a repo to get updates&lt;br /&gt;
** if possible, copy &amp;quot;.vscode*&amp;quot; directories from an existing configuration&lt;br /&gt;
** &#039;&#039;&#039;&#039;&#039;LOTS&#039;&#039;&#039;&#039;&#039; of plugins/modules/addons/extensions ... easy to waste a lot of time configuring&lt;br /&gt;
* PodMan -- rootless docker replacement ... in the repo&lt;br /&gt;
* Docker-CE -- is this even available?&lt;br /&gt;
&lt;br /&gt;
== Extended/Optional Stuff ==&lt;br /&gt;
This is not intended to be a complete list of all the random/useful stuff I do on workstations, but just a catch-all for links and reminders&lt;br /&gt;
&lt;br /&gt;
=== Enable RPM fusion ===&lt;br /&gt;
If not already done as part of the NVIDIA/CUDA driver debacle, install it -- there are useful things there&lt;br /&gt;
 sudo dnf install https://download1.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpm&lt;br /&gt;
 sudo dnf install https://download1.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-$(rpm -E %fedora).noarch.rpm&lt;/div&gt;</summary>
		<author><name>DrEdWilliams</name></author>
	</entry>
	<entry>
		<id>https://wiki.williams-net.org/index.php?title=Pages_that_need_to_be_updated&amp;diff=660</id>
		<title>Pages that need to be updated</title>
		<link rel="alternate" type="text/html" href="https://wiki.williams-net.org/index.php?title=Pages_that_need_to_be_updated&amp;diff=660"/>
		<updated>2021-11-25T13:04:10Z</updated>

		<summary type="html">&lt;p&gt;DrEdWilliams: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[SSH Host Key Management]]&lt;br /&gt;
&lt;br /&gt;
[[Diggle]] - manage configuration in GitLab&lt;br /&gt;
&lt;br /&gt;
[[MediaWiki Deployment]] (needs to be created)&lt;br /&gt;
&lt;br /&gt;
Update Architecture to reflect [[OpenSearch]] and Elastic clusters&lt;br /&gt;
&lt;br /&gt;
[[Synergy Installation]] (needs to be created)&lt;/div&gt;</summary>
		<author><name>DrEdWilliams</name></author>
	</entry>
	<entry>
		<id>https://wiki.williams-net.org/index.php?title=Basic_Fedora_31%2B_Installation&amp;diff=659</id>
		<title>Basic Fedora 31+ Installation</title>
		<link rel="alternate" type="text/html" href="https://wiki.williams-net.org/index.php?title=Basic_Fedora_31%2B_Installation&amp;diff=659"/>
		<updated>2021-11-25T12:56:42Z</updated>

		<summary type="html">&lt;p&gt;DrEdWilliams: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Fedora Distribution Install ==&lt;br /&gt;
Fedora 31 install from DVD install disk - this process should work for most (if not all) the variants of Fedora (Workstation, server, KDE Plasma).&lt;br /&gt;
&lt;br /&gt;
During install process:&lt;br /&gt;
* use custom formatting&lt;br /&gt;
* set partition type to &#039;standard&#039;&lt;br /&gt;
* click on &#039;automatically create partitions&#039;&lt;br /&gt;
* delete /home partition and increase size of / to fill the disk&lt;br /&gt;
* change all filesystem types to &#039;xfs&#039;&lt;br /&gt;
* set hostname (if known) &lt;br /&gt;
* enable all basic network interfaces (do not rename -- it will crash the installer)&lt;br /&gt;
&lt;br /&gt;
== Basic system prep ==&lt;br /&gt;
Most of the initial configuration is now contained in a script that can be executed directly from the config server as root on the target system:&lt;br /&gt;
&lt;br /&gt;
 curl -s http://config/config/fedora-basic-config.sh | bash&lt;br /&gt;
&lt;br /&gt;
The contents of this script are included here for reference, though updates to the script may occur without updates to this page:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#!/bin/sh&lt;br /&gt;
#&lt;br /&gt;
# script to do the basic install of a centos7 headless server&lt;br /&gt;
#&lt;br /&gt;
# Assumptions:&lt;br /&gt;
#  - this is run as root immediately after the install has completed&lt;br /&gt;
#  - the hostname has been set as desired before this script is run&lt;br /&gt;
#  - an administrator account &#039;ewilliam&#039; was created during installation&lt;br /&gt;
&lt;br /&gt;
CONFIG=http://kube202/config&lt;br /&gt;
&lt;br /&gt;
# first -- install all the basic necessities (some may already be there)&lt;br /&gt;
yum -y install net-tools rsync zsh yum-utils mlocate drpm&lt;br /&gt;
yum -y install sshfs nfs-utils ssmtp psmisc git&lt;br /&gt;
yum -y remove firewalld postfix&lt;br /&gt;
&lt;br /&gt;
# things that seem to not be included in the server version?&lt;br /&gt;
yum -y install cronie cronie-anacron&lt;br /&gt;
systemctl enable --now crond&lt;br /&gt;
&lt;br /&gt;
# Enable automatic updates.  &lt;br /&gt;
#  Parameters can be set in the config files &#039;/etc/dnf/automatic.conf&#039;&lt;br /&gt;
yum -y install dnf-automatic&lt;br /&gt;
systemctl enable --now dnf-automatic.timer&lt;br /&gt;
&lt;br /&gt;
# now get all the updates&lt;br /&gt;
yum -y update&lt;br /&gt;
&lt;br /&gt;
# now disable SELinux (no comment)&lt;br /&gt;
sed -i &#039;s/=enforcing/=disabled/g&#039; /etc/selinux/config&lt;br /&gt;
setenforce 0&lt;br /&gt;
&lt;br /&gt;
# Enable the SSH server (why it&#039;s not enabled by default is strange ...)&lt;br /&gt;
systemctl enable --now sshd&lt;br /&gt;
&lt;br /&gt;
# make sudo passwordless for group wheel&lt;br /&gt;
echo &amp;quot;%wheel ALL=(ALL) NOPASSWD:ALL&amp;quot; &amp;gt;&amp;gt; /etc/sudoers.d/91-wheel-NOPASSWD&lt;br /&gt;
&lt;br /&gt;
# now that zsh is installed, make it the default&lt;br /&gt;
chsh -s /bin/zsh&lt;br /&gt;
chsh -s /bin/zsh ewilliam&lt;br /&gt;
&lt;br /&gt;
# copy the standard zsh config files&lt;br /&gt;
curl -s $CONFIG/centos7/.zshrc -o /root/.zshrc&lt;br /&gt;
curl -s $CONFIG/centos7/.zshrc -o /home/ewilliam/.zshrc&lt;br /&gt;
chown ewilliam.ewilliam /home/ewilliam/.zshrc&lt;br /&gt;
&lt;br /&gt;
# load ssh known_hosts from the config server&lt;br /&gt;
mkdir -p /root/.ssh&lt;br /&gt;
curl -s $CONFIG/ssh/known_hosts -o /root/.ssh/known_hosts&lt;br /&gt;
mkdir -p /home/ewilliam/.ssh&lt;br /&gt;
curl -s $CONFIG/ssh/known_hosts -o /home/ewilliam/.ssh/known_hosts&lt;br /&gt;
chown -R ewilliam.ewilliam /home/ewilliam/.ssh&lt;br /&gt;
&lt;br /&gt;
# get backup scripts&lt;br /&gt;
curl -s $CONFIG/centos7/backup -o /etc/cron.daily/backup&lt;br /&gt;
curl -s $CONFIG/centos7/rsync_backup.sh -o /usr/local/bin/rsync_backup.sh&lt;br /&gt;
chmod +x /usr/local/bin/rsync_backup.sh&lt;br /&gt;
&lt;br /&gt;
# configure log server&lt;br /&gt;
curl -s $CONFIG/centos7/99-remotelog.conf -o /etc/rsyslog.d/99-remotelog.conf&lt;br /&gt;
systemctl restart rsyslog&lt;br /&gt;
&lt;br /&gt;
# enable mail to the central email server&lt;br /&gt;
echo &amp;quot;root: ewilliam@williams.localnet&amp;quot; &amp;gt;&amp;gt; /etc/aliases&lt;br /&gt;
echo &amp;quot;ewilliam: ewilliam@williams.localnet&amp;quot; &amp;gt;&amp;gt; /etc/aliases&lt;br /&gt;
&lt;br /&gt;
# get the standard /etc/hosts file&lt;br /&gt;
curl $CONFIG/hosts -o /etc/hosts&lt;br /&gt;
&lt;br /&gt;
# install metricbeat&lt;br /&gt;
curl -s $CONFIG/centos7/elastic.repo &amp;gt; /etc/yum.repos.d/elastic.repo&lt;br /&gt;
yum -y install metricbeat&lt;br /&gt;
curl -s $CONFIG/centos7/metricbeat.yml &amp;gt; /etc/metricbeat/metricbeat.yml&lt;br /&gt;
&lt;br /&gt;
# install the host/known_hosts synchronization&lt;br /&gt;
curl -s $CONFIG/host_check.sh &amp;gt; /etc/cron.hourly/host_check&lt;br /&gt;
chmod +x /etc/cron.hourly/host_check&lt;br /&gt;
&lt;br /&gt;
# now reboot&lt;br /&gt;
reboot&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Next Steps ==&lt;br /&gt;
The rest of the installation process is not OS-dependent and is described [[Common Post-Install|here]].&lt;/div&gt;</summary>
		<author><name>DrEdWilliams</name></author>
	</entry>
	<entry>
		<id>https://wiki.williams-net.org/index.php?title=Basic_CentOS_7_Installation&amp;diff=658</id>
		<title>Basic CentOS 7 Installation</title>
		<link rel="alternate" type="text/html" href="https://wiki.williams-net.org/index.php?title=Basic_CentOS_7_Installation&amp;diff=658"/>
		<updated>2021-11-25T12:56:11Z</updated>

		<summary type="html">&lt;p&gt;DrEdWilliams: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== CentOS Distribution Install ==&lt;br /&gt;
Centos 7 minimal install from DVD install disk&lt;br /&gt;
During install process:&lt;br /&gt;
* use custom formatting&lt;br /&gt;
* set partition type to &#039;standard&#039;&lt;br /&gt;
* click on &#039;automatically create partitions&lt;br /&gt;
* delete /home partition and increase size of / to fill the disk&lt;br /&gt;
* set hostname (if known) &lt;br /&gt;
* enable all basic network interfaces (do not rename -- it will crash the installer)&lt;br /&gt;
&lt;br /&gt;
== Basic system prep ==&lt;br /&gt;
Most of the initial configuration is now contained in a script that can be executed directly from the config server as root on the target system:&lt;br /&gt;
&lt;br /&gt;
 curl -s http://config/config/centos7-basic-config.sh | bash&lt;br /&gt;
&lt;br /&gt;
The contents of this script are included here for reference, though updates to the script may occur without updates to this page:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#!/bin/sh&lt;br /&gt;
#&lt;br /&gt;
# script to do the basic install of a centos7 headless server&lt;br /&gt;
#&lt;br /&gt;
# Assumptions:&lt;br /&gt;
#  - this is run as root immediately after the install has completed&lt;br /&gt;
#  - the hostname has been set as desired before this script is run&lt;br /&gt;
#  - an administrator account &#039;ewilliam&#039; was created during installation&lt;br /&gt;
&lt;br /&gt;
CONFIG=http://config/config&lt;br /&gt;
&lt;br /&gt;
# first -- install all the basic necessities (some may already be there)&lt;br /&gt;
yum -y install net-tools rsync zsh epel-release yum-cron yum-utils mlocate deltarpm&lt;br /&gt;
yum -y install sshfs nfs-utils ssmtp psmisc&lt;br /&gt;
yum -y remove firewalld postfix&lt;br /&gt;
yum autoremove -y NetworkManager NetworkManager-libnm&lt;br /&gt;
systemctl enable --now yum-cron&lt;br /&gt;
yum -y update&lt;br /&gt;
&lt;br /&gt;
# now disable SELinux (no comment)&lt;br /&gt;
sed -i &#039;s/=enforcing/=disabled/g&#039; /etc/selinux/config&lt;br /&gt;
setenforce 0&lt;br /&gt;
&lt;br /&gt;
# make sudo passwordless for group wheel&lt;br /&gt;
echo &amp;quot;%wheel ALL=(ALL) NOPASSWD:ALL&amp;quot; &amp;gt;&amp;gt; /etc/sudoers.d/91-wheel-NOPASSWD&lt;br /&gt;
&lt;br /&gt;
# now that zsh is installed, make it the default&lt;br /&gt;
chsh -s /bin/zsh&lt;br /&gt;
chsh -s /bin/zsh ewilliam&lt;br /&gt;
&lt;br /&gt;
# copy the standard zsh config files&lt;br /&gt;
curl -s $CONFIG/centos7/.zshrc -o /root/.zshrc&lt;br /&gt;
curl -s $CONFIG/centos7/.zshrc -o /home/ewilliam/.zshrc&lt;br /&gt;
chown ewilliam.ewilliam /home/ewilliam/.zshrc&lt;br /&gt;
&lt;br /&gt;
# load ssh known_hosts from the config server&lt;br /&gt;
mkdir -p /root/.ssh&lt;br /&gt;
curl -s $CONFIG/ssh/known_hosts -o /root/.ssh/known_hosts&lt;br /&gt;
mkdir -p /home/ewilliam/.ssh&lt;br /&gt;
curl -s $CONFIG/ssh/known_hosts -o /home/ewilliam/.ssh/known_hosts&lt;br /&gt;
&lt;br /&gt;
# get backup scripts&lt;br /&gt;
curl -s $CONFIG/centos7/backup -o /etc/cron.daily/backup&lt;br /&gt;
curl -s $CONFIG/centos7/rsync_backup.sh -o /usr/local/bin/rsync_backup.sh&lt;br /&gt;
chmod +x /usr/local/bin/rsync_backup.sh&lt;br /&gt;
&lt;br /&gt;
# configure log server&lt;br /&gt;
curl -s $CONFIG/centos7/99-remotelog.conf -o /etc/rsyslog.d/99-remotelog.conf&lt;br /&gt;
systemctl restart rsyslog&lt;br /&gt;
&lt;br /&gt;
# enable mail to the central email server&lt;br /&gt;
echo &amp;quot;root: ewilliam@williams.localnet&amp;quot; &amp;gt;&amp;gt; /etc/aliases&lt;br /&gt;
echo &amp;quot;ewilliam: ewilliam@williams.localnet&amp;quot; &amp;gt;&amp;gt; /etc/aliases&lt;br /&gt;
&lt;br /&gt;
# get the standard /etc/hosts file&lt;br /&gt;
curl $CONFIG/hosts -o /etc/hosts&lt;br /&gt;
&lt;br /&gt;
# install metricbeat&lt;br /&gt;
curl -s $CONFIG/centos7/elastic.repo &amp;gt; /etc/yum.repos.d/elastic.repo&lt;br /&gt;
yum -y install metricbeat&lt;br /&gt;
curl -s $CONFIG/centos7/metricbeat.yml &amp;gt; /etc/metricbeat/metricbeat.yml&lt;br /&gt;
&lt;br /&gt;
# install the host/known_hosts synchronization&lt;br /&gt;
curl -s $CONFIG/host_check.sh &amp;gt; /etc/cron.hourly/host_check&lt;br /&gt;
chmod +x /etc/cron.hourly/host_check&lt;br /&gt;
&lt;br /&gt;
# now reboot&lt;br /&gt;
reboot&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Next Steps ==&lt;br /&gt;
The rest of the installation process is not OS-dependent and is described [[Common Post-Install|here]].&lt;/div&gt;</summary>
		<author><name>DrEdWilliams</name></author>
	</entry>
</feed>