Now Reading
Keycloak SSO with docker compose and nginx

Keycloak SSO with docker compose and nginx

2024-02-11 02:11:18

Printed: 2024-02-11, Revised: 2024-02-11


nextcloud_bg


TL;DR I all the time hesitated to deploy an additional device for person administration and SSO, however the present state of the online makes it very troublesome to maintain up with safety, CVEs and so forth. Why not belief one of many longest standing options for id and entry administration? Keycloak is open supply, interoperable with main SSO protocols (OpenID Join (OIDC), OAuth 2.0, SAML), and sturdy. The setup with docker compose shouldn’t be difficult, however it was not straight ahead both. Because of this I present a abstract of the method under.

Data

That is at the moment a stub. I believed I’d share my docker-compose.yml and nginx.conf rapidly and replace the publish later so as to add steps for theming and integration.

Idea

You will have seen the idea under already in my previous post about Mastodon. We are going to use a normal setup of nginx as a central reverse proxy that forwards visitors by means of localhost to particular person companies, all working in their very own rootless docker namespaces. I contemplate this the everyday economical setup, by sharing sources of a single host however with maximally remoted environments. Adapt the place this doesn’t suit your usecase.


                                                      Net
                                                       |
                                                       |
                                                  0.0.0.0:80
                                                  0.0.0.0:443
+------------------------------------------------------+-----------------------------------------------------+
|                                                      |                                                     |
|                                                      v                                                     |
|                +------------------------------- nginx/acme -----------------------------+                  |
|                |                                     |                                  |                  |
|        http://127.0.0.1:3000                         |                                  |                  |
|        http://127.0.0.1:4000                http://127.0.0.1:8080              http://127.0.0.1:9999       |
| +--------------+---------------+      +--------------+---------------+    +-------------+----------------+ |
| |              |               |      |              |               |    |             |                | |
| |   Rootless Docker Service    |      |   Rootless Docker Service    |    |   Rootless Docker Service    | |
| |    +---------+----------+    |      |    +---------+----------+    |    |    +--------+-----------+    | |
| |    |         |          |    |      |    |         |          |    |    |    |        |           |    | |
| |    |         v          |    |      |    |         v          |    |    |    |        v           |    | |
| |    |  Mastdon Docker    |    |      |    |  Keycloak Docker   |    |    |    |  Nextcloud Docker  |    | |
| |    |                    |    |      |    |                    |    |    |    |                    |    | |
| |    |                    |    |      |    |                    |    |    |    |                    |    | |
| |    +--------------------+    |      |    +--------------------+    |    |    +--------------------+    | |
| |                              |      |                              |    |                              | |
| +------------------------------+      +------------------------------+    +------------------------------+ |
|                                                                                                            |
+------------------------------------------------------------------------------------------------------------+

Preparations

You have to some fundamental instruments:

  • SSH
  • A VM with Linux (Ubuntu; Debian and so forth.)
  • A website or subdomain the place you possibly can add an A (and optionally AAAA) file in your service

Observe the Mastodon post for fundamental setup of docker rootless to:

  • create a brand new non-root person named keycloak, with out password, with its house listing set to /srv/keycloak
  • replace /and so forth/subuid and /and so forth/subgid ranges with person keycloak (as a result of e.g. the postgres container will want these to create a nested non-root person itself)
  • set up docker rootless by means of dockerd-rootless-setuptool.sh and configure automated service begin for the keycloak person

Keycloak Setup

Login to the newly created keycloak person.

machinectl shell keycloak@

Warning

We have to use machinectl to login, in any other case
XDG_RUNTIME_DIR setting variables is not going to be out there.
Don’t use (e.g.) sudo -u keycloak -H bash.

Create directories for persistent information (information/postgres16) and the docker recordsdata.

cd ~ 
  && mkdir -p information/postgres16 
  && mkdir docker && cd docker

docker-compose.yml

