<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.williams-net.org/index.php?action=history&amp;feed=atom&amp;title=GitLab_V18_Upgrade</id>
	<title>GitLab V18 Upgrade - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.williams-net.org/index.php?action=history&amp;feed=atom&amp;title=GitLab_V18_Upgrade"/>
	<link rel="alternate" type="text/html" href="https://wiki.williams-net.org/index.php?title=GitLab_V18_Upgrade&amp;action=history"/>
	<updated>2026-06-01T04:50:26Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.40.1</generator>
	<entry>
		<id>https://wiki.williams-net.org/index.php?title=GitLab_V18_Upgrade&amp;diff=721&amp;oldid=prev</id>
		<title>DrEdWilliams at 22:52, 13 June 2025</title>
		<link rel="alternate" type="text/html" href="https://wiki.williams-net.org/index.php?title=GitLab_V18_Upgrade&amp;diff=721&amp;oldid=prev"/>
		<updated>2025-06-13T22:52:09Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 22:52, 13 June 2025&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l3&quot;&gt;Line 3:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 3:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* deleting the database PVCs&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* deleting the database PVCs&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* performing the upgrade (without the migrations step)&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* performing the upgrade (without the migrations step)&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* running their database_upgrade script again to restore the database and &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;restarting &lt;/del&gt;the services.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* running their database_upgrade script again to restore the database and &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;restart &lt;/ins&gt;the services.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt; &lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt; &lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;All this is documented on their documentation site:&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt; &lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt; https://docs.gitlab.com/charts/installation/database_upgrade/#steps-for-upgrading-the-bundled-postgresql&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br/&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br/&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;This is all well and good -- it&amp;#039;s been required before ... but the postgresql user in the new configuration doesn&amp;#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;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;This is all well and good -- it&amp;#039;s been required before ... but the postgresql user in the new configuration doesn&amp;#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;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>DrEdWilliams</name></author>
	</entry>
	<entry>
		<id>https://wiki.williams-net.org/index.php?title=GitLab_V18_Upgrade&amp;diff=720&amp;oldid=prev</id>
		<title>DrEdWilliams: Created page with &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...&quot;</title>
		<link rel="alternate" type="text/html" href="https://wiki.williams-net.org/index.php?title=GitLab_V18_Upgrade&amp;diff=720&amp;oldid=prev"/>
		<updated>2025-06-13T22:47:56Z</updated>

		<summary type="html">&lt;p&gt;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;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&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&amp;#039;s been required before ... but the postgresql user in the new configuration doesn&amp;#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&amp;#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&amp;#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&amp;#039;t from GitLab&amp;#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&amp;#039;re using Helm, you&amp;#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&amp;#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&amp;#039;re using an external PostgreSQL, you&amp;#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&amp;#039;s not the default.)&lt;br /&gt;
&lt;br /&gt;
4.  **Grant the permission:**&lt;br /&gt;
Identify the GitLab database user (it&amp;#039;s often `gitlab` or `gitlab-rails` if you&amp;#039;re using the default Helm chart). You can check it in your `values.yaml` or in the `webservice` pod&amp;#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&amp;#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;
&amp;#039;&amp;#039;&amp;#039;Note:&amp;#039;&amp;#039;&amp;#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 = &amp;#039;pg_ls_waldir&amp;#039; AND n.nspname = &amp;#039;pg_catalog&amp;#039;) THEN&lt;br /&gt;
             GRANT EXECUTE ON FUNCTION pg_catalog.pg_ls_waldir() TO gitlab; -- Replace &amp;#039;gitlab&amp;#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 = &amp;#039;pg_monitor&amp;#039;) THEN&lt;br /&gt;
             GRANT pg_monitor TO gitlab; -- Replace &amp;#039;gitlab&amp;#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&amp;#039;s `global.psql.username` or `global.postgresql.username` setting, or if you&amp;#039;re using the bundled PostgreSQL, it&amp;#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>
</feed>