<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Quay on TechBlog about OpenShift/Ansible/Satellite and much more</title><link>https://blog.stderr.at/categories/quay/</link><description>TechBlog about OpenShift/Ansible/Satellite and much more</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><copyright>Toni Schmidbauer &amp; Thomas Jungbauer</copyright><lastBuildDate>Fri, 19 Sep 2025 00:00:00 +0000</lastBuildDate><atom:link href="https://blog.stderr.at/categories/quay/index.xml" rel="self" type="application/rss+xml"/><item><title>Red Hat Quay Registry - Integrate Keycloak</title><link>https://blog.stderr.at/openshift-platform/quay/2025-09-19-quay-integrate-keycloak/</link><pubDate>Fri, 19 Sep 2025 00:00:00 +0000</pubDate><guid>https://blog.stderr.at/openshift-platform/quay/2025-09-19-quay-integrate-keycloak/</guid><description>&lt;div class="paragraph"&gt;
&lt;p&gt;This guide shows you how to configure Keycloak as an OpenID Connect (OIDC) provider for Red Hat Quay Registry. It covers what to configure in Keycloak, what to put into Quay’s config.yaml (or Operator config), how to verify the login flow, and how to switch your Quay initial/admin account (stored locally in Quay’s DB) to an admin user that authenticates via Keycloak.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_prerequisites"&gt;Prerequisites&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Before starting this integration, ensure you have:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="ulist"&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;OpenShift cluster with admin access&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Red Hat Quay Registry 3.15+ installed (via Operator)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Red Hat build of Keycloak stable-v22+ installed and configured (via Operator)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Valid SSL certificates for both Quay and Keycloak&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Admin access to both Keycloak Admin Console and Quay configuration&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Basic understanding of OIDC/OAuth2 concepts&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="admonitionblock note"&gt;
&lt;table&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td class="icon"&gt;
&lt;i class="fa icon-note" title="Note"&gt;&lt;/i&gt;
&lt;/td&gt;
&lt;td class="content"&gt;
Here we are using the Quay Operator and the Keycloak Operator on OpenShift.
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_quick_overview_what_happens"&gt;Quick overview (what happens)&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="olist arabic"&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;
&lt;p&gt;Create a Keycloak client for Quay (OIDC).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Configure Quay’s OIDC provider section in config.yaml to point to Keycloak (client id/secret, endpoints, scopes, claim names).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Restart Quay, test login via Keycloak. The first time an OIDC user logs in, Quay creates a local user record that is linked to the OIDC identity.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Promote that Quay user to superuser by adding their Quay username to SUPER_USERS (or use the UI/API).&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_keycloak_create_a_client_for_quay"&gt;Keycloak: create a client for Quay&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Steps in Keycloak Admin console:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="olist arabic"&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;
&lt;p&gt;Log in to the Keycloak Admin Console and select the realm you will use for Quay or create a new realm.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Select that realm and go to clients&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Press &lt;strong&gt;Create client&lt;/strong&gt; to create and configure a new client for Quay. Not much must be configured here, but at least the following:&lt;/p&gt;
&lt;div class="olist loweralpha"&gt;
&lt;ol class="loweralpha" type="a"&gt;
&lt;li&gt;
&lt;p&gt;Client type: OpenID Connect&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Client ID: quay-enterprise (The ID we will use in the Quay configuration as well)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Client authentication: ON&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Valid redirects URIs:&lt;/p&gt;
&lt;div class="ulist"&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://&amp;lt;quay-hostname&amp;gt;/oauth2/&amp;lt;service-id&amp;gt;/callback" class="bare"&gt;https://&amp;lt;quay-hostname&amp;gt;/oauth2/&amp;lt;service-id&amp;gt;/callback&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;(Optional) &lt;a href="https://&amp;lt;quay-hostname&amp;gt;/oauth2/&amp;lt;service-id&amp;gt;/callback/attach" class="bare"&gt;https://&amp;lt;quay-hostname&amp;gt;/oauth2/&amp;lt;service-id&amp;gt;/callback/attach&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;(Optional) &lt;a href="https://&amp;lt;quay-hostname&amp;gt;/oauth2/&amp;lt;service-id&amp;gt;/callback/cli" class="bare"&gt;https://&amp;lt;quay-hostname&amp;gt;/oauth2/&amp;lt;service-id&amp;gt;/callback/cli&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class="admonitionblock note"&gt;
&lt;table&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td class="icon"&gt;
&lt;i class="fa icon-note" title="Note"&gt;&lt;/i&gt;
&lt;/td&gt;
&lt;td class="content"&gt;
The service-id is the parent key you’ll use in Quay config — e.g. keycloak.
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;div class="olist loweralpha"&gt;
&lt;ol class="loweralpha" type="a"&gt;
&lt;li&gt;
&lt;p&gt;Save the client.&lt;/p&gt;
&lt;div class="olist arabic"&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;
&lt;p&gt;Go to Credentials and create or copy the &lt;strong&gt;client secret&lt;/strong&gt; you will use in Quay.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class="admonitionblock note"&gt;
&lt;table&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td class="icon"&gt;
&lt;i class="fa icon-note" title="Note"&gt;&lt;/i&gt;
&lt;/td&gt;
&lt;td class="content"&gt;
&lt;strong&gt;(Optional)&lt;/strong&gt; If you intend to use groups/roles from Keycloak for Quay team synchronization, ensure your Keycloak users or groups are populated and that Keycloak includes group membership in tokens or exposes group claims (you may need to add a protocol mapper in the client to include groups or roles in the ID token or userinfo response). Refer to Keycloak docs for adding protocol mappers.
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_keycloak_create_users_and_groups"&gt;Keycloak: create users and groups&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="olist arabic"&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;
&lt;p&gt;Go to Users and create a new user or use an existing one.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If you created a new user, set a password for them in the Credentials tab.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Go to Groups and create a new group or use an existing one.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;You can assign users to that group.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_quay_add_oidc_configuration"&gt;Quay: add OIDC configuration&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Quay’s OIDC block is a nested object under &lt;strong&gt;AUTHENTICATION_TYPE: OIDC&lt;/strong&gt;. The parent key can be any name (e.g., KEYCLOAK_LOGIN_CONFIG) — Quay uses the parent key name to form the callback paths.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonitionblock important"&gt;
&lt;table&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td class="icon"&gt;
&lt;i class="fa icon-important" title="Important"&gt;&lt;/i&gt;
&lt;/td&gt;
&lt;td class="content"&gt;
The parent key name (before _LOGIN_CONFIG) must match the service-id used in Keycloak redirect URIs.
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Example config.yaml snippet for Keycloak:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonitionblock note"&gt;
&lt;table&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td class="icon"&gt;
&lt;i class="fa icon-note" title="Note"&gt;&lt;/i&gt;
&lt;/td&gt;
&lt;td class="content"&gt;
Using Quay Operator this configuration is stored as a secret in the namespace where Quay is installed.
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="highlightjs highlight"&gt;&lt;code class="language-yaml hljs" data-lang="yaml"&gt;AUTHENTICATION_TYPE: OIDC &lt;i class="conum" data-value="1"&gt;&lt;/i&gt;&lt;b&gt;(1)&lt;/b&gt;
KEYCLOAK_LOGIN_CONFIG: &lt;i class="conum" data-value="2"&gt;&lt;/i&gt;&lt;b&gt;(2)&lt;/b&gt;
CLIENT_ID: quay-enterprise &lt;i class="conum" data-value="3"&gt;&lt;/i&gt;&lt;b&gt;(3)&lt;/b&gt;
CLIENT_SECRET: &amp;lt;client-secret&amp;gt; &lt;i class="conum" data-value="4"&gt;&lt;/i&gt;&lt;b&gt;(4)&lt;/b&gt;
LOGIN_SCOPES:
- openid
- email
- profile
- groups
OIDC_SERVER: https://&amp;lt;keycloak hostname&amp;gt;/realms/quay/ &lt;i class="conum" data-value="5"&gt;&lt;/i&gt;&lt;b&gt;(5)&lt;/b&gt;
SERVICE_NAME: keycloak &lt;i class="conum" data-value="6"&gt;&lt;/i&gt;&lt;b&gt;(6)&lt;/b&gt;
PREFERRED_USERNAME_CLAIM_NAME: preferred_username
VERIFIED_EMAIL_CLAIM_NAME: email
PREFERRED_GROUP_CLAIM_NAME: groups
OIDC_DISABLE_USER_ENDPOINT: false &lt;i class="conum" data-value="7"&gt;&lt;/i&gt;&lt;b&gt;(7)&lt;/b&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="colist arabic"&gt;
&lt;table&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;i class="conum" data-value="1"&gt;&lt;/i&gt;&lt;b&gt;1&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;Set this parameter to &lt;strong&gt;OIDC&lt;/strong&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;i class="conum" data-value="2"&gt;&lt;/i&gt;&lt;b&gt;2&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;parent key name can be any string (use KEYCLOAK_LOGIN_CONFIG here). This is important, and the part in front of _LOGIN_CONFIG must match the service-id you used in Keycloak.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;i class="conum" data-value="3"&gt;&lt;/i&gt;&lt;b&gt;3&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;The client id you used in Keycloak.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;i class="conum" data-value="4"&gt;&lt;/i&gt;&lt;b&gt;4&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;The client secret you used in Keycloak.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;i class="conum" data-value="5"&gt;&lt;/i&gt;&lt;b&gt;5&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;The realm base URL (no trailing /protocol…​), e.g.:
&lt;a href="https://&amp;lt;keycloak_hostname&amp;gt;/realms/quay/" class="bare"&gt;https://&amp;lt;keycloak_hostname&amp;gt;/realms/quay/&lt;/a&gt; — Quay will discover .well-known/openid-configuration endpoints automatically.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;i class="conum" data-value="6"&gt;&lt;/i&gt;&lt;b&gt;6&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;The service name you used in Keycloak.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;i class="conum" data-value="7"&gt;&lt;/i&gt;&lt;b&gt;7&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;Set this parameter to &lt;strong&gt;false&lt;/strong&gt; to allow Quay to fetch user information from Keycloak. If using Azure Entra ID set this to &lt;strong&gt;true&lt;/strong&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Since we are using Quay Operator, the operator will pick up the changes automatically and restart Quay.
If you are using a standalone Quay installation, you need to restart Quay for the change to take effect. (Config is not hot-reloaded.)&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_testing_login"&gt;Testing Login&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Let’s do some tests to verify the configuration.
Above we have created some users and groups in Keycloak. Let’s try to log in with one of them.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="olist arabic"&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;
&lt;p&gt;Open your Quay UI ( &lt;a href="https://&amp;lt;quay_hostname&amp;gt;" class="bare"&gt;https://&amp;lt;quay_hostname&amp;gt;&lt;/a&gt;; ) in a browser. On the login page you should see the external login option labelled Keycloak (or the SERVICE_NAME you set).&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class="imageblock"&gt;
&lt;div class="content"&gt;
&lt;img src="https://blog.stderr.at/openshift-platform/quay/images/quay-login-oidc.png?width=320" alt="quay login oidc"/&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="olist arabic"&gt;
&lt;ol class="arabic" start="2"&gt;
&lt;li&gt;
&lt;p&gt;Click the &amp;#34;Sign in with Keycloak&amp;#34; option. and you will be redirected to Keycloak’s login screen. Here you can authenticate with a Keycloak user.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class="imageblock"&gt;
&lt;div class="content"&gt;
&lt;img src="https://blog.stderr.at/openshift-platform/quay/images/quay-keycloak.png?width=320" alt="quay keycloak"/&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;After successful authentication, Keycloak redirects back to Quay and Quay creates a local user mapped to the OIDC claims (username, email). If you set USERNAME_CLAIM to preferred_username, look at the created Quay username in the UI under your user’s profile.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_make_the_keycloak_user_a_quay_admin"&gt;Make the Keycloak user a Quay admin&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;In Quay only one identity provider can be used at a time. If you previously set up a local admin account, you need to make a Keycloak user a Quay admin by adding their Quay username to SUPER_USERS where all administrators are listed.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;In the Quay configuration, you can define administrators using the SUPER_USERS array.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonitionblock note"&gt;
&lt;table&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td class="icon"&gt;
&lt;i class="fa icon-note" title="Note"&gt;&lt;/i&gt;
&lt;/td&gt;
&lt;td class="content"&gt;
Make sure the Keycloak user has logged in once so Quay has created a local user record
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Edit the Quay configuration once more and add the Quay username (exact username created by Quay).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;For example, let’s say we have created a user called &amp;#34;alice&amp;#34; in Keycloak. We need to add this user to the SUPER_USERS array.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="highlightjs highlight"&gt;&lt;code class="language-yaml hljs" data-lang="yaml"&gt;SETUP_COMPLETE: true
SUPER_USERS:
- admin # existing local admin (optional)
- alice # alice is the Quay username created from Keycloak login&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;After restart, the Quay account alice will have superuser privileges (same as if created in the UI).&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_working_with_podman_on_cli"&gt;Working with Podman on CLI&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Now, as we changed the authentication method, we need to verify if we can push/pull images from/to the registry.
The command line tool of the choice is &lt;strong&gt;podman&lt;/strong&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;However, podman does not redirect to SSO login, so it needs a token to authenticate. We can generate a new token for a user in the Quay UI.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="olist arabic"&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;
&lt;p&gt;In the Quay UI, go to the &lt;strong&gt;Account Settings&lt;/strong&gt; (upper right corner)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;In the settings section, under &lt;strong&gt;Docker CLI and other Application Tokens&lt;/strong&gt;, click on &lt;strong&gt;Create Application Token&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Enter a name for the token&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Select the newly created token and copy the podman login command (or any other command you need)&lt;/p&gt;
&lt;div class="imageblock"&gt;
&lt;div class="content"&gt;
&lt;img src="https://blog.stderr.at/openshift-platform/quay/images/quay-app-pass.png?width=320" alt="quay app pass"/&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The command for podman will look like this:&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="highlightjs highlight"&gt;&lt;code class="language-bash hljs" data-lang="bash"&gt;podman login -u=&amp;#39;$app&amp;#39; -p=&amp;#39;&amp;lt;token&amp;gt;&amp;#39; &amp;lt;quay-url&amp;gt;
Login Succeeded!&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Now you can push/pull images from/to the registry.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_troubleshooting"&gt;Troubleshooting&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Common issues and their solutions:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_redirect_uri_mismatch"&gt;Redirect URI Mismatch&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;&lt;strong&gt;Problem&lt;/strong&gt;: Keycloak returns &amp;#34;Invalid redirect URI&amp;#34; error&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;: Ensure all three redirect URIs are configured in Keycloak client:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="highlightjs highlight"&gt;&lt;code class="language-none hljs"&gt;https://&amp;lt;quay-hostname&amp;gt;/oauth2/keycloak/callback
https://&amp;lt;quay-hostname&amp;gt;/oauth2/keycloak/callback/attach
https://&amp;lt;quay-hostname&amp;gt;/oauth2/keycloak/callback/cli&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_username_mapping_issues"&gt;Username Mapping Issues&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;&lt;strong&gt;Problem&lt;/strong&gt;: Quay creates unexpected usernames&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="olist arabic"&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;
&lt;p&gt;Check which claim Keycloak sends: inspect ID token in browser dev tools&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Common claims: preferred_username, email, sub, name&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Update PREFERRED_USERNAME_CLAIM_NAME in Quay config accordingly&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_ssl_certificate_issues"&gt;SSL Certificate Issues&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;&lt;strong&gt;Problem&lt;/strong&gt;: Quay cannot reach Keycloak due to TLS verification errors&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;&lt;strong&gt;Solutions&lt;/strong&gt;:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="olist arabic"&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;
&lt;p&gt;Install your internal CA certificate in the Quay container&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Use publicly trusted certificates for both services&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;For testing only: disable SSL verification (not recommended for production)&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_authentication_flow_failures"&gt;Authentication Flow Failures&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;&lt;strong&gt;Problem&lt;/strong&gt;: Login redirects but fails to create user in Quay&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;&lt;strong&gt;Debugging steps&lt;/strong&gt;:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="olist arabic"&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;
&lt;p&gt;Check Quay logs: &lt;code&gt;oc logs deployment/quay-app&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Verify OIDC discovery endpoint: &lt;code&gt;&lt;a href="https://&amp;lt;keycloak&amp;gt;/realms/&amp;lt;realm&amp;gt;/.well-known/openid-configuration" class="bare"&gt;https://&amp;lt;keycloak&amp;gt;/realms/&amp;lt;realm&amp;gt;/.well-known/openid-configuration&lt;/a&gt;&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Confirm client secret matches between Keycloak and Quay&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Test with curl: &lt;code&gt;curl -k &lt;a href="https://&amp;lt;keycloak&amp;gt;/realms/&amp;lt;realm&amp;gt;/.well-known/openid-configuration" class="bare"&gt;https://&amp;lt;keycloak&amp;gt;/realms/&amp;lt;realm&amp;gt;/.well-known/openid-configuration&lt;/a&gt;&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Integrating Quay 3.15 with Keycloak via OIDC centralizes authentication, simplifies user management, and allows you to leverage enterprise identity features. The key steps are straightforward: create a Keycloak client with the correct redirect URIs, configure the corresponding OIDC block in Quay’s config.yaml.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;By switching the initial database-backed admin to an identity managed in Keycloak, you reduce the risk of &amp;#34;orphaned&amp;#34; local accounts and align Quay administration with your organization’s identity and access management strategy.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</description></item><item><title>Stumbling into Quay: Upgrading from 3.3 to 3.4 with the quay-operator</title><link>https://blog.stderr.at/openshift-platform/quay/2021-09-07-quay-upgrade-3.4/</link><pubDate>Sat, 16 Oct 2021 00:00:00 +0000</pubDate><guid>https://blog.stderr.at/openshift-platform/quay/2021-09-07-quay-upgrade-3.4/</guid><description>
&lt;p&gt;
We had the task of answering various questions related to upgrading
Red Hat Quay 3.3 to 3.4 and to 3.5 with the help of the quay-operator.&lt;/p&gt;
&lt;p&gt;
Thankfully (sic!) everything changed in regards to the Quay operator
between Quay 3.3 and Quay 3.4.&lt;/p&gt;
&lt;p&gt;
So this is a brain dump of the things to consider.&lt;/p&gt;
&lt;div id="outline-container-headline-1" class="outline-2"&gt;
&lt;h2 id="headline-1"&gt;
Operator changes
&lt;/h2&gt;
&lt;div id="outline-text-headline-1" class="outline-text-2"&gt;
&lt;p&gt;
With Quay 3.4 the operator was completely reworked and it basically
changed from opinionated to &lt;strong&gt;very&lt;/strong&gt; opinionated. The upgrade works
quite well but you have to be aware about the following points:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The name of the custom resource changed from &lt;code&gt;QuayEcosystem&lt;/code&gt; to &lt;code&gt;QuayRegistry&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;configHostname&lt;/code&gt;, used for providing the quay configuration UI, is no longer configurable&lt;/li&gt;
&lt;li&gt;The password for the configuration UI is &lt;strong&gt;always&lt;/strong&gt; regenerated after a configuration re-deployment&lt;/li&gt;
&lt;li&gt;The volume size of the PostgreSQL PVC will change to 50G&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonitionblock warning" &gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class="icon"&gt;&lt;i class="fa icon-warning" title="warning"&gt;&lt;/i&gt;&lt;/td&gt;&lt;td class="content"&gt;&lt;p&gt;
In my test cluster I was using a 10G Ceph block device and the
StorageClass did not support volume expansion. So my upgrade stopped
at this point and I had to allow volume expansion in the storage
class.&lt;/p&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;A horizontal pod autoscaler is also deploy during the upgrade. The
default is to scale automatically to 20 pods, you might reconsider this…&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;With the Quay operator version 3.5 the operator is monitoring all
namespaces for custom resources and needs to be installed in the
openshift-operators namespace, this is how we upgraded Quay to 3.5
including the operator:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;change the quay operator channel to 3.5&lt;/li&gt;
&lt;li&gt;trigger an upgrade&lt;/li&gt;
&lt;li&gt;now Quay gets upgraded to version 3.5&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;after the Quay upgrade you need to reinstall the operator:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;deinstall the quay operator, Quay is &lt;strong&gt;not&lt;/strong&gt; affected by this&lt;/li&gt;
&lt;li&gt;reinstall the Quay operator (3.5) in all-namespaces&lt;/li&gt;
&lt;li&gt;the re-installation of the operator triggers a quay deployment,
all Quay pods are restarted!&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;You have to manually cleanup old&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;postgres-config-secrets and&lt;/li&gt;
&lt;li&gt;quay-config-bundle&amp;#39;s&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-headline-2" class="outline-2"&gt;
&lt;h2 id="headline-2"&gt;
Backup and restore considerations
&lt;/h2&gt;
&lt;div id="outline-text-headline-2" class="outline-text-2"&gt;
&lt;p&gt;
Red Hat is working on providing documentation on how to backup and
restore Quay in various scenarios. There&amp;#39;s an open task for this
that provides more information
&lt;a href="https://issues.redhat.com/browse/PROJQUAY-2242"&gt;https://issues.redhat.com/browse/PROJQUAY-2242&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;</description></item><item><title>Red Hat Quay Registry - Overview and Installation</title><link>https://blog.stderr.at/openshift-platform/quay/2020-05-13-quay-tutorial1/</link><pubDate>Wed, 13 May 2020 00:00:00 +0000</pubDate><guid>https://blog.stderr.at/openshift-platform/quay/2020-05-13-quay-tutorial1/</guid><description>&lt;div class="paragraph"&gt;
&lt;p&gt;Red Hat Quay is an enterprise-quality container registry, which is responsible to build, scan, store and deploy containers.
The main features of Quay include:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="ulist"&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;High Availability&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Security Scanning (with Clair)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Registry mirroring&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Docker v2&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Continuous integration&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;and much more.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Quay can be installed as:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="ulist"&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Standalone single service&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;High Availibility service&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;On OpenShift with an Operator&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;On OpenShift without an Operator.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;For the following Quay Tutorial Quay version 3.3 on OpenShift 4.3/4.4 with an Operator is used. Moreover, a local storage is used, to make the deployment easier and independent to a storage provider. In any case, be sure that for a production environment a &amp;#34;real&amp;#34; storage is used.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Further details can be found at the official Red Hat documentation at: &lt;a href="https://access.redhat.com/documentation/en-us/red_hat_quay/3.3/html-single/deploy_red_hat_quay_on_openshift_with_quay_operator/index#configuration_deployment_after_initial_setup" target="_blank" rel="noopener"&gt;Deploy Red Hat Quay on OpenShift with an Operator&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_quay_architecture"&gt;Quay Architecture&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Several components are used to build Quay&lt;/p&gt;
&lt;/div&gt;
&lt;div class="ulist"&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Database: used to store metadata (not images)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Redis: stores live builder logs&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Quay container registry: Runs Quay as a service&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Two types of storages are supported:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="ulist"&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Public cloud storage, like Amazon S3, Google Cloud Storage&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Private cloud storage, S3 compliant Object Store, Like Ceph RADOS or OpenStack Swift.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="admonitionblock caution"&gt;
&lt;table&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td class="icon"&gt;
&lt;i class="fa icon-caution" title="Caution"&gt;&lt;/i&gt;
&lt;/td&gt;
&lt;td class="content"&gt;
Since I perform the example setup in a limited lab environment, I used local storage. This is not supported for production installations.
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_installation"&gt;Installation&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;This example installation, covers the configuration of all credentials, but it ignores the configuration of a storage engine. Instead it is using local storage.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_create_a_new_project_and_install_the_quay_operator"&gt;Create a new project and install the Quay Operator&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Note: Before you begin create a new project called &amp;#34;&lt;strong&gt;quay&lt;/strong&gt;&amp;#34;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;From the OpenShift console goto Operators &amp;gt; OperationHub and search for &amp;#34;Red Hat Quay Operator&amp;#34;. Be sure &lt;strong&gt;NOT&lt;/strong&gt; to select the community version.
Install the Operator using the following settings:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="ulist"&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Installation Mode: select the namespace &amp;#34;quay&amp;#34;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Leave the other settings as default.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="imageblock"&gt;
&lt;div class="content"&gt;
&lt;img src="https://blog.stderr.at/openshift-platform/quay/images/quay/quay-operator-installation.png?width=940px" alt="quay operator installation"/&gt;
&lt;/div&gt;
&lt;div class="title"&gt;Figure 1. Operator Installation&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Once you select &amp;#34;Subscribe&amp;#34;, the installation process will take a few minutes. At the end, the operator pods should run inside your namespace and is ready to bse used.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="imageblock"&gt;
&lt;div class="content"&gt;
&lt;img src="https://blog.stderr.at/openshift-platform/quay/images/quay/quay-operator-running.png?width=940px" alt="quay operator running"/&gt;
&lt;/div&gt;
&lt;div class="title"&gt;Figure 2. Operator Running&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_configure_quay"&gt;Configure Quay&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;To configure Quay the Custom Resource Definition &amp;#34;&lt;strong&gt;QuayEcosystem&lt;/strong&gt;&amp;#34; must be defined. Below example shows a ready to use example to test the deployment. Several secrets are used in this QuayEcosystem which must be created first. If they are not specified in the QuayEcosystem, then default values would be used. However, it always makes sense to specify passwords :)&lt;/p&gt;
&lt;/div&gt;
&lt;div class="sect3"&gt;
&lt;h4 id="_create_a_pull_secret_to_pull_from_quay_io"&gt;&lt;strong&gt;Create a Pull Secret to pull from Quay.io&lt;/strong&gt;&lt;/h4&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Check the article &lt;a href="https://access.redhat.com/solutions/3533201" target="_blank" rel="noopener"&gt;Accessing Red Hat Quay&lt;/a&gt; to find the appropriate credentials you need to fetch images from quay.io. Find the section &amp;#34;Red Hat Quay v3 on OpenShift&amp;#34;, copy the secret into the file &lt;em&gt;redhat_secret.yaml&lt;/em&gt; and create the object in OpenShift:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="highlightjs highlight"&gt;&lt;code class="language-bash hljs" data-lang="bash"&gt;oc create -f redhat_secret.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect3"&gt;
&lt;h4 id="_create_quay_superuser_credentials"&gt;&lt;strong&gt;Create Quay Superuser Credentials&lt;/strong&gt;&lt;/h4&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;The Quay superuser will be able to manage other users or projects. Create the secret by defining username, password and e-mail address:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonitionblock caution"&gt;
&lt;table&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td class="icon"&gt;
&lt;i class="fa icon-caution" title="Caution"&gt;&lt;/i&gt;
&lt;/td&gt;
&lt;td class="content"&gt;
The password must have a minimum length of 8 characters.
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="highlightjs highlight"&gt;&lt;code class="language-bash hljs" data-lang="bash"&gt;oc create secret generic quay-credentials \
--from-literal=superuser-username=&amp;lt;username&amp;gt; \
--from-literal=superuser-password=&amp;lt;password&amp;gt; \
--from-literal=superuser-email=&amp;lt;email&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect3"&gt;
&lt;h4 id="_create_quay_configuration_credentials"&gt;&lt;strong&gt;Create Quay Configuration Credentials&lt;/strong&gt;&lt;/h4&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;The Quay configuration is done, by a separate pod, with a separate accessible route. To set the password, create the following secret:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonitionblock caution"&gt;
&lt;table&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td class="icon"&gt;
&lt;i class="fa icon-caution" title="Caution"&gt;&lt;/i&gt;
&lt;/td&gt;
&lt;td class="content"&gt;
The password must have a minimum length of 8 characters.
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="highlightjs highlight"&gt;&lt;code class="language-bash hljs" data-lang="bash"&gt;oc create secret generic quay-config-app \
--from-literal=config-app-password=&amp;lt;password&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect3"&gt;
&lt;h4 id="_specify_database_credentials"&gt;&lt;strong&gt;Specify database credentials&lt;/strong&gt;&lt;/h4&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;As next let’s create the credentials for the database:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="highlightjs highlight"&gt;&lt;code class="language-bash hljs" data-lang="bash"&gt;oc create secret generic &amp;lt;secret_name&amp;gt; \
--from-literal=database-username=&amp;lt;username&amp;gt; \
--from-literal=database-password=&amp;lt;password&amp;gt; \
--from-literal=database-root-password=&amp;lt;root-password&amp;gt; \
--from-literal=database-name=&amp;lt;database-name&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="admonitionblock note"&gt;
&lt;table&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td class="icon"&gt;
&lt;i class="fa icon-note" title="Note"&gt;&lt;/i&gt;
&lt;/td&gt;
&lt;td class="content"&gt;
It is also possible to use and existing database. To configure this, create the secret as described and add the server parameter, containing the hostname, to the QuayEcosystem definition+
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect3"&gt;
&lt;h4 id="_setting_redis_password"&gt;&lt;strong&gt;Setting Redis password&lt;/strong&gt;&lt;/h4&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;By default, the operator would install Redis without any password. To specify a password, create the following secret:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="highlightjs highlight"&gt;&lt;code class="language-bash hljs" data-lang="bash"&gt;oc create secret generic quay-redis-password \
--from-literal=password=&amp;lt;password&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_create_quayecosystem_resource"&gt;Create QuayEcosystem Resource&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;With all the secrets created above, it is time to create the &lt;strong&gt;QuayEcosystem&lt;/strong&gt;. Once it is defined, the operator will automatically start all required services.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;The following is an example, using the different secret names (The names should be self explaining)
In addition, the following has been defined:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="ulist"&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;volumeSize = 10GI for the database&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;keepConfigDeployment to false, this will remove the configuration pod after the deployment.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;hostname: to reach the Quay registry under a defined hostname (otherwise a default name would be created)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Clair container scanning is enabled&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="highlightjs highlight"&gt;&lt;code class="language-yaml hljs" data-lang="yaml"&gt;apiVersion: redhatcop.redhat.io/v1alpha1
kind: QuayEcosystem
metadata:
name: quayecosystem
spec:
quay:
imagePullSecretName: redhat-quay-pull-secret
superuserCredentialsSecretName: quay-credentials
configSecretName: quay-config-app
deploymentStrategy: Recreate
skipSetup: false
keepConfigDeployment: false
externalAccess:
hostname: quay.apps.ocp.ispworld.at
database:
volumeSize: 10Gi
credentialsSecretName: quay-database-credential
registryBackends:
- name: local
local:
storagePath: /opt/quayregistry
redis:
credentialsSecretName: quay-redis-password
imagePullSecretName: redhat-quay-pull-secret
clair:
enabled: true
imagePullSecretName: redhat-quay-pull-secret&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_quay_webui"&gt;Quay WebUI&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Once the Quay Operator has deployed all containers, you should see one route (or 2 if you kept Configuration Deployment Container) and can access your Quay installation.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="imageblock"&gt;
&lt;div class="content"&gt;
&lt;img src="https://blog.stderr.at/openshift-platform/quay/images/quay/quay-login.png?width=240px" alt="quay login"/&gt;
&lt;/div&gt;
&lt;div class="title"&gt;Figure 3. Quay WebUI&lt;/div&gt;
&lt;/div&gt;
&lt;hr/&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_optional_disable_self_account_creation"&gt;Optional: Disable self account creation&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Many customers want to disable the &amp;#34;Create Account&amp;#34; link on the login page (see Figure #3), to prevent that anybody could create a new account. To remove this option, the configuration pod must run.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_verify_if_the_configuration_pod_is_running"&gt;Verify if the Configuration pod is running&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;If the following does not return anything, then the container is not running:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="highlightjs highlight"&gt;&lt;code class="language-bash hljs" data-lang="bash"&gt;oc get routes -n quay | grep config&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;If this is the case, modify the resource QuayEcosystem to enable the Configuration UI.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Edit:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="highlightjs highlight"&gt;&lt;code class="language-bash hljs" data-lang="bash"&gt;oc edit QuayEcosystem/quayecosystem&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;and set &amp;#34;KeepConfigDeployment&amp;#34; to true:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="highlightjs highlight"&gt;&lt;code class="language-yaml hljs" data-lang="yaml"&gt; quay:
[...]
keepConfigDeployment: true&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;After a few minutes another pod, called &amp;#34;quayecosystem-quay-config&amp;#34; will be started and a new route is created:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="highlightjs highlight"&gt;&lt;code class="language-bash hljs" data-lang="bash"&gt;oc get routes -n quay | grep config
quayecosystem-quay-config quayecosystem-quay-config-quay.apps.ocp.ispworld.at quayecosystem-quay-config 8443 passthrough/Redirect None&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_configure_account_creation_and_anonymous_access"&gt;Configure Account Creation and Anonymous Access&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Login to the Configuration Web Interface with the credentials you specified during the deployment and scroll down to the section &amp;#34;Access Settings&amp;#34;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="imageblock"&gt;
&lt;div class="content"&gt;
&lt;img src="https://blog.stderr.at/openshift-platform/quay/images/quay/quay-config.png" alt="quay config"/&gt;
&lt;/div&gt;
&lt;div class="title"&gt;Figure 4. Quay Configuration&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;There remove the checkbox from:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="ulist"&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Anonymous Access&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;User Creation&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;and save and build the configuration.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;This will trigger a change on the Quay pod. After it has been recreated (this will take a few minutes), the feature to create a new account is removed from the Login page.&lt;/p&gt;
&lt;/div&gt;
&lt;hr/&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_working_with_quay"&gt;Working with Quay&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;The following quick steps through Quay are the steps of the Quay tutorial, which can be seen at the Quay WebUI at the &amp;#34;Tutorial&amp;#34; tab.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_login_via_docker_cli"&gt;Login via Docker CLI&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;To login via docker CLI simply use:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="highlightjs highlight"&gt;&lt;code class="language-bash hljs" data-lang="bash"&gt;docker login &amp;lt;your selected hostname for quay&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="admonitionblock note"&gt;
&lt;table&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td class="icon"&gt;
&lt;i class="fa icon-note" title="Note"&gt;&lt;/i&gt;
&lt;/td&gt;
&lt;td class="content"&gt;
Docker expects a valid certificate. Such certificate could be added to the definition of QuayEcosystem. However, I did not create a certificate for this lab. To allow untrusted certificates, on a Mac, simply download the certificates (For Chrome: you can drag and drop the certificate from the browser to your Desktop, for Firefox, you need to open the Options menu and export the certificates.). After that double click both certificates (the root and the site certificate), which will install them on you local Keychain. Open the Keychain on you Mac, find the appropriate certificates and set both to &amp;#34;Always trust&amp;#34;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_create_an_example_container"&gt;Create an example container&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;The next step to create a new image is to create a container. For this example the &lt;em&gt;busybox&lt;/em&gt; base image is used.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="highlightjs highlight"&gt;&lt;code class="language-bash hljs" data-lang="bash"&gt;docker run busybox echo &amp;#34;fun&amp;#34; &amp;gt; newfile&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;This will pull the latest image of busybox and create a container:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="highlightjs highlight"&gt;&lt;code class="language-bash hljs" data-lang="bash"&gt;Unable to find image &amp;#39;busybox:latest&amp;#39; locally
latest: Pulling from library/busybox
d9cbbca60e5f: Pulling fs layer
d9cbbca60e5f: Verifying Checksum
d9cbbca60e5f: Download complete
d9cbbca60e5f: Pull complete
Digest: sha256:836945da1f3afe2cfff376d379852bbb82e0237cb2925d53a13f53d6e8a8c48c
Status: Downloaded newer image for busybox:latest&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;With &amp;#34;docker ps&amp;#34; the running container is shown.
Remember the &lt;strong&gt;Container ID&lt;/strong&gt; for further steps. In this case &lt;em&gt;fc3e9bb1e9da&lt;/em&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="highlightjs highlight"&gt;&lt;code class="language-bash hljs" data-lang="bash"&gt;docker ps -l
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
fc3e9bb1e9da busybox &amp;#34;echo fun&amp;#34; 3 minutes ago Exited (0) 3 minutes ago relaxed_proskuriakova&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_create_the_image"&gt;Create the image&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Once a container has terminated in Docker, the next step is to commit the container to an image.
To do so we will use &amp;#34;docker commit&amp;#34; command. As name for the repository I took &lt;strong&gt;superapp&lt;/strong&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="highlightjs highlight"&gt;&lt;code class="language-bash hljs" data-lang="bash"&gt;docker commit fc3e9bb1e9da quay.apps.ocp.ispworld.at/quay/superapp&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_push_the_image_to_red_hat_quay"&gt;Push the image to Red Hat Quay&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;The final step is to push the image to our repository, where it will be stored for future use.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="highlightjs highlight"&gt;&lt;code class="language-bash hljs" data-lang="bash"&gt;docker push quay.apps.ocp.ispworld.at/quay/superapp&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="imageblock"&gt;
&lt;div class="content"&gt;
&lt;img src="https://blog.stderr.at/openshift-platform/quay/images/quay/quay-repos.png?width=940px" alt="quay repos"/&gt;
&lt;/div&gt;
&lt;div class="title"&gt;Figure 5. Quay Repository&lt;/div&gt;
&lt;/div&gt;
&lt;hr/&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_test_container_security_scanner"&gt;Test Container Security Scanner&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Clair is used to scan containers about possible security risks. It imports vulnerability data permanently from a known source and creates a list of threats for an image.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;To test such scanning, we pull the &amp;#34;Universal Base Image RHEL 7&amp;#34; from Red Hat. I am using version 7.6 since this is already quite old and we expect some known vulnerabilities for this image.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;First you need to login to Red Hat Registry:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="highlightjs highlight"&gt;&lt;code class="language-bash hljs" data-lang="bash"&gt;docker login registry.redhat.io
Username: &amp;lt;Username&amp;gt;
Password: &amp;lt;Password&amp;gt;
Login Succeeded&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Then let’s pull the UBI Image 7.6 (instead of the latest)&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="highlightjs highlight"&gt;&lt;code class="language-bash hljs" data-lang="bash"&gt;docker pull registry.redhat.io/ubi7/ubi:7.6&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Before we can push it to our Quay registry, we need to tag it:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="highlightjs highlight"&gt;&lt;code class="language-bash hljs" data-lang="bash"&gt;docker tag registry.redhat.io/ubi7/ubi:7.6 quay.apps.ocp.ispworld.at/quay/ubi7:7.6&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;If we now check the local images, we see that there are two UBI images.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="highlightjs highlight"&gt;&lt;code class="language-bash hljs" data-lang="bash"&gt;docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
quay.apps.ocp.ispworld.at/quay/ubi7 7.6 247ee58855fd 10 months ago 204MB
registry.redhat.io/ubi7/ubi 7.6 247ee58855fd 10 months ago 204MB&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Now it is possible to push the image to the Quay repository.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="highlightjs highlight"&gt;&lt;code class="language-bash hljs" data-lang="bash"&gt;docker push quay.apps.ocp.ispworld.at/quay/ubi7:7.6&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Finally the image is available inside our Registry and Clair will queue it for a security scan.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Once the scan is finished, possible found issues are shown under the &amp;#34;Repository Tags&amp;#34;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="imageblock"&gt;
&lt;div class="content"&gt;
&lt;img src="https://blog.stderr.at/openshift-platform/quay/images/quay/quay-clair.png" alt="quay clair"/&gt;
&lt;/div&gt;
&lt;div class="title"&gt;Figure 6. Clair Security Scanning&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;When you click on then, you will see a detailed result page, with all vulnerabilities found:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="imageblock"&gt;
&lt;div class="content"&gt;
&lt;img src="https://blog.stderr.at/openshift-platform/quay/images/quay/quay-clair-results.png" alt="quay clair results"/&gt;
&lt;/div&gt;
&lt;div class="title"&gt;Figure 7. Clair Security Scanning Result&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</description></item></channel></rss>