The official docs present some data right here . However they use docker run, which might be uncommon in manufacturing.

Going to a compose file shouldn’t be difficult and permits us to have a extra reproducable setup. There are some instance docker-compose.ymls out there, similar to , or .

We are going to begin with a docker-compose.yml that instantly makes use of the official keycloak image. This may be modified later.

model: '3'

companies:
  postgres_db:
      picture: postgres:16
      volumes:
        - /srv/keycloak/information/postgres16:/var/lib/postgresql/information
      setting:
        POSTGRES_DB: keycloak
        POSTGRES_USER: ${POSTGRES_USER:-keycloak}
        POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-eX4mP13p455w0Rd}

  keycloak:
      # construct: .
      picture: quay.io/keycloak/keycloak:23.0.6
      setting:
        KC_LOG_LEVEL: debug
        KC_DB: postgres
        KC_DB_URL: 'jdbc:postgresql://postgres_db/keycloak'
        KC_DB_USERNAME: ${POSTGRES_USER:-keycloak}
        KC_DB_PASSWORD: ${POSTGRES_PASSWORD:-eX4mP13p455w0Rd}
        KC_DB_SCHEMA: public
        KC_HOSTNAME: ${KC_HOSTNAME:-your.tld.com}
        KC_HOSTNAME_STRICT_HTTPS: true
        KC_HOSTNAME_STRICT: true
        KC_PROXY: edge
        HTTP_ADDRESS_FORWARDING: true
        KEYCLOAK_ADMIN: admin
        KEYCLOAK_ADMIN_PASSWORD: ${KEYCLOAK_ADMIN_PASSWORD:-eX4mP13p455w0Rd}
      # command: begin --optimized
      ports:
        - '127.0.0.1:8080:8080'
      depends_on:
        - postgres_db

Create an .env file together with your delicate and variable data:

Contents (change passwords):

# DB Password
POSTGRES_PASSWORD=eX4mP13p455w0Rd

# admin password
KEYCLOAK_ADMIN_PASSWORD=eX4mP13p455w0Rd

# area
KC_HOSTNAME=your.tld.com

The related documentation of all these variables could be discovered right here .

Be aware

Optionally initialize a .git repository in ~/docker now, create a .gitignore and add .env to it, and commit the docker-compose.yml, for monitoring modifications.

Some explanations for the docker-compose.yml above
  • '127.0.0.1:8080:8080' and KC_PROXY: edge will make keycloak hear on localhost
  • the syntax for env variables (${KC_HOSTNAME:-your.tld.com}) means:
    1. use KC_HOSTNAME from .env, if out there;
    2. in any other case substitute a default worth (your.tld.com)
  • observe (e.g.) that we don’t set KC_DB_USERNAME, which implies: use the default
  • picture: quay.io/keycloak/keycloak:23.0.6 references a selected picture tag, as is advised for manufacturing (solely use :newest for growth).
  • KC_LOG_LEVEL: debug could be commented out as soon as we’re finished with growth
  • bind-mount the persistent postgres information from the subfolder created earlier within the person’s house listing:
    companies:
      postgres_db:
        picture: postgres:16
        volumes:
          - /srv/keycloak/information/postgres16:/var/lib/postgresql/information
    
  • if you wish to begin over from scratch, merely delete this postgres folder and it will probably be re-initialized on subsequent startup:
    CTRL+D
    sudo rm -rf /srv/keycloak/information/postgres16
    sudo machinectl shell keycloak@
    cd ~ && mkdir -p information/postgres16
    
  • /srv/keycloak/information/postgres16 holds the persistent information that would want periodic backups

Take a look at domestically

At this stage, we are able to check the docker compose stack:

docker compose up -d && docker compose logs --follow

Afterwards, create a reverse SSH tunnel to your VM and the keycloak native port.

ssh you@111.11.11.11 -L :8080:127.0.0.1:8080 -p 22 -N -v

