[{"data":1,"prerenderedAt":243},["ShallowReactive",2],{"seo-verification":3,"blog-deploy-keycloak-for-sso-on-your-vps-ma-en":6,"promo-bar-likely":242},{"google":4,"bing":5},"EycwPY2XMyTkVzas3n1ygeNJFGAH513qrMjfDljzsMQ","",{"key":7,"data":8},"blog-deploy-keycloak-for-sso-on-your-vps-ma-en",{"id":9,"slug":10,"slugs":11,"title":15,"excerpt":16,"readTime":17,"views":18,"isPinned":19,"noindex":19,"publishedAt":20,"updatedAt":21,"category":22,"categories":28,"featuredImage":30,"bgImage":31,"posterImage":32,"relatedSolution":33,"intro":36,"sections":37,"ctaTitle":182,"ctaBody":183,"ctaButton":184,"ctaUrl":185,"relatedPosts":186},112,"deploy-keycloak-for-sso-on-your-vps",{"fr":12,"en":10,"ar":13,"es":14},"keycloak-sso-vps","نشر-keycloak-لتسجيل-الدخول-الموحد-sso-على-خادمك-vps","desplegar-keycloak-sso-en-un-vps","Deploy Keycloak for SSO on Your VPS","Deploy Keycloak on your VPS for enterprise-grade SSO: OIDC, SAML, realms and federation. A complete Docker guide and comparison.",10,0,false,"2026-02-28T00:00:00+00:00","2026-11-04T16:30:25+00:00",{"id":23,"name":24,"slug":25,"color":26,"icon":27},8,"Security & Monitoring","securite-monitoring","bg-rose-500\u002F10 text-rose-400","security",[29],{"id":23,"name":24,"slug":25,"color":26,"icon":27},null,"\u002Fblog\u002Fcovers\u002Fbg.svg","\u002Fblog\u002Fcovers\u002Fkeycloak-sso-vps-poster.svg",{"categorySlug":34,"appSlug":35},"cybersecurity-bastion","keycloak","Keycloak is the open source reference for enterprise SSO, backed by Red Hat and used even in highly regulated environments. With its realms, LDAP federation and full support for OIDC and SAML, it covers needs that few IdPs can match. Self-hosted on a VPS, it gives you this level of industrialization without any licensing or cloud dependency.",[38,42,52,55,77,80,95,135,138,147,150,158,176,180],{"type":39,"title":40,"body":41},"h2","Why deploy Keycloak on your VPS","Where some IdPs aim for simplicity, Keycloak aims for completeness: multi-tenant isolation through realms, LDAP\u002FActive Directory directory federation, brokering to external providers (Google, GitHub, another OIDC), full theming of login pages and fine-grained authorization. For an agency managing several clients or an IT department with compliance requirements, this level of control is decisive. Self-hosting on a VPS spares you the per-user costs of managed IdP offerings and keeps the entire identity base under your jurisdiction, a critical point for sensitive data you would rather not entrust to a third party.",{"type":43,"title":44,"items":45},"ul","The strengths of a self-hosted Keycloak",[46,47,48,49,50,51],"Multiple realms to fully isolate several clients or environments on a single instance.","Native, complete support for OpenID Connect, OAuth2 and SAML 2.0.","LDAP \u002F Active Directory federation to reuse an existing directory without migration.","Identity brokering: sign-in via Google, GitHub or any external IdP in a few clicks.","Fully customizable login pages (themes, languages, per-realm branding).","Fine-grained authentication policies: conditional MFA, session duration, role-based constraints.",{"type":39,"title":53,"body":54},"Prerequisites for this deployment","Keycloak runs on the JVM (Quarkus since v17+) and remains more resource-hungry than a lightweight IdP. Plan for a VPS with at least 2 vCPUs and 4 GB of RAM, ideally 6 GB if you expect load or several active realms. An external PostgreSQL database is strongly recommended in production (never use the embedded H2 database beyond testing). Docker and Docker Compose, a dedicated domain (`sso.mydomain.com`) and a reverse proxy handling SSL round out the prerequisites, because Keycloak expects to be told that it is served behind an HTTPS proxy.",{"type":56,"title":57,"steps":58},"steps","Deploy Keycloak with PostgreSQL",[59,62,65,68,71,74],{"title":60,"body":61},"Define Keycloak and PostgreSQL in Compose","In your `docker-compose.yml`, declare the `postgres` service (image `postgres:16`) and the `keycloak` service (image `quay.io\u002Fkeycloak\u002Fkeycloak`). Connect Keycloak to the database via `KC_DB=postgres`, `KC_DB_URL`, `KC_DB_USERNAME` and `KC_DB_PASSWORD`.",{"title":63,"body":64},"Configure production mode and the proxy","Launch with the `start` command (not `start-dev`). Set `KC_HOSTNAME=sso.mydomain.com` and `KC_PROXY_HEADERS=xforwarded` so that Keycloak generates correct URLs behind the reverse proxy. Define the initial admin via `KC_BOOTSTRAP_ADMIN_USERNAME` \u002F `KC_BOOTSTRAP_ADMIN_PASSWORD`.",{"title":66,"body":67},"Start and complete the build","Run `docker compose up -d`. On first start, Keycloak performs an optimized Quarkus build and then migrates the PostgreSQL schema. Follow `docker compose logs -f keycloak` until the message indicating that the server is listening.",{"title":69,"body":70},"Set up the SSL reverse proxy","Route `sso.mydomain.com` to port `8080` of the Keycloak container via Caddy, Traefik or Nginx, with a Let's Encrypt certificate. Be sure to pass the `X-Forwarded-*` headers, otherwise login redirects will break.",{"title":72,"body":73},"Create a realm and a client","Log in to the admin console, create a dedicated realm (never the `master` realm for your apps), then an OIDC client. Set your application's `Valid redirect URIs` and retrieve the `Client ID` and secret in the Credentials tab.",{"title":75,"body":76},"Connect an application and test the flow","Configure your app with the discovery URL `https:\u002F\u002Fsso.mydomain.com\u002Frealms\u002Fmon-realm\u002F.well-known\u002Fopenid-configuration`. Create a test user in the realm, start a login and verify the token issuance in the console's Sessions.",{"type":39,"title":78,"body":79},"Pre-optimized image: separate the build from startup","By default, the `start` command checks at startup whether a Quarkus build phase is needed and runs it if so: this is what lengthens the first start, and it is what writes into the installation tree. The vendor documentation recommends the opposite for a container: run `kc.sh build` while building the image, then start with `start --optimized`. The `--optimized` parameter tells Keycloak it is running in an already optimized image and can skip that check. Build options, such as the database type (`db`) or enabling health probes (`health-enabled`), are frozen into the image: passed again at startup with the same value they are ignored, and with a different value they cause an error and require a new build. Secrets, database password included, belong to configuration options and stay supplied at runtime.",{"type":56,"title":81,"steps":82},"Build and run a pre-optimized image",[83,86,89,92],{"title":84,"body":85},"Write a two-stage Dockerfile","The first stage starts from `quay.io\u002Fkeycloak\u002Fkeycloak` named `builder`, sets `ENV KC_DB=postgres` and `ENV KC_HEALTH_ENABLED=true`, then runs `RUN \u002Fopt\u002Fkeycloak\u002Fbin\u002Fkc.sh build`. Pin a precise version number rather than `latest`, so that every rebuild stays reproducible.",{"title":87,"body":88},"Copy the result into the final image","The second stage starts again from the same image and runs `COPY --from=builder \u002Fopt\u002Fkeycloak\u002F \u002Fopt\u002Fkeycloak\u002F`. Place your custom themes and providers before the build: they are then taken into account by the optimization. If you add files with `COPY`, add `--chown=keycloak:keycloak` so that Keycloak can write into the folders concerned.",{"title":90,"body":91},"Start with the optimized option","In Compose, replace the command with `start --optimized`. Behind a reverse proxy that terminates TLS, add `KC_HTTP_ENABLED=true`. The `KC_HOSTNAME` and `KC_PROXY_HEADERS` variables and the database credentials remain runtime configuration.",{"title":93,"body":94},"Wire up the health probes","With `KC_HEALTH_ENABLED=true` set at build time, the `\u002Fhealth\u002Fstarted`, `\u002Fhealth\u002Flive` and `\u002Fhealth\u002Fready` endpoints are served on management port `9000`, separate from the application port `8080`. Do not publish this port on the Internet: use it only for the Compose `healthcheck` or your monitoring.",{"type":96,"title":97,"headers":98,"rows":102},"comparison","Keycloak or Authentik: which to choose?",[99,100,101],"Criterion","Keycloak","Authentik",[103,107,111,115,119,123,127,131],[104,105,106],"Target use case","Enterprise SSO, multi-tenant, compliance","Self-hosting, homelab, agencies",[108,109,110],"Protocols","OIDC, OAuth2, SAML, LDAP","OIDC, OAuth2, SAML, LDAP, forward auth",[112,113,114],"Forward auth (proxy)","Not native (via extensions)","Native and central to the tool",[116,117,118],"Resource footprint","High (JVM, 4 GB+ RAM)","Moderate (2-4 GB RAM)",[120,121,122],"Multi-realm \u002F tenants","Excellent (isolated realms)","Tenants supported, less advanced",[124,125,126],"Flow customization","Themes and Java SPI","Visual step-based flows",[128,129,130],"Learning curve","Steep, very complete","More accessible",[132,133,134],"Directory federation","Mature (LDAP\u002FAD)","Good (LDAP)",{"type":39,"title":136,"body":137},"Back up and migrate without losing a realm","Keycloak's state lives in two places: the PostgreSQL database, and your configuration files (themes, providers, import files). The reference backup is a scheduled `pg_dump`, copied off the VPS; test the restore on a throwaway instance, because a backup that has never been restored remains a hypothesis. Realm export complements this setup without replacing it: `kc.sh export --dir \u003Cfolder>`, or `--realm my-realm` for a single realm, with the `--users` option to choose the user export strategy. The documentation specifies that the server must not be running during the export, that consistency is only guaranteed with all nodes stopped, and that events, persisted sessions and revoked tokens are not exported. Beyond 50,000 users, export to a directory rather than to a single file. On import, `start --import-realm` reads the `.json` files of the `\u002Fopt\u002Fkeycloak\u002Fdata\u002Fimport` folder and skips a realm that already exists.",{"type":43,"title":139,"items":140},"Operations checklist",[141,142,143,144,145,146],"**Pinned version** — fix the image version number, read the release notes before changing major branch and rebuild the optimized image on every version upgrade.","**Backed-up database** — scheduled `pg_dump`, copy off the VPS, restore proven on a throwaway instance.","**Bounded memory** — always set a memory limit on the container: the JVM computes its heap from it, with 70% maximum and 50% initial by default.","**Probes monitored** — follow `\u002Fhealth\u002Fready` on the unpublished port `9000` from your monitoring.","**Proxy headers under control** — the reverse proxy must overwrite the `X-Forwarded-*` headers received from the client rather than append to them, and must never be bypassed.","**Events enabled** — log sign-ins and administration actions in each realm, to know who signed in and who changed what.",{"type":39,"title":148,"body":149},"Troubleshooting: startup fails with a read-only filesystem","Hardening a container often means `read_only: true` in Compose or `readOnlyRootFilesystem: true` in Kubernetes. With Keycloak, the topic has been open since April 2022 in issue keycloak\u002Fkeycloak #11286 (\"Keycloak does not work with Docker read_only: true\"), and it was still active at the end of October 2026. What is established on the project side: a Keycloak contributor reproduced the failure on version 19.0.2 in September 2022, the issue is classified as an enhancement with the \"help wanted\" label, and it was added to a repository project board in September 2026. What is not: the official documentation describes no read-only mode to date (the page on containers does not mention it), and no maintainer has validated a workaround. The solutions below come from discussion participants; they worked for them, on their versions, with no guarantee after a version upgrade. On 26 October 2026, a contributor offered to write the missing documentation after verifying these workarounds themselves.",{"type":43,"title":151,"items":152},"Error messages to recognize",[153,154,155,156,157],"**`sed: couldn't open temporary file \u002Fopt\u002Fjboss\u002Fkeycloak\u002Fbin\u002FseduHoQM0: Read-only file system`** — message from the original report, on the former WildFly image (version 16.1.1 in the issue): a `sed -i` in the startup script cannot create its temporary file. On the Quarkus distribution the symptoms differ, see the following lines.","**`KC-SERVICES0075: Failed to get theme request: java.lang.RuntimeException: Temporary directory \u002Fopt\u002Fkeycloak\u002Fbin\u002F..\u002Fdata\u002Ftmp does not exist and it was not possible to create it.`** — reported during an upgrade to 20.0.1: the server starts, then fails on the first page that serves a theme. A participant reported that a writable volume mounted on `\u002Fopt\u002Fkeycloak\u002Fdata\u002Ftmp` fixes this case.","**Slow startup or write failure in `\u002Fopt\u002Fkeycloak\u002Flib\u002Fquarkus`** — a participant compared the container before and after startup with `docker diff`: three folders change, `\u002Ftmp`, `\u002Fopt\u002Fkeycloak\u002Fdata` and `\u002Fopt\u002Fkeycloak\u002Flib\u002Fquarkus`. The last one holds the build output, which `start` regenerates unless the image is pre-optimized.","**Read-only `data` folder after a `COPY`** — a participant reports that forgetting `--chown=keycloak:keycloak` when copying a realm file leaves `\u002Fopt\u002Fkeycloak\u002Fdata` owned by root, hence not writable by Keycloak.","**Copying `\u002Fopt\u002Fkeycloak` into a volume at startup** — an init container workaround, reported on Kubernetes: it works, but several participants dread having to retest it on every version upgrade.",{"type":56,"title":159,"steps":160},"Reported workaround in Docker Compose",[161,164,167,170,173],{"title":162,"body":163},"Start from the pre-optimized image","Reuse the image built above. `kc.sh build` runs at build time: `\u002Fopt\u002Fkeycloak\u002Flib\u002Fquarkus` is no longer rewritten at startup, which is done with `start --optimized`.",{"title":165,"body":166},"Declare the read-only filesystem","Add `read_only: true` to the `keycloak` service of the Compose file. With no other change, the container fails: this is the behavior described by the issue.",{"title":168,"body":169},"Provide the writable directories","Mount a `tmpfs` on `\u002Ftmp` and a temporary volume on `\u002Fopt\u002Fkeycloak\u002Fdata`. In the report relying on a pre-optimized image, these two directories were enough; on a non-optimized image, other participants added `\u002Fopt\u002Fkeycloak\u002Flib\u002Fquarkus`.",{"title":171,"body":172},"Put back what was in data","A temporary volume starts empty: what the image placed in this folder, including `data\u002Fimport`, is no longer visible there. If you import realms with `--import-realm`, mount their folder separately, read-only.",{"title":174,"body":175},"Check by opening a login page","Run `docker compose up -d` then `docker compose logs -f keycloak`, then open the sign-in page: the first theme request is what made some setups fail. Finish with `docker diff` to list what the container actually wrote.",{"type":177,"title":178,"body":179},"tip","Read-only: a hardening measure the vendor does not document","Keep this mode for environments where a policy requires it, such as a security audit or a cluster rule, and accept the cost: an undocumented configuration to retest on every version upgrade, which several participants of the issue dread. On a single VPS, other measures give a clearer gain for less upkeep: Linux capabilities dropped (`cap_drop: [ALL]`), the `no-new-privileges` option, unpublished management ports and the PostgreSQL database on an internal Docker network.",{"type":177,"body":181},"In production, never serve Keycloak with the embedded H2 database and never expose the `master` realm to the public: create a dedicated realm per application or per client, and reserve `master` for administration. To harden the instance, disable free registration, enable `brute force detection` in Realm Settings > Security Defenses, and provision everything via realm import files (`--import-realm`) so you version your configuration rather than clicking through the UI.","Install Keycloak on your VPS","Keycloak is available in the ServOrbit Marketplace: official image, PostgreSQL database, HTTPS and administrator account ready at install time.","See Keycloak in the Marketplace","\u002Fapplications\u002Fcybersecurity-bastion\u002Fkeycloak",[187,205,224],{"id":188,"slug":189,"slugs":190,"title":194,"excerpt":195,"readTime":23,"views":18,"isPinned":19,"noindex":19,"publishedAt":196,"updatedAt":197,"category":198,"categories":199,"featuredImage":30,"bgImage":31,"posterImage":201,"relatedSolution":202},105,"monitoring-your-vps-with-uptime-kuma",{"fr":191,"en":189,"ar":192,"es":193},"superviser-vps-uptime-kuma","مراقبة-خادمك-الافتراضي-vps-باستخدام-uptime-kuma","supervisar-vps-con-uptime-kuma","Monitoring your VPS with Uptime Kuma","Deploy Uptime Kuma on your VPS to monitor your sites and services self-hosted, with alerts and a public status page.","2026-03-07T00:00:00+00:00","2026-11-09T20:55:19+00:00",{"id":23,"name":24,"slug":25,"color":26,"icon":27},[200],{"id":23,"name":24,"slug":25,"color":26,"icon":27},"\u002Fblog\u002Fcovers\u002Fsuperviser-vps-uptime-kuma-poster.svg",{"categorySlug":203,"appSlug":204},"monitoring-observability","uptime-kuma",{"id":206,"slug":207,"slugs":208,"title":212,"excerpt":213,"readTime":214,"views":215,"isPinned":19,"noindex":19,"publishedAt":216,"updatedAt":217,"category":218,"categories":219,"featuredImage":30,"bgImage":31,"posterImage":221,"relatedSolution":222},106,"vps-monitoring-with-grafana-and-prometheus",{"fr":209,"en":207,"ar":210,"es":211},"monitoring-vps-grafana-prometheus","مراقبة-الخادم-الافتراضي-vps-باستخدام-grafana-و-prometheus","monitorizacion-vps-grafana-prometheus","VPS Monitoring with Grafana and Prometheus","Deploy Prometheus 3.x, Grafana 13.x, Node Exporter and Alertmanager on your VPS with Docker Compose. Dashboards, alerts and hardening.",11,1,"2026-03-06T00:00:00+00:00","2026-10-05T14:05:27+00:00",{"id":23,"name":24,"slug":25,"color":26,"icon":27},[220],{"id":23,"name":24,"slug":25,"color":26,"icon":27},"\u002Fblog\u002Fcovers\u002Fmonitoring-vps-grafana-prometheus-poster.svg",{"categorySlug":203,"appSlug":223},"grafana",{"id":225,"slug":226,"slugs":227,"title":231,"excerpt":232,"readTime":233,"views":215,"isPinned":19,"noindex":19,"publishedAt":234,"updatedAt":235,"category":236,"categories":237,"featuredImage":30,"bgImage":31,"posterImage":239,"relatedSolution":240},107,"monitor-your-vps-in-real-time-with-netdata",{"fr":228,"en":226,"ar":229,"es":230},"monitorer-vps-netdata","راقب-خادمك-الافتراضي-vps-في-الوقت-الفعلي-باستخدام-netdata","monitorizar-vps-en-tiempo-real-con-netdata","Monitor your VPS in real time with Netdata","Install Netdata on your VPS for per-second real-time monitoring: thousands of metrics, zero configuration, alerts included.",3,"2026-03-05T00:00:00+00:00","2026-09-07T11:26:10+00:00",{"id":23,"name":24,"slug":25,"color":26,"icon":27},[238],{"id":23,"name":24,"slug":25,"color":26,"icon":27},"\u002Fblog\u002Fcovers\u002Fmonitorer-vps-netdata-poster.svg",{"categorySlug":203,"appSlug":241},"netdata",true,1794270386934]