Open 127.0.0.1:8080 in your browser and you need to be greeted with the keycloak welcome display:
keycloak_local

nginx

Logout from the keycloak person with CTRL+D.

Observe the Mastodon post for setup of nginx as a system reverse proxy.

Create a brand new nginx .conf for the keycloak service.

Be aware

From right here on, wherever you see your.tld.com: exchange together with your precise area.

Be aware

At this stage, it is best to head to your area registrar and add an A file to ahead DNS queries to your VM’s IP.

nano /and so forth/nginx/sites-available/your.tld.com.conf
ln -s /and so forth/nginx/sites-available/your.tld.com.conf /and so forth/nginx/sites-enabled/

We are able to discover some related data within the keycloak docs .

Data

I like to recommend to make use of the Mozilla SSL configurator to generate greatest follow defaults for nginx . Be certain that to replace together with your nginx model (nginx -v).

server {
    if ($host = your.tld.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


    hear 80;
    hear [::]:80;
    server_name your.tld.com;
    location / { return 301 https://$host$request_uri; }
}

server {
    hear 443 ssl http2;
    hear [::]:443 ssl http2;
    server_name your.tld.com;

    ssl_session_timeout 1d;
    ssl_session_cache shared:MozSSL:10m;  # about 40000 periods
    ssl_session_tickets off;

    # curl https://ssl-config.mozilla.org/ffdhe2048.txt > /path/to/dhparam
    ssl_dhparam /and so forth/nginx/dhparam/dhparam;

    # intermediate configuration
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305;
    ssl_prefer_server_ciphers off;

    # HSTS (ngx_http_headers_module is required) (63072000 seconds)
    add_header Strict-Transport-Safety "max-age=63072000" all the time;

    # OCSP stapling
    ssl_stapling on;
    ssl_stapling_verify on;

    # confirm chain of belief of OCSP response utilizing Root CA and Intermediate certs
    # ssl_trusted_certificate /and so forth/letsencrypt/stay/your.tld.com/chain.pem;

    access_log /var/log/nginx/your.tld.com-access.log;
    error_log /var/log/nginx/your.tld.com-error.log;

    location / {

        proxy_set_header Host $host;
        proxy_set_header X-Actual-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_pass http://127.0.0.1:8080;

        # the next headers are wanted, in case your utility makes use of redirection circulate to authenticate with Keycloak.
        # exchange http://127.0.0.1:8080 with the applying server url
        # add_header Content material-Safety-Coverage "frame-src *; frame-ancestors *; object-src *;";
        # add_header Entry-Management-Permit-Origin 'http://127.0.0.1:8080'; 
        # add_header Entry-Management-Permit-Credentials true;

    }


    # ssl_certificate /and so forth/letsencrypt/stay/your.tld.com/fullchain.pem; # managed by Certbot
    # ssl_certificate_key /and so forth/letsencrypt/stay/your.tld.com/privkey.pem; # managed by Certbot
}

Take a look at the configuration and reload nginx.

nginx -t
systemctl reload nginx

Use certbot to request SSL certificates in your service.

certbot --nginx -d your.tld.com

This can robotically replace crucial traces in your.tld.com.conf.

Edit your.tld.com.conf and uncomment ssl_trusted_certificate.

# confirm chain of belief of OCSP response utilizing Root CA and Intermediate certs
ssl_trusted_certificate /and so forth/letsencrypt/stay/your.tld.com/chain.pem;

Reload nginx

Debug

Now you can open your.tld.com and login to keycloak utilizing the admin person with the password from the .env file.

For debugging, the primary cease are the docker compose logs.

docker compose logs --follow

For nginx, observe the entry and error logs.

tail -f /var/log/nginx/your.tld.com-access.log;
tail -f /var/log/nginx/your.tld.com-error.log;

When you want to take a look on the keycloak database.

machinectl shell keycloak@
cd ~/docker
docker compose exec postgres_db /bin/bash
psql -h localhost -p 5432 -U keycloak keycloak
SELECT ...;

Customized construct with Dockerfile

To this point, we’re utilizing the prebuild picture from quay.io.

For any customization, e.g. in an effort to use themes and run the keycloak container in --optimized mode , we have to construct our personal picture.

We are going to make the most of a multi-stage docker construct beginning with the official quay.io picture.

Add a Dockerfile

cd ~/docker
nano Dockerfile

.. with the next content material.

FROM quay.io/keycloak/keycloak:23.0.6 as builder

# Configure a database vendor
ENV KC_DB=postgres

WORKDIR /choose/keycloak
# COPY --from=keycloakify_jar_builder /choose/app/build_keycloak/goal/ keycloakify-starter-keycloak-theme-5.1.3.jar /choose/keycloak/suppliers/
RUN /choose/keycloak/bin/kc.sh construct

FROM quay.io/keycloak/keycloak:23.0.6
COPY --from=builder /choose/keycloak/ /choose/keycloak/

# Add ENTRYPOINT
ENTRYPOINT ["/opt/keycloak/bin/kc.sh"]

Afterwards, edit the docker-compose.yml:

  • take away or remark out the picture: line
  • uncomment construct: .
  • add command: begin --optimized
Closing docker-compose.yml
model: '3'

companies:
  postgres_db:
      picture: postgres:16
      volumes:
        - /srv/keycloak/information/postgres16:/var/lib/postgresql/information
      setting:
        POSTGRES_DB: keycloak
        POSTGRES_USER: ${POSTGRES_USER:-keycloak}
        POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-eX4mP13p455w0Rd}

  keycloak:
      construct: .
      setting:
        KC_LOG_LEVEL: debug
        KC_DB: postgres
        KC_DB_URL: 'jdbc:postgresql://postgres_db/keycloak'
        KC_DB_USERNAME: ${POSTGRES_USER:-keycloak}
        KC_DB_PASSWORD: ${POSTGRES_PASSWORD:-eX4mP13p455w0Rd}
        KC_DB_SCHEMA: public
        KC_HOSTNAME: ${KC_HOSTNAME:-your.tld.com}
        KC_HOSTNAME_STRICT_HTTPS: true
        KC_HOSTNAME_STRICT: true
        KC_PROXY: edge
        HTTP_ADDRESS_FORWARDING: true
        KEYCLOAK_ADMIN: admin
        KEYCLOAK_ADMIN_PASSWORD: ${KEYCLOAK_ADMIN_PASSWORD:-eX4mP13p455w0Rd}
      command: begin --optimized
      ports:
        - '127.0.0.1:8080:8080'
      depends_on:
        - postgres_db

Restart the docker stack afterwards with

docker compose down
# elective specific construct step
docker compose construct
docker compose up -d && docker compose logs --follow

This can construct the picture and begin the service.

Conclusions

We are actually working a keycloak service in rootless docker behind our system nginx reverse proxy, which does the SSL termination for us.

For automated updates of the docker container, see the Mastodon post.

The subsequent step could be logging in to the keycloak companies and including
an electronic mail beneath https://your.tld.com/admin/grasp/console/#/grasp/realm-settings/electronic mail.

Subsequent comes (e.g.) including a realm. Then theming, which could be finished with keycloakify .

You’ll be able to see that I already added the required traces to the Dockerfile:

# COPY --from=keycloakify_jar_builder /choose/app/build_keycloak/goal/ keycloakify-starter-keycloak-theme-5.1.3.jar /choose/keycloak/suppliers/

When you discover enhancements to the directions above, please add within the feedback part!


Source Link

What's Your Reaction?
Excited
0
Happy
0
In Love
0
Not Sure
0
Silly
0
View Comments (0)

Leave a Reply

Your email address will not be published.

2022 Blinking Robots.
WordPress by Doejo

Scroll To Top